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