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