Path: blob/main/libexec/bootpd/tools/bootpef/bootpef.c
34898 views
/************************************************************************1Copyright 1988, 1991 by Carnegie Mellon University23All Rights Reserved45Permission to use, copy, modify, and distribute this software and its6documentation for any purpose and without fee is hereby granted, provided7that the above copyright notice appear in all copies and that both that8copyright notice and this permission notice appear in supporting9documentation, and that the name of Carnegie Mellon University not be used10in advertising or publicity pertaining to distribution of the software11without specific, written prior permission.1213CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS14SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.15IN NO EVENT SHALL CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL16DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR17PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS18ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS19SOFTWARE.2021************************************************************************/2223/*24* bootpef - BOOTP Extension File generator25* Makes an "Extension File" for each host entry that26* defines an and Extension File. (See RFC1497, tag 18.)27*28* HISTORY29* See ./Changes30*31* BUGS32* See ./ToDo33*/34353637#include <stdarg.h>3839#include <sys/types.h>40#include <sys/time.h>4142#include <netinet/in.h>43#include <arpa/inet.h> /* inet_ntoa */4445#ifndef NO_UNISTD46#include <unistd.h>47#endif48#include <stdlib.h>49#include <stdio.h>50#include <string.h>51#include <errno.h>52#include <ctype.h>53#include <syslog.h>5455#include "bootp.h"56#include "hash.h"57#include "hwaddr.h"58#include "bootpd.h"59#include "dovend.h"60#include "readfile.h"61#include "report.h"62#include "tzone.h"63#include "patchlevel.h"6465#define BUFFERSIZE 0x40006667#ifndef CONFIG_FILE68#define CONFIG_FILE "/etc/bootptab"69#endif70717273/*74* Externals, forward declarations, and global variables75*/7677static void mktagfile(struct host *);78static void usage(void) __dead2;7980/*81* General82*/8384char *progname;85char *chdir_path;86int debug = 0; /* Debugging flag (level) */87byte *buffer;8889/*90* Globals below are associated with the bootp database file (bootptab).91*/9293char *bootptab = CONFIG_FILE;949596/*97* Print "usage" message and exit98*/99static void100usage(void)101{102fprintf(stderr,103"usage: $s [ -c chdir ] [-d level] [-f configfile] [host...]\n");104fprintf(stderr, "\t -c n\tset current directory\n");105fprintf(stderr, "\t -d n\tset debug level\n");106fprintf(stderr, "\t -f n\tconfig file name\n");107exit(1);108}109110111/*112* Initialization such as command-line processing is done and then the113* main server loop is started.114*/115int116main(int argc, char **argv)117{118struct host *hp;119char *stmp;120int n;121122progname = strrchr(argv[0], '/');123if (progname) progname++;124else progname = argv[0];125126/* Get work space for making tag 18 files. */127buffer = (byte *) malloc(BUFFERSIZE);128if (!buffer) {129report(LOG_ERR, "malloc failed");130exit(1);131}132/*133* Set defaults that might be changed by option switches.134*/135stmp = NULL;136137/*138* Read switches.139*/140for (argc--, argv++; argc > 0; argc--, argv++) {141if (argv[0][0] != '-')142break;143switch (argv[0][1]) {144145case 'c': /* chdir_path */146if (argv[0][2]) {147stmp = &(argv[0][2]);148} else {149argc--;150argv++;151stmp = argv[0];152}153if (!stmp || (stmp[0] != '/')) {154fprintf(stderr,155"bootpd: invalid chdir specification\n");156break;157}158chdir_path = stmp;159break;160161case 'd': /* debug */162if (argv[0][2]) {163stmp = &(argv[0][2]);164} else if (argv[1] && argv[1][0] == '-') {165/*166* Backwards-compatible behavior:167* no parameter, so just increment the debug flag.168*/169debug++;170break;171} else {172argc--;173argv++;174stmp = argv[0];175}176if (!stmp || (sscanf(stmp, "%d", &n) != 1) || (n < 0)) {177fprintf(stderr,178"bootpd: invalid debug level\n");179break;180}181debug = n;182break;183184case 'f': /* config file */185if (argv[0][2]) {186stmp = &(argv[0][2]);187} else {188argc--;189argv++;190stmp = argv[0];191}192bootptab = stmp;193break;194195default:196fprintf(stderr, "bootpd: unknown switch: -%c\n",197argv[0][1]);198usage();199break;200}201}202203/* Get the timezone. */204tzone_init();205206/* Allocate hash tables. */207rdtab_init();208209/*210* Read the bootptab file.211*/212readtab(1); /* force read */213214/* Set the cwd (i.e. to /tftpboot) */215if (chdir_path) {216if (chdir(chdir_path) < 0)217report(LOG_ERR, "%s: chdir failed", chdir_path);218}219/* If there are host names on the command line, do only those. */220if (argc > 0) {221unsigned int tlen, hashcode;222223while (argc) {224tlen = strlen(argv[0]);225hashcode = hash_HashFunction((u_char *)argv[0], tlen);226hp = (struct host *) hash_Lookup(nmhashtable,227hashcode,228nmcmp, argv[0]);229if (!hp) {230printf("%s: no matching entry\n", argv[0]);231exit(1);232}233if (!hp->flags.exten_file) {234printf("%s: no extension file\n", argv[0]);235exit(1);236}237mktagfile(hp);238argv++;239argc--;240}241exit(0);242}243/* No host names specified. Do them all. */244hp = (struct host *) hash_FirstEntry(nmhashtable);245while (hp != NULL) {246mktagfile(hp);247hp = (struct host *) hash_NextEntry(nmhashtable);248}249return (0);250}251252253254/*255* Make a "TAG 18" file for this host.256* (Insert the RFC1497 options.)257*/258259static void260mktagfile(struct host *hp)261{262FILE *fp;263int bytesleft, len;264byte *vp;265266if (!hp->flags.exten_file)267return;268269vp = buffer;270bytesleft = BUFFERSIZE;271bcopy(vm_rfc1048, vp, 4); /* Copy in the magic cookie */272vp += 4;273bytesleft -= 4;274275/*276* The "extension file" options are appended by the following277* function (which is shared with bootpd.c).278*/279len = dovend_rfc1497(hp, vp, bytesleft);280vp += len;281bytesleft -= len;282283if (bytesleft < 1) {284report(LOG_ERR, "%s: too much option data",285hp->exten_file->string);286return;287}288*vp++ = TAG_END;289bytesleft--;290291/* Write the buffer to the extension file. */292printf("Updating \"%s\"\n", hp->exten_file->string);293if ((fp = fopen(hp->exten_file->string, "w")) == NULL) {294report(LOG_ERR, "error opening \"%s\": %s",295hp->exten_file->string, get_errmsg());296return;297}298len = vp - buffer;299if (len != fwrite(buffer, 1, len, fp)) {300report(LOG_ERR, "write failed on \"%s\" : %s",301hp->exten_file->string, get_errmsg());302}303fclose(fp);304305} /* mktagfile */306307/*308* Local Variables:309* tab-width: 4310* c-indent-level: 4311* c-argdecl-indent: 4312* c-continued-statement-offset: 4313* c-continued-brace-offset: -4314* c-label-offset: -4315* c-brace-offset: 0316* End:317*/318319320