diff options
Diffstat (limited to 'usr.sbin/bootpd/readfile.c')
-rw-r--r-- | usr.sbin/bootpd/readfile.c | 2097 |
1 files changed, 0 insertions, 2097 deletions
diff --git a/usr.sbin/bootpd/readfile.c b/usr.sbin/bootpd/readfile.c deleted file mode 100644 index 1f70b45..0000000 --- a/usr.sbin/bootpd/readfile.c +++ /dev/null @@ -1,2097 +0,0 @@ -/************************************************************************ - Copyright 1988, 1991 by Carnegie Mellon University - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, provided -that the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation, and that the name of Carnegie Mellon University not be used -in advertising or publicity pertaining to distribution of the software -without specific, written prior permission. - -CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS -SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL -DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR -PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS -ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. -************************************************************************/ - -#ifndef lint -static char rcsid[] = "$Id: readfile.c,v 1.2 1994/08/22 22:15:04 gwr Exp $"; -#endif - - -/* - * bootpd configuration file reading code. - * - * The routines in this file deal with reading, interpreting, and storing - * the information found in the bootpd configuration file (usually - * /etc/bootptab). - */ - - -#include <sys/errno.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/file.h> -#include <sys/time.h> -#include <netinet/in.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <ctype.h> -#include <assert.h> -#include <syslog.h> - -#ifndef USE_BFUNCS -#include <memory.h> -/* Yes, memcpy is OK here (no overlapped copies). */ -#define bcopy(a,b,c) memcpy(b,a,c) -#define bzero(p,l) memset(p,0,l) -#define bcmp(a,b,c) memcmp(a,b,c) -#endif - -#include "bootp.h" -#include "hash.h" -#include "hwaddr.h" -#include "lookup.h" -#include "readfile.h" -#include "report.h" -#include "tzone.h" -#include "bootpd.h" - -#define HASHTABLESIZE 257 /* Hash table size (prime) */ - -/* Non-standard hardware address type (see bootp.h) */ -#define HTYPE_DIRECT 0 - -/* Error codes returned by eval_symbol: */ -#define SUCCESS 0 -#define E_END_OF_ENTRY (-1) -#define E_SYNTAX_ERROR (-2) -#define E_UNKNOWN_SYMBOL (-3) -#define E_BAD_IPADDR (-4) -#define E_BAD_HWADDR (-5) -#define E_BAD_LONGWORD (-6) -#define E_BAD_HWATYPE (-7) -#define E_BAD_PATHNAME (-8) -#define E_BAD_VALUE (-9) - -/* Tag idendities. */ -#define SYM_NULL 0 -#define SYM_BOOTFILE 1 -#define SYM_COOKIE_SERVER 2 -#define SYM_DOMAIN_SERVER 3 -#define SYM_GATEWAY 4 -#define SYM_HWADDR 5 -#define SYM_HOMEDIR 6 -#define SYM_HTYPE 7 -#define SYM_IMPRESS_SERVER 8 -#define SYM_IPADDR 9 -#define SYM_LOG_SERVER 10 -#define SYM_LPR_SERVER 11 -#define SYM_NAME_SERVER 12 -#define SYM_RLP_SERVER 13 -#define SYM_SUBNET_MASK 14 -#define SYM_TIME_OFFSET 15 -#define SYM_TIME_SERVER 16 -#define SYM_VENDOR_MAGIC 17 -#define SYM_SIMILAR_ENTRY 18 -#define SYM_NAME_SWITCH 19 -#define SYM_BOOTSIZE 20 -#define SYM_BOOT_SERVER 22 -#define SYM_TFTPDIR 23 -#define SYM_DUMP_FILE 24 -#define SYM_DOMAIN_NAME 25 -#define SYM_SWAP_SERVER 26 -#define SYM_ROOT_PATH 27 -#define SYM_EXTEN_FILE 28 -#define SYM_REPLY_ADDR 29 -#define SYM_NIS_DOMAIN 30 /* RFC 1533 */ -#define SYM_NIS_SERVER 31 /* RFC 1533 */ -#define SYM_NTP_SERVER 32 /* RFC 1533 */ -#define SYM_EXEC_FILE 33 /* YORK_EX_OPTION */ -#define SYM_MSG_SIZE 34 -#define SYM_MIN_WAIT 35 -/* XXX - Add new tags here */ - -#define OP_ADDITION 1 /* Operations on tags */ -#define OP_DELETION 2 -#define OP_BOOLEAN 3 - -#define MAXINADDRS 16 /* Max size of an IP address list */ -#define MAXBUFLEN 256 /* Max temp buffer space */ -#define MAXENTRYLEN 2048 /* Max size of an entire entry */ - - - -/* - * Structure used to map a configuration-file symbol (such as "ds") to a - * unique integer. - */ - -struct symbolmap { - char *symbol; - int symbolcode; -}; - - -struct htypename { - char *name; - byte htype; -}; - - -PRIVATE int nhosts; /* Number of hosts (/w hw or IP address) */ -PRIVATE int nentries; /* Total number of entries */ -PRIVATE int32 modtime = 0; /* Last modification time of bootptab */ -PRIVATE char *current_hostname; /* Name of the current entry. */ -PRIVATE char current_tagname[8]; - -/* - * List of symbolic names used in the bootptab file. The order and actual - * values of the symbol codes (SYM_. . .) are unimportant, but they must - * all be unique. - */ - -PRIVATE struct symbolmap symbol_list[] = { - {"bf", SYM_BOOTFILE}, - {"bs", SYM_BOOTSIZE}, - {"cs", SYM_COOKIE_SERVER}, - {"df", SYM_DUMP_FILE}, - {"dn", SYM_DOMAIN_NAME}, - {"ds", SYM_DOMAIN_SERVER}, - {"ef", SYM_EXTEN_FILE}, - {"ex", SYM_EXEC_FILE}, /* YORK_EX_OPTION */ - {"gw", SYM_GATEWAY}, - {"ha", SYM_HWADDR}, - {"hd", SYM_HOMEDIR}, - {"hn", SYM_NAME_SWITCH}, - {"ht", SYM_HTYPE}, - {"im", SYM_IMPRESS_SERVER}, - {"ip", SYM_IPADDR}, - {"lg", SYM_LOG_SERVER}, - {"lp", SYM_LPR_SERVER}, - {"ms", SYM_MSG_SIZE}, - {"mw", SYM_MIN_WAIT}, - {"ns", SYM_NAME_SERVER}, - {"nt", SYM_NTP_SERVER}, - {"ra", SYM_REPLY_ADDR}, - {"rl", SYM_RLP_SERVER}, - {"rp", SYM_ROOT_PATH}, - {"sa", SYM_BOOT_SERVER}, - {"sm", SYM_SUBNET_MASK}, - {"sw", SYM_SWAP_SERVER}, - {"tc", SYM_SIMILAR_ENTRY}, - {"td", SYM_TFTPDIR}, - {"to", SYM_TIME_OFFSET}, - {"ts", SYM_TIME_SERVER}, - {"vm", SYM_VENDOR_MAGIC}, - {"yd", SYM_NIS_DOMAIN}, - {"ys", SYM_NIS_SERVER}, - /* XXX - Add new tags here */ -}; - - -/* - * List of symbolic names for hardware types. Name translates into - * hardware type code listed with it. Names must begin with a letter - * and must be all lowercase. This is searched linearly, so put - * commonly-used entries near the beginning. - */ - -PRIVATE struct htypename htnamemap[] = { - {"ethernet", HTYPE_ETHERNET}, - {"ethernet3", HTYPE_EXP_ETHERNET}, - {"ether", HTYPE_ETHERNET}, - {"ether3", HTYPE_EXP_ETHERNET}, - {"ieee802", HTYPE_IEEE802}, - {"tr", HTYPE_IEEE802}, - {"token-ring", HTYPE_IEEE802}, - {"pronet", HTYPE_PRONET}, - {"chaos", HTYPE_CHAOS}, - {"arcnet", HTYPE_ARCNET}, - {"ax.25", HTYPE_AX25}, - {"direct", HTYPE_DIRECT}, - {"serial", HTYPE_DIRECT}, - {"slip", HTYPE_DIRECT}, - {"ppp", HTYPE_DIRECT} -}; - - - -/* - * Externals and forward declarations. - */ - -#ifdef __STDC__ -#define P(args) args -#else -#define P(args) () -#endif - -extern boolean iplookcmp(); -boolean nmcmp P((hash_datum *, hash_datum *)); - -PRIVATE void - adjust P((char **)); -PRIVATE void - del_string P((struct shared_string *)); -PRIVATE void - del_bindata P((struct shared_bindata *)); -PRIVATE void - del_iplist P((struct in_addr_list *)); -PRIVATE void - eat_whitespace P((char **)); -PRIVATE int - eval_symbol P((char **, struct host *)); -PRIVATE void - fill_defaults P((struct host *, char **)); -PRIVATE void - free_host P((hash_datum *)); -PRIVATE struct in_addr_list * - get_addresses P((char **)); -PRIVATE struct shared_string * - get_shared_string P((char **)); -PRIVATE char * - get_string P((char **, char *, u_int *)); -PRIVATE u_int32 - get_u_long P((char **)); -PRIVATE boolean - goodname P((char *)); -PRIVATE boolean - hwinscmp P((hash_datum *, hash_datum *)); -PRIVATE int - interp_byte P((char **, byte *)); -PRIVATE void - makelower P((char *)); -PRIVATE boolean - nullcmp P((hash_datum *, hash_datum *)); -PRIVATE int - process_entry P((struct host *, char *)); -PRIVATE int - process_generic P((char **, struct shared_bindata **, u_int)); -PRIVATE byte * - prs_haddr P((char **, u_int)); -PRIVATE int - prs_inetaddr P((char **, u_int32 *)); -PRIVATE void - read_entry P((FILE *, char *, u_int *)); -PRIVATE char * - smalloc P((u_int)); - -#undef P - - -/* - * Vendor magic cookies for CMU and RFC1048 - */ -u_char vm_cmu[4] = VM_CMU; -u_char vm_rfc1048[4] = VM_RFC1048; - -/* - * Main hash tables - */ -hash_tbl *hwhashtable; -hash_tbl *iphashtable; -hash_tbl *nmhashtable; - -/* - * Allocate hash tables for hardware address, ip address, and hostname - * (shared by bootpd and bootpef) - */ -void -rdtab_init() -{ - hwhashtable = hash_Init(HASHTABLESIZE); - iphashtable = hash_Init(HASHTABLESIZE); - nmhashtable = hash_Init(HASHTABLESIZE); - if (!(hwhashtable && iphashtable && nmhashtable)) { - report(LOG_ERR, "Unable to allocate hash tables."); - exit(1); - } -} - - -/* - * Read bootptab database file. Avoid rereading the file if the - * write date hasn't changed since the last time we read it. - */ - -void -readtab(force) - int force; -{ - struct host *hp; - FILE *fp; - struct stat st; - unsigned hashcode, buflen; - static char buffer[MAXENTRYLEN]; - - /* - * Check the last modification time. - */ - if (stat(bootptab, &st) < 0) { - report(LOG_ERR, "stat on \"%s\": %s", - bootptab, get_errmsg()); - return; - } -#ifdef DEBUG - if (debug > 3) { - char timestr[28]; - strcpy(timestr, ctime(&(st.st_mtime))); - /* zap the newline */ - timestr[24] = '\0'; - report(LOG_INFO, "bootptab mtime: %s", - timestr); - } -#endif - if ((force == 0) && - (st.st_mtime == modtime) && - st.st_nlink) { - /* - * hasn't been modified or deleted yet. - */ - return; - } - if (debug) - report(LOG_INFO, "reading %s\"%s\"", - (modtime != 0L) ? "new " : "", - bootptab); - - /* - * Open bootptab file. - */ - if ((fp = fopen(bootptab, "r")) == NULL) { - report(LOG_ERR, "error opening \"%s\": %s", bootptab, get_errmsg()); - return; - } - /* - * Record file modification time. - */ - if (fstat(fileno(fp), &st) < 0) { - report(LOG_ERR, "fstat: %s", get_errmsg()); - fclose(fp); - return; - } - modtime = st.st_mtime; - - /* - * Entirely erase all hash tables. - */ - hash_Reset(hwhashtable, free_host); - hash_Reset(iphashtable, free_host); - hash_Reset(nmhashtable, free_host); - - nhosts = 0; - nentries = 0; - while (TRUE) { - buflen = sizeof(buffer); - read_entry(fp, buffer, &buflen); - if (buflen == 0) { /* More entries? */ - break; - } - hp = (struct host *) smalloc(sizeof(struct host)); - bzero((char *) hp, sizeof(*hp)); - /* the link count it zero */ - - /* - * Get individual info - */ - if (process_entry(hp, buffer) < 0) { - hp->linkcount = 1; - free_host((hash_datum *) hp); - continue; - } - /* - * If this is not a dummy entry, and the IP or HW - * address is not yet set, try to get them here. - * Dummy entries have . as first char of name. - */ - if (goodname(hp->hostname->string)) { - char *hn = hp->hostname->string; - u_int32 value; - if (hp->flags.iaddr == 0) { - if (lookup_ipa(hn, &value)) { - report(LOG_ERR, "can not get IP addr for %s", hn); - report(LOG_ERR, "(dummy names should start with '.')"); - } else { - hp->iaddr.s_addr = value; - hp->flags.iaddr = TRUE; - } - } - /* Set default subnet mask. */ - if (hp->flags.subnet_mask == 0) { - if (lookup_netmask(hp->iaddr.s_addr, &value)) { - report(LOG_ERR, "can not get netmask for %s", hn); - } else { - hp->subnet_mask.s_addr = value; - hp->flags.subnet_mask = TRUE; - } - } - } - if (hp->flags.iaddr) { - nhosts++; - } - /* Register by HW addr if known. */ - if (hp->flags.htype && hp->flags.haddr) { - /* We will either insert it or free it. */ - hp->linkcount++; - hashcode = hash_HashFunction(hp->haddr, haddrlength(hp->htype)); - if (hash_Insert(hwhashtable, hashcode, hwinscmp, hp, hp) < 0) { - report(LOG_NOTICE, "duplicate %s address: %s", - netname(hp->htype), - haddrtoa(hp->haddr, hp->htype)); - free_host((hash_datum *) hp); - continue; - } - } - /* Register by IP addr if known. */ - if (hp->flags.iaddr) { - hashcode = hash_HashFunction((u_char *) & (hp->iaddr.s_addr), 4); - if (hash_Insert(iphashtable, hashcode, nullcmp, hp, hp) < 0) { - report(LOG_ERR, - "hash_Insert() failed on IP address insertion"); - } else { - /* Just inserted the host struct in a new hash list. */ - hp->linkcount++; - } - } - /* Register by Name (always known) */ - hashcode = hash_HashFunction((u_char *) hp->hostname->string, - strlen(hp->hostname->string)); - if (hash_Insert(nmhashtable, hashcode, nullcmp, - hp->hostname->string, hp) < 0) { - report(LOG_ERR, - "hash_Insert() failed on insertion of hostname: \"%s\"", - hp->hostname->string); - } else { - /* Just inserted the host struct in a new hash list. */ - hp->linkcount++; - } - - nentries++; - } - - fclose(fp); - if (debug) - report(LOG_INFO, "read %d entries (%d hosts) from \"%s\"", - nentries, nhosts, bootptab); - return; -} - - - -/* - * Read an entire host entry from the file pointed to by "fp" and insert it - * into the memory pointed to by "buffer". Leading whitespace and comments - * starting with "#" are ignored (removed). Backslashes (\) always quote - * the next character except that newlines preceeded by a backslash cause - * line-continuation onto the next line. The entry is terminated by a - * newline character which is not preceeded by a backslash. Sequences - * surrounded by double quotes are taken literally (including newlines, but - * not backslashes). - * - * The "bufsiz" parameter points to an unsigned int which specifies the - * maximum permitted buffer size. Upon return, this value will be replaced - * with the actual length of the entry (not including the null terminator). - * - * This code is a little scary. . . . I don't like using gotos in C - * either, but I first wrote this as an FSM diagram and gotos seemed like - * the easiest way to implement it. Maybe later I'll clean it up. - */ - -PRIVATE void -read_entry(fp, buffer, bufsiz) - FILE *fp; - char *buffer; - unsigned *bufsiz; -{ - int c, length; - - length = 0; - - /* - * Eat whitespace, blank lines, and comment lines. - */ - top: - c = fgetc(fp); - if (c < 0) { - goto done; /* Exit if end-of-file */ - } - if (isspace(c)) { - goto top; /* Skip over whitespace */ - } - if (c == '#') { - while (TRUE) { /* Eat comments after # */ - c = fgetc(fp); - if (c < 0) { - goto done; /* Exit if end-of-file */ - } - if (c == '\n') { - goto top; /* Try to read the next line */ - } - } - } - ungetc(c, fp); /* Other character, push it back to reprocess it */ - - - /* - * Now we're actually reading a data entry. Get each character and - * assemble it into the data buffer, processing special characters like - * double quotes (") and backslashes (\). - */ - - mainloop: - c = fgetc(fp); - switch (c) { - case EOF: - case '\n': - goto done; /* Exit on EOF or newline */ - case '\\': - c = fgetc(fp); /* Backslash, read a new character */ - if (c < 0) { - goto done; /* Exit on EOF */ - } - *buffer++ = c; /* Store the literal character */ - length++; - if (length < *bufsiz - 1) { - goto mainloop; - } else { - goto done; - } - case '"': - *buffer++ = '"'; /* Store double-quote */ - length++; - if (length >= *bufsiz - 1) { - goto done; - } - while (TRUE) { /* Special quote processing loop */ - c = fgetc(fp); - switch (c) { - case EOF: - goto done; /* Exit on EOF . . . */ - case '"': - *buffer++ = '"';/* Store matching quote */ - length++; - if (length < *bufsiz - 1) { - goto mainloop; /* And continue main loop */ - } else { - goto done; - } - case '\\': - if ((c = fgetc(fp)) < 0) { /* Backslash */ - goto done; /* EOF. . . .*/ - } /* else fall through */ - default: - *buffer++ = c; /* Other character, store it */ - length++; - if (length >= *bufsiz - 1) { - goto done; - } - } - } - case ':': - *buffer++ = c; /* Store colons */ - length++; - if (length >= *bufsiz - 1) { - goto done; - } - do { /* But remove whitespace after them */ - c = fgetc(fp); - if ((c < 0) || (c == '\n')) { - goto done; - } - } while (isspace(c)); /* Skip whitespace */ - - if (c == '\\') { /* Backslash quotes next character */ - c = fgetc(fp); - if (c < 0) { - goto done; - } - if (c == '\n') { - goto top; /* Backslash-newline continuation */ - } - } - /* fall through if "other" character */ - default: - *buffer++ = c; /* Store other characters */ - length++; - if (length >= *bufsiz - 1) { - goto done; - } - } - goto mainloop; /* Keep going */ - - done: - *buffer = '\0'; /* Terminate string */ - *bufsiz = length; /* Tell the caller its length */ -} - - - -/* - * Parse out all the various tags and parameters in the host entry pointed - * to by "src". Stuff all the data into the appropriate fields of the - * host structure pointed to by "host". If there is any problem with the - * entry, an error message is reported via report(), no further processing - * is done, and -1 is returned. Successful calls return 0. - * - * (Some errors probably shouldn't be so completely fatal. . . .) - */ - -PRIVATE int -process_entry(host, src) - struct host *host; - char *src; -{ - int retval; - char *msg; - - if (!host || *src == '\0') { - return -1; - } - host->hostname = get_shared_string(&src); -#if 0 - /* Be more liberal for the benefit of dummy tag names. */ - if (!goodname(host->hostname->string)) { - report(LOG_ERR, "bad hostname: \"%s\"", host->hostname->string); - del_string(host->hostname); - return -1; - } -#endif - current_hostname = host->hostname->string; - adjust(&src); - while (TRUE) { - retval = eval_symbol(&src, host); - if (retval == SUCCESS) { - adjust(&src); - continue; - } - if (retval == E_END_OF_ENTRY) { - /* The default subnet mask is set in readtab() */ - return 0; - } - /* Some kind of error. */ - switch (retval) { - case E_SYNTAX_ERROR: - msg = "bad syntax"; - break; - case E_UNKNOWN_SYMBOL: - msg = "unknown symbol"; - break; - case E_BAD_IPADDR: - msg = "bad INET address"; - break; - case E_BAD_HWADDR: - msg = "bad hardware address"; - break; - case E_BAD_LONGWORD: - msg = "bad longword value"; - break; - case E_BAD_HWATYPE: - msg = "bad HW address type"; - break; - case E_BAD_PATHNAME: - msg = "bad pathname (need leading '/')"; - case E_BAD_VALUE: - msg = "bad value"; - default: - msg = "unkown error"; - break; - } /* switch */ - report(LOG_ERR, "in entry named \"%s\", symbol \"%s\": %s", - current_hostname, current_tagname, msg); - return -1; - } -} - - -/* - * Macros for use in the function below: - */ - -/* Parse one INET address stored directly in MEMBER. */ -#define PARSE_IA1(MEMBER) do \ -{ \ - if (optype == OP_BOOLEAN) \ - return E_SYNTAX_ERROR; \ - hp->flags.MEMBER = FALSE; \ - if (optype == OP_ADDITION) { \ - if (prs_inetaddr(symbol, &value) < 0) \ - return E_BAD_IPADDR; \ - hp->MEMBER.s_addr = value; \ - hp->flags.MEMBER = TRUE; \ - } \ -} while (0) - -/* Parse a list of INET addresses pointed to by MEMBER */ -#define PARSE_IAL(MEMBER) do \ -{ \ - if (optype == OP_BOOLEAN) \ - return E_SYNTAX_ERROR; \ - if (hp->flags.MEMBER) { \ - hp->flags.MEMBER = FALSE; \ - assert(hp->MEMBER); \ - del_iplist(hp->MEMBER); \ - hp->MEMBER = NULL; \ - } \ - if (optype == OP_ADDITION) { \ - hp->MEMBER = get_addresses(symbol); \ - if (hp->MEMBER == NULL) \ - return E_SYNTAX_ERROR; \ - hp->flags.MEMBER = TRUE; \ - } \ -} while (0) - -/* Parse a shared string pointed to by MEMBER */ -#define PARSE_STR(MEMBER) do \ -{ \ - if (optype == OP_BOOLEAN) \ - return E_SYNTAX_ERROR; \ - if (hp->flags.MEMBER) { \ - hp->flags.MEMBER = FALSE; \ - assert(hp->MEMBER); \ - del_string(hp->MEMBER); \ - hp->MEMBER = NULL; \ - } \ - if (optype == OP_ADDITION) { \ - hp->MEMBER = get_shared_string(symbol); \ - if (hp->MEMBER == NULL) \ - return E_SYNTAX_ERROR; \ - hp->flags.MEMBER = TRUE; \ - } \ -} while (0) - -/* Parse an integer value for MEMBER */ -#define PARSE_INT(MEMBER) do \ -{ \ - if (optype == OP_BOOLEAN) \ - return E_SYNTAX_ERROR; \ - hp->flags.MEMBER = FALSE; \ - if (optype == OP_ADDITION) { \ - value = get_u_long(symbol); \ - hp->MEMBER = value; \ - hp->flags.MEMBER = TRUE; \ - } \ -} while (0) - -/* - * Evaluate the two-character tag symbol pointed to by "symbol" and place - * the data in the structure pointed to by "hp". The pointer pointed to - * by "symbol" is updated to point past the source string (but may not - * point to the next tag entry). - * - * Obviously, this need a few more comments. . . . - */ -PRIVATE int -eval_symbol(symbol, hp) - char **symbol; - struct host *hp; -{ - char tmpstr[MAXSTRINGLEN]; - byte *tmphaddr; - struct shared_string *ss; - struct symbolmap *symbolptr; - u_int32 value; - int32 timeoff; - int i, numsymbols; - unsigned len; - int optype; /* Indicates boolean, addition, or deletion */ - - eat_whitespace(symbol); - - /* Make sure this is set before returning. */ - current_tagname[0] = (*symbol)[0]; - current_tagname[1] = (*symbol)[1]; - current_tagname[2] = 0; - - if ((*symbol)[0] == '\0') { - return E_END_OF_ENTRY; - } - if ((*symbol)[0] == ':') { - return SUCCESS; - } - if ((*symbol)[0] == 'T') { /* generic symbol */ - (*symbol)++; - value = get_u_long(symbol); - sprintf(current_tagname, "T%d", value); - eat_whitespace(symbol); - if ((*symbol)[0] != '=') { - return E_SYNTAX_ERROR; - } - (*symbol)++; - if (!(hp->generic)) { - hp->generic = (struct shared_bindata *) - smalloc(sizeof(struct shared_bindata)); - } - if (process_generic(symbol, &(hp->generic), (byte) (value & 0xFF))) - return E_SYNTAX_ERROR; - hp->flags.generic = TRUE; - return SUCCESS; - } - /* - * Determine the type of operation to be done on this symbol - */ - switch ((*symbol)[2]) { - case '=': - optype = OP_ADDITION; - break; - case '@': - optype = OP_DELETION; - break; - case ':': - case '\0': - optype = OP_BOOLEAN; - break; - default: - return E_SYNTAX_ERROR; - } - - symbolptr = symbol_list; - numsymbols = sizeof(symbol_list) / sizeof(struct symbolmap); - for (i = 0; i < numsymbols; i++) { - if (((symbolptr->symbol)[0] == (*symbol)[0]) && - ((symbolptr->symbol)[1] == (*symbol)[1])) { - break; - } - symbolptr++; - } - if (i >= numsymbols) { - return E_UNKNOWN_SYMBOL; - } - /* - * Skip past the = or @ character (to point to the data) if this - * isn't a boolean operation. For boolean operations, just skip - * over the two-character tag symbol (and nothing else. . . .). - */ - (*symbol) += (optype == OP_BOOLEAN) ? 2 : 3; - - eat_whitespace(symbol); - - /* The cases below are in order by symbolcode value. */ - switch (symbolptr->symbolcode) { - - case SYM_BOOTFILE: - PARSE_STR(bootfile); - break; - - case SYM_COOKIE_SERVER: - PARSE_IAL(cookie_server); - break; - - case SYM_DOMAIN_SERVER: - PARSE_IAL(domain_server); - break; - - case SYM_GATEWAY: - PARSE_IAL(gateway); - break; - - case SYM_HWADDR: - if (optype == OP_BOOLEAN) - return E_SYNTAX_ERROR; - hp->flags.haddr = FALSE; - if (optype == OP_ADDITION) { - /* Default the HW type to Ethernet */ - if (hp->flags.htype == 0) { - hp->flags.htype = TRUE; - hp->htype = HTYPE_ETHERNET; - } - tmphaddr = prs_haddr(symbol, hp->htype); - if (!tmphaddr) - return E_BAD_HWADDR; - bcopy(tmphaddr, hp->haddr, haddrlength(hp->htype)); - hp->flags.haddr = TRUE; - } - break; - - case SYM_HOMEDIR: - PARSE_STR(homedir); - break; - - case SYM_HTYPE: - if (optype == OP_BOOLEAN) - return E_SYNTAX_ERROR; - hp->flags.htype = FALSE; - if (optype == OP_ADDITION) { - value = 0L; /* Assume an illegal value */ - eat_whitespace(symbol); - if (isdigit(**symbol)) { - value = get_u_long(symbol); - } else { - len = sizeof(tmpstr); - (void) get_string(symbol, tmpstr, &len); - makelower(tmpstr); - numsymbols = sizeof(htnamemap) / - sizeof(struct htypename); - for (i = 0; i < numsymbols; i++) { - if (!strcmp(htnamemap[i].name, tmpstr)) { - break; - } - } - if (i < numsymbols) { - value = htnamemap[i].htype; - } - } - if (value >= hwinfocnt) { - return E_BAD_HWATYPE; - } - hp->htype = (byte) (value & 0xFF); - hp->flags.htype = TRUE; - } - break; - - case SYM_IMPRESS_SERVER: - PARSE_IAL(impress_server); - break; - - case SYM_IPADDR: - PARSE_IA1(iaddr); - break; - - case SYM_LOG_SERVER: - PARSE_IAL(log_server); - break; - - case SYM_LPR_SERVER: - PARSE_IAL(lpr_server); - break; - - case SYM_NAME_SERVER: - PARSE_IAL(name_server); - break; - - case SYM_RLP_SERVER: - PARSE_IAL(rlp_server); - break; - - case SYM_SUBNET_MASK: - PARSE_IA1(subnet_mask); - break; - - case SYM_TIME_OFFSET: - if (optype == OP_BOOLEAN) - return E_SYNTAX_ERROR; - hp->flags.time_offset = FALSE; - if (optype == OP_ADDITION) { - len = sizeof(tmpstr); - (void) get_string(symbol, tmpstr, &len); - if (!strncmp(tmpstr, "auto", 4)) { - hp->time_offset = secondswest; - } else { - if (sscanf(tmpstr, "%d", &timeoff) != 1) - return E_BAD_LONGWORD; - hp->time_offset = timeoff; - } - hp->flags.time_offset = TRUE; - } - break; - - case SYM_TIME_SERVER: - PARSE_IAL(time_server); - break; - - case SYM_VENDOR_MAGIC: - if (optype == OP_BOOLEAN) - return E_SYNTAX_ERROR; - hp->flags.vm_cookie = FALSE; - if (optype == OP_ADDITION) { - if (strncmp(*symbol, "auto", 4)) { - /* The string is not "auto" */ - if (!strncmp(*symbol, "rfc", 3)) { - bcopy(vm_rfc1048, hp->vm_cookie, 4); - } else if (!strncmp(*symbol, "cmu", 3)) { - bcopy(vm_cmu, hp->vm_cookie, 4); - } else { - if (!isdigit(**symbol)) - return E_BAD_IPADDR; - if (prs_inetaddr(symbol, &value) < 0) - return E_BAD_IPADDR; - bcopy(&value, hp->vm_cookie, 4); - } - hp->flags.vm_cookie = TRUE; - } - } - break; - - case SYM_SIMILAR_ENTRY: - switch (optype) { - case OP_ADDITION: - fill_defaults(hp, symbol); - break; - default: - return E_SYNTAX_ERROR; - } - break; - - case SYM_NAME_SWITCH: - switch (optype) { - case OP_ADDITION: - return E_SYNTAX_ERROR; - case OP_DELETION: - hp->flags.send_name = FALSE; - hp->flags.name_switch = FALSE; - break; - case OP_BOOLEAN: - hp->flags.send_name = TRUE; - hp->flags.name_switch = TRUE; - break; - } - break; - - case SYM_BOOTSIZE: - switch (optype) { - case OP_ADDITION: - if (!strncmp(*symbol, "auto", 4)) { - hp->flags.bootsize = TRUE; - hp->flags.bootsize_auto = TRUE; - } else { - hp->bootsize = (unsigned int) get_u_long(symbol); - hp->flags.bootsize = TRUE; - hp->flags.bootsize_auto = FALSE; - } - break; - case OP_DELETION: - hp->flags.bootsize = FALSE; - break; - case OP_BOOLEAN: - hp->flags.bootsize = TRUE; - hp->flags.bootsize_auto = TRUE; - break; - } - break; - - case SYM_BOOT_SERVER: - PARSE_IA1(bootserver); - break; - - case SYM_TFTPDIR: - PARSE_STR(tftpdir); - if ((hp->tftpdir != NULL) && - (hp->tftpdir->string[0] != '/')) - return E_BAD_PATHNAME; - break; - - case SYM_DUMP_FILE: - PARSE_STR(dump_file); - break; - - case SYM_DOMAIN_NAME: - PARSE_STR(domain_name); - break; - - case SYM_SWAP_SERVER: - PARSE_IA1(swap_server); - break; - - case SYM_ROOT_PATH: - PARSE_STR(root_path); - break; - - case SYM_EXTEN_FILE: - PARSE_STR(exten_file); - break; - - case SYM_REPLY_ADDR: - PARSE_IA1(reply_addr); - break; - - case SYM_NIS_DOMAIN: - PARSE_STR(nis_domain); - break; - - case SYM_NIS_SERVER: - PARSE_IAL(nis_server); - break; - - case SYM_NTP_SERVER: - PARSE_IAL(ntp_server); - break; - -#ifdef YORK_EX_OPTION - case SYM_EXEC_FILE: - PARSE_STR(exec_file); - break; -#endif - - case SYM_MSG_SIZE: - PARSE_INT(msg_size); - if (hp->msg_size < BP_MINPKTSZ || - hp->msg_size > MAX_MSG_SIZE) - return E_BAD_VALUE; - break; - - case SYM_MIN_WAIT: - PARSE_INT(min_wait); - if (hp->min_wait < 0) - return E_BAD_VALUE; - break; - - /* XXX - Add new tags here */ - - default: - return E_UNKNOWN_SYMBOL; - - } /* switch symbolcode */ - - return SUCCESS; -} -#undef PARSE_IA1 -#undef PARSE_IAL -#undef PARSE_STR - - - - -/* - * Read a string from the buffer indirectly pointed to through "src" and - * move it into the buffer pointed to by "dest". A pointer to the maximum - * allowable length of the string (including null-terminator) is passed as - * "length". The actual length of the string which was read is returned in - * the unsigned integer pointed to by "length". This value is the same as - * that which would be returned by applying the strlen() function on the - * destination string (i.e the terminating null is not counted as a - * character). Trailing whitespace is removed from the string. For - * convenience, the function returns the new value of "dest". - * - * The string is read until the maximum number of characters, an unquoted - * colon (:), or a null character is read. The return string in "dest" is - * null-terminated. - */ - -PRIVATE char * -get_string(src, dest, length) - char **src, *dest; - unsigned *length; -{ - int n, len, quoteflag; - - quoteflag = FALSE; - n = 0; - len = *length - 1; - while ((n < len) && (**src)) { - if (!quoteflag && (**src == ':')) { - break; - } - if (**src == '"') { - (*src)++; - quoteflag = !quoteflag; - continue; - } - if (**src == '\\') { - (*src)++; - if (!**src) { - break; - } - } - *dest++ = *(*src)++; - n++; - } - - /* - * Remove that troublesome trailing whitespace. . . - */ - while ((n > 0) && isspace(dest[-1])) { - dest--; - n--; - } - - *dest = '\0'; - *length = n; - return dest; -} - - - -/* - * Read the string indirectly pointed to by "src", update the caller's - * pointer, and return a pointer to a malloc'ed shared_string structure - * containing the string. - * - * The string is read using the same rules as get_string() above. - */ - -PRIVATE struct shared_string * -get_shared_string(src) - char **src; -{ - char retstring[MAXSTRINGLEN]; - struct shared_string *s; - unsigned length; - - length = sizeof(retstring); - (void) get_string(src, retstring, &length); - - s = (struct shared_string *) smalloc(sizeof(struct shared_string) - + length); - s->linkcount = 1; - strcpy(s->string, retstring); - - return s; -} - - - -/* - * Load RFC1048 generic information directly into a memory buffer. - * - * "src" indirectly points to the ASCII representation of the generic data. - * "dest" points to a string structure which is updated to point to a new - * string with the new data appended to the old string. The old string is - * freed. - * - * The given tag value is inserted with the new data. - * - * The data may be represented as either a stream of hexadecimal numbers - * representing bytes (any or all bytes may optionally start with '0x' and - * be separated with periods ".") or as a quoted string of ASCII - * characters (the quotes are required). - */ - -PRIVATE int -process_generic(src, dest, tagvalue) - char **src; - struct shared_bindata **dest; - u_int tagvalue; -{ - byte tmpbuf[MAXBUFLEN]; - byte *str; - struct shared_bindata *bdata; - u_int newlength, oldlength; - - str = tmpbuf; - *str++ = (tagvalue & 0xFF); /* Store tag value */ - str++; /* Skip over length field */ - if ((*src)[0] == '"') { /* ASCII data */ - newlength = sizeof(tmpbuf) - 2; /* Set maximum allowed length */ - (void) get_string(src, (char *) str, &newlength); - newlength++; /* null terminator */ - } else { /* Numeric data */ - newlength = 0; - while (newlength < sizeof(tmpbuf) - 2) { - if (interp_byte(src, str++) < 0) - break; - newlength++; - if (**src == '.') { - (*src)++; - } - } - } - if ((*src)[0] != ':') - return -1; - - tmpbuf[1] = (newlength & 0xFF); - oldlength = ((*dest)->length); - bdata = (struct shared_bindata *) smalloc(sizeof(struct shared_bindata) - + oldlength + newlength + 1); - if (oldlength > 0) { - bcopy((*dest)->data, bdata->data, oldlength); - } - bcopy(tmpbuf, bdata->data + oldlength, newlength + 2); - bdata->length = oldlength + newlength + 2; - bdata->linkcount = 1; - if (*dest) { - del_bindata(*dest); - } - *dest = bdata; - return 0; -} - - - -/* - * Verify that the given string makes sense as a hostname (according to - * Appendix 1, page 29 of RFC882). - * - * Return TRUE for good names, FALSE otherwise. - */ - -PRIVATE boolean -goodname(hostname) - register char *hostname; -{ - do { - if (!isalpha(*hostname++)) { /* First character must be a letter */ - return FALSE; - } - while (isalnum(*hostname) || - (*hostname == '-') || - (*hostname == '_') ) - { - hostname++; /* Alphanumeric or a hyphen */ - } - if (!isalnum(hostname[-1])) { /* Last must be alphanumeric */ - return FALSE; - } - if (*hostname == '\0') {/* Done? */ - return TRUE; - } - } while (*hostname++ == '.'); /* Dot, loop for next label */ - - return FALSE; /* If it's not a dot, lose */ -} - - - -/* - * Null compare function -- always returns FALSE so an element is always - * inserted into a hash table (i.e. there is never a collision with an - * existing element). - */ - -PRIVATE boolean -nullcmp(d1, d2) - hash_datum *d1, *d2; -{ - return FALSE; -} - - -/* - * Function for comparing a string with the hostname field of a host - * structure. - */ - -boolean -nmcmp(d1, d2) - hash_datum *d1, *d2; -{ - char *name = (char *) d1; /* XXX - OK? */ - struct host *hp = (struct host *) d2; - - return !strcmp(name, hp->hostname->string); -} - - -/* - * Compare function to determine whether two hardware addresses are - * equivalent. Returns TRUE if "host1" and "host2" are equivalent, FALSE - * otherwise. - * - * If the hardware addresses of "host1" and "host2" are identical, but - * they are on different IP subnets, this function returns FALSE. - * - * This function is used when inserting elements into the hardware address - * hash table. - */ - -PRIVATE boolean -hwinscmp(d1, d2) - hash_datum *d1, *d2; -{ - struct host *host1 = (struct host *) d1; - struct host *host2 = (struct host *) d2; - - if (host1->htype != host2->htype) { - return FALSE; - } - if (bcmp(host1->haddr, host2->haddr, haddrlength(host1->htype))) { - return FALSE; - } - /* XXX - Is the subnet_mask field set yet? */ - if ((host1->subnet_mask.s_addr) == (host2->subnet_mask.s_addr)) { - if (((host1->iaddr.s_addr) & (host1->subnet_mask.s_addr)) != - ((host2->iaddr.s_addr) & (host2->subnet_mask.s_addr))) - { - return FALSE; - } - } - return TRUE; -} - - -/* - * Macros for use in the function below: - */ - -#define DUP_COPY(MEMBER) do \ -{ \ - if (!hp->flags.MEMBER) { \ - if ((hp->flags.MEMBER = hp2->flags.MEMBER) != 0) { \ - hp->MEMBER = hp2->MEMBER; \ - } \ - } \ -} while (0) - -#define DUP_LINK(MEMBER) do \ -{ \ - if (!hp->flags.MEMBER) { \ - if ((hp->flags.MEMBER = hp2->flags.MEMBER) != 0) { \ - assert(hp2->MEMBER); \ - hp->MEMBER = hp2->MEMBER; \ - (hp->MEMBER->linkcount)++; \ - } \ - } \ -} while (0) - -/* - * Process the "similar entry" symbol. - * - * The host specified as the value of the "tc" symbol is used as a template - * for the current host entry. Symbol values not explicitly set in the - * current host entry are inferred from the template entry. - */ -PRIVATE void -fill_defaults(hp, src) - struct host *hp; - char **src; -{ - unsigned int tlen, hashcode; - struct host *hp2; - char tstring[MAXSTRINGLEN]; - - tlen = sizeof(tstring); - (void) get_string(src, tstring, &tlen); - hashcode = hash_HashFunction((u_char *) tstring, tlen); - hp2 = (struct host *) hash_Lookup(nmhashtable, hashcode, nmcmp, tstring); - - if (hp2 == NULL) { - report(LOG_ERR, "can't find tc=\"%s\"", tstring); - return; - } - DUP_LINK(bootfile); - DUP_LINK(cookie_server); - DUP_LINK(domain_server); - DUP_LINK(gateway); - /* haddr not copied */ - DUP_LINK(homedir); - DUP_COPY(htype); - - DUP_LINK(impress_server); - /* iaddr not copied */ - DUP_LINK(log_server); - DUP_LINK(lpr_server); - DUP_LINK(name_server); - DUP_LINK(rlp_server); - - DUP_COPY(subnet_mask); - DUP_COPY(time_offset); - DUP_LINK(time_server); - - if (!hp->flags.vm_cookie) { - if ((hp->flags.vm_cookie = hp2->flags.vm_cookie)) { - bcopy(hp2->vm_cookie, hp->vm_cookie, 4); - } - } - if (!hp->flags.name_switch) { - if ((hp->flags.name_switch = hp2->flags.name_switch)) { - hp->flags.send_name = hp2->flags.send_name; - } - } - if (!hp->flags.bootsize) { - if ((hp->flags.bootsize = hp2->flags.bootsize)) { - hp->flags.bootsize_auto = hp2->flags.bootsize_auto; - hp->bootsize = hp2->bootsize; - } - } - DUP_COPY(bootserver); - - DUP_LINK(tftpdir); - DUP_LINK(dump_file); - DUP_LINK(domain_name); - - DUP_COPY(swap_server); - DUP_LINK(root_path); - DUP_LINK(exten_file); - - DUP_COPY(reply_addr); - - DUP_LINK(nis_domain); - DUP_LINK(nis_server); - DUP_LINK(ntp_server); - -#ifdef YORK_EX_OPTION - DUP_LINK(exec_file); -#endif - - DUP_COPY(msg_size); - DUP_COPY(min_wait); - - /* XXX - Add new tags here */ - - DUP_LINK(generic); - -} -#undef DUP_COPY -#undef DUP_LINK - - - -/* - * This function adjusts the caller's pointer to point just past the - * first-encountered colon. If it runs into a null character, it leaves - * the pointer pointing to it. - */ - -PRIVATE void -adjust(s) - char **s; -{ - register char *t; - - t = *s; - while (*t && (*t != ':')) { - t++; - } - if (*t) { - t++; - } - *s = t; -} - - - - -/* - * This function adjusts the caller's pointer to point to the first - * non-whitespace character. If it runs into a null character, it leaves - * the pointer pointing to it. - */ - -PRIVATE void -eat_whitespace(s) - char **s; -{ - register char *t; - - t = *s; - while (*t && isspace(*t)) { - t++; - } - *s = t; -} - - - -/* - * This function converts the given string to all lowercase. - */ - -PRIVATE void -makelower(s) - char *s; -{ - while (*s) { - if (isupper(*s)) { - *s = tolower(*s); - } - s++; - } -} - - - -/* - * - * N O T E : - * - * In many of the functions which follow, a parameter such as "src" or - * "symbol" is passed as a pointer to a pointer to something. This is - * done for the purpose of letting the called function update the - * caller's copy of the parameter (i.e. to effect call-by-reference - * parameter passing). The value of the actual parameter is only used - * to locate the real parameter of interest and then update this indirect - * parameter. - * - * I'm sure somebody out there won't like this. . . . - * (Yea, because it usually makes code slower... -gwr) - * - */ - - - -/* - * "src" points to a character pointer which points to an ASCII string of - * whitespace-separated IP addresses. A pointer to an in_addr_list - * structure containing the list of addresses is returned. NULL is - * returned if no addresses were found at all. The pointer pointed to by - * "src" is updated to point to the first non-address (illegal) character. - */ - -PRIVATE struct in_addr_list * -get_addresses(src) - char **src; -{ - struct in_addr tmpaddrlist[MAXINADDRS]; - struct in_addr *address1, *address2; - struct in_addr_list *result; - unsigned addrcount, totalsize; - - address1 = tmpaddrlist; - for (addrcount = 0; addrcount < MAXINADDRS; addrcount++) { - while (isspace(**src) || (**src == ',')) { - (*src)++; - } - if (!**src) { /* Quit if nothing more */ - break; - } - if (prs_inetaddr(src, &(address1->s_addr)) < 0) { - break; - } - address1++; /* Point to next address slot */ - } - if (addrcount < 1) { - result = NULL; - } else { - totalsize = sizeof(struct in_addr_list) - + (addrcount - 1) * sizeof(struct in_addr); - result = (struct in_addr_list *) smalloc(totalsize); - result->linkcount = 1; - result->addrcount = addrcount; - address1 = tmpaddrlist; - address2 = result->addr; - for (; addrcount > 0; addrcount--) { - address2->s_addr = address1->s_addr; - address1++; - address2++; - } - } - return result; -} - - - -/* - * prs_inetaddr(src, result) - * - * "src" is a value-result parameter; the pointer it points to is updated - * to point to the next data position. "result" points to an unsigned long - * in which an address is returned. - * - * This function parses the IP address string in ASCII "dot notation" pointed - * to by (*src) and places the result (in network byte order) in the unsigned - * long pointed to by "result". For malformed addresses, -1 is returned, - * (*src) points to the first illegal character, and the unsigned long pointed - * to by "result" is unchanged. Successful calls return 0. - */ - -PRIVATE int -prs_inetaddr(src, result) - char **src; - u_int32 *result; -{ - char tmpstr[MAXSTRINGLEN]; - register u_int32 value; - u_int32 parts[4], *pp; - int n; - char *s, *t; - -#if 1 /* XXX - experimental */ - /* Leading alpha char causes IP addr lookup. */ - if (isalpha(**src)) { - /* Lookup IP address. */ - s = *src; - t = tmpstr; - while ((isalnum(*s) || (*s == '.') || - (*s == '-') || (*s == '_') ) && - (t < &tmpstr[MAXSTRINGLEN - 1]) ) - *t++ = *s++; - *t = '\0'; - *src = s; - - n = lookup_ipa(tmpstr, result); - if (n < 0) - report(LOG_ERR, "can not get IP addr for %s", tmpstr); - return n; - } -#endif - - /* - * Parse an address in Internet format: - * a.b.c.d - * a.b.c (with c treated as 16-bits) - * a.b (with b treated as 24 bits) - */ - pp = parts; - loop: - /* If it's not a digit, return error. */ - if (!isdigit(**src)) - return -1; - *pp++ = get_u_long(src); - if (**src == '.') { - if (pp < (parts + 4)) { - (*src)++; - goto loop; - } - return (-1); - } -#if 0 - /* This is handled by the caller. */ - if (**src && !(isspace(**src) || (**src == ':'))) { - return (-1); - } -#endif - - /* - * Construct the address according to - * the number of parts specified. - */ - n = pp - parts; - switch (n) { - case 1: /* a -- 32 bits */ - value = parts[0]; - break; - case 2: /* a.b -- 8.24 bits */ - value = (parts[0] << 24) | (parts[1] & 0xFFFFFF); - break; - case 3: /* a.b.c -- 8.8.16 bits */ - value = (parts[0] << 24) | ((parts[1] & 0xFF) << 16) | - (parts[2] & 0xFFFF); - break; - case 4: /* a.b.c.d -- 8.8.8.8 bits */ - value = (parts[0] << 24) | ((parts[1] & 0xFF) << 16) | - ((parts[2] & 0xFF) << 8) | (parts[3] & 0xFF); - break; - default: - return (-1); - } - *result = htonl(value); - return (0); -} - - - -/* - * "src" points to a pointer which in turn points to a hexadecimal ASCII - * string. This string is interpreted as a hardware address and returned - * as a pointer to the actual hardware address, represented as an array of - * bytes. - * - * The ASCII string must have the proper number of digits for the specified - * hardware type (e.g. twelve digits for a 48-bit Ethernet address). - * Two-digit sequences (bytes) may be separated with periods (.) and/or - * prefixed with '0x' for readability, but this is not required. - * - * For bad addresses, the pointer which "src" points to is updated to point - * to the start of the first two-digit sequence which was bad, and the - * function returns a NULL pointer. - */ - -PRIVATE byte * -prs_haddr(src, htype) - char **src; - u_int htype; -{ - static byte haddr[MAXHADDRLEN]; - byte *hap; - char tmpstr[MAXSTRINGLEN]; - u_int tmplen; - unsigned hal; - char *p; - - hal = haddrlength(htype); /* Get length of this address type */ - if (hal <= 0) { - report(LOG_ERR, "Invalid addr type for HW addr parse"); - return NULL; - } - tmplen = sizeof(tmpstr); - get_string(src, tmpstr, &tmplen); - p = tmpstr; - -#if 1 /* XXX - experimental */ - /* If it's a valid host name, try to lookup the HW address. */ - if (goodname(p)) { - /* Lookup Hardware Address for hostname. */ - if ((hap = lookup_hwa(p, htype)) != NULL) - return hap; /* success */ - report(LOG_ERR, "Add 0x prefix if hex value starts with A-F"); - /* OK, assume it must be numeric. */ - } -#endif - - hap = haddr; - while (hap < haddr + hal) { - if (*p == '.') - p++; - if (interp_byte(&p, hap++) < 0) { - return NULL; - } - } - return haddr; -} - - - -/* - * "src" is a pointer to a character pointer which in turn points to a - * hexadecimal ASCII representation of a byte. This byte is read, the - * character pointer is updated, and the result is deposited into the - * byte pointed to by "retbyte". - * - * The usual '0x' notation is allowed but not required. The number must be - * a two digit hexadecimal number. If the number is invalid, "src" and - * "retbyte" are left untouched and -1 is returned as the function value. - * Successful calls return 0. - */ - -PRIVATE int -interp_byte(src, retbyte) - char **src; - byte *retbyte; -{ - int v; - - if ((*src)[0] == '0' && - ((*src)[1] == 'x' || - (*src)[1] == 'X')) { - (*src) += 2; /* allow 0x for hex, but don't require it */ - } - if (!isxdigit((*src)[0]) || !isxdigit((*src)[1])) { - return -1; - } - if (sscanf(*src, "%2x", &v) != 1) { - return -1; - } - (*src) += 2; - *retbyte = (byte) (v & 0xFF); - return 0; -} - - - -/* - * The parameter "src" points to a character pointer which points to an - * ASCII string representation of an unsigned number. The number is - * returned as an unsigned long and the character pointer is updated to - * point to the first illegal character. - */ - -PRIVATE u_int32 -get_u_long(src) - char **src; -{ - register u_int32 value, base; - char c; - - /* - * Collect number up to first illegal character. Values are specified - * as for C: 0x=hex, 0=octal, other=decimal. - */ - value = 0; - base = 10; - if (**src == '0') { - base = 8; - (*src)++; - } - if (**src == 'x' || **src == 'X') { - base = 16; - (*src)++; - } - while ((c = **src)) { - if (isdigit(c)) { - value = (value * base) + (c - '0'); - (*src)++; - continue; - } - if (base == 16 && isxdigit(c)) { - value = (value << 4) + ((c & ~32) + 10 - 'A'); - (*src)++; - continue; - } - break; - } - return value; -} - - - -/* - * Routines for deletion of data associated with the main data structure. - */ - - -/* - * Frees the entire host data structure given. Does nothing if the passed - * pointer is NULL. - */ - -PRIVATE void -free_host(hmp) - hash_datum *hmp; -{ - struct host *hostptr = (struct host *) hmp; - if (hostptr == NULL) - return; - assert(hostptr->linkcount > 0); - if (--(hostptr->linkcount)) - return; /* Still has references */ - del_iplist(hostptr->cookie_server); - del_iplist(hostptr->domain_server); - del_iplist(hostptr->gateway); - del_iplist(hostptr->impress_server); - del_iplist(hostptr->log_server); - del_iplist(hostptr->lpr_server); - del_iplist(hostptr->name_server); - del_iplist(hostptr->rlp_server); - del_iplist(hostptr->time_server); - del_iplist(hostptr->nis_server); - del_iplist(hostptr->ntp_server); - - /* - * XXX - Add new tags here - * (if the value is an IP list) - */ - - del_string(hostptr->hostname); - del_string(hostptr->homedir); - del_string(hostptr->bootfile); - del_string(hostptr->tftpdir); - del_string(hostptr->root_path); - del_string(hostptr->domain_name); - del_string(hostptr->dump_file); - del_string(hostptr->exten_file); - del_string(hostptr->nis_domain); - -#ifdef YORK_EX_OPTION - del_string(hostptr->exec_file); -#endif - - /* - * XXX - Add new tags here - * (if it is a shared string) - */ - - del_bindata(hostptr->generic); - free((char *) hostptr); -} - - - -/* - * Decrements the linkcount on the given IP address data structure. If the - * linkcount goes to zero, the memory associated with the data is freed. - */ - -PRIVATE void -del_iplist(iplist) - struct in_addr_list *iplist; -{ - if (iplist) { - if (!(--(iplist->linkcount))) { - free((char *) iplist); - } - } -} - - - -/* - * Decrements the linkcount on a string data structure. If the count - * goes to zero, the memory associated with the string is freed. Does - * nothing if the passed pointer is NULL. - */ - -PRIVATE void -del_string(stringptr) - struct shared_string *stringptr; -{ - if (stringptr) { - if (!(--(stringptr->linkcount))) { - free((char *) stringptr); - } - } -} - - - -/* - * Decrements the linkcount on a shared_bindata data structure. If the - * count goes to zero, the memory associated with the data is freed. Does - * nothing if the passed pointer is NULL. - */ - -PRIVATE void -del_bindata(dataptr) - struct shared_bindata *dataptr; -{ - if (dataptr) { - if (!(--(dataptr->linkcount))) { - free((char *) dataptr); - } - } -} - - - - -/* smalloc() -- safe malloc() - * - * Always returns a valid pointer (if it returns at all). The allocated - * memory is initialized to all zeros. If malloc() returns an error, a - * message is printed using the report() function and the program aborts - * with a status of 1. - */ - -PRIVATE char * -smalloc(nbytes) - unsigned nbytes; -{ - char *retvalue; - - retvalue = malloc(nbytes); - if (!retvalue) { - report(LOG_ERR, "malloc() failure -- exiting"); - exit(1); - } - bzero(retvalue, nbytes); - return retvalue; -} - - -/* - * Compare function to determine whether two hardware addresses are - * equivalent. Returns TRUE if "host1" and "host2" are equivalent, FALSE - * otherwise. - * - * This function is used when retrieving elements from the hardware address - * hash table. - */ - -boolean -hwlookcmp(d1, d2) - hash_datum *d1, *d2; -{ - struct host *host1 = (struct host *) d1; - struct host *host2 = (struct host *) d2; - - if (host1->htype != host2->htype) { - return FALSE; - } - if (bcmp(host1->haddr, host2->haddr, haddrlength(host1->htype))) { - return FALSE; - } - return TRUE; -} - - -/* - * Compare function for doing IP address hash table lookup. - */ - -boolean -iplookcmp(d1, d2) - hash_datum *d1, *d2; -{ - struct host *host1 = (struct host *) d1; - struct host *host2 = (struct host *) d2; - - return (host1->iaddr.s_addr == host2->iaddr.s_addr); -} - -/* - * Local Variables: - * tab-width: 4 - * c-indent-level: 4 - * c-argdecl-indent: 4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: -4 - * c-label-offset: -4 - * c-brace-offset: 0 - * End: - */ |