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.5 lukem #include <sys/cdefs.h> 24 1.1 gwr #ifndef lint 25 1.21 mrg __RCSID("$NetBSD: readfile.c,v 1.21 2019/02/03 03:19:30 mrg Exp $"); 26 1.1 gwr #endif 27 1.1 gwr 28 1.1 gwr 29 1.1 gwr /* 30 1.1 gwr * bootpd configuration file reading code. 31 1.1 gwr * 32 1.1 gwr * The routines in this file deal with reading, interpreting, and storing 33 1.1 gwr * the information found in the bootpd configuration file (usually 34 1.1 gwr * /etc/bootptab). 35 1.1 gwr */ 36 1.1 gwr 37 1.1 gwr 38 1.1 gwr #include <sys/types.h> 39 1.1 gwr #include <sys/stat.h> 40 1.1 gwr #include <sys/file.h> 41 1.1 gwr #include <sys/time.h> 42 1.1 gwr #include <netinet/in.h> 43 1.1 gwr 44 1.7 kleink #include <errno.h> 45 1.1 gwr #include <stdlib.h> 46 1.1 gwr #include <stdio.h> 47 1.1 gwr #include <string.h> 48 1.15 tls #include <strings.h> 49 1.6 kleink #include <time.h> 50 1.1 gwr #include <ctype.h> 51 1.1 gwr #include <assert.h> 52 1.1 gwr #include <syslog.h> 53 1.1 gwr 54 1.1 gwr #include "bootp.h" 55 1.1 gwr #include "hash.h" 56 1.1 gwr #include "hwaddr.h" 57 1.1 gwr #include "lookup.h" 58 1.1 gwr #include "readfile.h" 59 1.1 gwr #include "report.h" 60 1.1 gwr #include "tzone.h" 61 1.1 gwr #include "bootpd.h" 62 1.1 gwr 63 1.1 gwr #define HASHTABLESIZE 257 /* Hash table size (prime) */ 64 1.1 gwr 65 1.1 gwr /* Non-standard hardware address type (see bootp.h) */ 66 1.1 gwr #define HTYPE_DIRECT 0 67 1.1 gwr 68 1.1 gwr /* Error codes returned by eval_symbol: */ 69 1.1 gwr #define SUCCESS 0 70 1.1 gwr #define E_END_OF_ENTRY (-1) 71 1.1 gwr #define E_SYNTAX_ERROR (-2) 72 1.1 gwr #define E_UNKNOWN_SYMBOL (-3) 73 1.1 gwr #define E_BAD_IPADDR (-4) 74 1.1 gwr #define E_BAD_HWADDR (-5) 75 1.1 gwr #define E_BAD_LONGWORD (-6) 76 1.1 gwr #define E_BAD_HWATYPE (-7) 77 1.1 gwr #define E_BAD_PATHNAME (-8) 78 1.2 gwr #define E_BAD_VALUE (-9) 79 1.1 gwr 80 1.1 gwr /* Tag idendities. */ 81 1.1 gwr #define SYM_NULL 0 82 1.1 gwr #define SYM_BOOTFILE 1 83 1.1 gwr #define SYM_COOKIE_SERVER 2 84 1.1 gwr #define SYM_DOMAIN_SERVER 3 85 1.1 gwr #define SYM_GATEWAY 4 86 1.1 gwr #define SYM_HWADDR 5 87 1.1 gwr #define SYM_HOMEDIR 6 88 1.1 gwr #define SYM_HTYPE 7 89 1.1 gwr #define SYM_IMPRESS_SERVER 8 90 1.1 gwr #define SYM_IPADDR 9 91 1.1 gwr #define SYM_LOG_SERVER 10 92 1.1 gwr #define SYM_LPR_SERVER 11 93 1.1 gwr #define SYM_NAME_SERVER 12 94 1.1 gwr #define SYM_RLP_SERVER 13 95 1.1 gwr #define SYM_SUBNET_MASK 14 96 1.1 gwr #define SYM_TIME_OFFSET 15 97 1.1 gwr #define SYM_TIME_SERVER 16 98 1.1 gwr #define SYM_VENDOR_MAGIC 17 99 1.1 gwr #define SYM_SIMILAR_ENTRY 18 100 1.1 gwr #define SYM_NAME_SWITCH 19 101 1.1 gwr #define SYM_BOOTSIZE 20 102 1.1 gwr #define SYM_BOOT_SERVER 22 103 1.1 gwr #define SYM_TFTPDIR 23 104 1.1 gwr #define SYM_DUMP_FILE 24 105 1.1 gwr #define SYM_DOMAIN_NAME 25 106 1.1 gwr #define SYM_SWAP_SERVER 26 107 1.1 gwr #define SYM_ROOT_PATH 27 108 1.1 gwr #define SYM_EXTEN_FILE 28 109 1.1 gwr #define SYM_REPLY_ADDR 29 110 1.1 gwr #define SYM_NIS_DOMAIN 30 /* RFC 1533 */ 111 1.1 gwr #define SYM_NIS_SERVER 31 /* RFC 1533 */ 112 1.1 gwr #define SYM_NTP_SERVER 32 /* RFC 1533 */ 113 1.1 gwr #define SYM_EXEC_FILE 33 /* YORK_EX_OPTION */ 114 1.2 gwr #define SYM_MSG_SIZE 34 115 1.2 gwr #define SYM_MIN_WAIT 35 116 1.1 gwr /* XXX - Add new tags here */ 117 1.1 gwr 118 1.2 gwr #define OP_ADDITION 1 /* Operations on tags */ 119 1.1 gwr #define OP_DELETION 2 120 1.1 gwr #define OP_BOOLEAN 3 121 1.1 gwr 122 1.2 gwr #define MAXINADDRS 16 /* Max size of an IP address list */ 123 1.2 gwr #define MAXBUFLEN 256 /* Max temp buffer space */ 124 1.1 gwr #define MAXENTRYLEN 2048 /* Max size of an entire entry */ 125 1.1 gwr 126 1.1 gwr 128 1.1 gwr 129 1.1 gwr /* 130 1.1 gwr * Structure used to map a configuration-file symbol (such as "ds") to a 131 1.1 gwr * unique integer. 132 1.1 gwr */ 133 1.1 gwr 134 1.16 xtraeme struct symbolmap { 135 1.1 gwr const char *symbol; 136 1.1 gwr int symbolcode; 137 1.1 gwr }; 138 1.1 gwr 139 1.1 gwr 140 1.16 xtraeme struct htypename { 141 1.1 gwr const char *name; 142 1.1 gwr byte htype; 143 1.1 gwr }; 144 1.1 gwr 145 1.1 gwr 146 1.1 gwr PRIVATE int nhosts; /* Number of hosts (/w hw or IP address) */ 147 1.1 gwr PRIVATE int nentries; /* Total number of entries */ 148 1.1 gwr PRIVATE int32 modtime = 0; /* Last modification time of bootptab */ 149 1.1 gwr PRIVATE char *current_hostname; /* Name of the current entry. */ 150 1.1 gwr PRIVATE char current_tagname[8]; 151 1.1 gwr 152 1.1 gwr /* 153 1.1 gwr * List of symbolic names used in the bootptab file. The order and actual 154 1.1 gwr * values of the symbol codes (SYM_. . .) are unimportant, but they must 155 1.1 gwr * all be unique. 156 1.1 gwr */ 157 1.1 gwr 158 1.1 gwr PRIVATE struct symbolmap symbol_list[] = { 159 1.1 gwr {"bf", SYM_BOOTFILE}, 160 1.1 gwr {"bs", SYM_BOOTSIZE}, 161 1.1 gwr {"cs", SYM_COOKIE_SERVER}, 162 1.1 gwr {"df", SYM_DUMP_FILE}, 163 1.1 gwr {"dn", SYM_DOMAIN_NAME}, 164 1.1 gwr {"ds", SYM_DOMAIN_SERVER}, 165 1.1 gwr {"ef", SYM_EXTEN_FILE}, 166 1.1 gwr {"ex", SYM_EXEC_FILE}, /* YORK_EX_OPTION */ 167 1.1 gwr {"gw", SYM_GATEWAY}, 168 1.1 gwr {"ha", SYM_HWADDR}, 169 1.1 gwr {"hd", SYM_HOMEDIR}, 170 1.1 gwr {"hn", SYM_NAME_SWITCH}, 171 1.1 gwr {"ht", SYM_HTYPE}, 172 1.1 gwr {"im", SYM_IMPRESS_SERVER}, 173 1.1 gwr {"ip", SYM_IPADDR}, 174 1.1 gwr {"lg", SYM_LOG_SERVER}, 175 1.2 gwr {"lp", SYM_LPR_SERVER}, 176 1.2 gwr {"ms", SYM_MSG_SIZE}, 177 1.1 gwr {"mw", SYM_MIN_WAIT}, 178 1.1 gwr {"ns", SYM_NAME_SERVER}, 179 1.1 gwr {"nt", SYM_NTP_SERVER}, 180 1.1 gwr {"ra", SYM_REPLY_ADDR}, 181 1.1 gwr {"rl", SYM_RLP_SERVER}, 182 1.1 gwr {"rp", SYM_ROOT_PATH}, 183 1.1 gwr {"sa", SYM_BOOT_SERVER}, 184 1.1 gwr {"sm", SYM_SUBNET_MASK}, 185 1.1 gwr {"sw", SYM_SWAP_SERVER}, 186 1.1 gwr {"tc", SYM_SIMILAR_ENTRY}, 187 1.1 gwr {"td", SYM_TFTPDIR}, 188 1.1 gwr {"to", SYM_TIME_OFFSET}, 189 1.1 gwr {"ts", SYM_TIME_SERVER}, 190 1.1 gwr {"vm", SYM_VENDOR_MAGIC}, 191 1.1 gwr {"yd", SYM_NIS_DOMAIN}, 192 1.1 gwr {"ys", SYM_NIS_SERVER}, 193 1.1 gwr /* XXX - Add new tags here */ 194 1.1 gwr }; 195 1.1 gwr 196 1.1 gwr 197 1.1 gwr /* 198 1.1 gwr * List of symbolic names for hardware types. Name translates into 199 1.1 gwr * hardware type code listed with it. Names must begin with a letter 200 1.1 gwr * and must be all lowercase. This is searched linearly, so put 201 1.1 gwr * commonly-used entries near the beginning. 202 1.1 gwr */ 203 1.1 gwr 204 1.1 gwr PRIVATE struct htypename htnamemap[] = { 205 1.1 gwr {"ethernet", HTYPE_ETHERNET}, 206 1.1 gwr {"ethernet3", HTYPE_EXP_ETHERNET}, 207 1.1 gwr {"ether", HTYPE_ETHERNET}, 208 1.1 gwr {"ether3", HTYPE_EXP_ETHERNET}, 209 1.1 gwr {"ieee802", HTYPE_IEEE802}, 210 1.1 gwr {"tr", HTYPE_IEEE802}, 211 1.1 gwr {"token-ring", HTYPE_IEEE802}, 212 1.1 gwr {"pronet", HTYPE_PRONET}, 213 1.1 gwr {"chaos", HTYPE_CHAOS}, 214 1.1 gwr {"arcnet", HTYPE_ARCNET}, 215 1.1 gwr {"ax.25", HTYPE_AX25}, 216 1.1 gwr {"direct", HTYPE_DIRECT}, 217 1.1 gwr {"serial", HTYPE_DIRECT}, 218 1.1 gwr {"slip", HTYPE_DIRECT}, 219 1.1 gwr {"ppp", HTYPE_DIRECT} 220 1.1 gwr }; 221 1.1 gwr 222 1.1 gwr 223 1.1 gwr 224 1.1 gwr /* 225 1.1 gwr * Externals and forward declarations. 226 1.1 gwr */ 227 1.9 wiz 228 1.1 gwr boolean nmcmp(hash_datum *, hash_datum *); 229 1.1 gwr 230 1.9 wiz PRIVATE void 231 1.1 gwr adjust(char **); 232 1.9 wiz PRIVATE void 233 1.1 gwr del_string(struct shared_string *); 234 1.9 wiz PRIVATE void 235 1.1 gwr del_bindata(struct shared_bindata *); 236 1.9 wiz PRIVATE void 237 1.1 gwr del_iplist(struct in_addr_list *); 238 1.9 wiz PRIVATE void 239 1.1 gwr eat_whitespace(char **); 240 1.9 wiz PRIVATE int 241 1.1 gwr eval_symbol(char **, struct host *); 242 1.9 wiz PRIVATE void 243 1.1 gwr fill_defaults(struct host *, char **); 244 1.9 wiz PRIVATE void 245 1.1 gwr free_host(hash_datum *); 246 1.9 wiz PRIVATE struct in_addr_list * 247 1.1 gwr get_addresses(char **); 248 1.9 wiz PRIVATE struct shared_string * 249 1.1 gwr get_shared_string(char **); 250 1.9 wiz PRIVATE char * 251 1.1 gwr get_string(char **, char *, u_int *); 252 1.9 wiz PRIVATE u_int32 253 1.1 gwr get_u_long(char **); 254 1.9 wiz PRIVATE boolean 255 1.1 gwr goodname(char *); 256 1.9 wiz PRIVATE boolean 257 1.1 gwr hwinscmp(hash_datum *, hash_datum *); 258 1.9 wiz PRIVATE int 259 1.1 gwr interp_byte(char **, byte *); 260 1.9 wiz PRIVATE void 261 1.1 gwr makelower(char *); 262 1.9 wiz PRIVATE boolean 263 1.1 gwr nullcmp(hash_datum *, hash_datum *); 264 1.9 wiz PRIVATE int 265 1.1 gwr process_entry(struct host *, char *); 266 1.9 wiz PRIVATE int 267 1.1 gwr process_generic(char **, struct shared_bindata **, u_int); 268 1.9 wiz PRIVATE byte * 269 1.1 gwr prs_haddr(char **, u_int); 270 1.9 wiz PRIVATE int 271 1.1 gwr prs_inetaddr(char **, u_int32 *); 272 1.9 wiz PRIVATE void 273 1.1 gwr read_entry(FILE *, char *, u_int *); 274 1.9 wiz PRIVATE char * 275 1.1 gwr smalloc(u_int); 276 1.1 gwr 277 1.1 gwr 278 1.1 gwr 280 1.1 gwr /* 281 1.1 gwr * Vendor magic cookies for CMU and RFC1048 282 1.1 gwr */ 283 1.1 gwr u_char vm_cmu[4] = VM_CMU; 284 1.1 gwr u_char vm_rfc1048[4] = VM_RFC1048; 285 1.1 gwr 286 1.1 gwr /* 287 1.1 gwr * Main hash tables 288 1.1 gwr */ 289 1.1 gwr hash_tbl *hwhashtable; 290 1.1 gwr hash_tbl *iphashtable; 291 1.1 gwr hash_tbl *nmhashtable; 292 1.1 gwr 293 1.1 gwr /* 294 1.1 gwr * Allocate hash tables for hardware address, ip address, and hostname 295 1.1 gwr * (shared by bootpd and bootpef) 296 1.9 wiz */ 297 1.1 gwr void 298 1.1 gwr rdtab_init(void) 299 1.1 gwr { 300 1.1 gwr hwhashtable = hash_Init(HASHTABLESIZE); 301 1.1 gwr iphashtable = hash_Init(HASHTABLESIZE); 302 1.1 gwr nmhashtable = hash_Init(HASHTABLESIZE); 303 1.1 gwr if (!(hwhashtable && iphashtable && nmhashtable)) { 304 1.1 gwr report(LOG_ERR, "Unable to allocate hash tables."); 305 1.1 gwr exit(1); 306 1.1 gwr } 307 1.1 gwr } 308 1.1 gwr 309 1.1 gwr 311 1.1 gwr /* 312 1.1 gwr * Read bootptab database file. Avoid rereading the file if the 313 1.1 gwr * write date hasn't changed since the last time we read it. 314 1.9 wiz */ 315 1.1 gwr 316 1.1 gwr void 317 1.1 gwr readtab(int force) 318 1.1 gwr { 319 1.1 gwr struct host *hp; 320 1.1 gwr FILE *fp; 321 1.1 gwr struct stat st; 322 1.1 gwr unsigned hashcode, buflen; 323 1.1 gwr static char buffer[MAXENTRYLEN]; 324 1.1 gwr 325 1.1 gwr /* 326 1.1 gwr * Check the last modification time. 327 1.1 gwr */ 328 1.1 gwr if (stat(bootptab, &st) < 0) { 329 1.1 gwr report(LOG_ERR, "stat on \"%s\": %s", 330 1.1 gwr bootptab, get_errmsg()); 331 1.1 gwr return; 332 1.1 gwr } 333 1.12 itojun #ifdef DEBUG 334 1.1 gwr if (debug > 3) { 335 1.1 gwr char timestr[28]; 336 1.1 gwr strlcpy(timestr, ctime(&(st.st_mtime)), sizeof(timestr)); 337 1.1 gwr /* zap the newline */ 338 1.1 gwr timestr[24] = '\0'; 339 1.1 gwr report(LOG_INFO, "bootptab mtime: %s", 340 1.1 gwr timestr); 341 1.1 gwr } 342 1.1 gwr #endif 343 1.1 gwr if ((force == 0) && 344 1.1 gwr (st.st_mtime == modtime) && 345 1.1 gwr st.st_nlink) { 346 1.1 gwr /* 347 1.1 gwr * hasn't been modified or deleted yet. 348 1.1 gwr */ 349 1.1 gwr return; 350 1.1 gwr } 351 1.1 gwr if (debug) 352 1.1 gwr report(LOG_INFO, "reading %s\"%s\"", 353 1.1 gwr (modtime != 0L) ? "new " : "", 354 1.1 gwr bootptab); 355 1.1 gwr 356 1.1 gwr /* 357 1.1 gwr * Open bootptab file. 358 1.1 gwr */ 359 1.1 gwr if ((fp = fopen(bootptab, "r")) == NULL) { 360 1.1 gwr report(LOG_ERR, "error opening \"%s\": %s", bootptab, get_errmsg()); 361 1.1 gwr return; 362 1.1 gwr } 363 1.1 gwr /* 364 1.1 gwr * Record file modification time. 365 1.1 gwr */ 366 1.1 gwr if (fstat(fileno(fp), &st) < 0) { 367 1.1 gwr report(LOG_ERR, "fstat: %s", get_errmsg()); 368 1.1 gwr fclose(fp); 369 1.1 gwr return; 370 1.1 gwr } 371 1.1 gwr modtime = st.st_mtime; 372 1.1 gwr 373 1.1 gwr /* 374 1.1 gwr * Entirely erase all hash tables. 375 1.1 gwr */ 376 1.1 gwr hash_Reset(hwhashtable, free_host); 377 1.1 gwr hash_Reset(iphashtable, free_host); 378 1.1 gwr hash_Reset(nmhashtable, free_host); 379 1.1 gwr 380 1.1 gwr nhosts = 0; 381 1.1 gwr nentries = 0; 382 1.1 gwr while (TRUE) { 383 1.1 gwr buflen = sizeof(buffer); 384 1.1 gwr read_entry(fp, buffer, &buflen); 385 1.1 gwr if (buflen == 0) { /* More entries? */ 386 1.1 gwr break; 387 1.1 gwr } 388 1.1 gwr hp = (struct host *) smalloc(sizeof(struct host)); 389 1.1 gwr bzero((char *) hp, sizeof(*hp)); 390 1.1 gwr /* the link count it zero */ 391 1.1 gwr 392 1.1 gwr /* 393 1.1 gwr * Get individual info 394 1.1 gwr */ 395 1.1 gwr if (process_entry(hp, buffer) < 0) { 396 1.1 gwr hp->linkcount = 1; 397 1.1 gwr free_host((hash_datum *) hp); 398 1.1 gwr continue; 399 1.1 gwr } 400 1.1 gwr /* 401 1.1 gwr * If this is not a dummy entry, and the IP or HW 402 1.1 gwr * address is not yet set, try to get them here. 403 1.1 gwr * Dummy entries have . as first char of name. 404 1.1 gwr */ 405 1.1 gwr if (goodname(hp->hostname->string)) { 406 1.1 gwr char *hn = hp->hostname->string; 407 1.1 gwr u_int32 value; 408 1.1 gwr if (hp->flags.iaddr == 0) { 409 1.1 gwr if (lookup_ipa(hn, &value)) { 410 1.1 gwr report(LOG_ERR, "can not get IP addr for %s", hn); 411 1.1 gwr report(LOG_ERR, "(dummy names should start with '.')"); 412 1.1 gwr } else { 413 1.1 gwr hp->iaddr.s_addr = value; 414 1.1 gwr hp->flags.iaddr = TRUE; 415 1.1 gwr } 416 1.1 gwr } 417 1.1 gwr /* Set default subnet mask. */ 418 1.1 gwr if (hp->flags.subnet_mask == 0) { 419 1.1 gwr if (lookup_netmask(hp->iaddr.s_addr, &value)) { 420 1.1 gwr report(LOG_ERR, "can not get netmask for %s", hn); 421 1.1 gwr } else { 422 1.1 gwr hp->subnet_mask.s_addr = value; 423 1.1 gwr hp->flags.subnet_mask = TRUE; 424 1.1 gwr } 425 1.1 gwr } 426 1.1 gwr } 427 1.1 gwr if (hp->flags.iaddr) { 428 1.1 gwr nhosts++; 429 1.1 gwr } 430 1.1 gwr /* Register by HW addr if known. */ 431 1.1 gwr if (hp->flags.htype && hp->flags.haddr) { 432 1.1 gwr /* We will either insert it or free it. */ 433 1.1 gwr hp->linkcount++; 434 1.1 gwr hashcode = hash_HashFunction(hp->haddr, haddrlength(hp->htype)); 435 1.3 gwr if (hash_Insert(hwhashtable, hashcode, hwinscmp, hp, hp) < 0) { 436 1.1 gwr report(LOG_NOTICE, "duplicate %s address: %s", 437 1.1 gwr netname(hp->htype), 438 1.1 gwr haddrtoa(hp->haddr, haddrlength(hp->htype))); 439 1.1 gwr free_host((hash_datum *) hp); 440 1.1 gwr continue; 441 1.1 gwr } 442 1.1 gwr } 443 1.1 gwr /* Register by IP addr if known. */ 444 1.1 gwr if (hp->flags.iaddr) { 445 1.1 gwr hashcode = hash_HashFunction((u_char *) & (hp->iaddr.s_addr), 4); 446 1.1 gwr if (hash_Insert(iphashtable, hashcode, nullcmp, hp, hp) < 0) { 447 1.1 gwr report(LOG_ERR, 448 1.1 gwr "hash_Insert() failed on IP address insertion"); 449 1.1 gwr } else { 450 1.1 gwr /* Just inserted the host struct in a new hash list. */ 451 1.1 gwr hp->linkcount++; 452 1.1 gwr } 453 1.1 gwr } 454 1.1 gwr /* Register by Name (always known) */ 455 1.1 gwr hashcode = hash_HashFunction((u_char *) hp->hostname->string, 456 1.1 gwr strlen(hp->hostname->string)); 457 1.1 gwr if (hash_Insert(nmhashtable, hashcode, nullcmp, 458 1.1 gwr hp->hostname->string, hp) < 0) { 459 1.1 gwr report(LOG_ERR, 460 1.1 gwr "hash_Insert() failed on insertion of hostname: \"%s\"", 461 1.1 gwr hp->hostname->string); 462 1.1 gwr } else { 463 1.1 gwr /* Just inserted the host struct in a new hash list. */ 464 1.1 gwr hp->linkcount++; 465 1.1 gwr } 466 1.1 gwr 467 1.1 gwr nentries++; 468 1.1 gwr } 469 1.1 gwr 470 1.1 gwr fclose(fp); 471 1.1 gwr if (debug) 472 1.1 gwr report(LOG_INFO, "read %d entries (%d hosts) from \"%s\"", 473 1.1 gwr nentries, nhosts, bootptab); 474 1.1 gwr return; 475 1.1 gwr } 476 1.1 gwr 477 1.1 gwr 479 1.1 gwr 480 1.8 wiz /* 481 1.1 gwr * Read an entire host entry from the file pointed to by "fp" and insert it 482 1.8 wiz * into the memory pointed to by "buffer". Leading whitespace and comments 483 1.1 gwr * starting with "#" are ignored (removed). Backslashes (\) always quote 484 1.1 gwr * the next character except that newlines preceded by a backslash cause 485 1.1 gwr * line-continuation onto the next line. The entry is terminated by a 486 1.1 gwr * newline character which is not preceded by a backslash. Sequences 487 1.1 gwr * surrounded by double quotes are taken literally (including newlines, but 488 1.1 gwr * not backslashes). 489 1.1 gwr * 490 1.1 gwr * The "bufsiz" parameter points to an unsigned int which specifies the 491 1.1 gwr * maximum permitted buffer size. Upon return, this value will be replaced 492 1.1 gwr * with the actual length of the entry (not including the null terminator). 493 1.1 gwr * 494 1.1 gwr * This code is a little scary. . . . I don't like using gotos in C 495 1.1 gwr * either, but I first wrote this as an FSM diagram and gotos seemed like 496 1.9 wiz * the easiest way to implement it. Maybe later I'll clean it up. 497 1.1 gwr */ 498 1.17 lukem 499 1.17 lukem PRIVATE void 500 1.1 gwr read_entry(FILE *fp, char *buffer, unsigned int *bufsiz) 501 1.1 gwr { 502 1.1 gwr int c; 503 1.1 gwr unsigned int length; 504 1.1 gwr 505 1.1 gwr length = 0; 506 1.1 gwr 507 1.1 gwr /* 508 1.1 gwr * Eat whitespace, blank lines, and comment lines. 509 1.1 gwr */ 510 1.1 gwr top: 511 1.1 gwr c = fgetc(fp); 512 1.1 gwr if (c < 0) { 513 1.1 gwr goto done; /* Exit if end-of-file */ 514 1.1 gwr } 515 1.1 gwr if (isspace(c)) { 516 1.1 gwr goto top; /* Skip over whitespace */ 517 1.1 gwr } 518 1.1 gwr if (c == '#') { 519 1.1 gwr while (TRUE) { /* Eat comments after # */ 520 1.1 gwr c = fgetc(fp); 521 1.1 gwr if (c < 0) { 522 1.1 gwr goto done; /* Exit if end-of-file */ 523 1.1 gwr } 524 1.1 gwr if (c == '\n') { 525 1.1 gwr goto top; /* Try to read the next line */ 526 1.1 gwr } 527 1.1 gwr } 528 1.1 gwr } 529 1.1 gwr ungetc(c, fp); /* Other character, push it back to reprocess it */ 530 1.1 gwr 531 1.1 gwr 532 1.1 gwr /* 533 1.1 gwr * Now we're actually reading a data entry. Get each character and 534 1.1 gwr * assemble it into the data buffer, processing special characters like 535 1.1 gwr * double quotes (") and backslashes (\). 536 1.1 gwr */ 537 1.1 gwr 538 1.1 gwr mainloop: 539 1.1 gwr c = fgetc(fp); 540 1.1 gwr switch (c) { 541 1.1 gwr case EOF: 542 1.1 gwr case '\n': 543 1.1 gwr goto done; /* Exit on EOF or newline */ 544 1.1 gwr case '\\': 545 1.1 gwr c = fgetc(fp); /* Backslash, read a new character */ 546 1.1 gwr if (c < 0) { 547 1.1 gwr goto done; /* Exit on EOF */ 548 1.1 gwr } 549 1.1 gwr *buffer++ = c; /* Store the literal character */ 550 1.1 gwr length++; 551 1.1 gwr if (length < *bufsiz - 1) { 552 1.1 gwr goto mainloop; 553 1.1 gwr } else { 554 1.1 gwr goto done; 555 1.1 gwr } 556 1.1 gwr case '"': 557 1.1 gwr *buffer++ = '"'; /* Store double-quote */ 558 1.1 gwr length++; 559 1.1 gwr if (length >= *bufsiz - 1) { 560 1.1 gwr goto done; 561 1.1 gwr } 562 1.1 gwr while (TRUE) { /* Special quote processing loop */ 563 1.1 gwr c = fgetc(fp); 564 1.1 gwr switch (c) { 565 1.1 gwr case EOF: 566 1.1 gwr goto done; /* Exit on EOF . . . */ 567 1.1 gwr case '"': 568 1.1 gwr *buffer++ = '"';/* Store matching quote */ 569 1.1 gwr length++; 570 1.1 gwr if (length < *bufsiz - 1) { 571 1.1 gwr goto mainloop; /* And continue main loop */ 572 1.1 gwr } else { 573 1.1 gwr goto done; 574 1.1 gwr } 575 1.1 gwr case '\\': 576 1.1 gwr if ((c = fgetc(fp)) < 0) { /* Backslash */ 577 1.1 gwr goto done; /* EOF. . . .*/ 578 1.1 gwr } /* else fall through */ 579 1.1 gwr default: 580 1.1 gwr *buffer++ = c; /* Other character, store it */ 581 1.1 gwr length++; 582 1.1 gwr if (length >= *bufsiz - 1) { 583 1.1 gwr goto done; 584 1.1 gwr } 585 1.1 gwr } 586 1.1 gwr } 587 1.1 gwr case ':': 588 1.1 gwr *buffer++ = c; /* Store colons */ 589 1.1 gwr length++; 590 1.1 gwr if (length >= *bufsiz - 1) { 591 1.1 gwr goto done; 592 1.1 gwr } 593 1.1 gwr do { /* But remove whitespace after them */ 594 1.1 gwr c = fgetc(fp); 595 1.1 gwr if ((c < 0) || (c == '\n')) { 596 1.1 gwr goto done; 597 1.1 gwr } 598 1.1 gwr } while (isspace(c)); /* Skip whitespace */ 599 1.1 gwr 600 1.1 gwr if (c == '\\') { /* Backslash quotes next character */ 601 1.1 gwr c = fgetc(fp); 602 1.1 gwr if (c < 0) { 603 1.1 gwr goto done; 604 1.1 gwr } 605 1.1 gwr if (c == '\n') { 606 1.21 mrg goto top; /* Backslash-newline continuation */ 607 1.1 gwr } 608 1.1 gwr } 609 1.1 gwr /* fall through if "other" character */ 610 1.1 gwr /* FALLTHROUGH */ 611 1.1 gwr default: 612 1.1 gwr *buffer++ = c; /* Store other characters */ 613 1.1 gwr length++; 614 1.1 gwr if (length >= *bufsiz - 1) { 615 1.1 gwr goto done; 616 1.1 gwr } 617 1.1 gwr } 618 1.1 gwr goto mainloop; /* Keep going */ 619 1.1 gwr 620 1.1 gwr done: 621 1.1 gwr *buffer = '\0'; /* Terminate string */ 622 1.1 gwr *bufsiz = length; /* Tell the caller its length */ 623 1.1 gwr } 624 1.1 gwr 625 1.1 gwr 627 1.1 gwr 628 1.1 gwr /* 629 1.1 gwr * Parse out all the various tags and parameters in the host entry pointed 630 1.1 gwr * to by "src". Stuff all the data into the appropriate fields of the 631 1.1 gwr * host structure pointed to by "host". If there is any problem with the 632 1.1 gwr * entry, an error message is reported via report(), no further processing 633 1.1 gwr * is done, and -1 is returned. Successful calls return 0. 634 1.9 wiz * 635 1.1 gwr * (Some errors probably shouldn't be so completely fatal. . . .) 636 1.1 gwr */ 637 1.16 xtraeme 638 1.1 gwr PRIVATE int 639 1.1 gwr process_entry(struct host *host, char *src) 640 1.1 gwr { 641 1.1 gwr int retval; 642 1.1 gwr const char *msg; 643 1.1 gwr 644 1.1 gwr if (!host || *src == '\0') { 645 1.1 gwr return -1; 646 1.1 gwr } 647 1.1 gwr host->hostname = get_shared_string(&src); 648 1.1 gwr #if 0 649 1.1 gwr /* Be more liberal for the benefit of dummy tag names. */ 650 1.1 gwr if (!goodname(host->hostname->string)) { 651 1.1 gwr report(LOG_ERR, "bad hostname: \"%s\"", host->hostname->string); 652 1.1 gwr del_string(host->hostname); 653 1.1 gwr return -1; 654 1.1 gwr } 655 1.1 gwr #endif 656 1.1 gwr current_hostname = host->hostname->string; 657 1.1 gwr adjust(&src); 658 1.1 gwr while (TRUE) { 659 1.1 gwr retval = eval_symbol(&src, host); 660 1.1 gwr if (retval == SUCCESS) { 661 1.1 gwr adjust(&src); 662 1.1 gwr continue; 663 1.1 gwr } 664 1.1 gwr if (retval == E_END_OF_ENTRY) { 665 1.1 gwr /* The default subnet mask is set in readtab() */ 666 1.1 gwr return 0; 667 1.1 gwr } 668 1.1 gwr /* Some kind of error. */ 669 1.1 gwr switch (retval) { 670 1.1 gwr case E_SYNTAX_ERROR: 671 1.1 gwr msg = "bad syntax"; 672 1.1 gwr break; 673 1.1 gwr case E_UNKNOWN_SYMBOL: 674 1.1 gwr msg = "unknown symbol"; 675 1.1 gwr break; 676 1.1 gwr case E_BAD_IPADDR: 677 1.1 gwr msg = "bad INET address"; 678 1.1 gwr break; 679 1.1 gwr case E_BAD_HWADDR: 680 1.1 gwr msg = "bad hardware address"; 681 1.1 gwr break; 682 1.1 gwr case E_BAD_LONGWORD: 683 1.1 gwr msg = "bad longword value"; 684 1.1 gwr break; 685 1.18 wiz case E_BAD_HWATYPE: 686 1.2 gwr msg = "bad HW address type"; 687 1.2 gwr break; 688 1.18 wiz case E_BAD_PATHNAME: 689 1.1 gwr msg = "bad pathname (need leading '/')"; 690 1.11 wiz break; 691 1.1 gwr case E_BAD_VALUE: 692 1.1 gwr msg = "bad value"; 693 1.1 gwr break; 694 1.1 gwr default: 695 1.1 gwr msg = "unknown error"; 696 1.1 gwr break; 697 1.1 gwr } /* switch */ 698 1.1 gwr report(LOG_ERR, "in entry named \"%s\", symbol \"%s\": %s", 699 1.1 gwr current_hostname, current_tagname, msg); 700 1.1 gwr return -1; 701 1.1 gwr } 702 1.1 gwr } 703 1.1 gwr 704 1.1 gwr 706 1.1 gwr /* 707 1.1 gwr * Macros for use in the function below: 708 1.1 gwr */ 709 1.1 gwr 710 1.1 gwr /* Parse one INET address stored directly in MEMBER. */ 711 1.1 gwr #define PARSE_IA1(MEMBER) do \ 712 1.1 gwr { \ 713 1.1 gwr if (optype == OP_BOOLEAN) \ 714 1.1 gwr return E_SYNTAX_ERROR; \ 715 1.1 gwr hp->flags.MEMBER = FALSE; \ 716 1.1 gwr if (optype == OP_ADDITION) { \ 717 1.1 gwr if (prs_inetaddr(symbol, &value) < 0) \ 718 1.1 gwr return E_BAD_IPADDR; \ 719 1.1 gwr hp->MEMBER.s_addr = value; \ 720 1.1 gwr hp->flags.MEMBER = TRUE; \ 721 1.1 gwr } \ 722 1.1 gwr } while (0) 723 1.1 gwr 724 1.1 gwr /* Parse a list of INET addresses pointed to by MEMBER */ 725 1.1 gwr #define PARSE_IAL(MEMBER) do \ 726 1.1 gwr { \ 727 1.1 gwr if (optype == OP_BOOLEAN) \ 728 1.1 gwr return E_SYNTAX_ERROR; \ 729 1.1 gwr if (hp->flags.MEMBER) { \ 730 1.1 gwr hp->flags.MEMBER = FALSE; \ 731 1.1 gwr assert(hp->MEMBER); \ 732 1.1 gwr del_iplist(hp->MEMBER); \ 733 1.1 gwr hp->MEMBER = NULL; \ 734 1.1 gwr } \ 735 1.1 gwr if (optype == OP_ADDITION) { \ 736 1.1 gwr hp->MEMBER = get_addresses(symbol); \ 737 1.1 gwr if (hp->MEMBER == NULL) \ 738 1.1 gwr return E_SYNTAX_ERROR; \ 739 1.1 gwr hp->flags.MEMBER = TRUE; \ 740 1.1 gwr } \ 741 1.1 gwr } while (0) 742 1.1 gwr 743 1.1 gwr /* Parse a shared string pointed to by MEMBER */ 744 1.1 gwr #define PARSE_STR(MEMBER) do \ 745 1.1 gwr { \ 746 1.1 gwr if (optype == OP_BOOLEAN) \ 747 1.1 gwr return E_SYNTAX_ERROR; \ 748 1.1 gwr if (hp->flags.MEMBER) { \ 749 1.1 gwr hp->flags.MEMBER = FALSE; \ 750 1.1 gwr assert(hp->MEMBER); \ 751 1.1 gwr del_string(hp->MEMBER); \ 752 1.1 gwr hp->MEMBER = NULL; \ 753 1.1 gwr } \ 754 1.1 gwr if (optype == OP_ADDITION) { \ 755 1.1 gwr hp->MEMBER = get_shared_string(symbol); \ 756 1.2 gwr if (hp->MEMBER == NULL) \ 757 1.2 gwr return E_SYNTAX_ERROR; \ 758 1.2 gwr hp->flags.MEMBER = TRUE; \ 759 1.2 gwr } \ 760 1.2 gwr } while (0) 761 1.2 gwr 762 1.2 gwr /* Parse an integer value for MEMBER */ 763 1.2 gwr #define PARSE_INT(MEMBER) do \ 764 1.2 gwr { \ 765 1.2 gwr if (optype == OP_BOOLEAN) \ 766 1.2 gwr return E_SYNTAX_ERROR; \ 767 1.2 gwr hp->flags.MEMBER = FALSE; \ 768 1.2 gwr if (optype == OP_ADDITION) { \ 769 1.1 gwr value = get_u_long(symbol); \ 770 1.1 gwr hp->MEMBER = value; \ 771 1.1 gwr hp->flags.MEMBER = TRUE; \ 772 1.1 gwr } \ 773 1.1 gwr } while (0) 774 1.1 gwr 775 1.1 gwr /* 776 1.1 gwr * Evaluate the two-character tag symbol pointed to by "symbol" and place 777 1.1 gwr * the data in the structure pointed to by "hp". The pointer pointed to 778 1.9 wiz * by "symbol" is updated to point past the source string (but may not 779 1.1 gwr * point to the next tag entry). 780 1.1 gwr * 781 1.1 gwr * Obviously, this need a few more comments. . . . 782 1.1 gwr */ 783 1.1 gwr PRIVATE int 784 1.16 xtraeme eval_symbol(char **symbol, struct host *hp) 785 1.1 gwr { 786 1.1 gwr char tmpstr[MAXSTRINGLEN]; 787 1.1 gwr byte *tmphaddr; 788 1.1 gwr struct symbolmap *symbolptr; 789 1.1 gwr u_int32 value; 790 1.1 gwr int32 ltimeoff; 791 1.1 gwr int i, numsymbols; 792 1.1 gwr unsigned len; 793 1.1 gwr int optype; /* Indicates boolean, addition, or deletion */ 794 1.1 gwr 795 1.1 gwr eat_whitespace(symbol); 796 1.1 gwr 797 1.1 gwr /* Make sure this is set before returning. */ 798 1.1 gwr current_tagname[0] = (*symbol)[0]; 799 1.1 gwr current_tagname[1] = (*symbol)[1]; 800 1.1 gwr current_tagname[2] = 0; 801 1.1 gwr 802 1.1 gwr if ((*symbol)[0] == '\0') { 803 1.1 gwr return E_END_OF_ENTRY; 804 1.1 gwr } 805 1.12 itojun if ((*symbol)[0] == ':') { 806 1.12 itojun return SUCCESS; 807 1.1 gwr } 808 1.1 gwr if ((*symbol)[0] == 'T') { /* generic symbol */ 809 1.1 gwr (*symbol)++; 810 1.1 gwr value = get_u_long(symbol); 811 1.1 gwr snprintf(current_tagname, sizeof(current_tagname), 812 1.1 gwr "T%d", value); 813 1.1 gwr eat_whitespace(symbol); 814 1.1 gwr if ((*symbol)[0] != '=') { 815 1.1 gwr return E_SYNTAX_ERROR; 816 1.1 gwr } 817 1.1 gwr (*symbol)++; 818 1.1 gwr if (!(hp->generic)) { 819 1.1 gwr hp->generic = (struct shared_bindata *) 820 1.1 gwr smalloc(sizeof(struct shared_bindata)); 821 1.1 gwr } 822 1.1 gwr if (process_generic(symbol, &(hp->generic), (byte) (value & 0xFF))) 823 1.1 gwr return E_SYNTAX_ERROR; 824 1.1 gwr hp->flags.generic = TRUE; 825 1.1 gwr return SUCCESS; 826 1.1 gwr } 827 1.1 gwr /* 828 1.1 gwr * Determine the type of operation to be done on this symbol 829 1.1 gwr */ 830 1.1 gwr switch ((*symbol)[2]) { 831 1.1 gwr case '=': 832 1.1 gwr optype = OP_ADDITION; 833 1.1 gwr break; 834 1.1 gwr case '@': 835 1.1 gwr optype = OP_DELETION; 836 1.1 gwr break; 837 1.1 gwr case ':': 838 1.1 gwr case '\0': 839 1.1 gwr optype = OP_BOOLEAN; 840 1.1 gwr break; 841 1.1 gwr default: 842 1.1 gwr return E_SYNTAX_ERROR; 843 1.1 gwr } 844 1.1 gwr 845 1.1 gwr symbolptr = symbol_list; 846 1.1 gwr numsymbols = sizeof(symbol_list) / sizeof(struct symbolmap); 847 1.1 gwr for (i = 0; i < numsymbols; i++) { 848 1.1 gwr if (((symbolptr->symbol)[0] == (*symbol)[0]) && 849 1.1 gwr ((symbolptr->symbol)[1] == (*symbol)[1])) { 850 1.1 gwr break; 851 1.1 gwr } 852 1.1 gwr symbolptr++; 853 1.1 gwr } 854 1.1 gwr if (i >= numsymbols) { 855 1.1 gwr return E_UNKNOWN_SYMBOL; 856 1.1 gwr } 857 1.1 gwr /* 858 1.1 gwr * Skip past the = or @ character (to point to the data) if this 859 1.1 gwr * isn't a boolean operation. For boolean operations, just skip 860 1.1 gwr * over the two-character tag symbol (and nothing else. . . .). 861 1.1 gwr */ 862 1.1 gwr (*symbol) += (optype == OP_BOOLEAN) ? 2 : 3; 863 1.1 gwr 864 1.1 gwr eat_whitespace(symbol); 865 1.1 gwr 866 1.1 gwr /* The cases below are in order by symbolcode value. */ 867 1.1 gwr switch (symbolptr->symbolcode) { 868 1.1 gwr 869 1.1 gwr case SYM_BOOTFILE: 870 1.1 gwr PARSE_STR(bootfile); 871 1.1 gwr break; 872 1.1 gwr 873 1.1 gwr case SYM_COOKIE_SERVER: 874 1.1 gwr PARSE_IAL(cookie_server); 875 1.1 gwr break; 876 1.1 gwr 877 1.1 gwr case SYM_DOMAIN_SERVER: 878 1.1 gwr PARSE_IAL(domain_server); 879 1.1 gwr break; 880 1.1 gwr 881 1.1 gwr case SYM_GATEWAY: 882 1.1 gwr PARSE_IAL(gateway); 883 1.1 gwr break; 884 1.1 gwr 885 1.1 gwr case SYM_HWADDR: 886 1.1 gwr if (optype == OP_BOOLEAN) 887 1.1 gwr return E_SYNTAX_ERROR; 888 1.1 gwr hp->flags.haddr = FALSE; 889 1.1 gwr if (optype == OP_ADDITION) { 890 1.1 gwr /* Default the HW type to Ethernet */ 891 1.1 gwr if (hp->flags.htype == 0) { 892 1.1 gwr hp->flags.htype = TRUE; 893 1.1 gwr hp->htype = HTYPE_ETHERNET; 894 1.1 gwr } 895 1.1 gwr tmphaddr = prs_haddr(symbol, hp->htype); 896 1.1 gwr if (!tmphaddr) 897 1.1 gwr return E_BAD_HWADDR; 898 1.1 gwr bcopy(tmphaddr, hp->haddr, haddrlength(hp->htype)); 899 1.1 gwr hp->flags.haddr = TRUE; 900 1.1 gwr } 901 1.1 gwr break; 902 1.1 gwr 903 1.1 gwr case SYM_HOMEDIR: 904 1.1 gwr PARSE_STR(homedir); 905 1.1 gwr break; 906 1.1 gwr 907 1.1 gwr case SYM_HTYPE: 908 1.13 dsl if (optype == OP_BOOLEAN) 909 1.1 gwr return E_SYNTAX_ERROR; 910 1.1 gwr hp->flags.htype = FALSE; 911 1.1 gwr if (optype == OP_ADDITION) { 912 1.1 gwr value = 0L; /* Assume an illegal value */ 913 1.1 gwr eat_whitespace(symbol); 914 1.1 gwr if (isdigit((unsigned char)**symbol)) { 915 1.1 gwr value = get_u_long(symbol); 916 1.1 gwr } else { 917 1.1 gwr len = sizeof(tmpstr); 918 1.1 gwr (void) get_string(symbol, tmpstr, &len); 919 1.1 gwr makelower(tmpstr); 920 1.1 gwr numsymbols = sizeof(htnamemap) / 921 1.1 gwr sizeof(struct htypename); 922 1.1 gwr for (i = 0; i < numsymbols; i++) { 923 1.1 gwr if (!strcmp(htnamemap[i].name, tmpstr)) { 924 1.1 gwr break; 925 1.1 gwr } 926 1.1 gwr } 927 1.1 gwr if (i < numsymbols) { 928 1.1 gwr value = htnamemap[i].htype; 929 1.1 gwr } 930 1.1 gwr } 931 1.1 gwr if (value >= hwinfocnt) { 932 1.1 gwr return E_BAD_HWATYPE; 933 1.1 gwr } 934 1.1 gwr hp->htype = (byte) (value & 0xFF); 935 1.1 gwr hp->flags.htype = TRUE; 936 1.1 gwr } 937 1.1 gwr break; 938 1.1 gwr 939 1.1 gwr case SYM_IMPRESS_SERVER: 940 1.1 gwr PARSE_IAL(impress_server); 941 1.1 gwr break; 942 1.1 gwr 943 1.1 gwr case SYM_IPADDR: 944 1.1 gwr PARSE_IA1(iaddr); 945 1.1 gwr break; 946 1.1 gwr 947 1.1 gwr case SYM_LOG_SERVER: 948 1.1 gwr PARSE_IAL(log_server); 949 1.1 gwr break; 950 1.1 gwr 951 1.1 gwr case SYM_LPR_SERVER: 952 1.1 gwr PARSE_IAL(lpr_server); 953 1.1 gwr break; 954 1.1 gwr 955 1.1 gwr case SYM_NAME_SERVER: 956 1.1 gwr PARSE_IAL(name_server); 957 1.1 gwr break; 958 1.1 gwr 959 1.1 gwr case SYM_RLP_SERVER: 960 1.1 gwr PARSE_IAL(rlp_server); 961 1.1 gwr break; 962 1.1 gwr 963 1.1 gwr case SYM_SUBNET_MASK: 964 1.1 gwr PARSE_IA1(subnet_mask); 965 1.1 gwr break; 966 1.1 gwr 967 1.1 gwr case SYM_TIME_OFFSET: 968 1.1 gwr if (optype == OP_BOOLEAN) 969 1.1 gwr return E_SYNTAX_ERROR; 970 1.1 gwr hp->flags.time_offset = FALSE; 971 1.16 xtraeme if (optype == OP_ADDITION) { 972 1.1 gwr len = sizeof(tmpstr); 973 1.16 xtraeme (void) get_string(symbol, tmpstr, &len); 974 1.1 gwr if (!strncmp(tmpstr, "auto", 4)) { 975 1.1 gwr hp->time_offset = secondswest; 976 1.1 gwr } else { 977 1.1 gwr if (sscanf(tmpstr, "%d", <imeoff) != 1) 978 1.1 gwr return E_BAD_LONGWORD; 979 1.1 gwr hp->time_offset = ltimeoff; 980 1.1 gwr } 981 1.1 gwr hp->flags.time_offset = TRUE; 982 1.1 gwr } 983 1.1 gwr break; 984 1.1 gwr 985 1.1 gwr case SYM_TIME_SERVER: 986 1.1 gwr PARSE_IAL(time_server); 987 1.1 gwr break; 988 1.1 gwr 989 1.1 gwr case SYM_VENDOR_MAGIC: 990 1.1 gwr if (optype == OP_BOOLEAN) 991 1.1 gwr return E_SYNTAX_ERROR; 992 1.1 gwr hp->flags.vm_cookie = FALSE; 993 1.1 gwr if (optype == OP_ADDITION) { 994 1.1 gwr if (strncmp(*symbol, "auto", 4)) { 995 1.13 dsl /* The string is not "auto" */ 996 1.1 gwr if (!strncmp(*symbol, "rfc", 3)) { 997 1.1 gwr bcopy(vm_rfc1048, hp->vm_cookie, 4); 998 1.1 gwr } else if (!strncmp(*symbol, "cmu", 3)) { 999 1.1 gwr bcopy(vm_cmu, hp->vm_cookie, 4); 1000 1.1 gwr } else { 1001 1.1 gwr if (!isdigit((unsigned char)**symbol)) 1002 1.1 gwr return E_BAD_IPADDR; 1003 1.1 gwr if (prs_inetaddr(symbol, &value) < 0) 1004 1.1 gwr return E_BAD_IPADDR; 1005 1.1 gwr bcopy(&value, hp->vm_cookie, 4); 1006 1.1 gwr } 1007 1.1 gwr hp->flags.vm_cookie = TRUE; 1008 1.1 gwr } 1009 1.1 gwr } 1010 1.1 gwr break; 1011 1.1 gwr 1012 1.1 gwr case SYM_SIMILAR_ENTRY: 1013 1.1 gwr switch (optype) { 1014 1.1 gwr case OP_ADDITION: 1015 1.1 gwr fill_defaults(hp, symbol); 1016 1.1 gwr break; 1017 1.1 gwr default: 1018 1.1 gwr return E_SYNTAX_ERROR; 1019 1.1 gwr } 1020 1.1 gwr break; 1021 1.1 gwr 1022 1.1 gwr case SYM_NAME_SWITCH: 1023 1.1 gwr switch (optype) { 1024 1.1 gwr case OP_ADDITION: 1025 1.1 gwr return E_SYNTAX_ERROR; 1026 1.1 gwr case OP_DELETION: 1027 1.1 gwr hp->flags.send_name = FALSE; 1028 1.1 gwr hp->flags.name_switch = FALSE; 1029 1.1 gwr break; 1030 1.1 gwr case OP_BOOLEAN: 1031 1.1 gwr hp->flags.send_name = TRUE; 1032 1.1 gwr hp->flags.name_switch = TRUE; 1033 1.1 gwr break; 1034 1.1 gwr } 1035 1.1 gwr break; 1036 1.1 gwr 1037 1.1 gwr case SYM_BOOTSIZE: 1038 1.1 gwr switch (optype) { 1039 1.1 gwr case OP_ADDITION: 1040 1.1 gwr if (!strncmp(*symbol, "auto", 4)) { 1041 1.1 gwr hp->flags.bootsize = TRUE; 1042 1.1 gwr hp->flags.bootsize_auto = TRUE; 1043 1.1 gwr } else { 1044 1.1 gwr hp->bootsize = (unsigned int) get_u_long(symbol); 1045 1.1 gwr hp->flags.bootsize = TRUE; 1046 1.1 gwr hp->flags.bootsize_auto = FALSE; 1047 1.1 gwr } 1048 1.1 gwr break; 1049 1.1 gwr case OP_DELETION: 1050 1.1 gwr hp->flags.bootsize = FALSE; 1051 1.1 gwr break; 1052 1.1 gwr case OP_BOOLEAN: 1053 1.1 gwr hp->flags.bootsize = TRUE; 1054 1.1 gwr hp->flags.bootsize_auto = TRUE; 1055 1.1 gwr break; 1056 1.1 gwr } 1057 1.1 gwr break; 1058 1.1 gwr 1059 1.1 gwr case SYM_BOOT_SERVER: 1060 1.1 gwr PARSE_IA1(bootserver); 1061 1.1 gwr break; 1062 1.1 gwr 1063 1.1 gwr case SYM_TFTPDIR: 1064 1.1 gwr PARSE_STR(tftpdir); 1065 1.1 gwr if ((hp->tftpdir != NULL) && 1066 1.1 gwr (hp->tftpdir->string[0] != '/')) 1067 1.1 gwr return E_BAD_PATHNAME; 1068 1.1 gwr break; 1069 1.1 gwr 1070 1.1 gwr case SYM_DUMP_FILE: 1071 1.1 gwr PARSE_STR(dump_file); 1072 1.1 gwr break; 1073 1.1 gwr 1074 1.1 gwr case SYM_DOMAIN_NAME: 1075 1.1 gwr PARSE_STR(domain_name); 1076 1.1 gwr break; 1077 1.1 gwr 1078 1.1 gwr case SYM_SWAP_SERVER: 1079 1.1 gwr PARSE_IA1(swap_server); 1080 1.1 gwr break; 1081 1.1 gwr 1082 1.1 gwr case SYM_ROOT_PATH: 1083 1.1 gwr PARSE_STR(root_path); 1084 1.1 gwr break; 1085 1.1 gwr 1086 1.1 gwr case SYM_EXTEN_FILE: 1087 1.1 gwr PARSE_STR(exten_file); 1088 1.1 gwr break; 1089 1.1 gwr 1090 1.1 gwr case SYM_REPLY_ADDR: 1091 1.1 gwr PARSE_IA1(reply_addr); 1092 1.1 gwr break; 1093 1.1 gwr 1094 1.1 gwr case SYM_NIS_DOMAIN: 1095 1.1 gwr PARSE_STR(nis_domain); 1096 1.1 gwr break; 1097 1.1 gwr 1098 1.1 gwr case SYM_NIS_SERVER: 1099 1.1 gwr PARSE_IAL(nis_server); 1100 1.1 gwr break; 1101 1.1 gwr 1102 1.1 gwr case SYM_NTP_SERVER: 1103 1.1 gwr PARSE_IAL(ntp_server); 1104 1.1 gwr break; 1105 1.1 gwr 1106 1.2 gwr #ifdef YORK_EX_OPTION 1107 1.2 gwr case SYM_EXEC_FILE: 1108 1.2 gwr PARSE_STR(exec_file); 1109 1.2 gwr break; 1110 1.2 gwr #endif 1111 1.2 gwr 1112 1.2 gwr case SYM_MSG_SIZE: 1113 1.2 gwr PARSE_INT(msg_size); 1114 1.2 gwr if (hp->msg_size < BP_MINPKTSZ || 1115 1.16 xtraeme hp->msg_size > MAX_MSG_SIZE) 1116 1.2 gwr return E_BAD_VALUE; 1117 1.2 gwr break; 1118 1.2 gwr 1119 1.1 gwr case SYM_MIN_WAIT: 1120 1.1 gwr PARSE_INT(min_wait); 1121 1.1 gwr if (hp->min_wait == 0) 1122 1.1 gwr return E_BAD_VALUE; 1123 1.1 gwr break; 1124 1.1 gwr 1125 1.1 gwr /* XXX - Add new tags here */ 1126 1.1 gwr 1127 1.1 gwr default: 1128 1.1 gwr return E_UNKNOWN_SYMBOL; 1129 1.1 gwr 1130 1.1 gwr } /* switch symbolcode */ 1131 1.1 gwr 1132 1.1 gwr return SUCCESS; 1133 1.1 gwr } 1134 1.1 gwr #undef PARSE_IA1 1135 1.1 gwr #undef PARSE_IAL 1136 1.1 gwr #undef PARSE_STR 1137 1.1 gwr 1138 1.1 gwr 1140 1.1 gwr 1141 1.1 gwr 1142 1.1 gwr /* 1143 1.1 gwr * Read a string from the buffer indirectly pointed to through "src" and 1144 1.1 gwr * move it into the buffer pointed to by "dest". A pointer to the maximum 1145 1.1 gwr * allowable length of the string (including null-terminator) is passed as 1146 1.1 gwr * "length". The actual length of the string which was read is returned in 1147 1.1 gwr * the unsigned integer pointed to by "length". This value is the same as 1148 1.1 gwr * that which would be returned by applying the strlen() function on the 1149 1.1 gwr * destination string (i.e the terminating null is not counted as a 1150 1.1 gwr * character). Trailing whitespace is removed from the string. For 1151 1.1 gwr * convenience, the function returns the new value of "dest". 1152 1.9 wiz * 1153 1.1 gwr * The string is read until the maximum number of characters, an unquoted 1154 1.1 gwr * colon (:), or a null character is read. The return string in "dest" is 1155 1.1 gwr * null-terminated. 1156 1.1 gwr */ 1157 1.1 gwr 1158 1.1 gwr PRIVATE char * 1159 1.1 gwr get_string(char **src, char *dest, unsigned int *length) 1160 1.1 gwr { 1161 1.1 gwr int n, len, quoteflag; 1162 1.1 gwr 1163 1.1 gwr quoteflag = FALSE; 1164 1.1 gwr n = 0; 1165 1.1 gwr len = *length - 1; 1166 1.1 gwr while ((n < len) && (**src)) { 1167 1.1 gwr if (!quoteflag && (**src == ':')) { 1168 1.1 gwr break; 1169 1.1 gwr } 1170 1.1 gwr if (**src == '"') { 1171 1.1 gwr (*src)++; 1172 1.1 gwr quoteflag = !quoteflag; 1173 1.1 gwr continue; 1174 1.1 gwr } 1175 1.1 gwr if (**src == '\\') { 1176 1.1 gwr (*src)++; 1177 1.1 gwr if (!**src) { 1178 1.1 gwr break; 1179 1.1 gwr } 1180 1.1 gwr } 1181 1.13 dsl *dest++ = *(*src)++; 1182 1.1 gwr n++; 1183 1.1 gwr } 1184 1.1 gwr 1185 1.1 gwr /* 1186 1.1 gwr * Remove that troublesome trailing whitespace. . . 1187 1.1 gwr */ 1188 1.1 gwr while ((n > 0) && isspace((unsigned char)dest[-1])) { 1189 1.1 gwr dest--; 1190 1.1 gwr n--; 1191 1.1 gwr } 1192 1.1 gwr 1193 1.1 gwr *dest = '\0'; 1194 1.1 gwr *length = n; 1195 1.1 gwr return dest; 1196 1.1 gwr } 1197 1.1 gwr 1198 1.1 gwr 1200 1.1 gwr 1201 1.1 gwr /* 1202 1.9 wiz * Read the string indirectly pointed to by "src", update the caller's 1203 1.1 gwr * pointer, and return a pointer to a malloc'ed shared_string structure 1204 1.1 gwr * containing the string. 1205 1.1 gwr * 1206 1.1 gwr * The string is read using the same rules as get_string() above. 1207 1.1 gwr */ 1208 1.1 gwr 1209 1.1 gwr PRIVATE struct shared_string * 1210 1.1 gwr get_shared_string(char **src) 1211 1.12 itojun { 1212 1.19 joerg char retstring[MAXSTRINGLEN]; 1213 1.1 gwr struct shared_string *s; 1214 1.19 joerg unsigned length; 1215 1.1 gwr 1216 1.1 gwr length = sizeof(retstring); 1217 1.1 gwr (void) get_string(src, retstring, &length); 1218 1.1 gwr 1219 1.1 gwr s = (struct shared_string *) smalloc(sizeof(struct shared_string) + 1220 1.1 gwr length + 1); 1221 1.1 gwr s->linkcount = 1; 1222 1.1 gwr memcpy(s->string, retstring, length + 1); 1223 1.1 gwr 1224 1.1 gwr return s; 1225 1.1 gwr } 1226 1.1 gwr 1227 1.1 gwr 1229 1.1 gwr 1230 1.1 gwr /* 1231 1.1 gwr * Load RFC1048 generic information directly into a memory buffer. 1232 1.1 gwr * 1233 1.1 gwr * "src" indirectly points to the ASCII representation of the generic data. 1234 1.1 gwr * "dest" points to a string structure which is updated to point to a new 1235 1.1 gwr * string with the new data appended to the old string. The old string is 1236 1.1 gwr * freed. 1237 1.1 gwr * 1238 1.9 wiz * The given tag value is inserted with the new data. 1239 1.1 gwr * 1240 1.1 gwr * The data may be represented as either a stream of hexadecimal numbers 1241 1.1 gwr * representing bytes (any or all bytes may optionally start with '0x' and 1242 1.1 gwr * be separated with periods ".") or as a quoted string of ASCII 1243 1.1 gwr * characters (the quotes are required). 1244 1.1 gwr */ 1245 1.1 gwr 1246 1.1 gwr PRIVATE int 1247 1.1 gwr process_generic(char **src, struct shared_bindata **dest, u_int tagvalue) 1248 1.1 gwr { 1249 1.1 gwr byte tmpbuf[MAXBUFLEN]; 1250 1.1 gwr byte *str; 1251 1.3 gwr struct shared_bindata *bdata; 1252 1.1 gwr u_int newlength, oldlength; 1253 1.1 gwr 1254 1.1 gwr str = tmpbuf; 1255 1.1 gwr *str++ = (tagvalue & 0xFF); /* Store tag value */ 1256 1.1 gwr str++; /* Skip over length field */ 1257 1.1 gwr if ((*src)[0] == '"') { /* ASCII data */ 1258 1.1 gwr newlength = sizeof(tmpbuf) - 2; /* Set maximum allowed length */ 1259 1.1 gwr (void) get_string(src, (char *) str, &newlength); 1260 1.1 gwr /* Do NOT include the terminating null. */ 1261 1.1 gwr } else { /* Numeric data */ 1262 1.1 gwr newlength = 0; 1263 1.1 gwr while (newlength < sizeof(tmpbuf) - 2) { 1264 1.1 gwr if (interp_byte(src, str++) < 0) 1265 1.1 gwr break; 1266 1.1 gwr newlength++; 1267 1.1 gwr if (**src == '.') { 1268 1.1 gwr (*src)++; 1269 1.1 gwr } 1270 1.1 gwr } 1271 1.1 gwr } 1272 1.1 gwr if ((*src)[0] != ':') 1273 1.1 gwr return -1; 1274 1.1 gwr 1275 1.1 gwr tmpbuf[1] = (newlength & 0xFF); 1276 1.14 christos oldlength = ((*dest)->length); 1277 1.1 gwr bdata = (struct shared_bindata *) smalloc(sizeof(struct shared_bindata) 1278 1.1 gwr + oldlength + newlength + 1); 1279 1.1 gwr if (oldlength > 0) { 1280 1.1 gwr bcopy((*dest)->data, bdata->data, oldlength); 1281 1.1 gwr } 1282 1.1 gwr bcopy(tmpbuf, bdata->data + oldlength, newlength + 2); 1283 1.1 gwr bdata->length = oldlength + newlength + 2; 1284 1.1 gwr bdata->linkcount = 1; 1285 1.1 gwr del_bindata(*dest); 1286 1.1 gwr *dest = bdata; 1287 1.1 gwr return 0; 1288 1.1 gwr } 1289 1.1 gwr 1290 1.1 gwr 1292 1.1 gwr 1293 1.1 gwr /* 1294 1.13 dsl * Verify that the given string makes sense as a hostname (according to 1295 1.1 gwr * Appendix 1, page 29 of RFC882). 1296 1.1 gwr * 1297 1.13 dsl * Return TRUE for good names, FALSE otherwise. 1298 1.1 gwr */ 1299 1.1 gwr 1300 1.1 gwr PRIVATE boolean 1301 1.1 gwr goodname(char *hostname) 1302 1.1 gwr { 1303 1.13 dsl do { 1304 1.1 gwr if (!isalpha((unsigned char)*hostname++)) { /* First character must be a letter */ 1305 1.1 gwr return FALSE; 1306 1.1 gwr } 1307 1.1 gwr while (isalnum((unsigned char)*hostname) || 1308 1.1 gwr (*hostname == '-') || 1309 1.1 gwr (*hostname == '_') ) 1310 1.1 gwr { 1311 1.1 gwr hostname++; /* Alphanumeric or a hyphen */ 1312 1.1 gwr } 1313 1.1 gwr if (!isalnum((unsigned char)hostname[-1])) { /* Last must be alphanumeric */ 1314 1.1 gwr return FALSE; 1315 1.1 gwr } 1316 1.1 gwr if (*hostname == '\0') {/* Done? */ 1317 1.1 gwr return TRUE; 1318 1.1 gwr } 1319 1.1 gwr } while (*hostname++ == '.'); /* Dot, loop for next label */ 1320 1.1 gwr 1321 1.1 gwr return FALSE; /* If it's not a dot, lose */ 1322 1.1 gwr } 1323 1.9 wiz 1324 1.1 gwr 1326 1.1 gwr 1327 1.1 gwr /* 1328 1.1 gwr * Null compare function -- always returns FALSE so an element is always 1329 1.1 gwr * inserted into a hash table (i.e. there is never a collision with an 1330 1.1 gwr * existing element). 1331 1.1 gwr */ 1332 1.1 gwr 1333 1.1 gwr PRIVATE boolean 1334 1.1 gwr nullcmp(hash_datum *d1, hash_datum *d2) 1335 1.9 wiz { 1336 1.1 gwr return FALSE; 1337 1.1 gwr } 1338 1.1 gwr 1339 1.1 gwr 1340 1.1 gwr /* 1341 1.1 gwr * Function for comparing a string with the hostname field of a host 1342 1.1 gwr * structure. 1343 1.1 gwr */ 1344 1.1 gwr 1345 1.1 gwr boolean 1346 1.1 gwr nmcmp(hash_datum *d1, hash_datum *d2) 1347 1.1 gwr { 1348 1.1 gwr char *name = (char *) d1; /* XXX - OK? */ 1349 1.1 gwr struct host *hp = (struct host *) d2; 1350 1.1 gwr 1351 1.1 gwr return !strcmp(name, hp->hostname->string); 1352 1.1 gwr } 1353 1.1 gwr 1354 1.1 gwr 1355 1.1 gwr /* 1356 1.1 gwr * Compare function to determine whether two hardware addresses are 1357 1.9 wiz * equivalent. Returns TRUE if "host1" and "host2" are equivalent, FALSE 1358 1.1 gwr * otherwise. 1359 1.1 gwr * 1360 1.1 gwr * If the hardware addresses of "host1" and "host2" are identical, but 1361 1.1 gwr * they are on different IP subnets, this function returns FALSE. 1362 1.1 gwr * 1363 1.1 gwr * This function is used when inserting elements into the hardware address 1364 1.1 gwr * hash table. 1365 1.1 gwr */ 1366 1.1 gwr 1367 1.1 gwr PRIVATE boolean 1368 1.1 gwr hwinscmp(hash_datum *d1, hash_datum *d2) 1369 1.1 gwr { 1370 1.1 gwr struct host *host1 = (struct host *) d1; 1371 1.1 gwr struct host *host2 = (struct host *) d2; 1372 1.1 gwr 1373 1.1 gwr if (host1->htype != host2->htype) { 1374 1.1 gwr return FALSE; 1375 1.1 gwr } 1376 1.1 gwr if (bcmp(host1->haddr, host2->haddr, haddrlength(host1->htype))) { 1377 1.1 gwr return FALSE; 1378 1.1 gwr } 1379 1.1 gwr /* XXX - Is the subnet_mask field set yet? */ 1380 1.1 gwr if ((host1->subnet_mask.s_addr) == (host2->subnet_mask.s_addr)) { 1381 1.1 gwr if (((host1->iaddr.s_addr) & (host1->subnet_mask.s_addr)) != 1382 1.1 gwr ((host2->iaddr.s_addr) & (host2->subnet_mask.s_addr))) 1383 1.1 gwr { 1384 1.1 gwr return FALSE; 1385 1.1 gwr } 1386 1.1 gwr } 1387 1.1 gwr return TRUE; 1388 1.1 gwr } 1389 1.1 gwr 1390 1.1 gwr 1392 1.1 gwr /* 1393 1.1 gwr * Macros for use in the function below: 1394 1.1 gwr */ 1395 1.1 gwr 1396 1.1 gwr #define DUP_COPY(MEMBER) do \ 1397 1.1 gwr { \ 1398 1.1 gwr if (!hp->flags.MEMBER) { \ 1399 1.1 gwr if ((hp->flags.MEMBER = hp2->flags.MEMBER) != 0) { \ 1400 1.1 gwr hp->MEMBER = hp2->MEMBER; \ 1401 1.1 gwr } \ 1402 1.1 gwr } \ 1403 1.1 gwr } while (0) 1404 1.1 gwr 1405 1.1 gwr #define DUP_LINK(MEMBER) do \ 1406 1.1 gwr { \ 1407 1.1 gwr if (!hp->flags.MEMBER) { \ 1408 1.1 gwr if ((hp->flags.MEMBER = hp2->flags.MEMBER) != 0) { \ 1409 1.1 gwr assert(hp2->MEMBER); \ 1410 1.1 gwr hp->MEMBER = hp2->MEMBER; \ 1411 1.1 gwr (hp->MEMBER->linkcount)++; \ 1412 1.9 wiz } \ 1413 1.1 gwr } \ 1414 1.1 gwr } while (0) 1415 1.1 gwr 1416 1.1 gwr /* 1417 1.1 gwr * Process the "similar entry" symbol. 1418 1.1 gwr * 1419 1.1 gwr * The host specified as the value of the "tc" symbol is used as a template 1420 1.1 gwr * for the current host entry. Symbol values not explicitly set in the 1421 1.1 gwr * current host entry are inferred from the template entry. 1422 1.1 gwr */ 1423 1.1 gwr PRIVATE void 1424 1.1 gwr fill_defaults(struct host *hp, char **src) 1425 1.1 gwr { 1426 1.1 gwr unsigned int tlen, hashcode; 1427 1.1 gwr struct host *hp2; 1428 1.1 gwr char tstring[MAXSTRINGLEN]; 1429 1.1 gwr 1430 1.1 gwr tlen = sizeof(tstring); 1431 1.1 gwr (void) get_string(src, tstring, &tlen); 1432 1.1 gwr hashcode = hash_HashFunction((u_char *) tstring, tlen); 1433 1.1 gwr hp2 = (struct host *) hash_Lookup(nmhashtable, hashcode, nmcmp, tstring); 1434 1.1 gwr 1435 1.1 gwr if (hp2 == NULL) { 1436 1.1 gwr report(LOG_ERR, "can't find tc=\"%s\"", tstring); 1437 1.1 gwr return; 1438 1.1 gwr } 1439 1.1 gwr DUP_LINK(bootfile); 1440 1.1 gwr DUP_LINK(cookie_server); 1441 1.1 gwr DUP_LINK(domain_server); 1442 1.1 gwr DUP_LINK(gateway); 1443 1.1 gwr /* haddr not copied */ 1444 1.1 gwr DUP_LINK(homedir); 1445 1.1 gwr DUP_COPY(htype); 1446 1.1 gwr 1447 1.1 gwr DUP_LINK(impress_server); 1448 1.1 gwr /* iaddr not copied */ 1449 1.1 gwr DUP_LINK(log_server); 1450 1.1 gwr DUP_LINK(lpr_server); 1451 1.1 gwr DUP_LINK(name_server); 1452 1.1 gwr DUP_LINK(rlp_server); 1453 1.1 gwr 1454 1.1 gwr DUP_COPY(subnet_mask); 1455 1.1 gwr DUP_COPY(time_offset); 1456 1.1 gwr DUP_LINK(time_server); 1457 1.1 gwr 1458 1.1 gwr if (!hp->flags.vm_cookie) { 1459 1.1 gwr if ((hp->flags.vm_cookie = hp2->flags.vm_cookie)) { 1460 1.1 gwr bcopy(hp2->vm_cookie, hp->vm_cookie, 4); 1461 1.1 gwr } 1462 1.1 gwr } 1463 1.1 gwr if (!hp->flags.name_switch) { 1464 1.1 gwr if ((hp->flags.name_switch = hp2->flags.name_switch)) { 1465 1.1 gwr hp->flags.send_name = hp2->flags.send_name; 1466 1.1 gwr } 1467 1.1 gwr } 1468 1.1 gwr if (!hp->flags.bootsize) { 1469 1.1 gwr if ((hp->flags.bootsize = hp2->flags.bootsize)) { 1470 1.1 gwr hp->flags.bootsize_auto = hp2->flags.bootsize_auto; 1471 1.1 gwr hp->bootsize = hp2->bootsize; 1472 1.1 gwr } 1473 1.1 gwr } 1474 1.1 gwr DUP_COPY(bootserver); 1475 1.1 gwr 1476 1.1 gwr DUP_LINK(tftpdir); 1477 1.1 gwr DUP_LINK(dump_file); 1478 1.1 gwr DUP_LINK(domain_name); 1479 1.1 gwr 1480 1.1 gwr DUP_COPY(swap_server); 1481 1.2 gwr DUP_LINK(root_path); 1482 1.2 gwr DUP_LINK(exten_file); 1483 1.2 gwr 1484 1.1 gwr DUP_COPY(reply_addr); 1485 1.1 gwr 1486 1.1 gwr DUP_LINK(nis_domain); 1487 1.1 gwr DUP_LINK(nis_server); 1488 1.1 gwr DUP_LINK(ntp_server); 1489 1.1 gwr 1490 1.1 gwr #ifdef YORK_EX_OPTION 1491 1.1 gwr DUP_LINK(exec_file); 1492 1.1 gwr #endif 1493 1.1 gwr 1494 1.1 gwr DUP_COPY(msg_size); 1495 1.1 gwr DUP_COPY(min_wait); 1496 1.1 gwr 1497 1.1 gwr /* XXX - Add new tags here */ 1498 1.1 gwr 1499 1.1 gwr DUP_LINK(generic); 1500 1.1 gwr 1501 1.1 gwr } 1502 1.9 wiz #undef DUP_COPY 1503 1.1 gwr #undef DUP_LINK 1504 1.10 wiz 1505 1.1 gwr 1507 1.1 gwr 1508 1.1 gwr /* 1509 1.1 gwr * This function adjusts the caller's pointer to point just past the 1510 1.1 gwr * first-encountered colon. If it runs into a null character, it leaves 1511 1.1 gwr * the pointer pointing to it. 1512 1.1 gwr */ 1513 1.1 gwr 1514 1.1 gwr PRIVATE void 1515 1.1 gwr adjust(char **s) 1516 1.1 gwr { 1517 1.1 gwr char *t; 1518 1.1 gwr 1519 1.1 gwr t = *s; 1520 1.1 gwr while (*t && (*t != ':')) { 1521 1.1 gwr t++; 1522 1.1 gwr } 1523 1.1 gwr if (*t) { 1524 1.1 gwr t++; 1525 1.1 gwr } 1526 1.9 wiz *s = t; 1527 1.1 gwr } 1528 1.10 wiz 1529 1.1 gwr 1530 1.1 gwr 1531 1.13 dsl 1532 1.1 gwr /* 1533 1.1 gwr * This function adjusts the caller's pointer to point to the first 1534 1.1 gwr * non-whitespace character. If it runs into a null character, it leaves 1535 1.1 gwr * the pointer pointing to it. 1536 1.1 gwr */ 1537 1.1 gwr 1538 1.1 gwr PRIVATE void 1539 1.1 gwr eat_whitespace(char **s) 1540 1.1 gwr { 1541 1.1 gwr char *t; 1542 1.1 gwr 1543 1.1 gwr t = *s; 1544 1.9 wiz while (*t && isspace((unsigned char)*t)) { 1545 1.1 gwr t++; 1546 1.1 gwr } 1547 1.13 dsl *s = t; 1548 1.13 dsl } 1549 1.1 gwr 1550 1.1 gwr 1551 1.1 gwr 1552 1.1 gwr /* 1553 1.1 gwr * This function converts the given string to all lowercase. 1554 1.1 gwr */ 1555 1.1 gwr 1556 1.1 gwr PRIVATE void 1557 1.1 gwr makelower(char *s) 1558 1.1 gwr { 1559 1.1 gwr while (*s) { 1560 1.1 gwr if (isupper((unsigned char)*s)) { 1561 1.1 gwr *s = tolower((unsigned char)*s); 1562 1.1 gwr } 1563 1.1 gwr s++; 1564 1.1 gwr } 1565 1.1 gwr } 1566 1.1 gwr 1567 1.1 gwr 1569 1.1 gwr 1570 1.1 gwr /* 1571 1.1 gwr * 1572 1.1 gwr * N O T E : 1573 1.1 gwr * 1574 1.1 gwr * In many of the functions which follow, a parameter such as "src" or 1575 1.1 gwr * "symbol" is passed as a pointer to a pointer to something. This is 1576 1.1 gwr * done for the purpose of letting the called function update the 1577 1.1 gwr * caller's copy of the parameter (i.e. to effect call-by-reference 1578 1.1 gwr * parameter passing). The value of the actual parameter is only used 1579 1.1 gwr * to locate the real parameter of interest and then update this indirect 1580 1.1 gwr * parameter. 1581 1.1 gwr * 1582 1.1 gwr * I'm sure somebody out there won't like this. . . . 1583 1.1 gwr * (Yea, because it usually makes code slower... -gwr) 1584 1.9 wiz * 1585 1.1 gwr */ 1586 1.20 joerg 1587 1.1 gwr 1589 1.1 gwr 1590 1.20 joerg /* 1591 1.13 dsl * "src" points to a character pointer which points to an ASCII string of 1592 1.1 gwr * whitespace-separated IP addresses. A pointer to an in_addr_list 1593 1.1 gwr * structure containing the list of addresses is returned. NULL is 1594 1.1 gwr * returned if no addresses were found at all. The pointer pointed to by 1595 1.1 gwr * "src" is updated to point to the first non-address (illegal) character. 1596 1.1 gwr */ 1597 1.20 joerg 1598 1.1 gwr PRIVATE struct in_addr_list * 1599 1.1 gwr get_addresses(char **src) 1600 1.20 joerg { 1601 1.1 gwr __aligned(4) struct in_addr tmpaddrlist[MAXINADDRS]; 1602 1.1 gwr struct in_addr_list *result; 1603 1.1 gwr unsigned addrcount, totalsize, address; 1604 1.1 gwr 1605 1.1 gwr for (address = 0, addrcount = 0; addrcount < MAXINADDRS; addrcount++) { 1606 1.1 gwr while (isspace((unsigned char)**src) || (**src == ',')) { 1607 1.1 gwr (*src)++; 1608 1.1 gwr } 1609 1.1 gwr if (!**src) { /* Quit if nothing more */ 1610 1.20 joerg break; 1611 1.20 joerg } 1612 1.1 gwr if (prs_inetaddr(src, &tmpaddrlist[address].s_addr) < 0) { 1613 1.1 gwr break; 1614 1.1 gwr } 1615 1.1 gwr address++; /* Point to next address slot */ 1616 1.1 gwr } 1617 1.1 gwr if (addrcount < 1) { 1618 1.1 gwr result = NULL; 1619 1.1 gwr } else { 1620 1.1 gwr totalsize = sizeof(struct in_addr_list) 1621 1.1 gwr + (addrcount - 1) * sizeof(struct in_addr); 1622 1.1 gwr result = (struct in_addr_list *) smalloc(totalsize); 1623 1.1 gwr result->linkcount = 1; 1624 1.1 gwr result->addrcount = addrcount; 1625 1.1 gwr for (address = 0; address < addrcount; ++address) 1626 1.1 gwr result->addr[address] = tmpaddrlist[address]; 1627 1.1 gwr } 1628 1.1 gwr return result; 1629 1.1 gwr } 1630 1.1 gwr 1631 1.1 gwr 1633 1.9 wiz 1634 1.1 gwr /* 1635 1.1 gwr * prs_inetaddr(src, result) 1636 1.10 wiz * 1637 1.1 gwr * "src" is a value-result parameter; the pointer it points to is updated 1638 1.1 gwr * to point to the next data position. "result" points to an unsigned long 1639 1.1 gwr * in which an address is returned. 1640 1.1 gwr * 1641 1.1 gwr * This function parses the IP address string in ASCII "dot notation" pointed 1642 1.1 gwr * to by (*src) and places the result (in network byte order) in the unsigned 1643 1.13 dsl * long pointed to by "result". For malformed addresses, -1 is returned, 1644 1.1 gwr * (*src) points to the first illegal character, and the unsigned long pointed 1645 1.1 gwr * to by "result" is unchanged. Successful calls return 0. 1646 1.1 gwr */ 1647 1.13 dsl 1648 1.1 gwr PRIVATE int 1649 1.1 gwr prs_inetaddr(char **src, u_int32 *result) 1650 1.1 gwr { 1651 1.1 gwr char tmpstr[MAXSTRINGLEN]; 1652 1.1 gwr u_int32 value; 1653 1.1 gwr u_int32 parts[4], *pp; 1654 1.1 gwr int n; 1655 1.1 gwr char *s, *t; 1656 1.1 gwr 1657 1.1 gwr #if 1 /* XXX - experimental */ 1658 1.1 gwr /* Leading alpha char causes IP addr lookup. */ 1659 1.1 gwr if (isalpha((unsigned char)**src)) { 1660 1.1 gwr /* Lookup IP address. */ 1661 1.1 gwr s = *src; 1662 1.1 gwr t = tmpstr; 1663 1.1 gwr while ((isalnum((unsigned char)*s) || (*s == '.') || 1664 1.1 gwr (*s == '-') || (*s == '_') ) && 1665 1.1 gwr (t < &tmpstr[MAXSTRINGLEN - 1]) ) 1666 1.1 gwr *t++ = *s++; 1667 1.1 gwr *t = '\0'; 1668 1.1 gwr *src = s; 1669 1.1 gwr 1670 1.13 dsl n = lookup_ipa(tmpstr, result); 1671 1.1 gwr if (n < 0) 1672 1.1 gwr report(LOG_ERR, "can not get IP addr for %s", tmpstr); 1673 1.1 gwr return n; 1674 1.1 gwr } 1675 1.1 gwr #endif 1676 1.1 gwr 1677 1.1 gwr /* 1678 1.1 gwr * Parse an address in Internet format: 1679 1.1 gwr * a.b.c.d 1680 1.1 gwr * a.b.c (with c treated as 16-bits) 1681 1.1 gwr * a.b (with b treated as 24 bits) 1682 1.13 dsl */ 1683 1.1 gwr pp = parts; 1684 1.1 gwr loop: 1685 1.1 gwr /* If it's not a digit, return error. */ 1686 1.1 gwr if (!isdigit((unsigned char)**src)) 1687 1.1 gwr return -1; 1688 1.1 gwr *pp++ = get_u_long(src); 1689 1.1 gwr if (**src == '.') { 1690 1.1 gwr if (pp < (parts + 4)) { 1691 1.1 gwr (*src)++; 1692 1.1 gwr goto loop; 1693 1.1 gwr } 1694 1.1 gwr return (-1); 1695 1.1 gwr } 1696 1.1 gwr #if 0 1697 1.1 gwr /* This is handled by the caller. */ 1698 1.1 gwr if (**src && !((unsigned char)isspace(**src) || (**src == ':'))) { 1699 1.1 gwr return (-1); 1700 1.1 gwr } 1701 1.1 gwr #endif 1702 1.1 gwr 1703 1.1 gwr /* 1704 1.1 gwr * Construct the address according to 1705 1.1 gwr * the number of parts specified. 1706 1.1 gwr */ 1707 1.1 gwr n = pp - parts; 1708 1.1 gwr switch (n) { 1709 1.1 gwr case 1: /* a -- 32 bits */ 1710 1.1 gwr value = parts[0]; 1711 1.1 gwr break; 1712 1.1 gwr case 2: /* a.b -- 8.24 bits */ 1713 1.1 gwr value = (parts[0] << 24) | (parts[1] & 0xFFFFFF); 1714 1.1 gwr break; 1715 1.1 gwr case 3: /* a.b.c -- 8.8.16 bits */ 1716 1.1 gwr value = (parts[0] << 24) | ((parts[1] & 0xFF) << 16) | 1717 1.1 gwr (parts[2] & 0xFFFF); 1718 1.1 gwr break; 1719 1.1 gwr case 4: /* a.b.c.d -- 8.8.8.8 bits */ 1720 1.1 gwr value = (parts[0] << 24) | ((parts[1] & 0xFF) << 16) | 1721 1.1 gwr ((parts[2] & 0xFF) << 8) | (parts[3] & 0xFF); 1722 1.1 gwr break; 1723 1.1 gwr default: 1724 1.1 gwr return (-1); 1725 1.1 gwr } 1726 1.1 gwr *result = htonl(value); 1727 1.1 gwr return (0); 1728 1.1 gwr } 1729 1.1 gwr 1730 1.1 gwr 1732 1.1 gwr 1733 1.9 wiz /* 1734 1.1 gwr * "src" points to a pointer which in turn points to a hexadecimal ASCII 1735 1.1 gwr * string. This string is interpreted as a hardware address and returned 1736 1.1 gwr * as a pointer to the actual hardware address, represented as an array of 1737 1.1 gwr * bytes. 1738 1.1 gwr * 1739 1.1 gwr * The ASCII string must have the proper number of digits for the specified 1740 1.1 gwr * hardware type (e.g. twelve digits for a 48-bit Ethernet address). 1741 1.1 gwr * Two-digit sequences (bytes) may be separated with periods (.) and/or 1742 1.1 gwr * prefixed with '0x' for readability, but this is not required. 1743 1.1 gwr * 1744 1.1 gwr * For bad addresses, the pointer which "src" points to is updated to point 1745 1.1 gwr * to the start of the first two-digit sequence which was bad, and the 1746 1.1 gwr * function returns a NULL pointer. 1747 1.1 gwr */ 1748 1.1 gwr 1749 1.1 gwr PRIVATE byte * 1750 1.1 gwr prs_haddr(char **src, u_int htype) 1751 1.1 gwr { 1752 1.1 gwr static byte haddr[MAXHADDRLEN]; 1753 1.1 gwr byte *hap; 1754 1.1 gwr char tmpstr[MAXSTRINGLEN]; 1755 1.1 gwr u_int tmplen; 1756 1.1 gwr unsigned hal; 1757 1.1 gwr char *p; 1758 1.1 gwr 1759 1.1 gwr hal = haddrlength(htype); /* Get length of this address type */ 1760 1.1 gwr if (hal <= 0) { 1761 1.1 gwr report(LOG_ERR, "Invalid addr type for HW addr parse"); 1762 1.1 gwr return NULL; 1763 1.1 gwr } 1764 1.3 gwr tmplen = sizeof(tmpstr); 1765 1.1 gwr get_string(src, tmpstr, &tmplen); 1766 1.1 gwr p = tmpstr; 1767 1.1 gwr 1768 1.1 gwr #if 1 /* XXX - experimental */ 1769 1.1 gwr /* If it's a valid host name, try to lookup the HW address. */ 1770 1.1 gwr if (goodname(p)) { 1771 1.1 gwr /* Lookup Hardware Address for hostname. */ 1772 1.1 gwr if ((hap = lookup_hwa(p, htype)) != NULL) 1773 1.1 gwr return hap; /* success */ 1774 1.1 gwr report(LOG_ERR, "Add 0x prefix if hex value starts with A-F"); 1775 1.1 gwr /* OK, assume it must be numeric. */ 1776 1.1 gwr } 1777 1.1 gwr #endif 1778 1.1 gwr 1779 1.1 gwr hap = haddr; 1780 1.1 gwr while (hap < haddr + hal) { 1781 1.1 gwr if ((*p == '.') || (*p == ':')) 1782 1.1 gwr p++; 1783 1.1 gwr if (interp_byte(&p, hap++) < 0) { 1784 1.1 gwr return NULL; 1785 1.1 gwr } 1786 1.1 gwr } 1787 1.1 gwr return haddr; 1788 1.9 wiz } 1789 1.1 gwr 1790 1.1 gwr 1792 1.1 gwr 1793 1.1 gwr /* 1794 1.1 gwr * "src" is a pointer to a character pointer which in turn points to a 1795 1.1 gwr * hexadecimal ASCII representation of a byte. This byte is read, the 1796 1.1 gwr * character pointer is updated, and the result is deposited into the 1797 1.13 dsl * byte pointed to by "retbyte". 1798 1.1 gwr * 1799 1.1 gwr * The usual '0x' notation is allowed but not required. The number must be 1800 1.1 gwr * a two digit hexadecimal number. If the number is invalid, "src" and 1801 1.1 gwr * "retbyte" are left untouched and -1 is returned as the function value. 1802 1.1 gwr * Successful calls return 0. 1803 1.1 gwr */ 1804 1.1 gwr 1805 1.1 gwr PRIVATE int 1806 1.1 gwr interp_byte(char **src, byte *retbyte) 1807 1.1 gwr { 1808 1.1 gwr int v; 1809 1.1 gwr 1810 1.1 gwr if ((*src)[0] == '0' && 1811 1.1 gwr ((*src)[1] == 'x' || 1812 1.1 gwr (*src)[1] == 'X')) { 1813 1.1 gwr (*src) += 2; /* allow 0x for hex, but don't require it */ 1814 1.1 gwr } 1815 1.1 gwr if (!isxdigit((unsigned char)(*src)[0]) || !isxdigit((unsigned char)(*src)[1])) { 1816 1.1 gwr return -1; 1817 1.1 gwr } 1818 1.9 wiz if (sscanf(*src, "%2x", &v) != 1) { 1819 1.1 gwr return -1; 1820 1.10 wiz } 1821 1.1 gwr (*src) += 2; 1822 1.1 gwr *retbyte = (byte) (v & 0xFF); 1823 1.1 gwr return 0; 1824 1.1 gwr } 1825 1.1 gwr 1826 1.1 gwr 1828 1.1 gwr 1829 1.1 gwr /* 1830 1.1 gwr * The parameter "src" points to a character pointer which points to an 1831 1.1 gwr * ASCII string representation of an unsigned number. The number is 1832 1.1 gwr * returned as an unsigned long and the character pointer is updated to 1833 1.1 gwr * point to the first illegal character. 1834 1.1 gwr */ 1835 1.1 gwr 1836 1.1 gwr PRIVATE u_int32 1837 1.1 gwr get_u_long(char **src) 1838 1.13 dsl { 1839 1.1 gwr u_int32 value, base; 1840 1.1 gwr char c; 1841 1.1 gwr 1842 1.1 gwr /* 1843 1.13 dsl * Collect number up to first illegal character. Values are specified 1844 1.1 gwr * as for C: 0x=hex, 0=octal, other=decimal. 1845 1.1 gwr */ 1846 1.1 gwr value = 0; 1847 1.1 gwr base = 10; 1848 1.1 gwr if (**src == '0') { 1849 1.1 gwr base = 8; 1850 1.1 gwr (*src)++; 1851 1.1 gwr } 1852 1.1 gwr if (**src == 'x' || **src == 'X') { 1853 1.1 gwr base = 16; 1854 1.1 gwr (*src)++; 1855 1.1 gwr } 1856 1.1 gwr while ((c = **src)) { 1857 1.1 gwr if (isdigit((unsigned char)c)) { 1858 1.1 gwr value = (value * base) + (c - '0'); 1859 1.1 gwr (*src)++; 1860 1.1 gwr continue; 1861 1.1 gwr } 1862 1.1 gwr if (base == 16 && isxdigit((unsigned char)c)) { 1863 1.1 gwr value = (value << 4) + ((c & ~32) + 10 - 'A'); 1864 1.1 gwr (*src)++; 1865 1.1 gwr continue; 1866 1.9 wiz } 1867 1.1 gwr break; 1868 1.1 gwr } 1869 1.1 gwr return value; 1870 1.1 gwr } 1871 1.1 gwr 1872 1.1 gwr 1874 1.1 gwr 1875 1.1 gwr /* 1876 1.1 gwr * Routines for deletion of data associated with the main data structure. 1877 1.1 gwr */ 1878 1.1 gwr 1879 1.1 gwr 1880 1.1 gwr /* 1881 1.1 gwr * Frees the entire host data structure given. Does nothing if the passed 1882 1.1 gwr * pointer is NULL. 1883 1.1 gwr */ 1884 1.1 gwr 1885 1.1 gwr PRIVATE void 1886 1.1 gwr free_host(hash_datum *hmp) 1887 1.1 gwr { 1888 1.1 gwr struct host *hostptr = (struct host *) hmp; 1889 1.1 gwr if (hostptr == NULL) 1890 1.1 gwr return; 1891 1.1 gwr assert(hostptr->linkcount > 0); 1892 1.1 gwr if (--(hostptr->linkcount)) 1893 1.1 gwr return; /* Still has references */ 1894 1.1 gwr del_iplist(hostptr->cookie_server); 1895 1.1 gwr del_iplist(hostptr->domain_server); 1896 1.1 gwr del_iplist(hostptr->gateway); 1897 1.1 gwr del_iplist(hostptr->impress_server); 1898 1.1 gwr del_iplist(hostptr->log_server); 1899 1.1 gwr del_iplist(hostptr->lpr_server); 1900 1.1 gwr del_iplist(hostptr->name_server); 1901 1.1 gwr del_iplist(hostptr->rlp_server); 1902 1.1 gwr del_iplist(hostptr->time_server); 1903 1.1 gwr del_iplist(hostptr->nis_server); 1904 1.1 gwr del_iplist(hostptr->ntp_server); 1905 1.1 gwr 1906 1.1 gwr /* 1907 1.1 gwr * XXX - Add new tags here 1908 1.1 gwr * (if the value is an IP list) 1909 1.1 gwr */ 1910 1.1 gwr 1911 1.1 gwr del_string(hostptr->hostname); 1912 1.1 gwr del_string(hostptr->homedir); 1913 1.1 gwr del_string(hostptr->bootfile); 1914 1.1 gwr del_string(hostptr->tftpdir); 1915 1.1 gwr del_string(hostptr->root_path); 1916 1.1 gwr del_string(hostptr->domain_name); 1917 1.1 gwr del_string(hostptr->dump_file); 1918 1.1 gwr del_string(hostptr->exten_file); 1919 1.1 gwr del_string(hostptr->nis_domain); 1920 1.1 gwr 1921 1.1 gwr #ifdef YORK_EX_OPTION 1922 1.9 wiz del_string(hostptr->exec_file); 1923 1.1 gwr #endif 1924 1.1 gwr 1925 1.1 gwr /* 1926 1.1 gwr * XXX - Add new tags here 1927 1.1 gwr * (if it is a shared string) 1928 1.1 gwr */ 1929 1.1 gwr 1930 1.1 gwr del_bindata(hostptr->generic); 1931 1.1 gwr free((char *) hostptr); 1932 1.1 gwr } 1933 1.1 gwr 1934 1.1 gwr 1936 1.1 gwr 1937 1.1 gwr /* 1938 1.1 gwr * Decrements the linkcount on the given IP address data structure. If the 1939 1.1 gwr * linkcount goes to zero, the memory associated with the data is freed. 1940 1.9 wiz */ 1941 1.1 gwr 1942 1.1 gwr PRIVATE void 1943 1.1 gwr del_iplist(struct in_addr_list *iplist) 1944 1.1 gwr { 1945 1.1 gwr if (iplist) { 1946 1.1 gwr if (!(--(iplist->linkcount))) { 1947 1.1 gwr free((char *) iplist); 1948 1.1 gwr } 1949 1.1 gwr } 1950 1.1 gwr } 1951 1.1 gwr 1952 1.1 gwr 1953 1.1 gwr 1954 1.1 gwr /* 1955 1.1 gwr * Decrements the linkcount on a string data structure. If the count 1956 1.1 gwr * goes to zero, the memory associated with the string is freed. Does 1957 1.1 gwr * nothing if the passed pointer is NULL. 1958 1.9 wiz */ 1959 1.1 gwr 1960 1.1 gwr PRIVATE void 1961 1.1 gwr del_string(struct shared_string *stringptr) 1962 1.1 gwr { 1963 1.1 gwr if (stringptr) { 1964 1.1 gwr if (!(--(stringptr->linkcount))) { 1965 1.1 gwr free((char *) stringptr); 1966 1.1 gwr } 1967 1.1 gwr } 1968 1.1 gwr } 1969 1.1 gwr 1970 1.1 gwr 1971 1.1 gwr 1972 1.1 gwr /* 1973 1.1 gwr * Decrements the linkcount on a shared_bindata data structure. If the 1974 1.1 gwr * count goes to zero, the memory associated with the data is freed. Does 1975 1.1 gwr * nothing if the passed pointer is NULL. 1976 1.1 gwr */ 1977 1.1 gwr 1978 1.1 gwr PRIVATE void 1979 1.9 wiz del_bindata(struct shared_bindata *dataptr) 1980 1.1 gwr { 1981 1.1 gwr if (dataptr) { 1982 1.1 gwr if (!(--(dataptr->linkcount))) { 1983 1.1 gwr free((char *) dataptr); 1984 1.1 gwr } 1985 1.1 gwr } 1986 1.1 gwr } 1987 1.1 gwr 1988 1.1 gwr 1990 1.1 gwr 1991 1.1 gwr 1992 1.1 gwr /* smalloc() -- safe malloc() 1993 1.1 gwr * 1994 1.1 gwr * Always returns a valid pointer (if it returns at all). The allocated 1995 1.1 gwr * memory is initialized to all zeros. If malloc() returns an error, a 1996 1.1 gwr * message is printed using the report() function and the program aborts 1997 1.1 gwr * with a status of 1. 1998 1.1 gwr */ 1999 1.1 gwr 2000 1.1 gwr PRIVATE char * 2001 1.1 gwr smalloc(unsigned int nbytes) 2002 1.1 gwr { 2003 1.9 wiz char *retvalue; 2004 1.1 gwr 2005 1.1 gwr retvalue = malloc(nbytes); 2006 1.1 gwr if (!retvalue) { 2007 1.1 gwr report(LOG_ERR, "malloc() failure -- exiting"); 2008 1.1 gwr exit(1); 2009 1.1 gwr } 2010 1.1 gwr bzero(retvalue, nbytes); 2011 1.1 gwr return retvalue; 2012 1.1 gwr } 2013 1.1 gwr 2014 1.1 gwr 2016 1.1 gwr /* 2017 1.1 gwr * Compare function to determine whether two hardware addresses are 2018 1.1 gwr * equivalent. Returns TRUE if "host1" and "host2" are equivalent, FALSE 2019 1.1 gwr * otherwise. 2020 1.1 gwr * 2021 1.1 gwr * This function is used when retrieving elements from the hardware address 2022 1.1 gwr * hash table. 2023 1.9 wiz */ 2024 1.1 gwr 2025 1.1 gwr boolean 2026 1.1 gwr hwlookcmp(hash_datum *d1, hash_datum *d2) 2027 1.1 gwr { 2028 1.1 gwr struct host *host1 = (struct host *) d1; 2029 1.1 gwr struct host *host2 = (struct host *) d2; 2030 1.1 gwr 2031 1.1 gwr if (host1->htype != host2->htype) { 2032 1.1 gwr return FALSE; 2033 1.1 gwr } 2034 1.1 gwr if (bcmp(host1->haddr, host2->haddr, haddrlength(host1->htype))) { 2035 1.1 gwr return FALSE; 2036 1.1 gwr } 2037 1.1 gwr return TRUE; 2038 1.1 gwr } 2039 1.1 gwr 2040 1.1 gwr 2041 1.1 gwr /* 2042 * Compare function for doing IP address hash table lookup. 2043 */ 2044 2045 boolean 2046 iplookcmp(hash_datum *d1, hash_datum *d2) 2047 { 2048 struct host *host1 = (struct host *) d1; 2049 struct host *host2 = (struct host *) d2; 2050 2051 return (host1->iaddr.s_addr == host2->iaddr.s_addr); 2052 } 2053 2054 /* 2055 * Local Variables: 2056 * tab-width: 4 2057 * c-indent-level: 4 2058 * c-argdecl-indent: 4 2059 * c-continued-statement-offset: 4 2060 * c-continued-brace-offset: -4 2061 * c-label-offset: -4 2062 * c-brace-offset: 0 2063 * End: 2064 */ 2065