diff options
Diffstat (limited to 'lib/dns/gen.c')
-rw-r--r-- | lib/dns/gen.c | 1028 |
1 files changed, 1028 insertions, 0 deletions
diff --git a/lib/dns/gen.c b/lib/dns/gen.c new file mode 100644 index 0000000..6d40858 --- /dev/null +++ b/lib/dns/gen.c @@ -0,0 +1,1028 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#ifdef WIN32 +/* + * Silence compiler warnings about using strcpy and friends. + */ +#define _CRT_SECURE_NO_DEPRECATE 1 +/* + * We use snprintf which was defined late in Windows even it is in C99. + */ +#if _MSC_VER < 1900 +#define snprintf _snprintf +#endif /* if _MSC_VER < 1900 */ +#endif /* ifdef WIN32 */ + +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <time.h> + +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif /* ifndef PATH_MAX */ + +#ifdef WIN32 +#include "gen-win32.h" +#else /* ifdef WIN32 */ +#include "gen-unix.h" +#endif /* ifdef WIN32 */ + +#ifndef ULLONG_MAX +#define ULLONG_MAX (~0ULL) +#endif /* ifndef ULLONG_MAX */ + +#define INSIST(cond) \ + if (!(cond)) { \ + fprintf(stderr, "%s:%d: INSIST(%s)\n", __FILE__, __LINE__, \ + #cond); \ + abort(); \ + } + +#define FROMTEXTARGS "rdclass, type, lexer, origin, options, target, callbacks" +#define FROMTEXTCLASS "rdclass" +#define FROMTEXTTYPE "type" +#define FROMTEXTDEF "result = DNS_R_UNKNOWN" + +#define TOTEXTARGS "rdata, tctx, target" +#define TOTEXTCLASS "rdata->rdclass" +#define TOTEXTTYPE "rdata->type" +#define TOTEXTDEF "use_default = true" + +#define FROMWIREARGS "rdclass, type, source, dctx, options, target" +#define FROMWIRECLASS "rdclass" +#define FROMWIRETYPE "type" +#define FROMWIREDEF "use_default = true" + +#define TOWIREARGS "rdata, cctx, target" +#define TOWIRECLASS "rdata->rdclass" +#define TOWIRETYPE "rdata->type" +#define TOWIREDEF "use_default = true" + +#define FROMSTRUCTARGS "rdclass, type, source, target" +#define FROMSTRUCTCLASS "rdclass" +#define FROMSTRUCTTYPE "type" +#define FROMSTRUCTDEF "use_default = true" + +#define TOSTRUCTARGS "rdata, target, mctx" +#define TOSTRUCTCLASS "rdata->rdclass" +#define TOSTRUCTTYPE "rdata->type" +#define TOSTRUCTDEF "use_default = true" + +#define FREESTRUCTARGS "source" +#define FREESTRUCTCLASS "common->rdclass" +#define FREESTRUCTTYPE "common->rdtype" +#define FREESTRUCTDEF NULL + +#define COMPAREARGS "rdata1, rdata2" +#define COMPARECLASS "rdata1->rdclass" +#define COMPARETYPE "rdata1->type" +#define COMPAREDEF "use_default = true" + +#define ADDITIONALDATAARGS "rdata, add, arg" +#define ADDITIONALDATACLASS "rdata->rdclass" +#define ADDITIONALDATATYPE "rdata->type" +#define ADDITIONALDATADEF "use_default = true" + +#define DIGESTARGS "rdata, digest, arg" +#define DIGESTCLASS "rdata->rdclass" +#define DIGESTTYPE "rdata->type" +#define DIGESTDEF "use_default = true" + +#define CHECKOWNERARGS "name, rdclass, type, wildcard" +#define CHECKOWNERCLASS "rdclass" +#define CHECKOWNERTYPE "type" +#define CHECKOWNERDEF "result = true" + +#define CHECKNAMESARGS "rdata, owner, bad" +#define CHECKNAMESCLASS "rdata->rdclass" +#define CHECKNAMESTYPE "rdata->type" +#define CHECKNAMESDEF "result = true" + +static const char copyright[] = "/*\n" + " * Copyright (C) 1998%s Internet Systems " + "Consortium, Inc. (\"ISC\")\n" + " *\n" + " * This Source Code Form is subject to the " + "terms of the Mozilla Public\n" + " * License, v. 2.0. If a copy of the MPL was " + "not distributed with this\n" + " * file, you can obtain one at " + "https://mozilla.org/MPL/2.0/.\n" + " */\n" + "\n" + "/***************\n" + " ***************\n" + " *************** THIS FILE IS AUTOMATICALLY " + "GENERATED BY gen.c.\n" + " *************** DO NOT EDIT!\n" + " ***************\n" + " ***************/\n" + "\n" + "/*! \\file */\n" + "\n"; + +#define STR_EXPAND(tok) #tok +#define STR(tok) STR_EXPAND(tok) + +#define TYPENAMES 256 +#define TYPECLASSLEN 20 /* DNS mnemonic size. Must be less than 100. */ +#define TYPECLASSBUF (TYPECLASSLEN + 1) +#define TYPECLASSFMT "%" STR(TYPECLASSLEN) "[-0-9a-z]_%d" +#define ATTRIBUTESIZE 256 + +static struct cc { + struct cc *next; + int rdclass; + char classbuf[TYPECLASSBUF]; +} *classes; + +static struct tt { + struct tt *next; + uint16_t rdclass; + uint16_t type; + char classbuf[TYPECLASSBUF]; + char typebuf[TYPECLASSBUF]; + char dirbuf[PATH_MAX - 30]; +} *types; + +static struct ttnam { + char typebuf[TYPECLASSBUF]; + char macroname[TYPECLASSBUF]; + char attr[ATTRIBUTESIZE]; + unsigned int sorted; + uint16_t type; +} typenames[TYPENAMES]; + +static int maxtype = -1; + +static char * +upper(char *); +static char * +funname(const char *, char *); +static void +doswitch(const char *, const char *, const char *, const char *, const char *, + const char *); +static void +add(int, const char *, int, const char *, const char *); +static void +sd(int, const char *, const char *, char); +static void +insert_into_typenames(int, const char *, const char *); + +/*% + * If you use more than 10 of these in, say, a printf(), you'll have problems. + */ +static char * +upper(char *s) { + static int buf_to_use = 0; + static char buf[10][256]; + char *b; + int c; + + buf_to_use++; + if (buf_to_use > 9) { + buf_to_use = 0; + } + + b = buf[buf_to_use]; + memset(b, 0, 256); + + while ((c = (*s++) & 0xff)) { + *b++ = islower(c) ? toupper(c) : c; + } + *b = '\0'; + return (buf[buf_to_use]); +} + +static char * +funname(const char *s, char *buf) { + char *b = buf; + char c; + + INSIST(strlen(s) < TYPECLASSBUF); + while ((c = *s++)) { + *b++ = (c == '-') ? '_' : c; + } + *b = '\0'; + return (buf); +} + +static void +doswitch(const char *name, const char *function, const char *args, + const char *tsw, const char *csw, const char *res) { + struct tt *tt; + int first = 1; + int lasttype = 0; + int subswitch = 0; + char buf1[TYPECLASSBUF], buf2[TYPECLASSBUF]; + const char *result = " result ="; + + if (res == NULL) { + result = ""; + } + + for (tt = types; tt != NULL; tt = tt->next) { + if (first) { + fprintf(stdout, "\n#define %s \\\n", name); + fprintf(stdout, "\tswitch (%s) { \\\n" /*}*/, tsw); + first = 0; + } + if (tt->type != lasttype && subswitch) { + if (res == NULL) { + fprintf(stdout, "\t\tdefault: break; \\\n"); + } else { + fprintf(stdout, "\t\tdefault: %s; break; \\\n", + res); + } + fputs(/*{*/ "\t\t} \\\n", stdout); + fputs("\t\tbreak; \\\n", stdout); + subswitch = 0; + } + if (tt->rdclass && tt->type != lasttype) { + fprintf(stdout, "\tcase %d: switch (%s) { \\\n" /*}*/, + tt->type, csw); + subswitch = 1; + } + if (tt->rdclass == 0) { + fprintf(stdout, "\tcase %d:%s %s_%s(%s); break;", + tt->type, result, function, + funname(tt->typebuf, buf1), args); + } else { + fprintf(stdout, "\t\tcase %d:%s %s_%s_%s(%s); break;", + tt->rdclass, result, function, + funname(tt->classbuf, buf1), + funname(tt->typebuf, buf2), args); + } + fputs(" \\\n", stdout); + lasttype = tt->type; + } + if (subswitch) { + if (res == NULL) { + fprintf(stdout, "\t\tdefault: break; \\\n"); + } else { + fprintf(stdout, "\t\tdefault: %s; break; \\\n", res); + } + fputs(/*{*/ "\t\t} \\\n", stdout); + fputs("\t\tbreak; \\\n", stdout); + } + if (first) { + if (res == NULL) { + fprintf(stdout, "\n#define %s\n", name); + } else { + fprintf(stdout, "\n#define %s %s;\n", name, res); + } + } else { + if (res == NULL) { + fprintf(stdout, "\tdefault: break; \\\n"); + } else { + fprintf(stdout, "\tdefault: %s; break; \\\n", res); + } + fputs(/*{*/ "\t}\n", stdout); + } +} + +static struct ttnam * +find_typename(int type) { + int i; + + for (i = 0; i < TYPENAMES; i++) { + if (typenames[i].typebuf[0] != 0 && typenames[i].type == type) { + return (&typenames[i]); + } + } + return (NULL); +} + +static void +insert_into_typenames(int type, const char *typebuf, const char *attr) { + struct ttnam *ttn = NULL; + size_t c; + int i, n; + char tmp[256]; + + INSIST(strlen(typebuf) < TYPECLASSBUF); + for (i = 0; i < TYPENAMES; i++) { + if (typenames[i].typebuf[0] != 0 && typenames[i].type == type && + strcmp(typebuf, typenames[i].typebuf) != 0) + { + fprintf(stderr, + "Error: type %d has two names: %s, %s\n", type, + typenames[i].typebuf, typebuf); + exit(1); + } + if (typenames[i].typebuf[0] == 0 && ttn == NULL) { + ttn = &typenames[i]; + } + } + if (ttn == NULL) { + fprintf(stderr, "Error: typenames array too small\n"); + exit(1); + } + + /* XXXMUKS: This is redundant due to the INSIST above. */ + if (strlen(typebuf) > sizeof(ttn->typebuf) - 1) { + fprintf(stderr, "Error: type name %s is too long\n", typebuf); + exit(1); + } + + strncpy(ttn->typebuf, typebuf, sizeof(ttn->typebuf)); + ttn->typebuf[sizeof(ttn->typebuf) - 1] = '\0'; + + strncpy(ttn->macroname, ttn->typebuf, sizeof(ttn->macroname)); + ttn->macroname[sizeof(ttn->macroname) - 1] = '\0'; + + ttn->type = type; + c = strlen(ttn->macroname); + while (c > 0) { + if (ttn->macroname[c - 1] == '-') { + ttn->macroname[c - 1] = '_'; + } + c--; + } + + if (attr == NULL) { + n = snprintf(tmp, sizeof(tmp), "RRTYPE_%s_ATTRIBUTES", + upper(ttn->macroname)); + INSIST(n > 0 && (unsigned)n < sizeof(tmp)); + attr = tmp; + } + + if (ttn->attr[0] != 0 && strcmp(attr, ttn->attr) != 0) { + fprintf(stderr, + "Error: type %d has different attributes: " + "%s, %s\n", + type, ttn->attr, attr); + exit(1); + } + + if (strlen(attr) > sizeof(ttn->attr) - 1) { + fprintf(stderr, "Error: attr (%s) [name %s] is too long\n", + attr, typebuf); + exit(1); + } + + strncpy(ttn->attr, attr, sizeof(ttn->attr)); + ttn->attr[sizeof(ttn->attr) - 1] = '\0'; + + ttn->sorted = 0; + if (maxtype < type) { + maxtype = type; + } +} + +static void +add(int rdclass, const char *classbuf, int type, const char *typebuf, + const char *dirbuf) { + struct tt *newtt = (struct tt *)malloc(sizeof(*newtt)); + struct tt *tt, *oldtt; + struct cc *newcc; + struct cc *cc, *oldcc; + + INSIST(strlen(typebuf) < TYPECLASSBUF); + INSIST(strlen(classbuf) < TYPECLASSBUF); + INSIST(strlen(dirbuf) < PATH_MAX); + + insert_into_typenames(type, typebuf, NULL); + + if (newtt == NULL) { + fprintf(stderr, "malloc() failed\n"); + exit(1); + } + + newtt->next = NULL; + newtt->rdclass = rdclass; + newtt->type = type; + + strncpy(newtt->classbuf, classbuf, sizeof(newtt->classbuf)); + newtt->classbuf[sizeof(newtt->classbuf) - 1] = '\0'; + + strncpy(newtt->typebuf, typebuf, sizeof(newtt->typebuf)); + newtt->typebuf[sizeof(newtt->typebuf) - 1] = '\0'; + + if (strncmp(dirbuf, "./", 2) == 0) { + dirbuf += 2; + } + strncpy(newtt->dirbuf, dirbuf, sizeof(newtt->dirbuf)); + newtt->dirbuf[sizeof(newtt->dirbuf) - 1] = '\0'; + + tt = types; + oldtt = NULL; + + while ((tt != NULL) && (tt->type < type)) { + oldtt = tt; + tt = tt->next; + } + + while ((tt != NULL) && (tt->type == type) && (tt->rdclass < rdclass)) { + if (strcmp(tt->typebuf, typebuf) != 0) { + exit(1); + } + oldtt = tt; + tt = tt->next; + } + + if ((tt != NULL) && (tt->type == type) && (tt->rdclass == rdclass)) { + exit(1); + } + + newtt->next = tt; + if (oldtt != NULL) { + oldtt->next = newtt; + } else { + types = newtt; + } + + /* + * Do a class switch for this type. + */ + if (rdclass == 0) { + return; + } + + newcc = (struct cc *)malloc(sizeof(*newcc)); + if (newcc == NULL) { + fprintf(stderr, "malloc() failed\n"); + exit(1); + } + newcc->rdclass = rdclass; + strncpy(newcc->classbuf, classbuf, sizeof(newcc->classbuf)); + newcc->classbuf[sizeof(newcc->classbuf) - 1] = '\0'; + cc = classes; + oldcc = NULL; + + while ((cc != NULL) && (cc->rdclass < rdclass)) { + oldcc = cc; + cc = cc->next; + } + + if ((cc != NULL) && cc->rdclass == rdclass) { + free((char *)newcc); + return; + } + + newcc->next = cc; + if (oldcc != NULL) { + oldcc->next = newcc; + } else { + classes = newcc; + } +} + +static void +sd(int rdclass, const char *classbuf, const char *dirbuf, char filetype) { + char buf[TYPECLASSLEN + sizeof("_65535.h")]; + char typebuf[TYPECLASSBUF]; + int type, n; + isc_dir_t dir; + + if (!start_directory(dirbuf, &dir)) { + return; + } + + while (next_file(&dir)) { + if (sscanf(dir.filename, TYPECLASSFMT, typebuf, &type) != 2) { + continue; + } + if ((type > 65535) || (type < 0)) { + continue; + } + + n = snprintf(buf, sizeof(buf), "%s_%d.%c", typebuf, type, + filetype); + INSIST(n > 0 && (unsigned)n < sizeof(buf)); + if (strcmp(buf, dir.filename) != 0) { + continue; + } + add(rdclass, classbuf, type, typebuf, dirbuf); + } + + end_directory(&dir); +} + +static unsigned int +HASH(char *string) { + size_t n; + unsigned char a, b; + + n = strlen(string); + if (n == 0) { + fprintf(stderr, "n == 0?\n"); + exit(1); + } + a = tolower((unsigned char)string[0]); + b = tolower((unsigned char)string[n - 1]); + + return (((a + n) * b) % 256); +} + +int +main(int argc, char **argv) { + char buf[PATH_MAX]; + char srcdir[PATH_MAX]; + int rdclass; + char classbuf[TYPECLASSBUF]; + struct tt *tt; + struct cc *cc; + struct ttnam *ttn, *ttn2; + unsigned int hash; + time_t now; + char year[11]; + int lasttype; + int code = 1; + int class_enum = 0; + int type_enum = 0; + int structs = 0; + int depend = 0; + int c, i, j, n; + char buf1[TYPECLASSBUF]; + char filetype = 'c'; + FILE *fd; + char *prefix = NULL; + char *suffix = NULL; + char *file = NULL; + char *source_date_epoch; + unsigned long long epoch; + char *endptr; + isc_dir_t dir; + + for (i = 0; i < TYPENAMES; i++) { + memset(&typenames[i], 0, sizeof(typenames[i])); + } + + srcdir[0] = '\0'; + while ((c = isc_commandline_parse(argc, argv, "cdits:F:P:S:")) != -1) { + switch (c) { + case 'c': + code = 0; + depend = 0; + type_enum = 0; + class_enum = 1; + filetype = 'c'; + structs = 0; + break; + case 'd': + code = 0; + depend = 1; + class_enum = 0; + type_enum = 0; + structs = 0; + filetype = 'h'; + break; + case 't': + code = 0; + depend = 0; + class_enum = 0; + type_enum = 1; + filetype = 'c'; + structs = 0; + break; + case 'i': + code = 0; + depend = 0; + class_enum = 0; + type_enum = 0; + structs = 1; + filetype = 'h'; + break; + case 's': + if (strlen(isc_commandline_argument) > + PATH_MAX - 2 * TYPECLASSLEN - + sizeof("/rdata/_65535_65535")) + { + fprintf(stderr, "\"%s\" too long\n", + isc_commandline_argument); + exit(1); + } + n = snprintf(srcdir, sizeof(srcdir), "%s/", + isc_commandline_argument); + INSIST(n > 0 && (unsigned)n < sizeof(srcdir)); + break; + case 'F': + file = isc_commandline_argument; + break; + case 'P': + prefix = isc_commandline_argument; + break; + case 'S': + suffix = isc_commandline_argument; + break; + case '?': + exit(1); + } + } + + n = snprintf(buf, sizeof(buf), "%srdata", srcdir); + INSIST(n > 0 && (unsigned)n < sizeof(srcdir)); + + if (!start_directory(buf, &dir)) { + exit(1); + } + + while (next_file(&dir)) { + if (sscanf(dir.filename, TYPECLASSFMT, classbuf, &rdclass) != 2) + { + continue; + } + if ((rdclass > 65535) || (rdclass < 0)) { + continue; + } + + n = snprintf(buf, sizeof(buf), "%srdata/%s_%d", srcdir, + classbuf, rdclass); + INSIST(n > 0 && (unsigned)n < sizeof(buf)); + if (strcmp(buf + 6 + strlen(srcdir), dir.filename) != 0) { + continue; + } + sd(rdclass, classbuf, buf, filetype); + } + end_directory(&dir); + n = snprintf(buf, sizeof(buf), "%srdata/generic", srcdir); + INSIST(n > 0 && (unsigned)n < sizeof(srcdir)); + sd(0, "", buf, filetype); + + source_date_epoch = getenv("SOURCE_DATE_EPOCH"); + if (source_date_epoch) { + errno = 0; + epoch = strtoull(source_date_epoch, &endptr, 10); + if ((errno == ERANGE && (epoch == ULLONG_MAX || epoch == 0)) || + (errno != 0 && epoch == 0)) + { + fprintf(stderr, + "Environment variable " + "$SOURCE_DATE_EPOCH: strtoull: %s\n", + strerror(errno)); + exit(EXIT_FAILURE); + } + if (endptr == source_date_epoch) { + fprintf(stderr, + "Environment variable " + "$SOURCE_DATE_EPOCH: " + "No digits were found: %s\n", + endptr); + exit(EXIT_FAILURE); + } + if (*endptr != '\0') { + fprintf(stderr, + "Environment variable " + "$SOURCE_DATE_EPOCH: Trailing garbage: %s\n", + endptr); + exit(EXIT_FAILURE); + } + if (epoch > ULONG_MAX) { + fprintf(stderr, + "Environment variable " + "$SOURCE_DATE_EPOCH: value must be " + "smaller than or equal to: %lu but " + "was found to be: %llu \n", + ULONG_MAX, epoch); + exit(EXIT_FAILURE); + } + now = epoch; + } else { + time(&now); + } + + if (now != -1) { + struct tm t, *tm = gmtime_r(&now, &t); + + if (tm != NULL && tm->tm_year > 104) { + n = snprintf(year, sizeof(year), "-%d", + tm->tm_year + 1900); + INSIST(n > 0 && (unsigned)n < sizeof(year)); + } else { + snprintf(year, sizeof(year), "-2016"); + } + } else { + snprintf(year, sizeof(year), "-2016"); + } + + if (!depend) { + fprintf(stdout, copyright, year); + } + + if (code) { + fputs("#ifndef DNS_CODE_H\n", stdout); + fputs("#define DNS_CODE_H 1\n\n", stdout); + + fputs("#include <stdbool.h>\n", stdout); + fputs("#include <isc/result.h>\n\n", stdout); + fputs("#include <dns/name.h>\n\n", stdout); + + for (tt = types; tt != NULL; tt = tt->next) { + fprintf(stdout, "#include \"%s/%s_%d.c\"\n", tt->dirbuf, + tt->typebuf, tt->type); + } + + fputs("\n\n", stdout); + + doswitch("FROMTEXTSWITCH", "fromtext", FROMTEXTARGS, + FROMTEXTTYPE, FROMTEXTCLASS, FROMTEXTDEF); + doswitch("TOTEXTSWITCH", "totext", TOTEXTARGS, TOTEXTTYPE, + TOTEXTCLASS, TOTEXTDEF); + doswitch("FROMWIRESWITCH", "fromwire", FROMWIREARGS, + FROMWIRETYPE, FROMWIRECLASS, FROMWIREDEF); + doswitch("TOWIRESWITCH", "towire", TOWIREARGS, TOWIRETYPE, + TOWIRECLASS, TOWIREDEF); + doswitch("COMPARESWITCH", "compare", COMPAREARGS, COMPARETYPE, + COMPARECLASS, COMPAREDEF); + doswitch("CASECOMPARESWITCH", "casecompare", COMPAREARGS, + COMPARETYPE, COMPARECLASS, COMPAREDEF); + doswitch("FROMSTRUCTSWITCH", "fromstruct", FROMSTRUCTARGS, + FROMSTRUCTTYPE, FROMSTRUCTCLASS, FROMSTRUCTDEF); + doswitch("TOSTRUCTSWITCH", "tostruct", TOSTRUCTARGS, + TOSTRUCTTYPE, TOSTRUCTCLASS, TOSTRUCTDEF); + doswitch("FREESTRUCTSWITCH", "freestruct", FREESTRUCTARGS, + FREESTRUCTTYPE, FREESTRUCTCLASS, FREESTRUCTDEF); + doswitch("ADDITIONALDATASWITCH", "additionaldata", + ADDITIONALDATAARGS, ADDITIONALDATATYPE, + ADDITIONALDATACLASS, ADDITIONALDATADEF); + doswitch("DIGESTSWITCH", "digest", DIGESTARGS, DIGESTTYPE, + DIGESTCLASS, DIGESTDEF); + doswitch("CHECKOWNERSWITCH", "checkowner", CHECKOWNERARGS, + CHECKOWNERTYPE, CHECKOWNERCLASS, CHECKOWNERDEF); + doswitch("CHECKNAMESSWITCH", "checknames", CHECKNAMESARGS, + CHECKNAMESTYPE, CHECKNAMESCLASS, CHECKNAMESDEF); + + /* + * From here down, we are processing the rdata names and + * attributes. + */ + +#define PRINT_COMMA(x) (x == maxtype ? "" : ",") + +#define METANOTQUESTION \ + "DNS_RDATATYPEATTR_META | " \ + "DNS_RDATATYPEATTR_NOTQUESTION" +#define METAQUESTIONONLY \ + "DNS_RDATATYPEATTR_META | " \ + "DNS_RDATATYPEATTR_QUESTIONONLY" +#define RESERVEDNAME "0" +#define RESERVED "DNS_RDATATYPEATTR_RESERVED" + + /* + * Add in reserved/special types. This will let us + * sort them without special cases. + */ + insert_into_typenames(100, "uinfo", RESERVEDNAME); + insert_into_typenames(101, "uid", RESERVEDNAME); + insert_into_typenames(102, "gid", RESERVEDNAME); + insert_into_typenames(103, "unspec", RESERVEDNAME); + insert_into_typenames(251, "ixfr", METAQUESTIONONLY); + insert_into_typenames(252, "axfr", METAQUESTIONONLY); + insert_into_typenames(253, "mailb", METAQUESTIONONLY); + insert_into_typenames(254, "maila", METAQUESTIONONLY); + insert_into_typenames(255, "any", METAQUESTIONONLY); + + /* + * Spit out a quick and dirty hash function. Here, + * we walk through the list of type names, and calculate + * a hash. This isn't perfect, but it will generate "pretty + * good" estimates. Lowercase the characters before + * computing in all cases. + * + * Here, walk the list from top to bottom, calculating + * the hash (mod 256) for each name. + */ + fprintf(stdout, "#define RDATATYPE_COMPARE(_s, _d, _tn, _n, " + "_tp) \\\n"); + fprintf(stdout, "\tdo { \\\n"); + fprintf(stdout, "\t\tif (sizeof(_s) - 1 == _n && \\\n" + "\t\t strncasecmp(_s,(_tn)," + "(sizeof(_s) - 1)) == 0) { \\\n"); + fprintf(stdout, "\t\t\tif ((dns_rdatatype_attributes(_d) & " + "DNS_RDATATYPEATTR_RESERVED) != 0) \\\n"); + fprintf(stdout, "\t\t\t\treturn (ISC_R_NOTIMPLEMENTED); \\\n"); + fprintf(stdout, "\t\t\t*(_tp) = _d; \\\n"); + fprintf(stdout, "\t\t\treturn (ISC_R_SUCCESS); \\\n"); + fprintf(stdout, "\t\t} \\\n"); + fprintf(stdout, "\t} while (0)\n\n"); + + fprintf(stdout, "#define RDATATYPE_FROMTEXT_SW(_hash," + "_typename,_length,_typep) \\\n"); + fprintf(stdout, "\tswitch (_hash) { \\\n"); + for (i = 0; i <= maxtype; i++) { + ttn = find_typename(i); + if (ttn == NULL) { + continue; + } + + /* + * Skip entries we already processed. + */ + if (ttn->sorted != 0) { + continue; + } + + hash = HASH(ttn->typebuf); + fprintf(stdout, "\t\tcase %u: \\\n", hash); + + /* + * Find all other entries that happen to match + * this hash. + */ + for (j = 0; j <= maxtype; j++) { + ttn2 = find_typename(j); + if (ttn2 == NULL) { + continue; + } + if (hash == HASH(ttn2->typebuf)) { + fprintf(stdout, + "\t\t\t" + "RDATATYPE_COMPARE" + "(\"%s\", %d, _typename, " + " _length, _typep); \\\n", + ttn2->typebuf, ttn2->type); + ttn2->sorted = 1; + } + } + fprintf(stdout, "\t\t\tbreak; \\\n"); + } + fprintf(stdout, "\t}\n"); + + fprintf(stdout, "#define RDATATYPE_ATTRIBUTE_SW \\\n"); + fprintf(stdout, "\tswitch (type) { \\\n"); + for (i = 0; i <= maxtype; i++) { + ttn = find_typename(i); + if (ttn == NULL) { + continue; + } + fprintf(stdout, "\tcase %d: return (%s); \\\n", i, + upper(ttn->attr)); + } + fprintf(stdout, "\t}\n"); + + fprintf(stdout, "#define RDATATYPE_TOTEXT_SW \\\n"); + fprintf(stdout, "\tswitch (type) { \\\n"); + for (i = 0; i <= maxtype; i++) { + ttn = find_typename(i); + if (ttn == NULL) { + continue; + } + /* + * Remove KEYDATA (65533) from the type to memonic + * translation as it is internal use only. This + * stops the tools from displaying KEYDATA instead + * of TYPE65533. + */ + if (i == 65533U) { + continue; + } + fprintf(stdout, + "\tcase %d: return " + "(str_totext(\"%s\", target)); \\\n", + i, upper(ttn->typebuf)); + } + fprintf(stdout, "\t}\n"); + + fputs("#endif /* DNS_CODE_H */\n", stdout); + } else if (type_enum) { + char *s; + + fprintf(stdout, "#ifndef DNS_ENUMTYPE_H\n"); + fprintf(stdout, "#define DNS_ENUMTYPE_H 1\n\n"); + + fprintf(stdout, "enum {\n"); + fprintf(stdout, "\tdns_rdatatype_none = 0,\n"); + + lasttype = 0; + for (tt = types; tt != NULL; tt = tt->next) { + if (tt->type != lasttype) { + fprintf(stdout, "\tdns_rdatatype_%s = %d,\n", + funname(tt->typebuf, buf1), + lasttype = tt->type); + } + } + + fprintf(stdout, "\tdns_rdatatype_ixfr = 251,\n"); + fprintf(stdout, "\tdns_rdatatype_axfr = 252,\n"); + fprintf(stdout, "\tdns_rdatatype_mailb = 253,\n"); + fprintf(stdout, "\tdns_rdatatype_maila = 254,\n"); + fprintf(stdout, "\tdns_rdatatype_any = 255\n"); + + fprintf(stdout, "};\n\n"); + + fprintf(stdout, "#define dns_rdatatype_none\t" + "((dns_rdatatype_t)dns_rdatatype_none)\n"); + + for (tt = types; tt != NULL; tt = tt->next) { + if (tt->type != lasttype) { + s = funname(tt->typebuf, buf1); + fprintf(stdout, + "#define dns_rdatatype_%s\t%s" + "((dns_rdatatype_t)dns_rdatatype_%s)" + "\n", + s, strlen(s) < 2U ? "\t" : "", s); + lasttype = tt->type; + } + } + + fprintf(stdout, "#define dns_rdatatype_ixfr\t" + "((dns_rdatatype_t)dns_rdatatype_ixfr)\n"); + fprintf(stdout, "#define dns_rdatatype_axfr\t" + "((dns_rdatatype_t)dns_rdatatype_axfr)\n"); + fprintf(stdout, "#define dns_rdatatype_mailb\t" + "((dns_rdatatype_t)dns_rdatatype_mailb)\n"); + fprintf(stdout, "#define dns_rdatatype_maila\t" + "((dns_rdatatype_t)dns_rdatatype_maila)\n"); + fprintf(stdout, "#define dns_rdatatype_any\t" + "((dns_rdatatype_t)dns_rdatatype_any)\n"); + + fprintf(stdout, "\n#endif /* DNS_ENUMTYPE_H */\n"); + } else if (class_enum) { + char *s; + int classnum; + + fprintf(stdout, "#ifndef DNS_ENUMCLASS_H\n"); + fprintf(stdout, "#define DNS_ENUMCLASS_H 1\n\n"); + + fprintf(stdout, "enum {\n"); + + fprintf(stdout, "\tdns_rdataclass_reserved0 = 0,\n"); + fprintf(stdout, "#define dns_rdataclass_reserved0 \\\n\t\t\t\t" + "((dns_rdataclass_t)dns_rdataclass_reserved0)" + "\n"); + +#define PRINTCLASS(name, num) \ + do { \ + s = funname(name, buf1); \ + classnum = num; \ + fprintf(stdout, "\tdns_rdataclass_%s = %d%s\n", s, classnum, \ + classnum != 255 ? "," : ""); \ + fprintf(stdout, \ + "#define dns_rdataclass_%s\t" \ + "((dns_rdataclass_t)dns_rdataclass_%s)\n", \ + s, s); \ + } while (0) + + for (cc = classes; cc != NULL; cc = cc->next) { + if (cc->rdclass == 3) { + PRINTCLASS("chaos", 3); + } else if (cc->rdclass == 255) { + PRINTCLASS("none", 254); + } + PRINTCLASS(cc->classbuf, cc->rdclass); + } + +#undef PRINTCLASS + + fprintf(stdout, "};\n\n"); + fprintf(stdout, "#endif /* DNS_ENUMCLASS_H */\n"); + } else if (structs) { + if (prefix != NULL) { + if ((fd = fopen(prefix, "r")) != NULL) { + while (fgets(buf, sizeof(buf), fd) != NULL) { + fputs(buf, stdout); + } + fclose(fd); + } + } + for (tt = types; tt != NULL; tt = tt->next) { + snprintf(buf, sizeof(buf), "%s/%s_%d.h", tt->dirbuf, + tt->typebuf, tt->type); + if ((fd = fopen(buf, "r")) != NULL) { + while (fgets(buf, sizeof(buf), fd) != NULL) { + fputs(buf, stdout); + } + fclose(fd); + } + } + if (suffix != NULL) { + if ((fd = fopen(suffix, "r")) != NULL) { + while (fgets(buf, sizeof(buf), fd) != NULL) { + fputs(buf, stdout); + } + fclose(fd); + } + } + } else if (depend) { + for (tt = types; tt != NULL; tt = tt->next) { + fprintf(stdout, "%s:\t%s/%s_%d.h\n", file, tt->dirbuf, + tt->typebuf, tt->type); + } + } + + if (ferror(stdout) != 0) { + exit(1); + } + + return (0); +} |