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