bootpef.c revision 46078
197364Stjr/************************************************************************
297364Stjr          Copyright 1988, 1991 by Carnegie Mellon University
397364Stjr
497364Stjr                          All Rights Reserved
597364Stjr
697364StjrPermission to use, copy, modify, and distribute this software and its
797364Stjrdocumentation for any purpose and without fee is hereby granted, provided
897364Stjrthat the above copyright notice appear in all copies and that both that
997364Stjrcopyright notice and this permission notice appear in supporting
1097364Stjrdocumentation, and that the name of Carnegie Mellon University not be used
1197364Stjrin advertising or publicity pertaining to distribution of the software
1297364Stjrwithout specific, written prior permission.
1397364Stjr
1497364StjrCARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
1597364StjrSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
1697364StjrIN NO EVENT SHALL CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
1797364StjrDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
1897364StjrPROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
1997364StjrACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2097364StjrSOFTWARE.
2197364Stjr
2297364Stjr	$Id: bootpef.c,v 1.4 1997/02/22 14:21:18 peter Exp $
2397364Stjr
2497364Stjr************************************************************************/
2597364Stjr
2697364Stjr/*
2797364Stjr * bootpef - BOOTP Extension File generator
2897364Stjr *	Makes an "Extension File" for each host entry that
2997364Stjr *	defines an and Extension File. (See RFC1497, tag 18.)
3097364Stjr *
3197364Stjr * HISTORY
3297364Stjr *	See ./Changes
3397364Stjr *
3497364Stjr * BUGS
3597364Stjr *	See ./ToDo
3697364Stjr */
37200462Sdelphij
3897364Stjr
3997364Stjr
40200462Sdelphij#ifdef	__STDC__
4197364Stjr#include <stdarg.h>
4297364Stjr#else
4397364Stjr#include <varargs.h>
4497364Stjr#endif
4597364Stjr
4697364Stjr#include <sys/types.h>
4797364Stjr#include <sys/time.h>
4897364Stjr
4997364Stjr#include <netinet/in.h>
5097364Stjr#include <arpa/inet.h>			/* inet_ntoa */
5197364Stjr
5297364Stjr#ifndef	NO_UNISTD
5397364Stjr#include <unistd.h>
5497364Stjr#endif
5597364Stjr#include <stdlib.h>
5697364Stjr#include <stdio.h>
5797364Stjr#include <string.h>
5897364Stjr#include <errno.h>
5997364Stjr#include <ctype.h>
6097364Stjr#include <syslog.h>
6197364Stjr
6297364Stjr#ifndef	USE_BFUNCS
6397364Stjr#include <memory.h>
6497364Stjr/* Yes, memcpy is OK here (no overlapped copies). */
6597364Stjr#define bcopy(a,b,c)    memcpy(b,a,c)
6697364Stjr#define bzero(p,l)      memset(p,0,l)
6797364Stjr#define bcmp(a,b,c)     memcmp(a,b,c)
6897364Stjr#endif
6997364Stjr
7097364Stjr#include "bootp.h"
7197364Stjr#include "hash.h"
7297364Stjr#include "hwaddr.h"
7397364Stjr#include "bootpd.h"
7497364Stjr#include "dovend.h"
7597364Stjr#include "readfile.h"
76246553Sdes#include "report.h"
77246553Sdes#include "tzone.h"
7897364Stjr#include "patchlevel.h"
7997364Stjr
8097364Stjr#define	BUFFERSIZE   		0x4000
8197364Stjr
8297364Stjr#ifndef CONFIG_FILE
8397364Stjr#define CONFIG_FILE		"/etc/bootptab"
8497364Stjr#endif
8597364Stjr
8697364Stjr
8797364Stjr
8897364Stjr/*
8997364Stjr * Externals, forward declarations, and global variables
9097364Stjr */
9197364Stjr
9297364Stjr#ifdef	__STDC__
9397364Stjr#define P(args) args
9497364Stjr#else
9597364Stjr#define P(args) ()
9697364Stjr#endif
9797364Stjr
9897364Stjrstatic void mktagfile P((struct host *));
9997364Stjrstatic void usage P((void));
10097364Stjr
10197364Stjr#undef P
10297364Stjr
10397364Stjr
10497364Stjr/*
10597364Stjr * General
10697364Stjr */
10797364Stjr
10897364Stjrchar *progname;
10997364Stjrchar *chdir_path;
11097364Stjrint debug = 0;					/* Debugging flag (level) */
11197364Stjrbyte *buffer;
11297364Stjr
11397364Stjr/*
11497364Stjr * Globals below are associated with the bootp database file (bootptab).
11597364Stjr */
11697364Stjr
11797364Stjrchar *bootptab = CONFIG_FILE;
11897364Stjr
11997364Stjr
12097364Stjr/*
12197364Stjr * Print "usage" message and exit
12297364Stjr */
12397364Stjrstatic void
12497364Stjrusage()
12597364Stjr{
12697364Stjr	fprintf(stderr,
12797364Stjr	   "usage:  $s [ -c chdir ] [-d level] [-f configfile] [host...]\n");
12897364Stjr	fprintf(stderr, "\t -c n\tset current directory\n");
12997364Stjr	fprintf(stderr, "\t -d n\tset debug level\n");
13097364Stjr	fprintf(stderr, "\t -f n\tconfig file name\n");
13197364Stjr	exit(1);
13297364Stjr}
13397364Stjr
13497364Stjr
13597364Stjr/*
13697364Stjr * Initialization such as command-line processing is done and then the
13797364Stjr * main server loop is started.
13897364Stjr */
13997364Stjrint
14097364Stjrmain(argc, argv)
14197364Stjr	int argc;
14297364Stjr	char **argv;
14397364Stjr{
144226274Sdelphij	struct host *hp;
14597364Stjr	char *stmp;
14697364Stjr	int n;
14797364Stjr
14897364Stjr	progname = strrchr(argv[0], '/');
14997364Stjr	if (progname) progname++;
150194494Sbrooks	else progname = argv[0];
151194494Sbrooks
15297364Stjr	/* Get work space for making tag 18 files. */
15397364Stjr	buffer = (byte *) malloc(BUFFERSIZE);
15497364Stjr	if (!buffer) {
155231994Skevlo		report(LOG_ERR, "malloc failed");
15697364Stjr		exit(1);
15797364Stjr	}
15897364Stjr	/*
15997364Stjr	 * Set defaults that might be changed by option switches.
16097364Stjr	 */
16197364Stjr	stmp = NULL;
16297364Stjr
16397364Stjr	/*
16497364Stjr	 * Read switches.
16597364Stjr	 */
16697364Stjr	for (argc--, argv++; argc > 0; argc--, argv++) {
16797364Stjr		if (argv[0][0] != '-')
16897364Stjr			break;
16997364Stjr		switch (argv[0][1]) {
17097364Stjr
17197364Stjr		case 'c':				/* chdir_path */
17297364Stjr			if (argv[0][2]) {
17397364Stjr				stmp = &(argv[0][2]);
17497364Stjr			} else {
17597364Stjr				argc--;
17697364Stjr				argv++;
17797364Stjr				stmp = argv[0];
17897364Stjr			}
17997364Stjr			if (!stmp || (stmp[0] != '/')) {
18097364Stjr				fprintf(stderr,
18197364Stjr						"bootpd: invalid chdir specification\n");
182231994Skevlo				break;
183231994Skevlo			}
184231994Skevlo			chdir_path = stmp;
185231994Skevlo			break;
18697364Stjr
18797364Stjr		case 'd':				/* debug */
18897364Stjr			if (argv[0][2]) {
18997364Stjr				stmp = &(argv[0][2]);
19097364Stjr			} else if (argv[1] && argv[1][0] == '-') {
191194494Sbrooks				/*
192194494Sbrooks				 * Backwards-compatible behavior:
193194494Sbrooks				 * no parameter, so just increment the debug flag.
194194494Sbrooks				 */
19597364Stjr				debug++;
196229668Sghelmer				break;
19797364Stjr			} else {
19897364Stjr				argc--;
19997364Stjr				argv++;
20097364Stjr				stmp = argv[0];
20197364Stjr			}
20297364Stjr			if (!stmp || (sscanf(stmp, "%d", &n) != 1) || (n < 0)) {
20397364Stjr				fprintf(stderr,
20497364Stjr						"bootpd: invalid debug level\n");
20597364Stjr				break;
20697364Stjr			}
20797364Stjr			debug = n;
20897364Stjr			break;
20997364Stjr
210229668Sghelmer		case 'f':				/* config file */
21197364Stjr			if (argv[0][2]) {
21297364Stjr				stmp = &(argv[0][2]);
21397364Stjr			} else {
21497364Stjr				argc--;
21597364Stjr				argv++;
21697364Stjr				stmp = argv[0];
21797364Stjr			}
21897364Stjr			bootptab = stmp;
219229668Sghelmer			break;
22097364Stjr
22197364Stjr		default:
22297364Stjr			fprintf(stderr, "bootpd: unknown switch: -%c\n",
22397364Stjr					argv[0][1]);
22497364Stjr			usage();
22597364Stjr			break;
226226416Sdelphij		}
22797364Stjr	}
22897364Stjr
22997364Stjr	/* Get the timezone. */
23097364Stjr	tzone_init();
23197364Stjr
23297364Stjr	/* Allocate hash tables. */
23397364Stjr	rdtab_init();
234229668Sghelmer
23597364Stjr	/*
23697364Stjr	 * Read the bootptab file.
23797364Stjr	 */
23897364Stjr	readtab(1);					/* force read */
239229668Sghelmer
240194494Sbrooks	/* Set the cwd (i.e. to /tftpboot) */
24197364Stjr	if (chdir_path) {
24297364Stjr		if (chdir(chdir_path) < 0)
24397364Stjr			report(LOG_ERR, "%s: chdir failed", chdir_path);
24497364Stjr	}
24597364Stjr	/* If there are host names on the command line, do only those. */
24697364Stjr	if (argc > 0) {
24797364Stjr		unsigned int tlen, hashcode;
24897364Stjr
24997364Stjr		while (argc) {
25097364Stjr			tlen = strlen(argv[0]);
25197364Stjr			hashcode = hash_HashFunction((u_char *)argv[0], tlen);
25297364Stjr			hp = (struct host *) hash_Lookup(nmhashtable,
25397364Stjr											 hashcode,
25497364Stjr											 nmcmp, argv[0]);
25597364Stjr			if (!hp) {
25697364Stjr				printf("%s: no matching entry\n", argv[0]);
25797364Stjr				exit(1);
25897364Stjr			}
25997364Stjr			if (!hp->flags.exten_file) {
26097364Stjr				printf("%s: no extension file\n", argv[0]);
26197364Stjr				exit(1);
26297364Stjr			}
26397364Stjr			mktagfile(hp);
26497364Stjr			argv++;
26597364Stjr			argc--;
26697364Stjr		}
26797364Stjr		exit(0);
26897364Stjr	}
26997364Stjr	/* No host names specified.  Do them all. */
27097364Stjr	hp = (struct host *) hash_FirstEntry(nmhashtable);
27197364Stjr	while (hp != NULL) {
27297364Stjr		mktagfile(hp);
27397364Stjr		hp = (struct host *) hash_NextEntry(nmhashtable);
27497364Stjr	}
27597364Stjr	return (0);
27697364Stjr}
27797364Stjr
27897364Stjr
27997364Stjr
28097364Stjr/*
28197364Stjr * Make a "TAG 18" file for this host.
28297364Stjr * (Insert the RFC1497 options.)
28397364Stjr */
28497364Stjr
28597364Stjrstatic void
28697364Stjrmktagfile(hp)
28797364Stjr	struct host *hp;
28897364Stjr{
28997364Stjr	FILE *fp;
29097364Stjr	int bytesleft, len;
29197364Stjr	byte *vp;
29297364Stjr
29397364Stjr	if (!hp->flags.exten_file)
29497364Stjr		return;
29597364Stjr
29697364Stjr	vp = buffer;
29797364Stjr	bytesleft = BUFFERSIZE;
29897364Stjr	bcopy(vm_rfc1048, vp, 4);	/* Copy in the magic cookie */
29997364Stjr	vp += 4;
30097364Stjr	bytesleft -= 4;
30197364Stjr
30297364Stjr	/*
30397364Stjr	 * The "extension file" options are appended by the following
30497364Stjr	 * function (which is shared with bootpd.c).
30597364Stjr	 */
30697364Stjr	len = dovend_rfc1497(hp, vp, bytesleft);
30797364Stjr	vp += len;
30897364Stjr	bytesleft -= len;
309121741Sharti
31097364Stjr	if (bytesleft < 1) {
31197364Stjr		report(LOG_ERR, "%s: too much option data",
312			   hp->exten_file->string);
313		return;
314	}
315	*vp++ = TAG_END;
316	bytesleft--;
317
318	/* Write the buffer to the extension file. */
319	printf("Updating \"%s\"\n", hp->exten_file->string);
320	if ((fp = fopen(hp->exten_file->string, "w")) == NULL) {
321		report(LOG_ERR, "error opening \"%s\": %s",
322			   hp->exten_file->string, get_errmsg());
323		return;
324	}
325	len = vp - buffer;
326	if (len != fwrite(buffer, 1, len, fp)) {
327		report(LOG_ERR, "write failed on \"%s\" : %s",
328			   hp->exten_file->string, get_errmsg());
329	}
330	fclose(fp);
331
332} /* mktagfile */
333
334/*
335 * Local Variables:
336 * tab-width: 4
337 * c-indent-level: 4
338 * c-argdecl-indent: 4
339 * c-continued-statement-offset: 4
340 * c-continued-brace-offset: -4
341 * c-label-offset: -4
342 * c-brace-offset: 0
343 * End:
344 */
345