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