1 /* dnsmasq is Copyright (c) 2000-2022 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/>.
19 static struct blockdata *keyblock_free;
20 static unsigned int blockdata_count, blockdata_hwm, blockdata_alloced;
22 static void blockdata_expand(int n)
24 struct blockdata *new = whine_malloc(n * sizeof(struct blockdata));
30 new[n-1].next = keyblock_free;
33 for (i = 0; i < n - 1; i++)
34 new[i].next = &new[i+1];
36 blockdata_alloced += n;
40 /* Preallocate some blocks, proportional to cachesize, to reduce heap fragmentation. */
41 void blockdata_init(void)
44 blockdata_alloced = 0;
48 /* Note that daemon->cachesize is enforced to have non-zero size if OPT_DNSSEC_VALID is set */
49 if (option_bool(OPT_DNSSEC_VALID))
50 blockdata_expand(daemon->cachesize);
53 void blockdata_report(void)
55 my_syslog(LOG_INFO, _("pool memory in use %zu, max %zu, allocated %zu"),
56 blockdata_count * sizeof(struct blockdata),
57 blockdata_hwm * sizeof(struct blockdata),
58 blockdata_alloced * sizeof(struct blockdata));
61 static struct blockdata *blockdata_alloc_real(int fd, char *data, size_t len)
63 struct blockdata *block, *ret = NULL;
64 struct blockdata **prev = &ret;
74 block = keyblock_free;
75 keyblock_free = block->next;
80 /* failed to alloc, free partial chain */
85 if (blockdata_hwm < blockdata_count)
86 blockdata_hwm = blockdata_count;
88 blen = len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len;
91 memcpy(block->key, data, blen);
94 else if (!read_write(fd, block->key, blen, 1))
96 /* failed read free partial chain */
109 struct blockdata *blockdata_alloc(char *data, size_t len)
111 return blockdata_alloc_real(0, data, len);
114 void blockdata_free(struct blockdata *blocks)
116 struct blockdata *tmp;
120 for (tmp = blocks; tmp->next; tmp = tmp->next)
122 tmp->next = keyblock_free;
123 keyblock_free = blocks;
128 /* if data == NULL, return pointer to static block of sufficient size */
129 void *blockdata_retrieve(struct blockdata *block, size_t len, void *data)
135 static unsigned int buff_len = 0;
136 static unsigned char *buff = NULL;
142 if (!(new = whine_malloc(len)))
151 for (d = data, b = block; len > 0 && b; b = b->next)
153 blen = len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len;
154 memcpy(d, b->key, blen);
163 void blockdata_write(struct blockdata *block, size_t len, int fd)
165 for (; len > 0 && block; block = block->next)
167 size_t blen = len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len;
168 read_write(fd, block->key, blen, 0);
173 struct blockdata *blockdata_read(int fd, size_t len)
175 return blockdata_alloc_real(fd, NULL, len);