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