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