/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 dated June, 1991, or (at your option) version 3 dated 29 June, 2007. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "dnsmasq.h" #ifdef HAVE_DNSSEC static struct blockdata *keyblock_free = NULL; static unsigned int blockdata_count = 0, blockdata_hwm = 0; void blockdata_report(void) { my_syslog(LOG_INFO, _("DNSSEC memory in use %u, max %u"), blockdata_count * sizeof(struct blockdata), blockdata_hwm * sizeof(struct blockdata)); } struct blockdata *blockdata_alloc(char *data, size_t len) { struct blockdata *block, *ret = NULL; struct blockdata **prev = &ret; size_t blen; while (len > 0) { if (keyblock_free) { block = keyblock_free; keyblock_free = block->next; blockdata_count++; } else if ((block = whine_malloc(sizeof(struct blockdata)))) { blockdata_count++; if (blockdata_hwm < blockdata_count) blockdata_hwm = blockdata_count; } if (!block) { /* failed to alloc, free partial chain */ blockdata_free(ret); return NULL; } blen = len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len; memcpy(block->key, data, blen); data += blen; len -= blen; *prev = block; prev = &block->next; block->next = NULL; } return ret; } size_t blockdata_walk(struct blockdata **key, unsigned char **p, size_t cnt) { if (*p == NULL) *p = (*key)->key; else if (*p == (*key)->key + KEYBLOCK_LEN) { *key = (*key)->next; if (*key == NULL) return 0; *p = (*key)->key; } return MIN(cnt, (size_t)((*key)->key + KEYBLOCK_LEN - (*p))); } void blockdata_free(struct blockdata *blocks) { struct blockdata *tmp; if (blocks) { for (tmp = blocks; tmp->next; tmp = tmp->next) blockdata_count--; tmp->next = keyblock_free; keyblock_free = blocks; blockdata_count--; } } /* copy blocks into data[], return 1 if data[] unchanged by so doing */ int blockdata_retrieve(struct blockdata *block, size_t len, void *data) { size_t blen; struct blockdata *b; int match = 1; for (b = block; len > 0 && b; b = b->next) { blen = len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len; if (memcmp(data, b->key, blen) != 0) match = 0; memcpy(data, b->key, blen); data += blen; len -= blen; } return match; } #endif