Home | History | Annotate | Line # | Download | only in bootpef
bootpef.c revision 1.10
      1 /************************************************************************
      2           Copyright 1988, 1991 by Carnegie Mellon University
      3 
      4                           All Rights Reserved
      5 
      6 Permission to use, copy, modify, and distribute this software and its
      7 documentation for any purpose and without fee is hereby granted, provided
      8 that the above copyright notice appear in all copies and that both that
      9 copyright notice and this permission notice appear in supporting
     10 documentation, and that the name of Carnegie Mellon University not be used
     11 in advertising or publicity pertaining to distribution of the software
     12 without specific, written prior permission.
     13 
     14 CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
     15 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
     16 IN NO EVENT SHALL CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
     17 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
     18 PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
     19 ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
     20 SOFTWARE.
     21 ************************************************************************/
     22 
     23 #include <sys/cdefs.h>
     24 #ifndef lint
     25 __RCSID("$NetBSD: bootpef.c,v 1.10 2011/08/29 20:38:54 joerg Exp $");
     26 #endif
     27 
     28 
     29 /*
     30  * bootpef - BOOTP Extension File generator
     31  *	Makes an "Extension File" for each host entry that
     32  *	defines an and Extension File. (See RFC1497, tag 18.)
     33  *
     34  * HISTORY
     35  *	See ./Changes
     36  *
     37  * BUGS
     38  *	See ./ToDo
     39  */
     40 
     41 
     43 
     44 #include <stdarg.h>
     45 
     46 #include <sys/types.h>
     47 #include <sys/time.h>
     48 
     49 #include <netinet/in.h>
     50 #include <arpa/inet.h>			/* inet_ntoa */
     51 
     52 #ifndef	NO_UNISTD
     53 #include <unistd.h>
     54 #endif
     55 #include <stdlib.h>
     56 #include <stdio.h>
     57 #include <string.h>
     58 #include <strings.h>
     59 #include <errno.h>
     60 #include <ctype.h>
     61 #include <syslog.h>
     62 
     63 #include "bootp.h"
     64 #include "hash.h"
     65 #include "hwaddr.h"
     66 #include "bootpd.h"
     67 #include "dovend.h"
     68 #include "readfile.h"
     69 #include "report.h"
     70 #include "tzone.h"
     71 #include "patchlevel.h"
     72 
     73 #define	BUFFERSIZE   		0x4000
     74 
     75 #ifndef CONFIG_FILE
     76 #define CONFIG_FILE		"/etc/bootptab"
     77 #endif
     78 
     79 
     81 
     82 /*
     83  * Externals, forward declarations, and global variables
     84  */
     85 
     86 static void mktagfile(struct host *);
     87 __dead static void usage(void);
     88 int main(int, char **);
     89 
     90 
     91 /*
     92  * General
     93  */
     94 
     95 const char *progname;
     96 char *chdir_path;
     97 int debug = 0;					/* Debugging flag (level) */
     98 byte *buffer;
     99 
    100 /*
    101  * Globals below are associated with the bootp database file (bootptab).
    102  */
    103 
    104 const char *bootptab = CONFIG_FILE;
    105 
    106 
    108 /*
    109  * Print "usage" message and exit
    110  */
    111 static void
    112 usage(void)
    113 {
    114 	fprintf(stderr,
    115 	    "usage: %s [-c chdir] [-d level] [-f configfile] [host ...]\n",
    116 	    getprogname());
    117 	fprintf(stderr, "\t -c n\tset current directory\n");
    118 	fprintf(stderr, "\t -d n\tset debug level\n");
    119 	fprintf(stderr, "\t -f n\tconfig file name\n");
    120 	exit(1);
    121 }
    122 
    123 
    124 /*
    125  * Initialization such as command-line processing is done and then the
    126  * main server loop is started.
    127  */
    128 int
    129 main(int argc, char **argv)
    130 {
    131 	struct host *hp;
    132 	char *stmp;
    133 	int n;
    134 
    135 	progname = strrchr(argv[0], '/');
    136 	if (progname) progname++;
    137 	else progname = argv[0];
    138 
    139 	/* Get work space for making tag 18 files. */
    140 	buffer = (byte *) malloc(BUFFERSIZE);
    141 	if (!buffer) {
    142 		report(LOG_ERR, "malloc failed");
    143 		exit(1);
    144 	}
    145 	/*
    146 	 * Set defaults that might be changed by option switches.
    147 	 */
    148 	stmp = NULL;
    149 
    150 	/*
    151 	 * Read switches.
    152 	 */
    153 	for (argc--, argv++; argc > 0; argc--, argv++) {
    154 		if (argv[0][0] != '-')
    155 			break;
    156 		switch (argv[0][1]) {
    157 
    158 		case 'c':				/* chdir_path */
    159 			if (argv[0][2]) {
    160 				stmp = &(argv[0][2]);
    161 			} else {
    162 				argc--;
    163 				argv++;
    164 				stmp = argv[0];
    165 			}
    166 			if (!stmp || (stmp[0] != '/')) {
    167 				fprintf(stderr,
    168 						"bootpd: invalid chdir specification\n");
    169 				break;
    170 			}
    171 			chdir_path = stmp;
    172 			break;
    173 
    174 		case 'd':				/* debug */
    175 			if (argv[0][2]) {
    176 				stmp = &(argv[0][2]);
    177 			} else if (argv[1] && argv[1][0] == '-') {
    178 				/*
    179 				 * Backwards-compatible behavior:
    180 				 * no parameter, so just increment the debug flag.
    181 				 */
    182 				debug++;
    183 				break;
    184 			} else {
    185 				argc--;
    186 				argv++;
    187 				stmp = argv[0];
    188 			}
    189 			if (!stmp || (sscanf(stmp, "%d", &n) != 1) || (n < 0)) {
    190 				fprintf(stderr,
    191 						"bootpd: invalid debug level\n");
    192 				break;
    193 			}
    194 			debug = n;
    195 			break;
    196 
    197 		case 'f':				/* config file */
    198 			if (argv[0][2]) {
    199 				stmp = &(argv[0][2]);
    200 			} else {
    201 				argc--;
    202 				argv++;
    203 				stmp = argv[0];
    204 			}
    205 			bootptab = stmp;
    206 			break;
    207 
    208 		default:
    209 			fprintf(stderr, "bootpd: unknown switch: -%c\n",
    210 					argv[0][1]);
    211 			usage();
    212 			break;
    213 		}
    214 	}
    215 
    216 	/* Get the timezone. */
    217 	tzone_init();
    218 
    219 	/* Allocate hash tables. */
    220 	rdtab_init();
    221 
    222 	/*
    223 	 * Read the bootptab file.
    224 	 */
    225 	readtab(1);					/* force read */
    226 
    227 	/* Set the cwd (i.e. to /tftpboot) */
    228 	if (chdir_path) {
    229 		if (chdir(chdir_path) < 0)
    230 			report(LOG_ERR, "%s: chdir failed", chdir_path);
    231 	}
    232 	/* If there are host names on the command line, do only those. */
    233 	if (argc > 0) {
    234 		unsigned int tlen, hashcode;
    235 
    236 		while (argc) {
    237 			tlen = strlen(argv[0]);
    238 			hashcode = hash_HashFunction((u_char *)argv[0], tlen);
    239 			hp = (struct host *) hash_Lookup(nmhashtable,
    240 											 hashcode,
    241 											 nmcmp, argv[0]);
    242 			if (!hp) {
    243 				printf("%s: no matching entry\n", argv[0]);
    244 				exit(1);
    245 			}
    246 			if (!hp->flags.exten_file) {
    247 				printf("%s: no extension file\n", argv[0]);
    248 				exit(1);
    249 			}
    250 			mktagfile(hp);
    251 			argv++;
    252 			argc--;
    253 		}
    254 		exit(0);
    255 	}
    256 	/* No host names specified.  Do them all. */
    257 	hp = (struct host *) hash_FirstEntry(nmhashtable);
    258 	while (hp != NULL) {
    259 		mktagfile(hp);
    260 		hp = (struct host *) hash_NextEntry(nmhashtable);
    261 	}
    262 	exit(0);
    263 }
    264 
    265 
    267 
    268 /*
    269  * Make a "TAG 18" file for this host.
    270  * (Insert the RFC1497 options.)
    271  */
    272 
    273 static void
    274 mktagfile(struct host *hp)
    275 {
    276 	FILE *fp;
    277 	int bytesleft, len;
    278 	byte *vp;
    279 
    280 	if (!hp->flags.exten_file)
    281 		return;
    282 
    283 	vp = buffer;
    284 	bytesleft = BUFFERSIZE;
    285 	bcopy(vm_rfc1048, vp, 4);	/* Copy in the magic cookie */
    286 	vp += 4;
    287 	bytesleft -= 4;
    288 
    289 	/*
    290 	 * The "extension file" options are appended by the following
    291 	 * function (which is shared with bootpd.c).
    292 	 */
    293 	len = dovend_rfc1497(hp, vp, bytesleft);
    294 	vp += len;
    295 	bytesleft -= len;
    296 
    297 	if (bytesleft < 1) {
    298 		report(LOG_ERR, "%s: too much option data",
    299 			   hp->exten_file->string);
    300 		return;
    301 	}
    302 	*vp++ = TAG_END;
    303 	bytesleft--;
    304 
    305 	/* Write the buffer to the extension file. */
    306 	printf("Updating \"%s\"\n", hp->exten_file->string);
    307 	if ((fp = fopen(hp->exten_file->string, "w")) == NULL) {
    308 		report(LOG_ERR, "error opening \"%s\": %s",
    309 			   hp->exten_file->string, get_errmsg());
    310 		return;
    311 	}
    312 	len = vp - buffer;
    313 	if ((size_t)len != fwrite(buffer, 1, len, fp)) {
    314 		report(LOG_ERR, "write failed on \"%s\" : %s",
    315 			   hp->exten_file->string, get_errmsg());
    316 	}
    317 	fclose(fp);
    318 
    319 } /* mktagfile */
    320 
    321 /*
    322  * Local Variables:
    323  * tab-width: 4
    324  * c-indent-level: 4
    325  * c-argdecl-indent: 4
    326  * c-continued-statement-offset: 4
    327  * c-continued-brace-offset: -4
    328  * c-label-offset: -4
    329  * c-brace-offset: 0
    330  * End:
    331  */
    332