xref: /freebsd/libexec/bootpd/tools/bootpef/bootpef.c (revision a316b26e50bbed7cf655fbba726ab87d8ab7599d)
1 /************************************************************************
2           Copyright 1988, 1991 by Carnegie Mellon University
3 
4                           All Rights Reserved
5 
6 Permission to use, copy, modify, and distribute this software and its
7 documentation for any purpose and without fee is hereby granted, provided
8 that the above copyright notice appear in all copies and that both that
9 copyright notice and this permission notice appear in supporting
10 documentation, and that the name of Carnegie Mellon University not be used
11 in advertising or publicity pertaining to distribution of the software
12 without specific, written prior permission.
13 
14 CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
15 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
16 IN NO EVENT SHALL CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
17 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
18 PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
19 ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20 SOFTWARE.
21 ************************************************************************/
22 
23 #ifndef lint
24 static 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 
100 static void dovend_rfc1048 P((struct bootp *, struct host *, int32));
101 static void mktagfile P((struct host *));
102 static void usage P((void));
103 
104 #undef P
105 
106 
107 /*
108  * General
109  */
110 
111 char *progname;
112 char *chdir_path;
113 int debug = 0;					/* Debugging flag (level) */
114 byte *buffer;
115 
116 /*
117  * Globals below are associated with the bootp database file (bootptab).
118  */
119 
120 char *bootptab = CONFIG_FILE;
121 
122 
123 /*
124  * Print "usage" message and exit
125  */
126 static void
127 usage()
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  */
142 void
143 main(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 
287 static void
288 mktagfile(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