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