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