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