]>
Commit | Line | Data |
---|---|---|
aff33962 | 1 | /* dnsmasq is Copyright (c) 2000-2015 Simon Kelley |
98c098bf SK |
2 | |
3 | This program is free software; you can redistribute it and/or modify | |
4 | it under the terms of the GNU General Public License as published by | |
5 | the Free Software Foundation; version 2 dated June, 1991, or | |
6 | (at your option) version 3 dated 29 June, 2007. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #include "dnsmasq.h" | |
18 | ||
19 | #ifdef HAVE_DNSSEC | |
20 | ||
82e3f45a SK |
21 | static struct blockdata *keyblock_free; |
22 | static unsigned int blockdata_count, blockdata_hwm, blockdata_alloced; | |
23 | ||
8d718cbb SK |
24 | static void blockdata_expand(int n) |
25 | { | |
26 | struct blockdata *new = whine_malloc(n * sizeof(struct blockdata)); | |
27 | ||
b692f234 | 28 | if (n > 0 && new) |
8d718cbb SK |
29 | { |
30 | int i; | |
31 | ||
32 | new[n-1].next = keyblock_free; | |
33 | keyblock_free = new; | |
34 | ||
35 | for (i = 0; i < n - 1; i++) | |
36 | new[i].next = &new[i+1]; | |
37 | ||
38 | blockdata_alloced += n; | |
39 | } | |
40 | } | |
41 | ||
82e3f45a SK |
42 | /* Preallocate some blocks, proportional to cachesize, to reduce heap fragmentation. */ |
43 | void blockdata_init(void) | |
44 | { | |
8d718cbb SK |
45 | keyblock_free = NULL; |
46 | blockdata_alloced = 0; | |
82e3f45a SK |
47 | blockdata_count = 0; |
48 | blockdata_hwm = 0; | |
b692f234 SK |
49 | |
50 | /* Note that daemon->cachesize is enforced to have non-zero size if OPT_DNSSEC_VALID is set */ | |
51 | if (option_bool(OPT_DNSSEC_VALID)) | |
52 | blockdata_expand((daemon->cachesize * 100) / sizeof(struct blockdata)); | |
82e3f45a | 53 | } |
c2207688 SK |
54 | |
55 | void blockdata_report(void) | |
56 | { | |
b692f234 SK |
57 | if (option_bool(OPT_DNSSEC_VALID)) |
58 | my_syslog(LOG_INFO, _("DNSSEC memory in use %u, max %u, allocated %u"), | |
59 | blockdata_count * sizeof(struct blockdata), | |
60 | blockdata_hwm * sizeof(struct blockdata), | |
61 | blockdata_alloced * sizeof(struct blockdata)); | |
c2207688 | 62 | } |
98c098bf SK |
63 | |
64 | struct blockdata *blockdata_alloc(char *data, size_t len) | |
65 | { | |
66 | struct blockdata *block, *ret = NULL; | |
67 | struct blockdata **prev = &ret; | |
68 | size_t blen; | |
69 | ||
70 | while (len > 0) | |
71 | { | |
8d718cbb SK |
72 | if (!keyblock_free) |
73 | blockdata_expand(50); | |
74 | ||
98c098bf SK |
75 | if (keyblock_free) |
76 | { | |
77 | block = keyblock_free; | |
78 | keyblock_free = block->next; | |
c2207688 | 79 | blockdata_count++; |
98c098bf | 80 | } |
5f938534 | 81 | else |
98c098bf SK |
82 | { |
83 | /* failed to alloc, free partial chain */ | |
84 | blockdata_free(ret); | |
85 | return NULL; | |
86 | } | |
82e3f45a SK |
87 | |
88 | if (blockdata_hwm < blockdata_count) | |
89 | blockdata_hwm = blockdata_count; | |
98c098bf SK |
90 | |
91 | blen = len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len; | |
92 | memcpy(block->key, data, blen); | |
93 | data += blen; | |
94 | len -= blen; | |
95 | *prev = block; | |
96 | prev = &block->next; | |
97 | block->next = NULL; | |
98 | } | |
99 | ||
100 | return ret; | |
101 | } | |
102 | ||
98c098bf SK |
103 | void blockdata_free(struct blockdata *blocks) |
104 | { | |
105 | struct blockdata *tmp; | |
82e3f45a | 106 | |
98c098bf SK |
107 | if (blocks) |
108 | { | |
c2207688 SK |
109 | for (tmp = blocks; tmp->next; tmp = tmp->next) |
110 | blockdata_count--; | |
98c098bf | 111 | tmp->next = keyblock_free; |
c2207688 SK |
112 | keyblock_free = blocks; |
113 | blockdata_count--; | |
98c098bf SK |
114 | } |
115 | } | |
116 | ||
86bec2d3 SK |
117 | /* if data == NULL, return pointer to static block of sufficient size */ |
118 | void *blockdata_retrieve(struct blockdata *block, size_t len, void *data) | |
98c098bf SK |
119 | { |
120 | size_t blen; | |
121 | struct blockdata *b; | |
86bec2d3 | 122 | void *new, *d; |
98c098bf | 123 | |
86bec2d3 SK |
124 | static unsigned int buff_len = 0; |
125 | static unsigned char *buff = NULL; | |
126 | ||
127 | if (!data) | |
128 | { | |
129 | if (len > buff_len) | |
130 | { | |
131 | if (!(new = whine_malloc(len))) | |
132 | return NULL; | |
133 | if (buff) | |
134 | free(buff); | |
135 | buff = new; | |
136 | } | |
137 | data = buff; | |
138 | } | |
139 | ||
140 | for (d = data, b = block; len > 0 && b; b = b->next) | |
98c098bf SK |
141 | { |
142 | blen = len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len; | |
86bec2d3 SK |
143 | memcpy(d, b->key, blen); |
144 | d += blen; | |
98c098bf SK |
145 | len -= blen; |
146 | } | |
b6e9e7c3 | 147 | |
86bec2d3 | 148 | return data; |
98c098bf | 149 | } |
b6e9e7c3 | 150 | |
98c098bf | 151 | #endif |