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