xref: /freebsd-13-stable/libexec/bootpd/dumptab.c (revision 04866ffa491cca6ed1cc0916965aaa5932d72b3b)
1 /*
2  * dumptab.c - handles dumping the database
3  */
4 
5 #include <sys/types.h>
6 #include <netinet/in.h>
7 #include <arpa/inet.h>			/* inet_ntoa */
8 
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <strings.h>
12 #include <syslog.h>
13 #include <time.h>
14 
15 #include "bootp.h"
16 #include "hash.h"
17 #include "hwaddr.h"
18 #include "report.h"
19 #include "patchlevel.h"
20 #include "bootpd.h"
21 
22 #ifdef DEBUG
23 static void dump_generic(FILE *, struct shared_bindata *);
24 static void dump_host(FILE *, struct host *);
25 static void list_ipaddresses(FILE *, struct in_addr_list *);
26 #endif
27 
28 #ifndef	DEBUG
29 void
dumptab(filename)30 dumptab(filename)
31 	char *filename;
32 {
33 	report(LOG_INFO, "No dumptab support!");
34 }
35 
36 #else /* DEBUG */
37 
38 /*
39  * Dump the internal memory database to bootpd_dump.
40  */
41 
42 void
dumptab(filename)43 dumptab(filename)
44 	char *filename;
45 {
46 	int n;
47 	struct host *hp;
48 	FILE *fp;
49 	time_t t;
50 	/* Print symbols in alphabetical order for reader's convenience. */
51 	static char legend[] = "#\n# Legend:\t(see bootptab.5)\n\
52 #\tfirst field -- hostname (not indented)\n\
53 #\tbf -- bootfile\n\
54 #\tbs -- bootfile size in 512-octet blocks\n\
55 #\tcs -- cookie servers\n\
56 #\tdf -- dump file name\n\
57 #\tdn -- domain name\n\
58 #\tds -- domain name servers\n\
59 #\tef -- extension file\n\
60 #\tex -- exec file (YORK_EX_OPTION)\n\
61 #\tgw -- gateways\n\
62 #\tha -- hardware address\n\
63 #\thd -- home directory for bootfiles\n\
64 #\thn -- host name set for client\n\
65 #\tht -- hardware type\n\
66 #\tim -- impress servers\n\
67 #\tip -- host IP address\n\
68 #\tlg -- log servers\n\
69 #\tlp -- LPR servers\n\
70 #\tms -- message size\n\
71 #\tmw -- min wait (secs)\n\
72 #\tns -- IEN-116 name servers\n\
73 #\tnt -- NTP servers (RFC 1129)\n\
74 #\tra -- reply address override\n\
75 #\trl -- resource location protocol servers\n\
76 #\trp -- root path\n\
77 #\tsa -- boot server address\n\
78 #\tsm -- subnet mask\n\
79 #\tsw -- swap server\n\
80 #\ttc -- template host (points to similar host entry)\n\
81 #\ttd -- TFTP directory\n\
82 #\tto -- time offset (seconds)\n\
83 #\tts -- time servers\n\
84 #\tvm -- vendor magic number\n\
85 #\tyd -- YP (NIS) domain\n\
86 #\tys -- YP (NIS) servers\n\
87 #\tTn -- generic option tag n\n\
88 \n";
89 
90 	/*
91 	 * Open bootpd.dump file.
92 	 */
93 	if ((fp = fopen(filename, "w")) == NULL) {
94 		report(LOG_ERR, "error opening \"%s\": %s",
95 			   filename, get_errmsg());
96 		exit(1);
97 	}
98 	t = time(NULL);
99 	fprintf(fp, "\n# %s %s.%d\n", progname, VERSION, PATCHLEVEL);
100 	fprintf(fp, "# %s: dump of bootp server database.\n", filename);
101 	fprintf(fp, "# Dump taken %s", ctime(&t));
102 	fwrite(legend, 1, sizeof(legend) - 1, fp);
103 
104 	n = 0;
105 	for (hp = (struct host *) hash_FirstEntry(nmhashtable); hp != NULL;
106 		 hp = (struct host *) hash_NextEntry(nmhashtable)) {
107 		dump_host(fp, hp);
108 		fprintf(fp, "\n");
109 		n++;
110 	}
111 	fclose(fp);
112 
113 	report(LOG_INFO, "dumped %d entries to \"%s\".", n, filename);
114 }
115 
116 
117 
118 /*
119  * Dump all the available information on the host pointed to by "hp".
120  * The output is sent to the file pointed to by "fp".
121  */
122 
123 static void
dump_host(fp,hp)124 dump_host(fp, hp)
125 	FILE *fp;
126 	struct host *hp;
127 {
128 	/* Print symbols in alphabetical order for reader's convenience. */
129 	if (hp) {
130 		fprintf(fp, "%s:", (hp->hostname ?
131 							hp->hostname->string : "?"));
132 		if (hp->flags.bootfile) {
133 			fprintf(fp, "\\\n\t:bf=%s:", hp->bootfile->string);
134 		}
135 		if (hp->flags.bootsize) {
136 			fprintf(fp, "\\\n\t:bs=");
137 			if (hp->flags.bootsize_auto) {
138 				fprintf(fp, "auto:");
139 			} else {
140 				fprintf(fp, "%lu:", (u_long)hp->bootsize);
141 			}
142 		}
143 		if (hp->flags.cookie_server) {
144 			fprintf(fp, "\\\n\t:cs=");
145 			list_ipaddresses(fp, hp->cookie_server);
146 			fprintf(fp, ":");
147 		}
148 		if (hp->flags.dump_file) {
149 			fprintf(fp, "\\\n\t:df=%s:", hp->dump_file->string);
150 		}
151 		if (hp->flags.domain_name) {
152 			fprintf(fp, "\\\n\t:dn=%s:", hp->domain_name->string);
153 		}
154 		if (hp->flags.domain_server) {
155 			fprintf(fp, "\\\n\t:ds=");
156 			list_ipaddresses(fp, hp->domain_server);
157 			fprintf(fp, ":");
158 		}
159 		if (hp->flags.exten_file) {
160 			fprintf(fp, "\\\n\t:ef=%s:", hp->exten_file->string);
161 		}
162 		if (hp->flags.exec_file) {
163 			fprintf(fp, "\\\n\t:ex=%s:", hp->exec_file->string);
164 		}
165 		if (hp->flags.gateway) {
166 			fprintf(fp, "\\\n\t:gw=");
167 			list_ipaddresses(fp, hp->gateway);
168 			fprintf(fp, ":");
169 		}
170 		/* FdC: swap_server (see below) */
171 		if (hp->flags.homedir) {
172 			fprintf(fp, "\\\n\t:hd=%s:", hp->homedir->string);
173 		}
174 		/* FdC: dump_file (see above) */
175 		/* FdC: domain_name (see above) */
176 		/* FdC: root_path (see below) */
177 		if (hp->flags.name_switch && hp->flags.send_name) {
178 			fprintf(fp, "\\\n\t:hn:");
179 		}
180 		if (hp->flags.htype) {
181 			int hlen = haddrlength(hp->htype);
182 			fprintf(fp, "\\\n\t:ht=%u:", (unsigned) hp->htype);
183 			if (hp->flags.haddr) {
184 				fprintf(fp, "ha=\"%s\":",
185 						haddrtoa(hp->haddr, hlen));
186 			}
187 		}
188 		if (hp->flags.impress_server) {
189 			fprintf(fp, "\\\n\t:im=");
190 			list_ipaddresses(fp, hp->impress_server);
191 			fprintf(fp, ":");
192 		}
193 		/* NetBSD: swap_server (see below) */
194 		if (hp->flags.iaddr) {
195 			fprintf(fp, "\\\n\t:ip=%s:", inet_ntoa(hp->iaddr));
196 		}
197 		if (hp->flags.log_server) {
198 			fprintf(fp, "\\\n\t:lg=");
199 			list_ipaddresses(fp, hp->log_server);
200 			fprintf(fp, ":");
201 		}
202 		if (hp->flags.lpr_server) {
203 			fprintf(fp, "\\\n\t:lp=");
204 			list_ipaddresses(fp, hp->lpr_server);
205 			fprintf(fp, ":");
206 		}
207 		if (hp->flags.msg_size) {
208 			fprintf(fp, "\\\n\t:ms=%lu:", (u_long)hp->msg_size);
209 		}
210 		if (hp->flags.min_wait) {
211 			fprintf(fp, "\\\n\t:mw=%lu:", (u_long)hp->min_wait);
212 		}
213 		if (hp->flags.name_server) {
214 			fprintf(fp, "\\\n\t:ns=");
215 			list_ipaddresses(fp, hp->name_server);
216 			fprintf(fp, ":");
217 		}
218 		if (hp->flags.ntp_server) {
219 			fprintf(fp, "\\\n\t:nt=");
220 			list_ipaddresses(fp, hp->ntp_server);
221 			fprintf(fp, ":");
222 		}
223 		if (hp->flags.reply_addr) {
224 			fprintf(fp, "\\\n\t:ra=%s:", inet_ntoa(hp->reply_addr));
225 		}
226 		if (hp->flags.rlp_server) {
227 			fprintf(fp, "\\\n\t:rl=");
228 			list_ipaddresses(fp, hp->rlp_server);
229 			fprintf(fp, ":");
230 		}
231 		if (hp->flags.root_path) {
232 			fprintf(fp, "\\\n\t:rp=%s:", hp->root_path->string);
233 		}
234 		if (hp->flags.bootserver) {
235 			fprintf(fp, "\\\n\t:sa=%s:", inet_ntoa(hp->bootserver));
236 		}
237 		if (hp->flags.subnet_mask) {
238 			fprintf(fp, "\\\n\t:sm=%s:", inet_ntoa(hp->subnet_mask));
239 		}
240 		if (hp->flags.swap_server) {
241 			fprintf(fp, "\\\n\t:sw=%s:", inet_ntoa(hp->subnet_mask));
242 		}
243 		if (hp->flags.tftpdir) {
244 			fprintf(fp, "\\\n\t:td=%s:", hp->tftpdir->string);
245 		}
246 		/* NetBSD: rootpath (see above) */
247 		/* NetBSD: domainname (see above) */
248 		/* NetBSD: dumpfile (see above) */
249 		if (hp->flags.time_offset) {
250 			fprintf(fp, "\\\n\t:to=%ld:", (long)hp->time_offset);
251 		}
252 		if (hp->flags.time_server) {
253 			fprintf(fp, "\\\n\t:ts=");
254 			list_ipaddresses(fp, hp->time_server);
255 			fprintf(fp, ":");
256 		}
257 		if (hp->flags.vm_cookie) {
258 			fprintf(fp, "\\\n\t:vm=");
259 			if (!bcmp(hp->vm_cookie, vm_rfc1048, 4)) {
260 				fprintf(fp, "rfc1048:");
261 			} else if (!bcmp(hp->vm_cookie, vm_cmu, 4)) {
262 				fprintf(fp, "cmu:");
263 			} else {
264 				fprintf(fp, "%d.%d.%d.%d:",
265 						(int) ((hp->vm_cookie)[0]),
266 						(int) ((hp->vm_cookie)[1]),
267 						(int) ((hp->vm_cookie)[2]),
268 						(int) ((hp->vm_cookie)[3]));
269 			}
270 		}
271 		if (hp->flags.nis_domain) {
272 			fprintf(fp, "\\\n\t:yd=%s:",
273 					hp->nis_domain->string);
274 		}
275 		if (hp->flags.nis_server) {
276 			fprintf(fp, "\\\n\t:ys=");
277 			list_ipaddresses(fp, hp->nis_server);
278 			fprintf(fp, ":");
279 		}
280 		/*
281 		 * XXX - Add new tags here (or above,
282 		 * so they print in alphabetical order).
283 		 */
284 
285 		if (hp->flags.generic) {
286 			dump_generic(fp, hp->generic);
287 		}
288 	}
289 }
290 
291 
292 static void
dump_generic(fp,generic)293 dump_generic(fp, generic)
294 	FILE *fp;
295 	struct shared_bindata *generic;
296 {
297 	u_char *bp = generic->data;
298 	u_char *ep = bp + generic->length;
299 	u_char tag;
300 	int len;
301 
302 	while (bp < ep) {
303 		tag = *bp++;
304 		if (tag == TAG_PAD)
305 			continue;
306 		if (tag == TAG_END)
307 			return;
308 		len = *bp++;
309 		if (bp + len > ep) {
310 			fprintf(fp, " #junk in generic! :");
311 			return;
312 		}
313 		fprintf(fp, "\\\n\t:T%d=", tag);
314 		while (len) {
315 			fprintf(fp, "%02X", *bp);
316 			bp++;
317 			len--;
318 			if (len)
319 				fprintf(fp, ".");
320 		}
321 		fprintf(fp, ":");
322 	}
323 }
324 
325 
326 
327 /*
328  * Dump an entire struct in_addr_list of IP addresses to the indicated file.
329  *
330  * The addresses are printed in standard ASCII "dot" notation and separated
331  * from one another by a single space.  A single leading space is also
332  * printed before the first address.
333  *
334  * Null lists produce no output (and no error).
335  */
336 
337 static void
list_ipaddresses(fp,ipptr)338 list_ipaddresses(fp, ipptr)
339 	FILE *fp;
340 	struct in_addr_list *ipptr;
341 {
342 	unsigned count;
343 	struct in_addr *addrptr;
344 
345 	if (ipptr) {
346 		count = ipptr->addrcount;
347 		addrptr = ipptr->addr;
348 		while (count > 0) {
349 			fprintf(fp, "%s", inet_ntoa(*addrptr++));
350 			count--;
351 			if (count)
352 				fprintf(fp, ", ");
353 		}
354 	}
355 }
356 
357 #endif /* DEBUG */
358 
359 /*
360  * Local Variables:
361  * tab-width: 4
362  * c-indent-level: 4
363  * c-argdecl-indent: 4
364  * c-continued-statement-offset: 4
365  * c-continued-brace-offset: -4
366  * c-label-offset: -4
367  * c-brace-offset: 0
368  * End:
369  */
370