00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <config.h>
00026
00027 #include <string.h>
00028 #include <stdio.h>
00029
00030 #include <isc/mem.h>
00031 #include <isc/print.h>
00032 #include <isc/result.h>
00033 #include <isc/util.h>
00034
00035 #include <dns/result.h>
00036 #include <dns/sdb.h>
00037
00038 #include <named/builtin.h>
00039 #include <named/globals.h>
00040 #include <named/server.h>
00041 #include <named/os.h>
00042
00043 typedef struct builtin builtin_t;
00044
00045 static isc_result_t do_version_lookup(dns_sdblookup_t *lookup);
00046 static isc_result_t do_hostname_lookup(dns_sdblookup_t *lookup);
00047 static isc_result_t do_authors_lookup(dns_sdblookup_t *lookup);
00048 static isc_result_t do_id_lookup(dns_sdblookup_t *lookup);
00049 static isc_result_t do_empty_lookup(dns_sdblookup_t *lookup);
00050 static isc_result_t do_dns64_lookup(dns_sdblookup_t *lookup);
00051
00052
00053
00054
00055
00056
00057
00058 struct builtin {
00059 isc_result_t (*do_lookup)(dns_sdblookup_t *lookup);
00060 char *server;
00061 char *contact;
00062 };
00063
00064 static builtin_t version_builtin = { do_version_lookup, NULL, NULL };
00065 static builtin_t hostname_builtin = { do_hostname_lookup, NULL, NULL };
00066 static builtin_t authors_builtin = { do_authors_lookup, NULL, NULL };
00067 static builtin_t id_builtin = { do_id_lookup, NULL, NULL };
00068 static builtin_t empty_builtin = { do_empty_lookup, NULL, NULL };
00069 static builtin_t dns64_builtin = { do_dns64_lookup, NULL, NULL };
00070
00071 static dns_sdbimplementation_t *builtin_impl;
00072 static dns_sdbimplementation_t *dns64_impl;
00073
00074
00075
00076
00077 static const unsigned char hex16[256] = {
00078 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00079 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00080 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00081 0, 16, 32, 48, 64, 80, 96,112,128,144, 1, 1, 1, 1, 1, 1,
00082 1,160,176,192,208,224,240, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00083 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00084 1,160,176,192,208,224,240, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00085 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00086 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00087 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00088 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00089 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00090 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00091 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00092 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00093 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
00094 };
00095
00096 const unsigned char decimal[] = "0123456789";
00097
00098 static size_t
00099 dns64_rdata(unsigned char *v, size_t start, unsigned char *rdata) {
00100 size_t i, j = 0;
00101
00102 for (i = 0; i < 4U; i++) {
00103 unsigned char c = v[start++];
00104 if (start == 7U)
00105 start++;
00106 if (c > 99) {
00107 rdata[j++] = 3;
00108 rdata[j++] = decimal[c/100]; c = c % 100;
00109 rdata[j++] = decimal[c/10]; c = c % 10;
00110 rdata[j++] = decimal[c];
00111 } else if (c > 9) {
00112 rdata[j++] = 2;
00113 rdata[j++] = decimal[c/10]; c = c % 10;
00114 rdata[j++] = decimal[c];
00115 } else {
00116 rdata[j++] = 1;
00117 rdata[j++] = decimal[c];
00118 }
00119 }
00120 memmove(&rdata[j], "\07in-addr\04arpa", 14);
00121 return (j + 14);
00122 }
00123
00124 static isc_result_t
00125 dns64_cname(const dns_name_t *zone, const dns_name_t *name,
00126 dns_sdblookup_t *lookup)
00127 {
00128 size_t zlen, nlen, j, len;
00129 unsigned char v[16], n;
00130 unsigned int i;
00131 unsigned char rdata[sizeof("123.123.123.123.in-addr.arpa.")];
00132 unsigned char *ndata;
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142 zlen = zone->length;
00143 nlen = name->length;
00144 if ((zlen + nlen) > 74U || zlen < 10U || (nlen % 2) != 0U)
00145 return (ISC_R_NOTFOUND);
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 ndata = name->ndata;
00164 i = (nlen % 4) == 2U ? 1 : 0;
00165 j = nlen;
00166 memset(v, 0, sizeof(v));
00167 while (j != 0U) {
00168 INSIST((i/2) < sizeof(v));
00169 if (ndata[0] != 1)
00170 return (ISC_R_NOTFOUND);
00171 n = hex16[ndata[1]&0xff];
00172 if (n == 1)
00173 return (ISC_R_NOTFOUND);
00174 v[i/2] = n | (v[i/2]>>4);
00175 j -= 2;
00176 ndata += 2;
00177 i++;
00178 }
00179
00180
00181
00182
00183
00184
00185
00186 #define ZLEN(x) (10 + (x)/2)
00187 switch (zlen) {
00188 case ZLEN(32):
00189
00190
00191
00192
00193 if (nlen > 16U && v[(nlen-1)/4 - 4] != 0)
00194 return (ISC_R_NOTFOUND);
00195
00196
00197
00198
00199 if (nlen + zlen != 74U)
00200 return (ISC_R_SUCCESS);
00201 len = dns64_rdata(v, 8, rdata);
00202 break;
00203 case ZLEN(40):
00204
00205
00206
00207
00208 if (nlen > 12U && v[(nlen-1)/4 - 3] != 0)
00209 return (ISC_R_NOTFOUND);
00210
00211
00212
00213
00214 if (nlen + zlen != 74U)
00215 return (ISC_R_SUCCESS);
00216 len = dns64_rdata(v, 6, rdata);
00217 break;
00218 case ZLEN(48):
00219
00220
00221
00222
00223 if (nlen > 8U && v[(nlen-1)/4 - 2] != 0)
00224 return (ISC_R_NOTFOUND);
00225
00226
00227
00228
00229 if (nlen + zlen != 74U)
00230 return (ISC_R_SUCCESS);
00231 len = dns64_rdata(v, 5, rdata);
00232 break;
00233 case ZLEN(56):
00234
00235
00236
00237
00238 if (nlen > 4U && v[(nlen-1)/4 - 1] != 0)
00239 return (ISC_R_NOTFOUND);
00240
00241
00242
00243
00244 if (nlen + zlen != 74U)
00245 return (ISC_R_SUCCESS);
00246 len = dns64_rdata(v, 4, rdata);
00247 break;
00248 case ZLEN(64):
00249
00250
00251
00252
00253 if (v[(nlen-1)/4] != 0)
00254 return (ISC_R_NOTFOUND);
00255
00256
00257
00258
00259 if (nlen + zlen != 74U)
00260 return (ISC_R_SUCCESS);
00261 len = dns64_rdata(v, 3, rdata);
00262 break;
00263 case ZLEN(96):
00264
00265
00266
00267
00268 if (nlen + zlen != 74U)
00269 return (ISC_R_SUCCESS);
00270 len = dns64_rdata(v, 0, rdata);
00271 break;
00272 default:
00273
00274
00275
00276
00277 return (ISC_R_NOTFOUND);
00278 }
00279 return (dns_sdb_putrdata(lookup, dns_rdatatype_cname, 600,
00280 rdata, (unsigned int)len));
00281 }
00282
00283 static isc_result_t
00284 builtin_lookup(const char *zone, const char *name, void *dbdata,
00285 dns_sdblookup_t *lookup, dns_clientinfomethods_t *methods,
00286 dns_clientinfo_t *clientinfo)
00287 {
00288 builtin_t *b = (builtin_t *) dbdata;
00289
00290 UNUSED(zone);
00291 UNUSED(methods);
00292 UNUSED(clientinfo);
00293
00294 if (strcmp(name, "@") == 0)
00295 return (b->do_lookup(lookup));
00296 else
00297 return (ISC_R_NOTFOUND);
00298 }
00299
00300 static isc_result_t
00301 dns64_lookup(const dns_name_t *zone, const dns_name_t *name, void *dbdata,
00302 dns_sdblookup_t *lookup, dns_clientinfomethods_t *methods,
00303 dns_clientinfo_t *clientinfo)
00304 {
00305 builtin_t *b = (builtin_t *) dbdata;
00306
00307 UNUSED(methods);
00308 UNUSED(clientinfo);
00309
00310 if (name->labels == 0 && name->length == 0)
00311 return (b->do_lookup(lookup));
00312 else
00313 return (dns64_cname(zone, name, lookup));
00314 }
00315
00316 static isc_result_t
00317 put_txt(dns_sdblookup_t *lookup, const char *text) {
00318 unsigned char buf[256];
00319 unsigned int len = strlen(text);
00320 if (len > 255)
00321 len = 255;
00322 buf[0] = len;
00323 memmove(&buf[1], text, len);
00324 return (dns_sdb_putrdata(lookup, dns_rdatatype_txt, 0, buf, len + 1));
00325 }
00326
00327 static isc_result_t
00328 do_version_lookup(dns_sdblookup_t *lookup) {
00329 if (ns_g_server->version_set) {
00330 if (ns_g_server->version == NULL)
00331 return (ISC_R_SUCCESS);
00332 else
00333 return (put_txt(lookup, ns_g_server->version));
00334 } else {
00335 return (put_txt(lookup, ns_g_version));
00336 }
00337 }
00338
00339 static isc_result_t
00340 do_hostname_lookup(dns_sdblookup_t *lookup) {
00341 if (ns_g_server->hostname_set) {
00342 if (ns_g_server->hostname == NULL)
00343 return (ISC_R_SUCCESS);
00344 else
00345 return (put_txt(lookup, ns_g_server->hostname));
00346 } else {
00347 char buf[256];
00348 isc_result_t result = ns_os_gethostname(buf, sizeof(buf));
00349 if (result != ISC_R_SUCCESS)
00350 return (result);
00351 return (put_txt(lookup, buf));
00352 }
00353 }
00354
00355 static isc_result_t
00356 do_authors_lookup(dns_sdblookup_t *lookup) {
00357 isc_result_t result;
00358 const char **p;
00359 static const char *authors[] = {
00360 "Mark Andrews",
00361 "Curtis Blackburn",
00362 "James Brister",
00363 "Ben Cottrell",
00364 "John H. DuBois III",
00365 "Francis Dupont",
00366 "Michael Graff",
00367 "Andreas Gustafsson",
00368 "Bob Halley",
00369 "Evan Hunt",
00370 "JINMEI Tatuya",
00371 "David Lawrence",
00372 "Scott Mann",
00373 "Danny Mayer",
00374 "Damien Neil",
00375 "Matt Nelson",
00376 "Jeremy C. Reed",
00377 "Michael Sawyer",
00378 "Brian Wellington",
00379 NULL
00380 };
00381
00382
00383
00384
00385 if (ns_g_server->version_set)
00386 return (ISC_R_SUCCESS);
00387
00388 for (p = authors; *p != NULL; p++) {
00389 result = put_txt(lookup, *p);
00390 if (result != ISC_R_SUCCESS)
00391 return (result);
00392 }
00393 return (ISC_R_SUCCESS);
00394 }
00395
00396 static isc_result_t
00397 do_id_lookup(dns_sdblookup_t *lookup) {
00398
00399 if (ns_g_server->server_usehostname) {
00400 char buf[256];
00401 isc_result_t result = ns_os_gethostname(buf, sizeof(buf));
00402 if (result != ISC_R_SUCCESS)
00403 return (result);
00404 return (put_txt(lookup, buf));
00405 }
00406
00407 if (ns_g_server->server_id == NULL)
00408 return (ISC_R_SUCCESS);
00409 else
00410 return (put_txt(lookup, ns_g_server->server_id));
00411 }
00412
00413 static isc_result_t
00414 do_dns64_lookup(dns_sdblookup_t *lookup) {
00415 UNUSED(lookup);
00416 return (ISC_R_SUCCESS);
00417 }
00418
00419 static isc_result_t
00420 do_empty_lookup(dns_sdblookup_t *lookup) {
00421
00422 UNUSED(lookup);
00423 return (ISC_R_SUCCESS);
00424 }
00425
00426 static isc_result_t
00427 builtin_authority(const char *zone, void *dbdata, dns_sdblookup_t *lookup) {
00428 isc_result_t result;
00429 const char *contact = "hostmaster";
00430 const char *server = "@";
00431 builtin_t *b = (builtin_t *) dbdata;
00432
00433 UNUSED(zone);
00434 UNUSED(dbdata);
00435
00436 if (b == &empty_builtin) {
00437 server = ".";
00438 contact = ".";
00439 } else {
00440 if (b->server != NULL)
00441 server = b->server;
00442 if (b->contact != NULL)
00443 contact = b->contact;
00444 }
00445
00446 result = dns_sdb_putsoa(lookup, server, contact, 0);
00447 if (result != ISC_R_SUCCESS)
00448 return (ISC_R_FAILURE);
00449
00450 result = dns_sdb_putrr(lookup, "ns", 0, server);
00451 if (result != ISC_R_SUCCESS)
00452 return (ISC_R_FAILURE);
00453
00454 return (ISC_R_SUCCESS);
00455 }
00456
00457 static isc_result_t
00458 builtin_create(const char *zone, int argc, char **argv,
00459 void *driverdata, void **dbdata)
00460 {
00461 REQUIRE(argc >= 1);
00462
00463 UNUSED(zone);
00464 UNUSED(driverdata);
00465
00466 if (strcmp(argv[0], "empty") == 0 || strcmp(argv[0], "dns64") == 0) {
00467 if (argc != 3)
00468 return (DNS_R_SYNTAX);
00469 } else if (argc != 1)
00470 return (DNS_R_SYNTAX);
00471
00472 if (strcmp(argv[0], "version") == 0)
00473 *dbdata = &version_builtin;
00474 else if (strcmp(argv[0], "hostname") == 0)
00475 *dbdata = &hostname_builtin;
00476 else if (strcmp(argv[0], "authors") == 0)
00477 *dbdata = &authors_builtin;
00478 else if (strcmp(argv[0], "id") == 0)
00479 *dbdata = &id_builtin;
00480 else if (strcmp(argv[0], "empty") == 0 ||
00481 strcmp(argv[0], "dns64") == 0) {
00482 builtin_t *empty;
00483 char *server;
00484 char *contact;
00485
00486
00487
00488
00489 empty = isc_mem_get(ns_g_mctx, sizeof(*empty));
00490 server = isc_mem_strdup(ns_g_mctx, argv[1]);
00491 contact = isc_mem_strdup(ns_g_mctx, argv[2]);
00492 if (empty == NULL || server == NULL || contact == NULL) {
00493 if (strcmp(argv[0], "empty") == 0)
00494 *dbdata = &empty_builtin;
00495 else
00496 *dbdata = &dns64_builtin;
00497 if (server != NULL)
00498 isc_mem_free(ns_g_mctx, server);
00499 if (contact != NULL)
00500 isc_mem_free(ns_g_mctx, contact);
00501 if (empty != NULL)
00502 isc_mem_put(ns_g_mctx, empty, sizeof (*empty));
00503 } else {
00504 if (strcmp(argv[0], "empty") == 0)
00505 memmove(empty, &empty_builtin,
00506 sizeof (empty_builtin));
00507 else
00508 memmove(empty, &dns64_builtin,
00509 sizeof (empty_builtin));
00510 empty->server = server;
00511 empty->contact = contact;
00512 *dbdata = empty;
00513 }
00514 } else
00515 return (ISC_R_NOTIMPLEMENTED);
00516 return (ISC_R_SUCCESS);
00517 }
00518
00519 static void
00520 builtin_destroy(const char *zone, void *driverdata, void **dbdata) {
00521 builtin_t *b = (builtin_t *) *dbdata;
00522
00523 UNUSED(zone);
00524 UNUSED(driverdata);
00525
00526
00527
00528
00529 if (*dbdata == &version_builtin || *dbdata == &hostname_builtin ||
00530 *dbdata == &authors_builtin || *dbdata == &id_builtin ||
00531 *dbdata == &empty_builtin || *dbdata == &dns64_builtin)
00532 return;
00533
00534 isc_mem_free(ns_g_mctx, b->server);
00535 isc_mem_free(ns_g_mctx, b->contact);
00536 isc_mem_put(ns_g_mctx, b, sizeof (*b));
00537 }
00538
00539 static dns_sdbmethods_t builtin_methods = {
00540 builtin_lookup,
00541 builtin_authority,
00542 NULL,
00543 builtin_create,
00544 builtin_destroy,
00545 NULL
00546 };
00547
00548 static dns_sdbmethods_t dns64_methods = {
00549 NULL,
00550 builtin_authority,
00551 NULL,
00552 builtin_create,
00553 builtin_destroy,
00554 dns64_lookup,
00555 };
00556
00557 isc_result_t
00558 ns_builtin_init(void) {
00559 RUNTIME_CHECK(dns_sdb_register("_builtin", &builtin_methods, NULL,
00560 DNS_SDBFLAG_RELATIVEOWNER |
00561 DNS_SDBFLAG_RELATIVERDATA,
00562 ns_g_mctx, &builtin_impl)
00563 == ISC_R_SUCCESS);
00564 RUNTIME_CHECK(dns_sdb_register("_dns64", &dns64_methods, NULL,
00565 DNS_SDBFLAG_RELATIVEOWNER |
00566 DNS_SDBFLAG_RELATIVERDATA |
00567 DNS_SDBFLAG_DNS64,
00568 ns_g_mctx, &dns64_impl)
00569 == ISC_R_SUCCESS);
00570 return (ISC_R_SUCCESS);
00571 }
00572
00573 void
00574 ns_builtin_deinit(void) {
00575 dns_sdb_unregister(&builtin_impl);
00576 dns_sdb_unregister(&dns64_impl);
00577 }