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