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