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