1238106Sdes/************************************************************************ 2238106Sdes Copyright 1988, 1991 by Carnegie Mellon University 3238106Sdes 4238106Sdes All Rights Reserved 5238106Sdes 6238106SdesPermission to use, copy, modify, and distribute this software and its 7238106Sdesdocumentation for any purpose and without fee is hereby granted, provided 8238106Sdesthat the above copyright notice appear in all copies and that both that 9238106Sdescopyright notice and this permission notice appear in supporting 10238106Sdesdocumentation, and that the name of Carnegie Mellon University not be used 11238106Sdesin advertising or publicity pertaining to distribution of the software 12238106Sdeswithout specific, written prior permission. 13238106Sdes 14238106SdesCARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 15238106SdesSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. 16238106SdesIN NO EVENT SHALL CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 17238106SdesDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 18238106SdesPROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 19238106SdesACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 20238106SdesSOFTWARE. 21238106Sdes 22238106Sdes************************************************************************/ 23238106Sdes 24238106Sdes/* 25238106Sdes * bootpef - BOOTP Extension File generator 26238106Sdes * Makes an "Extension File" for each host entry that 27238106Sdes * defines an and Extension File. (See RFC1497, tag 18.) 28238106Sdes * 29238106Sdes * HISTORY 30238106Sdes * See ./Changes 31238106Sdes * 32238106Sdes * BUGS 33238106Sdes * See ./ToDo 34238106Sdes */ 35238106Sdes 36238106Sdes 37238106Sdes 38238106Sdes#include <stdarg.h> 39238106Sdes 40238106Sdes#include <sys/types.h> 41238106Sdes#include <sys/time.h> 42238106Sdes 43238106Sdes#include <netinet/in.h> 44238106Sdes#include <arpa/inet.h> /* inet_ntoa */ 45238106Sdes 46238106Sdes#ifndef NO_UNISTD 47238106Sdes#include <unistd.h> 48238106Sdes#endif 49238106Sdes#include <stdlib.h> 50238106Sdes#include <stdio.h> 51238106Sdes#include <string.h> 52238106Sdes#include <errno.h> 53238106Sdes#include <ctype.h> 54238106Sdes#include <syslog.h> 55238106Sdes 56238106Sdes#include "bootp.h" 57238106Sdes#include "hash.h" 58238106Sdes#include "hwaddr.h" 59238106Sdes#include "bootpd.h" 60238106Sdes#include "dovend.h" 61238106Sdes#include "readfile.h" 62238106Sdes#include "report.h" 63238106Sdes#include "tzone.h" 64238106Sdes#include "patchlevel.h" 65238106Sdes 66238106Sdes#define BUFFERSIZE 0x4000 67238106Sdes 68238106Sdes#ifndef CONFIG_FILE 69238106Sdes#define CONFIG_FILE "/etc/bootptab" 70238106Sdes#endif 71238106Sdes 72238106Sdes 73238106Sdes 74238106Sdes/* 75238106Sdes * Externals, forward declarations, and global variables 76238106Sdes */ 77238106Sdes 78238106Sdesstatic void mktagfile(struct host *); 79238106Sdesstatic void usage(void) __dead2; 80238106Sdes 81238106Sdes/* 82238106Sdes * General 83238106Sdes */ 84238106Sdes 85238106Sdeschar *progname; 86238106Sdeschar *chdir_path; 87238106Sdesint debug = 0; /* Debugging flag (level) */ 88238106Sdesbyte *buffer; 89238106Sdes 90238106Sdes/* 91238106Sdes * Globals below are associated with the bootp database file (bootptab). 92238106Sdes */ 93238106Sdes 94238106Sdeschar *bootptab = CONFIG_FILE; 95238106Sdes 96238106Sdes 97238106Sdes/* 98238106Sdes * Print "usage" message and exit 99238106Sdes */ 100238106Sdesstatic void 101238106Sdesusage(void) 102238106Sdes{ 103238106Sdes fprintf(stderr, 104238106Sdes "usage: $s [ -c chdir ] [-d level] [-f configfile] [host...]\n"); 105238106Sdes fprintf(stderr, "\t -c n\tset current directory\n"); 106238106Sdes fprintf(stderr, "\t -d n\tset debug level\n"); 107238106Sdes fprintf(stderr, "\t -f n\tconfig file name\n"); 108238106Sdes exit(1); 109238106Sdes} 110238106Sdes 111238106Sdes 112238106Sdes/* 113238106Sdes * Initialization such as command-line processing is done and then the 114238106Sdes * main server loop is started. 115238106Sdes */ 116238106Sdesint 117238106Sdesmain(int argc, char **argv) 118238106Sdes{ 119238106Sdes struct host *hp; 120238106Sdes char *stmp; 121238106Sdes int n; 122238106Sdes 123238106Sdes progname = strrchr(argv[0], '/'); 124238106Sdes if (progname) progname++; 125238106Sdes else progname = argv[0]; 126238106Sdes 127238106Sdes /* Get work space for making tag 18 files. */ 128238106Sdes buffer = (byte *) malloc(BUFFERSIZE); 129238106Sdes if (!buffer) { 130238106Sdes report(LOG_ERR, "malloc failed"); 131238106Sdes exit(1); 132238106Sdes } 133238106Sdes /* 134238106Sdes * Set defaults that might be changed by option switches. 135238106Sdes */ 136238106Sdes stmp = NULL; 137238106Sdes 138238106Sdes /* 139238106Sdes * Read switches. 140238106Sdes */ 141238106Sdes for (argc--, argv++; argc > 0; argc--, argv++) { 142238106Sdes if (argv[0][0] != '-') 143238106Sdes break; 144238106Sdes switch (argv[0][1]) { 145238106Sdes 146238106Sdes case 'c': /* chdir_path */ 147238106Sdes if (argv[0][2]) { 148238106Sdes stmp = &(argv[0][2]); 149238106Sdes } else { 150238106Sdes argc--; 151238106Sdes argv++; 152238106Sdes stmp = argv[0]; 153238106Sdes } 154238106Sdes if (!stmp || (stmp[0] != '/')) { 155238106Sdes fprintf(stderr, 156238106Sdes "bootpd: invalid chdir specification\n"); 157238106Sdes break; 158238106Sdes } 159238106Sdes chdir_path = stmp; 160238106Sdes break; 161238106Sdes 162238106Sdes case 'd': /* debug */ 163238106Sdes if (argv[0][2]) { 164238106Sdes stmp = &(argv[0][2]); 165238106Sdes } else if (argv[1] && argv[1][0] == '-') { 166238106Sdes /* 167238106Sdes * Backwards-compatible behavior: 168238106Sdes * no parameter, so just increment the debug flag. 169238106Sdes */ 170238106Sdes debug++; 171238106Sdes break; 172238106Sdes } else { 173238106Sdes argc--; 174238106Sdes argv++; 175238106Sdes stmp = argv[0]; 176238106Sdes } 177238106Sdes if (!stmp || (sscanf(stmp, "%d", &n) != 1) || (n < 0)) { 178238106Sdes fprintf(stderr, 179238106Sdes "bootpd: invalid debug level\n"); 180238106Sdes break; 181238106Sdes } 182238106Sdes debug = n; 183238106Sdes break; 184238106Sdes 185238106Sdes case 'f': /* config file */ 186238106Sdes if (argv[0][2]) { 187238106Sdes stmp = &(argv[0][2]); 188238106Sdes } else { 189238106Sdes argc--; 190238106Sdes argv++; 191238106Sdes stmp = argv[0]; 192238106Sdes } 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 260static void 261mktagfile(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