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