Home | History | Annotate | Line # | Download | only in bootpef
bootpef.c revision 1.4
      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.4 1998/03/14 04:39:53 lukem 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 #ifdef	__STDC__
     45 #include <stdarg.h>
     46 #else
     47 #include <varargs.h>
     48 #endif
     49 
     50 #include <sys/types.h>
     51 #include <sys/time.h>
     52 
     53 #include <netinet/in.h>
     54 #include <arpa/inet.h>			/* inet_ntoa */
     55 
     56 #ifndef	NO_UNISTD
     57 #include <unistd.h>
     58 #endif
     59 #include <stdlib.h>
     60 #include <stdio.h>
     61 #include <string.h>
     62 #include <errno.h>
     63 #include <ctype.h>
     64 #include <syslog.h>
     65 
     66 #ifndef	USE_BFUNCS
     67 #include <memory.h>
     68 /* Yes, memcpy is OK here (no overlapped copies). */
     69 #define bcopy(a,b,c)    memcpy(b,a,c)
     70 #define bzero(p,l)      memset(p,0,l)
     71 #define bcmp(a,b,c)     memcmp(a,b,c)
     72 #endif
     73 
     74 #include "bootp.h"
     75 #include "hash.h"
     76 #include "hwaddr.h"
     77 #include "bootpd.h"
     78 #include "dovend.h"
     79 #include "readfile.h"
     80 #include "report.h"
     81 #include "tzone.h"
     82 #include "patchlevel.h"
     83 
     84 #define	BUFFERSIZE   		0x4000
     85 
     86 #ifndef CONFIG_FILE
     87 #define CONFIG_FILE		"/etc/bootptab"
     88 #endif
     89 
     90 
     92 
     93 /*
     94  * Externals, forward declarations, and global variables
     95  */
     96 
     97 #ifdef	__STDC__
     98 #define P(args) args
     99 #else
    100 #define P(args) ()
    101 #endif
    102 
    103 static void mktagfile P((struct host *));
    104 static void usage P((void));
    105 int main P((int, char **));
    106 
    107 #undef P
    108 
    109 
    110 /*
    111  * General
    112  */
    113 
    114 char *progname;
    115 char *chdir_path;
    116 int debug = 0;					/* Debugging flag (level) */
    117 byte *buffer;
    118 
    119 /*
    120  * Globals below are associated with the bootp database file (bootptab).
    121  */
    122 
    123 char *bootptab = CONFIG_FILE;
    124 
    125 
    127 /*
    128  * Print "usage" message and exit
    129  */
    130 static void
    131 usage()
    132 {
    133 	fprintf(stderr,
    134 	   "usage:  $s [ -c chdir ] [-d level] [-f configfile] [host...]\n");
    135 	fprintf(stderr, "\t -c n\tset current directory\n");
    136 	fprintf(stderr, "\t -d n\tset debug level\n");
    137 	fprintf(stderr, "\t -f n\tconfig file name\n");
    138 	exit(1);
    139 }
    140 
    141 
    142 /*
    143  * Initialization such as command-line processing is done and then the
    144  * main server loop is started.
    145  */
    146 int
    147 main(argc, argv)
    148 	int argc;
    149 	char **argv;
    150 {
    151 	struct host *hp;
    152 	char *stmp;
    153 	int n;
    154 
    155 	progname = strrchr(argv[0], '/');
    156 	if (progname) progname++;
    157 	else progname = argv[0];
    158 
    159 	/* Get work space for making tag 18 files. */
    160 	buffer = (byte *) malloc(BUFFERSIZE);
    161 	if (!buffer) {
    162 		report(LOG_ERR, "malloc failed");
    163 		exit(1);
    164 	}
    165 	/*
    166 	 * Set defaults that might be changed by option switches.
    167 	 */
    168 	stmp = NULL;
    169 
    170 	/*
    171 	 * Read switches.
    172 	 */
    173 	for (argc--, argv++; argc > 0; argc--, argv++) {
    174 		if (argv[0][0] != '-')
    175 			break;
    176 		switch (argv[0][1]) {
    177 
    178 		case 'c':				/* chdir_path */
    179 			if (argv[0][2]) {
    180 				stmp = &(argv[0][2]);
    181 			} else {
    182 				argc--;
    183 				argv++;
    184 				stmp = argv[0];
    185 			}
    186 			if (!stmp || (stmp[0] != '/')) {
    187 				fprintf(stderr,
    188 						"bootpd: invalid chdir specification\n");
    189 				break;
    190 			}
    191 			chdir_path = stmp;
    192 			break;
    193 
    194 		case 'd':				/* debug */
    195 			if (argv[0][2]) {
    196 				stmp = &(argv[0][2]);
    197 			} else if (argv[1] && argv[1][0] == '-') {
    198 				/*
    199 				 * Backwards-compatible behavior:
    200 				 * no parameter, so just increment the debug flag.
    201 				 */
    202 				debug++;
    203 				break;
    204 			} else {
    205 				argc--;
    206 				argv++;
    207 				stmp = argv[0];
    208 			}
    209 			if (!stmp || (sscanf(stmp, "%d", &n) != 1) || (n < 0)) {
    210 				fprintf(stderr,
    211 						"bootpd: invalid debug level\n");
    212 				break;
    213 			}
    214 			debug = n;
    215 			break;
    216 
    217 		case 'f':				/* config file */
    218 			if (argv[0][2]) {
    219 				stmp = &(argv[0][2]);
    220 			} else {
    221 				argc--;
    222 				argv++;
    223 				stmp = argv[0];
    224 			}
    225 			bootptab = stmp;
    226 			break;
    227 
    228 		default:
    229 			fprintf(stderr, "bootpd: unknown switch: -%c\n",
    230 					argv[0][1]);
    231 			usage();
    232 			break;
    233 		}
    234 	}
    235 
    236 	/* Get the timezone. */
    237 	tzone_init();
    238 
    239 	/* Allocate hash tables. */
    240 	rdtab_init();
    241 
    242 	/*
    243 	 * Read the bootptab file.
    244 	 */
    245 	readtab(1);					/* force read */
    246 
    247 	/* Set the cwd (i.e. to /tftpboot) */
    248 	if (chdir_path) {
    249 		if (chdir(chdir_path) < 0)
    250 			report(LOG_ERR, "%s: chdir failed", chdir_path);
    251 	}
    252 	/* If there are host names on the command line, do only those. */
    253 	if (argc > 0) {
    254 		unsigned int tlen, hashcode;
    255 
    256 		while (argc) {
    257 			tlen = strlen(argv[0]);
    258 			hashcode = hash_HashFunction((u_char *)argv[0], tlen);
    259 			hp = (struct host *) hash_Lookup(nmhashtable,
    260 											 hashcode,
    261 											 nmcmp, argv[0]);
    262 			if (!hp) {
    263 				printf("%s: no matching entry\n", argv[0]);
    264 				exit(1);
    265 			}
    266 			if (!hp->flags.exten_file) {
    267 				printf("%s: no extension file\n", argv[0]);
    268 				exit(1);
    269 			}
    270 			mktagfile(hp);
    271 			argv++;
    272 			argc--;
    273 		}
    274 		exit(0);
    275 	}
    276 	/* No host names specified.  Do them all. */
    277 	hp = (struct host *) hash_FirstEntry(nmhashtable);
    278 	while (hp != NULL) {
    279 		mktagfile(hp);
    280 		hp = (struct host *) hash_NextEntry(nmhashtable);
    281 	}
    282 	exit(0);
    283 }
    284 
    285 
    287 
    288 /*
    289  * Make a "TAG 18" file for this host.
    290  * (Insert the RFC1497 options.)
    291  */
    292 
    293 static void
    294 mktagfile(hp)
    295 	struct host *hp;
    296 {
    297 	FILE *fp;
    298 	int bytesleft, len;
    299 	byte *vp;
    300 
    301 	if (!hp->flags.exten_file)
    302 		return;
    303 
    304 	vp = buffer;
    305 	bytesleft = BUFFERSIZE;
    306 	bcopy(vm_rfc1048, vp, 4);	/* Copy in the magic cookie */
    307 	vp += 4;
    308 	bytesleft -= 4;
    309 
    310 	/*
    311 	 * The "extension file" options are appended by the following
    312 	 * function (which is shared with bootpd.c).
    313 	 */
    314 	len = dovend_rfc1497(hp, vp, bytesleft);
    315 	vp += len;
    316 	bytesleft -= len;
    317 
    318 	if (bytesleft < 1) {
    319 		report(LOG_ERR, "%s: too much option data",
    320 			   hp->exten_file->string);
    321 		return;
    322 	}
    323 	*vp++ = TAG_END;
    324 	bytesleft--;
    325 
    326 	/* Write the buffer to the extension file. */
    327 	printf("Updating \"%s\"\n", hp->exten_file->string);
    328 	if ((fp = fopen(hp->exten_file->string, "w")) == NULL) {
    329 		report(LOG_ERR, "error opening \"%s\": %s",
    330 			   hp->exten_file->string, get_errmsg());
    331 		return;
    332 	}
    333 	len = vp - buffer;
    334 	if (len != fwrite(buffer, 1, len, fp)) {
    335 		report(LOG_ERR, "write failed on \"%s\" : %s",
    336 			   hp->exten_file->string, get_errmsg());
    337 	}
    338 	fclose(fp);
    339 
    340 } /* mktagfile */
    341 
    342 /*
    343  * Local Variables:
    344  * tab-width: 4
    345  * c-indent-level: 4
    346  * c-argdecl-indent: 4
    347  * c-continued-statement-offset: 4
    348  * c-continued-brace-offset: -4
    349  * c-label-offset: -4
    350  * c-brace-offset: 0
    351  * End:
    352  */
    353