xref: /freebsd/libexec/bootpd/tools/bootpef/bootpef.c (revision 7f3dea244c40159a41ab22da77a434d7c5b5e85a)
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  $FreeBSD$
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 
98 static void mktagfile P((struct host *));
99 static void usage P((void));
100 
101 #undef P
102 
103 
104 /*
105  * General
106  */
107 
108 char *progname;
109 char *chdir_path;
110 int debug = 0;					/* Debugging flag (level) */
111 byte *buffer;
112 
113 /*
114  * Globals below are associated with the bootp database file (bootptab).
115  */
116 
117 char *bootptab = CONFIG_FILE;
118 
119 
120 /*
121  * Print "usage" message and exit
122  */
123 static void
124 usage()
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  */
139 int
140 main(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 	return (0);
276 }
277 
278 
279 
280 /*
281  * Make a "TAG 18" file for this host.
282  * (Insert the RFC1497 options.)
283  */
284 
285 static void
286 mktagfile(hp)
287 	struct host *hp;
288 {
289 	FILE *fp;
290 	int bytesleft, len;
291 	byte *vp;
292 
293 	if (!hp->flags.exten_file)
294 		return;
295 
296 	vp = buffer;
297 	bytesleft = BUFFERSIZE;
298 	bcopy(vm_rfc1048, vp, 4);	/* Copy in the magic cookie */
299 	vp += 4;
300 	bytesleft -= 4;
301 
302 	/*
303 	 * The "extension file" options are appended by the following
304 	 * function (which is shared with bootpd.c).
305 	 */
306 	len = dovend_rfc1497(hp, vp, bytesleft);
307 	vp += len;
308 	bytesleft -= len;
309 
310 	if (bytesleft < 1) {
311 		report(LOG_ERR, "%s: too much option data",
312 			   hp->exten_file->string);
313 		return;
314 	}
315 	*vp++ = TAG_END;
316 	bytesleft--;
317 
318 	/* Write the buffer to the extension file. */
319 	printf("Updating \"%s\"\n", hp->exten_file->string);
320 	if ((fp = fopen(hp->exten_file->string, "w")) == NULL) {
321 		report(LOG_ERR, "error opening \"%s\": %s",
322 			   hp->exten_file->string, get_errmsg());
323 		return;
324 	}
325 	len = vp - buffer;
326 	if (len != fwrite(buffer, 1, len, fp)) {
327 		report(LOG_ERR, "write failed on \"%s\" : %s",
328 			   hp->exten_file->string, get_errmsg());
329 	}
330 	fclose(fp);
331 
332 } /* mktagfile */
333 
334 /*
335  * Local Variables:
336  * tab-width: 4
337  * c-indent-level: 4
338  * c-argdecl-indent: 4
339  * c-continued-statement-offset: 4
340  * c-continued-brace-offset: -4
341  * c-label-offset: -4
342  * c-brace-offset: 0
343  * End:
344  */
345