]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - contrib/bind9/lib/dns/gen.c
Fix BIND resolver remote denial of service when validating.
[FreeBSD/stable/8.git] / contrib / bind9 / lib / dns / gen.c
1 /*
2  * Copyright (C) 2004-2009, 2012, 2013  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1998-2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 /*! \file */
19
20 #ifdef WIN32
21 /*
22  * Silence compiler warnings about using strcpy and friends.
23  */
24 #define _CRT_SECURE_NO_DEPRECATE 1
25 /*
26  * We use snprintf.
27  */
28 #define snprintf _snprintf
29 #endif
30
31 #include <sys/types.h>
32
33 #include <ctype.h>
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <time.h>
39
40 #ifdef WIN32
41 #include "gen-win32.h"
42 #else
43 #include "gen-unix.h"
44 #endif
45
46 #define INSIST(cond) \
47         if (!(cond)) { \
48                 fprintf(stderr, "%s:%d: INSIST(%s)\n", \
49                          __FILE__, __LINE__, #cond); \
50                 abort(); \
51         }
52
53 #define FROMTEXTARGS "rdclass, type, lexer, origin, options, target, callbacks"
54 #define FROMTEXTCLASS "rdclass"
55 #define FROMTEXTTYPE "type"
56 #define FROMTEXTDEF "result = DNS_R_UNKNOWN"
57
58 #define TOTEXTARGS "rdata, tctx, target"
59 #define TOTEXTCLASS "rdata->rdclass"
60 #define TOTEXTTYPE "rdata->type"
61 #define TOTEXTDEF "use_default = ISC_TRUE"
62
63 #define FROMWIREARGS "rdclass, type, source, dctx, options, target"
64 #define FROMWIRECLASS "rdclass"
65 #define FROMWIRETYPE "type"
66 #define FROMWIREDEF "use_default = ISC_TRUE"
67
68 #define TOWIREARGS "rdata, cctx, target"
69 #define TOWIRECLASS "rdata->rdclass"
70 #define TOWIRETYPE "rdata->type"
71 #define TOWIREDEF "use_default = ISC_TRUE"
72
73 #define FROMSTRUCTARGS "rdclass, type, source, target"
74 #define FROMSTRUCTCLASS "rdclass"
75 #define FROMSTRUCTTYPE "type"
76 #define FROMSTRUCTDEF "use_default = ISC_TRUE"
77
78 #define TOSTRUCTARGS "rdata, target, mctx"
79 #define TOSTRUCTCLASS "rdata->rdclass"
80 #define TOSTRUCTTYPE "rdata->type"
81 #define TOSTRUCTDEF "use_default = ISC_TRUE"
82
83 #define FREESTRUCTARGS "source"
84 #define FREESTRUCTCLASS "common->rdclass"
85 #define FREESTRUCTTYPE "common->rdtype"
86 #define FREESTRUCTDEF NULL
87
88 #define COMPAREARGS "rdata1, rdata2"
89 #define COMPARECLASS "rdata1->rdclass"
90 #define COMPARETYPE "rdata1->type"
91 #define COMPAREDEF "use_default = ISC_TRUE"
92
93 #define ADDITIONALDATAARGS "rdata, add, arg"
94 #define ADDITIONALDATACLASS "rdata->rdclass"
95 #define ADDITIONALDATATYPE "rdata->type"
96 #define ADDITIONALDATADEF "use_default = ISC_TRUE"
97
98 #define DIGESTARGS "rdata, digest, arg"
99 #define DIGESTCLASS "rdata->rdclass"
100 #define DIGESTTYPE "rdata->type"
101 #define DIGESTDEF "use_default = ISC_TRUE"
102
103 #define CHECKOWNERARGS "name, rdclass, type, wildcard"
104 #define CHECKOWNERCLASS "rdclass"
105 #define CHECKOWNERTYPE "type"
106 #define CHECKOWNERDEF "result = ISC_TRUE"
107
108 #define CHECKNAMESARGS "rdata, owner, bad"
109 #define CHECKNAMESCLASS "rdata->rdclass"
110 #define CHECKNAMESTYPE "rdata->type"
111 #define CHECKNAMESDEF "result = ISC_TRUE"
112
113 static const char copyright[] =
114 "/*\n"
115 " * Copyright (C) 2004%s Internet Systems Consortium, Inc. (\"ISC\")\n"
116 " * Copyright (C) 1998-2003 Internet Software Consortium.\n"
117 " *\n"
118 " * Permission to use, copy, modify, and distribute this software for any\n"
119 " * purpose with or without fee is hereby granted, provided that the above\n"
120 " * copyright notice and this permission notice appear in all copies.\n"
121 " *\n"
122 " * THE SOFTWARE IS PROVIDED \"AS IS\" AND ISC DISCLAIMS ALL WARRANTIES WITH\n"
123 " * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\n"
124 " * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,\n"
125 " * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\n"
126 " * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE\n"
127 " * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\n"
128 " * PERFORMANCE OF THIS SOFTWARE.\n"
129 " */\n"
130 "\n"
131 "/***************\n"
132 " ***************\n"
133 " ***************   THIS FILE IS AUTOMATICALLY GENERATED BY gen.c.\n"
134 " ***************   DO NOT EDIT!\n"
135 " ***************\n"
136 " ***************/\n"
137 "\n"
138 "/*! \\file */\n"
139 "\n";
140
141 #define STR_EXPAND(tok) #tok
142 #define STR(tok) STR_EXPAND(tok)
143
144 #define TYPENAMES 256
145 #define TYPECLASSLEN 20         /* DNS mnemonic size. Must be less than 100. */
146 #define TYPECLASSBUF (TYPECLASSLEN + 1)
147 #define TYPECLASSFMT "%" STR(TYPECLASSLEN) "[-0-9a-z]_%d"
148 #define ATTRIBUTESIZE 256
149 #define DIRNAMESIZE 256
150
151 static struct cc {
152         struct cc *next;
153         int rdclass;
154         char classname[TYPECLASSBUF];
155 } *classes;
156
157 static struct tt {
158         struct tt *next;
159         int rdclass;
160         int type;
161         char classname[TYPECLASSBUF];
162         char typename[TYPECLASSBUF];
163         char dirname[DIRNAMESIZE];      /* XXX Should be max path length */
164 } *types;
165
166 static struct ttnam {
167         char typename[TYPECLASSBUF];
168         char macroname[TYPECLASSBUF];
169         char attr[ATTRIBUTESIZE];
170         unsigned int sorted;
171         int type;
172 } typenames[TYPENAMES];
173
174 static int maxtype = -1;
175
176 static char *
177 upper(char *);
178 static char *
179 funname(const char *, char *);
180 static void
181 doswitch(const char *, const char *, const char *, const char *,
182          const char *, const char *);
183 static void
184 add(int, const char *, int, const char *, const char *);
185 static void
186 sd(int, const char *, const char *, char);
187 static void
188 insert_into_typenames(int, const char *, const char *);
189
190 /*%
191  * If you use more than 10 of these in, say, a printf(), you'll have problems.
192  */
193 static char *
194 upper(char *s) {
195         static int buf_to_use = 0;
196         static char buf[10][256];
197         char *b;
198         int c;
199
200         buf_to_use++;
201         if (buf_to_use > 9)
202                 buf_to_use = 0;
203
204         b = buf[buf_to_use];
205         memset(b, 0, 256);
206
207         while ((c = (*s++) & 0xff))
208                 *b++ = islower(c) ? toupper(c) : c;
209         *b = '\0';
210         return (buf[buf_to_use]);
211 }
212
213 static char *
214 funname(const char *s, char *buf) {
215         char *b = buf;
216         char c;
217
218         INSIST(strlen(s) < TYPECLASSBUF);
219         while ((c = *s++)) {
220                 *b++ = (c == '-') ? '_' : c;
221         }
222         *b = '\0';
223         return (buf);
224 }
225
226 static void
227 doswitch(const char *name, const char *function, const char *args,
228          const char *tsw, const char *csw, const char *res)
229 {
230         struct tt *tt;
231         int first = 1;
232         int lasttype = 0;
233         int subswitch = 0;
234         char buf1[TYPECLASSBUF], buf2[TYPECLASSBUF];
235         const char *result = " result =";
236
237         if (res == NULL)
238                 result = "";
239
240         for (tt = types; tt != NULL; tt = tt->next) {
241                 if (first) {
242                         fprintf(stdout, "\n#define %s \\\n", name);
243                         fprintf(stdout, "\tswitch (%s) { \\\n" /*}*/, tsw);
244                         first = 0;
245                 }
246                 if (tt->type != lasttype && subswitch) {
247                         if (res == NULL)
248                                 fprintf(stdout, "\t\tdefault: break; \\\n");
249                         else
250                                 fprintf(stdout,
251                                         "\t\tdefault: %s; break; \\\n", res);
252                         fputs(/*{*/ "\t\t} \\\n", stdout);
253                         fputs("\t\tbreak; \\\n", stdout);
254                         subswitch = 0;
255                 }
256                 if (tt->rdclass && tt->type != lasttype) {
257                         fprintf(stdout, "\tcase %d: switch (%s) { \\\n" /*}*/,
258                                 tt->type, csw);
259                         subswitch = 1;
260                 }
261                 if (tt->rdclass == 0)
262                         fprintf(stdout,
263                                 "\tcase %d:%s %s_%s(%s); break;",
264                                 tt->type, result, function,
265                                 funname(tt->typename, buf1), args);
266                 else
267                         fprintf(stdout,
268                                 "\t\tcase %d:%s %s_%s_%s(%s); break;",
269                                 tt->rdclass, result, function,
270                                 funname(tt->classname, buf1),
271                                 funname(tt->typename, buf2), args);
272                 fputs(" \\\n", stdout);
273                 lasttype = tt->type;
274         }
275         if (subswitch) {
276                 if (res == NULL)
277                         fprintf(stdout, "\t\tdefault: break; \\\n");
278                 else
279                         fprintf(stdout, "\t\tdefault: %s; break; \\\n", res);
280                 fputs(/*{*/ "\t\t} \\\n", stdout);
281                 fputs("\t\tbreak; \\\n", stdout);
282         }
283         if (first) {
284                 if (res == NULL)
285                         fprintf(stdout, "\n#define %s\n", name);
286                 else
287                         fprintf(stdout, "\n#define %s %s;\n", name, res);
288         } else {
289                 if (res == NULL)
290                         fprintf(stdout, "\tdefault: break; \\\n");
291                 else
292                         fprintf(stdout, "\tdefault: %s; break; \\\n", res);
293                 fputs(/*{*/ "\t}\n", stdout);
294         }
295 }
296
297 static struct ttnam *
298 find_typename(int type) {
299         int i;
300
301         for (i = 0; i < TYPENAMES; i++) {
302                 if (typenames[i].typename[0] != 0 &&
303                     typenames[i].type == type)
304                         return (&typenames[i]);
305         }
306         return (NULL);
307 }
308
309 static void
310 insert_into_typenames(int type, const char *typename, const char *attr) {
311         struct ttnam *ttn = NULL;
312         size_t c;
313         int i, n;
314         char tmp[256];
315
316         INSIST(strlen(typename) < TYPECLASSBUF);
317         for (i = 0; i < TYPENAMES; i++) {
318                 if (typenames[i].typename[0] != 0 &&
319                     typenames[i].type == type &&
320                     strcmp(typename, typenames[i].typename) != 0) {
321                         fprintf(stderr,
322                                 "Error:  type %d has two names: %s, %s\n",
323                                 type, typenames[i].typename, typename);
324                         exit(1);
325                 }
326                 if (typenames[i].typename[0] == 0 && ttn == NULL)
327                         ttn = &typenames[i];
328         }
329         if (ttn == NULL) {
330                 fprintf(stderr, "Error: typenames array too small\n");
331                 exit(1);
332         }
333
334         if (strlen(typename) > sizeof(ttn->typename) - 1) {
335                 fprintf(stderr, "Error:  type name %s is too long\n",
336                         typename);
337                 exit(1);
338         }
339         strncpy(ttn->typename, typename, sizeof(ttn->typename));
340         ttn->type = type;
341
342         strncpy(ttn->macroname, ttn->typename, sizeof(ttn->macroname));
343         c = strlen(ttn->macroname);
344         while (c > 0) {
345                 if (ttn->macroname[c - 1] == '-')
346                         ttn->macroname[c - 1] = '_';
347                 c--;
348         }
349
350         if (attr == NULL) {
351                 n = snprintf(tmp, sizeof(tmp),
352                              "RRTYPE_%s_ATTRIBUTES", upper(ttn->macroname));
353                 INSIST(n > 0 && (unsigned)n < sizeof(tmp));
354                 attr = tmp;
355         }
356
357         if (ttn->attr[0] != 0 && strcmp(attr, ttn->attr) != 0) {
358                 fprintf(stderr, "Error:  type %d has different attributes: "
359                         "%s, %s\n", type, ttn->attr, attr);
360                 exit(1);
361         }
362
363         if (strlen(attr) > sizeof(ttn->attr) - 1) {
364                 fprintf(stderr, "Error:  attr (%s) [name %s] is too long\n",
365                         attr, typename);
366                 exit(1);
367         }
368         strncpy(ttn->attr, attr, sizeof(ttn->attr));
369         ttn->sorted = 0;
370         if (maxtype < type)
371                 maxtype = type;
372 }
373
374 static void
375 add(int rdclass, const char *classname, int type, const char *typename,
376     const char *dirname)
377 {
378         struct tt *newtt = (struct tt *)malloc(sizeof(*newtt));
379         struct tt *tt, *oldtt;
380         struct cc *newcc;
381         struct cc *cc, *oldcc;
382
383         INSIST(strlen(typename) < TYPECLASSBUF);
384         INSIST(strlen(classname) < TYPECLASSBUF);
385         INSIST(strlen(dirname) < DIRNAMESIZE);
386
387         insert_into_typenames(type, typename, NULL);
388
389         if (newtt == NULL) {
390                 fprintf(stderr, "malloc() failed\n");
391                 exit(1);
392         }
393
394         newtt->next = NULL;
395         newtt->rdclass = rdclass;
396         newtt->type = type;
397         strncpy(newtt->classname, classname, sizeof(newtt->classname));
398         strncpy(newtt->typename, typename, sizeof(newtt->typename));
399         if (strncmp(dirname, "./", 2) == 0)
400                 dirname += 2;
401         strncpy(newtt->dirname, dirname, sizeof(newtt->dirname));
402
403         tt = types;
404         oldtt = NULL;
405
406         while ((tt != NULL) && (tt->type < type)) {
407                 oldtt = tt;
408                 tt = tt->next;
409         }
410
411         while ((tt != NULL) && (tt->type == type) && (tt->rdclass < rdclass)) {
412                 if (strcmp(tt->typename, typename) != 0)
413                         exit(1);
414                 oldtt = tt;
415                 tt = tt->next;
416         }
417
418         if ((tt != NULL) && (tt->type == type) && (tt->rdclass == rdclass))
419                 exit(1);
420
421         newtt->next = tt;
422         if (oldtt != NULL)
423                 oldtt->next = newtt;
424         else
425                 types = newtt;
426
427         /*
428          * Do a class switch for this type.
429          */
430         if (rdclass == 0)
431                 return;
432
433         newcc = (struct cc *)malloc(sizeof(*newcc));
434         if (newcc == NULL) {
435                 fprintf(stderr, "malloc() failed\n");
436                 exit(1);
437         }
438         newcc->rdclass = rdclass;
439         strncpy(newcc->classname, classname, sizeof(newcc->classname));
440         cc = classes;
441         oldcc = NULL;
442
443         while ((cc != NULL) && (cc->rdclass < rdclass)) {
444                 oldcc = cc;
445                 cc = cc->next;
446         }
447
448         if ((cc != NULL) && cc->rdclass == rdclass) {
449                 free((char *)newcc);
450                 return;
451         }
452
453         newcc->next = cc;
454         if (oldcc != NULL)
455                 oldcc->next = newcc;
456         else
457                 classes = newcc;
458 }
459
460 static void
461 sd(int rdclass, const char *classname, const char *dirname, char filetype) {
462         char buf[TYPECLASSLEN + sizeof("_65535.h")];
463         char typename[TYPECLASSBUF];
464         int type, n;
465         isc_dir_t dir;
466
467         if (!start_directory(dirname, &dir))
468                 return;
469
470         while (next_file(&dir)) {
471                 if (sscanf(dir.filename, TYPECLASSFMT, typename, &type) != 2)
472                         continue;
473                 if ((type > 65535) || (type < 0))
474                         continue;
475
476                 n = snprintf(buf, sizeof(buf), "%s_%d.%c", typename,
477                              type, filetype);
478                 INSIST(n > 0 && (unsigned)n < sizeof(buf));
479                 if (strcmp(buf, dir.filename) != 0)
480                         continue;
481                 add(rdclass, classname, type, typename, dirname);
482         }
483
484         end_directory(&dir);
485 }
486
487 static unsigned int
488 HASH(char *string) {
489         size_t n;
490         unsigned char a, b;
491
492         n = strlen(string);
493         if (n == 0) {
494                 fprintf(stderr, "n == 0?\n");
495                 exit(1);
496         }
497         a = tolower((unsigned char)string[0]);
498         b = tolower((unsigned char)string[n - 1]);
499
500         return ((a + n) * b) % 256;
501 }
502
503 int
504 main(int argc, char **argv) {
505         char buf[DIRNAMESIZE];          /* XXX Should be max path length */
506         char srcdir[DIRNAMESIZE];       /* XXX Should be max path length */
507         int rdclass;
508         char classname[TYPECLASSBUF];
509         struct tt *tt;
510         struct cc *cc;
511         struct ttnam *ttn, *ttn2;
512         unsigned int hash;
513         struct tm *tm;
514         time_t now;
515         char year[11];
516         int lasttype;
517         int code = 1;
518         int class_enum = 0;
519         int type_enum = 0;
520         int structs = 0;
521         int depend = 0;
522         int c, i, j, n;
523         char buf1[TYPECLASSBUF];
524         char filetype = 'c';
525         FILE *fd;
526         char *prefix = NULL;
527         char *suffix = NULL;
528         char *file = NULL;
529         isc_dir_t dir;
530
531         for (i = 0; i < TYPENAMES; i++)
532                 memset(&typenames[i], 0, sizeof(typenames[i]));
533
534         strcpy(srcdir, "");
535         while ((c = isc_commandline_parse(argc, argv, "cdits:F:P:S:")) != -1)
536                 switch (c) {
537                 case 'c':
538                         code = 0;
539                         depend = 0;
540                         type_enum = 0;
541                         class_enum = 1;
542                         filetype = 'c';
543                         structs = 0;
544                         break;
545                 case 'd':
546                         code = 0;
547                         depend = 1;
548                         class_enum = 0;
549                         type_enum = 0;
550                         structs = 0;
551                         filetype = 'h';
552                         break;
553                 case 't':
554                         code = 0;
555                         depend = 0;
556                         class_enum = 0;
557                         type_enum = 1;
558                         filetype = 'c';
559                         structs = 0;
560                         break;
561                 case 'i':
562                         code = 0;
563                         depend = 0;
564                         class_enum = 0;
565                         type_enum = 0;
566                         structs = 1;
567                         filetype = 'h';
568                         break;
569                 case 's':
570                         if (strlen(isc_commandline_argument) >
571                             DIRNAMESIZE - 2 * TYPECLASSLEN  -
572                             sizeof("/rdata/_65535_65535")) {
573                                 fprintf(stderr, "\"%s\" too long\n",
574                                         isc_commandline_argument);
575                                 exit(1);
576                         }
577                         n = snprintf(srcdir, sizeof(srcdir), "%s/",
578                                      isc_commandline_argument);
579                         INSIST(n > 0 && (unsigned)n < sizeof(srcdir));
580                         break;
581                 case 'F':
582                         file = isc_commandline_argument;
583                         break;
584                 case 'P':
585                         prefix = isc_commandline_argument;
586                         break;
587                 case 'S':
588                         suffix = isc_commandline_argument;
589                         break;
590                 case '?':
591                         exit(1);
592                 }
593
594         n = snprintf(buf, sizeof(buf), "%srdata", srcdir);
595         INSIST(n > 0 && (unsigned)n < sizeof(srcdir));
596
597         if (!start_directory(buf, &dir))
598                 exit(1);
599
600         while (next_file(&dir)) {
601                 if (sscanf(dir.filename, TYPECLASSFMT, classname,
602                            &rdclass) != 2)
603                         continue;
604                 if ((rdclass > 65535) || (rdclass < 0))
605                         continue;
606
607                 n = snprintf(buf, sizeof(buf), "%srdata/%s_%d",
608                              srcdir, classname, rdclass);
609                 INSIST(n > 0 && (unsigned)n < sizeof(buf));
610                 if (strcmp(buf + 6 + strlen(srcdir), dir.filename) != 0)
611                         continue;
612                 sd(rdclass, classname, buf, filetype);
613         }
614         end_directory(&dir);
615         n = snprintf(buf, sizeof(buf), "%srdata/generic", srcdir);
616         INSIST(n > 0 && (unsigned)n < sizeof(srcdir));
617         sd(0, "", buf, filetype);
618
619         if (time(&now) != -1) {
620                 if ((tm = localtime(&now)) != NULL && tm->tm_year > 104) {
621                         n = snprintf(year, sizeof(year), "-%d",
622                                      tm->tm_year + 1900);
623                         INSIST(n > 0 && (unsigned)n < sizeof(year));
624                 } else
625                         year[0] = 0;
626         } else
627                 year[0] = 0;
628
629         if (!depend) fprintf(stdout, copyright, year);
630
631         if (code) {
632                 fputs("#ifndef DNS_CODE_H\n", stdout);
633                 fputs("#define DNS_CODE_H 1\n\n", stdout);
634
635                 fputs("#include <isc/boolean.h>\n", stdout);
636                 fputs("#include <isc/result.h>\n\n", stdout);
637                 fputs("#include <dns/name.h>\n\n", stdout);
638
639                 for (tt = types; tt != NULL; tt = tt->next)
640                         fprintf(stdout, "#include \"%s/%s_%d.c\"\n",
641                                 tt->dirname, tt->typename, tt->type);
642
643                 fputs("\n\n", stdout);
644
645                 doswitch("FROMTEXTSWITCH", "fromtext", FROMTEXTARGS,
646                          FROMTEXTTYPE, FROMTEXTCLASS, FROMTEXTDEF);
647                 doswitch("TOTEXTSWITCH", "totext", TOTEXTARGS,
648                          TOTEXTTYPE, TOTEXTCLASS, TOTEXTDEF);
649                 doswitch("FROMWIRESWITCH", "fromwire", FROMWIREARGS,
650                          FROMWIRETYPE, FROMWIRECLASS, FROMWIREDEF);
651                 doswitch("TOWIRESWITCH", "towire", TOWIREARGS,
652                          TOWIRETYPE, TOWIRECLASS, TOWIREDEF);
653                 doswitch("COMPARESWITCH", "compare", COMPAREARGS,
654                           COMPARETYPE, COMPARECLASS, COMPAREDEF);
655                 doswitch("CASECOMPARESWITCH", "casecompare", COMPAREARGS,
656                           COMPARETYPE, COMPARECLASS, COMPAREDEF);
657                 doswitch("FROMSTRUCTSWITCH", "fromstruct", FROMSTRUCTARGS,
658                           FROMSTRUCTTYPE, FROMSTRUCTCLASS, FROMSTRUCTDEF);
659                 doswitch("TOSTRUCTSWITCH", "tostruct", TOSTRUCTARGS,
660                           TOSTRUCTTYPE, TOSTRUCTCLASS, TOSTRUCTDEF);
661                 doswitch("FREESTRUCTSWITCH", "freestruct", FREESTRUCTARGS,
662                           FREESTRUCTTYPE, FREESTRUCTCLASS, FREESTRUCTDEF);
663                 doswitch("ADDITIONALDATASWITCH", "additionaldata",
664                          ADDITIONALDATAARGS, ADDITIONALDATATYPE,
665                          ADDITIONALDATACLASS, ADDITIONALDATADEF);
666                 doswitch("DIGESTSWITCH", "digest",
667                          DIGESTARGS, DIGESTTYPE,
668                          DIGESTCLASS, DIGESTDEF);
669                 doswitch("CHECKOWNERSWITCH", "checkowner",
670                         CHECKOWNERARGS, CHECKOWNERTYPE,
671                         CHECKOWNERCLASS, CHECKOWNERDEF);
672                 doswitch("CHECKNAMESSWITCH", "checknames",
673                         CHECKNAMESARGS, CHECKNAMESTYPE,
674                         CHECKNAMESCLASS, CHECKNAMESDEF);
675
676                 /*
677                  * From here down, we are processing the rdata names and
678                  * attributes.
679                  */
680
681 #define PRINT_COMMA(x) (x == maxtype ? "" : ",")
682
683 #define METANOTQUESTION  "DNS_RDATATYPEATTR_META | " \
684                          "DNS_RDATATYPEATTR_NOTQUESTION"
685 #define METAQUESTIONONLY "DNS_RDATATYPEATTR_META | " \
686                          "DNS_RDATATYPEATTR_QUESTIONONLY"
687 #define RESERVED "DNS_RDATATYPEATTR_RESERVED"
688
689                 /*
690                  * Add in reserved/special types.  This will let us
691                  * sort them without special cases.
692                  */
693                 insert_into_typenames(0, "reserved0", RESERVED);
694                 insert_into_typenames(31, "eid", RESERVED);
695                 insert_into_typenames(32, "nimloc", RESERVED);
696                 insert_into_typenames(34, "atma", RESERVED);
697                 insert_into_typenames(100, "uinfo", RESERVED);
698                 insert_into_typenames(101, "uid", RESERVED);
699                 insert_into_typenames(102, "gid", RESERVED);
700                 insert_into_typenames(251, "ixfr", METAQUESTIONONLY);
701                 insert_into_typenames(252, "axfr", METAQUESTIONONLY);
702                 insert_into_typenames(253, "mailb", METAQUESTIONONLY);
703                 insert_into_typenames(254, "maila", METAQUESTIONONLY);
704                 insert_into_typenames(255, "any", METAQUESTIONONLY);
705
706                 /*
707                  * Spit out a quick and dirty hash function.  Here,
708                  * we walk through the list of type names, and calculate
709                  * a hash.  This isn't perfect, but it will generate "pretty
710                  * good" estimates.  Lowercase the characters before
711                  * computing in all cases.
712                  *
713                  * Here, walk the list from top to bottom, calculating
714                  * the hash (mod 256) for each name.
715                  */
716                 fprintf(stdout, "#define RDATATYPE_COMPARE(_s, _d, _tn, _n, _tp) \\\n");
717                 fprintf(stdout, "\tdo { \\\n");
718                 fprintf(stdout, "\t\tif (sizeof(_s) - 1 == _n && \\\n"
719                                 "\t\t    strncasecmp(_s,(_tn),"
720                                 "(sizeof(_s) - 1)) == 0) { \\\n");
721                 fprintf(stdout, "\t\t\tif ((dns_rdatatype_attributes(_d) & "
722                                   "DNS_RDATATYPEATTR_RESERVED) != 0) \\\n");
723                 fprintf(stdout, "\t\t\t\treturn (ISC_R_NOTIMPLEMENTED); \\\n");
724                 fprintf(stdout, "\t\t\t*(_tp) = _d; \\\n");
725                 fprintf(stdout, "\t\t\treturn (ISC_R_SUCCESS); \\\n");
726                 fprintf(stdout, "\t\t} \\\n");
727                 fprintf(stdout, "\t} while (0)\n\n");
728
729                 fprintf(stdout, "#define RDATATYPE_FROMTEXT_SW(_hash,"
730                                 "_typename,_length,_typep) \\\n");
731                 fprintf(stdout, "\tswitch (_hash) { \\\n");
732                 for (i = 0; i <= maxtype; i++) {
733                         ttn = find_typename(i);
734                         if (ttn == NULL)
735                                 continue;
736
737                         /*
738                          * Skip entries we already processed.
739                          */
740                         if (ttn->sorted != 0)
741                                 continue;
742
743                         hash = HASH(ttn->typename);
744                         fprintf(stdout, "\t\tcase %u: \\\n", hash);
745
746                         /*
747                          * Find all other entries that happen to match
748                          * this hash.
749                          */
750                         for (j = 0; j <= maxtype; j++) {
751                                 ttn2 = find_typename(j);
752                                 if (ttn2 == NULL)
753                                         continue;
754                                 if (hash == HASH(ttn2->typename)) {
755                                         fprintf(stdout, "\t\t\tRDATATYPE_COMPARE"
756                                                "(\"%s\", %u, "
757                                                "_typename, _length, _typep); \\\n",
758                                                ttn2->typename, ttn2->type);
759                                         ttn2->sorted = 1;
760                                 }
761                         }
762                         fprintf(stdout, "\t\t\tbreak; \\\n");
763                 }
764                 fprintf(stdout, "\t}\n");
765
766                 fprintf(stdout, "#define RDATATYPE_ATTRIBUTE_SW \\\n");
767                 fprintf(stdout, "\tswitch (type) { \\\n");
768                 for (i = 0; i <= maxtype; i++) {
769                         ttn = find_typename(i);
770                         if (ttn == NULL)
771                                 continue;
772                         fprintf(stdout, "\tcase %u: return (%s); \\\n",
773                                 i, upper(ttn->attr));
774                 }
775                 fprintf(stdout, "\t}\n");
776
777                 fprintf(stdout, "#define RDATATYPE_TOTEXT_SW \\\n");
778                 fprintf(stdout, "\tswitch (type) { \\\n");
779                 for (i = 0; i <= maxtype; i++) {
780                         ttn = find_typename(i);
781                         if (ttn == NULL)
782                                 continue;
783                         /*
784                          * Remove KEYDATA (65533) from the type to memonic
785                          * translation as it is internal use only.  This
786                          * stops the tools from displaying KEYDATA instead
787                          * of TYPE65533.
788                          */
789                         if (i == 65533U)
790                                 continue;
791                         fprintf(stdout, "\tcase %u: return "
792                                 "(str_totext(\"%s\", target)); \\\n",
793                                 i, upper(ttn->typename));
794                 }
795                 fprintf(stdout, "\t}\n");
796
797                 fputs("#endif /* DNS_CODE_H */\n", stdout);
798         } else if (type_enum) {
799                 char *s;
800
801                 fprintf(stdout, "#ifndef DNS_ENUMTYPE_H\n");
802                 fprintf(stdout, "#define DNS_ENUMTYPE_H 1\n\n");
803
804                 fprintf(stdout, "enum {\n");
805                 fprintf(stdout, "\tdns_rdatatype_none = 0,\n");
806
807                 lasttype = 0;
808                 for (tt = types; tt != NULL; tt = tt->next)
809                         if (tt->type != lasttype)
810                                 fprintf(stdout,
811                                         "\tdns_rdatatype_%s = %d,\n",
812                                         funname(tt->typename, buf1),
813                                         lasttype = tt->type);
814
815                 fprintf(stdout, "\tdns_rdatatype_ixfr = 251,\n");
816                 fprintf(stdout, "\tdns_rdatatype_axfr = 252,\n");
817                 fprintf(stdout, "\tdns_rdatatype_mailb = 253,\n");
818                 fprintf(stdout, "\tdns_rdatatype_maila = 254,\n");
819                 fprintf(stdout, "\tdns_rdatatype_any = 255\n");
820
821                 fprintf(stdout, "};\n\n");
822
823                 fprintf(stdout, "#define dns_rdatatype_none\t"
824                         "((dns_rdatatype_t)dns_rdatatype_none)\n");
825
826                 for (tt = types; tt != NULL; tt = tt->next)
827                         if (tt->type != lasttype) {
828                                 s = funname(tt->typename, buf1);
829                                 fprintf(stdout,
830                                         "#define dns_rdatatype_%s\t%s"
831                                         "((dns_rdatatype_t)dns_rdatatype_%s)"
832                                         "\n",
833                                         s, strlen(s) < 2U ? "\t" : "", s);
834                                 lasttype = tt->type;
835                         }
836
837                 fprintf(stdout, "#define dns_rdatatype_ixfr\t"
838                         "((dns_rdatatype_t)dns_rdatatype_ixfr)\n");
839                 fprintf(stdout, "#define dns_rdatatype_axfr\t"
840                         "((dns_rdatatype_t)dns_rdatatype_axfr)\n");
841                 fprintf(stdout, "#define dns_rdatatype_mailb\t"
842                         "((dns_rdatatype_t)dns_rdatatype_mailb)\n");
843                 fprintf(stdout, "#define dns_rdatatype_maila\t"
844                         "((dns_rdatatype_t)dns_rdatatype_maila)\n");
845                 fprintf(stdout, "#define dns_rdatatype_any\t"
846                         "((dns_rdatatype_t)dns_rdatatype_any)\n");
847
848                 fprintf(stdout, "\n#endif /* DNS_ENUMTYPE_H */\n");
849
850         } else if (class_enum) {
851                 char *s;
852                 int classnum;
853
854                 fprintf(stdout, "#ifndef DNS_ENUMCLASS_H\n");
855                 fprintf(stdout, "#define DNS_ENUMCLASS_H 1\n\n");
856
857                 fprintf(stdout, "enum {\n");
858
859                 fprintf(stdout, "\tdns_rdataclass_reserved0 = 0,\n");
860                 fprintf(stdout, "#define dns_rdataclass_reserved0 \\\n\t\t\t\t"
861                         "((dns_rdataclass_t)dns_rdataclass_reserved0)\n");
862
863 #define PRINTCLASS(name, num) \
864         do { \
865                 s = funname(name, buf1); \
866                 classnum = num; \
867                 fprintf(stdout, "\tdns_rdataclass_%s = %d%s\n", s, classnum, \
868                        classnum != 255 ? "," : ""); \
869                 fprintf(stdout, "#define dns_rdataclass_%s\t" \
870                        "((dns_rdataclass_t)dns_rdataclass_%s)\n", s, s); \
871         } while (0)
872
873                 for (cc = classes; cc != NULL; cc = cc->next) {
874                         if (cc->rdclass == 3)
875                                 PRINTCLASS("chaos", 3);
876                         else if (cc->rdclass == 255)
877                                 PRINTCLASS("none", 254);
878                         PRINTCLASS(cc->classname, cc->rdclass);
879                 }
880
881 #undef PRINTCLASS
882
883                 fprintf(stdout, "};\n\n");
884                 fprintf(stdout, "#endif /* DNS_ENUMCLASS_H */\n");
885         } else if (structs) {
886                 if (prefix != NULL) {
887                         if ((fd = fopen(prefix,"r")) != NULL) {
888                                 while (fgets(buf, sizeof(buf), fd) != NULL)
889                                         fputs(buf, stdout);
890                                 fclose(fd);
891                         }
892                 }
893                 for (tt = types; tt != NULL; tt = tt->next) {
894                         snprintf(buf, sizeof(buf), "%s/%s_%d.h",
895                                 tt->dirname, tt->typename, tt->type);
896                         if ((fd = fopen(buf,"r")) != NULL) {
897                                 while (fgets(buf, sizeof(buf), fd) != NULL)
898                                         fputs(buf, stdout);
899                                 fclose(fd);
900                         }
901                 }
902                 if (suffix != NULL) {
903                         if ((fd = fopen(suffix,"r")) != NULL) {
904                                 while (fgets(buf, sizeof(buf), fd) != NULL)
905                                         fputs(buf, stdout);
906                                 fclose(fd);
907                         }
908                 }
909         } else if (depend) {
910                 for (tt = types; tt != NULL; tt = tt->next)
911                         fprintf(stdout, "%s:\t%s/%s_%d.h\n", file,
912                                 tt->dirname, tt->typename, tt->type);
913         }
914
915         if (ferror(stdout) != 0)
916                 exit(1);
917
918         return (0);
919 }