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