1: /* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
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: static struct blockdata *keyblock_free;
20: static unsigned int blockdata_count, blockdata_hwm, blockdata_alloced;
21:
22: static void blockdata_expand(int n)
23: {
24: struct blockdata *new = whine_malloc(n * sizeof(struct blockdata));
25:
26: if (new)
27: {
28: int i;
29:
30: new[n-1].next = keyblock_free;
31: keyblock_free = new;
32:
33: for (i = 0; i < n - 1; i++)
34: new[i].next = &new[i+1];
35:
36: blockdata_alloced += n;
37: }
38: }
39:
40: /* Preallocate some blocks, proportional to cachesize, to reduce heap fragmentation. */
41: void blockdata_init(void)
42: {
43: keyblock_free = NULL;
44: blockdata_alloced = 0;
45: blockdata_count = 0;
46: blockdata_hwm = 0;
47:
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);
51: }
52:
53: void blockdata_report(void)
54: {
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));
59: }
60:
61: static struct blockdata *blockdata_alloc_real(int fd, char *data, size_t len)
62: {
63: struct blockdata *block, *ret = NULL;
64: struct blockdata **prev = &ret;
65: size_t blen;
66:
67: while (len > 0)
68: {
69: if (!keyblock_free)
70: blockdata_expand(50);
71:
72: if (keyblock_free)
73: {
74: block = keyblock_free;
75: keyblock_free = block->next;
76: blockdata_count++;
77: }
78: else
79: {
80: /* failed to alloc, free partial chain */
81: blockdata_free(ret);
82: return NULL;
83: }
84:
85: if (blockdata_hwm < blockdata_count)
86: blockdata_hwm = blockdata_count;
87:
88: blen = len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len;
89: if (data)
90: {
91: memcpy(block->key, data, blen);
92: data += blen;
93: }
94: else if (!read_write(fd, block->key, blen, 1))
95: {
96: /* failed read free partial chain */
97: blockdata_free(ret);
98: return NULL;
99: }
100: len -= blen;
101: *prev = block;
102: prev = &block->next;
103: block->next = NULL;
104: }
105:
106: return ret;
107: }
108:
109: struct blockdata *blockdata_alloc(char *data, size_t len)
110: {
111: return blockdata_alloc_real(0, data, len);
112: }
113:
114: void blockdata_free(struct blockdata *blocks)
115: {
116: struct blockdata *tmp;
117:
118: if (blocks)
119: {
120: for (tmp = blocks; tmp->next; tmp = tmp->next)
121: blockdata_count--;
122: tmp->next = keyblock_free;
123: keyblock_free = blocks;
124: blockdata_count--;
125: }
126: }
127:
128: /* if data == NULL, return pointer to static block of sufficient size */
129: void *blockdata_retrieve(struct blockdata *block, size_t len, void *data)
130: {
131: size_t blen;
132: struct blockdata *b;
133: void *new, *d;
134:
135: static unsigned int buff_len = 0;
136: static unsigned char *buff = NULL;
137:
138: if (!data)
139: {
140: if (len > buff_len)
141: {
142: if (!(new = whine_malloc(len)))
143: return NULL;
144: if (buff)
145: free(buff);
146: buff = new;
147: }
148: data = buff;
149: }
150:
151: for (d = data, b = block; len > 0 && b; b = b->next)
152: {
153: blen = len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len;
154: memcpy(d, b->key, blen);
155: d += blen;
156: len -= blen;
157: }
158:
159: return data;
160: }
161:
162:
163: void blockdata_write(struct blockdata *block, size_t len, int fd)
164: {
165: for (; len > 0 && block; block = block->next)
166: {
167: size_t blen = len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len;
168: read_write(fd, block->key, blen, 0);
169: len -= blen;
170: }
171: }
172:
173: struct blockdata *blockdata_read(int fd, size_t len)
174: {
175: return blockdata_alloc_real(fd, NULL, len);
176: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>