summaryrefslogtreecommitdiff
path: root/src/zcompile/parser-util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/zcompile/parser-util.c')
-rw-r--r--src/zcompile/parser-util.c2488
1 files changed, 0 insertions, 2488 deletions
diff --git a/src/zcompile/parser-util.c b/src/zcompile/parser-util.c
deleted file mode 100644
index b112ece..0000000
--- a/src/zcompile/parser-util.c
+++ /dev/null
@@ -1,2488 +0,0 @@
-/*!
- * \file parser-util.c
- *
- * \author NLnet Labs
- * Copyright (c) 2001-2011, NLnet Labs. All rights reserved.
- *
- * \brief utility functions for zone parser.
- *
- * \addtogroup zoneparser
- * @{
- */
-
-/*
- * Copyright (c) 2001-2011, NLnet Labs. All rights reserved.
- *
- * This software is open source.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the NLNET LABS nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <config.h>
-#include <assert.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-
-//#include "common.h"
-#include "common/base32hex.h"
-#include "zcompile/parser-util.h"
-#include "zcompile/zcompile.h"
-#include "parser-descriptor.h"
-#include "libknot/util/utils.h"
-#include "zcompile/zcompile-error.h"
-
-#define IP6ADDRLEN (128/8)
-#define NS_INT16SZ 2
-#define NS_INADDRSZ 4
-#define NS_IN6ADDRSZ 16
-#define APL_NEGATION_MASK 0x80U
-
-/* int
- * inet_pton(af, src, dst)
- * convert from presentation format (which usually means ASCII printable)
- * to network format (which is usually some kind of binary format).
- * return:
- * 1 if the address was valid for the specified address family
- * 0 if the address wasn't valid (`dst' is untouched in this case)
- * -1 if some other error occurred (`dst' is untouched in this case, too)
- * author:
- * Paul Vixie, 1996.
- */
-int inet_pton(int af, const char *src, void *dst)
-{
- switch (af) {
- case AF_INET:
- return (inet_pton4(src, dst));
- case AF_INET6:
- return (inet_pton6(src, dst));
- default:
- errno = EAFNOSUPPORT;
- return (-1);
- }
- /* NOTREACHED */
-}
-
-//int my_b32_pton(const char *src, uint8_t *target, size_t tsize)
-//{
-// char ch;
-// size_t p = 0;
-
-// memset(target, '\0', tsize);
-// while ((ch = *src++)) {
-// uint8_t d;
-// size_t b;
-// size_t n;
-
-// if (p + 5 >= tsize * 8) {
-// return -1;
-// }
-
-// if (isspace(ch)) {
-// continue;
-// }
-
-// if (ch >= '0' && ch <= '9') {
-// d = ch - '0';
-// } else if (ch >= 'A' && ch <= 'V') {
-// d = ch - 'A' + 10;
-// } else if (ch >= 'a' && ch <= 'v') {
-// d = ch - 'a' + 10;
-// } else {
-// return -1;
-// }
-
-// b = 7 - p % 8;
-// n = p / 8;
-
-// if (b >= 4) {
-// target[n] |= d << (b - 4);
-// } else {
-// target[n] |= d >> (4 - b);
-// target[n+1] |= d << (b + 4);
-// }
-// p += 5;
-// }
-// return (p + 7) / 8;
-//}
-
-
-#define Assert(Cond) if (!(Cond)) abort()
-
-static const char Base64[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-static const char Pad64 = '=';
-
-/* int
- * inet_pton4(src, dst)
- * like inet_aton() but without all the hexadecimal and shorthand.
- * return:
- * 1 if `src' is a valid dotted quad, else 0.
- * notice:
- * does not touch `dst' unless it's returning 1.
- * author:
- * Paul Vixie, 1996.
- */
-int inet_pton4(const char *src, uint8_t *dst)
-{
- static const char digits[] = "0123456789";
- int saw_digit, octets, ch;
- uint8_t tmp[NS_INADDRSZ], *tp;
-
- saw_digit = 0;
- octets = 0;
- *(tp = tmp) = 0;
- while ((ch = *src++) != '\0') {
- const char *pch;
-
- if ((pch = strchr(digits, ch)) != NULL) {
- uint32_t new = *tp * 10 + (pch - digits);
-
- if (new > 255) {
- return (0);
- }
- *tp = new;
- if (! saw_digit) {
- if (++octets > 4) {
- return (0);
- }
- saw_digit = 1;
- }
- } else if (ch == '.' && saw_digit) {
- if (octets == 4) {
- return (0);
- }
- *++tp = 0;
- saw_digit = 0;
- } else {
- return (0);
- }
- }
- if (octets < 4) {
- return (0);
- }
-
- memcpy(dst, tmp, NS_INADDRSZ);
- return (1);
-}
-
-/* int
- * inet_pton6(src, dst)
- * convert presentation level address to network order binary form.
- * return:
- * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
- * notice:
- * (1) does not touch `dst' unless it's returning 1.
- * (2) :: in a full address is silently ignored.
- * credit:
- * inspired by Mark Andrews.
- * author:
- * Paul Vixie, 1996.
- */
-int inet_pton6(const char *src, uint8_t *dst)
-{
- static const char xdigits_l[] = "0123456789abcdef",
- xdigits_u[] = "0123456789ABCDEF";
- uint8_t tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
- const char *xdigits, *curtok;
- int ch, saw_xdigit;
- uint32_t val;
-
- memset((tp = tmp), '\0', NS_IN6ADDRSZ);
- endp = tp + NS_IN6ADDRSZ;
- colonp = NULL;
- /* Leading :: requires some special handling. */
- if (*src == ':')
- if (*++src != ':') {
- return (0);
- }
- curtok = src;
- saw_xdigit = 0;
- val = 0;
- while ((ch = *src++) != '\0') {
- const char *pch;
-
- if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) {
- pch = strchr((xdigits = xdigits_u), ch);
- }
- if (pch != NULL) {
- val <<= 4;
- val |= (pch - xdigits);
- if (val > 0xffff) {
- return (0);
- }
- saw_xdigit = 1;
- continue;
- }
- if (ch == ':') {
- curtok = src;
- if (!saw_xdigit) {
- if (colonp) {
- return (0);
- }
- colonp = tp;
- continue;
- }
- if (tp + NS_INT16SZ > endp) {
- return (0);
- }
- *tp++ = (uint8_t)(val >> 8) & 0xff;
- *tp++ = (uint8_t) val & 0xff;
- saw_xdigit = 0;
- val = 0;
- continue;
- }
- if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
- inet_pton4(curtok, tp) > 0) {
- tp += NS_INADDRSZ;
- saw_xdigit = 0;
- break; /* '\0' was seen by inet_pton4(). */
- }
- return (0);
- }
- if (saw_xdigit) {
- if (tp + NS_INT16SZ > endp) {
- return (0);
- }
- *tp++ = (uint8_t)(val >> 8) & 0xff;
- *tp++ = (uint8_t) val & 0xff;
- }
- if (colonp != NULL) {
- /*
- * Since some memmove()'s erroneously fail to handle
- * overlapping regions, we'll do the shift by hand.
- */
- const int n = tp - colonp;
- int i;
-
- for (i = 1; i <= n; i++) {
- endp[- i] = colonp[n - i];
- colonp[n - i] = 0;
- }
- tp = endp;
- }
- if (tp != endp) {
- return (0);
- }
- memcpy(dst, tmp, NS_IN6ADDRSZ);
- return (1);
-}
-
-
-#ifndef IN6ADDRSZ
-#define IN6ADDRSZ 16 /* IPv6 T_AAAA */
-#endif
-
-#ifndef INT16SZ
-#define INT16SZ 2 /* for systems without 16-bit ints */
-#endif
-
-/*
- * WARNING: Don't even consider trying to compile this on a system where
- * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
- */
-
-
-/* char *
- * inet_ntop(af, src, dst, size)
- * convert a network format address to presentation format.
- * return:
- * pointer to presentation format address (`dst'), or NULL (see errno).
- * author:
- * Paul Vixie, 1996.
- */
-//const char *inet_ntop(int af, const void *src, char *dst, size_t size)
-//{
-// switch (af) {
-// case AF_INET:
-// return (inet_ntop4(src, dst, size));
-// case AF_INET6:
-// return (inet_ntop6(src, dst, size));
-// default:
-// errno = EAFNOSUPPORT;
-// return (NULL);
-// }
-// /* NOTREACHED */
-//}
-
-/* const char *
- * inet_ntop4(src, dst, size)
- * format an IPv4 address, more or less like inet_ntoa()
- * return:
- * `dst' (as a const)
- * notes:
- * (1) uses no statics
- * (2) takes a u_char* not an in_addr as input
- * author:
- * Paul Vixie, 1996.
- */
-const char *inet_ntop4(const u_char *src, char *dst, size_t size)
-{
- static const char fmt[] = "%u.%u.%u.%u";
- char tmp[sizeof "255.255.255.255"];
- int l;
-
- l = snprintf(tmp, size, fmt, src[0], src[1], src[2], src[3]);
- if (l <= 0 || l >= (int)size) {
- errno = ENOSPC;
- return (NULL);
- }
- knot_strlcpy(dst, tmp, size);
- return (dst);
-}
-
-/* const char *
- * inet_ntop6(src, dst, size)
- * convert IPv6 binary address into presentation (printable) format
- * author:
- * Paul Vixie, 1996.
- */
-const char *inet_ntop6(const u_char *src, char *dst, size_t size)
-{
- /*
- * Note that int32_t and int16_t need only be "at least" large enough
- * to contain a value of the specified size. On some systems, like
- * Crays, there is no such thing as an integer variable with 16 bits.
- * Keep this in mind if you think this function should have been coded
- * to use pointer overlays. All the world's not a VAX.
- */
- char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
- char *tp, *ep;
- struct {
- int base, len;
- } best, cur;
- best.base = cur.base =-1;
- best.len = cur.len = 0;
- u_int words[IN6ADDRSZ / INT16SZ];
- int i;
- int advance;
-
- /*
- * Preprocess:
- * Copy the input (bytewise) array into a wordwise array.
- * Find the longest run of 0x00's in src[] for :: shorthanding.
- */
- memset(words, '\0', sizeof words);
- for (i = 0; i < IN6ADDRSZ; i++) {
- words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
- }
-
- for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
- if (words[i] == 0) {
- if (cur.base == -1) {
- cur.base = i, cur.len = 1;
- } else {
- cur.len++;
- }
- } else {
- if (cur.base != -1) {
- if (best.base == -1 || cur.len > best.len) {
- best = cur;
- }
- cur.base = -1;
- }
- }
- }
- if (cur.base != -1) {
- if (best.base == -1 || cur.len > best.len) {
- best = cur;
- }
- }
- if (best.base != -1 && best.len < 2) {
- best.base = -1;
- }
-
- /*
- * Format the result.
- */
- tp = tmp;
- ep = tmp + sizeof(tmp);
- for (i = 0; i < (IN6ADDRSZ / INT16SZ) && tp < ep; i++) {
- /* Are we inside the best run of 0x00's? */
- if (best.base != -1 && i >= best.base &&
- i < (best.base + best.len)) {
- if (i == best.base) {
- if (tp + 1 >= ep) {
- return (NULL);
- }
- *tp++ = ':';
- }
- continue;
- }
- /* Are we following an initial run of 0x00s or any real hex? */
- if (i != 0) {
- if (tp + 1 >= ep) {
- return (NULL);
- }
- *tp++ = ':';
- }
- /* Is this address an encapsulated IPv4? */
- if (i == 6 && best.base == 0 &&
- (best.len == 6 ||
- (best.len == 5 && words[5] == 0xffff))) {
- if (!inet_ntop4(src + 12, tp, (size_t)(ep - tp))) {
- return (NULL);
- }
- tp += strlen(tp);
- break;
- }
- advance = snprintf(tp, ep - tp, "%x", words[i]);
- if (advance <= 0 || advance >= ep - tp) {
- return (NULL);
- }
- tp += advance;
- }
- /* Was it a trailing run of 0x00's? */
- if (best.base != -1 && (best.base + best.len) ==
- (IN6ADDRSZ / INT16SZ)) {
- if (tp + 1 >= ep) {
- return (NULL);
- }
- *tp++ = ':';
- }
- if (tp + 1 >= ep) {
- return (NULL);
- }
- *tp++ = '\0';
-
- /*
- * Check for overflow, copy, and we're done.
- */
- if ((size_t)(tp - tmp) > size) {
- errno = ENOSPC;
- return (NULL);
- }
- knot_strlcpy(dst, tmp, size);
- return (dst);
-}
-
-
-static int b64rmap_initialized = 0;
-static uint8_t b64rmap[256];
-
-static const uint8_t b64rmap_special = 0xf0;
-static const uint8_t b64rmap_end = 0xfd;
-static const uint8_t b64rmap_space = 0xfe;
-static const uint8_t b64rmap_invalid = 0xff;
-
-/**
- * Initializing the reverse map is not thread safe.
- * Which is fine for NSD. For now...
- **/
-void b64_initialize_rmap()
-{
- int i;
- char ch;
-
- /* Null: end of string, stop parsing */
- b64rmap[0] = b64rmap_end;
-
- for (i = 1; i < 256; ++i) {
- ch = (char)i;
- /* Whitespaces */
- if (isspace(ch)) {
- b64rmap[i] = b64rmap_space;
- }
- /* Padding: stop parsing */
- else if (ch == Pad64) {
- b64rmap[i] = b64rmap_end;
- }
- /* Non-base64 char */
- else {
- b64rmap[i] = b64rmap_invalid;
- }
- }
-
- /* Fill reverse mapping for base64 chars */
- for (i = 0; Base64[i] != '\0'; ++i) {
- b64rmap[(uint8_t)Base64[i]] = i;
- }
-
- b64rmap_initialized = 1;
-}
-
-int b64_pton_do(char const *src, uint8_t *target, size_t targsize)
-{
- int tarindex, state, ch;
- uint8_t ofs;
-
- state = 0;
- tarindex = 0;
-
- while (1) {
- ch = *src++;
- ofs = b64rmap[ch];
-
- if (ofs >= b64rmap_special) {
- /* Ignore whitespaces */
- if (ofs == b64rmap_space) {
- continue;
- }
- /* End of base64 characters */
- if (ofs == b64rmap_end) {
- break;
- }
- /* A non-base64 character. */
- return (-1);
- }
-
- switch (state) {
- case 0:
- if ((size_t)tarindex >= targsize) {
- return (-1);
- }
- target[tarindex] = ofs << 2;
- state = 1;
- break;
- case 1:
- if ((size_t)tarindex + 1 >= targsize) {
- return (-1);
- }
- target[tarindex] |= ofs >> 4;
- target[tarindex+1] = (ofs & 0x0f)
- << 4 ;
- tarindex++;
- state = 2;
- break;
- case 2:
- if ((size_t)tarindex + 1 >= targsize) {
- return (-1);
- }
- target[tarindex] |= ofs >> 2;
- target[tarindex+1] = (ofs & 0x03)
- << 6;
- tarindex++;
- state = 3;
- break;
- case 3:
- if ((size_t)tarindex >= targsize) {
- return (-1);
- }
- target[tarindex] |= ofs;
- tarindex++;
- state = 0;
- break;
- default:
- abort();
- }
- }
-
- /*
- * We are done decoding Base-64 chars. Let's see if we ended
- * on a byte boundary, and/or with erroneous trailing characters.
- */
-
- if (ch == Pad64) { /* We got a pad char. */
- ch = *src++; /* Skip it, get next. */
- switch (state) {
- case 0: /* Invalid = in first position */
- case 1: /* Invalid = in second position */
- return (-1);
-
- case 2: /* Valid, means one byte of info */
- /* Skip any number of spaces. */
- for ((void)NULL; ch != '\0'; ch = *src++)
- if (b64rmap[ch] != b64rmap_space) {
- break;
- }
- /* Make sure there is another trailing = sign. */
- if (ch != Pad64) {
- return (-1);
- }
- ch = *src++; /* Skip the = */
- /* Fall through to "single trailing =" case. */
- /* FALLTHROUGH */
-
- case 3: /* Valid, means two bytes of info */
- /*
- * We know this char is an =. Is there anything but
- * whitespace after it?
- */
- for ((void)NULL; ch != '\0'; ch = *src++)
- if (b64rmap[ch] != b64rmap_space) {
- return (-1);
- }
-
- /*
- * Now make sure for cases 2 and 3 that the "extra"
- * bits that slopped past the last full byte were
- * zeros. If we don't check them, they become a
- * subliminal channel.
- */
- if (target[tarindex] != 0) {
- return (-1);
- }
- }
- } else {
- /*
- * We ended by seeing the end of the string. Make sure we
- * have no partial bytes lying around.
- */
- if (state != 0) {
- return (-1);
- }
- }
-
- return (tarindex);
-}
-
-
-int b64_pton_len(char const *src)
-{
- int tarindex, state, ch;
- uint8_t ofs;
-
- state = 0;
- tarindex = 0;
-
- while (1) {
- ch = *src++;
- ofs = b64rmap[ch];
-
- if (ofs >= b64rmap_special) {
- /* Ignore whitespaces */
- if (ofs == b64rmap_space) {
- continue;
- }
- /* End of base64 characters */
- if (ofs == b64rmap_end) {
- break;
- }
- /* A non-base64 character. */
- return (-1);
- }
-
- switch (state) {
- case 0:
- state = 1;
- break;
- case 1:
- tarindex++;
- state = 2;
- break;
- case 2:
- tarindex++;
- state = 3;
- break;
- case 3:
- tarindex++;
- state = 0;
- break;
- default:
- abort();
- }
- }
-
- /*
- * We are done decoding Base-64 chars. Let's see if we ended
- * on a byte boundary, and/or with erroneous trailing characters.
- */
-
- if (ch == Pad64) { /* We got a pad char. */
- ch = *src++; /* Skip it, get next. */
- switch (state) {
- case 0: /* Invalid = in first position */
- case 1: /* Invalid = in second position */
- return (-1);
-
- case 2: /* Valid, means one byte of info */
- /* Skip any number of spaces. */
- for ((void)NULL; ch != '\0'; ch = *src++)
- if (b64rmap[ch] != b64rmap_space) {
- break;
- }
- /* Make sure there is another trailing = sign. */
- if (ch != Pad64) {
- return (-1);
- }
- ch = *src++; /* Skip the = */
- /* Fall through to "single trailing =" case. */
- /* FALLTHROUGH */
-
- case 3: /* Valid, means two bytes of info */
- /*
- * We know this char is an =. Is there anything but
- * whitespace after it?
- */
- for ((void)NULL; ch != '\0'; ch = *src++)
- if (b64rmap[ch] != b64rmap_space) {
- return (-1);
- }
-
- }
- } else {
- /*
- * We ended by seeing the end of the string. Make sure we
- * have no partial bytes lying around.
- */
- if (state != 0) {
- return (-1);
- }
- }
-
- return (tarindex);
-}
-
-int b64_pton(char const *src, uint8_t *target, size_t targsize)
-{
- if (!b64rmap_initialized) {
- b64_initialize_rmap();
- }
-
- if (target) {
- return b64_pton_do(src, target, targsize);
- } else {
- return b64_pton_len(src);
- }
-}
-
-void set_bit(uint8_t bits[], size_t index)
-{
- /*
- * The bits are counted from left to right, so bit #0 is the
- * left most bit.
- */
- bits[index / 8] |= (1 << (7 - index % 8));
-}
-
-uint32_t strtoserial(const char *nptr, const char **endptr)
-{
- uint32_t i = 0;
- uint32_t serial = 0;
-
- for (*endptr = nptr; **endptr; (*endptr)++) {
- switch (**endptr) {
- case ' ':
- case '\t':
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- i *= 10;
- i += (**endptr - '0');
- break;
- default:
- break;
- }
- }
- serial += i;
- return serial;
-}
-
-inline void write_uint32(void *dst, uint32_t data)
-{
-/*!< \todo Check what this means and delete if obsolete. */
-#ifdef ALLOW_UNALIGNED_ACCESSES
- *(uint32_t *) dst = htonl(data);
-#else
- uint8_t *p = (uint8_t *) dst;
- p[0] = (uint8_t)((data >> 24) & 0xff);
- p[1] = (uint8_t)((data >> 16) & 0xff);
- p[2] = (uint8_t)((data >> 8) & 0xff);
- p[3] = (uint8_t)(data & 0xff);
-#endif
-}
-
-uint32_t strtottl(const char *nptr, const char **endptr)
-{
- uint32_t i = 0;
- uint32_t seconds = 0;
-
- for (*endptr = nptr; **endptr; (*endptr)++) {
- switch (**endptr) {
- case ' ':
- case '\t':
- break;
- case 's':
- case 'S':
- seconds += i;
- i = 0;
- break;
- case 'm':
- case 'M':
- seconds += i * 60;
- i = 0;
- break;
- case 'h':
- case 'H':
- seconds += i * 60 * 60;
- i = 0;
- break;
- case 'd':
- case 'D':
- seconds += i * 60 * 60 * 24;
- i = 0;
- break;
- case 'w':
- case 'W':
- seconds += i * 60 * 60 * 24 * 7;
- i = 0;
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- i *= 10;
- i += (**endptr - '0');
- break;
- default:
- seconds += i;
- return seconds;
- }
- }
- seconds += i;
- return seconds;
-}
-
-/* Number of days per month (except for February in leap years). */
-static const int mdays[] = {
- 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
-};
-
-static int is_leap_year(int year)
-{
- return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
-}
-
-static int leap_days(int y1, int y2)
-{
- --y1;
- --y2;
- return (y2/4 - y1/4) - (y2/100 - y1/100) + (y2/400 - y1/400);
-}
-
-/*
- * Code adapted from Python 2.4.1 sources (Lib/calendar.py).
- */
-time_t mktime_from_utc(const struct tm *tm)
-{
- int year = 1900 + tm->tm_year;
- time_t days = 365 * (year - 1970) + leap_days(1970, year);
- time_t hours;
- time_t minutes;
- time_t seconds;
- int i;
-
- for (i = 0; i < tm->tm_mon; ++i) {
- days += mdays[i];
- }
- if (tm->tm_mon > 1 && is_leap_year(year)) {
- ++days;
- }
- days += tm->tm_mday - 1;
-
- hours = days * 24 + tm->tm_hour;
- minutes = hours * 60 + tm->tm_min;
- seconds = minutes * 60 + tm->tm_sec;
-
- return seconds;
-}
-
-/*!< Following functions are conversions from text to wire. */
-//#define DEBUG_UNKNOWN_RDATA
-
-#ifdef DEBUG_UNKNOWN_RDATA
-#define dbg_rdata(msg...) fprintf(stderr, msg)
-#define DBG_RDATA(cmds) do { cmds } while (0)
-#else
-#define dbg_rdata(msg...)
-#define DBG_RDATA(cmds)
-#endif
-
-
-
-#define IP6ADDRLEN (128/8)
-#define NS_INT16SZ 2
-#define NS_INADDRSZ 4
-#define NS_IN6ADDRSZ 16
-#define APL_NEGATION_MASK 0x80U
-#define APL_LENGTH_MASK (~APL_NEGATION_MASK)
-
-//#define ZP_DEBUG
-
-#ifdef ZP_DEBUG
-#define dbg_zp(msg...) fprintf(stderr, msg)
-#else
-#define dbg_zp(msg...)
-#endif
-
-
-/*!
- * \brief Return data of raw data item.
- *
- * \param item Item.
- * \return uint16_t * Raw data.
- */
-static inline uint16_t * rdata_atom_data(knot_rdata_item_t item)
-{
- return (uint16_t *)(item.raw_data + 1);
-}
-
-/*!
- * \brief Return type of RRSet covered by given RRSIG.
- *
- * \param rrset RRSIG.
- * \return uint16_t Type covered.
- */
-uint16_t rrsig_type_covered(knot_rrset_t *rrset)
-{
- assert(rrset->rdata->items[0].raw_data[0] == sizeof(uint16_t));
-
- return ntohs(*(uint16_t *) rdata_atom_data(rrset->rdata->items[0]));
-}
-
-/*!
- * \brief Checks if item contains domain.
- *
- * \param type Type of RRSet.
- * \param index Index to check.
- *
- * \return > 1 if item is domain, 0 otherwise.
- */
-static inline int rdata_atom_is_domain(uint16_t type, size_t index)
-{
- const knot_rrtype_descriptor_t *descriptor
- = knot_rrtype_descriptor_by_type(type);
- return (index < descriptor->length
- && (descriptor->wireformat[index] ==
- KNOT_RDATA_WF_COMPRESSED_DNAME ||
- descriptor->wireformat[index] ==
- KNOT_RDATA_WF_LITERAL_DNAME ||
- descriptor->wireformat[index] ==
- KNOT_RDATA_WF_UNCOMPRESSED_DNAME));
-}
-
-/*!
- * \brief Returns which wireformat type is on given index.
- *
- * \param type Type of RRSet.
- * \param index Index.
- *
- * \return uint8_t Wireformat type.
- */
-static inline uint8_t rdata_atom_wireformat_type(uint16_t type, size_t index)
-{
- const knot_rrtype_descriptor_t *descriptor =
- knot_rrtype_descriptor_by_type(type);
- assert(index < descriptor->length);
- return descriptor->wireformat[index];
-}
-
-typedef int (*printf_t)(const char *fmt, ...);
-
-/*!
- * \brief Converts rdata wireformat to rdata items.
- *
- * \param wireformat Wireformat/.
- * \param rrtype RR type.
- * \param data_size Size of wireformat.
- * \param items created rdata items.
- *
- * \return Number of items converted.
- */
-static ssize_t rdata_wireformat_to_rdata_atoms(const uint16_t *wireformat,
- uint16_t rrtype,
- const uint16_t data_size,
- knot_rdata_item_t **items)
-{
- /*!< \todo This is so ugly, it makes me wanna puke. */
- uint16_t const *end =
- (uint16_t *)((uint8_t *)wireformat + (data_size));
- dbg_rdata("set end pointer: %p which means length: %d\n", end,
- (uint8_t *)end - (uint8_t *)wireformat);
- dbg_rdata("Parsing following wf: ");
- size_t i;
- knot_rdata_item_t *temp_rdatas =
- malloc(sizeof(*temp_rdatas) * MAXRDATALEN);
- if (temp_rdatas == NULL) {
- ERR_ALLOC_FAILED;
- return KNOTDZCOMPILE_ENOMEM;
- }
- memset(temp_rdatas, 0, sizeof(*temp_rdatas) * MAXRDATALEN);
-
- knot_rrtype_descriptor_t *descriptor =
- knot_rrtype_descriptor_by_type(rrtype);
-
- assert(descriptor->length <= MAXRDATALEN);
-
- dbg_rdata("will be parsing %d items, total size: %d\n",
- descriptor->length, data_size);
-
- for (i = 0; i < descriptor->length; ++i) {
- dbg_rdata("this particular item is type %d.\n",
- rdata_atom_wireformat_type(rrtype, i));
- int is_domain = 0;
- int is_wirestore = 0;
- size_t length = 0;
- length = 0;
- bool required = descriptor->fixed_items;
-
- switch (rdata_atom_wireformat_type(rrtype, i)) {
- case KNOT_RDATA_WF_COMPRESSED_DNAME:
- case KNOT_RDATA_WF_UNCOMPRESSED_DNAME:
- dbg_rdata("Parsed item is a dname.\n");
- is_domain = 1;
- break;
- case KNOT_RDATA_WF_LITERAL_DNAME:
- dbg_rdata("Parsed item is a literal dname.\n");
- is_domain = 1;
- is_wirestore = 1;
- break;
- case KNOT_RDATA_WF_BYTE:
- dbg_rdata("Parsed item is a byte.\n");
- length = sizeof(uint8_t);
- break;
- case KNOT_RDATA_WF_SHORT:
- dbg_rdata("Parsed item is a short.\n");
- length = sizeof(uint16_t);
- break;
- case KNOT_RDATA_WF_LONG:
- dbg_rdata("Parsed item is a long.\n");
- length = sizeof(uint32_t);
- break;
- case KNOT_RDATA_WF_APL:
- dbg_rdata("APL data.\n");
- case KNOT_RDATA_WF_TEXT_SINGLE:
- case KNOT_RDATA_WF_TEXT:
- dbg_rdata("TEXT rdata.\n");
- case KNOT_RDATA_WF_BINARYWITHLENGTH:
- dbg_rdata("BINARYWITHLENGTH rdata.\n");
- /* Length is stored in the first byte. */
- length = data_size;
- break;
- case KNOT_RDATA_WF_A:
- dbg_rdata("Parsed item is an IPv4 address.\n");
- length = sizeof(in_addr_t);
- break;
- case KNOT_RDATA_WF_AAAA:
- dbg_rdata("Parsed item is an IPv6 address.\n");
- length = IP6ADDRLEN;
- break;
- case KNOT_RDATA_WF_BINARY:
- /* Remaining RDATA is binary. */
- dbg_rdata("BINARY: item %d: guessing length from pointers: %p %p. ",
- i,
- wireformat, end);
- length = (uint8_t *)end - (uint8_t *)wireformat;
- dbg_rdata("Result: %d.\n",
- length);
- break;
-// case KNOT_RDATA_WF_APL:
-// length = (sizeof(uint16_t) /* address family */
-// + sizeof(uint8_t) /* prefix */
-// + sizeof(uint8_t)); /* length */
-// if ((uint8_t *)wireformat + length <= (uint8_t *)end) {
-// /* Mask out negation bit. */
-// dbg_rdata("APL: length was %d. ", length);
-// length += (wireformat[data_size - 1]
-// & APL_LENGTH_MASK);
-// dbg_rdata("APL: after masking: %d.\n", length);
-// }
-// break;
- case KNOT_RDATA_WF_IPSECGATEWAY:
- dbg_rdata("Parsed item is an IPSECGATEWAY address.\n");
- dbg_rdata("Gateway type: %d\n",
- ((uint8_t *)rdata_atom_data(temp_rdatas[1]))[0]);
- switch (((uint8_t *)rdata_atom_data(temp_rdatas[1]))[0]) {
- /* gateway type */
- case IPSECKEY_NOGATEWAY:
- dbg_rdata("NOGATEWAY\n");
- length = 0;
- break;
- case IPSECKEY_IP4:
- dbg_rdata("IPv4\n");
- length = 4;
- break;
- case IPSECKEY_IP6:
- dbg_rdata("IPv6\n");
- length = IP6ADDRLEN;
- break;
- case IPSECKEY_DNAME:
- dbg_rdata("DNAME\n");
- is_domain = 1;
- is_wirestore = 1;
- break;
- default:
- dbg_rdata("Unknown IPSECKEY gateway!\n");
- free(temp_rdatas);
- return -1;
- } // switch
- }
-
- if (is_domain) {
- knot_dname_t *dname = NULL;
- /*
- * Since we don't know how many dnames there are
- * in the whole wireformat we have to search for next
- * '\0'.
- */
- for (length = 0;
- (length < ((uint8_t *)end - (uint8_t *)wireformat))
- && (((uint8_t *)wireformat)[length] != '\0');
- length++) {
- ;
- }
- length++;
- dbg_rdata("item %d: length derived from position of "
- "0: %d\n", i, length);
-
- if (!required && (wireformat == end)) {
- break;
- }
-
- dname = knot_dname_new_from_wire((uint8_t *)wireformat,
- length,
- NULL);
-
- if (dname == NULL) {
- dbg_rdata("malformed dname!\n");
- /*! \todo rdata purge */
- free(temp_rdatas);
- return KNOTDZCOMPILE_EBRDATA;
- }
-
- dbg_rdata("item %d: created dname: %s, length: %d\n", i,
- knot_dname_to_str(dname), length);
-
- if (is_wirestore) {
- /*temp_rdatas[i].raw_data =
- (uint16_t *) region_alloc(
- region, sizeof(uint16_t) + dname->name_size);
- temp_rdatas[i].data[0] = dname->name_size;
- memcpy(temp_rdatas[i].data+1, dname_name(dname),
- dname->name_size); */
- temp_rdatas[i].raw_data =
- malloc(sizeof(uint16_t) +
- sizeof(uint8_t) * dname->size);
- if (temp_rdatas[i].raw_data == NULL) {
- ERR_ALLOC_FAILED;
- /*! \todo rdata purge */
- free(temp_rdatas);
- return KNOTDZCOMPILE_ENOMEM;
- }
-
- temp_rdatas[i].raw_data[0] = dname->size;
- memcpy(temp_rdatas[i].raw_data + 1,
- dname->name, dname->size);
-
- knot_dname_release(dname);
- } else {
- temp_rdatas[i].dname = dname;
- }
-
- } else {
- /*!< \todo This calculated length makes no sense! */
- dbg_rdata("item %d :length: %d calculated: %d (%p %p)\n", i, length,
- end - wireformat,
- wireformat, end);
- if ((uint8_t *)wireformat + length > (uint8_t *)end) {
- if (required) {
- /* Truncated RDATA. */
- /*! \todo rdata purge */
- free(temp_rdatas);
- dbg_rdata("truncated rdata, end pointer is exceeded by %d octets.\n",
- (wireformat + length) - end);
- return KNOTDZCOMPILE_EBRDATA;
- } else {
- break;
- }
- }
-
- assert(wireformat <= end); /*!< \todo remove! */
- dbg_rdata("calling init with: %p and length : %d\n",
- wireformat, length);
- temp_rdatas[i].raw_data = alloc_rdata_init(wireformat,
- length);
- if (temp_rdatas[i].raw_data == NULL) {
- ERR_ALLOC_FAILED;
- /*! \todo rdata purge */
- free(temp_rdatas);
- return -1;
- }
-
-// temp_rdatas[i].raw_data[0] = length;
-// memcpy(temp_rdatas[i].raw_data + 1, wireformat, length);
-
-/* temp_rdatas[i].data = (uint16_t *) region_alloc(
- region, sizeof(uint16_t) + length);
- temp_rdatas[i].data[0] = length;
- buffer_read(packet,
- temp_rdatas[i].data + 1, length); */
- }
- dbg_rdata("%d: adding length: %d (remaining: %d)\n", i, length,
- (uint8_t *)end - ((uint8_t *)wireformat + length));
-// hex_print(temp_rdatas[i].raw_data + 1, length);
- wireformat = (uint16_t *)((uint8_t *)wireformat + length);
-// wireformat = wireformat + length;
- dbg_rdata("wire: %p\n", wireformat);
- dbg_rdata("remaining now: %d\n",
- end - wireformat);
- }
-
- dbg_rdata("%p %p\n", wireformat, (uint8_t *)wireformat);
-
- if (wireformat < end) {
- /* Trailing garbage. */
- dbg_rdata("Garbage: w: %p e: %p %d\n", wireformat, end, end - wireformat);
- free(temp_rdatas);
- return KNOTDZCOMPILE_EBRDATA;
- }
-
- *items = temp_rdatas;
- /* *rdatas = (rdata_atom_type *) region_alloc_init(
- region, temp_rdatas, i * sizeof(rdata_atom_type)); */
- dbg_rdata("wf_to_rdata_atoms: Succesfully converted %d items.\n",
- i);
- return (ssize_t)i;
-}
-
-/* Taken from RFC 2535, section 7. */
-knot_lookup_table_t dns_algorithms[] = {
- { 1, "RSAMD5" }, /* RFC 2537 */
- { 2, "DH" }, /* RFC 2539 */
- { 3, "DSA" }, /* RFC 2536 */
- { 4, "ECC" },
- { 5, "RSASHA1" }, /* RFC 3110 */
- { 252, "INDIRECT" },
- { 253, "PRIVATEDNS" },
- { 254, "PRIVATEOID" },
- { 0, NULL }
-};
-
-/* Taken from RFC 4398, section 2.1. */
-knot_lookup_table_t dns_certificate_types[] = {
- /* 0 Reserved */
- { 1, "PKIX" }, /* X.509 as per PKIX */
- { 2, "SPKI" }, /* SPKI cert */
- { 3, "PGP" }, /* OpenPGP packet */
- { 4, "IPKIX" }, /* The URL of an X.509 data object */
- { 5, "ISPKI" }, /* The URL of an SPKI certificate */
- { 6, "IPGP" }, /* The fingerprint and URL of an OpenPGP packet */
- { 7, "ACPKIX" }, /* Attribute Certificate */
- { 8, "IACPKIX" }, /* The URL of an Attribute Certificate */
- { 253, "URI" }, /* URI private */
- { 254, "OID" }, /* OID private */
- /* 255 Reserved */
- /* 256-65279 Available for IANA assignment */
- /* 65280-65534 Experimental */
- /* 65535 Reserved */
- { 0, NULL }
-};
-
-/* Imported from lexer. */
-extern int hexdigit_to_int(char ch);
-
-extern uint8_t nsecbits[NSEC_WINDOW_COUNT][NSEC_WINDOW_BITS_SIZE];
-extern uint16_t nsec_highest_rcode;
-
-/*!
- * \brief Allocate SIZE+sizeof(uint16_t) bytes and store SIZE in the first
- * element. Return a pointer to the allocation.
- *
- * \param size How many bytes to allocate.
- */
-static uint16_t * alloc_rdata(size_t size)
-{
- uint16_t *result = malloc(sizeof(uint16_t) + size);
- *result = size;
- return result;
-}
-
-uint16_t *alloc_rdata_init(const void *data, size_t size)
-{
- uint16_t *result = malloc(sizeof(uint16_t) + size);
- if (result == NULL) {
- return NULL;
- }
- *result = size;
- memcpy(result + 1, data, size);
- return result;
-}
-
-/*
- * These are parser function for generic zone file stuff.
- */
-uint16_t * zparser_conv_hex(const char *hex, size_t len)
-{
- /* convert a hex value to wireformat */
- uint16_t *r = NULL;
- uint8_t *t;
- int i;
-
- if (len % 2 != 0) {
- zc_error_prev_line("number of hex digits "
- "must be a multiple of 2");
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- } else if (len > MAX_RDLENGTH * 2) {
- zc_error_prev_line("hex data exceeds maximum rdata length (%d)",
- MAX_RDLENGTH);
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- } else {
- /* the length part */
-
- r = alloc_rdata(len / 2);
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
- t = (uint8_t *)(r + 1);
-
- /* Now process octet by octet... */
- while (*hex) {
- *t = 0;
- for (i = 16; i >= 1; i -= 15) {
- if (isxdigit((int)*hex)) {
- *t += hexdigit_to_int(*hex) * i;
- } else {
- zc_error_prev_line(
- "illegal hex character '%c'",
- (int) *hex);
- parser->error_occurred =
- KNOTDZCOMPILE_EBRDATA;
- free(r);
- return NULL;
- }
- ++hex;
- }
- ++t;
- }
- }
-
- return r;
-}
-
-/* convert hex, precede by a 1-byte length */
-uint16_t * zparser_conv_hex_length(const char *hex, size_t len)
-{
- uint16_t *r = NULL;
- uint8_t *t;
- int i;
- if (len % 2 != 0) {
- zc_error_prev_line("number of hex digits must be a "
- "multiple of 2");
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- } else if (len > 255 * 2) {
- zc_error_prev_line("hex data exceeds 255 bytes");
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- } else {
- uint8_t *l;
-
- /* the length part */
- r = alloc_rdata(len / 2 + 1);
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
-
- t = (uint8_t *)(r + 1);
-
- l = t++;
- *l = '\0';
-
- /* Now process octet by octet... */
- while (*hex) {
- *t = 0;
- for (i = 16; i >= 1; i -= 15) {
- if (isxdigit((int)*hex)) {
- *t += hexdigit_to_int(*hex) * i;
- } else {
- zc_error_prev_line(
- "illegal hex character '%c'",
- (int) *hex);
- parser->error_occurred =
- KNOTDZCOMPILE_EBRDATA;
- free(r);
- return NULL;
- }
- ++hex;
- }
- ++t;
- ++*l;
- }
- }
- return r;
-}
-
-uint16_t * zparser_conv_time(const char *time)
-{
- /* convert a time YYHM to wireformat */
- uint16_t *r = NULL;
- struct tm tm;
-
- /* Try to scan the time... */
- if (!strptime(time, "%Y%m%d%H%M%S", &tm)) {
- zc_error_prev_line("date and time is expected");
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- } else {
- uint32_t l = htonl(mktime_from_utc(&tm));
- r = alloc_rdata_init(&l, sizeof(l));
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
- }
- return r;
-}
-
-uint16_t * zparser_conv_services(const char *protostr, char *servicestr)
-{
- /*
- * Convert a protocol and a list of service port numbers
- * (separated by spaces) in the rdata to wireformat
- */
- uint16_t *r = NULL;
- uint8_t *p;
- uint8_t bitmap[65536/8];
- char sep[] = " ";
- char *word;
- int max_port = -8;
- /* convert a protocol in the rdata to wireformat */
- struct protoent *proto;
-
- memset(bitmap, 0, sizeof(bitmap));
-
- proto = getprotobyname(protostr);
- if (!proto) {
- proto = getprotobynumber(atoi(protostr));
- }
- if (!proto) {
- zc_error_prev_line("unknown protocol '%s'", protostr);
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- return NULL;
- }
-
- char *sp = 0;
- while ((word = strtok_r(servicestr, sep, &sp))) {
- struct servent *service = NULL;
- int port;
-
- service = getservbyname(word, proto->p_name);
- if (service) {
- /* Note: ntohs not ntohl! Strange but true. */
- port = ntohs((uint16_t) service->s_port);
-// printf("assigned port %d\n", port);
- } else {
-// printf("else\n");
- char *end;
- port = strtol(word, &end, 10);
- if (*end != '\0') {
- zc_error_prev_line(
- "unknown service '%s' for"
- " protocol '%s'",
- word, protostr);
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- return NULL;
- }
- }
-
- if (port < 0 || port > 65535) {
- zc_error_prev_line("bad port number %d", port);
- } else {
- set_bit(bitmap, port);
- if (port > max_port) {
- max_port = port;
- }
- }
- servicestr = NULL;
- }
-
- r = alloc_rdata(sizeof(uint8_t) + max_port / 8 + 1);
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
-
- p = (uint8_t *)(r + 1);
- *p = proto->p_proto;
- memcpy(p + 1, bitmap, *r - 1);
-
- return r;
-}
-
-uint16_t * zparser_conv_serial(const char *serialstr)
-{
- uint16_t *r = NULL;
- uint32_t serial;
- const char *t;
-
- serial = strtoserial(serialstr, &t);
- if (*t != '\0') {
- zc_error_prev_line("serial is expected");
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- } else {
- serial = htonl(serial);
- r = alloc_rdata_init(&serial, sizeof(serial));
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
- }
- return r;
-}
-
-uint16_t * zparser_conv_period(const char *periodstr)
-{
- /* convert a time period (think TTL's) to wireformat) */
- uint16_t *r = NULL;
- uint32_t period;
- const char *end;
-
- /* Allocate required space... */
- period = strtottl(periodstr, &end);
- if (*end != '\0') {
- zc_error_prev_line("time period is expected");
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- } else {
- period = htonl(period);
- r = alloc_rdata_init(&period, sizeof(period));
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
- }
- return r;
-}
-
-uint16_t * zparser_conv_short(const char *text)
-{
- uint16_t *r = NULL;
- uint16_t value;
- char *end;
-
- value = htons((uint16_t) strtol(text, &end, 10));
- if (*end != '\0') {
- zc_error_prev_line("integer value is expected");
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- } else {
- r = alloc_rdata_init(&value, sizeof(value));
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
- }
- return r;
-}
-
-uint16_t * zparser_conv_byte(const char *text)
-{
- uint16_t *r = NULL;
- uint8_t value;
- char *end;
-
- value = (uint8_t) strtol(text, &end, 10);
- if (*end != '\0') {
- zc_error_prev_line("integer value is expected");
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- } else {
- r = alloc_rdata_init(&value, sizeof(value));
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
- }
- return r;
-}
-
-uint16_t * zparser_conv_algorithm(const char *text)
-{
- const knot_lookup_table_t *alg;
- uint8_t id;
-
- alg = knot_lookup_by_name(dns_algorithms, text);
- if (alg) {
- id = (uint8_t) alg->id;
- } else {
- char *end;
- id = (uint8_t) strtol(text, &end, 10);
- if (*end != '\0') {
- zc_error_prev_line("algorithm is expected");
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- return NULL;
- }
- }
-
- uint16_t *r = alloc_rdata_init(&id, sizeof(id));
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
-
- return r;
-}
-
-uint16_t * zparser_conv_certificate_type(const char *text)
-{
- /* convert a algoritm string to integer */
- const knot_lookup_table_t *type;
- uint16_t id;
-
- type = knot_lookup_by_name(dns_certificate_types, text);
- if (type) {
- id = htons((uint16_t) type->id);
- } else {
- char *end;
- id = htons((uint16_t) strtol(text, &end, 10));
- if (*end != '\0') {
- zc_error_prev_line("certificate type is expected");
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- return NULL;
- }
- }
-
- uint16_t *r = alloc_rdata_init(&id, sizeof(id));
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
-
- return r;
-}
-
-uint16_t * zparser_conv_a(const char *text)
-{
- in_addr_t address;
- uint16_t *r = NULL;
-
- if (inet_pton(AF_INET, text, &address) != 1) {
- zc_error_prev_line("invalid IPv4 address '%s'", text);
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- } else {
- r = alloc_rdata_init(&address, sizeof(address));
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
- }
-
- return r;
-}
-
-uint16_t * zparser_conv_aaaa(const char *text)
-{
- uint8_t address[IP6ADDRLEN];
- uint16_t *r = NULL;
-
- if (inet_pton(AF_INET6, text, address) != 1) {
- zc_error_prev_line("invalid IPv6 address '%s'", text);
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- } else {
- r = alloc_rdata_init(address, sizeof(address));
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
- }
- return r;
-}
-
-uint16_t * zparser_conv_text(const char *text, size_t len)
-{
- uint16_t *r = NULL;
-
- dbg_zp("Converting text: %s\n", text);
-
- if (len > 255) {
- zc_error_prev_line("text string is longer than 255 characters,"
- " try splitting it into multiple parts");
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- } else {
- uint8_t *p;
- r = alloc_rdata(len + 1);
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
- p = (uint8_t *)(r + 1);
- *p = len;
- memcpy(p + 1, text, len);
- }
- return r;
-}
-
-uint16_t * zparser_conv_dns_name(const uint8_t *name, size_t len)
-{
- uint16_t *r = NULL;
- uint8_t *p = NULL;
- r = alloc_rdata(len);
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
- p = (uint8_t *)(r + 1);
- memcpy(p, name, len);
-
- return r;
-}
-
-uint16_t * zparser_conv_b32(const char *b32)
-{
- uint8_t buffer[B64BUFSIZE];
- uint16_t *r = NULL;
- size_t i = B64BUFSIZE - 1;
-
- if (strcmp(b32, "-") == 0) {
- r = alloc_rdata_init("", 1);
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
- return r;
- }
-
- /*!< \todo BLEEDING EYES! */
-
- char b32_copy[strlen(b32) + 1];
-
- for (int i = 0; i < strlen(b32); i++) {
- b32_copy[i] = toupper(b32[i]);
- }
-
- /*!< \todo BLEEDING EYES! */
- b32_copy[strlen(b32)] = '\0';
-
- int32_t b32_ret = base32hex_decode((uint8_t *)b32_copy, strlen(b32_copy),
- buffer + 1, i);
-
- i = b32_ret;
-
- if (b32_ret <= 0) {
- zc_error_prev_line("invalid base32 data");
- parser->error_occurred = 1;
- } else {
- buffer[0] = i; /* store length byte */
- r = alloc_rdata_init(buffer, i + 1);
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
- }
- return r;
-}
-
-uint16_t * zparser_conv_b64(const char *b64)
-{
- uint8_t buffer[B64BUFSIZE];
- uint16_t *r = NULL;
- int i;
-
- i = b64_pton(b64, buffer, B64BUFSIZE);
- if (i == -1) {
- zc_error_prev_line("invalid base64 data\n");
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- } else {
- r = alloc_rdata_init(buffer, i);
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
- }
- return r;
-}
-
-uint16_t * zparser_conv_rrtype(const char *text)
-{
- uint16_t *r = NULL;
- uint16_t type = knot_rrtype_from_string(text);
-
- if (type == 0) {
- zc_error_prev_line("unrecognized RR type '%s'", text);
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- } else {
- type = htons(type);
- r = alloc_rdata_init(&type, sizeof(type));
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
- }
- return r;
-}
-
-uint16_t * zparser_conv_nxt(uint8_t nxtbits[])
-{
- /* nxtbits[] consists of 16 bytes with some zero's in it
- * copy every byte with zero to r and write the length in
- * the first byte
- */
- uint16_t i;
- uint16_t last = 0;
-
- for (i = 0; i < 16; i++) {
- if (nxtbits[i] != 0) {
- last = i + 1;
- }
- }
-
- uint16_t *r = alloc_rdata_init(nxtbits, last);
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
-
- return r;
-}
-
-
-/* we potentially have 256 windows, each one is numbered. empty ones
- * should be discarded
- */
-uint16_t * zparser_conv_nsec(uint8_t nsecbits[NSEC_WINDOW_COUNT]
- [NSEC_WINDOW_BITS_SIZE])
-{
- /* nsecbits contains up to 64K of bits which represent the
- * types available for a name. Walk the bits according to
- * nsec++ draft from jakob
- */
- uint16_t *r;
- uint8_t *ptr;
- size_t i, j;
- uint16_t window_count = 0;
- uint16_t total_size = 0;
- uint16_t window_max = 0;
-
- /* The used windows. */
- int used[NSEC_WINDOW_COUNT];
- /* The last byte used in each the window. */
- int size[NSEC_WINDOW_COUNT];
-
- window_max = 1 + (nsec_highest_rcode / 256);
-
- /* used[i] is the i-th window included in the nsec
- * size[used[0]] is the size of window 0
- */
-
- /* walk through the 256 windows */
- for (i = 0; i < window_max; ++i) {
- int empty_window = 1;
- /* check each of the 32 bytes */
- for (j = 0; j < NSEC_WINDOW_BITS_SIZE; ++j) {
- if (nsecbits[i][j] != 0) {
- size[i] = j + 1;
- empty_window = 0;
- }
- }
- if (!empty_window) {
- used[window_count] = i;
- window_count++;
- }
- }
-
- for (i = 0; i < window_count; ++i) {
- total_size += sizeof(uint16_t) + size[used[i]];
- }
-
- r = alloc_rdata(total_size);
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- return NULL;
- }
- ptr = (uint8_t *)(r + 1);
-
- /* now walk used and copy it */
- for (i = 0; i < window_count; ++i) {
- ptr[0] = used[i];
- ptr[1] = size[used[i]];
- memcpy(ptr + 2, &nsecbits[used[i]], size[used[i]]);
- ptr += size[used[i]] + 2;
- }
-
- return r;
-}
-
-/* Parse an int terminated in the specified range. */
-static int parse_int(const char *str,
- char **end,
- int *result,
- const char *name,
- int min,
- int max)
-{
- long value;
- value = strtol(str, end, 10);
- if (value < min || value > max) {
- zc_error_prev_line("%s must be within the range [%d .. %d]",
- name,
- min,
- max);
- return 0;
- } else {
- *result = (int) value;
- return 1;
- }
-}
-
-/* RFC1876 conversion routines */
-static uint32_t poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
- 1000000, 10000000, 100000000, 1000000000
- };
-
-/*
- * Converts ascii size/precision X * 10**Y(cm) to 0xXY.
- * Sets the given pointer to the last used character.
- *
- */
-static uint8_t precsize_aton(char *cp, char **endptr)
-{
- unsigned int mval = 0, cmval = 0;
- uint8_t retval = 0;
- int exponent;
- int mantissa;
-
- while (isdigit((int)*cp)) {
- mval = mval * 10 + hexdigit_to_int(*cp++);
- }
-
- if (*cp == '.') { /* centimeters */
- cp++;
- if (isdigit((int)*cp)) {
- cmval = hexdigit_to_int(*cp++) * 10;
- if (isdigit((int)*cp)) {
- cmval += hexdigit_to_int(*cp++);
- }
- }
- }
-
- if (mval >= poweroften[7]) {
- /* integer overflow possible for *100 */
- mantissa = mval / poweroften[7];
- exponent = 9; /* max */
- } else {
- cmval = (mval * 100) + cmval;
-
- for (exponent = 0; exponent < 9; exponent++)
- if (cmval < poweroften[exponent+1]) {
- break;
- }
-
- mantissa = cmval / poweroften[exponent];
- }
- if (mantissa > 9) {
- mantissa = 9;
- }
-
- retval = (mantissa << 4) | exponent;
-
- if (*cp == 'm') {
- cp++;
- }
-
- *endptr = cp;
-
- return (retval);
-}
-
-/*
- * Parses a specific part of rdata.
- *
- * Returns:
- *
- * number of elements parsed
- * zero on error
- *
- */
-uint16_t * zparser_conv_loc(char *str)
-{
- uint16_t *r;
- uint32_t *p;
- int i;
- int deg, min, secs; /* Secs is stored times 1000. */
- uint32_t lat = 0, lon = 0, alt = 0;
- /* encoded defaults: version=0 sz=1m hp=10000m vp=10m */
- uint8_t vszhpvp[4] = {0, 0x12, 0x16, 0x13};
- char *start;
- double d;
-
- for (;;) {
- deg = min = secs = 0;
-
- /* Degrees */
- if (*str == '\0') {
- zc_error_prev_line("unexpected end of LOC data");
- return NULL;
- }
-
- if (!parse_int(str, &str, &deg, "degrees", 0, 180)) {
- return NULL;
- }
- if (!isspace((int)*str)) {
- zc_error_prev_line("space expected after degrees");
- return NULL;
- }
- ++str;
-
- /* Minutes? */
- if (isdigit((int)*str)) {
- if (!parse_int(str, &str, &min, "minutes", 0, 60)) {
- return NULL;
- }
- if (!isspace((int)*str)) {
- zc_error_prev_line("space expected after minutes");
- return NULL;
- }
- ++str;
- }
-
- /* Seconds? */
- if (isdigit((int)*str)) {
- start = str;
- if (!parse_int(str, &str, &i, "seconds", 0, 60)) {
- return NULL;
- }
-
- if (*str == '.' && !parse_int(str + 1, &str, &i,
- "seconds fraction",
- 0, 999)) {
- return NULL;
- }
-
- if (!isspace((int)*str)) {
- zc_error_prev_line("space expected after seconds");
- return NULL;
- }
-
- d = strtod(start, &start);
- if (errno != 0) {
- zc_error_prev_line("error parsing seconds");
- }
-
- if (d < 0.0 || d > 60.0) {
- zc_error_prev_line(
- "seconds not in range 0.0 .. 60.0");
- }
-
- secs = (int)(d * 1000.0 + 0.5);
- ++str;
- }
-
- switch (*str) {
- case 'N':
- case 'n':
- lat = ((uint32_t)1 << 31) +
- (deg * 3600000 + min * 60000 + secs);
- break;
- case 'E':
- case 'e':
- lon = ((uint32_t)1 << 31) +
- (deg * 3600000 + min * 60000 + secs);
- break;
- case 'S':
- case 's':
- lat = ((uint32_t)1 << 31) -
- (deg * 3600000 + min * 60000 + secs);
- break;
- case 'W':
- case 'w':
- lon = ((uint32_t)1 << 31) -
- (deg * 3600000 + min * 60000 + secs);
- break;
- default:
- zc_error_prev_line(
- "invalid latitude/longtitude: '%c'", *str);
- return NULL;
- }
- ++str;
-
- if (lat != 0 && lon != 0) {
- break;
- }
-
- if (!isspace((int)*str)) {
- zc_error_prev_line("space expected after"
- " latitude/longitude");
- return NULL;
- }
- ++str;
- }
-
- /* Altitude */
- if (*str == '\0') {
- zc_error_prev_line("unexpected end of LOC data");
- return NULL;
- }
-
- if (!isspace((int)*str)) {
- zc_error_prev_line("space expected before altitude");
- return NULL;
- }
- ++str;
-
- start = str;
-
- /* Sign */
- if (*str == '+' || *str == '-') {
- ++str;
- }
-
- /* Meters of altitude... */
- int ret = strtol(str, &str, 10);
- UNUSED(ret); // Result checked in following switch
-
- switch (*str) {
- case ' ':
- case '\0':
- case 'm':
- break;
- case '.':
- if (!parse_int(str + 1, &str, &i, "altitude fraction", 0, 99)) {
- return NULL;
- }
- if (!isspace((int)*str) && *str != '\0' && *str != 'm') {
- zc_error_prev_line("altitude fraction must be a number");
- return NULL;
- }
- break;
- default:
- zc_error_prev_line("altitude must be expressed in meters");
- return NULL;
- }
- if (!isspace((int)*str) && *str != '\0') {
- ++str;
- }
-
- d = strtod(start, &start);
- if (errno != 0) {
- zc_error_prev_line("error parsing altitued");
- }
-
- alt = (uint32_t)(10000000.0 + d * 100 + 0.5);
-
- if (!isspace((int)*str) && *str != '\0') {
- zc_error_prev_line("unexpected character after altitude");
- return NULL;
- }
-
- /* Now parse size, horizontal precision and vertical precision if any */
- for (i = 1; isspace((int)*str) && i <= 3; i++) {
- vszhpvp[i] = precsize_aton(str + 1, &str);
-
- if (!isspace((int)*str) && *str != '\0') {
- zc_error_prev_line("invalid size or precision");
- return NULL;
- }
- }
-
- /* Allocate required space... */
- r = alloc_rdata(16);
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- return NULL;
- }
- p = (uint32_t *)(r + 1);
-
- memmove(p, vszhpvp, 4);
- write_uint32(p + 1, lat);
- write_uint32(p + 2, lon);
- write_uint32(p + 3, alt);
-
- return r;
-}
-
-/*
- * Convert an APL RR RDATA element.
- */
-uint16_t * zparser_conv_apl_rdata(char *str)
-{
- int negated = 0;
- uint16_t address_family;
- uint8_t prefix;
- uint8_t maximum_prefix;
- uint8_t length;
- uint8_t address[IP6ADDRLEN];
- char *colon = strchr(str, ':');
- char *slash = strchr(str, '/');
- int af;
- int rc;
- uint16_t rdlength;
- uint16_t *r;
- uint8_t *t;
- char *end;
- long p;
-
- if (!colon) {
- zc_error_prev_line("address family separator is missing");
- return NULL;
- }
- if (!slash) {
- zc_error_prev_line("prefix separator is missing");
- return NULL;
- }
-
- *colon = '\0';
- *slash = '\0';
-
- if (*str == '!') {
- negated = 1;
- ++str;
- }
-
- if (strcmp(str, "1") == 0) {
- address_family = htons(1);
- af = AF_INET;
- length = sizeof(in_addr_t);
- maximum_prefix = length * 8;
- } else if (strcmp(str, "2") == 0) {
- address_family = htons(2);
- af = AF_INET6;
- length = IP6ADDRLEN;
- maximum_prefix = length * 8;
- } else {
- zc_error_prev_line("invalid address family '%s'", str);
- return NULL;
- }
-
- rc = inet_pton(af, colon + 1, address);
- if (rc == 0) {
- zc_error_prev_line("invalid address '%s'", colon + 1);
- return NULL;
- } else if (rc == -1) {
- char ebuf[256] = {0};
- strerror_r(errno, ebuf, sizeof(ebuf));
- zc_error_prev_line("inet_pton failed: %s", ebuf);
- return NULL;
- }
-
- /* Strip trailing zero octets. */
- while (length > 0 && address[length - 1] == 0) {
- --length;
- }
-
-
- p = strtol(slash + 1, &end, 10);
- if (p < 0 || p > maximum_prefix) {
- zc_error_prev_line("prefix not in the range 0 .. %d",
- maximum_prefix);
- return NULL;
- } else if (*end != '\0') {
- zc_error_prev_line("invalid prefix '%s'", slash + 1);
- return NULL;
- }
- prefix = (uint8_t) p;
-
- rdlength = (sizeof(address_family) + sizeof(prefix) + sizeof(length)
- + length);
- r = alloc_rdata(rdlength);
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- return NULL;
- }
- t = (uint8_t *)(r + 1);
-
- memcpy(t, &address_family, sizeof(address_family));
- t += sizeof(address_family);
- memcpy(t, &prefix, sizeof(prefix));
- t += sizeof(prefix);
- memcpy(t, &length, sizeof(length));
- if (negated) {
- *t |= APL_NEGATION_MASK;
- }
- t += sizeof(length);
- memcpy(t, address, length);
-
- return r;
-}
-
-/*
- * Below some function that also convert but not to wireformat
- * but to "normal" (int,long,char) types
- */
-
-uint32_t zparser_ttl2int(const char *ttlstr, int *error)
-{
- /* convert a ttl value to a integer
- * return the ttl in a int
- * -1 on error
- */
-
- uint32_t ttl;
- const char *t;
-
- ttl = strtottl(ttlstr, &t);
- if (*t != 0) {
- zc_error_prev_line("invalid TTL value: %s", ttlstr);
- *error = 1;
- }
-
- return ttl;
-}
-
-void zadd_rdata_wireformat(uint16_t *data)
-{
- parser->temporary_items[parser->rdata_count].raw_data = data;
- parser->rdata_count++;
-}
-
-/**
- * Used for TXT RR's to grow with undefined number of strings.
- */
-void zadd_rdata_txt_wireformat(uint16_t *data, int first)
-{
- if (data == NULL) {
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- return;
- }
- dbg_zp("Adding text!\n");
- knot_rdata_item_t *rd;
-
- /* First STR in str_seq, allocate 65K in first unused rdata
- * else find last used rdata */
- if (first) {
- rd = &parser->temporary_items[parser->rdata_count];
- rd->raw_data = alloc_rdata(65535 * sizeof(uint8_t));
- if (rd->raw_data == NULL) {
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- }
- parser->rdata_count++;
- rd->raw_data[0] = 0;
- } else {
- rd = &parser->temporary_items[parser->rdata_count-1];
- }
-
- if (rd == NULL || rd->raw_data == NULL) {
- return;
- }
-
- if ((size_t)rd->raw_data[0] + (size_t)data[0] > 65535) {
- zc_error_prev_line("too large rdata element");
- return;
- }
-
- memcpy((uint8_t *)rd->raw_data + 2 + rd->raw_data[0],
- data + 1, data[0]);
- rd->raw_data[0] += data[0];
- free(data);
- dbg_zp("Item after add\n");
-// hex_print(rd->raw_data + 1, rd->raw_data[0]);
-}
-
-void zadd_rdata_domain(knot_dname_t *dname)
-{
- knot_dname_retain(dname);
-// printf("Adding rdata name: %s %p\n", dname->name, dname);
- parser->temporary_items[parser->rdata_count].dname = dname;
- parser->rdata_count++;
-}
-
-void parse_unknown_rdata(uint16_t type, uint16_t *wireformat)
-{
- dbg_rdata("parsing unknown rdata for type: %s (%d)\n",
- knot_rrtype_to_string(type), type);
- uint16_t size;
- ssize_t rdata_count;
- ssize_t i;
- knot_rdata_item_t *items = NULL;
-
- if (wireformat) {
- size = *wireformat;
- } else {
- return;
- }
-
- rdata_count = rdata_wireformat_to_rdata_atoms(wireformat + 1, type,
- size, &items);
- dbg_rdata("got %d items\n", rdata_count);
- if (rdata_count < 0) {
- dbg_rdata("wf to items returned error: %s (%d)\n",
- error_to_str(knot_zcompile_error_msgs, rdata_count),
- rdata_count);
- zc_error_prev_line("bad unknown RDATA\n");
- /*!< \todo leaks */
- return;
- }
-
- for (i = 0; i < rdata_count; ++i) {
- if (rdata_atom_is_domain(type, i)) {
- zadd_rdata_domain(items[i].dname);
- } else {
- //XXX won't this create size two times?
- zadd_rdata_wireformat((uint16_t *)items[i].raw_data);
- }
- }
- free(items);
- /* Free wireformat */
- free(wireformat);
-
- dbg_rdata("parse_unknown_rdata: Successfuly parsed unknown rdata.\n");
-}
-
-void set_bitnsec(uint8_t bits[NSEC_WINDOW_COUNT][NSEC_WINDOW_BITS_SIZE],
- uint16_t index)
-{
- /*
- * The bits are counted from left to right, so bit #0 is the
- * left most bit.
- */
- uint8_t window = index / 256;
- uint8_t bit = index % 256;
-
- bits[window][bit / 8] |= (1 << (7 - bit % 8));
-}
-
-/*! @} */