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