1 /* 2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14 * PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 /*! \file */ 18 19 #include <sys/types.h> 20 21 #include <ctype.h> 22 #include <dirent.h> 23 #include <stdlib.h> 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <string.h> 27 #include <time.h> 28 #include <unistd.h> 29 30 #define INSIST(cond) \ 31 if (!(cond)) { \ 32 fprintf(stderr, "%s:%d: INSIST(%s)\n", \ 33 __FILE__, __LINE__, #cond); \ 34 abort(); \ 35 } 36 37 #define TOTEXTARGS "rdata, tctx, target" 38 #define TOTEXTCLASS "rdata->rdclass" 39 #define TOTEXTTYPE "rdata->type" 40 #define TOTEXTDEF "use_default = 1" 41 42 #define FROMWIREARGS "rdclass, type, source, dctx, options, target" 43 #define FROMWIRECLASS "rdclass" 44 #define FROMWIRETYPE "type" 45 #define FROMWIREDEF "use_default = 1" 46 47 #define TOWIREARGS "rdata, cctx, target" 48 #define TOWIRECLASS "rdata->rdclass" 49 #define TOWIRETYPE "rdata->type" 50 #define TOWIREDEF "use_default = 1" 51 52 static const char copyright[] = 53 "/*\n" 54 " * Copyright (C) 2004%s Internet Systems Consortium, Inc. (\"ISC\")\n" 55 " * Copyright (C) 1998-2003 Internet Software Consortium.\n" 56 " *\n" 57 " * Permission to use, copy, modify, and distribute this software for any\n" 58 " * purpose with or without fee is hereby granted, provided that the above\n" 59 " * copyright notice and this permission notice appear in all copies.\n" 60 " *\n" 61 " * THE SOFTWARE IS PROVIDED \"AS IS\" AND ISC DISCLAIMS ALL WARRANTIES WITH\n" 62 " * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\n" 63 " * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,\n" 64 " * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\n" 65 " * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE\n" 66 " * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\n" 67 " * PERFORMANCE OF THIS SOFTWARE.\n" 68 " */\n" 69 "\n" 70 "/***************\n" 71 " ***************\n" 72 " *************** THIS FILE IS AUTOMATICALLY GENERATED BY gen.c.\n" 73 " *************** DO NOT EDIT!\n" 74 " ***************\n" 75 " ***************/\n" 76 "\n" 77 "/*! \\file */\n" 78 "\n"; 79 80 #define STR_EXPAND(tok) #tok 81 #define STR(tok) STR_EXPAND(tok) 82 83 #define TYPECLASSLEN 20 /* DNS mnemonic size. Must be less than 100. */ 84 #define TYPECLASSBUF (TYPECLASSLEN + 1) 85 #define TYPECLASSFMT "%" STR(TYPECLASSLEN) "[-0-9a-z]_%d" 86 #define ATTRIBUTESIZE 256 87 #define DIRNAMESIZE 256 88 89 static struct cc { 90 struct cc *next; 91 int rdclass; 92 char classname[TYPECLASSBUF]; 93 } *classes; 94 95 static struct tt { 96 struct tt *next; 97 int rdclass; 98 int type; 99 char classname[TYPECLASSBUF]; 100 char typename[TYPECLASSBUF]; 101 char dirname[DIRNAMESIZE]; /* XXX Should be max path length */ 102 } *types; 103 104 static char * 105 funname(const char *, char *); 106 static void 107 doswitch(const char *, const char *, const char *, const char *, 108 const char *, const char *); 109 static void 110 add(int, const char *, int, const char *, const char *); 111 static void 112 sd(int, const char *, const char *, char); 113 114 115 static char * 116 funname(const char *s, char *buf) { 117 char *b = buf; 118 char c; 119 120 INSIST(strlen(s) < TYPECLASSBUF); 121 while ((c = *s++)) { 122 *b++ = (c == '-') ? '_' : c; 123 } 124 *b = '\0'; 125 return (buf); 126 } 127 128 static void 129 doswitch(const char *name, const char *function, const char *args, 130 const char *tsw, const char *csw, const char *res) 131 { 132 struct tt *tt; 133 int first = 1; 134 int lasttype = 0; 135 int subswitch = 0; 136 char buf1[TYPECLASSBUF], buf2[TYPECLASSBUF]; 137 const char *result = " result ="; 138 139 if (res == NULL) 140 result = ""; 141 142 for (tt = types; tt != NULL; tt = tt->next) { 143 if (first) { 144 fprintf(stdout, "\n#define %s \\\n", name); 145 fprintf(stdout, "\tswitch (%s) { \\\n" /*}*/, tsw); 146 first = 0; 147 } 148 if (tt->type != lasttype && subswitch) { 149 if (res == NULL) 150 fprintf(stdout, "\t\tdefault: break; \\\n"); 151 else 152 fprintf(stdout, 153 "\t\tdefault: %s; break; \\\n", res); 154 fputs(/*{*/ "\t\t} \\\n", stdout); 155 fputs("\t\tbreak; \\\n", stdout); 156 subswitch = 0; 157 } 158 if (tt->rdclass && tt->type != lasttype) { 159 fprintf(stdout, "\tcase %d: switch (%s) { \\\n" /*}*/, 160 tt->type, csw); 161 subswitch = 1; 162 } 163 if (tt->rdclass == 0) 164 fprintf(stdout, 165 "\tcase %d:%s %s_%s(%s); break;", 166 tt->type, result, function, 167 funname(tt->typename, buf1), args); 168 else 169 fprintf(stdout, 170 "\t\tcase %d:%s %s_%s_%s(%s); break;", 171 tt->rdclass, result, function, 172 funname(tt->classname, buf1), 173 funname(tt->typename, buf2), args); 174 fputs(" \\\n", stdout); 175 lasttype = tt->type; 176 } 177 if (subswitch) { 178 if (res == NULL) 179 fprintf(stdout, "\t\tdefault: break; \\\n"); 180 else 181 fprintf(stdout, "\t\tdefault: %s; break; \\\n", res); 182 fputs(/*{*/ "\t\t} \\\n", stdout); 183 fputs("\t\tbreak; \\\n", stdout); 184 } 185 if (first) { 186 if (res == NULL) 187 fprintf(stdout, "\n#define %s\n", name); 188 else 189 fprintf(stdout, "\n#define %s %s;\n", name, res); 190 } else { 191 if (res == NULL) 192 fprintf(stdout, "\tdefault: break; \\\n"); 193 else 194 fprintf(stdout, "\tdefault: %s; break; \\\n", res); 195 fputs(/*{*/ "\t}\n", stdout); 196 } 197 } 198 199 static void 200 add(int rdclass, const char *classname, int type, const char *typename, 201 const char *dirname) 202 { 203 struct tt *newtt = (struct tt *)malloc(sizeof(*newtt)); 204 struct tt *tt, *oldtt; 205 struct cc *newcc; 206 struct cc *cc, *oldcc; 207 208 INSIST(strlen(typename) < TYPECLASSBUF); 209 INSIST(strlen(classname) < TYPECLASSBUF); 210 INSIST(strlen(dirname) < DIRNAMESIZE); 211 212 if (newtt == NULL) { 213 fprintf(stderr, "malloc() failed\n"); 214 exit(1); 215 } 216 217 newtt->next = NULL; 218 newtt->rdclass = rdclass; 219 newtt->type = type; 220 221 strncpy(newtt->classname, classname, sizeof(newtt->classname)); 222 newtt->classname[sizeof(newtt->classname) - 1] = '\0'; 223 224 strncpy(newtt->typename, typename, sizeof(newtt->typename)); 225 newtt->typename[sizeof(newtt->typename) - 1] = '\0'; 226 227 if (strncmp(dirname, "./", 2) == 0) 228 dirname += 2; 229 strncpy(newtt->dirname, dirname, sizeof(newtt->dirname)); 230 newtt->dirname[sizeof(newtt->dirname) - 1] = '\0'; 231 232 tt = types; 233 oldtt = NULL; 234 235 while ((tt != NULL) && (tt->type < type)) { 236 oldtt = tt; 237 tt = tt->next; 238 } 239 240 while ((tt != NULL) && (tt->type == type) && (tt->rdclass < rdclass)) { 241 if (strcmp(tt->typename, typename) != 0) 242 exit(1); 243 oldtt = tt; 244 tt = tt->next; 245 } 246 247 if ((tt != NULL) && (tt->type == type) && (tt->rdclass == rdclass)) 248 exit(1); 249 250 newtt->next = tt; 251 if (oldtt != NULL) 252 oldtt->next = newtt; 253 else 254 types = newtt; 255 256 /* 257 * Do a class switch for this type. 258 */ 259 if (rdclass == 0) 260 return; 261 262 newcc = (struct cc *)malloc(sizeof(*newcc)); 263 if (newcc == NULL) { 264 fprintf(stderr, "malloc() failed\n"); 265 exit(1); 266 } 267 newcc->rdclass = rdclass; 268 strncpy(newcc->classname, classname, sizeof(newcc->classname)); 269 newcc->classname[sizeof(newcc->classname) - 1] = '\0'; 270 cc = classes; 271 oldcc = NULL; 272 273 while ((cc != NULL) && (cc->rdclass < rdclass)) { 274 oldcc = cc; 275 cc = cc->next; 276 } 277 278 if ((cc != NULL) && cc->rdclass == rdclass) { 279 free((char *)newcc); 280 return; 281 } 282 283 newcc->next = cc; 284 if (oldcc != NULL) 285 oldcc->next = newcc; 286 else 287 classes = newcc; 288 } 289 290 static void 291 sd(int rdclass, const char *classname, const char *dirname, char filetype) { 292 DIR *dirp; 293 struct dirent *dp; 294 char buf[TYPECLASSLEN + sizeof("_65535.h")]; 295 char typename[TYPECLASSBUF]; 296 int type, n; 297 298 if ((dirp = opendir(dirname)) == NULL) 299 return; 300 301 while ((dp = readdir(dirp)) != NULL) { 302 if (sscanf(dp->d_name, TYPECLASSFMT, typename, &type) != 2) 303 continue; 304 if ((type > 65535) || (type < 0)) 305 continue; 306 307 n = snprintf(buf, sizeof(buf), "%s_%d.%c", typename, 308 type, filetype); 309 INSIST(n > 0 && (unsigned)n < sizeof(buf)); 310 if (strcmp(buf, dp->d_name) != 0) 311 continue; 312 add(rdclass, classname, type, typename, dirname); 313 } 314 315 closedir(dirp); 316 } 317 318 int 319 main(int argc, char **argv) { 320 DIR *dirp; 321 struct dirent *dp; 322 char buf[DIRNAMESIZE]; /* XXX Should be max path length */ 323 char srcdir[DIRNAMESIZE]; /* XXX Should be max path length */ 324 int rdclass; 325 char classname[TYPECLASSBUF]; 326 struct tt *tt; 327 struct cc *cc; 328 struct tm *tm; 329 time_t now; 330 char year[11]; 331 int lasttype; 332 int code = 1; 333 int class_enum = 0; 334 int type_enum = 0; 335 int structs = 0; 336 int depend = 0; 337 int c, n; 338 char buf1[TYPECLASSBUF]; 339 char filetype = 'c'; 340 FILE *fd; 341 char *prefix = NULL; 342 char *suffix = NULL; 343 char *file = NULL; 344 345 srcdir[0] = '\0'; 346 while ((c = getopt(argc, argv, "cdits:F:P:S:")) != -1) 347 switch (c) { 348 case 'c': 349 code = 0; 350 depend = 0; 351 type_enum = 0; 352 class_enum = 1; 353 filetype = 'c'; 354 structs = 0; 355 break; 356 case 'd': 357 code = 0; 358 depend = 1; 359 class_enum = 0; 360 type_enum = 0; 361 structs = 0; 362 filetype = 'h'; 363 break; 364 case 't': 365 code = 0; 366 depend = 0; 367 class_enum = 0; 368 type_enum = 1; 369 filetype = 'c'; 370 structs = 0; 371 break; 372 case 'i': 373 code = 0; 374 depend = 0; 375 class_enum = 0; 376 type_enum = 0; 377 structs = 1; 378 filetype = 'h'; 379 break; 380 case 's': 381 if (strlen(optarg) > 382 DIRNAMESIZE - 2 * TYPECLASSLEN - 383 sizeof("/rdata/_65535_65535")) { 384 fprintf(stderr, "\"%s\" too long\n", 385 optarg); 386 exit(1); 387 } 388 n = snprintf(srcdir, sizeof(srcdir), "%s/", 389 optarg); 390 INSIST(n > 0 && (unsigned)n < sizeof(srcdir)); 391 break; 392 case 'F': 393 file = optarg; 394 break; 395 case 'P': 396 prefix = optarg; 397 break; 398 case 'S': 399 suffix = optarg; 400 break; 401 case '?': 402 exit(1); 403 } 404 405 n = snprintf(buf, sizeof(buf), "%srdata", srcdir); 406 INSIST(n > 0 && (unsigned)n < sizeof(srcdir)); 407 408 if ((dirp = opendir(buf)) == NULL) 409 exit(1); 410 411 while ((dp = readdir(dirp)) != NULL) { 412 if (sscanf(dp->d_name, TYPECLASSFMT, classname, 413 &rdclass) != 2) 414 continue; 415 if ((rdclass > 65535) || (rdclass < 0)) 416 continue; 417 418 n = snprintf(buf, sizeof(buf), "%srdata/%s_%d", 419 srcdir, classname, rdclass); 420 INSIST(n > 0 && (unsigned)n < sizeof(buf)); 421 if (strcmp(buf + 6 + strlen(srcdir), dp->d_name) != 0) 422 continue; 423 sd(rdclass, classname, buf, filetype); 424 } 425 closedir(dirp); 426 427 n = snprintf(buf, sizeof(buf), "%srdata/generic", srcdir); 428 INSIST(n > 0 && (unsigned)n < sizeof(srcdir)); 429 sd(0, "", buf, filetype); 430 431 if (time(&now) != -1) { 432 if ((tm = localtime(&now)) != NULL && tm->tm_year > 104) { 433 n = snprintf(year, sizeof(year), "-%d", 434 tm->tm_year + 1900); 435 INSIST(n > 0 && (unsigned)n < sizeof(year)); 436 } else 437 year[0] = 0; 438 } else 439 year[0] = 0; 440 441 if (!depend) 442 fprintf(stdout, copyright, year); 443 444 if (code) { 445 fputs("#ifndef DNS_CODE_H\n", stdout); 446 fputs("#define DNS_CODE_H 1\n\n", stdout); 447 448 fputs("#include <isc/result.h>\n\n", stdout); 449 fputs("#include <dns/name.h>\n\n", stdout); 450 451 for (tt = types; tt != NULL; tt = tt->next) 452 fprintf(stdout, "#include \"%s/%s_%d.c\"\n", 453 tt->dirname, tt->typename, tt->type); 454 455 fputs("\n\n", stdout); 456 457 doswitch("TOTEXTSWITCH", "totext", TOTEXTARGS, 458 TOTEXTTYPE, TOTEXTCLASS, TOTEXTDEF); 459 doswitch("FROMWIRESWITCH", "fromwire", FROMWIREARGS, 460 FROMWIRETYPE, FROMWIRECLASS, FROMWIREDEF); 461 doswitch("TOWIRESWITCH", "towire", TOWIREARGS, 462 TOWIRETYPE, TOWIRECLASS, TOWIREDEF); 463 464 fputs("#endif /* DNS_CODE_H */\n", stdout); 465 } else if (type_enum) { 466 char *s; 467 468 fprintf(stdout, "#ifndef DNS_ENUMTYPE_H\n"); 469 fprintf(stdout, "#define DNS_ENUMTYPE_H 1\n\n"); 470 471 fprintf(stdout, "enum {\n"); 472 fprintf(stdout, "\tdns_rdatatype_none = 0,\n"); 473 474 lasttype = 0; 475 for (tt = types; tt != NULL; tt = tt->next) 476 if (tt->type != lasttype) 477 fprintf(stdout, 478 "\tdns_rdatatype_%s = %d,\n", 479 funname(tt->typename, buf1), 480 lasttype = tt->type); 481 482 fprintf(stdout, "\tdns_rdatatype_ixfr = 251,\n"); 483 fprintf(stdout, "\tdns_rdatatype_axfr = 252,\n"); 484 fprintf(stdout, "\tdns_rdatatype_mailb = 253,\n"); 485 fprintf(stdout, "\tdns_rdatatype_maila = 254,\n"); 486 fprintf(stdout, "\tdns_rdatatype_any = 255\n"); 487 488 fprintf(stdout, "};\n\n"); 489 490 fprintf(stdout, "#define dns_rdatatype_none\t" 491 "((dns_rdatatype_t)dns_rdatatype_none)\n"); 492 493 for (tt = types; tt != NULL; tt = tt->next) 494 if (tt->type != lasttype) { 495 s = funname(tt->typename, buf1); 496 fprintf(stdout, 497 "#define dns_rdatatype_%s\t%s" 498 "((dns_rdatatype_t)dns_rdatatype_%s)" 499 "\n", 500 s, strlen(s) < 2U ? "\t" : "", s); 501 lasttype = tt->type; 502 } 503 504 fprintf(stdout, "#define dns_rdatatype_ixfr\t" 505 "((dns_rdatatype_t)dns_rdatatype_ixfr)\n"); 506 fprintf(stdout, "#define dns_rdatatype_axfr\t" 507 "((dns_rdatatype_t)dns_rdatatype_axfr)\n"); 508 fprintf(stdout, "#define dns_rdatatype_mailb\t" 509 "((dns_rdatatype_t)dns_rdatatype_mailb)\n"); 510 fprintf(stdout, "#define dns_rdatatype_maila\t" 511 "((dns_rdatatype_t)dns_rdatatype_maila)\n"); 512 fprintf(stdout, "#define dns_rdatatype_any\t" 513 "((dns_rdatatype_t)dns_rdatatype_any)\n"); 514 515 fprintf(stdout, "\n#endif /* DNS_ENUMTYPE_H */\n"); 516 517 } else if (class_enum) { 518 char *s; 519 int classnum; 520 521 fprintf(stdout, "#ifndef DNS_ENUMCLASS_H\n"); 522 fprintf(stdout, "#define DNS_ENUMCLASS_H 1\n\n"); 523 524 fprintf(stdout, "enum {\n"); 525 526 fprintf(stdout, "\tdns_rdataclass_reserved0 = 0,\n"); 527 fprintf(stdout, "#define dns_rdataclass_reserved0 \\\n\t\t\t\t" 528 "((dns_rdataclass_t)dns_rdataclass_reserved0)\n"); 529 530 #define PRINTCLASS(name, num) \ 531 do { \ 532 s = funname(name, buf1); \ 533 classnum = num; \ 534 fprintf(stdout, "\tdns_rdataclass_%s = %d%s\n", s, classnum, \ 535 classnum != 255 ? "," : ""); \ 536 fprintf(stdout, "#define dns_rdataclass_%s\t" \ 537 "((dns_rdataclass_t)dns_rdataclass_%s)\n", s, s); \ 538 } while (0) 539 540 for (cc = classes; cc != NULL; cc = cc->next) { 541 if (cc->rdclass == 3) 542 PRINTCLASS("chaos", 3); 543 else if (cc->rdclass == 255) 544 PRINTCLASS("none", 254); 545 PRINTCLASS(cc->classname, cc->rdclass); 546 } 547 548 #undef PRINTCLASS 549 550 fprintf(stdout, "};\n\n"); 551 fprintf(stdout, "#endif /* DNS_ENUMCLASS_H */\n"); 552 } else if (structs) { 553 if (prefix != NULL) { 554 if ((fd = fopen(prefix,"r")) != NULL) { 555 while (fgets(buf, sizeof(buf), fd) != NULL) 556 fputs(buf, stdout); 557 fclose(fd); 558 } 559 } 560 for (tt = types; tt != NULL; tt = tt->next) { 561 snprintf(buf, sizeof(buf), "%s/%s_%d.h", 562 tt->dirname, tt->typename, tt->type); 563 if ((fd = fopen(buf,"r")) != NULL) { 564 while (fgets(buf, sizeof(buf), fd) != NULL) 565 fputs(buf, stdout); 566 fclose(fd); 567 } 568 } 569 if (suffix != NULL) { 570 if ((fd = fopen(suffix,"r")) != NULL) { 571 while (fgets(buf, sizeof(buf), fd) != NULL) 572 fputs(buf, stdout); 573 fclose(fd); 574 } 575 } 576 } else if (depend) { 577 for (tt = types; tt != NULL; tt = tt->next) 578 fprintf(stdout, "%s:\t%s/%s_%d.h\n", file, 579 tt->dirname, tt->typename, tt->type); 580 } 581 582 if (ferror(stdout) != 0) 583 exit(1); 584 585 return (0); 586 } 587