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