bootpef.c revision 21673
1/************************************************************************
2          Copyright 1988, 1991 by Carnegie Mellon University
3
4                          All Rights Reserved
5
6Permission to use, copy, modify, and distribute this software and its
7documentation for any purpose and without fee is hereby granted, provided
8that the above copyright notice appear in all copies and that both that
9copyright notice and this permission notice appear in supporting
10documentation, and that the name of Carnegie Mellon University not be used
11in advertising or publicity pertaining to distribution of the software
12without specific, written prior permission.
13
14CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
15SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
16IN NO EVENT SHALL CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
17DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
18PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
19ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20SOFTWARE.
21
22	$FreeBSD: head/libexec/bootpd/tools/bootpef/bootpef.c 21673 1997-01-14 07:20:47Z jkh $
23
24************************************************************************/
25
26/*
27 * bootpef - BOOTP Extension File generator
28 *	Makes an "Extension File" for each host entry that
29 *	defines an and Extension File. (See RFC1497, tag 18.)
30 *
31 * HISTORY
32 *	See ./Changes
33 *
34 * BUGS
35 *	See ./ToDo
36 */
37
38
39
40#ifdef	__STDC__
41#include <stdarg.h>
42#else
43#include <varargs.h>
44#endif
45
46#include <sys/types.h>
47#include <sys/time.h>
48
49#include <netinet/in.h>
50#include <arpa/inet.h>			/* inet_ntoa */
51
52#ifndef	NO_UNISTD
53#include <unistd.h>
54#endif
55#include <stdlib.h>
56#include <stdio.h>
57#include <string.h>
58#include <errno.h>
59#include <ctype.h>
60#include <syslog.h>
61
62#ifndef	USE_BFUNCS
63#include <memory.h>
64/* Yes, memcpy is OK here (no overlapped copies). */
65#define bcopy(a,b,c)    memcpy(b,a,c)
66#define bzero(p,l)      memset(p,0,l)
67#define bcmp(a,b,c)     memcmp(a,b,c)
68#endif
69
70#include "bootp.h"
71#include "hash.h"
72#include "hwaddr.h"
73#include "bootpd.h"
74#include "dovend.h"
75#include "readfile.h"
76#include "report.h"
77#include "tzone.h"
78#include "patchlevel.h"
79
80#define	BUFFERSIZE   		0x4000
81
82#ifndef CONFIG_FILE
83#define CONFIG_FILE		"/etc/bootptab"
84#endif
85
86
87
88/*
89 * Externals, forward declarations, and global variables
90 */
91
92#ifdef	__STDC__
93#define P(args) args
94#else
95#define P(args) ()
96#endif
97
98static void mktagfile P((struct host *));
99static void usage P((void));
100
101#undef P
102
103
104/*
105 * General
106 */
107
108char *progname;
109char *chdir_path;
110int debug = 0;					/* Debugging flag (level) */
111byte *buffer;
112
113/*
114 * Globals below are associated with the bootp database file (bootptab).
115 */
116
117char *bootptab = CONFIG_FILE;
118
119
120/*
121 * Print "usage" message and exit
122 */
123static void
124usage()
125{
126	fprintf(stderr,
127	   "usage:  $s [ -c chdir ] [-d level] [-f configfile] [host...]\n");
128	fprintf(stderr, "\t -c n\tset current directory\n");
129	fprintf(stderr, "\t -d n\tset debug level\n");
130	fprintf(stderr, "\t -f n\tconfig file name\n");
131	exit(1);
132}
133
134
135/*
136 * Initialization such as command-line processing is done and then the
137 * main server loop is started.
138 */
139void
140main(argc, argv)
141	int argc;
142	char **argv;
143{
144	struct host *hp;
145	char *stmp;
146	int n;
147
148	progname = strrchr(argv[0], '/');
149	if (progname) progname++;
150	else progname = argv[0];
151
152	/* Get work space for making tag 18 files. */
153	buffer = (byte *) malloc(BUFFERSIZE);
154	if (!buffer) {
155		report(LOG_ERR, "malloc failed");
156		exit(1);
157	}
158	/*
159	 * Set defaults that might be changed by option switches.
160	 */
161	stmp = NULL;
162
163	/*
164	 * Read switches.
165	 */
166	for (argc--, argv++; argc > 0; argc--, argv++) {
167		if (argv[0][0] != '-')
168			break;
169		switch (argv[0][1]) {
170
171		case 'c':				/* chdir_path */
172			if (argv[0][2]) {
173				stmp = &(argv[0][2]);
174			} else {
175				argc--;
176				argv++;
177				stmp = argv[0];
178			}
179			if (!stmp || (stmp[0] != '/')) {
180				fprintf(stderr,
181						"bootpd: invalid chdir specification\n");
182				break;
183			}
184			chdir_path = stmp;
185			break;
186
187		case 'd':				/* debug */
188			if (argv[0][2]) {
189				stmp = &(argv[0][2]);
190			} else if (argv[1] && argv[1][0] == '-') {
191				/*
192				 * Backwards-compatible behavior:
193				 * no parameter, so just increment the debug flag.
194				 */
195				debug++;
196				break;
197			} else {
198				argc--;
199				argv++;
200				stmp = argv[0];
201			}
202			if (!stmp || (sscanf(stmp, "%d", &n) != 1) || (n < 0)) {
203				fprintf(stderr,
204						"bootpd: invalid debug level\n");
205				break;
206			}
207			debug = n;
208			break;
209
210		case 'f':				/* config file */
211			if (argv[0][2]) {
212				stmp = &(argv[0][2]);
213			} else {
214				argc--;
215				argv++;
216				stmp = argv[0];
217			}
218			bootptab = stmp;
219			break;
220
221		default:
222			fprintf(stderr, "bootpd: unknown switch: -%c\n",
223					argv[0][1]);
224			usage();
225			break;
226		}
227	}
228
229	/* Get the timezone. */
230	tzone_init();
231
232	/* Allocate hash tables. */
233	rdtab_init();
234
235	/*
236	 * Read the bootptab file.
237	 */
238	readtab(1);					/* force read */
239
240	/* Set the cwd (i.e. to /tftpboot) */
241	if (chdir_path) {
242		if (chdir(chdir_path) < 0)
243			report(LOG_ERR, "%s: chdir failed", chdir_path);
244	}
245	/* If there are host names on the command line, do only those. */
246	if (argc > 0) {
247		unsigned int tlen, hashcode;
248
249		while (argc) {
250			tlen = strlen(argv[0]);
251			hashcode = hash_HashFunction((u_char *)argv[0], tlen);
252			hp = (struct host *) hash_Lookup(nmhashtable,
253											 hashcode,
254											 nmcmp, argv[0]);
255			if (!hp) {
256				printf("%s: no matching entry\n", argv[0]);
257				exit(1);
258			}
259			if (!hp->flags.exten_file) {
260				printf("%s: no extension file\n", argv[0]);
261				exit(1);
262			}
263			mktagfile(hp);
264			argv++;
265			argc--;
266		}
267		exit(0);
268	}
269	/* No host names specified.  Do them all. */
270	hp = (struct host *) hash_FirstEntry(nmhashtable);
271	while (hp != NULL) {
272		mktagfile(hp);
273		hp = (struct host *) hash_NextEntry(nmhashtable);
274	}
275}
276
277
278
279/*
280 * Make a "TAG 18" file for this host.
281 * (Insert the RFC1497 options.)
282 */
283
284static void
285mktagfile(hp)
286	struct host *hp;
287{
288	FILE *fp;
289	int bytesleft, len;
290	byte *vp;
291
292	if (!hp->flags.exten_file)
293		return;
294
295	vp = buffer;
296	bytesleft = BUFFERSIZE;
297	bcopy(vm_rfc1048, vp, 4);	/* Copy in the magic cookie */
298	vp += 4;
299	bytesleft -= 4;
300
301	/*
302	 * The "extension file" options are appended by the following
303	 * function (which is shared with bootpd.c).
304	 */
305	len = dovend_rfc1497(hp, vp, bytesleft);
306	vp += len;
307	bytesleft -= len;
308
309	if (bytesleft < 1) {
310		report(LOG_ERR, "%s: too much option data",
311			   hp->exten_file->string);
312		return;
313	}
314	*vp++ = TAG_END;
315	bytesleft--;
316
317	/* Write the buffer to the extension file. */
318	printf("Updating \"%s\"\n", hp->exten_file->string);
319	if ((fp = fopen(hp->exten_file->string, "w")) == NULL) {
320		report(LOG_ERR, "error opening \"%s\": %s",
321			   hp->exten_file->string, get_errmsg());
322		return;
323	}
324	len = vp - buffer;
325	if (len != fwrite(buffer, 1, len, fp)) {
326		report(LOG_ERR, "write failed on \"%s\" : %s",
327			   hp->exten_file->string, get_errmsg());
328	}
329	fclose(fp);
330
331} /* mktagfile */
332
333/*
334 * Local Variables:
335 * tab-width: 4
336 * c-indent-level: 4
337 * c-argdecl-indent: 4
338 * c-continued-statement-offset: 4
339 * c-continued-brace-offset: -4
340 * c-label-offset: -4
341 * c-brace-offset: 0
342 * End:
343 */
344