bind - Upgraded vendor branch to 9.5.2-P1
[dragonfly.git] / contrib / bind-9.5.2 / bin / named / builtin.c
1 /*
2  * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 2001-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 /* $Id: builtin.c,v 1.12 2007/06/19 23:46:59 tbox Exp $ */
19
20 /*! \file
21  * \brief
22  * The built-in "version", "hostname", "id", "authors" and "empty" databases.
23  */
24
25 #include <config.h>
26
27 #include <string.h>
28 #include <stdio.h>
29
30 #include <isc/mem.h>
31 #include <isc/print.h>
32 #include <isc/result.h>
33 #include <isc/util.h>
34
35 #include <dns/result.h>
36 #include <dns/sdb.h>
37
38 #include <named/builtin.h>
39 #include <named/globals.h>
40 #include <named/server.h>
41 #include <named/os.h>
42
43 typedef struct builtin builtin_t;
44
45 static isc_result_t do_version_lookup(dns_sdblookup_t *lookup);
46 static isc_result_t do_hostname_lookup(dns_sdblookup_t *lookup);
47 static isc_result_t do_authors_lookup(dns_sdblookup_t *lookup);
48 static isc_result_t do_id_lookup(dns_sdblookup_t *lookup);
49 static isc_result_t do_empty_lookup(dns_sdblookup_t *lookup);
50
51 /*
52  * We can't use function pointers as the db_data directly
53  * because ANSI C does not guarantee that function pointers
54  * can safely be cast to void pointers and back.
55  */
56
57 struct builtin {
58         isc_result_t (*do_lookup)(dns_sdblookup_t *lookup);
59         char *server;
60         char *contact;
61 };
62
63 static builtin_t version_builtin = { do_version_lookup,  NULL, NULL };
64 static builtin_t hostname_builtin = { do_hostname_lookup, NULL, NULL };
65 static builtin_t authors_builtin = { do_authors_lookup, NULL, NULL };
66 static builtin_t id_builtin = { do_id_lookup, NULL, NULL };
67 static builtin_t empty_builtin = { do_empty_lookup, NULL, NULL };
68
69 static dns_sdbimplementation_t *builtin_impl;
70
71 static isc_result_t
72 builtin_lookup(const char *zone, const char *name, void *dbdata,
73                dns_sdblookup_t *lookup)
74 {
75         builtin_t *b = (builtin_t *) dbdata;
76
77         UNUSED(zone);
78
79         if (strcmp(name, "@") == 0)
80                 return (b->do_lookup(lookup));
81         else
82                 return (ISC_R_NOTFOUND);
83 }
84
85 static isc_result_t
86 put_txt(dns_sdblookup_t *lookup, const char *text) {
87         unsigned char buf[256];
88         unsigned int len = strlen(text);
89         if (len > 255)
90                 len = 255; /* Silently truncate */
91         buf[0] = len;
92         memcpy(&buf[1], text, len);
93         return (dns_sdb_putrdata(lookup, dns_rdatatype_txt, 0, buf, len + 1));
94 }
95
96 static isc_result_t
97 do_version_lookup(dns_sdblookup_t *lookup) {
98         if (ns_g_server->version_set) { 
99                 if (ns_g_server->version == NULL)
100                         return (ISC_R_SUCCESS);
101                 else
102                         return (put_txt(lookup, ns_g_server->version));
103         } else {
104                 return (put_txt(lookup, ns_g_version));
105         }
106 }
107
108 static isc_result_t
109 do_hostname_lookup(dns_sdblookup_t *lookup) {
110         if (ns_g_server->hostname_set) {
111                 if (ns_g_server->hostname == NULL)
112                         return (ISC_R_SUCCESS);
113                 else
114                         return (put_txt(lookup, ns_g_server->hostname));
115         } else {
116                 char buf[256];
117                 isc_result_t result = ns_os_gethostname(buf, sizeof(buf));
118                 if (result != ISC_R_SUCCESS)
119                         return (result);
120                 return (put_txt(lookup, buf));
121         }
122 }
123
124 static isc_result_t
125 do_authors_lookup(dns_sdblookup_t *lookup) {
126         isc_result_t result;
127         const char **p;
128         static const char *authors[] = {
129                 "Mark Andrews",
130                 "James Brister",
131                 "Ben Cottrell",
132                 "Michael Graff",
133                 "Andreas Gustafsson",
134                 "Bob Halley",
135                 "David Lawrence",
136                 "Danny Mayer",
137                 "Damien Neil",
138                 "Matt Nelson",
139                 "Michael Sawyer",
140                 "Brian Wellington",
141                 NULL
142         };
143
144         /*
145          * If a version string is specified, disable the authors.bind zone.
146          */
147         if (ns_g_server->version_set)
148                 return (ISC_R_SUCCESS);
149
150         for (p = authors; *p != NULL; p++) {
151                 result = put_txt(lookup, *p);
152                 if (result != ISC_R_SUCCESS)
153                         return (result);
154         }
155         return (ISC_R_SUCCESS);
156 }
157
158 static isc_result_t
159 do_id_lookup(dns_sdblookup_t *lookup) {
160
161         if (ns_g_server->server_usehostname) {
162                 char buf[256];
163                 isc_result_t result = ns_os_gethostname(buf, sizeof(buf));
164                 if (result != ISC_R_SUCCESS)
165                         return (result);
166                 return (put_txt(lookup, buf));
167         }
168
169         if (ns_g_server->server_id == NULL)
170                 return (ISC_R_SUCCESS);
171         else
172                 return (put_txt(lookup, ns_g_server->server_id));
173 }
174
175 static isc_result_t
176 do_empty_lookup(dns_sdblookup_t *lookup) {
177
178         UNUSED(lookup);
179         return (ISC_R_SUCCESS);
180 }
181
182 static isc_result_t
183 builtin_authority(const char *zone, void *dbdata, dns_sdblookup_t *lookup) {
184         isc_result_t result;
185         const char *contact = "hostmaster";
186         const char *server = "@";
187         builtin_t *b = (builtin_t *) dbdata;
188
189         UNUSED(zone);
190         UNUSED(dbdata);
191
192         if (b == &empty_builtin) {
193                 server = ".";
194                 contact = ".";
195         } else {
196                 if (b->server != NULL)
197                         server = b->server;
198                 if (b->contact != NULL)
199                         contact = b->contact;
200         }
201         
202         result = dns_sdb_putsoa(lookup, server, contact, 0);
203         if (result != ISC_R_SUCCESS)
204                 return (ISC_R_FAILURE);
205
206         result = dns_sdb_putrr(lookup, "ns", 0, server);
207         if (result != ISC_R_SUCCESS)
208                 return (ISC_R_FAILURE);
209
210         return (ISC_R_SUCCESS);
211 }
212
213 static isc_result_t
214 builtin_create(const char *zone, int argc, char **argv,
215                void *driverdata, void **dbdata)
216 {
217         REQUIRE(argc >= 1);
218
219         UNUSED(zone);
220         UNUSED(driverdata);
221
222         if (strcmp(argv[0], "empty") == 0) {
223                 if (argc != 3)
224                         return (DNS_R_SYNTAX);
225         } else if (argc != 1)
226                 return (DNS_R_SYNTAX);
227
228         if (strcmp(argv[0], "version") == 0)
229                 *dbdata = &version_builtin;
230         else if (strcmp(argv[0], "hostname") == 0)
231                 *dbdata = &hostname_builtin;
232         else if (strcmp(argv[0], "authors") == 0)
233                 *dbdata = &authors_builtin;
234         else if (strcmp(argv[0], "id") == 0)
235                 *dbdata = &id_builtin;
236         else if (strcmp(argv[0], "empty") == 0) { 
237                 builtin_t *empty;
238                 char *server;
239                 char *contact;
240                 /*
241                  * We don't want built-in zones to fail.  Fallback to
242                  * the static configuration if memory allocation fails.
243                  */
244                 empty = isc_mem_get(ns_g_mctx, sizeof(*empty));
245                 server = isc_mem_strdup(ns_g_mctx, argv[1]);
246                 contact = isc_mem_strdup(ns_g_mctx, argv[2]);
247                 if (empty == NULL || server == NULL || contact == NULL) {
248                         *dbdata = &empty_builtin;
249                         if (server != NULL)
250                                 isc_mem_free(ns_g_mctx, server);
251                         if (contact != NULL)
252                                 isc_mem_free(ns_g_mctx, contact);
253                         if (empty != NULL)
254                                 isc_mem_put(ns_g_mctx, empty, sizeof (*empty));
255                 } else {
256                         memcpy(empty, &empty_builtin, sizeof (empty_builtin));
257                         empty->server = server;
258                         empty->contact = contact;
259                         *dbdata = empty;
260                 }
261         } else
262                 return (ISC_R_NOTIMPLEMENTED);
263         return (ISC_R_SUCCESS);
264 }
265
266 static void
267 builtin_destroy(const char *zone, void *driverdata, void **dbdata) {
268         builtin_t *b = (builtin_t *) *dbdata;
269
270         UNUSED(zone);
271         UNUSED(driverdata);
272
273         /*
274          * Don't free the static versions.
275          */
276         if (*dbdata == &version_builtin || *dbdata == &hostname_builtin ||
277             *dbdata == &authors_builtin || *dbdata == &id_builtin ||
278             *dbdata == &empty_builtin)
279                 return;
280
281         isc_mem_free(ns_g_mctx, b->server);
282         isc_mem_free(ns_g_mctx, b->contact);
283         isc_mem_put(ns_g_mctx, b, sizeof (*b));
284 }
285
286 static dns_sdbmethods_t builtin_methods = {
287         builtin_lookup,
288         builtin_authority,
289         NULL,           /* allnodes */
290         builtin_create,
291         builtin_destroy
292 };
293
294 isc_result_t
295 ns_builtin_init(void) {
296         RUNTIME_CHECK(dns_sdb_register("_builtin", &builtin_methods, NULL,
297                                        DNS_SDBFLAG_RELATIVEOWNER |
298                                        DNS_SDBFLAG_RELATIVERDATA,
299                                        ns_g_mctx, &builtin_impl)
300                       == ISC_R_SUCCESS);
301         return (ISC_R_SUCCESS);
302 }
303
304 void
305 ns_builtin_deinit(void) {
306         dns_sdb_unregister(&builtin_impl);
307 }