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