mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-22 10:10:06 +00:00
Formerly, the gen.h header contained a compatibility layer between Win32 and POSIX platforms. Since we have already dropped the Win32 build, we can merged gen.h into gen.c as the header file is not used elsewhere.
1063 lines
26 KiB
C
1063 lines
26 KiB
C
/*
|
|
* 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 */
|
|
|
|
#include <ctype.h>
|
|
#include <dirent.h>
|
|
#include <errno.h>
|
|
#include <limits.h>
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
|
|
#ifndef PATH_MAX
|
|
#define PATH_MAX 1024
|
|
#endif /* ifndef PATH_MAX */
|
|
|
|
#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, owner, 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]_%u"
|
|
#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;
|
|
|
|
typedef struct {
|
|
DIR *handle;
|
|
char *filename;
|
|
} isc_dir_t;
|
|
|
|
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(unsigned int, const char *, int, const char *, const char *);
|
|
static void
|
|
sd(unsigned int, const char *, const char *, char);
|
|
static void
|
|
insert_into_typenames(int, const char *, const char *);
|
|
|
|
static bool
|
|
start_directory(const char *path, isc_dir_t *dir) {
|
|
dir->handle = opendir(path);
|
|
|
|
if (dir->handle != NULL) {
|
|
return (true);
|
|
} else {
|
|
return (false);
|
|
}
|
|
}
|
|
|
|
static bool
|
|
next_file(isc_dir_t *dir) {
|
|
struct dirent *dirent;
|
|
|
|
dir->filename = NULL;
|
|
|
|
if (dir->handle != NULL) {
|
|
errno = 0;
|
|
dirent = readdir(dir->handle);
|
|
if (dirent != NULL) {
|
|
dir->filename = dirent->d_name;
|
|
} else {
|
|
if (errno != 0) {
|
|
fprintf(stderr,
|
|
"Error: reading directory: %s\n",
|
|
strerror(errno));
|
|
exit(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (dir->filename != NULL) {
|
|
return (true);
|
|
} else {
|
|
return (false);
|
|
}
|
|
}
|
|
|
|
static void
|
|
end_directory(isc_dir_t *dir) {
|
|
if (dir->handle != NULL) {
|
|
(void)closedir(dir->handle);
|
|
}
|
|
|
|
dir->handle = NULL;
|
|
}
|
|
|
|
/*%
|
|
* 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) {
|
|
printf("\n#define %s \\\n", name);
|
|
printf("\tswitch (%s) { \\\n" /*}*/, tsw);
|
|
first = 0;
|
|
}
|
|
if (tt->type != lasttype && subswitch) {
|
|
if (res == NULL) {
|
|
printf("\t\tdefault: break; \\\n");
|
|
} else {
|
|
printf("\t\tdefault: %s; break; \\\n", res);
|
|
}
|
|
printf("\t\t} \\\n");
|
|
printf("\t\tbreak; \\\n");
|
|
subswitch = 0;
|
|
}
|
|
if (tt->rdclass && tt->type != lasttype) {
|
|
printf("\tcase %d: switch (%s) { \\\n" /*}*/, tt->type,
|
|
csw);
|
|
subswitch = 1;
|
|
}
|
|
if (tt->rdclass == 0) {
|
|
printf("\tcase %d:%s %s_%s(%s); break;", tt->type,
|
|
result, function, funname(tt->typebuf, buf1),
|
|
args);
|
|
} else {
|
|
printf("\t\tcase %d:%s %s_%s_%s(%s); break;",
|
|
tt->rdclass, result, function,
|
|
funname(tt->classbuf, buf1),
|
|
funname(tt->typebuf, buf2), args);
|
|
}
|
|
printf(" \\\n");
|
|
lasttype = tt->type;
|
|
}
|
|
if (subswitch) {
|
|
if (res == NULL) {
|
|
printf("\t\tdefault: break; \\\n");
|
|
} else {
|
|
printf("\t\tdefault: %s; break; \\\n", res);
|
|
}
|
|
printf("\t\t} \\\n");
|
|
printf("\t\tbreak; \\\n");
|
|
}
|
|
if (first) {
|
|
if (res == NULL) {
|
|
printf("\n#define %s\n", name);
|
|
} else {
|
|
printf("\n#define %s %s;\n", name, res);
|
|
}
|
|
} else {
|
|
if (res == NULL) {
|
|
printf("\tdefault: break; \\\n");
|
|
} else {
|
|
printf("\tdefault: %s; break; \\\n", res);
|
|
}
|
|
printf("\t}\n");
|
|
}
|
|
}
|
|
|
|
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(unsigned 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(unsigned int rdclass, const char *classbuf, const char *dirbuf,
|
|
char filetype) {
|
|
char buf[TYPECLASSLEN + sizeof("_4294967295.h")];
|
|
char typebuf[TYPECLASSBUF];
|
|
unsigned int type;
|
|
int n;
|
|
isc_dir_t dir;
|
|
|
|
if (!start_directory(dirbuf, &dir)) {
|
|
return;
|
|
}
|
|
|
|
while (next_file(&dir)) {
|
|
if (sscanf(dir.filename, TYPECLASSFMT, typebuf, &type) != 2) {
|
|
continue;
|
|
}
|
|
|
|
/*
|
|
* sscanf accepts leading sign and zeros before type so
|
|
* compare the scanned items against the filename. Filter
|
|
* out mismatches. Also filter out bad file extensions.
|
|
*/
|
|
n = snprintf(buf, sizeof(buf), "%s_%u.%c", typebuf, type,
|
|
filetype);
|
|
INSIST(n > 0 && (unsigned)n < sizeof(buf));
|
|
if (strcmp(buf, dir.filename) != 0) {
|
|
continue;
|
|
}
|
|
if (type > 65535) {
|
|
fprintf(stderr, "Error: type value > 65535 (%s)\n",
|
|
dir.filename);
|
|
exit(1);
|
|
}
|
|
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];
|
|
unsigned 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 = getopt(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(optarg) >
|
|
PATH_MAX - 2 * TYPECLASSLEN -
|
|
sizeof("/rdata/_65535_65535"))
|
|
{
|
|
fprintf(stderr, "\"%s\" too long\n", optarg);
|
|
exit(1);
|
|
}
|
|
n = snprintf(srcdir, sizeof(srcdir), "%s/", optarg);
|
|
INSIST(n > 0 && (unsigned)n < sizeof(srcdir));
|
|
break;
|
|
case 'F':
|
|
file = optarg;
|
|
break;
|
|
case 'P':
|
|
prefix = optarg;
|
|
break;
|
|
case 'S':
|
|
suffix = optarg;
|
|
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;
|
|
}
|
|
|
|
/*
|
|
* sscanf accepts leading sign and zeros before type so
|
|
* compare the scanned items against the filename. Filter
|
|
* out mismatches.
|
|
*/
|
|
n = snprintf(buf, sizeof(buf), "%srdata/%s_%u", srcdir,
|
|
classbuf, rdclass);
|
|
INSIST(n > 0 && (unsigned)n < sizeof(buf));
|
|
if (strcmp(buf + 6 + strlen(srcdir), dir.filename) != 0) {
|
|
continue;
|
|
}
|
|
if (rdclass > 65535) {
|
|
fprintf(stderr, "Error: class value > 65535 (%s)\n",
|
|
dir.filename);
|
|
exit(1);
|
|
}
|
|
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) {
|
|
printf(copyright, year);
|
|
}
|
|
|
|
if (code) {
|
|
printf("#pragma once\n");
|
|
|
|
printf("#include <stdbool.h>\n");
|
|
printf("#include <isc/result.h>\n\n");
|
|
printf("#include <dns/name.h>\n\n");
|
|
|
|
for (tt = types; tt != NULL; tt = tt->next) {
|
|
printf("#include \"%s/%s_%d.c\"\n", tt->dirbuf,
|
|
tt->typebuf, tt->type);
|
|
}
|
|
|
|
printf("\n\n");
|
|
|
|
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.
|
|
*/
|
|
printf("#define RDATATYPE_COMPARE(_s, _d, _tn, _n, _tp) \\\n");
|
|
printf("\tdo { \\\n");
|
|
printf("\t\tif (sizeof(_s) - 1 == _n && \\\n"
|
|
"\t\t strncasecmp(_s,(_tn),"
|
|
"(sizeof(_s) - 1)) == 0) { \\\n");
|
|
printf("\t\t\tif ((dns_rdatatype_attributes(_d) & "
|
|
"DNS_RDATATYPEATTR_RESERVED) != 0) \\\n");
|
|
printf("\t\t\t\treturn (ISC_R_NOTIMPLEMENTED); \\\n");
|
|
printf("\t\t\t*(_tp) = _d; \\\n");
|
|
printf("\t\t\treturn (ISC_R_SUCCESS); \\\n");
|
|
printf("\t\t} \\\n");
|
|
printf("\t} while (0)\n\n");
|
|
|
|
printf("#define RDATATYPE_FROMTEXT_SW(_hash,"
|
|
"_typename,_length,_typep) \\\n");
|
|
printf("\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);
|
|
printf("\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)) {
|
|
printf("\t\t\tRDATATYPE_COMPARE"
|
|
"(\"%s\", %d, _typename, "
|
|
" _length, _typep); \\\n",
|
|
ttn2->typebuf, ttn2->type);
|
|
ttn2->sorted = 1;
|
|
}
|
|
}
|
|
printf("\t\t\tbreak; \\\n");
|
|
}
|
|
printf("\t}\n");
|
|
|
|
printf("#define RDATATYPE_ATTRIBUTE_SW \\\n");
|
|
printf("\tswitch (type) { \\\n");
|
|
for (i = 0; i <= maxtype; i++) {
|
|
ttn = find_typename(i);
|
|
if (ttn == NULL) {
|
|
continue;
|
|
}
|
|
printf("\tcase %d: return (%s); \\\n", i,
|
|
upper(ttn->attr));
|
|
}
|
|
printf("\t}\n");
|
|
|
|
printf("#define RDATATYPE_TOTEXT_SW \\\n");
|
|
printf("\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;
|
|
}
|
|
printf("\tcase %d: return "
|
|
"(str_totext(\"%s\", target)); \\\n",
|
|
i, upper(ttn->typebuf));
|
|
}
|
|
printf("\t}\n");
|
|
} else if (type_enum) {
|
|
char *s;
|
|
|
|
printf("#pragma once\n");
|
|
|
|
printf("enum {\n");
|
|
printf("\tdns_rdatatype_none = 0,\n");
|
|
|
|
lasttype = 0;
|
|
for (tt = types; tt != NULL; tt = tt->next) {
|
|
if (tt->type != lasttype) {
|
|
printf("\tdns_rdatatype_%s = %d,\n",
|
|
funname(tt->typebuf, buf1),
|
|
lasttype = tt->type);
|
|
}
|
|
}
|
|
|
|
printf("\tdns_rdatatype_ixfr = 251,\n");
|
|
printf("\tdns_rdatatype_axfr = 252,\n");
|
|
printf("\tdns_rdatatype_mailb = 253,\n");
|
|
printf("\tdns_rdatatype_maila = 254,\n");
|
|
printf("\tdns_rdatatype_any = 255\n");
|
|
|
|
printf("};\n\n");
|
|
|
|
printf("#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);
|
|
printf("#define dns_rdatatype_%s\t%s"
|
|
"((dns_rdatatype_t)dns_rdatatype_%s)\n",
|
|
s, strlen(s) < 2U ? "\t" : "", s);
|
|
lasttype = tt->type;
|
|
}
|
|
}
|
|
|
|
printf("#define dns_rdatatype_ixfr\t"
|
|
"((dns_rdatatype_t)dns_rdatatype_ixfr)\n");
|
|
printf("#define dns_rdatatype_axfr\t"
|
|
"((dns_rdatatype_t)dns_rdatatype_axfr)\n");
|
|
printf("#define dns_rdatatype_mailb\t"
|
|
"((dns_rdatatype_t)dns_rdatatype_mailb)\n");
|
|
printf("#define dns_rdatatype_maila\t"
|
|
"((dns_rdatatype_t)dns_rdatatype_maila)\n");
|
|
printf("#define dns_rdatatype_any\t"
|
|
"((dns_rdatatype_t)dns_rdatatype_any)\n");
|
|
} else if (class_enum) {
|
|
char *s;
|
|
int classnum;
|
|
|
|
printf("#pragma once\n");
|
|
|
|
printf("enum {\n");
|
|
|
|
printf("\tdns_rdataclass_reserved0 = 0,\n");
|
|
printf("#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; \
|
|
printf("\tdns_rdataclass_%s = %d%s\n", s, classnum, \
|
|
classnum != 255 ? "," : ""); \
|
|
printf("#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
|
|
|
|
printf("};\n\n");
|
|
} else if (structs) {
|
|
if (prefix != NULL) {
|
|
if ((fd = fopen(prefix, "r")) != NULL) {
|
|
while (fgets(buf, sizeof(buf), fd) != NULL) {
|
|
printf("%s", buf);
|
|
}
|
|
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) {
|
|
printf("%s", buf);
|
|
}
|
|
fclose(fd);
|
|
}
|
|
}
|
|
if (suffix != NULL) {
|
|
if ((fd = fopen(suffix, "r")) != NULL) {
|
|
while (fgets(buf, sizeof(buf), fd) != NULL) {
|
|
printf("%s", buf);
|
|
}
|
|
fclose(fd);
|
|
}
|
|
}
|
|
} else if (depend) {
|
|
for (tt = types; tt != NULL; tt = tt->next) {
|
|
printf("%s:\t%s/%s_%d.h\n", file, tt->dirbuf,
|
|
tt->typebuf, tt->type);
|
|
}
|
|
}
|
|
|
|
if (ferror(stdout) != 0) {
|
|
exit(1);
|
|
}
|
|
|
|
return (0);
|
|
}
|