bootpef.c revision 46078
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. 2118471Swosch 2246078Simp $Id: bootpef.c,v 1.4 1997/02/22 14:21:18 peter Exp $ 2318471Swosch 243229Spst************************************************************************/ 253229Spst 263229Spst/* 273229Spst * bootpef - BOOTP Extension File generator 283229Spst * Makes an "Extension File" for each host entry that 293229Spst * defines an and Extension File. (See RFC1497, tag 18.) 303229Spst * 313229Spst * HISTORY 323229Spst * See ./Changes 333229Spst * 343229Spst * BUGS 353229Spst * See ./ToDo 363229Spst */ 373229Spst 383229Spst 393229Spst 403229Spst#ifdef __STDC__ 413229Spst#include <stdarg.h> 423229Spst#else 433229Spst#include <varargs.h> 443229Spst#endif 453229Spst 463229Spst#include <sys/types.h> 473229Spst#include <sys/time.h> 483229Spst 493229Spst#include <netinet/in.h> 503229Spst#include <arpa/inet.h> /* inet_ntoa */ 513229Spst 523229Spst#ifndef NO_UNISTD 533229Spst#include <unistd.h> 543229Spst#endif 553229Spst#include <stdlib.h> 563229Spst#include <stdio.h> 573229Spst#include <string.h> 583229Spst#include <errno.h> 593229Spst#include <ctype.h> 603229Spst#include <syslog.h> 613229Spst 623229Spst#ifndef USE_BFUNCS 633229Spst#include <memory.h> 643229Spst/* Yes, memcpy is OK here (no overlapped copies). */ 653229Spst#define bcopy(a,b,c) memcpy(b,a,c) 663229Spst#define bzero(p,l) memset(p,0,l) 673229Spst#define bcmp(a,b,c) memcmp(a,b,c) 683229Spst#endif 693229Spst 703229Spst#include "bootp.h" 713229Spst#include "hash.h" 723229Spst#include "hwaddr.h" 733229Spst#include "bootpd.h" 743229Spst#include "dovend.h" 753229Spst#include "readfile.h" 763229Spst#include "report.h" 773229Spst#include "tzone.h" 783229Spst#include "patchlevel.h" 793229Spst 803229Spst#define BUFFERSIZE 0x4000 813229Spst 823229Spst#ifndef CONFIG_FILE 833229Spst#define CONFIG_FILE "/etc/bootptab" 843229Spst#endif 853229Spst 863229Spst 873229Spst 883229Spst/* 893229Spst * Externals, forward declarations, and global variables 903229Spst */ 913229Spst 923229Spst#ifdef __STDC__ 933229Spst#define P(args) args 943229Spst#else 953229Spst#define P(args) () 963229Spst#endif 973229Spst 983229Spststatic void mktagfile P((struct host *)); 993229Spststatic void usage P((void)); 1003229Spst 1013229Spst#undef P 1023229Spst 1033229Spst 1043229Spst/* 1053229Spst * General 1063229Spst */ 1073229Spst 1083229Spstchar *progname; 1093229Spstchar *chdir_path; 1103229Spstint debug = 0; /* Debugging flag (level) */ 1113229Spstbyte *buffer; 1123229Spst 1133229Spst/* 1143229Spst * Globals below are associated with the bootp database file (bootptab). 1153229Spst */ 1163229Spst 1173229Spstchar *bootptab = CONFIG_FILE; 1183229Spst 1193229Spst 1203229Spst/* 1213229Spst * Print "usage" message and exit 1223229Spst */ 1233229Spststatic void 1243229Spstusage() 1253229Spst{ 1263229Spst fprintf(stderr, 1273229Spst "usage: $s [ -c chdir ] [-d level] [-f configfile] [host...]\n"); 1283229Spst fprintf(stderr, "\t -c n\tset current directory\n"); 1293229Spst fprintf(stderr, "\t -d n\tset debug level\n"); 1303229Spst fprintf(stderr, "\t -f n\tconfig file name\n"); 1313229Spst exit(1); 1323229Spst} 1333229Spst 1343229Spst 1353229Spst/* 1363229Spst * Initialization such as command-line processing is done and then the 1373229Spst * main server loop is started. 1383229Spst */ 13946078Simpint 1403229Spstmain(argc, argv) 1413229Spst int argc; 1423229Spst char **argv; 1433229Spst{ 1443229Spst struct host *hp; 1453229Spst char *stmp; 1463229Spst int n; 1473229Spst 1483229Spst progname = strrchr(argv[0], '/'); 1493229Spst if (progname) progname++; 1503229Spst else progname = argv[0]; 1513229Spst 1523229Spst /* Get work space for making tag 18 files. */ 1533229Spst buffer = (byte *) malloc(BUFFERSIZE); 1543229Spst if (!buffer) { 1553229Spst report(LOG_ERR, "malloc failed"); 1563229Spst exit(1); 1573229Spst } 1583229Spst /* 1593229Spst * Set defaults that might be changed by option switches. 1603229Spst */ 1613229Spst stmp = NULL; 1623229Spst 1633229Spst /* 1643229Spst * Read switches. 1653229Spst */ 1663229Spst for (argc--, argv++; argc > 0; argc--, argv++) { 1673229Spst if (argv[0][0] != '-') 1683229Spst break; 1693229Spst switch (argv[0][1]) { 1703229Spst 1713229Spst case 'c': /* chdir_path */ 1723229Spst if (argv[0][2]) { 1733229Spst stmp = &(argv[0][2]); 1743229Spst } else { 1753229Spst argc--; 1763229Spst argv++; 1773229Spst stmp = argv[0]; 1783229Spst } 1793229Spst if (!stmp || (stmp[0] != '/')) { 1803229Spst fprintf(stderr, 1813229Spst "bootpd: invalid chdir specification\n"); 1823229Spst break; 1833229Spst } 1843229Spst chdir_path = stmp; 1853229Spst break; 1863229Spst 1873229Spst case 'd': /* debug */ 1883229Spst if (argv[0][2]) { 1893229Spst stmp = &(argv[0][2]); 1903229Spst } else if (argv[1] && argv[1][0] == '-') { 1913229Spst /* 1923229Spst * Backwards-compatible behavior: 1933229Spst * no parameter, so just increment the debug flag. 1943229Spst */ 1953229Spst debug++; 1963229Spst break; 1973229Spst } else { 1983229Spst argc--; 1993229Spst argv++; 2003229Spst stmp = argv[0]; 2013229Spst } 2023229Spst if (!stmp || (sscanf(stmp, "%d", &n) != 1) || (n < 0)) { 2033229Spst fprintf(stderr, 2043229Spst "bootpd: invalid debug level\n"); 2053229Spst break; 2063229Spst } 2073229Spst debug = n; 2083229Spst break; 2093229Spst 2103229Spst case 'f': /* config file */ 2113229Spst if (argv[0][2]) { 2123229Spst stmp = &(argv[0][2]); 2133229Spst } else { 2143229Spst argc--; 2153229Spst argv++; 2163229Spst stmp = argv[0]; 2173229Spst } 2183229Spst bootptab = stmp; 2193229Spst break; 2203229Spst 2213229Spst default: 2223229Spst fprintf(stderr, "bootpd: unknown switch: -%c\n", 2233229Spst argv[0][1]); 2243229Spst usage(); 2253229Spst break; 2263229Spst } 2273229Spst } 2283229Spst 2293229Spst /* Get the timezone. */ 2303229Spst tzone_init(); 2313229Spst 2323229Spst /* Allocate hash tables. */ 2333229Spst rdtab_init(); 2343229Spst 2353229Spst /* 2363229Spst * Read the bootptab file. 2373229Spst */ 2383229Spst readtab(1); /* force read */ 2393229Spst 2403229Spst /* Set the cwd (i.e. to /tftpboot) */ 2413229Spst if (chdir_path) { 2423229Spst if (chdir(chdir_path) < 0) 2433229Spst report(LOG_ERR, "%s: chdir failed", chdir_path); 2443229Spst } 2453229Spst /* If there are host names on the command line, do only those. */ 2463229Spst if (argc > 0) { 2473229Spst unsigned int tlen, hashcode; 2483229Spst 2493229Spst while (argc) { 2503229Spst tlen = strlen(argv[0]); 2513229Spst hashcode = hash_HashFunction((u_char *)argv[0], tlen); 2523229Spst hp = (struct host *) hash_Lookup(nmhashtable, 2533229Spst hashcode, 2543229Spst nmcmp, argv[0]); 2553229Spst if (!hp) { 2563229Spst printf("%s: no matching entry\n", argv[0]); 2573229Spst exit(1); 2583229Spst } 2593229Spst if (!hp->flags.exten_file) { 2603229Spst printf("%s: no extension file\n", argv[0]); 2613229Spst exit(1); 2623229Spst } 2633229Spst mktagfile(hp); 2643229Spst argv++; 2653229Spst argc--; 2663229Spst } 2673229Spst exit(0); 2683229Spst } 2693229Spst /* No host names specified. Do them all. */ 2703229Spst hp = (struct host *) hash_FirstEntry(nmhashtable); 2713229Spst while (hp != NULL) { 2723229Spst mktagfile(hp); 2733229Spst hp = (struct host *) hash_NextEntry(nmhashtable); 2743229Spst } 27546078Simp return (0); 2763229Spst} 2773229Spst 2783229Spst 2793229Spst 2803229Spst/* 2813229Spst * Make a "TAG 18" file for this host. 2823229Spst * (Insert the RFC1497 options.) 2833229Spst */ 2843229Spst 2853229Spststatic void 2863229Spstmktagfile(hp) 2873229Spst struct host *hp; 2883229Spst{ 2893229Spst FILE *fp; 2903229Spst int bytesleft, len; 2913229Spst byte *vp; 2923229Spst 2933229Spst if (!hp->flags.exten_file) 2943229Spst return; 2953229Spst 2963229Spst vp = buffer; 2973229Spst bytesleft = BUFFERSIZE; 2983229Spst bcopy(vm_rfc1048, vp, 4); /* Copy in the magic cookie */ 2993229Spst vp += 4; 3003229Spst bytesleft -= 4; 3013229Spst 3023229Spst /* 3033229Spst * The "extension file" options are appended by the following 3043229Spst * function (which is shared with bootpd.c). 3053229Spst */ 3063229Spst len = dovend_rfc1497(hp, vp, bytesleft); 3073229Spst vp += len; 3083229Spst bytesleft -= len; 3093229Spst 3103229Spst if (bytesleft < 1) { 3113229Spst report(LOG_ERR, "%s: too much option data", 3123229Spst hp->exten_file->string); 3133229Spst return; 3143229Spst } 3153229Spst *vp++ = TAG_END; 3163229Spst bytesleft--; 3173229Spst 3183229Spst /* Write the buffer to the extension file. */ 3193229Spst printf("Updating \"%s\"\n", hp->exten_file->string); 3203229Spst if ((fp = fopen(hp->exten_file->string, "w")) == NULL) { 3213229Spst report(LOG_ERR, "error opening \"%s\": %s", 3223229Spst hp->exten_file->string, get_errmsg()); 3233229Spst return; 3243229Spst } 3253229Spst len = vp - buffer; 3263229Spst if (len != fwrite(buffer, 1, len, fp)) { 3273229Spst report(LOG_ERR, "write failed on \"%s\" : %s", 3283229Spst hp->exten_file->string, get_errmsg()); 3293229Spst } 3303229Spst fclose(fp); 3313229Spst 33213572Spst} /* mktagfile */ 3333229Spst 3343229Spst/* 3353229Spst * Local Variables: 3363229Spst * tab-width: 4 3373229Spst * c-indent-level: 4 3383229Spst * c-argdecl-indent: 4 3393229Spst * c-continued-statement-offset: 4 3403229Spst * c-continued-brace-offset: -4 3413229Spst * c-label-offset: -4 3423229Spst * c-brace-offset: 0 3433229Spst * End: 3443229Spst */ 345