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