dnsmasq 2.72+ up to December 9 2014
[tomato.git] / release / src / router / dnsmasq / src / blockdata.c
blobf98f509f4502c135b3ea487c3a6e1bf4b89e9d02
1 /* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
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.
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.
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/>.
17 #include "dnsmasq.h"
19 #ifdef HAVE_DNSSEC
21 static struct blockdata *keyblock_free;
22 static unsigned int blockdata_count, blockdata_hwm, blockdata_alloced;
24 static void blockdata_expand(int n)
26 struct blockdata *new = whine_malloc(n * sizeof(struct blockdata));
28 if (n > 0 && new)
30 int i;
32 new[n-1].next = keyblock_free;
33 keyblock_free = new;
35 for (i = 0; i < n - 1; i++)
36 new[i].next = &new[i+1];
38 blockdata_alloced += n;
42 /* Preallocate some blocks, proportional to cachesize, to reduce heap fragmentation. */
43 void blockdata_init(void)
45 keyblock_free = NULL;
46 blockdata_alloced = 0;
47 blockdata_count = 0;
48 blockdata_hwm = 0;
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));
55 void blockdata_report(void)
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));
64 struct blockdata *blockdata_alloc(char *data, size_t len)
66 struct blockdata *block, *ret = NULL;
67 struct blockdata **prev = &ret;
68 size_t blen;
70 while (len > 0)
72 if (!keyblock_free)
73 blockdata_expand(50);
75 if (keyblock_free)
77 block = keyblock_free;
78 keyblock_free = block->next;
79 blockdata_count++;
81 else
83 /* failed to alloc, free partial chain */
84 blockdata_free(ret);
85 return NULL;
88 if (blockdata_hwm < blockdata_count)
89 blockdata_hwm = blockdata_count;
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;
100 return ret;
103 void blockdata_free(struct blockdata *blocks)
105 struct blockdata *tmp;
107 if (blocks)
109 for (tmp = blocks; tmp->next; tmp = tmp->next)
110 blockdata_count--;
111 tmp->next = keyblock_free;
112 keyblock_free = blocks;
113 blockdata_count--;
117 /* if data == NULL, return pointer to static block of sufficient size */
118 void *blockdata_retrieve(struct blockdata *block, size_t len, void *data)
120 size_t blen;
121 struct blockdata *b;
122 void *new, *d;
124 static unsigned int buff_len = 0;
125 static unsigned char *buff = NULL;
127 if (!data)
129 if (len > buff_len)
131 if (!(new = whine_malloc(len)))
132 return NULL;
133 if (buff)
134 free(buff);
135 buff = new;
137 data = buff;
140 for (d = data, b = block; len > 0 && b; b = b->next)
142 blen = len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len;
143 memcpy(d, b->key, blen);
144 d += blen;
145 len -= blen;
148 return data;
151 #endif