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