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