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