Home | History | Annotate | Line # | Download | only in bootpef
      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.11 2017/05/04 16:26:09 sevan 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 
     89 
     90 /*
     91  * General
     92  */
     93 
     94 const char *progname;
     95 char *chdir_path;
     96 int debug = 0;					/* Debugging flag (level) */
     97 byte *buffer;
     98 
     99 /*
    100  * Globals below are associated with the bootp database file (bootptab).
    101  */
    102 
    103 const char *bootptab = CONFIG_FILE;
    104 
    105 
    107 /*
    108  * Print "usage" message and exit
    109  */
    110 static void
    111 usage(void)
    112 {
    113 	fprintf(stderr,
    114 	    "usage: %s [-c chdir] [-d level] [-f configfile] [host ...]\n",
    115 	    getprogname());
    116 	fprintf(stderr, "\t -c n\tset current directory\n");
    117 	fprintf(stderr, "\t -d n\tset debug level\n");
    118 	fprintf(stderr, "\t -f n\tconfig file name\n");
    119 	exit(1);
    120 }
    121 
    122 
    123 /*
    124  * Initialization such as command-line processing is done and then the
    125  * main server loop is started.
    126  */
    127 int
    128 main(int argc, char **argv)
    129 {
    130 	struct host *hp;
    131 	char *stmp;
    132 	int n;
    133 
    134 	progname = strrchr(argv[0], '/');
    135 	if (progname) progname++;
    136 	else progname = argv[0];
    137 
    138 	/* Get work space for making tag 18 files. */
    139 	buffer = (byte *) malloc(BUFFERSIZE);
    140 	if (!buffer) {
    141 		report(LOG_ERR, "malloc failed");
    142 		exit(1);
    143 	}
    144 	/*
    145 	 * Set defaults that might be changed by option switches.
    146 	 */
    147 	stmp = NULL;
    148 
    149 	/*
    150 	 * Read switches.
    151 	 */
    152 	for (argc--, argv++; argc > 0; argc--, argv++) {
    153 		if (argv[0][0] != '-')
    154 			break;
    155 		switch (argv[0][1]) {
    156 
    157 		case 'c':				/* chdir_path */
    158 			if (argv[0][2]) {
    159 				stmp = &(argv[0][2]);
    160 			} else {
    161 				argc--;
    162 				argv++;
    163 				stmp = argv[0];
    164 			}
    165 			if (!stmp || (stmp[0] != '/')) {
    166 				fprintf(stderr,
    167 						"bootpd: invalid chdir specification\n");
    168 				break;
    169 			}
    170 			chdir_path = stmp;
    171 			break;
    172 
    173 		case 'd':				/* debug */
    174 			if (argv[0][2]) {
    175 				stmp = &(argv[0][2]);
    176 			} else if (argv[1] && argv[1][0] == '-') {
    177 				/*
    178 				 * Backwards-compatible behavior:
    179 				 * no parameter, so just increment the debug flag.
    180 				 */
    181 				debug++;
    182 				break;
    183 			} else {
    184 				argc--;
    185 				argv++;
    186 				stmp = argv[0];
    187 			}
    188 			if (!stmp || (sscanf(stmp, "%d", &n) != 1) || (n < 0)) {
    189 				fprintf(stderr,
    190 						"bootpd: invalid debug level\n");
    191 				break;
    192 			}
    193 			debug = n;
    194 			break;
    195 
    196 		case 'f':				/* config file */
    197 			if (argv[0][2]) {
    198 				stmp = &(argv[0][2]);
    199 			} else {
    200 				argc--;
    201 				argv++;
    202 				stmp = argv[0];
    203 			}
    204 			bootptab = stmp;
    205 			break;
    206 
    207 		default:
    208 			fprintf(stderr, "bootpd: unknown switch: -%c\n",
    209 					argv[0][1]);
    210 			usage();
    211 			break;
    212 		}
    213 	}
    214 
    215 	/* Get the timezone. */
    216 	tzone_init();
    217 
    218 	/* Allocate hash tables. */
    219 	rdtab_init();
    220 
    221 	/*
    222 	 * Read the bootptab file.
    223 	 */
    224 	readtab(1);					/* force read */
    225 
    226 	/* Set the cwd (i.e. to /tftpboot) */
    227 	if (chdir_path) {
    228 		if (chdir(chdir_path) < 0)
    229 			report(LOG_ERR, "%s: chdir failed", chdir_path);
    230 	}
    231 	/* If there are host names on the command line, do only those. */
    232 	if (argc > 0) {
    233 		unsigned int tlen, hashcode;
    234 
    235 		while (argc) {
    236 			tlen = strlen(argv[0]);
    237 			hashcode = hash_HashFunction((u_char *)argv[0], tlen);
    238 			hp = (struct host *) hash_Lookup(nmhashtable,
    239 											 hashcode,
    240 											 nmcmp, argv[0]);
    241 			if (!hp) {
    242 				printf("%s: no matching entry\n", argv[0]);
    243 				exit(1);
    244 			}
    245 			if (!hp->flags.exten_file) {
    246 				printf("%s: no extension file\n", argv[0]);
    247 				exit(1);
    248 			}
    249 			mktagfile(hp);
    250 			argv++;
    251 			argc--;
    252 		}
    253 		exit(0);
    254 	}
    255 	/* No host names specified.  Do them all. */
    256 	hp = (struct host *) hash_FirstEntry(nmhashtable);
    257 	while (hp != NULL) {
    258 		mktagfile(hp);
    259 		hp = (struct host *) hash_NextEntry(nmhashtable);
    260 	}
    261 	exit(0);
    262 }
    263 
    264 
    266 
    267 /*
    268  * Make a "TAG 18" file for this host.
    269  * (Insert the RFC1497 options.)
    270  */
    271 
    272 static void
    273 mktagfile(struct host *hp)
    274 {
    275 	FILE *fp;
    276 	int bytesleft, len;
    277 	byte *vp;
    278 
    279 	if (!hp->flags.exten_file)
    280 		return;
    281 
    282 	vp = buffer;
    283 	bytesleft = BUFFERSIZE;
    284 	bcopy(vm_rfc1048, vp, 4);	/* Copy in the magic cookie */
    285 	vp += 4;
    286 	bytesleft -= 4;
    287 
    288 	/*
    289 	 * The "extension file" options are appended by the following
    290 	 * function (which is shared with bootpd.c).
    291 	 */
    292 	len = dovend_rfc1497(hp, vp, bytesleft);
    293 	vp += len;
    294 	bytesleft -= len;
    295 
    296 	if (bytesleft < 1) {
    297 		report(LOG_ERR, "%s: too much option data",
    298 			   hp->exten_file->string);
    299 		return;
    300 	}
    301 	*vp++ = TAG_END;
    302 	bytesleft--;
    303 
    304 	/* Write the buffer to the extension file. */
    305 	printf("Updating \"%s\"\n", hp->exten_file->string);
    306 	if ((fp = fopen(hp->exten_file->string, "w")) == NULL) {
    307 		report(LOG_ERR, "error opening \"%s\": %s",
    308 			   hp->exten_file->string, get_errmsg());
    309 		return;
    310 	}
    311 	len = vp - buffer;
    312 	if ((size_t)len != fwrite(buffer, 1, len, fp)) {
    313 		report(LOG_ERR, "write failed on \"%s\" : %s",
    314 			   hp->exten_file->string, get_errmsg());
    315 	}
    316 	fclose(fp);
    317 
    318 } /* mktagfile */
    319 
    320 /*
    321  * Local Variables:
    322  * tab-width: 4
    323  * c-indent-level: 4
    324  * c-argdecl-indent: 4
    325  * c-continued-statement-offset: 4
    326  * c-continued-brace-offset: -4
    327  * c-label-offset: -4
    328  * c-brace-offset: 0
    329  * End:
    330  */
    331