bootpef.c revision 18471
140711Swollman/************************************************************************ 240711Swollman Copyright 1988, 1991 by Carnegie Mellon University 340711Swollman 440711Swollman All Rights Reserved 540711Swollman 640711SwollmanPermission to use, copy, modify, and distribute this software and its 740711Swollmandocumentation for any purpose and without fee is hereby granted, provided 840711Swollmanthat the above copyright notice appear in all copies and that both that 940711Swollmancopyright notice and this permission notice appear in supporting 1040711Swollmandocumentation, and that the name of Carnegie Mellon University not be used 1140711Swollmanin advertising or publicity pertaining to distribution of the software 1240711Swollmanwithout specific, written prior permission. 1340711Swollman 1440711SwollmanCARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 1540711SwollmanSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. 1640711SwollmanIN NO EVENT SHALL CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 1740711SwollmanDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 1840711SwollmanPROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 1940711SwollmanACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2040711SwollmanSOFTWARE. 2140711Swollman 2240711Swollman $Id$ 2340711Swollman 2440711Swollman************************************************************************/ 2540711Swollman 2640711Swollman/* 2740711Swollman * bootpef - BOOTP Extension File generator 2840711Swollman * Makes an "Extension File" for each host entry that 2950477Speter * defines an and Extension File. (See RFC1497, tag 18.) 3040711Swollman * 3140711Swollman * HISTORY 3240711Swollman * See ./Changes 3340711Swollman * 3440711Swollman * BUGS 3540711Swollman * See ./ToDo 3640711Swollman */ 3740711Swollman 3840711Swollman 3940711Swollman 4040711Swollman#ifdef __STDC__ 4140711Swollman#include <stdarg.h> 4240711Swollman#else 4340711Swollman#include <varargs.h> 4440711Swollman#endif 4540711Swollman 4640711Swollman#include <sys/types.h> 4740711Swollman#include <sys/time.h> 4840711Swollman 4940711Swollman#include <netinet/in.h> 5040711Swollman#include <arpa/inet.h> /* inet_ntoa */ 5140711Swollman 5240711Swollman#ifndef NO_UNISTD 5340711Swollman#include <unistd.h> 5440711Swollman#endif 5540711Swollman#include <stdlib.h> 5640711Swollman#include <stdio.h> 5740711Swollman#include <string.h> 5840711Swollman#include <errno.h> 5940711Swollman#include <ctype.h> 6040711Swollman#include <syslog.h> 6140711Swollman 6241304Sbde#ifndef USE_BFUNCS 6340711Swollman#include <memory.h> 6440711Swollman/* Yes, memcpy is OK here (no overlapped copies). */ 6571576Sjasone#define bcopy(a,b,c) memcpy(b,a,c) 6645720Speter#define bzero(p,l) memset(p,0,l) 6745720Speter#define bcmp(a,b,c) memcmp(a,b,c) 6840711Swollman#endif 69102962Siwasaki 7040711Swollman#include "bootp.h" 71102962Siwasaki#include "hash.h" 72102962Siwasaki#include "hwaddr.h" 73102962Siwasaki#include "bootpd.h" 74102962Siwasaki#include "dovend.h" 7559910Spaul#include "readfile.h" 76102962Siwasaki#include "report.h" 77102962Siwasaki#include "tzone.h" 7845569Seivind#include "patchlevel.h" 7940711Swollman 8040711Swollman#define BUFFERSIZE 0x4000 8171576Sjasone 8240711Swollman#ifndef CONFIG_FILE 8340711Swollman#define CONFIG_FILE "/etc/bootptab" 8445720Speter#endif 8540711Swollman 8640711Swollman 8740711Swollman 8840711Swollman/* 8940711Swollman * Externals, forward declarations, and global variables 9040711Swollman */ 9140711Swollman 9240711Swollman#ifdef __STDC__ 9340711Swollman#define P(args) args 9440711Swollman#else 9593818Sjhb#define P(args) () 9640711Swollman#endif 9740711Swollman 9840711Swollmanstatic void mktagfile P((struct host *)); 9940711Swollmanstatic void usage P((void)); 10040711Swollman 10140711Swollman#undef P 10240711Swollman 10368727Smckusick 10484781Sjhb/* 10571576Sjasone * General 10640711Swollman */ 10793818Sjhb 10840711Swollmanchar *progname; 10972200Sbmilekicchar *chdir_path; 11040711Swollmanint debug = 0; /* Debugging flag (level) */ 11172200Sbmilekicbyte *buffer; 11240711Swollman 11340711Swollman/* 11440711Swollman * Globals below are associated with the bootp database file (bootptab). 11540711Swollman */ 11640711Swollman 11740711Swollmanchar *bootptab = CONFIG_FILE; 11840711Swollman 11940711Swollman 12040711Swollman/* 12140711Swollman * Print "usage" message and exit 12240711Swollman */ 12340711Swollmanstatic void 12469781Sdwmaloneusage() 12540711Swollman{ 12640711Swollman fprintf(stderr, 12740711Swollman "usage: $s [ -c chdir ] [-d level] [-f configfile] [host...]\n"); 12840711Swollman fprintf(stderr, "\t -c n\tset current directory\n"); 12940711Swollman fprintf(stderr, "\t -d n\tset debug level\n"); 13040711Swollman fprintf(stderr, "\t -f n\tconfig file name\n"); 13172200Sbmilekic exit(1); 13268727Smckusick} 13368727Smckusick 13468727Smckusick 13540711Swollman/* 13640711Swollman * Initialization such as command-line processing is done and then the 13768727Smckusick * main server loop is started. 13868727Smckusick */ 13940711Swollmanvoid 14068727Smckusickmain(argc, argv) 14140711Swollman int argc; 14240711Swollman char **argv; 14372200Sbmilekic{ 14440711Swollman struct host *hp; 14540711Swollman char *stmp; 14640711Swollman int n; 14740711Swollman 14840711Swollman progname = strrchr(argv[0], '/'); 14940711Swollman if (progname) progname++; 15040711Swollman else progname = argv[0]; 15140711Swollman 15272200Sbmilekic /* Get work space for making tag 18 files. */ 15368727Smckusick buffer = (byte *) malloc(BUFFERSIZE); 15445720Speter if (!buffer) { 15572200Sbmilekic report(LOG_ERR, "malloc failed"); 15640711Swollman exit(1); 15745720Speter } 15840711Swollman /* 15940711Swollman * Set defaults that might be changed by option switches. 16040711Swollman */ 16140711Swollman stmp = NULL; 16240711Swollman 16340711Swollman /* 16468727Smckusick * Read switches. 16568727Smckusick */ 16668727Smckusick for (argc--, argv++; argc > 0; argc--, argv++) { 16740711Swollman if (argv[0][0] != '-') 16840711Swollman break; 16972200Sbmilekic switch (argv[0][1]) { 17072200Sbmilekic 17140711Swollman case 'c': /* chdir_path */ 17272200Sbmilekic if (argv[0][2]) { 17371576Sjasone stmp = &(argv[0][2]); 17471576Sjasone } else { 17540711Swollman argc--; 17640711Swollman argv++; 17740711Swollman stmp = argv[0]; 17840711Swollman } 17940711Swollman if (!stmp || (stmp[0] != '/')) { 18088372Stmm fprintf(stderr, 18188372Stmm "bootpd: invalid chdir specification\n"); 18288372Stmm break; 18340711Swollman } 18440711Swollman chdir_path = stmp; 18540711Swollman break; 18688372Stmm 18740711Swollman case 'd': /* debug */ 18840711Swollman if (argv[0][2]) { 18940711Swollman stmp = &(argv[0][2]); 19059910Spaul } else if (argv[1] && argv[1][0] == '-') { 19177288Sbrian /* 19277288Sbrian * Backwards-compatible behavior: 19340711Swollman * no parameter, so just increment the debug flag. 19440711Swollman */ 19540711Swollman debug++; 19672200Sbmilekic break; 19740711Swollman } else { 19868727Smckusick argc--; 19968727Smckusick argv++; 20068727Smckusick stmp = argv[0]; 20140711Swollman } 20240711Swollman if (!stmp || (sscanf(stmp, "%d", &n) != 1) || (n < 0)) { 20368727Smckusick fprintf(stderr, 20459910Spaul "bootpd: invalid debug level\n"); 20540711Swollman break; 20640711Swollman } 20740711Swollman debug = n; 20888372Stmm break; 20988372Stmm 21088372Stmm case 'f': /* config file */ 21140711Swollman if (argv[0][2]) { 21240711Swollman stmp = &(argv[0][2]); 21340711Swollman } else { 21468727Smckusick argc--; 21559910Spaul argv++; 21640711Swollman stmp = argv[0]; 21759910Spaul } 21840711Swollman bootptab = stmp; 21940711Swollman break; 22040711Swollman 22159910Spaul default: 22240711Swollman fprintf(stderr, "bootpd: unknown switch: -%c\n", 22340711Swollman argv[0][1]); 22488372Stmm usage(); 22588372Stmm break; 22688372Stmm } 22788372Stmm } 22888372Stmm 22988372Stmm /* Get the timezone. */ 23088372Stmm tzone_init(); 23188372Stmm 23288372Stmm /* Allocate hash tables. */ 23388372Stmm rdtab_init(); 23488372Stmm 23588372Stmm /* 23688372Stmm * Read the bootptab file. 237102572Siwasaki */ 238102572Siwasaki readtab(1); /* force read */ 239102572Siwasaki 240102572Siwasaki /* Set the cwd (i.e. to /tftpboot) */ 24159910Spaul if (chdir_path) { 24259910Spaul if (chdir(chdir_path) < 0) 24340711Swollman report(LOG_ERR, "%s: chdir failed", chdir_path); 24440711Swollman } 24559910Spaul /* If there are host names on the command line, do only those. */ 24659910Spaul if (argc > 0) { 24740711Swollman unsigned int tlen, hashcode; 24859910Spaul 24940711Swollman while (argc) { 25048235Sdfr tlen = strlen(argv[0]); 25140711Swollman hashcode = hash_HashFunction((u_char *)argv[0], tlen); 25240711Swollman hp = (struct host *) hash_Lookup(nmhashtable, 25340711Swollman hashcode, 25440711Swollman nmcmp, argv[0]); 25540711Swollman if (!hp) { 25640711Swollman printf("%s: no matching entry\n", argv[0]); 25740711Swollman exit(1); 25840711Swollman } 25940711Swollman if (!hp->flags.exten_file) { 26040711Swollman printf("%s: no extension file\n", argv[0]); 26140711Swollman exit(1); 26240711Swollman } 26340711Swollman mktagfile(hp); 26440711Swollman argv++; 26569781Sdwmalone argc--; 26640711Swollman } 26740711Swollman exit(0); 26840711Swollman } 26940711Swollman /* No host names specified. Do them all. */ 27040711Swollman hp = (struct host *) hash_FirstEntry(nmhashtable); 27140711Swollman while (hp != NULL) { 27245720Speter mktagfile(hp); 27340711Swollman hp = (struct host *) hash_NextEntry(nmhashtable); 27440711Swollman } 27559910Spaul} 27640711Swollman 27740711Swollman 27840711Swollman 27959910Spaul/* 28040711Swollman * Make a "TAG 18" file for this host. 28140711Swollman * (Insert the RFC1497 options.) 28240711Swollman */ 28369781Sdwmalone 28440711Swollmanstatic void 28540711Swollmanmktagfile(hp) 28640711Swollman struct host *hp; 28740711Swollman{ 28840711Swollman FILE *fp; 28940711Swollman int bytesleft, len; 29040711Swollman byte *vp; 29140711Swollman 29245720Speter if (!hp->flags.exten_file) 29340711Swollman return; 29468727Smckusick 29540711Swollman vp = buffer; 29668727Smckusick bytesleft = BUFFERSIZE; 29740711Swollman bcopy(vm_rfc1048, vp, 4); /* Copy in the magic cookie */ 29840711Swollman vp += 4; 29959910Spaul bytesleft -= 4; 30040711Swollman 30140711Swollman /* 30240711Swollman * The "extension file" options are appended by the following 30340711Swollman * function (which is shared with bootpd.c). 30468727Smckusick */ 30540711Swollman len = dovend_rfc1497(hp, vp, bytesleft); 30659910Spaul vp += len; 30740711Swollman bytesleft -= len; 30840711Swollman 30940711Swollman if (bytesleft < 1) { 31040711Swollman report(LOG_ERR, "%s: too much option data", 31168727Smckusick hp->exten_file->string); 31240711Swollman return; 31340711Swollman } 31440711Swollman *vp++ = TAG_END; 31540711Swollman bytesleft--; 31640711Swollman 31740711Swollman /* Write the buffer to the extension file. */ 31840711Swollman printf("Updating \"%s\"\n", hp->exten_file->string); 31940711Swollman if ((fp = fopen(hp->exten_file->string, "w")) == NULL) { 32040711Swollman report(LOG_ERR, "error opening \"%s\": %s", 32140711Swollman hp->exten_file->string, get_errmsg()); 32240711Swollman return; 32340711Swollman } 32440711Swollman len = vp - buffer; 32540711Swollman if (len != fwrite(buffer, 1, len, fp)) { 32659910Spaul report(LOG_ERR, "write failed on \"%s\" : %s", 32740711Swollman hp->exten_file->string, get_errmsg()); 32840711Swollman } 32940711Swollman fclose(fp); 33068727Smckusick 33140711Swollman} /* mktagfile */ 33240711Swollman 33340711Swollman/* 33440711Swollman * Local Variables: 33588372Stmm * tab-width: 4 33688372Stmm * c-indent-level: 4 33740711Swollman * c-argdecl-indent: 4 33888372Stmm * c-continued-statement-offset: 4 33988372Stmm * c-continued-brace-offset: -4 34088372Stmm * c-label-offset: -4 34169781Sdwmalone * c-brace-offset: 0 34240711Swollman * End: 34340711Swollman */ 34440711Swollman