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