bootpef.c revision 18471
140711Swollman/************************************************************************
240711Swollman          Copyright 1988, 1991 by Carnegie Mellon University
340711Swollman
440711Swollman                          All Rights Reserved
540711Swollman
640711SwollmanPermission to use, copy, modify, and distribute this software and its
740711Swollmandocumentation for any purpose and without fee is hereby granted, provided
840711Swollmanthat the above copyright notice appear in all copies and that both that
940711Swollmancopyright notice and this permission notice appear in supporting
1040711Swollmandocumentation, and that the name of Carnegie Mellon University not be used
1140711Swollmanin advertising or publicity pertaining to distribution of the software
1240711Swollmanwithout specific, written prior permission.
1340711Swollman
1440711SwollmanCARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
1540711SwollmanSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
1640711SwollmanIN NO EVENT SHALL CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
1740711SwollmanDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
1840711SwollmanPROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
1940711SwollmanACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2040711SwollmanSOFTWARE.
2140711Swollman
2240711Swollman	$Id$
2340711Swollman
2440711Swollman************************************************************************/
2540711Swollman
2640711Swollman/*
2740711Swollman * bootpef - BOOTP Extension File generator
2840711Swollman *	Makes an "Extension File" for each host entry that
2950477Speter *	defines an and Extension File. (See RFC1497, tag 18.)
3040711Swollman *
3140711Swollman * HISTORY
3240711Swollman *	See ./Changes
3340711Swollman *
3440711Swollman * BUGS
3540711Swollman *	See ./ToDo
3640711Swollman */
3740711Swollman
3840711Swollman
3940711Swollman
4040711Swollman#ifdef	__STDC__
4140711Swollman#include <stdarg.h>
4240711Swollman#else
4340711Swollman#include <varargs.h>
4440711Swollman#endif
4540711Swollman
4640711Swollman#include <sys/types.h>
4740711Swollman#include <sys/time.h>
4840711Swollman
4940711Swollman#include <netinet/in.h>
5040711Swollman#include <arpa/inet.h>			/* inet_ntoa */
5140711Swollman
5240711Swollman#ifndef	NO_UNISTD
5340711Swollman#include <unistd.h>
5440711Swollman#endif
5540711Swollman#include <stdlib.h>
5640711Swollman#include <stdio.h>
5740711Swollman#include <string.h>
5840711Swollman#include <errno.h>
5940711Swollman#include <ctype.h>
6040711Swollman#include <syslog.h>
6140711Swollman
6241304Sbde#ifndef	USE_BFUNCS
6340711Swollman#include <memory.h>
6440711Swollman/* Yes, memcpy is OK here (no overlapped copies). */
6571576Sjasone#define bcopy(a,b,c)    memcpy(b,a,c)
6645720Speter#define bzero(p,l)      memset(p,0,l)
6745720Speter#define bcmp(a,b,c)     memcmp(a,b,c)
6840711Swollman#endif
69102962Siwasaki
7040711Swollman#include "bootp.h"
71102962Siwasaki#include "hash.h"
72102962Siwasaki#include "hwaddr.h"
73102962Siwasaki#include "bootpd.h"
74102962Siwasaki#include "dovend.h"
7559910Spaul#include "readfile.h"
76102962Siwasaki#include "report.h"
77102962Siwasaki#include "tzone.h"
7845569Seivind#include "patchlevel.h"
7940711Swollman
8040711Swollman#define	BUFFERSIZE   		0x4000
8171576Sjasone
8240711Swollman#ifndef CONFIG_FILE
8340711Swollman#define CONFIG_FILE		"/etc/bootptab"
8445720Speter#endif
8540711Swollman
8640711Swollman
8740711Swollman
8840711Swollman/*
8940711Swollman * Externals, forward declarations, and global variables
9040711Swollman */
9140711Swollman
9240711Swollman#ifdef	__STDC__
9340711Swollman#define P(args) args
9440711Swollman#else
9593818Sjhb#define P(args) ()
9640711Swollman#endif
9740711Swollman
9840711Swollmanstatic void mktagfile P((struct host *));
9940711Swollmanstatic void usage P((void));
10040711Swollman
10140711Swollman#undef P
10240711Swollman
10368727Smckusick
10484781Sjhb/*
10571576Sjasone * General
10640711Swollman */
10793818Sjhb
10840711Swollmanchar *progname;
10972200Sbmilekicchar *chdir_path;
11040711Swollmanint debug = 0;					/* Debugging flag (level) */
11172200Sbmilekicbyte *buffer;
11240711Swollman
11340711Swollman/*
11440711Swollman * Globals below are associated with the bootp database file (bootptab).
11540711Swollman */
11640711Swollman
11740711Swollmanchar *bootptab = CONFIG_FILE;
11840711Swollman
11940711Swollman
12040711Swollman/*
12140711Swollman * Print "usage" message and exit
12240711Swollman */
12340711Swollmanstatic void
12469781Sdwmaloneusage()
12540711Swollman{
12640711Swollman	fprintf(stderr,
12740711Swollman	   "usage:  $s [ -c chdir ] [-d level] [-f configfile] [host...]\n");
12840711Swollman	fprintf(stderr, "\t -c n\tset current directory\n");
12940711Swollman	fprintf(stderr, "\t -d n\tset debug level\n");
13040711Swollman	fprintf(stderr, "\t -f n\tconfig file name\n");
13172200Sbmilekic	exit(1);
13268727Smckusick}
13368727Smckusick
13468727Smckusick
13540711Swollman/*
13640711Swollman * Initialization such as command-line processing is done and then the
13768727Smckusick * main server loop is started.
13868727Smckusick */
13940711Swollmanvoid
14068727Smckusickmain(argc, argv)
14140711Swollman	int argc;
14240711Swollman	char **argv;
14372200Sbmilekic{
14440711Swollman	struct host *hp;
14540711Swollman	char *stmp;
14640711Swollman	int n;
14740711Swollman
14840711Swollman	progname = strrchr(argv[0], '/');
14940711Swollman	if (progname) progname++;
15040711Swollman	else progname = argv[0];
15140711Swollman
15272200Sbmilekic	/* Get work space for making tag 18 files. */
15368727Smckusick	buffer = (byte *) malloc(BUFFERSIZE);
15445720Speter	if (!buffer) {
15572200Sbmilekic		report(LOG_ERR, "malloc failed");
15640711Swollman		exit(1);
15745720Speter	}
15840711Swollman	/*
15940711Swollman	 * Set defaults that might be changed by option switches.
16040711Swollman	 */
16140711Swollman	stmp = NULL;
16240711Swollman
16340711Swollman	/*
16468727Smckusick	 * Read switches.
16568727Smckusick	 */
16668727Smckusick	for (argc--, argv++; argc > 0; argc--, argv++) {
16740711Swollman		if (argv[0][0] != '-')
16840711Swollman			break;
16972200Sbmilekic		switch (argv[0][1]) {
17072200Sbmilekic
17140711Swollman		case 'c':				/* chdir_path */
17272200Sbmilekic			if (argv[0][2]) {
17371576Sjasone				stmp = &(argv[0][2]);
17471576Sjasone			} else {
17540711Swollman				argc--;
17640711Swollman				argv++;
17740711Swollman				stmp = argv[0];
17840711Swollman			}
17940711Swollman			if (!stmp || (stmp[0] != '/')) {
18088372Stmm				fprintf(stderr,
18188372Stmm						"bootpd: invalid chdir specification\n");
18288372Stmm				break;
18340711Swollman			}
18440711Swollman			chdir_path = stmp;
18540711Swollman			break;
18688372Stmm
18740711Swollman		case 'd':				/* debug */
18840711Swollman			if (argv[0][2]) {
18940711Swollman				stmp = &(argv[0][2]);
19059910Spaul			} else if (argv[1] && argv[1][0] == '-') {
19177288Sbrian				/*
19277288Sbrian				 * Backwards-compatible behavior:
19340711Swollman				 * no parameter, so just increment the debug flag.
19440711Swollman				 */
19540711Swollman				debug++;
19672200Sbmilekic				break;
19740711Swollman			} else {
19868727Smckusick				argc--;
19968727Smckusick				argv++;
20068727Smckusick				stmp = argv[0];
20140711Swollman			}
20240711Swollman			if (!stmp || (sscanf(stmp, "%d", &n) != 1) || (n < 0)) {
20368727Smckusick				fprintf(stderr,
20459910Spaul						"bootpd: invalid debug level\n");
20540711Swollman				break;
20640711Swollman			}
20740711Swollman			debug = n;
20888372Stmm			break;
20988372Stmm
21088372Stmm		case 'f':				/* config file */
21140711Swollman			if (argv[0][2]) {
21240711Swollman				stmp = &(argv[0][2]);
21340711Swollman			} else {
21468727Smckusick				argc--;
21559910Spaul				argv++;
21640711Swollman				stmp = argv[0];
21759910Spaul			}
21840711Swollman			bootptab = stmp;
21940711Swollman			break;
22040711Swollman
22159910Spaul		default:
22240711Swollman			fprintf(stderr, "bootpd: unknown switch: -%c\n",
22340711Swollman					argv[0][1]);
22488372Stmm			usage();
22588372Stmm			break;
22688372Stmm		}
22788372Stmm	}
22888372Stmm
22988372Stmm	/* Get the timezone. */
23088372Stmm	tzone_init();
23188372Stmm
23288372Stmm	/* Allocate hash tables. */
23388372Stmm	rdtab_init();
23488372Stmm
23588372Stmm	/*
23688372Stmm	 * Read the bootptab file.
237102572Siwasaki	 */
238102572Siwasaki	readtab(1);					/* force read */
239102572Siwasaki
240102572Siwasaki	/* Set the cwd (i.e. to /tftpboot) */
24159910Spaul	if (chdir_path) {
24259910Spaul		if (chdir(chdir_path) < 0)
24340711Swollman			report(LOG_ERR, "%s: chdir failed", chdir_path);
24440711Swollman	}
24559910Spaul	/* If there are host names on the command line, do only those. */
24659910Spaul	if (argc > 0) {
24740711Swollman		unsigned int tlen, hashcode;
24859910Spaul
24940711Swollman		while (argc) {
25048235Sdfr			tlen = strlen(argv[0]);
25140711Swollman			hashcode = hash_HashFunction((u_char *)argv[0], tlen);
25240711Swollman			hp = (struct host *) hash_Lookup(nmhashtable,
25340711Swollman											 hashcode,
25440711Swollman											 nmcmp, argv[0]);
25540711Swollman			if (!hp) {
25640711Swollman				printf("%s: no matching entry\n", argv[0]);
25740711Swollman				exit(1);
25840711Swollman			}
25940711Swollman			if (!hp->flags.exten_file) {
26040711Swollman				printf("%s: no extension file\n", argv[0]);
26140711Swollman				exit(1);
26240711Swollman			}
26340711Swollman			mktagfile(hp);
26440711Swollman			argv++;
26569781Sdwmalone			argc--;
26640711Swollman		}
26740711Swollman		exit(0);
26840711Swollman	}
26940711Swollman	/* No host names specified.  Do them all. */
27040711Swollman	hp = (struct host *) hash_FirstEntry(nmhashtable);
27140711Swollman	while (hp != NULL) {
27245720Speter		mktagfile(hp);
27340711Swollman		hp = (struct host *) hash_NextEntry(nmhashtable);
27440711Swollman	}
27559910Spaul}
27640711Swollman
27740711Swollman
27840711Swollman
27959910Spaul/*
28040711Swollman * Make a "TAG 18" file for this host.
28140711Swollman * (Insert the RFC1497 options.)
28240711Swollman */
28369781Sdwmalone
28440711Swollmanstatic void
28540711Swollmanmktagfile(hp)
28640711Swollman	struct host *hp;
28740711Swollman{
28840711Swollman	FILE *fp;
28940711Swollman	int bytesleft, len;
29040711Swollman	byte *vp;
29140711Swollman
29245720Speter	if (!hp->flags.exten_file)
29340711Swollman		return;
29468727Smckusick
29540711Swollman	vp = buffer;
29668727Smckusick	bytesleft = BUFFERSIZE;
29740711Swollman	bcopy(vm_rfc1048, vp, 4);	/* Copy in the magic cookie */
29840711Swollman	vp += 4;
29959910Spaul	bytesleft -= 4;
30040711Swollman
30140711Swollman	/*
30240711Swollman	 * The "extension file" options are appended by the following
30340711Swollman	 * function (which is shared with bootpd.c).
30468727Smckusick	 */
30540711Swollman	len = dovend_rfc1497(hp, vp, bytesleft);
30659910Spaul	vp += len;
30740711Swollman	bytesleft -= len;
30840711Swollman
30940711Swollman	if (bytesleft < 1) {
31040711Swollman		report(LOG_ERR, "%s: too much option data",
31168727Smckusick			   hp->exten_file->string);
31240711Swollman		return;
31340711Swollman	}
31440711Swollman	*vp++ = TAG_END;
31540711Swollman	bytesleft--;
31640711Swollman
31740711Swollman	/* Write the buffer to the extension file. */
31840711Swollman	printf("Updating \"%s\"\n", hp->exten_file->string);
31940711Swollman	if ((fp = fopen(hp->exten_file->string, "w")) == NULL) {
32040711Swollman		report(LOG_ERR, "error opening \"%s\": %s",
32140711Swollman			   hp->exten_file->string, get_errmsg());
32240711Swollman		return;
32340711Swollman	}
32440711Swollman	len = vp - buffer;
32540711Swollman	if (len != fwrite(buffer, 1, len, fp)) {
32659910Spaul		report(LOG_ERR, "write failed on \"%s\" : %s",
32740711Swollman			   hp->exten_file->string, get_errmsg());
32840711Swollman	}
32940711Swollman	fclose(fp);
33068727Smckusick
33140711Swollman} /* mktagfile */
33240711Swollman
33340711Swollman/*
33440711Swollman * Local Variables:
33588372Stmm * tab-width: 4
33688372Stmm * c-indent-level: 4
33740711Swollman * c-argdecl-indent: 4
33888372Stmm * c-continued-statement-offset: 4
33988372Stmm * c-continued-brace-offset: -4
34088372Stmm * c-label-offset: -4
34169781Sdwmalone * c-brace-offset: 0
34240711Swollman * End:
34340711Swollman */
34440711Swollman