bootpef.c revision 46078
197364Stjr/************************************************************************ 297364Stjr Copyright 1988, 1991 by Carnegie Mellon University 397364Stjr 497364Stjr All Rights Reserved 597364Stjr 697364StjrPermission to use, copy, modify, and distribute this software and its 797364Stjrdocumentation for any purpose and without fee is hereby granted, provided 897364Stjrthat the above copyright notice appear in all copies and that both that 997364Stjrcopyright notice and this permission notice appear in supporting 1097364Stjrdocumentation, and that the name of Carnegie Mellon University not be used 1197364Stjrin advertising or publicity pertaining to distribution of the software 1297364Stjrwithout specific, written prior permission. 1397364Stjr 1497364StjrCARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 1597364StjrSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. 1697364StjrIN NO EVENT SHALL CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 1797364StjrDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 1897364StjrPROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 1997364StjrACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2097364StjrSOFTWARE. 2197364Stjr 2297364Stjr $Id: bootpef.c,v 1.4 1997/02/22 14:21:18 peter Exp $ 2397364Stjr 2497364Stjr************************************************************************/ 2597364Stjr 2697364Stjr/* 2797364Stjr * bootpef - BOOTP Extension File generator 2897364Stjr * Makes an "Extension File" for each host entry that 2997364Stjr * defines an and Extension File. (See RFC1497, tag 18.) 3097364Stjr * 3197364Stjr * HISTORY 3297364Stjr * See ./Changes 3397364Stjr * 3497364Stjr * BUGS 3597364Stjr * See ./ToDo 3697364Stjr */ 37200462Sdelphij 3897364Stjr 3997364Stjr 40200462Sdelphij#ifdef __STDC__ 4197364Stjr#include <stdarg.h> 4297364Stjr#else 4397364Stjr#include <varargs.h> 4497364Stjr#endif 4597364Stjr 4697364Stjr#include <sys/types.h> 4797364Stjr#include <sys/time.h> 4897364Stjr 4997364Stjr#include <netinet/in.h> 5097364Stjr#include <arpa/inet.h> /* inet_ntoa */ 5197364Stjr 5297364Stjr#ifndef NO_UNISTD 5397364Stjr#include <unistd.h> 5497364Stjr#endif 5597364Stjr#include <stdlib.h> 5697364Stjr#include <stdio.h> 5797364Stjr#include <string.h> 5897364Stjr#include <errno.h> 5997364Stjr#include <ctype.h> 6097364Stjr#include <syslog.h> 6197364Stjr 6297364Stjr#ifndef USE_BFUNCS 6397364Stjr#include <memory.h> 6497364Stjr/* Yes, memcpy is OK here (no overlapped copies). */ 6597364Stjr#define bcopy(a,b,c) memcpy(b,a,c) 6697364Stjr#define bzero(p,l) memset(p,0,l) 6797364Stjr#define bcmp(a,b,c) memcmp(a,b,c) 6897364Stjr#endif 6997364Stjr 7097364Stjr#include "bootp.h" 7197364Stjr#include "hash.h" 7297364Stjr#include "hwaddr.h" 7397364Stjr#include "bootpd.h" 7497364Stjr#include "dovend.h" 7597364Stjr#include "readfile.h" 76246553Sdes#include "report.h" 77246553Sdes#include "tzone.h" 7897364Stjr#include "patchlevel.h" 7997364Stjr 8097364Stjr#define BUFFERSIZE 0x4000 8197364Stjr 8297364Stjr#ifndef CONFIG_FILE 8397364Stjr#define CONFIG_FILE "/etc/bootptab" 8497364Stjr#endif 8597364Stjr 8697364Stjr 8797364Stjr 8897364Stjr/* 8997364Stjr * Externals, forward declarations, and global variables 9097364Stjr */ 9197364Stjr 9297364Stjr#ifdef __STDC__ 9397364Stjr#define P(args) args 9497364Stjr#else 9597364Stjr#define P(args) () 9697364Stjr#endif 9797364Stjr 9897364Stjrstatic void mktagfile P((struct host *)); 9997364Stjrstatic void usage P((void)); 10097364Stjr 10197364Stjr#undef P 10297364Stjr 10397364Stjr 10497364Stjr/* 10597364Stjr * General 10697364Stjr */ 10797364Stjr 10897364Stjrchar *progname; 10997364Stjrchar *chdir_path; 11097364Stjrint debug = 0; /* Debugging flag (level) */ 11197364Stjrbyte *buffer; 11297364Stjr 11397364Stjr/* 11497364Stjr * Globals below are associated with the bootp database file (bootptab). 11597364Stjr */ 11697364Stjr 11797364Stjrchar *bootptab = CONFIG_FILE; 11897364Stjr 11997364Stjr 12097364Stjr/* 12197364Stjr * Print "usage" message and exit 12297364Stjr */ 12397364Stjrstatic void 12497364Stjrusage() 12597364Stjr{ 12697364Stjr fprintf(stderr, 12797364Stjr "usage: $s [ -c chdir ] [-d level] [-f configfile] [host...]\n"); 12897364Stjr fprintf(stderr, "\t -c n\tset current directory\n"); 12997364Stjr fprintf(stderr, "\t -d n\tset debug level\n"); 13097364Stjr fprintf(stderr, "\t -f n\tconfig file name\n"); 13197364Stjr exit(1); 13297364Stjr} 13397364Stjr 13497364Stjr 13597364Stjr/* 13697364Stjr * Initialization such as command-line processing is done and then the 13797364Stjr * main server loop is started. 13897364Stjr */ 13997364Stjrint 14097364Stjrmain(argc, argv) 14197364Stjr int argc; 14297364Stjr char **argv; 14397364Stjr{ 144226274Sdelphij struct host *hp; 14597364Stjr char *stmp; 14697364Stjr int n; 14797364Stjr 14897364Stjr progname = strrchr(argv[0], '/'); 14997364Stjr if (progname) progname++; 150194494Sbrooks else progname = argv[0]; 151194494Sbrooks 15297364Stjr /* Get work space for making tag 18 files. */ 15397364Stjr buffer = (byte *) malloc(BUFFERSIZE); 15497364Stjr if (!buffer) { 155231994Skevlo report(LOG_ERR, "malloc failed"); 15697364Stjr exit(1); 15797364Stjr } 15897364Stjr /* 15997364Stjr * Set defaults that might be changed by option switches. 16097364Stjr */ 16197364Stjr stmp = NULL; 16297364Stjr 16397364Stjr /* 16497364Stjr * Read switches. 16597364Stjr */ 16697364Stjr for (argc--, argv++; argc > 0; argc--, argv++) { 16797364Stjr if (argv[0][0] != '-') 16897364Stjr break; 16997364Stjr switch (argv[0][1]) { 17097364Stjr 17197364Stjr case 'c': /* chdir_path */ 17297364Stjr if (argv[0][2]) { 17397364Stjr stmp = &(argv[0][2]); 17497364Stjr } else { 17597364Stjr argc--; 17697364Stjr argv++; 17797364Stjr stmp = argv[0]; 17897364Stjr } 17997364Stjr if (!stmp || (stmp[0] != '/')) { 18097364Stjr fprintf(stderr, 18197364Stjr "bootpd: invalid chdir specification\n"); 182231994Skevlo break; 183231994Skevlo } 184231994Skevlo chdir_path = stmp; 185231994Skevlo break; 18697364Stjr 18797364Stjr case 'd': /* debug */ 18897364Stjr if (argv[0][2]) { 18997364Stjr stmp = &(argv[0][2]); 19097364Stjr } else if (argv[1] && argv[1][0] == '-') { 191194494Sbrooks /* 192194494Sbrooks * Backwards-compatible behavior: 193194494Sbrooks * no parameter, so just increment the debug flag. 194194494Sbrooks */ 19597364Stjr debug++; 196229668Sghelmer break; 19797364Stjr } else { 19897364Stjr argc--; 19997364Stjr argv++; 20097364Stjr stmp = argv[0]; 20197364Stjr } 20297364Stjr if (!stmp || (sscanf(stmp, "%d", &n) != 1) || (n < 0)) { 20397364Stjr fprintf(stderr, 20497364Stjr "bootpd: invalid debug level\n"); 20597364Stjr break; 20697364Stjr } 20797364Stjr debug = n; 20897364Stjr break; 20997364Stjr 210229668Sghelmer case 'f': /* config file */ 21197364Stjr if (argv[0][2]) { 21297364Stjr stmp = &(argv[0][2]); 21397364Stjr } else { 21497364Stjr argc--; 21597364Stjr argv++; 21697364Stjr stmp = argv[0]; 21797364Stjr } 21897364Stjr bootptab = stmp; 219229668Sghelmer break; 22097364Stjr 22197364Stjr default: 22297364Stjr fprintf(stderr, "bootpd: unknown switch: -%c\n", 22397364Stjr argv[0][1]); 22497364Stjr usage(); 22597364Stjr break; 226226416Sdelphij } 22797364Stjr } 22897364Stjr 22997364Stjr /* Get the timezone. */ 23097364Stjr tzone_init(); 23197364Stjr 23297364Stjr /* Allocate hash tables. */ 23397364Stjr rdtab_init(); 234229668Sghelmer 23597364Stjr /* 23697364Stjr * Read the bootptab file. 23797364Stjr */ 23897364Stjr readtab(1); /* force read */ 239229668Sghelmer 240194494Sbrooks /* Set the cwd (i.e. to /tftpboot) */ 24197364Stjr if (chdir_path) { 24297364Stjr if (chdir(chdir_path) < 0) 24397364Stjr report(LOG_ERR, "%s: chdir failed", chdir_path); 24497364Stjr } 24597364Stjr /* If there are host names on the command line, do only those. */ 24697364Stjr if (argc > 0) { 24797364Stjr unsigned int tlen, hashcode; 24897364Stjr 24997364Stjr while (argc) { 25097364Stjr tlen = strlen(argv[0]); 25197364Stjr hashcode = hash_HashFunction((u_char *)argv[0], tlen); 25297364Stjr hp = (struct host *) hash_Lookup(nmhashtable, 25397364Stjr hashcode, 25497364Stjr nmcmp, argv[0]); 25597364Stjr if (!hp) { 25697364Stjr printf("%s: no matching entry\n", argv[0]); 25797364Stjr exit(1); 25897364Stjr } 25997364Stjr if (!hp->flags.exten_file) { 26097364Stjr printf("%s: no extension file\n", argv[0]); 26197364Stjr exit(1); 26297364Stjr } 26397364Stjr mktagfile(hp); 26497364Stjr argv++; 26597364Stjr argc--; 26697364Stjr } 26797364Stjr exit(0); 26897364Stjr } 26997364Stjr /* No host names specified. Do them all. */ 27097364Stjr hp = (struct host *) hash_FirstEntry(nmhashtable); 27197364Stjr while (hp != NULL) { 27297364Stjr mktagfile(hp); 27397364Stjr hp = (struct host *) hash_NextEntry(nmhashtable); 27497364Stjr } 27597364Stjr return (0); 27697364Stjr} 27797364Stjr 27897364Stjr 27997364Stjr 28097364Stjr/* 28197364Stjr * Make a "TAG 18" file for this host. 28297364Stjr * (Insert the RFC1497 options.) 28397364Stjr */ 28497364Stjr 28597364Stjrstatic void 28697364Stjrmktagfile(hp) 28797364Stjr struct host *hp; 28897364Stjr{ 28997364Stjr FILE *fp; 29097364Stjr int bytesleft, len; 29197364Stjr byte *vp; 29297364Stjr 29397364Stjr if (!hp->flags.exten_file) 29497364Stjr return; 29597364Stjr 29697364Stjr vp = buffer; 29797364Stjr bytesleft = BUFFERSIZE; 29897364Stjr bcopy(vm_rfc1048, vp, 4); /* Copy in the magic cookie */ 29997364Stjr vp += 4; 30097364Stjr bytesleft -= 4; 30197364Stjr 30297364Stjr /* 30397364Stjr * The "extension file" options are appended by the following 30497364Stjr * function (which is shared with bootpd.c). 30597364Stjr */ 30697364Stjr len = dovend_rfc1497(hp, vp, bytesleft); 30797364Stjr vp += len; 30897364Stjr bytesleft -= len; 309121741Sharti 31097364Stjr if (bytesleft < 1) { 31197364Stjr 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