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