xref: /minix/external/bsd/bind/dist/contrib/sdb/dir/dirdb.c (revision bb9622b5)
1 /*	$NetBSD: dirdb.c,v 1.4 2014/12/10 04:37:57 christos Exp $	*/
2 
3 /*
4  * Copyright (C) 2004, 2007, 2011, 2014  Internet Systems Consortium, Inc. ("ISC")
5  * Copyright (C) 2000, 2001  Internet Software Consortium.
6  *
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.
10  *
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.
18  */
19 
20 /* Id: dirdb.c,v 1.14 2011/10/11 23:46:45 tbox Exp  */
21 
22 /*
23  * A simple database driver that returns basic information about
24  * files and directories in the Unix file system as DNS data.
25  */
26 
27 #include <config.h>
28 
29 #include <stdio.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <sys/stat.h>
33 #include <sys/sysmacros.h>
34 
35 #include <isc/mem.h>
36 #include <isc/print.h>
37 #include <isc/result.h>
38 #include <isc/util.h>
39 
40 #include <dns/sdb.h>
41 
42 #include <named/globals.h>
43 
44 #include "dirdb.h"
45 
46 static dns_sdbimplementation_t *dirdb = NULL;
47 
48 #define CHECK(op)						\
49 	do { result = (op);					\
50 		if (result != ISC_R_SUCCESS) return (result);	\
51 	} while (/*CONSTCOND*/0)
52 
53 #define CHECKN(op)						\
54 	do { n = (op);						\
55 		if (n < 0) return (ISC_R_FAILURE);		\
56 	} while (/*CONSTCOND*/0)
57 
58 
59 /*
60  * This database operates on relative names.
61  *
62  * Any name will be interpreted as a pathname offset from the directory
63  * specified in the configuration file.
64  */
65 #ifdef DNS_CLIENTINFO_VERSION
66 static isc_result_t
67 dirdb_lookup(const char *zone, const char *name, void *dbdata,
68 	      dns_sdblookup_t *lookup, dns_clientinfomethods_t *methods,
69 	      dns_clientinfo_t *clientinfo)
70 #else
71 static isc_result_t
72 dirdb_lookup(const char *zone, const char *name, void *dbdata,
73 	      dns_sdblookup_t *lookup)
74 #endif /* DNS_CLIENTINFO_VERSION */
75 {
76 	char filename[255];
77 	char filename2[255];
78 	char buf[1024];
79 	struct stat statbuf;
80 	isc_result_t result;
81 	int n;
82 
83 	UNUSED(zone);
84 	UNUSED(dbdata);
85 #ifdef DNS_CLIENTINFO_VERSION
86 	UNUSED(methods);
87 	UNUSED(clientinfo);
88 #endif /* DNS_CLIENTINFO_VERSION */
89 
90 	if (strcmp(name, "@") == 0)
91 		snprintf(filename, sizeof(filename), "%s", (char *)dbdata);
92 	else
93 		snprintf(filename, sizeof(filename), "%s/%s",
94 			 (char *)dbdata, name);
95 	CHECKN(lstat(filename, &statbuf));
96 
97 	if (S_ISDIR(statbuf.st_mode))
98 		CHECK(dns_sdb_putrr(lookup, "txt", 3600, "dir"));
99 	else if (S_ISCHR(statbuf.st_mode) || S_ISBLK(statbuf.st_mode)) {
100 		CHECKN(snprintf(buf, sizeof(buf),
101 				"\"%sdev\" \"major %d\" \"minor %d\"",
102 				S_ISCHR(statbuf.st_mode) ? "chr" : "blk",
103 				major(statbuf.st_rdev),
104 				minor(statbuf.st_rdev)));
105 		CHECK(dns_sdb_putrr(lookup, "txt", 3600, buf));
106 	} else if (S_ISFIFO(statbuf.st_mode))
107 		CHECK(dns_sdb_putrr(lookup, "txt", 3600, "pipe"));
108 	else if (S_ISSOCK(statbuf.st_mode))
109 		CHECK(dns_sdb_putrr(lookup, "txt", 3600, "socket"));
110 	else if (S_ISLNK(statbuf.st_mode)) {
111 		CHECKN(readlink(filename, filename2, sizeof(filename2) - 1));
112 		buf[n] = 0;
113 		CHECKN(snprintf(buf, sizeof(buf), "\"symlink\" \"%s\"",
114 				filename2));
115 		CHECK(dns_sdb_putrr(lookup, "txt", 3600, buf));
116 	} else if (!S_ISREG(statbuf.st_mode))
117 		CHECK(dns_sdb_putrr(lookup, "txt", 3600, "unknown"));
118 	else {
119 		CHECKN(snprintf(buf, sizeof(buf), "\"file\" \"size = %u\"",
120 			 (unsigned int)statbuf.st_size));
121 		CHECK(dns_sdb_putrr(lookup, "txt", 3600, buf));
122 	}
123 
124 	return (ISC_R_SUCCESS);
125 }
126 
127 /*
128  * lookup () does not return SOA or NS records, so authority() must be defined.
129  */
130 static isc_result_t
131 dirdb_authority(const char *zone, void *dbdata, dns_sdblookup_t *lookup) {
132 	isc_result_t result;
133 
134 	UNUSED(zone);
135 	UNUSED(dbdata);
136 
137 	result = dns_sdb_putsoa(lookup, "ns", "hostmaster", 0);
138 	INSIST(result == ISC_R_SUCCESS);
139 	result = dns_sdb_putrr(lookup, "ns", 86400, "ns1");
140 	INSIST(result == ISC_R_SUCCESS);
141 	result = dns_sdb_putrr(lookup, "ns", 86400, "ns2");
142 	INSIST(result == ISC_R_SUCCESS);
143 	return (ISC_R_SUCCESS);
144 }
145 
146 /*
147  * Each database stores the top-level directory as the dbdata opaque
148  * object.  The create() function allocates it.  argv[0] holds the top
149  * level directory.
150  */
151 static isc_result_t
152 dirdb_create(const char *zone, int argc, char **argv,
153 	     void *driverdata, void **dbdata)
154 {
155 	UNUSED(zone);
156 	UNUSED(driverdata);
157 
158 	if (argc < 1)
159 		return (ISC_R_FAILURE);
160 	*dbdata = isc_mem_strdup((isc_mem_t *)driverdata, argv[0]);
161 	if (*dbdata == NULL)
162 		return (ISC_R_NOMEMORY);
163 	return (ISC_R_SUCCESS);
164 }
165 
166 /*
167  * The destroy() function frees the memory allocated by create().
168  */
169 static void
170 dirdb_destroy(const char *zone, void *driverdata, void **dbdata) {
171 	UNUSED(zone);
172 	UNUSED(driverdata);
173 	isc_mem_free((isc_mem_t *)driverdata, *dbdata);
174 }
175 
176 /*
177  * This zone does not support zone transfer, so allnodes() is NULL.
178  */
179 static dns_sdbmethods_t dirdb_methods = {
180 	dirdb_lookup,
181 	dirdb_authority,
182 	NULL, /* allnodes */
183 	dirdb_create,
184 	dirdb_destroy,
185 	NULL /* lookup2 */
186 };
187 
188 /*
189  * Wrapper around dns_sdb_register().  Note that the first ns_g_mctx is
190  * being passed as the "driverdata" parameter, so that will it will be
191  * passed to create() and destroy().
192  */
193 isc_result_t
194 dirdb_init(void) {
195 	unsigned int flags;
196 	flags = DNS_SDBFLAG_RELATIVEOWNER | DNS_SDBFLAG_RELATIVERDATA |
197 		DNS_SDBFLAG_THREADSAFE;
198 	return (dns_sdb_register("dir", &dirdb_methods, ns_g_mctx, flags,
199 				 ns_g_mctx, &dirdb));
200 }
201 
202 /*
203  * Wrapper around dns_sdb_unregister().
204  */
205 void
206 dirdb_clear(void) {
207 	if (dirdb != NULL)
208 		dns_sdb_unregister(&dirdb);
209 }
210