blob: 272d3a67f4ebd0b293b4f26aafaf312f3772f6c9 [file] [log] [blame]
Simon Kelley98c098b2014-01-08 17:31:16 +00001/* dnsmasq is Copyright (c) 2000-2014 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#ifdef HAVE_DNSSEC
20
Simon Kelley82e3f452014-01-31 21:05:48 +000021static struct blockdata *keyblock_free;
22static unsigned int blockdata_count, blockdata_hwm, blockdata_alloced;
23
Simon Kelley8d718cb2014-02-03 16:27:37 +000024static void blockdata_expand(int n)
25{
26 struct blockdata *new = whine_malloc(n * sizeof(struct blockdata));
27
28 if (new)
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
Simon Kelley82e3f452014-01-31 21:05:48 +000042/* Preallocate some blocks, proportional to cachesize, to reduce heap fragmentation. */
43void blockdata_init(void)
44{
Simon Kelley8d718cb2014-02-03 16:27:37 +000045 keyblock_free = NULL;
46 blockdata_alloced = 0;
Simon Kelley82e3f452014-01-31 21:05:48 +000047 blockdata_count = 0;
48 blockdata_hwm = 0;
Simon Kelley8d718cb2014-02-03 16:27:37 +000049
50 blockdata_expand((daemon->cachesize * 100) / sizeof(struct blockdata));
Simon Kelley82e3f452014-01-31 21:05:48 +000051}
Simon Kelleyc2207682014-01-08 18:04:20 +000052
53void blockdata_report(void)
54{
Simon Kelley82e3f452014-01-31 21:05:48 +000055 my_syslog(LOG_INFO, _("DNSSEC memory in use %u, max %u, allocated %u"),
56 blockdata_count * sizeof(struct blockdata), blockdata_hwm * sizeof(struct blockdata), blockdata_alloced * sizeof(struct blockdata));
Simon Kelleyc2207682014-01-08 18:04:20 +000057}
Simon Kelley98c098b2014-01-08 17:31:16 +000058
59struct blockdata *blockdata_alloc(char *data, size_t len)
60{
61 struct blockdata *block, *ret = NULL;
62 struct blockdata **prev = &ret;
63 size_t blen;
64
65 while (len > 0)
66 {
Simon Kelley8d718cb2014-02-03 16:27:37 +000067 if (!keyblock_free)
68 blockdata_expand(50);
69
Simon Kelley98c098b2014-01-08 17:31:16 +000070 if (keyblock_free)
71 {
72 block = keyblock_free;
73 keyblock_free = block->next;
Simon Kelleyc2207682014-01-08 18:04:20 +000074 blockdata_count++;
Simon Kelley98c098b2014-01-08 17:31:16 +000075 }
Simon Kelley5f938532014-02-03 16:44:32 +000076 else
Simon Kelley98c098b2014-01-08 17:31:16 +000077 {
78 /* failed to alloc, free partial chain */
79 blockdata_free(ret);
80 return NULL;
81 }
Simon Kelley82e3f452014-01-31 21:05:48 +000082
83 if (blockdata_hwm < blockdata_count)
84 blockdata_hwm = blockdata_count;
Simon Kelley98c098b2014-01-08 17:31:16 +000085
86 blen = len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len;
87 memcpy(block->key, data, blen);
88 data += blen;
89 len -= blen;
90 *prev = block;
91 prev = &block->next;
92 block->next = NULL;
93 }
94
95 return ret;
96}
97
Simon Kelley98c098b2014-01-08 17:31:16 +000098void blockdata_free(struct blockdata *blocks)
99{
100 struct blockdata *tmp;
Simon Kelley82e3f452014-01-31 21:05:48 +0000101
Simon Kelley98c098b2014-01-08 17:31:16 +0000102 if (blocks)
103 {
Simon Kelleyc2207682014-01-08 18:04:20 +0000104 for (tmp = blocks; tmp->next; tmp = tmp->next)
105 blockdata_count--;
Simon Kelley98c098b2014-01-08 17:31:16 +0000106 tmp->next = keyblock_free;
Simon Kelleyc2207682014-01-08 18:04:20 +0000107 keyblock_free = blocks;
108 blockdata_count--;
Simon Kelley98c098b2014-01-08 17:31:16 +0000109 }
110}
111
Simon Kelley86bec2d2014-01-13 21:31:20 +0000112/* if data == NULL, return pointer to static block of sufficient size */
113void *blockdata_retrieve(struct blockdata *block, size_t len, void *data)
Simon Kelley98c098b2014-01-08 17:31:16 +0000114{
115 size_t blen;
116 struct blockdata *b;
Simon Kelley86bec2d2014-01-13 21:31:20 +0000117 void *new, *d;
Simon Kelley98c098b2014-01-08 17:31:16 +0000118
Simon Kelley86bec2d2014-01-13 21:31:20 +0000119 static unsigned int buff_len = 0;
120 static unsigned char *buff = NULL;
121
122 if (!data)
123 {
124 if (len > buff_len)
125 {
126 if (!(new = whine_malloc(len)))
127 return NULL;
128 if (buff)
129 free(buff);
130 buff = new;
131 }
132 data = buff;
133 }
134
135 for (d = data, b = block; len > 0 && b; b = b->next)
Simon Kelley98c098b2014-01-08 17:31:16 +0000136 {
137 blen = len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len;
Simon Kelley86bec2d2014-01-13 21:31:20 +0000138 memcpy(d, b->key, blen);
139 d += blen;
Simon Kelley98c098b2014-01-08 17:31:16 +0000140 len -= blen;
141 }
Simon Kelleyb6e9e7c2014-01-08 21:21:20 +0000142
Simon Kelley86bec2d2014-01-13 21:31:20 +0000143 return data;
Simon Kelley98c098b2014-01-08 17:31:16 +0000144}
Simon Kelleyb6e9e7c2014-01-08 21:21:20 +0000145
Simon Kelley98c098b2014-01-08 17:31:16 +0000146#endif