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 static void mktagfile(struct host *); 94 static void usage(void); 95 96 97 /* 98 * General 99 */ 100 101 char *progname; 102 char *chdir_path; 103 int debug = 0; /* Debugging flag (level) */ 104 byte *buffer; 105 106 /* 107 * Globals below are associated with the bootp database file (bootptab). 108 */ 109 110 char *bootptab = CONFIG_FILE; 111 112 113 /* 114 * Print "usage" message and exit 115 */ 116 static void 117 usage(void) 118 { 119 fprintf(stderr, 120 "usage: $s [ -c chdir ] [-d level] [-f configfile] [host...]\n"); 121 fprintf(stderr, "\t -c n\tset current directory\n"); 122 fprintf(stderr, "\t -d n\tset debug level\n"); 123 fprintf(stderr, "\t -f n\tconfig file name\n"); 124 exit(1); 125 } 126 127 128 /* 129 * Initialization such as command-line processing is done and then the 130 * main server loop is started. 131 */ 132 int 133 main(int argc, char **argv) 134 { 135 struct host *hp; 136 char *stmp; 137 int n; 138 139 progname = strrchr(argv[0], '/'); 140 if (progname) progname++; 141 else progname = argv[0]; 142 143 /* Get work space for making tag 18 files. */ 144 buffer = (byte *) malloc(BUFFERSIZE); 145 if (!buffer) { 146 report(LOG_ERR, "malloc failed"); 147 exit(1); 148 } 149 /* 150 * Set defaults that might be changed by option switches. 151 */ 152 stmp = NULL; 153 154 /* 155 * Read switches. 156 */ 157 for (argc--, argv++; argc > 0; argc--, argv++) { 158 if (argv[0][0] != '-') 159 break; 160 switch (argv[0][1]) { 161 162 case 'c': /* chdir_path */ 163 if (argv[0][2]) { 164 stmp = &(argv[0][2]); 165 } else { 166 argc--; 167 argv++; 168 stmp = argv[0]; 169 } 170 if (!stmp || (stmp[0] != '/')) { 171 fprintf(stderr, 172 "bootpd: invalid chdir specification\n"); 173 break; 174 } 175 chdir_path = stmp; 176 break; 177 178 case 'd': /* debug */ 179 if (argv[0][2]) { 180 stmp = &(argv[0][2]); 181 } else if (argv[1] && argv[1][0] == '-') { 182 /* 183 * Backwards-compatible behavior: 184 * no parameter, so just increment the debug flag. 185 */ 186 debug++; 187 break; 188 } else { 189 argc--; 190 argv++; 191 stmp = argv[0]; 192 } 193 if (!stmp || (sscanf(stmp, "%d", &n) != 1) || (n < 0)) { 194 fprintf(stderr, 195 "bootpd: invalid debug level\n"); 196 break; 197 } 198 debug = n; 199 break; 200 201 case 'f': /* config file */ 202 if (argv[0][2]) { 203 stmp = &(argv[0][2]); 204 } else { 205 argc--; 206 argv++; 207 stmp = argv[0]; 208 } 209 bootptab = stmp; 210 break; 211 212 default: 213 fprintf(stderr, "bootpd: unknown switch: -%c\n", 214 argv[0][1]); 215 usage(); 216 break; 217 } 218 } 219 220 /* Get the timezone. */ 221 tzone_init(); 222 223 /* Allocate hash tables. */ 224 rdtab_init(); 225 226 /* 227 * Read the bootptab file. 228 */ 229 readtab(1); /* force read */ 230 231 /* Set the cwd (i.e. to /tftpboot) */ 232 if (chdir_path) { 233 if (chdir(chdir_path) < 0) 234 report(LOG_ERR, "%s: chdir failed", chdir_path); 235 } 236 /* If there are host names on the command line, do only those. */ 237 if (argc > 0) { 238 unsigned int tlen, hashcode; 239 240 while (argc) { 241 tlen = strlen(argv[0]); 242 hashcode = hash_HashFunction((u_char *)argv[0], tlen); 243 hp = (struct host *) hash_Lookup(nmhashtable, 244 hashcode, 245 nmcmp, argv[0]); 246 if (!hp) { 247 printf("%s: no matching entry\n", argv[0]); 248 exit(1); 249 } 250 if (!hp->flags.exten_file) { 251 printf("%s: no extension file\n", argv[0]); 252 exit(1); 253 } 254 mktagfile(hp); 255 argv++; 256 argc--; 257 } 258 exit(0); 259 } 260 /* No host names specified. Do them all. */ 261 hp = (struct host *) hash_FirstEntry(nmhashtable); 262 while (hp != NULL) { 263 mktagfile(hp); 264 hp = (struct host *) hash_NextEntry(nmhashtable); 265 } 266 return (0); 267 } 268 269 270 271 /* 272 * Make a "TAG 18" file for this host. 273 * (Insert the RFC1497 options.) 274 */ 275 276 static void 277 mktagfile(struct host *hp) 278 { 279 FILE *fp; 280 int bytesleft, len; 281 byte *vp; 282 283 if (!hp->flags.exten_file) 284 return; 285 286 vp = buffer; 287 bytesleft = BUFFERSIZE; 288 bcopy(vm_rfc1048, vp, 4); /* Copy in the magic cookie */ 289 vp += 4; 290 bytesleft -= 4; 291 292 /* 293 * The "extension file" options are appended by the following 294 * function (which is shared with bootpd.c). 295 */ 296 len = dovend_rfc1497(hp, vp, bytesleft); 297 vp += len; 298 bytesleft -= len; 299 300 if (bytesleft < 1) { 301 report(LOG_ERR, "%s: too much option data", 302 hp->exten_file->string); 303 return; 304 } 305 *vp++ = TAG_END; 306 bytesleft--; 307 308 /* Write the buffer to the extension file. */ 309 printf("Updating \"%s\"\n", hp->exten_file->string); 310 if ((fp = fopen(hp->exten_file->string, "w")) == NULL) { 311 report(LOG_ERR, "error opening \"%s\": %s", 312 hp->exten_file->string, get_errmsg()); 313 return; 314 } 315 len = vp - buffer; 316 if (len != fwrite(buffer, 1, len, fp)) { 317 report(LOG_ERR, "write failed on \"%s\" : %s", 318 hp->exten_file->string, get_errmsg()); 319 } 320 fclose(fp); 321 322 } /* mktagfile */ 323 324 /* 325 * Local Variables: 326 * tab-width: 4 327 * c-indent-level: 4 328 * c-argdecl-indent: 4 329 * c-continued-statement-offset: 4 330 * c-continued-brace-offset: -4 331 * c-label-offset: -4 332 * c-brace-offset: 0 333 * End: 334 */ 335