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