Remove building with NOCRYPTO option
[minix.git] / external / bsd / bind / dist / bin / named / builtin.c
blob6393592349a768a78bc6dcf614cde37cd23daff1
1 /* $NetBSD: builtin.c,v 1.8 2014/12/10 04:37:51 christos Exp $ */
3 /*
4 * Copyright (C) 2004, 2005, 2007, 2009-2014 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 2001-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: builtin.c,v 1.26 2012/01/21 19:44:18 each Exp */
22 /*! \file
23 * \brief
24 * The built-in "version", "hostname", "id", "authors" and "empty" databases.
27 #include <config.h>
29 #include <string.h>
30 #include <stdio.h>
32 #include <isc/mem.h>
33 #include <isc/print.h>
34 #include <isc/result.h>
35 #include <isc/util.h>
37 #include <dns/result.h>
38 #include <dns/sdb.h>
40 #include <named/builtin.h>
41 #include <named/globals.h>
42 #include <named/server.h>
43 #include <named/os.h>
45 typedef struct builtin builtin_t;
47 static isc_result_t do_version_lookup(dns_sdblookup_t *lookup);
48 static isc_result_t do_hostname_lookup(dns_sdblookup_t *lookup);
49 static isc_result_t do_authors_lookup(dns_sdblookup_t *lookup);
50 static isc_result_t do_id_lookup(dns_sdblookup_t *lookup);
51 static isc_result_t do_empty_lookup(dns_sdblookup_t *lookup);
52 static isc_result_t do_dns64_lookup(dns_sdblookup_t *lookup);
55 * We can't use function pointers as the db_data directly
56 * because ANSI C does not guarantee that function pointers
57 * can safely be cast to void pointers and back.
60 struct builtin {
61 isc_result_t (*do_lookup)(dns_sdblookup_t *lookup);
62 char *server;
63 char *contact;
66 static builtin_t version_builtin = { do_version_lookup, NULL, NULL };
67 static builtin_t hostname_builtin = { do_hostname_lookup, NULL, NULL };
68 static builtin_t authors_builtin = { do_authors_lookup, NULL, NULL };
69 static builtin_t id_builtin = { do_id_lookup, NULL, NULL };
70 static builtin_t empty_builtin = { do_empty_lookup, NULL, NULL };
71 static builtin_t dns64_builtin = { do_dns64_lookup, NULL, NULL };
73 static dns_sdbimplementation_t *builtin_impl;
74 static dns_sdbimplementation_t *dns64_impl;
77 * Pre computed HEX * 16 or 1 table.
79 static const unsigned char hex16[256] = {
80 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*00*/
81 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*10*/
82 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*20*/
83 0, 16, 32, 48, 64, 80, 96,112,128,144, 1, 1, 1, 1, 1, 1, /*30*/
84 1,160,176,192,208,224,240, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*40*/
85 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*50*/
86 1,160,176,192,208,224,240, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*60*/
87 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*70*/
88 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*80*/
89 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*90*/
90 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*A0*/
91 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*B0*/
92 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*C0*/
93 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*D0*/
94 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*E0*/
95 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 /*F0*/
98 const unsigned char decimal[] = "0123456789";
100 static size_t
101 dns64_rdata(unsigned char *v, size_t start, unsigned char *rdata) {
102 size_t i, j = 0;
104 for (i = 0; i < 4U; i++) {
105 unsigned char c = v[start++];
106 if (start == 7U)
107 start++;
108 if (c > 99) {
109 rdata[j++] = 3;
110 rdata[j++] = decimal[c/100]; c = c % 100;
111 rdata[j++] = decimal[c/10]; c = c % 10;
112 rdata[j++] = decimal[c];
113 } else if (c > 9) {
114 rdata[j++] = 2;
115 rdata[j++] = decimal[c/10]; c = c % 10;
116 rdata[j++] = decimal[c];
117 } else {
118 rdata[j++] = 1;
119 rdata[j++] = decimal[c];
122 memmove(&rdata[j], "\07in-addr\04arpa", 14);
123 return (j + 14);
126 static isc_result_t
127 dns64_cname(const dns_name_t *zone, const dns_name_t *name,
128 dns_sdblookup_t *lookup)
130 size_t zlen, nlen, j, len;
131 unsigned char v[16], n;
132 unsigned int i;
133 unsigned char rdata[sizeof("123.123.123.123.in-addr.arpa.")];
134 unsigned char *ndata;
137 * The combined length of the zone and name is 74.
139 * The minimum zone length is 10 ((3)ip6(4)arpa(0)).
141 * The length of name should always be even as we are expecting
142 * a series of nibbles.
144 zlen = zone->length;
145 nlen = name->length;
146 if ((zlen + nlen) > 74U || zlen < 10U || (nlen % 2) != 0U)
147 return (ISC_R_NOTFOUND);
150 * We assume the zone name is well formed.
154 * XXXMPA We could check the dns64 suffix here if we need to.
157 * Check that name is a series of nibbles.
158 * Compute the byte values that correspond to the nibbles as we go.
160 * Shift the final result 4 bits, by setting 'i' to 1, if we if we
161 * have a odd number of nibbles so that "must be zero" tests below
162 * are byte aligned and we correctly return ISC_R_NOTFOUND or
163 * ISC_R_SUCCESS. We will not generate a CNAME in this case.
165 ndata = name->ndata;
166 i = (nlen % 4) == 2U ? 1 : 0;
167 j = nlen;
168 memset(v, 0, sizeof(v));
169 while (j != 0U) {
170 INSIST((i/2) < sizeof(v));
171 if (ndata[0] != 1)
172 return (ISC_R_NOTFOUND);
173 n = hex16[ndata[1]&0xff];
174 if (n == 1)
175 return (ISC_R_NOTFOUND);
176 v[i/2] = n | (v[i/2]>>4);
177 j -= 2;
178 ndata += 2;
179 i++;
183 * If we get here then we know name only consisted of nibbles.
184 * Now we need to determine if the name exists or not and whether
185 * it corresponds to a empty node in the zone or there should be
186 * a CNAME.
188 #define ZLEN(x) (10 + (x)/2)
189 switch (zlen) {
190 case ZLEN(32): /* prefix len 32 */
192 * The nibbles that map to this byte must be zero for 'name'
193 * to exist in the zone.
195 if (nlen > 16U && v[(nlen-1)/4 - 4] != 0)
196 return (ISC_R_NOTFOUND);
198 * If the total length is not 74 then this is a empty node
199 * so return success.
201 if (nlen + zlen != 74U)
202 return (ISC_R_SUCCESS);
203 len = dns64_rdata(v, 8, rdata);
204 break;
205 case ZLEN(40): /* prefix len 40 */
207 * The nibbles that map to this byte must be zero for 'name'
208 * to exist in the zone.
210 if (nlen > 12U && v[(nlen-1)/4 - 3] != 0)
211 return (ISC_R_NOTFOUND);
213 * If the total length is not 74 then this is a empty node
214 * so return success.
216 if (nlen + zlen != 74U)
217 return (ISC_R_SUCCESS);
218 len = dns64_rdata(v, 6, rdata);
219 break;
220 case ZLEN(48): /* prefix len 48 */
222 * The nibbles that map to this byte must be zero for 'name'
223 * to exist in the zone.
225 if (nlen > 8U && v[(nlen-1)/4 - 2] != 0)
226 return (ISC_R_NOTFOUND);
228 * If the total length is not 74 then this is a empty node
229 * so return success.
231 if (nlen + zlen != 74U)
232 return (ISC_R_SUCCESS);
233 len = dns64_rdata(v, 5, rdata);
234 break;
235 case ZLEN(56): /* prefix len 56 */
237 * The nibbles that map to this byte must be zero for 'name'
238 * to exist in the zone.
240 if (nlen > 4U && v[(nlen-1)/4 - 1] != 0)
241 return (ISC_R_NOTFOUND);
243 * If the total length is not 74 then this is a empty node
244 * so return success.
246 if (nlen + zlen != 74U)
247 return (ISC_R_SUCCESS);
248 len = dns64_rdata(v, 4, rdata);
249 break;
250 case ZLEN(64): /* prefix len 64 */
252 * The nibbles that map to this byte must be zero for 'name'
253 * to exist in the zone.
255 if (v[(nlen-1)/4] != 0)
256 return (ISC_R_NOTFOUND);
258 * If the total length is not 74 then this is a empty node
259 * so return success.
261 if (nlen + zlen != 74U)
262 return (ISC_R_SUCCESS);
263 len = dns64_rdata(v, 3, rdata);
264 break;
265 case ZLEN(96): /* prefix len 96 */
267 * If the total length is not 74 then this is a empty node
268 * so return success.
270 if (nlen + zlen != 74U)
271 return (ISC_R_SUCCESS);
272 len = dns64_rdata(v, 0, rdata);
273 break;
274 default:
276 * This should never be reached unless someone adds a
277 * zone declaration with this internal type to named.conf.
279 return (ISC_R_NOTFOUND);
281 return (dns_sdb_putrdata(lookup, dns_rdatatype_cname, 600,
282 rdata, (unsigned int)len));
285 static isc_result_t
286 builtin_lookup(const char *zone, const char *name, void *dbdata,
287 dns_sdblookup_t *lookup, dns_clientinfomethods_t *methods,
288 dns_clientinfo_t *clientinfo)
290 builtin_t *b = (builtin_t *) dbdata;
292 UNUSED(zone);
293 UNUSED(methods);
294 UNUSED(clientinfo);
296 if (strcmp(name, "@") == 0)
297 return (b->do_lookup(lookup));
298 else
299 return (ISC_R_NOTFOUND);
302 static isc_result_t
303 dns64_lookup(const dns_name_t *zone, const dns_name_t *name, void *dbdata,
304 dns_sdblookup_t *lookup, dns_clientinfomethods_t *methods,
305 dns_clientinfo_t *clientinfo)
307 builtin_t *b = (builtin_t *) dbdata;
309 UNUSED(methods);
310 UNUSED(clientinfo);
312 if (name->labels == 0 && name->length == 0)
313 return (b->do_lookup(lookup));
314 else
315 return (dns64_cname(zone, name, lookup));
318 static isc_result_t
319 put_txt(dns_sdblookup_t *lookup, const char *text) {
320 unsigned char buf[256];
321 unsigned int len = strlen(text);
322 if (len > 255)
323 len = 255; /* Silently truncate */
324 buf[0] = len;
325 memmove(&buf[1], text, len);
326 return (dns_sdb_putrdata(lookup, dns_rdatatype_txt, 0, buf, len + 1));
329 static isc_result_t
330 do_version_lookup(dns_sdblookup_t *lookup) {
331 if (ns_g_server->version_set) {
332 if (ns_g_server->version == NULL)
333 return (ISC_R_SUCCESS);
334 else
335 return (put_txt(lookup, ns_g_server->version));
336 } else {
337 return (put_txt(lookup, ns_g_version));
341 static isc_result_t
342 do_hostname_lookup(dns_sdblookup_t *lookup) {
343 if (ns_g_server->hostname_set) {
344 if (ns_g_server->hostname == NULL)
345 return (ISC_R_SUCCESS);
346 else
347 return (put_txt(lookup, ns_g_server->hostname));
348 } else {
349 char buf[256];
350 isc_result_t result = ns_os_gethostname(buf, sizeof(buf));
351 if (result != ISC_R_SUCCESS)
352 return (result);
353 return (put_txt(lookup, buf));
357 static isc_result_t
358 do_authors_lookup(dns_sdblookup_t *lookup) {
359 isc_result_t result;
360 const char **p;
361 static const char *authors[] = {
362 "Mark Andrews",
363 "Curtis Blackburn",
364 "James Brister",
365 "Ben Cottrell",
366 "John H. DuBois III",
367 "Francis Dupont",
368 "Michael Graff",
369 "Andreas Gustafsson",
370 "Bob Halley",
371 "Evan Hunt",
372 "JINMEI Tatuya",
373 "David Lawrence",
374 "Scott Mann",
375 "Danny Mayer",
376 "Damien Neil",
377 "Matt Nelson",
378 "Jeremy C. Reed",
379 "Michael Sawyer",
380 "Brian Wellington",
381 NULL
385 * If a version string is specified, disable the authors.bind zone.
387 if (ns_g_server->version_set)
388 return (ISC_R_SUCCESS);
390 for (p = authors; *p != NULL; p++) {
391 result = put_txt(lookup, *p);
392 if (result != ISC_R_SUCCESS)
393 return (result);
395 return (ISC_R_SUCCESS);
398 static isc_result_t
399 do_id_lookup(dns_sdblookup_t *lookup) {
401 if (ns_g_server->server_usehostname) {
402 char buf[256];
403 isc_result_t result = ns_os_gethostname(buf, sizeof(buf));
404 if (result != ISC_R_SUCCESS)
405 return (result);
406 return (put_txt(lookup, buf));
409 if (ns_g_server->server_id == NULL)
410 return (ISC_R_SUCCESS);
411 else
412 return (put_txt(lookup, ns_g_server->server_id));
415 static isc_result_t
416 do_dns64_lookup(dns_sdblookup_t *lookup) {
417 UNUSED(lookup);
418 return (ISC_R_SUCCESS);
421 static isc_result_t
422 do_empty_lookup(dns_sdblookup_t *lookup) {
424 UNUSED(lookup);
425 return (ISC_R_SUCCESS);
428 static isc_result_t
429 builtin_authority(const char *zone, void *dbdata, dns_sdblookup_t *lookup) {
430 isc_result_t result;
431 const char *contact = "hostmaster";
432 const char *server = "@";
433 builtin_t *b = (builtin_t *) dbdata;
435 UNUSED(zone);
436 UNUSED(dbdata);
438 if (b == &empty_builtin) {
439 server = ".";
440 contact = ".";
441 } else {
442 if (b->server != NULL)
443 server = b->server;
444 if (b->contact != NULL)
445 contact = b->contact;
448 result = dns_sdb_putsoa(lookup, server, contact, 0);
449 if (result != ISC_R_SUCCESS)
450 return (ISC_R_FAILURE);
452 result = dns_sdb_putrr(lookup, "ns", 0, server);
453 if (result != ISC_R_SUCCESS)
454 return (ISC_R_FAILURE);
456 return (ISC_R_SUCCESS);
459 static isc_result_t
460 builtin_create(const char *zone, int argc, char **argv,
461 void *driverdata, void **dbdata)
463 REQUIRE(argc >= 1);
465 UNUSED(zone);
466 UNUSED(driverdata);
468 if (strcmp(argv[0], "empty") == 0 || strcmp(argv[0], "dns64") == 0) {
469 if (argc != 3)
470 return (DNS_R_SYNTAX);
471 } else if (argc != 1)
472 return (DNS_R_SYNTAX);
474 if (strcmp(argv[0], "version") == 0)
475 *dbdata = &version_builtin;
476 else if (strcmp(argv[0], "hostname") == 0)
477 *dbdata = &hostname_builtin;
478 else if (strcmp(argv[0], "authors") == 0)
479 *dbdata = &authors_builtin;
480 else if (strcmp(argv[0], "id") == 0)
481 *dbdata = &id_builtin;
482 else if (strcmp(argv[0], "empty") == 0 ||
483 strcmp(argv[0], "dns64") == 0) {
484 builtin_t *empty;
485 char *server;
486 char *contact;
488 * We don't want built-in zones to fail. Fallback to
489 * the static configuration if memory allocation fails.
491 empty = isc_mem_get(ns_g_mctx, sizeof(*empty));
492 server = isc_mem_strdup(ns_g_mctx, argv[1]);
493 contact = isc_mem_strdup(ns_g_mctx, argv[2]);
494 if (empty == NULL || server == NULL || contact == NULL) {
495 if (strcmp(argv[0], "empty") == 0)
496 *dbdata = &empty_builtin;
497 else
498 *dbdata = &dns64_builtin;
499 if (server != NULL)
500 isc_mem_free(ns_g_mctx, server);
501 if (contact != NULL)
502 isc_mem_free(ns_g_mctx, contact);
503 if (empty != NULL)
504 isc_mem_put(ns_g_mctx, empty, sizeof (*empty));
505 } else {
506 if (strcmp(argv[0], "empty") == 0)
507 memmove(empty, &empty_builtin,
508 sizeof (empty_builtin));
509 else
510 memmove(empty, &dns64_builtin,
511 sizeof (empty_builtin));
512 empty->server = server;
513 empty->contact = contact;
514 *dbdata = empty;
516 } else
517 return (ISC_R_NOTIMPLEMENTED);
518 return (ISC_R_SUCCESS);
521 static void
522 builtin_destroy(const char *zone, void *driverdata, void **dbdata) {
523 builtin_t *b = (builtin_t *) *dbdata;
525 UNUSED(zone);
526 UNUSED(driverdata);
529 * Don't free the static versions.
531 if (*dbdata == &version_builtin || *dbdata == &hostname_builtin ||
532 *dbdata == &authors_builtin || *dbdata == &id_builtin ||
533 *dbdata == &empty_builtin || *dbdata == &dns64_builtin)
534 return;
536 isc_mem_free(ns_g_mctx, b->server);
537 isc_mem_free(ns_g_mctx, b->contact);
538 isc_mem_put(ns_g_mctx, b, sizeof (*b));
541 static dns_sdbmethods_t builtin_methods = {
542 builtin_lookup,
543 builtin_authority,
544 NULL, /* allnodes */
545 builtin_create,
546 builtin_destroy,
547 NULL
550 static dns_sdbmethods_t dns64_methods = {
551 NULL,
552 builtin_authority,
553 NULL, /* allnodes */
554 builtin_create,
555 builtin_destroy,
556 dns64_lookup,
559 isc_result_t
560 ns_builtin_init(void) {
561 RUNTIME_CHECK(dns_sdb_register("_builtin", &builtin_methods, NULL,
562 DNS_SDBFLAG_RELATIVEOWNER |
563 DNS_SDBFLAG_RELATIVERDATA,
564 ns_g_mctx, &builtin_impl)
565 == ISC_R_SUCCESS);
566 RUNTIME_CHECK(dns_sdb_register("_dns64", &dns64_methods, NULL,
567 DNS_SDBFLAG_RELATIVEOWNER |
568 DNS_SDBFLAG_RELATIVERDATA |
569 DNS_SDBFLAG_DNS64,
570 ns_g_mctx, &dns64_impl)
571 == ISC_R_SUCCESS);
572 return (ISC_R_SUCCESS);
575 void
576 ns_builtin_deinit(void) {
577 dns_sdb_unregister(&builtin_impl);
578 dns_sdb_unregister(&dns64_impl);