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