15e9d01f2Sgwr /************************************************************************
25e9d01f2Sgwr Copyright 1988, 1991 by Carnegie Mellon University
35e9d01f2Sgwr
45e9d01f2Sgwr All Rights Reserved
55e9d01f2Sgwr
65e9d01f2Sgwr Permission to use, copy, modify, and distribute this software and its
75e9d01f2Sgwr documentation for any purpose and without fee is hereby granted, provided
85e9d01f2Sgwr that the above copyright notice appear in all copies and that both that
95e9d01f2Sgwr copyright notice and this permission notice appear in supporting
105e9d01f2Sgwr documentation, and that the name of Carnegie Mellon University not be used
115e9d01f2Sgwr in advertising or publicity pertaining to distribution of the software
125e9d01f2Sgwr without specific, written prior permission.
135e9d01f2Sgwr
145e9d01f2Sgwr CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
155e9d01f2Sgwr SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
165e9d01f2Sgwr IN NO EVENT SHALL CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
175e9d01f2Sgwr DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
185e9d01f2Sgwr PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
195e9d01f2Sgwr ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
205e9d01f2Sgwr SOFTWARE.
215e9d01f2Sgwr ************************************************************************/
225e9d01f2Sgwr
239493bb79Slukem #include <sys/cdefs.h>
245e9d01f2Sgwr #ifndef lint
25*fbffadb9Smrg __RCSID("$NetBSD: readfile.c,v 1.21 2019/02/03 03:19:30 mrg Exp $");
265e9d01f2Sgwr #endif
275e9d01f2Sgwr
285e9d01f2Sgwr
295e9d01f2Sgwr /*
305e9d01f2Sgwr * bootpd configuration file reading code.
315e9d01f2Sgwr *
325e9d01f2Sgwr * The routines in this file deal with reading, interpreting, and storing
335e9d01f2Sgwr * the information found in the bootpd configuration file (usually
345e9d01f2Sgwr * /etc/bootptab).
355e9d01f2Sgwr */
365e9d01f2Sgwr
375e9d01f2Sgwr
385e9d01f2Sgwr #include <sys/types.h>
395e9d01f2Sgwr #include <sys/stat.h>
405e9d01f2Sgwr #include <sys/file.h>
415e9d01f2Sgwr #include <sys/time.h>
425e9d01f2Sgwr #include <netinet/in.h>
435e9d01f2Sgwr
443ed4fcf6Skleink #include <errno.h>
455e9d01f2Sgwr #include <stdlib.h>
465e9d01f2Sgwr #include <stdio.h>
475e9d01f2Sgwr #include <string.h>
48be45f4d0Stls #include <strings.h>
4953ec1d71Skleink #include <time.h>
505e9d01f2Sgwr #include <ctype.h>
515e9d01f2Sgwr #include <assert.h>
525e9d01f2Sgwr #include <syslog.h>
535e9d01f2Sgwr
545e9d01f2Sgwr #include "bootp.h"
555e9d01f2Sgwr #include "hash.h"
565e9d01f2Sgwr #include "hwaddr.h"
575e9d01f2Sgwr #include "lookup.h"
585e9d01f2Sgwr #include "readfile.h"
595e9d01f2Sgwr #include "report.h"
605e9d01f2Sgwr #include "tzone.h"
615e9d01f2Sgwr #include "bootpd.h"
625e9d01f2Sgwr
635e9d01f2Sgwr #define HASHTABLESIZE 257 /* Hash table size (prime) */
645e9d01f2Sgwr
655e9d01f2Sgwr /* Non-standard hardware address type (see bootp.h) */
665e9d01f2Sgwr #define HTYPE_DIRECT 0
675e9d01f2Sgwr
685e9d01f2Sgwr /* Error codes returned by eval_symbol: */
695e9d01f2Sgwr #define SUCCESS 0
705e9d01f2Sgwr #define E_END_OF_ENTRY (-1)
715e9d01f2Sgwr #define E_SYNTAX_ERROR (-2)
725e9d01f2Sgwr #define E_UNKNOWN_SYMBOL (-3)
735e9d01f2Sgwr #define E_BAD_IPADDR (-4)
745e9d01f2Sgwr #define E_BAD_HWADDR (-5)
755e9d01f2Sgwr #define E_BAD_LONGWORD (-6)
765e9d01f2Sgwr #define E_BAD_HWATYPE (-7)
775e9d01f2Sgwr #define E_BAD_PATHNAME (-8)
78bcb13babSgwr #define E_BAD_VALUE (-9)
795e9d01f2Sgwr
805e9d01f2Sgwr /* Tag idendities. */
815e9d01f2Sgwr #define SYM_NULL 0
825e9d01f2Sgwr #define SYM_BOOTFILE 1
835e9d01f2Sgwr #define SYM_COOKIE_SERVER 2
845e9d01f2Sgwr #define SYM_DOMAIN_SERVER 3
855e9d01f2Sgwr #define SYM_GATEWAY 4
865e9d01f2Sgwr #define SYM_HWADDR 5
875e9d01f2Sgwr #define SYM_HOMEDIR 6
885e9d01f2Sgwr #define SYM_HTYPE 7
895e9d01f2Sgwr #define SYM_IMPRESS_SERVER 8
905e9d01f2Sgwr #define SYM_IPADDR 9
915e9d01f2Sgwr #define SYM_LOG_SERVER 10
925e9d01f2Sgwr #define SYM_LPR_SERVER 11
935e9d01f2Sgwr #define SYM_NAME_SERVER 12
945e9d01f2Sgwr #define SYM_RLP_SERVER 13
955e9d01f2Sgwr #define SYM_SUBNET_MASK 14
965e9d01f2Sgwr #define SYM_TIME_OFFSET 15
975e9d01f2Sgwr #define SYM_TIME_SERVER 16
985e9d01f2Sgwr #define SYM_VENDOR_MAGIC 17
995e9d01f2Sgwr #define SYM_SIMILAR_ENTRY 18
1005e9d01f2Sgwr #define SYM_NAME_SWITCH 19
1015e9d01f2Sgwr #define SYM_BOOTSIZE 20
1025e9d01f2Sgwr #define SYM_BOOT_SERVER 22
1035e9d01f2Sgwr #define SYM_TFTPDIR 23
1045e9d01f2Sgwr #define SYM_DUMP_FILE 24
1055e9d01f2Sgwr #define SYM_DOMAIN_NAME 25
1065e9d01f2Sgwr #define SYM_SWAP_SERVER 26
1075e9d01f2Sgwr #define SYM_ROOT_PATH 27
1085e9d01f2Sgwr #define SYM_EXTEN_FILE 28
1095e9d01f2Sgwr #define SYM_REPLY_ADDR 29
1105e9d01f2Sgwr #define SYM_NIS_DOMAIN 30 /* RFC 1533 */
1115e9d01f2Sgwr #define SYM_NIS_SERVER 31 /* RFC 1533 */
1125e9d01f2Sgwr #define SYM_NTP_SERVER 32 /* RFC 1533 */
1135e9d01f2Sgwr #define SYM_EXEC_FILE 33 /* YORK_EX_OPTION */
114bcb13babSgwr #define SYM_MSG_SIZE 34
115bcb13babSgwr #define SYM_MIN_WAIT 35
1165e9d01f2Sgwr /* XXX - Add new tags here */
1175e9d01f2Sgwr
1185e9d01f2Sgwr #define OP_ADDITION 1 /* Operations on tags */
1195e9d01f2Sgwr #define OP_DELETION 2
1205e9d01f2Sgwr #define OP_BOOLEAN 3
1215e9d01f2Sgwr
1225e9d01f2Sgwr #define MAXINADDRS 16 /* Max size of an IP address list */
123bcb13babSgwr #define MAXBUFLEN 256 /* Max temp buffer space */
1245e9d01f2Sgwr #define MAXENTRYLEN 2048 /* Max size of an entire entry */
1255e9d01f2Sgwr
1265e9d01f2Sgwr
1275e9d01f2Sgwr
1285e9d01f2Sgwr /*
1295e9d01f2Sgwr * Structure used to map a configuration-file symbol (such as "ds") to a
1305e9d01f2Sgwr * unique integer.
1315e9d01f2Sgwr */
1325e9d01f2Sgwr
1335e9d01f2Sgwr struct symbolmap {
134c8f61d2bSxtraeme const char *symbol;
1355e9d01f2Sgwr int symbolcode;
1365e9d01f2Sgwr };
1375e9d01f2Sgwr
1385e9d01f2Sgwr
1395e9d01f2Sgwr struct htypename {
140c8f61d2bSxtraeme const char *name;
1415e9d01f2Sgwr byte htype;
1425e9d01f2Sgwr };
1435e9d01f2Sgwr
1445e9d01f2Sgwr
1455e9d01f2Sgwr PRIVATE int nhosts; /* Number of hosts (/w hw or IP address) */
1465e9d01f2Sgwr PRIVATE int nentries; /* Total number of entries */
1475e9d01f2Sgwr PRIVATE int32 modtime = 0; /* Last modification time of bootptab */
1485e9d01f2Sgwr PRIVATE char *current_hostname; /* Name of the current entry. */
1495e9d01f2Sgwr PRIVATE char current_tagname[8];
1505e9d01f2Sgwr
1515e9d01f2Sgwr /*
1525e9d01f2Sgwr * List of symbolic names used in the bootptab file. The order and actual
1535e9d01f2Sgwr * values of the symbol codes (SYM_. . .) are unimportant, but they must
1545e9d01f2Sgwr * all be unique.
1555e9d01f2Sgwr */
1565e9d01f2Sgwr
1575e9d01f2Sgwr PRIVATE struct symbolmap symbol_list[] = {
1585e9d01f2Sgwr {"bf", SYM_BOOTFILE},
1595e9d01f2Sgwr {"bs", SYM_BOOTSIZE},
1605e9d01f2Sgwr {"cs", SYM_COOKIE_SERVER},
1615e9d01f2Sgwr {"df", SYM_DUMP_FILE},
1625e9d01f2Sgwr {"dn", SYM_DOMAIN_NAME},
1635e9d01f2Sgwr {"ds", SYM_DOMAIN_SERVER},
1645e9d01f2Sgwr {"ef", SYM_EXTEN_FILE},
1655e9d01f2Sgwr {"ex", SYM_EXEC_FILE}, /* YORK_EX_OPTION */
1665e9d01f2Sgwr {"gw", SYM_GATEWAY},
1675e9d01f2Sgwr {"ha", SYM_HWADDR},
1685e9d01f2Sgwr {"hd", SYM_HOMEDIR},
1695e9d01f2Sgwr {"hn", SYM_NAME_SWITCH},
1705e9d01f2Sgwr {"ht", SYM_HTYPE},
1715e9d01f2Sgwr {"im", SYM_IMPRESS_SERVER},
1725e9d01f2Sgwr {"ip", SYM_IPADDR},
1735e9d01f2Sgwr {"lg", SYM_LOG_SERVER},
1745e9d01f2Sgwr {"lp", SYM_LPR_SERVER},
175bcb13babSgwr {"ms", SYM_MSG_SIZE},
176bcb13babSgwr {"mw", SYM_MIN_WAIT},
1775e9d01f2Sgwr {"ns", SYM_NAME_SERVER},
1785e9d01f2Sgwr {"nt", SYM_NTP_SERVER},
1795e9d01f2Sgwr {"ra", SYM_REPLY_ADDR},
1805e9d01f2Sgwr {"rl", SYM_RLP_SERVER},
1815e9d01f2Sgwr {"rp", SYM_ROOT_PATH},
1825e9d01f2Sgwr {"sa", SYM_BOOT_SERVER},
1835e9d01f2Sgwr {"sm", SYM_SUBNET_MASK},
1845e9d01f2Sgwr {"sw", SYM_SWAP_SERVER},
1855e9d01f2Sgwr {"tc", SYM_SIMILAR_ENTRY},
1865e9d01f2Sgwr {"td", SYM_TFTPDIR},
1875e9d01f2Sgwr {"to", SYM_TIME_OFFSET},
1885e9d01f2Sgwr {"ts", SYM_TIME_SERVER},
1895e9d01f2Sgwr {"vm", SYM_VENDOR_MAGIC},
1905e9d01f2Sgwr {"yd", SYM_NIS_DOMAIN},
1915e9d01f2Sgwr {"ys", SYM_NIS_SERVER},
1925e9d01f2Sgwr /* XXX - Add new tags here */
1935e9d01f2Sgwr };
1945e9d01f2Sgwr
1955e9d01f2Sgwr
1965e9d01f2Sgwr /*
1975e9d01f2Sgwr * List of symbolic names for hardware types. Name translates into
1985e9d01f2Sgwr * hardware type code listed with it. Names must begin with a letter
1995e9d01f2Sgwr * and must be all lowercase. This is searched linearly, so put
2005e9d01f2Sgwr * commonly-used entries near the beginning.
2015e9d01f2Sgwr */
2025e9d01f2Sgwr
2035e9d01f2Sgwr PRIVATE struct htypename htnamemap[] = {
2045e9d01f2Sgwr {"ethernet", HTYPE_ETHERNET},
2055e9d01f2Sgwr {"ethernet3", HTYPE_EXP_ETHERNET},
2065e9d01f2Sgwr {"ether", HTYPE_ETHERNET},
2075e9d01f2Sgwr {"ether3", HTYPE_EXP_ETHERNET},
2085e9d01f2Sgwr {"ieee802", HTYPE_IEEE802},
2095e9d01f2Sgwr {"tr", HTYPE_IEEE802},
2105e9d01f2Sgwr {"token-ring", HTYPE_IEEE802},
2115e9d01f2Sgwr {"pronet", HTYPE_PRONET},
2125e9d01f2Sgwr {"chaos", HTYPE_CHAOS},
2135e9d01f2Sgwr {"arcnet", HTYPE_ARCNET},
2145e9d01f2Sgwr {"ax.25", HTYPE_AX25},
2155e9d01f2Sgwr {"direct", HTYPE_DIRECT},
2165e9d01f2Sgwr {"serial", HTYPE_DIRECT},
2175e9d01f2Sgwr {"slip", HTYPE_DIRECT},
2185e9d01f2Sgwr {"ppp", HTYPE_DIRECT}
2195e9d01f2Sgwr };
2205e9d01f2Sgwr
2215e9d01f2Sgwr
2225e9d01f2Sgwr
2235e9d01f2Sgwr /*
2245e9d01f2Sgwr * Externals and forward declarations.
2255e9d01f2Sgwr */
2265e9d01f2Sgwr
227131109e4Swiz boolean nmcmp(hash_datum *, hash_datum *);
2285e9d01f2Sgwr
2295e9d01f2Sgwr PRIVATE void
230131109e4Swiz adjust(char **);
2315e9d01f2Sgwr PRIVATE void
232131109e4Swiz del_string(struct shared_string *);
2335e9d01f2Sgwr PRIVATE void
234131109e4Swiz del_bindata(struct shared_bindata *);
2355e9d01f2Sgwr PRIVATE void
236131109e4Swiz del_iplist(struct in_addr_list *);
2375e9d01f2Sgwr PRIVATE void
238131109e4Swiz eat_whitespace(char **);
2395e9d01f2Sgwr PRIVATE int
240131109e4Swiz eval_symbol(char **, struct host *);
2415e9d01f2Sgwr PRIVATE void
242131109e4Swiz fill_defaults(struct host *, char **);
2435e9d01f2Sgwr PRIVATE void
244131109e4Swiz free_host(hash_datum *);
2455e9d01f2Sgwr PRIVATE struct in_addr_list *
246131109e4Swiz get_addresses(char **);
2475e9d01f2Sgwr PRIVATE struct shared_string *
248131109e4Swiz get_shared_string(char **);
2495e9d01f2Sgwr PRIVATE char *
250131109e4Swiz get_string(char **, char *, u_int *);
2515e9d01f2Sgwr PRIVATE u_int32
252131109e4Swiz get_u_long(char **);
2535e9d01f2Sgwr PRIVATE boolean
254131109e4Swiz goodname(char *);
2555e9d01f2Sgwr PRIVATE boolean
256131109e4Swiz hwinscmp(hash_datum *, hash_datum *);
2575e9d01f2Sgwr PRIVATE int
258131109e4Swiz interp_byte(char **, byte *);
2595e9d01f2Sgwr PRIVATE void
260131109e4Swiz makelower(char *);
2615e9d01f2Sgwr PRIVATE boolean
262131109e4Swiz nullcmp(hash_datum *, hash_datum *);
2635e9d01f2Sgwr PRIVATE int
264131109e4Swiz process_entry(struct host *, char *);
2655e9d01f2Sgwr PRIVATE int
266131109e4Swiz process_generic(char **, struct shared_bindata **, u_int);
2675e9d01f2Sgwr PRIVATE byte *
268131109e4Swiz prs_haddr(char **, u_int);
2695e9d01f2Sgwr PRIVATE int
270131109e4Swiz prs_inetaddr(char **, u_int32 *);
2715e9d01f2Sgwr PRIVATE void
272131109e4Swiz read_entry(FILE *, char *, u_int *);
2735e9d01f2Sgwr PRIVATE char *
274131109e4Swiz smalloc(u_int);
2755e9d01f2Sgwr
2765e9d01f2Sgwr
2775e9d01f2Sgwr
2785e9d01f2Sgwr /*
2795e9d01f2Sgwr * Vendor magic cookies for CMU and RFC1048
2805e9d01f2Sgwr */
2815e9d01f2Sgwr u_char vm_cmu[4] = VM_CMU;
2825e9d01f2Sgwr u_char vm_rfc1048[4] = VM_RFC1048;
2835e9d01f2Sgwr
2845e9d01f2Sgwr /*
2855e9d01f2Sgwr * Main hash tables
2865e9d01f2Sgwr */
2875e9d01f2Sgwr hash_tbl *hwhashtable;
2885e9d01f2Sgwr hash_tbl *iphashtable;
2895e9d01f2Sgwr hash_tbl *nmhashtable;
2905e9d01f2Sgwr
2915e9d01f2Sgwr /*
2925e9d01f2Sgwr * Allocate hash tables for hardware address, ip address, and hostname
2935e9d01f2Sgwr * (shared by bootpd and bootpef)
2945e9d01f2Sgwr */
2955e9d01f2Sgwr void
rdtab_init(void)296131109e4Swiz rdtab_init(void)
2975e9d01f2Sgwr {
2985e9d01f2Sgwr hwhashtable = hash_Init(HASHTABLESIZE);
2995e9d01f2Sgwr iphashtable = hash_Init(HASHTABLESIZE);
3005e9d01f2Sgwr nmhashtable = hash_Init(HASHTABLESIZE);
3015e9d01f2Sgwr if (!(hwhashtable && iphashtable && nmhashtable)) {
3025e9d01f2Sgwr report(LOG_ERR, "Unable to allocate hash tables.");
3035e9d01f2Sgwr exit(1);
3045e9d01f2Sgwr }
3055e9d01f2Sgwr }
3065e9d01f2Sgwr
3075e9d01f2Sgwr
3085e9d01f2Sgwr /*
3095e9d01f2Sgwr * Read bootptab database file. Avoid rereading the file if the
3105e9d01f2Sgwr * write date hasn't changed since the last time we read it.
3115e9d01f2Sgwr */
3125e9d01f2Sgwr
3135e9d01f2Sgwr void
readtab(int force)314131109e4Swiz readtab(int force)
3155e9d01f2Sgwr {
3165e9d01f2Sgwr struct host *hp;
3175e9d01f2Sgwr FILE *fp;
3185e9d01f2Sgwr struct stat st;
3195e9d01f2Sgwr unsigned hashcode, buflen;
3205e9d01f2Sgwr static char buffer[MAXENTRYLEN];
3215e9d01f2Sgwr
3225e9d01f2Sgwr /*
3235e9d01f2Sgwr * Check the last modification time.
3245e9d01f2Sgwr */
3255e9d01f2Sgwr if (stat(bootptab, &st) < 0) {
3265e9d01f2Sgwr report(LOG_ERR, "stat on \"%s\": %s",
3275e9d01f2Sgwr bootptab, get_errmsg());
3285e9d01f2Sgwr return;
3295e9d01f2Sgwr }
3305e9d01f2Sgwr #ifdef DEBUG
3315e9d01f2Sgwr if (debug > 3) {
3325e9d01f2Sgwr char timestr[28];
3335402d14cSitojun strlcpy(timestr, ctime(&(st.st_mtime)), sizeof(timestr));
3345e9d01f2Sgwr /* zap the newline */
3355e9d01f2Sgwr timestr[24] = '\0';
3365e9d01f2Sgwr report(LOG_INFO, "bootptab mtime: %s",
3375e9d01f2Sgwr timestr);
3385e9d01f2Sgwr }
3395e9d01f2Sgwr #endif
3405e9d01f2Sgwr if ((force == 0) &&
3415e9d01f2Sgwr (st.st_mtime == modtime) &&
3425e9d01f2Sgwr st.st_nlink) {
3435e9d01f2Sgwr /*
3445e9d01f2Sgwr * hasn't been modified or deleted yet.
3455e9d01f2Sgwr */
3465e9d01f2Sgwr return;
3475e9d01f2Sgwr }
3485e9d01f2Sgwr if (debug)
3495e9d01f2Sgwr report(LOG_INFO, "reading %s\"%s\"",
3505e9d01f2Sgwr (modtime != 0L) ? "new " : "",
3515e9d01f2Sgwr bootptab);
3525e9d01f2Sgwr
3535e9d01f2Sgwr /*
3545e9d01f2Sgwr * Open bootptab file.
3555e9d01f2Sgwr */
3565e9d01f2Sgwr if ((fp = fopen(bootptab, "r")) == NULL) {
3575e9d01f2Sgwr report(LOG_ERR, "error opening \"%s\": %s", bootptab, get_errmsg());
3585e9d01f2Sgwr return;
3595e9d01f2Sgwr }
3605e9d01f2Sgwr /*
3615e9d01f2Sgwr * Record file modification time.
3625e9d01f2Sgwr */
3635e9d01f2Sgwr if (fstat(fileno(fp), &st) < 0) {
3645e9d01f2Sgwr report(LOG_ERR, "fstat: %s", get_errmsg());
3655e9d01f2Sgwr fclose(fp);
3665e9d01f2Sgwr return;
3675e9d01f2Sgwr }
3685e9d01f2Sgwr modtime = st.st_mtime;
3695e9d01f2Sgwr
3705e9d01f2Sgwr /*
3715e9d01f2Sgwr * Entirely erase all hash tables.
3725e9d01f2Sgwr */
3735e9d01f2Sgwr hash_Reset(hwhashtable, free_host);
3745e9d01f2Sgwr hash_Reset(iphashtable, free_host);
3755e9d01f2Sgwr hash_Reset(nmhashtable, free_host);
3765e9d01f2Sgwr
3775e9d01f2Sgwr nhosts = 0;
3785e9d01f2Sgwr nentries = 0;
3795e9d01f2Sgwr while (TRUE) {
3805e9d01f2Sgwr buflen = sizeof(buffer);
3815e9d01f2Sgwr read_entry(fp, buffer, &buflen);
3825e9d01f2Sgwr if (buflen == 0) { /* More entries? */
3835e9d01f2Sgwr break;
3845e9d01f2Sgwr }
3855e9d01f2Sgwr hp = (struct host *) smalloc(sizeof(struct host));
3865e9d01f2Sgwr bzero((char *) hp, sizeof(*hp));
3875e9d01f2Sgwr /* the link count it zero */
3885e9d01f2Sgwr
3895e9d01f2Sgwr /*
3905e9d01f2Sgwr * Get individual info
3915e9d01f2Sgwr */
3925e9d01f2Sgwr if (process_entry(hp, buffer) < 0) {
3935e9d01f2Sgwr hp->linkcount = 1;
3945e9d01f2Sgwr free_host((hash_datum *) hp);
3955e9d01f2Sgwr continue;
3965e9d01f2Sgwr }
3975e9d01f2Sgwr /*
3985e9d01f2Sgwr * If this is not a dummy entry, and the IP or HW
3995e9d01f2Sgwr * address is not yet set, try to get them here.
4005e9d01f2Sgwr * Dummy entries have . as first char of name.
4015e9d01f2Sgwr */
4025e9d01f2Sgwr if (goodname(hp->hostname->string)) {
4035e9d01f2Sgwr char *hn = hp->hostname->string;
4045e9d01f2Sgwr u_int32 value;
4055e9d01f2Sgwr if (hp->flags.iaddr == 0) {
4065e9d01f2Sgwr if (lookup_ipa(hn, &value)) {
4075e9d01f2Sgwr report(LOG_ERR, "can not get IP addr for %s", hn);
4085e9d01f2Sgwr report(LOG_ERR, "(dummy names should start with '.')");
4095e9d01f2Sgwr } else {
4105e9d01f2Sgwr hp->iaddr.s_addr = value;
4115e9d01f2Sgwr hp->flags.iaddr = TRUE;
4125e9d01f2Sgwr }
4135e9d01f2Sgwr }
4145e9d01f2Sgwr /* Set default subnet mask. */
4155e9d01f2Sgwr if (hp->flags.subnet_mask == 0) {
4165e9d01f2Sgwr if (lookup_netmask(hp->iaddr.s_addr, &value)) {
4175e9d01f2Sgwr report(LOG_ERR, "can not get netmask for %s", hn);
4185e9d01f2Sgwr } else {
4195e9d01f2Sgwr hp->subnet_mask.s_addr = value;
4205e9d01f2Sgwr hp->flags.subnet_mask = TRUE;
4215e9d01f2Sgwr }
4225e9d01f2Sgwr }
4235e9d01f2Sgwr }
4245e9d01f2Sgwr if (hp->flags.iaddr) {
4255e9d01f2Sgwr nhosts++;
4265e9d01f2Sgwr }
4275e9d01f2Sgwr /* Register by HW addr if known. */
4285e9d01f2Sgwr if (hp->flags.htype && hp->flags.haddr) {
4295e9d01f2Sgwr /* We will either insert it or free it. */
4305e9d01f2Sgwr hp->linkcount++;
4315e9d01f2Sgwr hashcode = hash_HashFunction(hp->haddr, haddrlength(hp->htype));
4325e9d01f2Sgwr if (hash_Insert(hwhashtable, hashcode, hwinscmp, hp, hp) < 0) {
4335e9d01f2Sgwr report(LOG_NOTICE, "duplicate %s address: %s",
4345e9d01f2Sgwr netname(hp->htype),
4352a645560Sgwr haddrtoa(hp->haddr, haddrlength(hp->htype)));
4365e9d01f2Sgwr free_host((hash_datum *) hp);
4375e9d01f2Sgwr continue;
4385e9d01f2Sgwr }
4395e9d01f2Sgwr }
4405e9d01f2Sgwr /* Register by IP addr if known. */
4415e9d01f2Sgwr if (hp->flags.iaddr) {
4425e9d01f2Sgwr hashcode = hash_HashFunction((u_char *) & (hp->iaddr.s_addr), 4);
4435e9d01f2Sgwr if (hash_Insert(iphashtable, hashcode, nullcmp, hp, hp) < 0) {
4445e9d01f2Sgwr report(LOG_ERR,
4455e9d01f2Sgwr "hash_Insert() failed on IP address insertion");
4465e9d01f2Sgwr } else {
4475e9d01f2Sgwr /* Just inserted the host struct in a new hash list. */
4485e9d01f2Sgwr hp->linkcount++;
4495e9d01f2Sgwr }
4505e9d01f2Sgwr }
4515e9d01f2Sgwr /* Register by Name (always known) */
4525e9d01f2Sgwr hashcode = hash_HashFunction((u_char *) hp->hostname->string,
4535e9d01f2Sgwr strlen(hp->hostname->string));
4545e9d01f2Sgwr if (hash_Insert(nmhashtable, hashcode, nullcmp,
4555e9d01f2Sgwr hp->hostname->string, hp) < 0) {
4565e9d01f2Sgwr report(LOG_ERR,
4575e9d01f2Sgwr "hash_Insert() failed on insertion of hostname: \"%s\"",
4585e9d01f2Sgwr hp->hostname->string);
4595e9d01f2Sgwr } else {
4605e9d01f2Sgwr /* Just inserted the host struct in a new hash list. */
4615e9d01f2Sgwr hp->linkcount++;
4625e9d01f2Sgwr }
4635e9d01f2Sgwr
4645e9d01f2Sgwr nentries++;
4655e9d01f2Sgwr }
4665e9d01f2Sgwr
4675e9d01f2Sgwr fclose(fp);
4685e9d01f2Sgwr if (debug)
4695e9d01f2Sgwr report(LOG_INFO, "read %d entries (%d hosts) from \"%s\"",
4705e9d01f2Sgwr nentries, nhosts, bootptab);
4715e9d01f2Sgwr return;
4725e9d01f2Sgwr }
4735e9d01f2Sgwr
4745e9d01f2Sgwr
4755e9d01f2Sgwr
4765e9d01f2Sgwr /*
4775e9d01f2Sgwr * Read an entire host entry from the file pointed to by "fp" and insert it
4785e9d01f2Sgwr * into the memory pointed to by "buffer". Leading whitespace and comments
4795e9d01f2Sgwr * starting with "#" are ignored (removed). Backslashes (\) always quote
4801e378c4cSwiz * the next character except that newlines preceded by a backslash cause
4815e9d01f2Sgwr * line-continuation onto the next line. The entry is terminated by a
4821e378c4cSwiz * newline character which is not preceded by a backslash. Sequences
4835e9d01f2Sgwr * surrounded by double quotes are taken literally (including newlines, but
4845e9d01f2Sgwr * not backslashes).
4855e9d01f2Sgwr *
4865e9d01f2Sgwr * The "bufsiz" parameter points to an unsigned int which specifies the
4875e9d01f2Sgwr * maximum permitted buffer size. Upon return, this value will be replaced
4885e9d01f2Sgwr * with the actual length of the entry (not including the null terminator).
4895e9d01f2Sgwr *
4905e9d01f2Sgwr * This code is a little scary. . . . I don't like using gotos in C
4915e9d01f2Sgwr * either, but I first wrote this as an FSM diagram and gotos seemed like
4925e9d01f2Sgwr * the easiest way to implement it. Maybe later I'll clean it up.
4935e9d01f2Sgwr */
4945e9d01f2Sgwr
4955e9d01f2Sgwr PRIVATE void
read_entry(FILE * fp,char * buffer,unsigned int * bufsiz)496131109e4Swiz read_entry(FILE *fp, char *buffer, unsigned int *bufsiz)
4975e9d01f2Sgwr {
4987affd655Slukem int c;
4997affd655Slukem unsigned int length;
5005e9d01f2Sgwr
5015e9d01f2Sgwr length = 0;
5025e9d01f2Sgwr
5035e9d01f2Sgwr /*
5045e9d01f2Sgwr * Eat whitespace, blank lines, and comment lines.
5055e9d01f2Sgwr */
5065e9d01f2Sgwr top:
5075e9d01f2Sgwr c = fgetc(fp);
5085e9d01f2Sgwr if (c < 0) {
5095e9d01f2Sgwr goto done; /* Exit if end-of-file */
5105e9d01f2Sgwr }
5115e9d01f2Sgwr if (isspace(c)) {
5125e9d01f2Sgwr goto top; /* Skip over whitespace */
5135e9d01f2Sgwr }
5145e9d01f2Sgwr if (c == '#') {
5155e9d01f2Sgwr while (TRUE) { /* Eat comments after # */
5165e9d01f2Sgwr c = fgetc(fp);
5175e9d01f2Sgwr if (c < 0) {
5185e9d01f2Sgwr goto done; /* Exit if end-of-file */
5195e9d01f2Sgwr }
5205e9d01f2Sgwr if (c == '\n') {
5215e9d01f2Sgwr goto top; /* Try to read the next line */
5225e9d01f2Sgwr }
5235e9d01f2Sgwr }
5245e9d01f2Sgwr }
5255e9d01f2Sgwr ungetc(c, fp); /* Other character, push it back to reprocess it */
5265e9d01f2Sgwr
5275e9d01f2Sgwr
5285e9d01f2Sgwr /*
5295e9d01f2Sgwr * Now we're actually reading a data entry. Get each character and
5305e9d01f2Sgwr * assemble it into the data buffer, processing special characters like
5315e9d01f2Sgwr * double quotes (") and backslashes (\).
5325e9d01f2Sgwr */
5335e9d01f2Sgwr
5345e9d01f2Sgwr mainloop:
5355e9d01f2Sgwr c = fgetc(fp);
5365e9d01f2Sgwr switch (c) {
5375e9d01f2Sgwr case EOF:
5385e9d01f2Sgwr case '\n':
5395e9d01f2Sgwr goto done; /* Exit on EOF or newline */
5405e9d01f2Sgwr case '\\':
5415e9d01f2Sgwr c = fgetc(fp); /* Backslash, read a new character */
5425e9d01f2Sgwr if (c < 0) {
5435e9d01f2Sgwr goto done; /* Exit on EOF */
5445e9d01f2Sgwr }
5455e9d01f2Sgwr *buffer++ = c; /* Store the literal character */
5465e9d01f2Sgwr length++;
5475e9d01f2Sgwr if (length < *bufsiz - 1) {
5485e9d01f2Sgwr goto mainloop;
5495e9d01f2Sgwr } else {
5505e9d01f2Sgwr goto done;
5515e9d01f2Sgwr }
5525e9d01f2Sgwr case '"':
5535e9d01f2Sgwr *buffer++ = '"'; /* Store double-quote */
5545e9d01f2Sgwr length++;
5555e9d01f2Sgwr if (length >= *bufsiz - 1) {
5565e9d01f2Sgwr goto done;
5575e9d01f2Sgwr }
5585e9d01f2Sgwr while (TRUE) { /* Special quote processing loop */
5595e9d01f2Sgwr c = fgetc(fp);
5605e9d01f2Sgwr switch (c) {
5615e9d01f2Sgwr case EOF:
5625e9d01f2Sgwr goto done; /* Exit on EOF . . . */
5635e9d01f2Sgwr case '"':
5645e9d01f2Sgwr *buffer++ = '"';/* Store matching quote */
5655e9d01f2Sgwr length++;
5665e9d01f2Sgwr if (length < *bufsiz - 1) {
5675e9d01f2Sgwr goto mainloop; /* And continue main loop */
5685e9d01f2Sgwr } else {
5695e9d01f2Sgwr goto done;
5705e9d01f2Sgwr }
5715e9d01f2Sgwr case '\\':
5725e9d01f2Sgwr if ((c = fgetc(fp)) < 0) { /* Backslash */
5735e9d01f2Sgwr goto done; /* EOF. . . .*/
5745e9d01f2Sgwr } /* else fall through */
5755e9d01f2Sgwr default:
5765e9d01f2Sgwr *buffer++ = c; /* Other character, store it */
5775e9d01f2Sgwr length++;
5785e9d01f2Sgwr if (length >= *bufsiz - 1) {
5795e9d01f2Sgwr goto done;
5805e9d01f2Sgwr }
5815e9d01f2Sgwr }
5825e9d01f2Sgwr }
5835e9d01f2Sgwr case ':':
5845e9d01f2Sgwr *buffer++ = c; /* Store colons */
5855e9d01f2Sgwr length++;
5865e9d01f2Sgwr if (length >= *bufsiz - 1) {
5875e9d01f2Sgwr goto done;
5885e9d01f2Sgwr }
5895e9d01f2Sgwr do { /* But remove whitespace after them */
5905e9d01f2Sgwr c = fgetc(fp);
5915e9d01f2Sgwr if ((c < 0) || (c == '\n')) {
5925e9d01f2Sgwr goto done;
5935e9d01f2Sgwr }
5945e9d01f2Sgwr } while (isspace(c)); /* Skip whitespace */
5955e9d01f2Sgwr
5965e9d01f2Sgwr if (c == '\\') { /* Backslash quotes next character */
5975e9d01f2Sgwr c = fgetc(fp);
5985e9d01f2Sgwr if (c < 0) {
5995e9d01f2Sgwr goto done;
6005e9d01f2Sgwr }
6015e9d01f2Sgwr if (c == '\n') {
6025e9d01f2Sgwr goto top; /* Backslash-newline continuation */
6035e9d01f2Sgwr }
6045e9d01f2Sgwr }
6055e9d01f2Sgwr /* fall through if "other" character */
606*fbffadb9Smrg /* FALLTHROUGH */
6075e9d01f2Sgwr default:
6085e9d01f2Sgwr *buffer++ = c; /* Store other characters */
6095e9d01f2Sgwr length++;
6105e9d01f2Sgwr if (length >= *bufsiz - 1) {
6115e9d01f2Sgwr goto done;
6125e9d01f2Sgwr }
6135e9d01f2Sgwr }
6145e9d01f2Sgwr goto mainloop; /* Keep going */
6155e9d01f2Sgwr
6165e9d01f2Sgwr done:
6175e9d01f2Sgwr *buffer = '\0'; /* Terminate string */
6185e9d01f2Sgwr *bufsiz = length; /* Tell the caller its length */
6195e9d01f2Sgwr }
6205e9d01f2Sgwr
6215e9d01f2Sgwr
6225e9d01f2Sgwr
6235e9d01f2Sgwr /*
6245e9d01f2Sgwr * Parse out all the various tags and parameters in the host entry pointed
6255e9d01f2Sgwr * to by "src". Stuff all the data into the appropriate fields of the
6265e9d01f2Sgwr * host structure pointed to by "host". If there is any problem with the
6275e9d01f2Sgwr * entry, an error message is reported via report(), no further processing
6285e9d01f2Sgwr * is done, and -1 is returned. Successful calls return 0.
6295e9d01f2Sgwr *
6305e9d01f2Sgwr * (Some errors probably shouldn't be so completely fatal. . . .)
6315e9d01f2Sgwr */
6325e9d01f2Sgwr
6335e9d01f2Sgwr PRIVATE int
process_entry(struct host * host,char * src)634131109e4Swiz process_entry(struct host *host, char *src)
6355e9d01f2Sgwr {
6365e9d01f2Sgwr int retval;
637c8f61d2bSxtraeme const char *msg;
6385e9d01f2Sgwr
6395e9d01f2Sgwr if (!host || *src == '\0') {
6405e9d01f2Sgwr return -1;
6415e9d01f2Sgwr }
6425e9d01f2Sgwr host->hostname = get_shared_string(&src);
6435e9d01f2Sgwr #if 0
6445e9d01f2Sgwr /* Be more liberal for the benefit of dummy tag names. */
6455e9d01f2Sgwr if (!goodname(host->hostname->string)) {
6465e9d01f2Sgwr report(LOG_ERR, "bad hostname: \"%s\"", host->hostname->string);
6475e9d01f2Sgwr del_string(host->hostname);
6485e9d01f2Sgwr return -1;
6495e9d01f2Sgwr }
6505e9d01f2Sgwr #endif
6515e9d01f2Sgwr current_hostname = host->hostname->string;
6525e9d01f2Sgwr adjust(&src);
6535e9d01f2Sgwr while (TRUE) {
6545e9d01f2Sgwr retval = eval_symbol(&src, host);
6555e9d01f2Sgwr if (retval == SUCCESS) {
6565e9d01f2Sgwr adjust(&src);
6575e9d01f2Sgwr continue;
6585e9d01f2Sgwr }
6595e9d01f2Sgwr if (retval == E_END_OF_ENTRY) {
6605e9d01f2Sgwr /* The default subnet mask is set in readtab() */
6615e9d01f2Sgwr return 0;
6625e9d01f2Sgwr }
6635e9d01f2Sgwr /* Some kind of error. */
6645e9d01f2Sgwr switch (retval) {
6655e9d01f2Sgwr case E_SYNTAX_ERROR:
6665e9d01f2Sgwr msg = "bad syntax";
6675e9d01f2Sgwr break;
6685e9d01f2Sgwr case E_UNKNOWN_SYMBOL:
6695e9d01f2Sgwr msg = "unknown symbol";
6705e9d01f2Sgwr break;
6715e9d01f2Sgwr case E_BAD_IPADDR:
6725e9d01f2Sgwr msg = "bad INET address";
6735e9d01f2Sgwr break;
6745e9d01f2Sgwr case E_BAD_HWADDR:
6755e9d01f2Sgwr msg = "bad hardware address";
6765e9d01f2Sgwr break;
6775e9d01f2Sgwr case E_BAD_LONGWORD:
6785e9d01f2Sgwr msg = "bad longword value";
6795e9d01f2Sgwr break;
6805e9d01f2Sgwr case E_BAD_HWATYPE:
6815e9d01f2Sgwr msg = "bad HW address type";
6825e9d01f2Sgwr break;
6835e9d01f2Sgwr case E_BAD_PATHNAME:
6845e9d01f2Sgwr msg = "bad pathname (need leading '/')";
6857e975aafSwiz break;
686bcb13babSgwr case E_BAD_VALUE:
687bcb13babSgwr msg = "bad value";
6887e975aafSwiz break;
6895e9d01f2Sgwr default:
6907bd6fd35Swiz msg = "unknown error";
6915e9d01f2Sgwr break;
6925e9d01f2Sgwr } /* switch */
6935e9d01f2Sgwr report(LOG_ERR, "in entry named \"%s\", symbol \"%s\": %s",
6945e9d01f2Sgwr current_hostname, current_tagname, msg);
6955e9d01f2Sgwr return -1;
6965e9d01f2Sgwr }
6975e9d01f2Sgwr }
6985e9d01f2Sgwr
6995e9d01f2Sgwr
7005e9d01f2Sgwr /*
7015e9d01f2Sgwr * Macros for use in the function below:
7025e9d01f2Sgwr */
7035e9d01f2Sgwr
7045e9d01f2Sgwr /* Parse one INET address stored directly in MEMBER. */
7055e9d01f2Sgwr #define PARSE_IA1(MEMBER) do \
7065e9d01f2Sgwr { \
7075e9d01f2Sgwr if (optype == OP_BOOLEAN) \
7085e9d01f2Sgwr return E_SYNTAX_ERROR; \
7095e9d01f2Sgwr hp->flags.MEMBER = FALSE; \
7105e9d01f2Sgwr if (optype == OP_ADDITION) { \
7115e9d01f2Sgwr if (prs_inetaddr(symbol, &value) < 0) \
7125e9d01f2Sgwr return E_BAD_IPADDR; \
7135e9d01f2Sgwr hp->MEMBER.s_addr = value; \
7145e9d01f2Sgwr hp->flags.MEMBER = TRUE; \
7155e9d01f2Sgwr } \
7165e9d01f2Sgwr } while (0)
7175e9d01f2Sgwr
7185e9d01f2Sgwr /* Parse a list of INET addresses pointed to by MEMBER */
7195e9d01f2Sgwr #define PARSE_IAL(MEMBER) do \
7205e9d01f2Sgwr { \
7215e9d01f2Sgwr if (optype == OP_BOOLEAN) \
7225e9d01f2Sgwr return E_SYNTAX_ERROR; \
7235e9d01f2Sgwr if (hp->flags.MEMBER) { \
7245e9d01f2Sgwr hp->flags.MEMBER = FALSE; \
7255e9d01f2Sgwr assert(hp->MEMBER); \
7265e9d01f2Sgwr del_iplist(hp->MEMBER); \
7275e9d01f2Sgwr hp->MEMBER = NULL; \
7285e9d01f2Sgwr } \
7295e9d01f2Sgwr if (optype == OP_ADDITION) { \
7305e9d01f2Sgwr hp->MEMBER = get_addresses(symbol); \
7315e9d01f2Sgwr if (hp->MEMBER == NULL) \
7325e9d01f2Sgwr return E_SYNTAX_ERROR; \
7335e9d01f2Sgwr hp->flags.MEMBER = TRUE; \
7345e9d01f2Sgwr } \
7355e9d01f2Sgwr } while (0)
7365e9d01f2Sgwr
7375e9d01f2Sgwr /* Parse a shared string pointed to by MEMBER */
7385e9d01f2Sgwr #define PARSE_STR(MEMBER) do \
7395e9d01f2Sgwr { \
7405e9d01f2Sgwr if (optype == OP_BOOLEAN) \
7415e9d01f2Sgwr return E_SYNTAX_ERROR; \
7425e9d01f2Sgwr if (hp->flags.MEMBER) { \
7435e9d01f2Sgwr hp->flags.MEMBER = FALSE; \
7445e9d01f2Sgwr assert(hp->MEMBER); \
7455e9d01f2Sgwr del_string(hp->MEMBER); \
7465e9d01f2Sgwr hp->MEMBER = NULL; \
7475e9d01f2Sgwr } \
7485e9d01f2Sgwr if (optype == OP_ADDITION) { \
7495e9d01f2Sgwr hp->MEMBER = get_shared_string(symbol); \
7505e9d01f2Sgwr if (hp->MEMBER == NULL) \
7515e9d01f2Sgwr return E_SYNTAX_ERROR; \
7525e9d01f2Sgwr hp->flags.MEMBER = TRUE; \
7535e9d01f2Sgwr } \
7545e9d01f2Sgwr } while (0)
7555e9d01f2Sgwr
756bcb13babSgwr /* Parse an integer value for MEMBER */
757bcb13babSgwr #define PARSE_INT(MEMBER) do \
758bcb13babSgwr { \
759bcb13babSgwr if (optype == OP_BOOLEAN) \
760bcb13babSgwr return E_SYNTAX_ERROR; \
761bcb13babSgwr hp->flags.MEMBER = FALSE; \
762bcb13babSgwr if (optype == OP_ADDITION) { \
763bcb13babSgwr value = get_u_long(symbol); \
764bcb13babSgwr hp->MEMBER = value; \
765bcb13babSgwr hp->flags.MEMBER = TRUE; \
766bcb13babSgwr } \
767bcb13babSgwr } while (0)
768bcb13babSgwr
7695e9d01f2Sgwr /*
7705e9d01f2Sgwr * Evaluate the two-character tag symbol pointed to by "symbol" and place
7715e9d01f2Sgwr * the data in the structure pointed to by "hp". The pointer pointed to
7725e9d01f2Sgwr * by "symbol" is updated to point past the source string (but may not
7735e9d01f2Sgwr * point to the next tag entry).
7745e9d01f2Sgwr *
7755e9d01f2Sgwr * Obviously, this need a few more comments. . . .
7765e9d01f2Sgwr */
7775e9d01f2Sgwr PRIVATE int
eval_symbol(char ** symbol,struct host * hp)778131109e4Swiz eval_symbol(char **symbol, struct host *hp)
7795e9d01f2Sgwr {
7805e9d01f2Sgwr char tmpstr[MAXSTRINGLEN];
7815e9d01f2Sgwr byte *tmphaddr;
7825e9d01f2Sgwr struct symbolmap *symbolptr;
7835e9d01f2Sgwr u_int32 value;
784c8f61d2bSxtraeme int32 ltimeoff;
7855e9d01f2Sgwr int i, numsymbols;
7865e9d01f2Sgwr unsigned len;
7875e9d01f2Sgwr int optype; /* Indicates boolean, addition, or deletion */
7885e9d01f2Sgwr
7895e9d01f2Sgwr eat_whitespace(symbol);
7905e9d01f2Sgwr
7915e9d01f2Sgwr /* Make sure this is set before returning. */
7925e9d01f2Sgwr current_tagname[0] = (*symbol)[0];
7935e9d01f2Sgwr current_tagname[1] = (*symbol)[1];
7945e9d01f2Sgwr current_tagname[2] = 0;
7955e9d01f2Sgwr
7965e9d01f2Sgwr if ((*symbol)[0] == '\0') {
7975e9d01f2Sgwr return E_END_OF_ENTRY;
7985e9d01f2Sgwr }
7995e9d01f2Sgwr if ((*symbol)[0] == ':') {
8005e9d01f2Sgwr return SUCCESS;
8015e9d01f2Sgwr }
8025e9d01f2Sgwr if ((*symbol)[0] == 'T') { /* generic symbol */
8035e9d01f2Sgwr (*symbol)++;
8045e9d01f2Sgwr value = get_u_long(symbol);
8055402d14cSitojun snprintf(current_tagname, sizeof(current_tagname),
8065402d14cSitojun "T%d", value);
8075e9d01f2Sgwr eat_whitespace(symbol);
8085e9d01f2Sgwr if ((*symbol)[0] != '=') {
8095e9d01f2Sgwr return E_SYNTAX_ERROR;
8105e9d01f2Sgwr }
8115e9d01f2Sgwr (*symbol)++;
8125e9d01f2Sgwr if (!(hp->generic)) {
8135e9d01f2Sgwr hp->generic = (struct shared_bindata *)
8145e9d01f2Sgwr smalloc(sizeof(struct shared_bindata));
8155e9d01f2Sgwr }
8165e9d01f2Sgwr if (process_generic(symbol, &(hp->generic), (byte) (value & 0xFF)))
8175e9d01f2Sgwr return E_SYNTAX_ERROR;
8185e9d01f2Sgwr hp->flags.generic = TRUE;
8195e9d01f2Sgwr return SUCCESS;
8205e9d01f2Sgwr }
8215e9d01f2Sgwr /*
8225e9d01f2Sgwr * Determine the type of operation to be done on this symbol
8235e9d01f2Sgwr */
8245e9d01f2Sgwr switch ((*symbol)[2]) {
8255e9d01f2Sgwr case '=':
8265e9d01f2Sgwr optype = OP_ADDITION;
8275e9d01f2Sgwr break;
8285e9d01f2Sgwr case '@':
8295e9d01f2Sgwr optype = OP_DELETION;
8305e9d01f2Sgwr break;
8315e9d01f2Sgwr case ':':
8325e9d01f2Sgwr case '\0':
8335e9d01f2Sgwr optype = OP_BOOLEAN;
8345e9d01f2Sgwr break;
8355e9d01f2Sgwr default:
8365e9d01f2Sgwr return E_SYNTAX_ERROR;
8375e9d01f2Sgwr }
8385e9d01f2Sgwr
8395e9d01f2Sgwr symbolptr = symbol_list;
8405e9d01f2Sgwr numsymbols = sizeof(symbol_list) / sizeof(struct symbolmap);
8415e9d01f2Sgwr for (i = 0; i < numsymbols; i++) {
8425e9d01f2Sgwr if (((symbolptr->symbol)[0] == (*symbol)[0]) &&
8435e9d01f2Sgwr ((symbolptr->symbol)[1] == (*symbol)[1])) {
8445e9d01f2Sgwr break;
8455e9d01f2Sgwr }
8465e9d01f2Sgwr symbolptr++;
8475e9d01f2Sgwr }
8485e9d01f2Sgwr if (i >= numsymbols) {
8495e9d01f2Sgwr return E_UNKNOWN_SYMBOL;
8505e9d01f2Sgwr }
8515e9d01f2Sgwr /*
8525e9d01f2Sgwr * Skip past the = or @ character (to point to the data) if this
8535e9d01f2Sgwr * isn't a boolean operation. For boolean operations, just skip
8545e9d01f2Sgwr * over the two-character tag symbol (and nothing else. . . .).
8555e9d01f2Sgwr */
8565e9d01f2Sgwr (*symbol) += (optype == OP_BOOLEAN) ? 2 : 3;
8575e9d01f2Sgwr
8585e9d01f2Sgwr eat_whitespace(symbol);
8595e9d01f2Sgwr
8605e9d01f2Sgwr /* The cases below are in order by symbolcode value. */
8615e9d01f2Sgwr switch (symbolptr->symbolcode) {
8625e9d01f2Sgwr
8635e9d01f2Sgwr case SYM_BOOTFILE:
8645e9d01f2Sgwr PARSE_STR(bootfile);
8655e9d01f2Sgwr break;
8665e9d01f2Sgwr
8675e9d01f2Sgwr case SYM_COOKIE_SERVER:
8685e9d01f2Sgwr PARSE_IAL(cookie_server);
8695e9d01f2Sgwr break;
8705e9d01f2Sgwr
8715e9d01f2Sgwr case SYM_DOMAIN_SERVER:
8725e9d01f2Sgwr PARSE_IAL(domain_server);
8735e9d01f2Sgwr break;
8745e9d01f2Sgwr
8755e9d01f2Sgwr case SYM_GATEWAY:
8765e9d01f2Sgwr PARSE_IAL(gateway);
8775e9d01f2Sgwr break;
8785e9d01f2Sgwr
8795e9d01f2Sgwr case SYM_HWADDR:
8805e9d01f2Sgwr if (optype == OP_BOOLEAN)
8815e9d01f2Sgwr return E_SYNTAX_ERROR;
8825e9d01f2Sgwr hp->flags.haddr = FALSE;
8835e9d01f2Sgwr if (optype == OP_ADDITION) {
8845e9d01f2Sgwr /* Default the HW type to Ethernet */
8855e9d01f2Sgwr if (hp->flags.htype == 0) {
8865e9d01f2Sgwr hp->flags.htype = TRUE;
8875e9d01f2Sgwr hp->htype = HTYPE_ETHERNET;
8885e9d01f2Sgwr }
8895e9d01f2Sgwr tmphaddr = prs_haddr(symbol, hp->htype);
8905e9d01f2Sgwr if (!tmphaddr)
8915e9d01f2Sgwr return E_BAD_HWADDR;
8925e9d01f2Sgwr bcopy(tmphaddr, hp->haddr, haddrlength(hp->htype));
8935e9d01f2Sgwr hp->flags.haddr = TRUE;
8945e9d01f2Sgwr }
8955e9d01f2Sgwr break;
8965e9d01f2Sgwr
8975e9d01f2Sgwr case SYM_HOMEDIR:
8985e9d01f2Sgwr PARSE_STR(homedir);
8995e9d01f2Sgwr break;
9005e9d01f2Sgwr
9015e9d01f2Sgwr case SYM_HTYPE:
9025e9d01f2Sgwr if (optype == OP_BOOLEAN)
9035e9d01f2Sgwr return E_SYNTAX_ERROR;
9045e9d01f2Sgwr hp->flags.htype = FALSE;
9055e9d01f2Sgwr if (optype == OP_ADDITION) {
9065e9d01f2Sgwr value = 0L; /* Assume an illegal value */
9075e9d01f2Sgwr eat_whitespace(symbol);
908e09553f3Sdsl if (isdigit((unsigned char)**symbol)) {
9095e9d01f2Sgwr value = get_u_long(symbol);
9105e9d01f2Sgwr } else {
9115e9d01f2Sgwr len = sizeof(tmpstr);
9125e9d01f2Sgwr (void) get_string(symbol, tmpstr, &len);
9135e9d01f2Sgwr makelower(tmpstr);
9145e9d01f2Sgwr numsymbols = sizeof(htnamemap) /
9155e9d01f2Sgwr sizeof(struct htypename);
9165e9d01f2Sgwr for (i = 0; i < numsymbols; i++) {
9175e9d01f2Sgwr if (!strcmp(htnamemap[i].name, tmpstr)) {
9185e9d01f2Sgwr break;
9195e9d01f2Sgwr }
9205e9d01f2Sgwr }
9215e9d01f2Sgwr if (i < numsymbols) {
9225e9d01f2Sgwr value = htnamemap[i].htype;
9235e9d01f2Sgwr }
9245e9d01f2Sgwr }
9255e9d01f2Sgwr if (value >= hwinfocnt) {
9265e9d01f2Sgwr return E_BAD_HWATYPE;
9275e9d01f2Sgwr }
9285e9d01f2Sgwr hp->htype = (byte) (value & 0xFF);
9295e9d01f2Sgwr hp->flags.htype = TRUE;
9305e9d01f2Sgwr }
9315e9d01f2Sgwr break;
9325e9d01f2Sgwr
9335e9d01f2Sgwr case SYM_IMPRESS_SERVER:
9345e9d01f2Sgwr PARSE_IAL(impress_server);
9355e9d01f2Sgwr break;
9365e9d01f2Sgwr
9375e9d01f2Sgwr case SYM_IPADDR:
9385e9d01f2Sgwr PARSE_IA1(iaddr);
9395e9d01f2Sgwr break;
9405e9d01f2Sgwr
9415e9d01f2Sgwr case SYM_LOG_SERVER:
9425e9d01f2Sgwr PARSE_IAL(log_server);
9435e9d01f2Sgwr break;
9445e9d01f2Sgwr
9455e9d01f2Sgwr case SYM_LPR_SERVER:
9465e9d01f2Sgwr PARSE_IAL(lpr_server);
9475e9d01f2Sgwr break;
9485e9d01f2Sgwr
9495e9d01f2Sgwr case SYM_NAME_SERVER:
9505e9d01f2Sgwr PARSE_IAL(name_server);
9515e9d01f2Sgwr break;
9525e9d01f2Sgwr
9535e9d01f2Sgwr case SYM_RLP_SERVER:
9545e9d01f2Sgwr PARSE_IAL(rlp_server);
9555e9d01f2Sgwr break;
9565e9d01f2Sgwr
9575e9d01f2Sgwr case SYM_SUBNET_MASK:
9585e9d01f2Sgwr PARSE_IA1(subnet_mask);
9595e9d01f2Sgwr break;
9605e9d01f2Sgwr
9615e9d01f2Sgwr case SYM_TIME_OFFSET:
9625e9d01f2Sgwr if (optype == OP_BOOLEAN)
9635e9d01f2Sgwr return E_SYNTAX_ERROR;
9645e9d01f2Sgwr hp->flags.time_offset = FALSE;
9655e9d01f2Sgwr if (optype == OP_ADDITION) {
9665e9d01f2Sgwr len = sizeof(tmpstr);
9675e9d01f2Sgwr (void) get_string(symbol, tmpstr, &len);
9685e9d01f2Sgwr if (!strncmp(tmpstr, "auto", 4)) {
9695e9d01f2Sgwr hp->time_offset = secondswest;
9705e9d01f2Sgwr } else {
971c8f61d2bSxtraeme if (sscanf(tmpstr, "%d", <imeoff) != 1)
9725e9d01f2Sgwr return E_BAD_LONGWORD;
973c8f61d2bSxtraeme hp->time_offset = ltimeoff;
9745e9d01f2Sgwr }
9755e9d01f2Sgwr hp->flags.time_offset = TRUE;
9765e9d01f2Sgwr }
9775e9d01f2Sgwr break;
9785e9d01f2Sgwr
9795e9d01f2Sgwr case SYM_TIME_SERVER:
9805e9d01f2Sgwr PARSE_IAL(time_server);
9815e9d01f2Sgwr break;
9825e9d01f2Sgwr
9835e9d01f2Sgwr case SYM_VENDOR_MAGIC:
9845e9d01f2Sgwr if (optype == OP_BOOLEAN)
9855e9d01f2Sgwr return E_SYNTAX_ERROR;
9865e9d01f2Sgwr hp->flags.vm_cookie = FALSE;
9875e9d01f2Sgwr if (optype == OP_ADDITION) {
9885e9d01f2Sgwr if (strncmp(*symbol, "auto", 4)) {
9895e9d01f2Sgwr /* The string is not "auto" */
9905e9d01f2Sgwr if (!strncmp(*symbol, "rfc", 3)) {
9915e9d01f2Sgwr bcopy(vm_rfc1048, hp->vm_cookie, 4);
9925e9d01f2Sgwr } else if (!strncmp(*symbol, "cmu", 3)) {
9935e9d01f2Sgwr bcopy(vm_cmu, hp->vm_cookie, 4);
9945e9d01f2Sgwr } else {
995e09553f3Sdsl if (!isdigit((unsigned char)**symbol))
9965e9d01f2Sgwr return E_BAD_IPADDR;
9975e9d01f2Sgwr if (prs_inetaddr(symbol, &value) < 0)
9985e9d01f2Sgwr return E_BAD_IPADDR;
9995e9d01f2Sgwr bcopy(&value, hp->vm_cookie, 4);
10005e9d01f2Sgwr }
10015e9d01f2Sgwr hp->flags.vm_cookie = TRUE;
10025e9d01f2Sgwr }
10035e9d01f2Sgwr }
10045e9d01f2Sgwr break;
10055e9d01f2Sgwr
10065e9d01f2Sgwr case SYM_SIMILAR_ENTRY:
10075e9d01f2Sgwr switch (optype) {
10085e9d01f2Sgwr case OP_ADDITION:
10095e9d01f2Sgwr fill_defaults(hp, symbol);
10105e9d01f2Sgwr break;
10115e9d01f2Sgwr default:
10125e9d01f2Sgwr return E_SYNTAX_ERROR;
10135e9d01f2Sgwr }
10145e9d01f2Sgwr break;
10155e9d01f2Sgwr
10165e9d01f2Sgwr case SYM_NAME_SWITCH:
10175e9d01f2Sgwr switch (optype) {
10185e9d01f2Sgwr case OP_ADDITION:
10195e9d01f2Sgwr return E_SYNTAX_ERROR;
10205e9d01f2Sgwr case OP_DELETION:
10215e9d01f2Sgwr hp->flags.send_name = FALSE;
10225e9d01f2Sgwr hp->flags.name_switch = FALSE;
10235e9d01f2Sgwr break;
10245e9d01f2Sgwr case OP_BOOLEAN:
10255e9d01f2Sgwr hp->flags.send_name = TRUE;
10265e9d01f2Sgwr hp->flags.name_switch = TRUE;
10275e9d01f2Sgwr break;
10285e9d01f2Sgwr }
10295e9d01f2Sgwr break;
10305e9d01f2Sgwr
10315e9d01f2Sgwr case SYM_BOOTSIZE:
10325e9d01f2Sgwr switch (optype) {
10335e9d01f2Sgwr case OP_ADDITION:
10345e9d01f2Sgwr if (!strncmp(*symbol, "auto", 4)) {
10355e9d01f2Sgwr hp->flags.bootsize = TRUE;
10365e9d01f2Sgwr hp->flags.bootsize_auto = TRUE;
10375e9d01f2Sgwr } else {
10385e9d01f2Sgwr hp->bootsize = (unsigned int) get_u_long(symbol);
10395e9d01f2Sgwr hp->flags.bootsize = TRUE;
10405e9d01f2Sgwr hp->flags.bootsize_auto = FALSE;
10415e9d01f2Sgwr }
10425e9d01f2Sgwr break;
10435e9d01f2Sgwr case OP_DELETION:
10445e9d01f2Sgwr hp->flags.bootsize = FALSE;
10455e9d01f2Sgwr break;
10465e9d01f2Sgwr case OP_BOOLEAN:
10475e9d01f2Sgwr hp->flags.bootsize = TRUE;
10485e9d01f2Sgwr hp->flags.bootsize_auto = TRUE;
10495e9d01f2Sgwr break;
10505e9d01f2Sgwr }
10515e9d01f2Sgwr break;
10525e9d01f2Sgwr
10535e9d01f2Sgwr case SYM_BOOT_SERVER:
10545e9d01f2Sgwr PARSE_IA1(bootserver);
10555e9d01f2Sgwr break;
10565e9d01f2Sgwr
10575e9d01f2Sgwr case SYM_TFTPDIR:
10585e9d01f2Sgwr PARSE_STR(tftpdir);
10595e9d01f2Sgwr if ((hp->tftpdir != NULL) &&
10605e9d01f2Sgwr (hp->tftpdir->string[0] != '/'))
10615e9d01f2Sgwr return E_BAD_PATHNAME;
10625e9d01f2Sgwr break;
10635e9d01f2Sgwr
10645e9d01f2Sgwr case SYM_DUMP_FILE:
10655e9d01f2Sgwr PARSE_STR(dump_file);
10665e9d01f2Sgwr break;
10675e9d01f2Sgwr
10685e9d01f2Sgwr case SYM_DOMAIN_NAME:
10695e9d01f2Sgwr PARSE_STR(domain_name);
10705e9d01f2Sgwr break;
10715e9d01f2Sgwr
10725e9d01f2Sgwr case SYM_SWAP_SERVER:
10735e9d01f2Sgwr PARSE_IA1(swap_server);
10745e9d01f2Sgwr break;
10755e9d01f2Sgwr
10765e9d01f2Sgwr case SYM_ROOT_PATH:
10775e9d01f2Sgwr PARSE_STR(root_path);
10785e9d01f2Sgwr break;
10795e9d01f2Sgwr
10805e9d01f2Sgwr case SYM_EXTEN_FILE:
10815e9d01f2Sgwr PARSE_STR(exten_file);
10825e9d01f2Sgwr break;
10835e9d01f2Sgwr
10845e9d01f2Sgwr case SYM_REPLY_ADDR:
10855e9d01f2Sgwr PARSE_IA1(reply_addr);
10865e9d01f2Sgwr break;
10875e9d01f2Sgwr
10885e9d01f2Sgwr case SYM_NIS_DOMAIN:
10895e9d01f2Sgwr PARSE_STR(nis_domain);
10905e9d01f2Sgwr break;
10915e9d01f2Sgwr
10925e9d01f2Sgwr case SYM_NIS_SERVER:
10935e9d01f2Sgwr PARSE_IAL(nis_server);
10945e9d01f2Sgwr break;
10955e9d01f2Sgwr
10965e9d01f2Sgwr case SYM_NTP_SERVER:
10975e9d01f2Sgwr PARSE_IAL(ntp_server);
10985e9d01f2Sgwr break;
10995e9d01f2Sgwr
11005e9d01f2Sgwr #ifdef YORK_EX_OPTION
11015e9d01f2Sgwr case SYM_EXEC_FILE:
11025e9d01f2Sgwr PARSE_STR(exec_file);
11035e9d01f2Sgwr break;
11045e9d01f2Sgwr #endif
11055e9d01f2Sgwr
1106bcb13babSgwr case SYM_MSG_SIZE:
1107bcb13babSgwr PARSE_INT(msg_size);
1108bcb13babSgwr if (hp->msg_size < BP_MINPKTSZ ||
1109bcb13babSgwr hp->msg_size > MAX_MSG_SIZE)
1110bcb13babSgwr return E_BAD_VALUE;
1111bcb13babSgwr break;
1112bcb13babSgwr
1113bcb13babSgwr case SYM_MIN_WAIT:
1114bcb13babSgwr PARSE_INT(min_wait);
1115c8f61d2bSxtraeme if (hp->min_wait == 0)
1116bcb13babSgwr return E_BAD_VALUE;
1117bcb13babSgwr break;
1118bcb13babSgwr
11195e9d01f2Sgwr /* XXX - Add new tags here */
11205e9d01f2Sgwr
11215e9d01f2Sgwr default:
11225e9d01f2Sgwr return E_UNKNOWN_SYMBOL;
11235e9d01f2Sgwr
11245e9d01f2Sgwr } /* switch symbolcode */
11255e9d01f2Sgwr
11265e9d01f2Sgwr return SUCCESS;
11275e9d01f2Sgwr }
11285e9d01f2Sgwr #undef PARSE_IA1
11295e9d01f2Sgwr #undef PARSE_IAL
11305e9d01f2Sgwr #undef PARSE_STR
11315e9d01f2Sgwr
11325e9d01f2Sgwr
11335e9d01f2Sgwr
11345e9d01f2Sgwr
11355e9d01f2Sgwr /*
11365e9d01f2Sgwr * Read a string from the buffer indirectly pointed to through "src" and
11375e9d01f2Sgwr * move it into the buffer pointed to by "dest". A pointer to the maximum
11385e9d01f2Sgwr * allowable length of the string (including null-terminator) is passed as
11395e9d01f2Sgwr * "length". The actual length of the string which was read is returned in
11405e9d01f2Sgwr * the unsigned integer pointed to by "length". This value is the same as
11415e9d01f2Sgwr * that which would be returned by applying the strlen() function on the
11425e9d01f2Sgwr * destination string (i.e the terminating null is not counted as a
11435e9d01f2Sgwr * character). Trailing whitespace is removed from the string. For
11445e9d01f2Sgwr * convenience, the function returns the new value of "dest".
11455e9d01f2Sgwr *
11465e9d01f2Sgwr * The string is read until the maximum number of characters, an unquoted
11475e9d01f2Sgwr * colon (:), or a null character is read. The return string in "dest" is
11485e9d01f2Sgwr * null-terminated.
11495e9d01f2Sgwr */
11505e9d01f2Sgwr
11515e9d01f2Sgwr PRIVATE char *
get_string(char ** src,char * dest,unsigned int * length)1152131109e4Swiz get_string(char **src, char *dest, unsigned int *length)
11535e9d01f2Sgwr {
11545e9d01f2Sgwr int n, len, quoteflag;
11555e9d01f2Sgwr
11565e9d01f2Sgwr quoteflag = FALSE;
11575e9d01f2Sgwr n = 0;
11585e9d01f2Sgwr len = *length - 1;
11595e9d01f2Sgwr while ((n < len) && (**src)) {
11605e9d01f2Sgwr if (!quoteflag && (**src == ':')) {
11615e9d01f2Sgwr break;
11625e9d01f2Sgwr }
11635e9d01f2Sgwr if (**src == '"') {
11645e9d01f2Sgwr (*src)++;
11655e9d01f2Sgwr quoteflag = !quoteflag;
11665e9d01f2Sgwr continue;
11675e9d01f2Sgwr }
11685e9d01f2Sgwr if (**src == '\\') {
11695e9d01f2Sgwr (*src)++;
11705e9d01f2Sgwr if (!**src) {
11715e9d01f2Sgwr break;
11725e9d01f2Sgwr }
11735e9d01f2Sgwr }
11745e9d01f2Sgwr *dest++ = *(*src)++;
11755e9d01f2Sgwr n++;
11765e9d01f2Sgwr }
11775e9d01f2Sgwr
11785e9d01f2Sgwr /*
11795e9d01f2Sgwr * Remove that troublesome trailing whitespace. . .
11805e9d01f2Sgwr */
1181e09553f3Sdsl while ((n > 0) && isspace((unsigned char)dest[-1])) {
11825e9d01f2Sgwr dest--;
11835e9d01f2Sgwr n--;
11845e9d01f2Sgwr }
11855e9d01f2Sgwr
11865e9d01f2Sgwr *dest = '\0';
11875e9d01f2Sgwr *length = n;
11885e9d01f2Sgwr return dest;
11895e9d01f2Sgwr }
11905e9d01f2Sgwr
11915e9d01f2Sgwr
11925e9d01f2Sgwr
11935e9d01f2Sgwr /*
11945e9d01f2Sgwr * Read the string indirectly pointed to by "src", update the caller's
11955e9d01f2Sgwr * pointer, and return a pointer to a malloc'ed shared_string structure
11965e9d01f2Sgwr * containing the string.
11975e9d01f2Sgwr *
11985e9d01f2Sgwr * The string is read using the same rules as get_string() above.
11995e9d01f2Sgwr */
12005e9d01f2Sgwr
12015e9d01f2Sgwr PRIVATE struct shared_string *
get_shared_string(char ** src)1202131109e4Swiz get_shared_string(char **src)
12035e9d01f2Sgwr {
12045e9d01f2Sgwr char retstring[MAXSTRINGLEN];
12055e9d01f2Sgwr struct shared_string *s;
12065e9d01f2Sgwr unsigned length;
12075e9d01f2Sgwr
12085e9d01f2Sgwr length = sizeof(retstring);
12095e9d01f2Sgwr (void) get_string(src, retstring, &length);
12105e9d01f2Sgwr
12115402d14cSitojun s = (struct shared_string *) smalloc(sizeof(struct shared_string) +
121232ffffe1Sjoerg length + 1);
12135e9d01f2Sgwr s->linkcount = 1;
121432ffffe1Sjoerg memcpy(s->string, retstring, length + 1);
12155e9d01f2Sgwr
12165e9d01f2Sgwr return s;
12175e9d01f2Sgwr }
12185e9d01f2Sgwr
12195e9d01f2Sgwr
12205e9d01f2Sgwr
12215e9d01f2Sgwr /*
12225e9d01f2Sgwr * Load RFC1048 generic information directly into a memory buffer.
12235e9d01f2Sgwr *
12245e9d01f2Sgwr * "src" indirectly points to the ASCII representation of the generic data.
12255e9d01f2Sgwr * "dest" points to a string structure which is updated to point to a new
12265e9d01f2Sgwr * string with the new data appended to the old string. The old string is
12275e9d01f2Sgwr * freed.
12285e9d01f2Sgwr *
12295e9d01f2Sgwr * The given tag value is inserted with the new data.
12305e9d01f2Sgwr *
12315e9d01f2Sgwr * The data may be represented as either a stream of hexadecimal numbers
12325e9d01f2Sgwr * representing bytes (any or all bytes may optionally start with '0x' and
12335e9d01f2Sgwr * be separated with periods ".") or as a quoted string of ASCII
12345e9d01f2Sgwr * characters (the quotes are required).
12355e9d01f2Sgwr */
12365e9d01f2Sgwr
12375e9d01f2Sgwr PRIVATE int
process_generic(char ** src,struct shared_bindata ** dest,u_int tagvalue)1238131109e4Swiz process_generic(char **src, struct shared_bindata **dest, u_int tagvalue)
12395e9d01f2Sgwr {
12405e9d01f2Sgwr byte tmpbuf[MAXBUFLEN];
12415e9d01f2Sgwr byte *str;
12425e9d01f2Sgwr struct shared_bindata *bdata;
12435e9d01f2Sgwr u_int newlength, oldlength;
12445e9d01f2Sgwr
12455e9d01f2Sgwr str = tmpbuf;
12465e9d01f2Sgwr *str++ = (tagvalue & 0xFF); /* Store tag value */
12475e9d01f2Sgwr str++; /* Skip over length field */
12485e9d01f2Sgwr if ((*src)[0] == '"') { /* ASCII data */
12495e9d01f2Sgwr newlength = sizeof(tmpbuf) - 2; /* Set maximum allowed length */
12505e9d01f2Sgwr (void) get_string(src, (char *) str, &newlength);
12512a645560Sgwr /* Do NOT include the terminating null. */
12525e9d01f2Sgwr } else { /* Numeric data */
12535e9d01f2Sgwr newlength = 0;
12545e9d01f2Sgwr while (newlength < sizeof(tmpbuf) - 2) {
12555e9d01f2Sgwr if (interp_byte(src, str++) < 0)
12565e9d01f2Sgwr break;
12575e9d01f2Sgwr newlength++;
12585e9d01f2Sgwr if (**src == '.') {
12595e9d01f2Sgwr (*src)++;
12605e9d01f2Sgwr }
12615e9d01f2Sgwr }
12625e9d01f2Sgwr }
12635e9d01f2Sgwr if ((*src)[0] != ':')
12645e9d01f2Sgwr return -1;
12655e9d01f2Sgwr
12665e9d01f2Sgwr tmpbuf[1] = (newlength & 0xFF);
12675e9d01f2Sgwr oldlength = ((*dest)->length);
12685e9d01f2Sgwr bdata = (struct shared_bindata *) smalloc(sizeof(struct shared_bindata)
12695e9d01f2Sgwr + oldlength + newlength + 1);
12705e9d01f2Sgwr if (oldlength > 0) {
12715e9d01f2Sgwr bcopy((*dest)->data, bdata->data, oldlength);
12725e9d01f2Sgwr }
12735e9d01f2Sgwr bcopy(tmpbuf, bdata->data + oldlength, newlength + 2);
12745e9d01f2Sgwr bdata->length = oldlength + newlength + 2;
12755e9d01f2Sgwr bdata->linkcount = 1;
12765e9d01f2Sgwr del_bindata(*dest);
12775e9d01f2Sgwr *dest = bdata;
12785e9d01f2Sgwr return 0;
12795e9d01f2Sgwr }
12805e9d01f2Sgwr
12815e9d01f2Sgwr
12825e9d01f2Sgwr
12835e9d01f2Sgwr /*
12845e9d01f2Sgwr * Verify that the given string makes sense as a hostname (according to
12855e9d01f2Sgwr * Appendix 1, page 29 of RFC882).
12865e9d01f2Sgwr *
12875e9d01f2Sgwr * Return TRUE for good names, FALSE otherwise.
12885e9d01f2Sgwr */
12895e9d01f2Sgwr
12905e9d01f2Sgwr PRIVATE boolean
goodname(char * hostname)1291aae9c2a0Swiz goodname(char *hostname)
12925e9d01f2Sgwr {
12935e9d01f2Sgwr do {
1294e09553f3Sdsl if (!isalpha((unsigned char)*hostname++)) { /* First character must be a letter */
12955e9d01f2Sgwr return FALSE;
12965e9d01f2Sgwr }
1297e09553f3Sdsl while (isalnum((unsigned char)*hostname) ||
12985e9d01f2Sgwr (*hostname == '-') ||
12995e9d01f2Sgwr (*hostname == '_') )
13005e9d01f2Sgwr {
13015e9d01f2Sgwr hostname++; /* Alphanumeric or a hyphen */
13025e9d01f2Sgwr }
1303e09553f3Sdsl if (!isalnum((unsigned char)hostname[-1])) { /* Last must be alphanumeric */
13045e9d01f2Sgwr return FALSE;
13055e9d01f2Sgwr }
13065e9d01f2Sgwr if (*hostname == '\0') {/* Done? */
13075e9d01f2Sgwr return TRUE;
13085e9d01f2Sgwr }
13095e9d01f2Sgwr } while (*hostname++ == '.'); /* Dot, loop for next label */
13105e9d01f2Sgwr
13115e9d01f2Sgwr return FALSE; /* If it's not a dot, lose */
13125e9d01f2Sgwr }
13135e9d01f2Sgwr
13145e9d01f2Sgwr
13155e9d01f2Sgwr
13165e9d01f2Sgwr /*
13175e9d01f2Sgwr * Null compare function -- always returns FALSE so an element is always
13185e9d01f2Sgwr * inserted into a hash table (i.e. there is never a collision with an
13195e9d01f2Sgwr * existing element).
13205e9d01f2Sgwr */
13215e9d01f2Sgwr
13225e9d01f2Sgwr PRIVATE boolean
nullcmp(hash_datum * d1,hash_datum * d2)1323131109e4Swiz nullcmp(hash_datum *d1, hash_datum *d2)
13245e9d01f2Sgwr {
13255e9d01f2Sgwr return FALSE;
13265e9d01f2Sgwr }
13275e9d01f2Sgwr
13285e9d01f2Sgwr
13295e9d01f2Sgwr /*
13305e9d01f2Sgwr * Function for comparing a string with the hostname field of a host
13315e9d01f2Sgwr * structure.
13325e9d01f2Sgwr */
13335e9d01f2Sgwr
13345e9d01f2Sgwr boolean
nmcmp(hash_datum * d1,hash_datum * d2)1335131109e4Swiz nmcmp(hash_datum *d1, hash_datum *d2)
13365e9d01f2Sgwr {
13375e9d01f2Sgwr char *name = (char *) d1; /* XXX - OK? */
13385e9d01f2Sgwr struct host *hp = (struct host *) d2;
13395e9d01f2Sgwr
13405e9d01f2Sgwr return !strcmp(name, hp->hostname->string);
13415e9d01f2Sgwr }
13425e9d01f2Sgwr
13435e9d01f2Sgwr
13445e9d01f2Sgwr /*
13455e9d01f2Sgwr * Compare function to determine whether two hardware addresses are
13465e9d01f2Sgwr * equivalent. Returns TRUE if "host1" and "host2" are equivalent, FALSE
13475e9d01f2Sgwr * otherwise.
13485e9d01f2Sgwr *
13495e9d01f2Sgwr * If the hardware addresses of "host1" and "host2" are identical, but
13505e9d01f2Sgwr * they are on different IP subnets, this function returns FALSE.
13515e9d01f2Sgwr *
13525e9d01f2Sgwr * This function is used when inserting elements into the hardware address
13535e9d01f2Sgwr * hash table.
13545e9d01f2Sgwr */
13555e9d01f2Sgwr
13565e9d01f2Sgwr PRIVATE boolean
hwinscmp(hash_datum * d1,hash_datum * d2)1357131109e4Swiz hwinscmp(hash_datum *d1, hash_datum *d2)
13585e9d01f2Sgwr {
13595e9d01f2Sgwr struct host *host1 = (struct host *) d1;
13605e9d01f2Sgwr struct host *host2 = (struct host *) d2;
13615e9d01f2Sgwr
13625e9d01f2Sgwr if (host1->htype != host2->htype) {
13635e9d01f2Sgwr return FALSE;
13645e9d01f2Sgwr }
13655e9d01f2Sgwr if (bcmp(host1->haddr, host2->haddr, haddrlength(host1->htype))) {
13665e9d01f2Sgwr return FALSE;
13675e9d01f2Sgwr }
13685e9d01f2Sgwr /* XXX - Is the subnet_mask field set yet? */
13695e9d01f2Sgwr if ((host1->subnet_mask.s_addr) == (host2->subnet_mask.s_addr)) {
13705e9d01f2Sgwr if (((host1->iaddr.s_addr) & (host1->subnet_mask.s_addr)) !=
13715e9d01f2Sgwr ((host2->iaddr.s_addr) & (host2->subnet_mask.s_addr)))
13725e9d01f2Sgwr {
13735e9d01f2Sgwr return FALSE;
13745e9d01f2Sgwr }
13755e9d01f2Sgwr }
13765e9d01f2Sgwr return TRUE;
13775e9d01f2Sgwr }
13785e9d01f2Sgwr
13795e9d01f2Sgwr
13805e9d01f2Sgwr /*
13815e9d01f2Sgwr * Macros for use in the function below:
13825e9d01f2Sgwr */
13835e9d01f2Sgwr
13845e9d01f2Sgwr #define DUP_COPY(MEMBER) do \
13855e9d01f2Sgwr { \
13865e9d01f2Sgwr if (!hp->flags.MEMBER) { \
13875e9d01f2Sgwr if ((hp->flags.MEMBER = hp2->flags.MEMBER) != 0) { \
13885e9d01f2Sgwr hp->MEMBER = hp2->MEMBER; \
13895e9d01f2Sgwr } \
13905e9d01f2Sgwr } \
13915e9d01f2Sgwr } while (0)
13925e9d01f2Sgwr
13935e9d01f2Sgwr #define DUP_LINK(MEMBER) do \
13945e9d01f2Sgwr { \
13955e9d01f2Sgwr if (!hp->flags.MEMBER) { \
13965e9d01f2Sgwr if ((hp->flags.MEMBER = hp2->flags.MEMBER) != 0) { \
13975e9d01f2Sgwr assert(hp2->MEMBER); \
13985e9d01f2Sgwr hp->MEMBER = hp2->MEMBER; \
13995e9d01f2Sgwr (hp->MEMBER->linkcount)++; \
14005e9d01f2Sgwr } \
14015e9d01f2Sgwr } \
14025e9d01f2Sgwr } while (0)
14035e9d01f2Sgwr
14045e9d01f2Sgwr /*
14055e9d01f2Sgwr * Process the "similar entry" symbol.
14065e9d01f2Sgwr *
14075e9d01f2Sgwr * The host specified as the value of the "tc" symbol is used as a template
14085e9d01f2Sgwr * for the current host entry. Symbol values not explicitly set in the
14095e9d01f2Sgwr * current host entry are inferred from the template entry.
14105e9d01f2Sgwr */
14115e9d01f2Sgwr PRIVATE void
fill_defaults(struct host * hp,char ** src)1412131109e4Swiz fill_defaults(struct host *hp, char **src)
14135e9d01f2Sgwr {
14145e9d01f2Sgwr unsigned int tlen, hashcode;
14155e9d01f2Sgwr struct host *hp2;
14165e9d01f2Sgwr char tstring[MAXSTRINGLEN];
14175e9d01f2Sgwr
14185e9d01f2Sgwr tlen = sizeof(tstring);
14195e9d01f2Sgwr (void) get_string(src, tstring, &tlen);
14205e9d01f2Sgwr hashcode = hash_HashFunction((u_char *) tstring, tlen);
14215e9d01f2Sgwr hp2 = (struct host *) hash_Lookup(nmhashtable, hashcode, nmcmp, tstring);
14225e9d01f2Sgwr
14235e9d01f2Sgwr if (hp2 == NULL) {
14245e9d01f2Sgwr report(LOG_ERR, "can't find tc=\"%s\"", tstring);
14255e9d01f2Sgwr return;
14265e9d01f2Sgwr }
14275e9d01f2Sgwr DUP_LINK(bootfile);
14285e9d01f2Sgwr DUP_LINK(cookie_server);
14295e9d01f2Sgwr DUP_LINK(domain_server);
14305e9d01f2Sgwr DUP_LINK(gateway);
14315e9d01f2Sgwr /* haddr not copied */
14325e9d01f2Sgwr DUP_LINK(homedir);
14335e9d01f2Sgwr DUP_COPY(htype);
14345e9d01f2Sgwr
14355e9d01f2Sgwr DUP_LINK(impress_server);
14365e9d01f2Sgwr /* iaddr not copied */
14375e9d01f2Sgwr DUP_LINK(log_server);
14385e9d01f2Sgwr DUP_LINK(lpr_server);
14395e9d01f2Sgwr DUP_LINK(name_server);
14405e9d01f2Sgwr DUP_LINK(rlp_server);
14415e9d01f2Sgwr
14425e9d01f2Sgwr DUP_COPY(subnet_mask);
14435e9d01f2Sgwr DUP_COPY(time_offset);
14445e9d01f2Sgwr DUP_LINK(time_server);
14455e9d01f2Sgwr
14465e9d01f2Sgwr if (!hp->flags.vm_cookie) {
14475e9d01f2Sgwr if ((hp->flags.vm_cookie = hp2->flags.vm_cookie)) {
14485e9d01f2Sgwr bcopy(hp2->vm_cookie, hp->vm_cookie, 4);
14495e9d01f2Sgwr }
14505e9d01f2Sgwr }
14515e9d01f2Sgwr if (!hp->flags.name_switch) {
14525e9d01f2Sgwr if ((hp->flags.name_switch = hp2->flags.name_switch)) {
14535e9d01f2Sgwr hp->flags.send_name = hp2->flags.send_name;
14545e9d01f2Sgwr }
14555e9d01f2Sgwr }
14565e9d01f2Sgwr if (!hp->flags.bootsize) {
14575e9d01f2Sgwr if ((hp->flags.bootsize = hp2->flags.bootsize)) {
14585e9d01f2Sgwr hp->flags.bootsize_auto = hp2->flags.bootsize_auto;
14595e9d01f2Sgwr hp->bootsize = hp2->bootsize;
14605e9d01f2Sgwr }
14615e9d01f2Sgwr }
14625e9d01f2Sgwr DUP_COPY(bootserver);
14635e9d01f2Sgwr
14645e9d01f2Sgwr DUP_LINK(tftpdir);
14655e9d01f2Sgwr DUP_LINK(dump_file);
14665e9d01f2Sgwr DUP_LINK(domain_name);
14675e9d01f2Sgwr
14685e9d01f2Sgwr DUP_COPY(swap_server);
14695e9d01f2Sgwr DUP_LINK(root_path);
14705e9d01f2Sgwr DUP_LINK(exten_file);
14715e9d01f2Sgwr
14725e9d01f2Sgwr DUP_COPY(reply_addr);
14735e9d01f2Sgwr
14745e9d01f2Sgwr DUP_LINK(nis_domain);
14755e9d01f2Sgwr DUP_LINK(nis_server);
14765e9d01f2Sgwr DUP_LINK(ntp_server);
14775e9d01f2Sgwr
14785e9d01f2Sgwr #ifdef YORK_EX_OPTION
14795e9d01f2Sgwr DUP_LINK(exec_file);
14805e9d01f2Sgwr #endif
14815e9d01f2Sgwr
1482bcb13babSgwr DUP_COPY(msg_size);
1483bcb13babSgwr DUP_COPY(min_wait);
1484bcb13babSgwr
14855e9d01f2Sgwr /* XXX - Add new tags here */
14865e9d01f2Sgwr
14875e9d01f2Sgwr DUP_LINK(generic);
14885e9d01f2Sgwr
14895e9d01f2Sgwr }
14905e9d01f2Sgwr #undef DUP_COPY
14915e9d01f2Sgwr #undef DUP_LINK
14925e9d01f2Sgwr
14935e9d01f2Sgwr
14945e9d01f2Sgwr
14955e9d01f2Sgwr /*
14965e9d01f2Sgwr * This function adjusts the caller's pointer to point just past the
14975e9d01f2Sgwr * first-encountered colon. If it runs into a null character, it leaves
14985e9d01f2Sgwr * the pointer pointing to it.
14995e9d01f2Sgwr */
15005e9d01f2Sgwr
15015e9d01f2Sgwr PRIVATE void
adjust(char ** s)1502131109e4Swiz adjust(char **s)
15035e9d01f2Sgwr {
1504aae9c2a0Swiz char *t;
15055e9d01f2Sgwr
15065e9d01f2Sgwr t = *s;
15075e9d01f2Sgwr while (*t && (*t != ':')) {
15085e9d01f2Sgwr t++;
15095e9d01f2Sgwr }
15105e9d01f2Sgwr if (*t) {
15115e9d01f2Sgwr t++;
15125e9d01f2Sgwr }
15135e9d01f2Sgwr *s = t;
15145e9d01f2Sgwr }
15155e9d01f2Sgwr
15165e9d01f2Sgwr
15175e9d01f2Sgwr
15185e9d01f2Sgwr
15195e9d01f2Sgwr /*
15205e9d01f2Sgwr * This function adjusts the caller's pointer to point to the first
15215e9d01f2Sgwr * non-whitespace character. If it runs into a null character, it leaves
15225e9d01f2Sgwr * the pointer pointing to it.
15235e9d01f2Sgwr */
15245e9d01f2Sgwr
15255e9d01f2Sgwr PRIVATE void
eat_whitespace(char ** s)1526131109e4Swiz eat_whitespace(char **s)
15275e9d01f2Sgwr {
1528aae9c2a0Swiz char *t;
15295e9d01f2Sgwr
15305e9d01f2Sgwr t = *s;
1531e09553f3Sdsl while (*t && isspace((unsigned char)*t)) {
15325e9d01f2Sgwr t++;
15335e9d01f2Sgwr }
15345e9d01f2Sgwr *s = t;
15355e9d01f2Sgwr }
15365e9d01f2Sgwr
15375e9d01f2Sgwr
15385e9d01f2Sgwr
15395e9d01f2Sgwr /*
15405e9d01f2Sgwr * This function converts the given string to all lowercase.
15415e9d01f2Sgwr */
15425e9d01f2Sgwr
15435e9d01f2Sgwr PRIVATE void
makelower(char * s)1544131109e4Swiz makelower(char *s)
15455e9d01f2Sgwr {
15465e9d01f2Sgwr while (*s) {
1547e09553f3Sdsl if (isupper((unsigned char)*s)) {
1548e09553f3Sdsl *s = tolower((unsigned char)*s);
15495e9d01f2Sgwr }
15505e9d01f2Sgwr s++;
15515e9d01f2Sgwr }
15525e9d01f2Sgwr }
15535e9d01f2Sgwr
15545e9d01f2Sgwr
15555e9d01f2Sgwr
15565e9d01f2Sgwr /*
15575e9d01f2Sgwr *
15585e9d01f2Sgwr * N O T E :
15595e9d01f2Sgwr *
15605e9d01f2Sgwr * In many of the functions which follow, a parameter such as "src" or
15615e9d01f2Sgwr * "symbol" is passed as a pointer to a pointer to something. This is
15625e9d01f2Sgwr * done for the purpose of letting the called function update the
15635e9d01f2Sgwr * caller's copy of the parameter (i.e. to effect call-by-reference
15645e9d01f2Sgwr * parameter passing). The value of the actual parameter is only used
15655e9d01f2Sgwr * to locate the real parameter of interest and then update this indirect
15665e9d01f2Sgwr * parameter.
15675e9d01f2Sgwr *
15685e9d01f2Sgwr * I'm sure somebody out there won't like this. . . .
15695e9d01f2Sgwr * (Yea, because it usually makes code slower... -gwr)
15705e9d01f2Sgwr *
15715e9d01f2Sgwr */
15725e9d01f2Sgwr
15735e9d01f2Sgwr
15745e9d01f2Sgwr
15755e9d01f2Sgwr /*
15765e9d01f2Sgwr * "src" points to a character pointer which points to an ASCII string of
15775e9d01f2Sgwr * whitespace-separated IP addresses. A pointer to an in_addr_list
15785e9d01f2Sgwr * structure containing the list of addresses is returned. NULL is
15795e9d01f2Sgwr * returned if no addresses were found at all. The pointer pointed to by
15805e9d01f2Sgwr * "src" is updated to point to the first non-address (illegal) character.
15815e9d01f2Sgwr */
15825e9d01f2Sgwr
15835e9d01f2Sgwr PRIVATE struct in_addr_list *
get_addresses(char ** src)1584131109e4Swiz get_addresses(char **src)
15855e9d01f2Sgwr {
15868ef27f1eSjoerg __aligned(4) struct in_addr tmpaddrlist[MAXINADDRS];
15875e9d01f2Sgwr struct in_addr_list *result;
15888ef27f1eSjoerg unsigned addrcount, totalsize, address;
15895e9d01f2Sgwr
15908ef27f1eSjoerg for (address = 0, addrcount = 0; addrcount < MAXINADDRS; addrcount++) {
1591e09553f3Sdsl while (isspace((unsigned char)**src) || (**src == ',')) {
15925e9d01f2Sgwr (*src)++;
15935e9d01f2Sgwr }
15945e9d01f2Sgwr if (!**src) { /* Quit if nothing more */
15955e9d01f2Sgwr break;
15965e9d01f2Sgwr }
15978ef27f1eSjoerg if (prs_inetaddr(src, &tmpaddrlist[address].s_addr) < 0) {
15985e9d01f2Sgwr break;
15995e9d01f2Sgwr }
16008ef27f1eSjoerg address++; /* Point to next address slot */
16015e9d01f2Sgwr }
16025e9d01f2Sgwr if (addrcount < 1) {
16035e9d01f2Sgwr result = NULL;
16045e9d01f2Sgwr } else {
16055e9d01f2Sgwr totalsize = sizeof(struct in_addr_list)
16065e9d01f2Sgwr + (addrcount - 1) * sizeof(struct in_addr);
16075e9d01f2Sgwr result = (struct in_addr_list *) smalloc(totalsize);
16085e9d01f2Sgwr result->linkcount = 1;
16095e9d01f2Sgwr result->addrcount = addrcount;
16108ef27f1eSjoerg for (address = 0; address < addrcount; ++address)
16118ef27f1eSjoerg result->addr[address] = tmpaddrlist[address];
16125e9d01f2Sgwr }
16135e9d01f2Sgwr return result;
16145e9d01f2Sgwr }
16155e9d01f2Sgwr
16165e9d01f2Sgwr
16175e9d01f2Sgwr
16185e9d01f2Sgwr /*
16195e9d01f2Sgwr * prs_inetaddr(src, result)
16205e9d01f2Sgwr *
16215e9d01f2Sgwr * "src" is a value-result parameter; the pointer it points to is updated
16225e9d01f2Sgwr * to point to the next data position. "result" points to an unsigned long
16235e9d01f2Sgwr * in which an address is returned.
16245e9d01f2Sgwr *
16255e9d01f2Sgwr * This function parses the IP address string in ASCII "dot notation" pointed
16265e9d01f2Sgwr * to by (*src) and places the result (in network byte order) in the unsigned
16275e9d01f2Sgwr * long pointed to by "result". For malformed addresses, -1 is returned,
16285e9d01f2Sgwr * (*src) points to the first illegal character, and the unsigned long pointed
16295e9d01f2Sgwr * to by "result" is unchanged. Successful calls return 0.
16305e9d01f2Sgwr */
16315e9d01f2Sgwr
16325e9d01f2Sgwr PRIVATE int
prs_inetaddr(char ** src,u_int32 * result)1633131109e4Swiz prs_inetaddr(char **src, u_int32 *result)
16345e9d01f2Sgwr {
16355e9d01f2Sgwr char tmpstr[MAXSTRINGLEN];
1636aae9c2a0Swiz u_int32 value;
16375e9d01f2Sgwr u_int32 parts[4], *pp;
16385e9d01f2Sgwr int n;
16395e9d01f2Sgwr char *s, *t;
16405e9d01f2Sgwr
16415e9d01f2Sgwr #if 1 /* XXX - experimental */
16425e9d01f2Sgwr /* Leading alpha char causes IP addr lookup. */
1643e09553f3Sdsl if (isalpha((unsigned char)**src)) {
16445e9d01f2Sgwr /* Lookup IP address. */
16455e9d01f2Sgwr s = *src;
16465e9d01f2Sgwr t = tmpstr;
1647e09553f3Sdsl while ((isalnum((unsigned char)*s) || (*s == '.') ||
16485e9d01f2Sgwr (*s == '-') || (*s == '_') ) &&
16495e9d01f2Sgwr (t < &tmpstr[MAXSTRINGLEN - 1]) )
16505e9d01f2Sgwr *t++ = *s++;
16515e9d01f2Sgwr *t = '\0';
16525e9d01f2Sgwr *src = s;
16535e9d01f2Sgwr
16545e9d01f2Sgwr n = lookup_ipa(tmpstr, result);
16555e9d01f2Sgwr if (n < 0)
16565e9d01f2Sgwr report(LOG_ERR, "can not get IP addr for %s", tmpstr);
16575e9d01f2Sgwr return n;
16585e9d01f2Sgwr }
16595e9d01f2Sgwr #endif
16605e9d01f2Sgwr
16615e9d01f2Sgwr /*
16625e9d01f2Sgwr * Parse an address in Internet format:
16635e9d01f2Sgwr * a.b.c.d
16645e9d01f2Sgwr * a.b.c (with c treated as 16-bits)
16655e9d01f2Sgwr * a.b (with b treated as 24 bits)
16665e9d01f2Sgwr */
16675e9d01f2Sgwr pp = parts;
16685e9d01f2Sgwr loop:
16695e9d01f2Sgwr /* If it's not a digit, return error. */
1670e09553f3Sdsl if (!isdigit((unsigned char)**src))
16715e9d01f2Sgwr return -1;
16725e9d01f2Sgwr *pp++ = get_u_long(src);
16735e9d01f2Sgwr if (**src == '.') {
16745e9d01f2Sgwr if (pp < (parts + 4)) {
16755e9d01f2Sgwr (*src)++;
16765e9d01f2Sgwr goto loop;
16775e9d01f2Sgwr }
16785e9d01f2Sgwr return (-1);
16795e9d01f2Sgwr }
16805e9d01f2Sgwr #if 0
16815e9d01f2Sgwr /* This is handled by the caller. */
1682e09553f3Sdsl if (**src && !((unsigned char)isspace(**src) || (**src == ':'))) {
16835e9d01f2Sgwr return (-1);
16845e9d01f2Sgwr }
16855e9d01f2Sgwr #endif
16865e9d01f2Sgwr
16875e9d01f2Sgwr /*
16885e9d01f2Sgwr * Construct the address according to
16895e9d01f2Sgwr * the number of parts specified.
16905e9d01f2Sgwr */
16915e9d01f2Sgwr n = pp - parts;
16925e9d01f2Sgwr switch (n) {
16935e9d01f2Sgwr case 1: /* a -- 32 bits */
16945e9d01f2Sgwr value = parts[0];
16955e9d01f2Sgwr break;
16965e9d01f2Sgwr case 2: /* a.b -- 8.24 bits */
16975e9d01f2Sgwr value = (parts[0] << 24) | (parts[1] & 0xFFFFFF);
16985e9d01f2Sgwr break;
16995e9d01f2Sgwr case 3: /* a.b.c -- 8.8.16 bits */
17005e9d01f2Sgwr value = (parts[0] << 24) | ((parts[1] & 0xFF) << 16) |
17015e9d01f2Sgwr (parts[2] & 0xFFFF);
17025e9d01f2Sgwr break;
17035e9d01f2Sgwr case 4: /* a.b.c.d -- 8.8.8.8 bits */
17045e9d01f2Sgwr value = (parts[0] << 24) | ((parts[1] & 0xFF) << 16) |
17055e9d01f2Sgwr ((parts[2] & 0xFF) << 8) | (parts[3] & 0xFF);
17065e9d01f2Sgwr break;
17075e9d01f2Sgwr default:
17085e9d01f2Sgwr return (-1);
17095e9d01f2Sgwr }
17105e9d01f2Sgwr *result = htonl(value);
17115e9d01f2Sgwr return (0);
17125e9d01f2Sgwr }
17135e9d01f2Sgwr
17145e9d01f2Sgwr
17155e9d01f2Sgwr
17165e9d01f2Sgwr /*
17175e9d01f2Sgwr * "src" points to a pointer which in turn points to a hexadecimal ASCII
17185e9d01f2Sgwr * string. This string is interpreted as a hardware address and returned
17195e9d01f2Sgwr * as a pointer to the actual hardware address, represented as an array of
17205e9d01f2Sgwr * bytes.
17215e9d01f2Sgwr *
17225e9d01f2Sgwr * The ASCII string must have the proper number of digits for the specified
17235e9d01f2Sgwr * hardware type (e.g. twelve digits for a 48-bit Ethernet address).
17245e9d01f2Sgwr * Two-digit sequences (bytes) may be separated with periods (.) and/or
17255e9d01f2Sgwr * prefixed with '0x' for readability, but this is not required.
17265e9d01f2Sgwr *
17275e9d01f2Sgwr * For bad addresses, the pointer which "src" points to is updated to point
17285e9d01f2Sgwr * to the start of the first two-digit sequence which was bad, and the
17295e9d01f2Sgwr * function returns a NULL pointer.
17305e9d01f2Sgwr */
17315e9d01f2Sgwr
17325e9d01f2Sgwr PRIVATE byte *
prs_haddr(char ** src,u_int htype)1733131109e4Swiz prs_haddr(char **src, u_int htype)
17345e9d01f2Sgwr {
17355e9d01f2Sgwr static byte haddr[MAXHADDRLEN];
17365e9d01f2Sgwr byte *hap;
17375e9d01f2Sgwr char tmpstr[MAXSTRINGLEN];
17385e9d01f2Sgwr u_int tmplen;
17395e9d01f2Sgwr unsigned hal;
17405e9d01f2Sgwr char *p;
17415e9d01f2Sgwr
17425e9d01f2Sgwr hal = haddrlength(htype); /* Get length of this address type */
17435e9d01f2Sgwr if (hal <= 0) {
17445e9d01f2Sgwr report(LOG_ERR, "Invalid addr type for HW addr parse");
17455e9d01f2Sgwr return NULL;
17465e9d01f2Sgwr }
17475e9d01f2Sgwr tmplen = sizeof(tmpstr);
17485e9d01f2Sgwr get_string(src, tmpstr, &tmplen);
17495e9d01f2Sgwr p = tmpstr;
17505e9d01f2Sgwr
17515e9d01f2Sgwr #if 1 /* XXX - experimental */
17525e9d01f2Sgwr /* If it's a valid host name, try to lookup the HW address. */
17535e9d01f2Sgwr if (goodname(p)) {
17545e9d01f2Sgwr /* Lookup Hardware Address for hostname. */
17555e9d01f2Sgwr if ((hap = lookup_hwa(p, htype)) != NULL)
17565e9d01f2Sgwr return hap; /* success */
17575e9d01f2Sgwr report(LOG_ERR, "Add 0x prefix if hex value starts with A-F");
17585e9d01f2Sgwr /* OK, assume it must be numeric. */
17595e9d01f2Sgwr }
17605e9d01f2Sgwr #endif
17615e9d01f2Sgwr
17625e9d01f2Sgwr hap = haddr;
17635e9d01f2Sgwr while (hap < haddr + hal) {
17642a645560Sgwr if ((*p == '.') || (*p == ':'))
17655e9d01f2Sgwr p++;
17665e9d01f2Sgwr if (interp_byte(&p, hap++) < 0) {
17675e9d01f2Sgwr return NULL;
17685e9d01f2Sgwr }
17695e9d01f2Sgwr }
17705e9d01f2Sgwr return haddr;
17715e9d01f2Sgwr }
17725e9d01f2Sgwr
17735e9d01f2Sgwr
17745e9d01f2Sgwr
17755e9d01f2Sgwr /*
17765e9d01f2Sgwr * "src" is a pointer to a character pointer which in turn points to a
17775e9d01f2Sgwr * hexadecimal ASCII representation of a byte. This byte is read, the
17785e9d01f2Sgwr * character pointer is updated, and the result is deposited into the
17795e9d01f2Sgwr * byte pointed to by "retbyte".
17805e9d01f2Sgwr *
17815e9d01f2Sgwr * The usual '0x' notation is allowed but not required. The number must be
17825e9d01f2Sgwr * a two digit hexadecimal number. If the number is invalid, "src" and
17835e9d01f2Sgwr * "retbyte" are left untouched and -1 is returned as the function value.
17845e9d01f2Sgwr * Successful calls return 0.
17855e9d01f2Sgwr */
17865e9d01f2Sgwr
17875e9d01f2Sgwr PRIVATE int
interp_byte(char ** src,byte * retbyte)1788131109e4Swiz interp_byte(char **src, byte *retbyte)
17895e9d01f2Sgwr {
17905e9d01f2Sgwr int v;
17915e9d01f2Sgwr
17925e9d01f2Sgwr if ((*src)[0] == '0' &&
17935e9d01f2Sgwr ((*src)[1] == 'x' ||
17945e9d01f2Sgwr (*src)[1] == 'X')) {
17955e9d01f2Sgwr (*src) += 2; /* allow 0x for hex, but don't require it */
17965e9d01f2Sgwr }
1797e09553f3Sdsl if (!isxdigit((unsigned char)(*src)[0]) || !isxdigit((unsigned char)(*src)[1])) {
17985e9d01f2Sgwr return -1;
17995e9d01f2Sgwr }
18005e9d01f2Sgwr if (sscanf(*src, "%2x", &v) != 1) {
18015e9d01f2Sgwr return -1;
18025e9d01f2Sgwr }
18035e9d01f2Sgwr (*src) += 2;
18045e9d01f2Sgwr *retbyte = (byte) (v & 0xFF);
18055e9d01f2Sgwr return 0;
18065e9d01f2Sgwr }
18075e9d01f2Sgwr
18085e9d01f2Sgwr
18095e9d01f2Sgwr
18105e9d01f2Sgwr /*
18115e9d01f2Sgwr * The parameter "src" points to a character pointer which points to an
18125e9d01f2Sgwr * ASCII string representation of an unsigned number. The number is
18135e9d01f2Sgwr * returned as an unsigned long and the character pointer is updated to
18145e9d01f2Sgwr * point to the first illegal character.
18155e9d01f2Sgwr */
18165e9d01f2Sgwr
18175e9d01f2Sgwr PRIVATE u_int32
get_u_long(char ** src)1818131109e4Swiz get_u_long(char **src)
18195e9d01f2Sgwr {
1820aae9c2a0Swiz u_int32 value, base;
18215e9d01f2Sgwr char c;
18225e9d01f2Sgwr
18235e9d01f2Sgwr /*
18245e9d01f2Sgwr * Collect number up to first illegal character. Values are specified
18255e9d01f2Sgwr * as for C: 0x=hex, 0=octal, other=decimal.
18265e9d01f2Sgwr */
18275e9d01f2Sgwr value = 0;
18285e9d01f2Sgwr base = 10;
18295e9d01f2Sgwr if (**src == '0') {
18305e9d01f2Sgwr base = 8;
18315e9d01f2Sgwr (*src)++;
18325e9d01f2Sgwr }
18335e9d01f2Sgwr if (**src == 'x' || **src == 'X') {
18345e9d01f2Sgwr base = 16;
18355e9d01f2Sgwr (*src)++;
18365e9d01f2Sgwr }
18375e9d01f2Sgwr while ((c = **src)) {
1838e09553f3Sdsl if (isdigit((unsigned char)c)) {
18395e9d01f2Sgwr value = (value * base) + (c - '0');
18405e9d01f2Sgwr (*src)++;
18415e9d01f2Sgwr continue;
18425e9d01f2Sgwr }
1843e09553f3Sdsl if (base == 16 && isxdigit((unsigned char)c)) {
18445e9d01f2Sgwr value = (value << 4) + ((c & ~32) + 10 - 'A');
18455e9d01f2Sgwr (*src)++;
18465e9d01f2Sgwr continue;
18475e9d01f2Sgwr }
18485e9d01f2Sgwr break;
18495e9d01f2Sgwr }
18505e9d01f2Sgwr return value;
18515e9d01f2Sgwr }
18525e9d01f2Sgwr
18535e9d01f2Sgwr
18545e9d01f2Sgwr
18555e9d01f2Sgwr /*
18565e9d01f2Sgwr * Routines for deletion of data associated with the main data structure.
18575e9d01f2Sgwr */
18585e9d01f2Sgwr
18595e9d01f2Sgwr
18605e9d01f2Sgwr /*
18615e9d01f2Sgwr * Frees the entire host data structure given. Does nothing if the passed
18625e9d01f2Sgwr * pointer is NULL.
18635e9d01f2Sgwr */
18645e9d01f2Sgwr
18655e9d01f2Sgwr PRIVATE void
free_host(hash_datum * hmp)1866131109e4Swiz free_host(hash_datum *hmp)
18675e9d01f2Sgwr {
18685e9d01f2Sgwr struct host *hostptr = (struct host *) hmp;
18695e9d01f2Sgwr if (hostptr == NULL)
18705e9d01f2Sgwr return;
18715e9d01f2Sgwr assert(hostptr->linkcount > 0);
18725e9d01f2Sgwr if (--(hostptr->linkcount))
18735e9d01f2Sgwr return; /* Still has references */
18745e9d01f2Sgwr del_iplist(hostptr->cookie_server);
18755e9d01f2Sgwr del_iplist(hostptr->domain_server);
18765e9d01f2Sgwr del_iplist(hostptr->gateway);
18775e9d01f2Sgwr del_iplist(hostptr->impress_server);
18785e9d01f2Sgwr del_iplist(hostptr->log_server);
18795e9d01f2Sgwr del_iplist(hostptr->lpr_server);
18805e9d01f2Sgwr del_iplist(hostptr->name_server);
18815e9d01f2Sgwr del_iplist(hostptr->rlp_server);
18825e9d01f2Sgwr del_iplist(hostptr->time_server);
18835e9d01f2Sgwr del_iplist(hostptr->nis_server);
18845e9d01f2Sgwr del_iplist(hostptr->ntp_server);
18855e9d01f2Sgwr
18865e9d01f2Sgwr /*
18875e9d01f2Sgwr * XXX - Add new tags here
18885e9d01f2Sgwr * (if the value is an IP list)
18895e9d01f2Sgwr */
18905e9d01f2Sgwr
18915e9d01f2Sgwr del_string(hostptr->hostname);
18925e9d01f2Sgwr del_string(hostptr->homedir);
18935e9d01f2Sgwr del_string(hostptr->bootfile);
18945e9d01f2Sgwr del_string(hostptr->tftpdir);
18955e9d01f2Sgwr del_string(hostptr->root_path);
18965e9d01f2Sgwr del_string(hostptr->domain_name);
18975e9d01f2Sgwr del_string(hostptr->dump_file);
18985e9d01f2Sgwr del_string(hostptr->exten_file);
18995e9d01f2Sgwr del_string(hostptr->nis_domain);
19005e9d01f2Sgwr
19015e9d01f2Sgwr #ifdef YORK_EX_OPTION
19025e9d01f2Sgwr del_string(hostptr->exec_file);
19035e9d01f2Sgwr #endif
19045e9d01f2Sgwr
19055e9d01f2Sgwr /*
19065e9d01f2Sgwr * XXX - Add new tags here
19075e9d01f2Sgwr * (if it is a shared string)
19085e9d01f2Sgwr */
19095e9d01f2Sgwr
19105e9d01f2Sgwr del_bindata(hostptr->generic);
19115e9d01f2Sgwr free((char *) hostptr);
19125e9d01f2Sgwr }
19135e9d01f2Sgwr
19145e9d01f2Sgwr
19155e9d01f2Sgwr
19165e9d01f2Sgwr /*
19175e9d01f2Sgwr * Decrements the linkcount on the given IP address data structure. If the
19185e9d01f2Sgwr * linkcount goes to zero, the memory associated with the data is freed.
19195e9d01f2Sgwr */
19205e9d01f2Sgwr
19215e9d01f2Sgwr PRIVATE void
del_iplist(struct in_addr_list * iplist)1922131109e4Swiz del_iplist(struct in_addr_list *iplist)
19235e9d01f2Sgwr {
19245e9d01f2Sgwr if (iplist) {
19255e9d01f2Sgwr if (!(--(iplist->linkcount))) {
19265e9d01f2Sgwr free((char *) iplist);
19275e9d01f2Sgwr }
19285e9d01f2Sgwr }
19295e9d01f2Sgwr }
19305e9d01f2Sgwr
19315e9d01f2Sgwr
19325e9d01f2Sgwr
19335e9d01f2Sgwr /*
19345e9d01f2Sgwr * Decrements the linkcount on a string data structure. If the count
19355e9d01f2Sgwr * goes to zero, the memory associated with the string is freed. Does
19365e9d01f2Sgwr * nothing if the passed pointer is NULL.
19375e9d01f2Sgwr */
19385e9d01f2Sgwr
19395e9d01f2Sgwr PRIVATE void
del_string(struct shared_string * stringptr)1940131109e4Swiz del_string(struct shared_string *stringptr)
19415e9d01f2Sgwr {
19425e9d01f2Sgwr if (stringptr) {
19435e9d01f2Sgwr if (!(--(stringptr->linkcount))) {
19445e9d01f2Sgwr free((char *) stringptr);
19455e9d01f2Sgwr }
19465e9d01f2Sgwr }
19475e9d01f2Sgwr }
19485e9d01f2Sgwr
19495e9d01f2Sgwr
19505e9d01f2Sgwr
19515e9d01f2Sgwr /*
19525e9d01f2Sgwr * Decrements the linkcount on a shared_bindata data structure. If the
19535e9d01f2Sgwr * count goes to zero, the memory associated with the data is freed. Does
19545e9d01f2Sgwr * nothing if the passed pointer is NULL.
19555e9d01f2Sgwr */
19565e9d01f2Sgwr
19575e9d01f2Sgwr PRIVATE void
del_bindata(struct shared_bindata * dataptr)1958131109e4Swiz del_bindata(struct shared_bindata *dataptr)
19595e9d01f2Sgwr {
19605e9d01f2Sgwr if (dataptr) {
19615e9d01f2Sgwr if (!(--(dataptr->linkcount))) {
19625e9d01f2Sgwr free((char *) dataptr);
19635e9d01f2Sgwr }
19645e9d01f2Sgwr }
19655e9d01f2Sgwr }
19665e9d01f2Sgwr
19675e9d01f2Sgwr
19685e9d01f2Sgwr
19695e9d01f2Sgwr
19705e9d01f2Sgwr /* smalloc() -- safe malloc()
19715e9d01f2Sgwr *
19725e9d01f2Sgwr * Always returns a valid pointer (if it returns at all). The allocated
19735e9d01f2Sgwr * memory is initialized to all zeros. If malloc() returns an error, a
19745e9d01f2Sgwr * message is printed using the report() function and the program aborts
19755e9d01f2Sgwr * with a status of 1.
19765e9d01f2Sgwr */
19775e9d01f2Sgwr
19785e9d01f2Sgwr PRIVATE char *
smalloc(unsigned int nbytes)1979131109e4Swiz smalloc(unsigned int nbytes)
19805e9d01f2Sgwr {
19815e9d01f2Sgwr char *retvalue;
19825e9d01f2Sgwr
19835e9d01f2Sgwr retvalue = malloc(nbytes);
19845e9d01f2Sgwr if (!retvalue) {
19855e9d01f2Sgwr report(LOG_ERR, "malloc() failure -- exiting");
19865e9d01f2Sgwr exit(1);
19875e9d01f2Sgwr }
19885e9d01f2Sgwr bzero(retvalue, nbytes);
19895e9d01f2Sgwr return retvalue;
19905e9d01f2Sgwr }
19915e9d01f2Sgwr
19925e9d01f2Sgwr
19935e9d01f2Sgwr /*
19945e9d01f2Sgwr * Compare function to determine whether two hardware addresses are
19955e9d01f2Sgwr * equivalent. Returns TRUE if "host1" and "host2" are equivalent, FALSE
19965e9d01f2Sgwr * otherwise.
19975e9d01f2Sgwr *
19985e9d01f2Sgwr * This function is used when retrieving elements from the hardware address
19995e9d01f2Sgwr * hash table.
20005e9d01f2Sgwr */
20015e9d01f2Sgwr
20025e9d01f2Sgwr boolean
hwlookcmp(hash_datum * d1,hash_datum * d2)2003131109e4Swiz hwlookcmp(hash_datum *d1, hash_datum *d2)
20045e9d01f2Sgwr {
20055e9d01f2Sgwr struct host *host1 = (struct host *) d1;
20065e9d01f2Sgwr struct host *host2 = (struct host *) d2;
20075e9d01f2Sgwr
20085e9d01f2Sgwr if (host1->htype != host2->htype) {
20095e9d01f2Sgwr return FALSE;
20105e9d01f2Sgwr }
20115e9d01f2Sgwr if (bcmp(host1->haddr, host2->haddr, haddrlength(host1->htype))) {
20125e9d01f2Sgwr return FALSE;
20135e9d01f2Sgwr }
20145e9d01f2Sgwr return TRUE;
20155e9d01f2Sgwr }
20165e9d01f2Sgwr
20175e9d01f2Sgwr
20185e9d01f2Sgwr /*
20195e9d01f2Sgwr * Compare function for doing IP address hash table lookup.
20205e9d01f2Sgwr */
20215e9d01f2Sgwr
20225e9d01f2Sgwr boolean
iplookcmp(hash_datum * d1,hash_datum * d2)2023131109e4Swiz iplookcmp(hash_datum *d1, hash_datum *d2)
20245e9d01f2Sgwr {
20255e9d01f2Sgwr struct host *host1 = (struct host *) d1;
20265e9d01f2Sgwr struct host *host2 = (struct host *) d2;
20275e9d01f2Sgwr
20285e9d01f2Sgwr return (host1->iaddr.s_addr == host2->iaddr.s_addr);
20295e9d01f2Sgwr }
20305e9d01f2Sgwr
20315e9d01f2Sgwr /*
20325e9d01f2Sgwr * Local Variables:
20335e9d01f2Sgwr * tab-width: 4
20345e9d01f2Sgwr * c-indent-level: 4
20355e9d01f2Sgwr * c-argdecl-indent: 4
20365e9d01f2Sgwr * c-continued-statement-offset: 4
20375e9d01f2Sgwr * c-continued-brace-offset: -4
20385e9d01f2Sgwr * c-label-offset: -4
20395e9d01f2Sgwr * c-brace-offset: 0
20405e9d01f2Sgwr * End:
20415e9d01f2Sgwr */
2042