bootpef.c revision 13572
13229Spst/************************************************************************ 23229Spst Copyright 1988, 1991 by Carnegie Mellon University 33229Spst 43229Spst All Rights Reserved 53229Spst 63229SpstPermission to use, copy, modify, and distribute this software and its 73229Spstdocumentation for any purpose and without fee is hereby granted, provided 83229Spstthat the above copyright notice appear in all copies and that both that 93229Spstcopyright notice and this permission notice appear in supporting 103229Spstdocumentation, and that the name of Carnegie Mellon University not be used 113229Spstin advertising or publicity pertaining to distribution of the software 123229Spstwithout specific, written prior permission. 133229Spst 143229SpstCARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 153229SpstSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. 163229SpstIN NO EVENT SHALL CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 173229SpstDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 183229SpstPROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 193229SpstACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 203229SpstSOFTWARE. 213229Spst************************************************************************/ 223229Spst 233229Spst/* 243229Spst * bootpef - BOOTP Extension File generator 253229Spst * Makes an "Extension File" for each host entry that 263229Spst * defines an and Extension File. (See RFC1497, tag 18.) 273229Spst * 283229Spst * HISTORY 293229Spst * See ./Changes 303229Spst * 313229Spst * BUGS 323229Spst * See ./ToDo 333229Spst */ 343229Spst 353229Spst 363229Spst 373229Spst#ifdef __STDC__ 383229Spst#include <stdarg.h> 393229Spst#else 403229Spst#include <varargs.h> 413229Spst#endif 423229Spst 433229Spst#include <sys/types.h> 443229Spst#include <sys/time.h> 453229Spst 463229Spst#include <netinet/in.h> 473229Spst#include <arpa/inet.h> /* inet_ntoa */ 483229Spst 493229Spst#ifndef NO_UNISTD 503229Spst#include <unistd.h> 513229Spst#endif 523229Spst#include <stdlib.h> 533229Spst#include <stdio.h> 543229Spst#include <string.h> 553229Spst#include <errno.h> 563229Spst#include <ctype.h> 573229Spst#include <syslog.h> 583229Spst 593229Spst#ifndef USE_BFUNCS 603229Spst#include <memory.h> 613229Spst/* Yes, memcpy is OK here (no overlapped copies). */ 623229Spst#define bcopy(a,b,c) memcpy(b,a,c) 633229Spst#define bzero(p,l) memset(p,0,l) 643229Spst#define bcmp(a,b,c) memcmp(a,b,c) 653229Spst#endif 663229Spst 673229Spst#include "bootp.h" 683229Spst#include "hash.h" 693229Spst#include "hwaddr.h" 703229Spst#include "bootpd.h" 713229Spst#include "dovend.h" 723229Spst#include "readfile.h" 733229Spst#include "report.h" 743229Spst#include "tzone.h" 753229Spst#include "patchlevel.h" 763229Spst 773229Spst#define BUFFERSIZE 0x4000 783229Spst 793229Spst#ifndef CONFIG_FILE 803229Spst#define CONFIG_FILE "/etc/bootptab" 813229Spst#endif 823229Spst 833229Spst 843229Spst 853229Spst/* 863229Spst * Externals, forward declarations, and global variables 873229Spst */ 883229Spst 893229Spst#ifdef __STDC__ 903229Spst#define P(args) args 913229Spst#else 923229Spst#define P(args) () 933229Spst#endif 943229Spst 953229Spststatic void mktagfile P((struct host *)); 963229Spststatic void usage P((void)); 973229Spst 983229Spst#undef P 993229Spst 1003229Spst 1013229Spst/* 1023229Spst * General 1033229Spst */ 1043229Spst 1053229Spstchar *progname; 1063229Spstchar *chdir_path; 1073229Spstint debug = 0; /* Debugging flag (level) */ 1083229Spstbyte *buffer; 1093229Spst 1103229Spst/* 1113229Spst * Globals below are associated with the bootp database file (bootptab). 1123229Spst */ 1133229Spst 1143229Spstchar *bootptab = CONFIG_FILE; 1153229Spst 1163229Spst 1173229Spst/* 1183229Spst * Print "usage" message and exit 1193229Spst */ 1203229Spststatic void 1213229Spstusage() 1223229Spst{ 1233229Spst fprintf(stderr, 1243229Spst "usage: $s [ -c chdir ] [-d level] [-f configfile] [host...]\n"); 1253229Spst fprintf(stderr, "\t -c n\tset current directory\n"); 1263229Spst fprintf(stderr, "\t -d n\tset debug level\n"); 1273229Spst fprintf(stderr, "\t -f n\tconfig file name\n"); 1283229Spst exit(1); 1293229Spst} 1303229Spst 1313229Spst 1323229Spst/* 1333229Spst * Initialization such as command-line processing is done and then the 1343229Spst * main server loop is started. 1353229Spst */ 1363229Spstvoid 1373229Spstmain(argc, argv) 1383229Spst int argc; 1393229Spst char **argv; 1403229Spst{ 1413229Spst struct host *hp; 1423229Spst char *stmp; 1433229Spst int n; 1443229Spst 1453229Spst progname = strrchr(argv[0], '/'); 1463229Spst if (progname) progname++; 1473229Spst else progname = argv[0]; 1483229Spst 1493229Spst /* Get work space for making tag 18 files. */ 1503229Spst buffer = (byte *) malloc(BUFFERSIZE); 1513229Spst if (!buffer) { 1523229Spst report(LOG_ERR, "malloc failed"); 1533229Spst exit(1); 1543229Spst } 1553229Spst /* 1563229Spst * Set defaults that might be changed by option switches. 1573229Spst */ 1583229Spst stmp = NULL; 1593229Spst 1603229Spst /* 1613229Spst * Read switches. 1623229Spst */ 1633229Spst for (argc--, argv++; argc > 0; argc--, argv++) { 1643229Spst if (argv[0][0] != '-') 1653229Spst break; 1663229Spst switch (argv[0][1]) { 1673229Spst 1683229Spst case 'c': /* chdir_path */ 1693229Spst if (argv[0][2]) { 1703229Spst stmp = &(argv[0][2]); 1713229Spst } else { 1723229Spst argc--; 1733229Spst argv++; 1743229Spst stmp = argv[0]; 1753229Spst } 1763229Spst if (!stmp || (stmp[0] != '/')) { 1773229Spst fprintf(stderr, 1783229Spst "bootpd: invalid chdir specification\n"); 1793229Spst break; 1803229Spst } 1813229Spst chdir_path = stmp; 1823229Spst break; 1833229Spst 1843229Spst case 'd': /* debug */ 1853229Spst if (argv[0][2]) { 1863229Spst stmp = &(argv[0][2]); 1873229Spst } else if (argv[1] && argv[1][0] == '-') { 1883229Spst /* 1893229Spst * Backwards-compatible behavior: 1903229Spst * no parameter, so just increment the debug flag. 1913229Spst */ 1923229Spst debug++; 1933229Spst break; 1943229Spst } else { 1953229Spst argc--; 1963229Spst argv++; 1973229Spst stmp = argv[0]; 1983229Spst } 1993229Spst if (!stmp || (sscanf(stmp, "%d", &n) != 1) || (n < 0)) { 2003229Spst fprintf(stderr, 2013229Spst "bootpd: invalid debug level\n"); 2023229Spst break; 2033229Spst } 2043229Spst debug = n; 2053229Spst break; 2063229Spst 2073229Spst case 'f': /* config file */ 2083229Spst if (argv[0][2]) { 2093229Spst stmp = &(argv[0][2]); 2103229Spst } else { 2113229Spst argc--; 2123229Spst argv++; 2133229Spst stmp = argv[0]; 2143229Spst } 2153229Spst bootptab = stmp; 2163229Spst break; 2173229Spst 2183229Spst default: 2193229Spst fprintf(stderr, "bootpd: unknown switch: -%c\n", 2203229Spst argv[0][1]); 2213229Spst usage(); 2223229Spst break; 2233229Spst } 2243229Spst } 2253229Spst 2263229Spst /* Get the timezone. */ 2273229Spst tzone_init(); 2283229Spst 2293229Spst /* Allocate hash tables. */ 2303229Spst rdtab_init(); 2313229Spst 2323229Spst /* 2333229Spst * Read the bootptab file. 2343229Spst */ 2353229Spst readtab(1); /* force read */ 2363229Spst 2373229Spst /* Set the cwd (i.e. to /tftpboot) */ 2383229Spst if (chdir_path) { 2393229Spst if (chdir(chdir_path) < 0) 2403229Spst report(LOG_ERR, "%s: chdir failed", chdir_path); 2413229Spst } 2423229Spst /* If there are host names on the command line, do only those. */ 2433229Spst if (argc > 0) { 2443229Spst unsigned int tlen, hashcode; 2453229Spst 2463229Spst while (argc) { 2473229Spst tlen = strlen(argv[0]); 2483229Spst hashcode = hash_HashFunction((u_char *)argv[0], tlen); 2493229Spst hp = (struct host *) hash_Lookup(nmhashtable, 2503229Spst hashcode, 2513229Spst nmcmp, argv[0]); 2523229Spst if (!hp) { 2533229Spst printf("%s: no matching entry\n", argv[0]); 2543229Spst exit(1); 2553229Spst } 2563229Spst if (!hp->flags.exten_file) { 2573229Spst printf("%s: no extension file\n", argv[0]); 2583229Spst exit(1); 2593229Spst } 2603229Spst mktagfile(hp); 2613229Spst argv++; 2623229Spst argc--; 2633229Spst } 2643229Spst exit(0); 2653229Spst } 2663229Spst /* No host names specified. Do them all. */ 2673229Spst hp = (struct host *) hash_FirstEntry(nmhashtable); 2683229Spst while (hp != NULL) { 2693229Spst mktagfile(hp); 2703229Spst hp = (struct host *) hash_NextEntry(nmhashtable); 2713229Spst } 2723229Spst} 2733229Spst 2743229Spst 2753229Spst 2763229Spst/* 2773229Spst * Make a "TAG 18" file for this host. 2783229Spst * (Insert the RFC1497 options.) 2793229Spst */ 2803229Spst 2813229Spststatic void 2823229Spstmktagfile(hp) 2833229Spst struct host *hp; 2843229Spst{ 2853229Spst FILE *fp; 2863229Spst int bytesleft, len; 2873229Spst byte *vp; 2883229Spst 2893229Spst if (!hp->flags.exten_file) 2903229Spst return; 2913229Spst 2923229Spst vp = buffer; 2933229Spst bytesleft = BUFFERSIZE; 2943229Spst bcopy(vm_rfc1048, vp, 4); /* Copy in the magic cookie */ 2953229Spst vp += 4; 2963229Spst bytesleft -= 4; 2973229Spst 2983229Spst /* 2993229Spst * The "extension file" options are appended by the following 3003229Spst * function (which is shared with bootpd.c). 3013229Spst */ 3023229Spst len = dovend_rfc1497(hp, vp, bytesleft); 3033229Spst vp += len; 3043229Spst bytesleft -= len; 3053229Spst 3063229Spst if (bytesleft < 1) { 3073229Spst report(LOG_ERR, "%s: too much option data", 3083229Spst hp->exten_file->string); 3093229Spst return; 3103229Spst } 3113229Spst *vp++ = TAG_END; 3123229Spst bytesleft--; 3133229Spst 3143229Spst /* Write the buffer to the extension file. */ 3153229Spst printf("Updating \"%s\"\n", hp->exten_file->string); 3163229Spst if ((fp = fopen(hp->exten_file->string, "w")) == NULL) { 3173229Spst report(LOG_ERR, "error opening \"%s\": %s", 3183229Spst hp->exten_file->string, get_errmsg()); 3193229Spst return; 3203229Spst } 3213229Spst len = vp - buffer; 3223229Spst if (len != fwrite(buffer, 1, len, fp)) { 3233229Spst report(LOG_ERR, "write failed on \"%s\" : %s", 3243229Spst hp->exten_file->string, get_errmsg()); 3253229Spst } 3263229Spst fclose(fp); 3273229Spst 32813572Spst} /* mktagfile */ 3293229Spst 3303229Spst/* 3313229Spst * Local Variables: 3323229Spst * tab-width: 4 3333229Spst * c-indent-level: 4 3343229Spst * c-argdecl-indent: 4 3353229Spst * c-continued-statement-offset: 4 3363229Spst * c-continued-brace-offset: -4 3373229Spst * c-label-offset: -4 3383229Spst * c-brace-offset: 0 3393229Spst * End: 3403229Spst */ 341