144099b7bSPaul Traina /************************************************************************ 244099b7bSPaul Traina Copyright 1988, 1991 by Carnegie Mellon University 344099b7bSPaul Traina 444099b7bSPaul Traina All Rights Reserved 544099b7bSPaul Traina 644099b7bSPaul Traina Permission to use, copy, modify, and distribute this software and its 744099b7bSPaul Traina documentation for any purpose and without fee is hereby granted, provided 844099b7bSPaul Traina that the above copyright notice appear in all copies and that both that 944099b7bSPaul Traina copyright notice and this permission notice appear in supporting 1044099b7bSPaul Traina documentation, and that the name of Carnegie Mellon University not be used 1144099b7bSPaul Traina in advertising or publicity pertaining to distribution of the software 1244099b7bSPaul Traina without specific, written prior permission. 1344099b7bSPaul Traina 1444099b7bSPaul Traina CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 1544099b7bSPaul Traina SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. 1644099b7bSPaul Traina IN NO EVENT SHALL CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 1744099b7bSPaul Traina DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 1844099b7bSPaul Traina PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 1944099b7bSPaul Traina ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2044099b7bSPaul Traina SOFTWARE. 21148531efSWolfram Schneider 22148531efSWolfram Schneider $Id$ 23148531efSWolfram Schneider 2444099b7bSPaul Traina ************************************************************************/ 2544099b7bSPaul Traina 2644099b7bSPaul Traina /* 2744099b7bSPaul Traina * bootpef - BOOTP Extension File generator 2844099b7bSPaul Traina * Makes an "Extension File" for each host entry that 2944099b7bSPaul Traina * defines an and Extension File. (See RFC1497, tag 18.) 3044099b7bSPaul Traina * 3144099b7bSPaul Traina * HISTORY 3244099b7bSPaul Traina * See ./Changes 3344099b7bSPaul Traina * 3444099b7bSPaul Traina * BUGS 3544099b7bSPaul Traina * See ./ToDo 3644099b7bSPaul Traina */ 3744099b7bSPaul Traina 3844099b7bSPaul Traina 3944099b7bSPaul Traina 4044099b7bSPaul Traina #ifdef __STDC__ 4144099b7bSPaul Traina #include <stdarg.h> 4244099b7bSPaul Traina #else 4344099b7bSPaul Traina #include <varargs.h> 4444099b7bSPaul Traina #endif 4544099b7bSPaul Traina 4644099b7bSPaul Traina #include <sys/types.h> 4744099b7bSPaul Traina #include <sys/time.h> 4844099b7bSPaul Traina 4944099b7bSPaul Traina #include <netinet/in.h> 5044099b7bSPaul Traina #include <arpa/inet.h> /* inet_ntoa */ 5144099b7bSPaul Traina 5244099b7bSPaul Traina #ifndef NO_UNISTD 5344099b7bSPaul Traina #include <unistd.h> 5444099b7bSPaul Traina #endif 5544099b7bSPaul Traina #include <stdlib.h> 5644099b7bSPaul Traina #include <stdio.h> 5744099b7bSPaul Traina #include <string.h> 5844099b7bSPaul Traina #include <errno.h> 5944099b7bSPaul Traina #include <ctype.h> 6044099b7bSPaul Traina #include <syslog.h> 6144099b7bSPaul Traina 6244099b7bSPaul Traina #ifndef USE_BFUNCS 6344099b7bSPaul Traina #include <memory.h> 6444099b7bSPaul Traina /* Yes, memcpy is OK here (no overlapped copies). */ 6544099b7bSPaul Traina #define bcopy(a,b,c) memcpy(b,a,c) 6644099b7bSPaul Traina #define bzero(p,l) memset(p,0,l) 6744099b7bSPaul Traina #define bcmp(a,b,c) memcmp(a,b,c) 6844099b7bSPaul Traina #endif 6944099b7bSPaul Traina 7044099b7bSPaul Traina #include "bootp.h" 7144099b7bSPaul Traina #include "hash.h" 7244099b7bSPaul Traina #include "hwaddr.h" 7344099b7bSPaul Traina #include "bootpd.h" 7444099b7bSPaul Traina #include "dovend.h" 7544099b7bSPaul Traina #include "readfile.h" 7644099b7bSPaul Traina #include "report.h" 7744099b7bSPaul Traina #include "tzone.h" 7844099b7bSPaul Traina #include "patchlevel.h" 7944099b7bSPaul Traina 8044099b7bSPaul Traina #define BUFFERSIZE 0x4000 8144099b7bSPaul Traina 8244099b7bSPaul Traina #ifndef CONFIG_FILE 8344099b7bSPaul Traina #define CONFIG_FILE "/etc/bootptab" 8444099b7bSPaul Traina #endif 8544099b7bSPaul Traina 8644099b7bSPaul Traina 8744099b7bSPaul Traina 8844099b7bSPaul Traina /* 8944099b7bSPaul Traina * Externals, forward declarations, and global variables 9044099b7bSPaul Traina */ 9144099b7bSPaul Traina 9244099b7bSPaul Traina #ifdef __STDC__ 9344099b7bSPaul Traina #define P(args) args 9444099b7bSPaul Traina #else 9544099b7bSPaul Traina #define P(args) () 9644099b7bSPaul Traina #endif 9744099b7bSPaul Traina 9844099b7bSPaul Traina static void mktagfile P((struct host *)); 9944099b7bSPaul Traina static void usage P((void)); 10044099b7bSPaul Traina 10144099b7bSPaul Traina #undef P 10244099b7bSPaul Traina 10344099b7bSPaul Traina 10444099b7bSPaul Traina /* 10544099b7bSPaul Traina * General 10644099b7bSPaul Traina */ 10744099b7bSPaul Traina 10844099b7bSPaul Traina char *progname; 10944099b7bSPaul Traina char *chdir_path; 11044099b7bSPaul Traina int debug = 0; /* Debugging flag (level) */ 11144099b7bSPaul Traina byte *buffer; 11244099b7bSPaul Traina 11344099b7bSPaul Traina /* 11444099b7bSPaul Traina * Globals below are associated with the bootp database file (bootptab). 11544099b7bSPaul Traina */ 11644099b7bSPaul Traina 11744099b7bSPaul Traina char *bootptab = CONFIG_FILE; 11844099b7bSPaul Traina 11944099b7bSPaul Traina 12044099b7bSPaul Traina /* 12144099b7bSPaul Traina * Print "usage" message and exit 12244099b7bSPaul Traina */ 12344099b7bSPaul Traina static void 12444099b7bSPaul Traina usage() 12544099b7bSPaul Traina { 12644099b7bSPaul Traina fprintf(stderr, 12744099b7bSPaul Traina "usage: $s [ -c chdir ] [-d level] [-f configfile] [host...]\n"); 12844099b7bSPaul Traina fprintf(stderr, "\t -c n\tset current directory\n"); 12944099b7bSPaul Traina fprintf(stderr, "\t -d n\tset debug level\n"); 13044099b7bSPaul Traina fprintf(stderr, "\t -f n\tconfig file name\n"); 13144099b7bSPaul Traina exit(1); 13244099b7bSPaul Traina } 13344099b7bSPaul Traina 13444099b7bSPaul Traina 13544099b7bSPaul Traina /* 13644099b7bSPaul Traina * Initialization such as command-line processing is done and then the 13744099b7bSPaul Traina * main server loop is started. 13844099b7bSPaul Traina */ 13944099b7bSPaul Traina void 14044099b7bSPaul Traina main(argc, argv) 14144099b7bSPaul Traina int argc; 14244099b7bSPaul Traina char **argv; 14344099b7bSPaul Traina { 14444099b7bSPaul Traina struct host *hp; 14544099b7bSPaul Traina char *stmp; 14644099b7bSPaul Traina int n; 14744099b7bSPaul Traina 14844099b7bSPaul Traina progname = strrchr(argv[0], '/'); 14944099b7bSPaul Traina if (progname) progname++; 15044099b7bSPaul Traina else progname = argv[0]; 15144099b7bSPaul Traina 15244099b7bSPaul Traina /* Get work space for making tag 18 files. */ 15344099b7bSPaul Traina buffer = (byte *) malloc(BUFFERSIZE); 15444099b7bSPaul Traina if (!buffer) { 15544099b7bSPaul Traina report(LOG_ERR, "malloc failed"); 15644099b7bSPaul Traina exit(1); 15744099b7bSPaul Traina } 15844099b7bSPaul Traina /* 15944099b7bSPaul Traina * Set defaults that might be changed by option switches. 16044099b7bSPaul Traina */ 16144099b7bSPaul Traina stmp = NULL; 16244099b7bSPaul Traina 16344099b7bSPaul Traina /* 16444099b7bSPaul Traina * Read switches. 16544099b7bSPaul Traina */ 16644099b7bSPaul Traina for (argc--, argv++; argc > 0; argc--, argv++) { 16744099b7bSPaul Traina if (argv[0][0] != '-') 16844099b7bSPaul Traina break; 16944099b7bSPaul Traina switch (argv[0][1]) { 17044099b7bSPaul Traina 17144099b7bSPaul Traina case 'c': /* chdir_path */ 17244099b7bSPaul Traina if (argv[0][2]) { 17344099b7bSPaul Traina stmp = &(argv[0][2]); 17444099b7bSPaul Traina } else { 17544099b7bSPaul Traina argc--; 17644099b7bSPaul Traina argv++; 17744099b7bSPaul Traina stmp = argv[0]; 17844099b7bSPaul Traina } 17944099b7bSPaul Traina if (!stmp || (stmp[0] != '/')) { 18044099b7bSPaul Traina fprintf(stderr, 18144099b7bSPaul Traina "bootpd: invalid chdir specification\n"); 18244099b7bSPaul Traina break; 18344099b7bSPaul Traina } 18444099b7bSPaul Traina chdir_path = stmp; 18544099b7bSPaul Traina break; 18644099b7bSPaul Traina 18744099b7bSPaul Traina case 'd': /* debug */ 18844099b7bSPaul Traina if (argv[0][2]) { 18944099b7bSPaul Traina stmp = &(argv[0][2]); 19044099b7bSPaul Traina } else if (argv[1] && argv[1][0] == '-') { 19144099b7bSPaul Traina /* 19244099b7bSPaul Traina * Backwards-compatible behavior: 19344099b7bSPaul Traina * no parameter, so just increment the debug flag. 19444099b7bSPaul Traina */ 19544099b7bSPaul Traina debug++; 19644099b7bSPaul Traina break; 19744099b7bSPaul Traina } else { 19844099b7bSPaul Traina argc--; 19944099b7bSPaul Traina argv++; 20044099b7bSPaul Traina stmp = argv[0]; 20144099b7bSPaul Traina } 20244099b7bSPaul Traina if (!stmp || (sscanf(stmp, "%d", &n) != 1) || (n < 0)) { 20344099b7bSPaul Traina fprintf(stderr, 20444099b7bSPaul Traina "bootpd: invalid debug level\n"); 20544099b7bSPaul Traina break; 20644099b7bSPaul Traina } 20744099b7bSPaul Traina debug = n; 20844099b7bSPaul Traina break; 20944099b7bSPaul Traina 21044099b7bSPaul Traina case 'f': /* config file */ 21144099b7bSPaul Traina if (argv[0][2]) { 21244099b7bSPaul Traina stmp = &(argv[0][2]); 21344099b7bSPaul Traina } else { 21444099b7bSPaul Traina argc--; 21544099b7bSPaul Traina argv++; 21644099b7bSPaul Traina stmp = argv[0]; 21744099b7bSPaul Traina } 21844099b7bSPaul Traina bootptab = stmp; 21944099b7bSPaul Traina break; 22044099b7bSPaul Traina 22144099b7bSPaul Traina default: 22244099b7bSPaul Traina fprintf(stderr, "bootpd: unknown switch: -%c\n", 22344099b7bSPaul Traina argv[0][1]); 22444099b7bSPaul Traina usage(); 22544099b7bSPaul Traina break; 22644099b7bSPaul Traina } 22744099b7bSPaul Traina } 22844099b7bSPaul Traina 22944099b7bSPaul Traina /* Get the timezone. */ 23044099b7bSPaul Traina tzone_init(); 23144099b7bSPaul Traina 23244099b7bSPaul Traina /* Allocate hash tables. */ 23344099b7bSPaul Traina rdtab_init(); 23444099b7bSPaul Traina 23544099b7bSPaul Traina /* 23644099b7bSPaul Traina * Read the bootptab file. 23744099b7bSPaul Traina */ 23844099b7bSPaul Traina readtab(1); /* force read */ 23944099b7bSPaul Traina 24044099b7bSPaul Traina /* Set the cwd (i.e. to /tftpboot) */ 24144099b7bSPaul Traina if (chdir_path) { 24244099b7bSPaul Traina if (chdir(chdir_path) < 0) 24344099b7bSPaul Traina report(LOG_ERR, "%s: chdir failed", chdir_path); 24444099b7bSPaul Traina } 24544099b7bSPaul Traina /* If there are host names on the command line, do only those. */ 24644099b7bSPaul Traina if (argc > 0) { 24744099b7bSPaul Traina unsigned int tlen, hashcode; 24844099b7bSPaul Traina 24944099b7bSPaul Traina while (argc) { 25044099b7bSPaul Traina tlen = strlen(argv[0]); 25144099b7bSPaul Traina hashcode = hash_HashFunction((u_char *)argv[0], tlen); 25244099b7bSPaul Traina hp = (struct host *) hash_Lookup(nmhashtable, 25344099b7bSPaul Traina hashcode, 25444099b7bSPaul Traina nmcmp, argv[0]); 25544099b7bSPaul Traina if (!hp) { 25644099b7bSPaul Traina printf("%s: no matching entry\n", argv[0]); 25744099b7bSPaul Traina exit(1); 25844099b7bSPaul Traina } 25944099b7bSPaul Traina if (!hp->flags.exten_file) { 26044099b7bSPaul Traina printf("%s: no extension file\n", argv[0]); 26144099b7bSPaul Traina exit(1); 26244099b7bSPaul Traina } 26344099b7bSPaul Traina mktagfile(hp); 26444099b7bSPaul Traina argv++; 26544099b7bSPaul Traina argc--; 26644099b7bSPaul Traina } 26744099b7bSPaul Traina exit(0); 26844099b7bSPaul Traina } 26944099b7bSPaul Traina /* No host names specified. Do them all. */ 27044099b7bSPaul Traina hp = (struct host *) hash_FirstEntry(nmhashtable); 27144099b7bSPaul Traina while (hp != NULL) { 27244099b7bSPaul Traina mktagfile(hp); 27344099b7bSPaul Traina hp = (struct host *) hash_NextEntry(nmhashtable); 27444099b7bSPaul Traina } 27544099b7bSPaul Traina } 27644099b7bSPaul Traina 27744099b7bSPaul Traina 27844099b7bSPaul Traina 27944099b7bSPaul Traina /* 28044099b7bSPaul Traina * Make a "TAG 18" file for this host. 28144099b7bSPaul Traina * (Insert the RFC1497 options.) 28244099b7bSPaul Traina */ 28344099b7bSPaul Traina 28444099b7bSPaul Traina static void 28544099b7bSPaul Traina mktagfile(hp) 28644099b7bSPaul Traina struct host *hp; 28744099b7bSPaul Traina { 28844099b7bSPaul Traina FILE *fp; 28944099b7bSPaul Traina int bytesleft, len; 29044099b7bSPaul Traina byte *vp; 29144099b7bSPaul Traina 29244099b7bSPaul Traina if (!hp->flags.exten_file) 29344099b7bSPaul Traina return; 29444099b7bSPaul Traina 29544099b7bSPaul Traina vp = buffer; 29644099b7bSPaul Traina bytesleft = BUFFERSIZE; 29744099b7bSPaul Traina bcopy(vm_rfc1048, vp, 4); /* Copy in the magic cookie */ 29844099b7bSPaul Traina vp += 4; 29944099b7bSPaul Traina bytesleft -= 4; 30044099b7bSPaul Traina 30144099b7bSPaul Traina /* 30244099b7bSPaul Traina * The "extension file" options are appended by the following 30344099b7bSPaul Traina * function (which is shared with bootpd.c). 30444099b7bSPaul Traina */ 30544099b7bSPaul Traina len = dovend_rfc1497(hp, vp, bytesleft); 30644099b7bSPaul Traina vp += len; 30744099b7bSPaul Traina bytesleft -= len; 30844099b7bSPaul Traina 30944099b7bSPaul Traina if (bytesleft < 1) { 31044099b7bSPaul Traina report(LOG_ERR, "%s: too much option data", 31144099b7bSPaul Traina hp->exten_file->string); 31244099b7bSPaul Traina return; 31344099b7bSPaul Traina } 31444099b7bSPaul Traina *vp++ = TAG_END; 31544099b7bSPaul Traina bytesleft--; 31644099b7bSPaul Traina 31744099b7bSPaul Traina /* Write the buffer to the extension file. */ 31844099b7bSPaul Traina printf("Updating \"%s\"\n", hp->exten_file->string); 31944099b7bSPaul Traina if ((fp = fopen(hp->exten_file->string, "w")) == NULL) { 32044099b7bSPaul Traina report(LOG_ERR, "error opening \"%s\": %s", 32144099b7bSPaul Traina hp->exten_file->string, get_errmsg()); 32244099b7bSPaul Traina return; 32344099b7bSPaul Traina } 32444099b7bSPaul Traina len = vp - buffer; 32544099b7bSPaul Traina if (len != fwrite(buffer, 1, len, fp)) { 32644099b7bSPaul Traina report(LOG_ERR, "write failed on \"%s\" : %s", 32744099b7bSPaul Traina hp->exten_file->string, get_errmsg()); 32844099b7bSPaul Traina } 32944099b7bSPaul Traina fclose(fp); 33044099b7bSPaul Traina 331e08ac58bSPaul Traina } /* mktagfile */ 33244099b7bSPaul Traina 33344099b7bSPaul Traina /* 33444099b7bSPaul Traina * Local Variables: 33544099b7bSPaul Traina * tab-width: 4 33644099b7bSPaul Traina * c-indent-level: 4 33744099b7bSPaul Traina * c-argdecl-indent: 4 33844099b7bSPaul Traina * c-continued-statement-offset: 4 33944099b7bSPaul Traina * c-continued-brace-offset: -4 34044099b7bSPaul Traina * c-label-offset: -4 34144099b7bSPaul Traina * c-brace-offset: 0 34244099b7bSPaul Traina * End: 34344099b7bSPaul Traina */ 344