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