xref: /freebsd/libexec/bootpd/readfile.c (revision 05248206f720394d95c2a7475429311df670a2e9)
144099b7bSPaul Traina /************************************************************************
244099b7bSPaul Traina           Copyright 1988, 1991 by Carnegie Mellon University
344099b7bSPaul Traina 
444099b7bSPaul Traina                           All Rights Reserved
544099b7bSPaul Traina 
644099b7bSPaul Traina Permission to use, copy, modify, and distribute this software and its
744099b7bSPaul Traina documentation for any purpose and without fee is hereby granted, provided
844099b7bSPaul Traina that the above copyright notice appear in all copies and that both that
944099b7bSPaul Traina copyright notice and this permission notice appear in supporting
1044099b7bSPaul Traina documentation, and that the name of Carnegie Mellon University not be used
1144099b7bSPaul Traina in advertising or publicity pertaining to distribution of the software
1244099b7bSPaul Traina without specific, written prior permission.
1344099b7bSPaul Traina 
1444099b7bSPaul Traina CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
1544099b7bSPaul Traina SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
1644099b7bSPaul Traina IN NO EVENT SHALL CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
1744099b7bSPaul Traina DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
1844099b7bSPaul Traina PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
1944099b7bSPaul Traina ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2044099b7bSPaul Traina SOFTWARE.
21148531efSWolfram Schneider 
2244099b7bSPaul Traina ************************************************************************/
2344099b7bSPaul Traina 
2444099b7bSPaul Traina /*
2544099b7bSPaul Traina  * bootpd configuration file reading code.
2644099b7bSPaul Traina  *
2744099b7bSPaul Traina  * The routines in this file deal with reading, interpreting, and storing
2844099b7bSPaul Traina  * the information found in the bootpd configuration file (usually
2944099b7bSPaul Traina  * /etc/bootptab).
3044099b7bSPaul Traina  */
3144099b7bSPaul Traina 
3244099b7bSPaul Traina 
3344099b7bSPaul Traina #include <sys/errno.h>
3444099b7bSPaul Traina #include <sys/types.h>
3544099b7bSPaul Traina #include <sys/stat.h>
3644099b7bSPaul Traina #include <sys/file.h>
3744099b7bSPaul Traina #include <sys/time.h>
3844099b7bSPaul Traina #include <netinet/in.h>
3944099b7bSPaul Traina 
4044099b7bSPaul Traina #include <stdlib.h>
4144099b7bSPaul Traina #include <stdio.h>
4244099b7bSPaul Traina #include <string.h>
4344099b7bSPaul Traina #include <ctype.h>
4444099b7bSPaul Traina #include <assert.h>
4544099b7bSPaul Traina #include <syslog.h>
4644099b7bSPaul Traina 
4744099b7bSPaul Traina #include "bootp.h"
4844099b7bSPaul Traina #include "hash.h"
4944099b7bSPaul Traina #include "hwaddr.h"
5044099b7bSPaul Traina #include "lookup.h"
5144099b7bSPaul Traina #include "readfile.h"
5244099b7bSPaul Traina #include "report.h"
5344099b7bSPaul Traina #include "tzone.h"
5444099b7bSPaul Traina #include "bootpd.h"
5544099b7bSPaul Traina 
5644099b7bSPaul Traina #define HASHTABLESIZE		257	/* Hash table size (prime) */
5744099b7bSPaul Traina 
5844099b7bSPaul Traina /* Non-standard hardware address type (see bootp.h) */
5944099b7bSPaul Traina #define HTYPE_DIRECT	0
6044099b7bSPaul Traina 
6144099b7bSPaul Traina /* Error codes returned by eval_symbol: */
6244099b7bSPaul Traina #define SUCCESS			  0
6344099b7bSPaul Traina #define E_END_OF_ENTRY		(-1)
6444099b7bSPaul Traina #define E_SYNTAX_ERROR		(-2)
6544099b7bSPaul Traina #define E_UNKNOWN_SYMBOL	(-3)
6644099b7bSPaul Traina #define E_BAD_IPADDR		(-4)
6744099b7bSPaul Traina #define E_BAD_HWADDR		(-5)
6844099b7bSPaul Traina #define E_BAD_LONGWORD		(-6)
6944099b7bSPaul Traina #define E_BAD_HWATYPE		(-7)
7044099b7bSPaul Traina #define E_BAD_PATHNAME		(-8)
7144099b7bSPaul Traina #define E_BAD_VALUE 		(-9)
7244099b7bSPaul Traina 
7344099b7bSPaul Traina /* Tag idendities. */
7444099b7bSPaul Traina #define SYM_NULL		  0
7544099b7bSPaul Traina #define SYM_BOOTFILE		  1
7644099b7bSPaul Traina #define SYM_COOKIE_SERVER	  2
7744099b7bSPaul Traina #define SYM_DOMAIN_SERVER	  3
7844099b7bSPaul Traina #define SYM_GATEWAY		  4
7944099b7bSPaul Traina #define SYM_HWADDR		  5
8044099b7bSPaul Traina #define SYM_HOMEDIR		  6
8144099b7bSPaul Traina #define SYM_HTYPE		  7
8244099b7bSPaul Traina #define SYM_IMPRESS_SERVER	  8
8344099b7bSPaul Traina #define SYM_IPADDR		  9
8444099b7bSPaul Traina #define SYM_LOG_SERVER		 10
8544099b7bSPaul Traina #define SYM_LPR_SERVER		 11
8644099b7bSPaul Traina #define SYM_NAME_SERVER		 12
8744099b7bSPaul Traina #define SYM_RLP_SERVER		 13
8844099b7bSPaul Traina #define SYM_SUBNET_MASK		 14
8944099b7bSPaul Traina #define SYM_TIME_OFFSET		 15
9044099b7bSPaul Traina #define SYM_TIME_SERVER		 16
9144099b7bSPaul Traina #define SYM_VENDOR_MAGIC	 17
9244099b7bSPaul Traina #define SYM_SIMILAR_ENTRY	 18
9344099b7bSPaul Traina #define SYM_NAME_SWITCH		 19
9444099b7bSPaul Traina #define SYM_BOOTSIZE		 20
9544099b7bSPaul Traina #define SYM_BOOT_SERVER		 22
9644099b7bSPaul Traina #define SYM_TFTPDIR		 23
9744099b7bSPaul Traina #define SYM_DUMP_FILE		 24
9844099b7bSPaul Traina #define SYM_DOMAIN_NAME          25
9944099b7bSPaul Traina #define SYM_SWAP_SERVER          26
10044099b7bSPaul Traina #define SYM_ROOT_PATH            27
10144099b7bSPaul Traina #define SYM_EXTEN_FILE           28
10244099b7bSPaul Traina #define SYM_REPLY_ADDR           29
10344099b7bSPaul Traina #define SYM_NIS_DOMAIN           30	/* RFC 1533 */
10444099b7bSPaul Traina #define SYM_NIS_SERVER           31	/* RFC 1533 */
10544099b7bSPaul Traina #define SYM_NTP_SERVER           32	/* RFC 1533 */
10644099b7bSPaul Traina #define SYM_EXEC_FILE		 33	/* YORK_EX_OPTION */
10744099b7bSPaul Traina #define SYM_MSG_SIZE 		 34
10844099b7bSPaul Traina #define SYM_MIN_WAIT		 35
10944099b7bSPaul Traina /* XXX - Add new tags here */
11044099b7bSPaul Traina 
11144099b7bSPaul Traina #define OP_ADDITION		  1	/* Operations on tags */
11244099b7bSPaul Traina #define OP_DELETION		  2
11344099b7bSPaul Traina #define OP_BOOLEAN		  3
11444099b7bSPaul Traina 
11544099b7bSPaul Traina #define MAXINADDRS		 16	/* Max size of an IP address list */
11644099b7bSPaul Traina #define MAXBUFLEN		256	/* Max temp buffer space */
11744099b7bSPaul Traina #define MAXENTRYLEN	       2048	/* Max size of an entire entry */
11844099b7bSPaul Traina 
11944099b7bSPaul Traina 
12044099b7bSPaul Traina 
12144099b7bSPaul Traina /*
12244099b7bSPaul Traina  * Structure used to map a configuration-file symbol (such as "ds") to a
12344099b7bSPaul Traina  * unique integer.
12444099b7bSPaul Traina  */
12544099b7bSPaul Traina 
12644099b7bSPaul Traina struct symbolmap {
12744099b7bSPaul Traina 	char *symbol;
12844099b7bSPaul Traina 	int symbolcode;
12944099b7bSPaul Traina };
13044099b7bSPaul Traina 
13144099b7bSPaul Traina 
13244099b7bSPaul Traina struct htypename {
13344099b7bSPaul Traina 	char *name;
13444099b7bSPaul Traina 	byte htype;
13544099b7bSPaul Traina };
13644099b7bSPaul Traina 
13744099b7bSPaul Traina 
13844099b7bSPaul Traina PRIVATE int nhosts;				/* Number of hosts (/w hw or IP address) */
13944099b7bSPaul Traina PRIVATE int nentries;			/* Total number of entries */
14044099b7bSPaul Traina PRIVATE int32 modtime = 0;		/* Last modification time of bootptab */
14144099b7bSPaul Traina PRIVATE char *current_hostname;	/* Name of the current entry. */
14244099b7bSPaul Traina PRIVATE char current_tagname[8];
14344099b7bSPaul Traina 
14444099b7bSPaul Traina /*
14544099b7bSPaul Traina  * List of symbolic names used in the bootptab file.  The order and actual
14644099b7bSPaul Traina  * values of the symbol codes (SYM_. . .) are unimportant, but they must
14744099b7bSPaul Traina  * all be unique.
14844099b7bSPaul Traina  */
14944099b7bSPaul Traina 
15044099b7bSPaul Traina PRIVATE struct symbolmap symbol_list[] = {
15144099b7bSPaul Traina 	{"bf", SYM_BOOTFILE},
15244099b7bSPaul Traina 	{"bs", SYM_BOOTSIZE},
15344099b7bSPaul Traina 	{"cs", SYM_COOKIE_SERVER},
15444099b7bSPaul Traina 	{"df", SYM_DUMP_FILE},
15544099b7bSPaul Traina 	{"dn", SYM_DOMAIN_NAME},
15644099b7bSPaul Traina 	{"ds", SYM_DOMAIN_SERVER},
15744099b7bSPaul Traina 	{"ef", SYM_EXTEN_FILE},
15844099b7bSPaul Traina 	{"ex", SYM_EXEC_FILE},		/* YORK_EX_OPTION */
15944099b7bSPaul Traina 	{"gw", SYM_GATEWAY},
16044099b7bSPaul Traina 	{"ha", SYM_HWADDR},
16144099b7bSPaul Traina 	{"hd", SYM_HOMEDIR},
16244099b7bSPaul Traina 	{"hn", SYM_NAME_SWITCH},
16344099b7bSPaul Traina 	{"ht", SYM_HTYPE},
16444099b7bSPaul Traina 	{"im", SYM_IMPRESS_SERVER},
16544099b7bSPaul Traina 	{"ip", SYM_IPADDR},
16644099b7bSPaul Traina 	{"lg", SYM_LOG_SERVER},
16744099b7bSPaul Traina 	{"lp", SYM_LPR_SERVER},
16844099b7bSPaul Traina 	{"ms", SYM_MSG_SIZE},
16944099b7bSPaul Traina 	{"mw", SYM_MIN_WAIT},
17044099b7bSPaul Traina 	{"ns", SYM_NAME_SERVER},
17144099b7bSPaul Traina 	{"nt", SYM_NTP_SERVER},
17244099b7bSPaul Traina 	{"ra", SYM_REPLY_ADDR},
17344099b7bSPaul Traina 	{"rl", SYM_RLP_SERVER},
17444099b7bSPaul Traina 	{"rp", SYM_ROOT_PATH},
17544099b7bSPaul Traina 	{"sa", SYM_BOOT_SERVER},
17644099b7bSPaul Traina 	{"sm", SYM_SUBNET_MASK},
17744099b7bSPaul Traina 	{"sw", SYM_SWAP_SERVER},
17844099b7bSPaul Traina 	{"tc", SYM_SIMILAR_ENTRY},
17944099b7bSPaul Traina 	{"td", SYM_TFTPDIR},
18044099b7bSPaul Traina 	{"to", SYM_TIME_OFFSET},
18144099b7bSPaul Traina 	{"ts", SYM_TIME_SERVER},
18244099b7bSPaul Traina 	{"vm", SYM_VENDOR_MAGIC},
18344099b7bSPaul Traina 	{"yd", SYM_NIS_DOMAIN},
18444099b7bSPaul Traina 	{"ys", SYM_NIS_SERVER},
18544099b7bSPaul Traina 	/* XXX - Add new tags here */
18644099b7bSPaul Traina };
18744099b7bSPaul Traina 
18844099b7bSPaul Traina 
18944099b7bSPaul Traina /*
19044099b7bSPaul Traina  * List of symbolic names for hardware types.  Name translates into
19144099b7bSPaul Traina  * hardware type code listed with it.  Names must begin with a letter
19244099b7bSPaul Traina  * and must be all lowercase.  This is searched linearly, so put
19344099b7bSPaul Traina  * commonly-used entries near the beginning.
19444099b7bSPaul Traina  */
19544099b7bSPaul Traina 
19644099b7bSPaul Traina PRIVATE struct htypename htnamemap[] = {
19744099b7bSPaul Traina 	{"ethernet", HTYPE_ETHERNET},
19844099b7bSPaul Traina 	{"ethernet3", HTYPE_EXP_ETHERNET},
19944099b7bSPaul Traina 	{"ether", HTYPE_ETHERNET},
20044099b7bSPaul Traina 	{"ether3", HTYPE_EXP_ETHERNET},
20144099b7bSPaul Traina 	{"ieee802", HTYPE_IEEE802},
20244099b7bSPaul Traina 	{"tr", HTYPE_IEEE802},
20344099b7bSPaul Traina 	{"token-ring", HTYPE_IEEE802},
20444099b7bSPaul Traina 	{"pronet", HTYPE_PRONET},
20544099b7bSPaul Traina 	{"chaos", HTYPE_CHAOS},
20644099b7bSPaul Traina 	{"arcnet", HTYPE_ARCNET},
20744099b7bSPaul Traina 	{"ax.25", HTYPE_AX25},
20844099b7bSPaul Traina 	{"direct", HTYPE_DIRECT},
20944099b7bSPaul Traina 	{"serial", HTYPE_DIRECT},
21044099b7bSPaul Traina 	{"slip", HTYPE_DIRECT},
21144099b7bSPaul Traina 	{"ppp", HTYPE_DIRECT}
21244099b7bSPaul Traina };
21344099b7bSPaul Traina 
21444099b7bSPaul Traina 
21544099b7bSPaul Traina 
21644099b7bSPaul Traina /*
21744099b7bSPaul Traina  * Externals and forward declarations.
21844099b7bSPaul Traina  */
21944099b7bSPaul Traina 
220f19d047aSAlfred Perlstein boolean nmcmp(hash_datum *, hash_datum *);
22144099b7bSPaul Traina 
22244099b7bSPaul Traina PRIVATE void
223f19d047aSAlfred Perlstein 	adjust(char **);
22444099b7bSPaul Traina PRIVATE void
225f19d047aSAlfred Perlstein 	del_string(struct shared_string *);
22644099b7bSPaul Traina PRIVATE void
227f19d047aSAlfred Perlstein 	del_bindata(struct shared_bindata *);
22844099b7bSPaul Traina PRIVATE void
229f19d047aSAlfred Perlstein 	del_iplist(struct in_addr_list *);
23044099b7bSPaul Traina PRIVATE void
231f19d047aSAlfred Perlstein 	eat_whitespace(char **);
23244099b7bSPaul Traina PRIVATE int
233f19d047aSAlfred Perlstein 	eval_symbol(char **, struct host *);
23444099b7bSPaul Traina PRIVATE void
235f19d047aSAlfred Perlstein 	fill_defaults(struct host *, char **);
23644099b7bSPaul Traina PRIVATE void
237f19d047aSAlfred Perlstein 	free_host(hash_datum *);
23844099b7bSPaul Traina PRIVATE struct in_addr_list *
239f19d047aSAlfred Perlstein 	get_addresses(char **);
24044099b7bSPaul Traina PRIVATE struct shared_string *
241f19d047aSAlfred Perlstein 	get_shared_string(char **);
24244099b7bSPaul Traina PRIVATE char *
243f19d047aSAlfred Perlstein 	get_string(char **, char *, u_int *);
24444099b7bSPaul Traina PRIVATE u_int32
245f19d047aSAlfred Perlstein 	get_u_long(char **);
24644099b7bSPaul Traina PRIVATE boolean
247f19d047aSAlfred Perlstein 	goodname(char *);
24844099b7bSPaul Traina PRIVATE boolean
249f19d047aSAlfred Perlstein 	hwinscmp(hash_datum *, hash_datum *);
25044099b7bSPaul Traina PRIVATE int
251f19d047aSAlfred Perlstein 	interp_byte(char **, byte *);
25244099b7bSPaul Traina PRIVATE void
253f19d047aSAlfred Perlstein 	makelower(char *);
25444099b7bSPaul Traina PRIVATE boolean
255f19d047aSAlfred Perlstein         nullcmp(hash_datum *, hash_datum *);
25644099b7bSPaul Traina PRIVATE int
257f19d047aSAlfred Perlstein 	process_entry(struct host *, char *);
25844099b7bSPaul Traina PRIVATE int
259f19d047aSAlfred Perlstein 	process_generic(char **, struct shared_bindata **, u_int);
26044099b7bSPaul Traina PRIVATE byte *
261f19d047aSAlfred Perlstein 	prs_haddr(char **, u_int);
26244099b7bSPaul Traina PRIVATE int
263f19d047aSAlfred Perlstein 	prs_inetaddr(char **, u_int32 *);
26444099b7bSPaul Traina PRIVATE void
265f19d047aSAlfred Perlstein 	read_entry(FILE *, char *, u_int *);
26644099b7bSPaul Traina PRIVATE char *
267f19d047aSAlfred Perlstein 	smalloc(u_int);
26844099b7bSPaul Traina 
26944099b7bSPaul Traina 
27044099b7bSPaul Traina /*
27144099b7bSPaul Traina  * Vendor magic cookies for CMU and RFC1048
27244099b7bSPaul Traina  */
27344099b7bSPaul Traina u_char vm_cmu[4] = VM_CMU;
27444099b7bSPaul Traina u_char vm_rfc1048[4] = VM_RFC1048;
27544099b7bSPaul Traina 
27644099b7bSPaul Traina /*
27744099b7bSPaul Traina  * Main hash tables
27844099b7bSPaul Traina  */
27944099b7bSPaul Traina hash_tbl *hwhashtable;
28044099b7bSPaul Traina hash_tbl *iphashtable;
28144099b7bSPaul Traina hash_tbl *nmhashtable;
28244099b7bSPaul Traina 
28344099b7bSPaul Traina /*
28444099b7bSPaul Traina  * Allocate hash tables for hardware address, ip address, and hostname
28544099b7bSPaul Traina  * (shared by bootpd and bootpef)
28644099b7bSPaul Traina  */
28744099b7bSPaul Traina void
rdtab_init(void)288*8b356c88SJohn Baldwin rdtab_init(void)
28944099b7bSPaul Traina {
29044099b7bSPaul Traina 	hwhashtable = hash_Init(HASHTABLESIZE);
29144099b7bSPaul Traina 	iphashtable = hash_Init(HASHTABLESIZE);
29244099b7bSPaul Traina 	nmhashtable = hash_Init(HASHTABLESIZE);
29344099b7bSPaul Traina 	if (!(hwhashtable && iphashtable && nmhashtable)) {
29444099b7bSPaul Traina 		report(LOG_ERR, "Unable to allocate hash tables.");
29544099b7bSPaul Traina 		exit(1);
29644099b7bSPaul Traina 	}
29744099b7bSPaul Traina }
29844099b7bSPaul Traina 
29944099b7bSPaul Traina 
30044099b7bSPaul Traina /*
30144099b7bSPaul Traina  * Read bootptab database file.  Avoid rereading the file if the
30244099b7bSPaul Traina  * write date hasn't changed since the last time we read it.
30344099b7bSPaul Traina  */
30444099b7bSPaul Traina 
30544099b7bSPaul Traina void
readtab(int force)306*8b356c88SJohn Baldwin readtab(int force)
30744099b7bSPaul Traina {
30844099b7bSPaul Traina 	struct host *hp;
30944099b7bSPaul Traina 	FILE *fp;
31044099b7bSPaul Traina 	struct stat st;
31144099b7bSPaul Traina 	unsigned hashcode, buflen;
31244099b7bSPaul Traina 	static char buffer[MAXENTRYLEN];
31344099b7bSPaul Traina 
31444099b7bSPaul Traina 	/*
31544099b7bSPaul Traina 	 * Check the last modification time.
31644099b7bSPaul Traina 	 */
31744099b7bSPaul Traina 	if (stat(bootptab, &st) < 0) {
31844099b7bSPaul Traina 		report(LOG_ERR, "stat on \"%s\": %s",
31944099b7bSPaul Traina 			   bootptab, get_errmsg());
32044099b7bSPaul Traina 		return;
32144099b7bSPaul Traina 	}
32244099b7bSPaul Traina #ifdef DEBUG
32344099b7bSPaul Traina 	if (debug > 3) {
32444099b7bSPaul Traina 		char timestr[28];
32544099b7bSPaul Traina 		strcpy(timestr, ctime(&(st.st_mtime)));
32644099b7bSPaul Traina 		/* zap the newline */
32744099b7bSPaul Traina 		timestr[24] = '\0';
32844099b7bSPaul Traina 		report(LOG_INFO, "bootptab mtime: %s",
32944099b7bSPaul Traina 			   timestr);
33044099b7bSPaul Traina 	}
33144099b7bSPaul Traina #endif
33244099b7bSPaul Traina 	if ((force == 0) &&
33344099b7bSPaul Traina 		(st.st_mtime == modtime) &&
33444099b7bSPaul Traina 		st.st_nlink) {
33544099b7bSPaul Traina 		/*
33644099b7bSPaul Traina 		 * hasn't been modified or deleted yet.
33744099b7bSPaul Traina 		 */
33844099b7bSPaul Traina 		return;
33944099b7bSPaul Traina 	}
34044099b7bSPaul Traina 	if (debug)
34144099b7bSPaul Traina 		report(LOG_INFO, "reading %s\"%s\"",
34244099b7bSPaul Traina 			   (modtime != 0L) ? "new " : "",
34344099b7bSPaul Traina 			   bootptab);
34444099b7bSPaul Traina 
34544099b7bSPaul Traina 	/*
34644099b7bSPaul Traina 	 * Open bootptab file.
34744099b7bSPaul Traina 	 */
34844099b7bSPaul Traina 	if ((fp = fopen(bootptab, "r")) == NULL) {
34944099b7bSPaul Traina 		report(LOG_ERR, "error opening \"%s\": %s", bootptab, get_errmsg());
35044099b7bSPaul Traina 		return;
35144099b7bSPaul Traina 	}
35244099b7bSPaul Traina 	/*
35344099b7bSPaul Traina 	 * Record file modification time.
35444099b7bSPaul Traina 	 */
35544099b7bSPaul Traina 	if (fstat(fileno(fp), &st) < 0) {
35644099b7bSPaul Traina 		report(LOG_ERR, "fstat: %s", get_errmsg());
35744099b7bSPaul Traina 		fclose(fp);
35844099b7bSPaul Traina 		return;
35944099b7bSPaul Traina 	}
36044099b7bSPaul Traina 	modtime = st.st_mtime;
36144099b7bSPaul Traina 
36244099b7bSPaul Traina 	/*
36344099b7bSPaul Traina 	 * Entirely erase all hash tables.
36444099b7bSPaul Traina 	 */
36544099b7bSPaul Traina 	hash_Reset(hwhashtable, free_host);
36644099b7bSPaul Traina 	hash_Reset(iphashtable, free_host);
36744099b7bSPaul Traina 	hash_Reset(nmhashtable, free_host);
36844099b7bSPaul Traina 
36944099b7bSPaul Traina 	nhosts = 0;
37044099b7bSPaul Traina 	nentries = 0;
37144099b7bSPaul Traina 	while (TRUE) {
37244099b7bSPaul Traina 		buflen = sizeof(buffer);
37344099b7bSPaul Traina 		read_entry(fp, buffer, &buflen);
37444099b7bSPaul Traina 		if (buflen == 0) {		/* More entries? */
37544099b7bSPaul Traina 			break;
37644099b7bSPaul Traina 		}
37744099b7bSPaul Traina 		hp = (struct host *) smalloc(sizeof(struct host));
37844099b7bSPaul Traina 		bzero((char *) hp, sizeof(*hp));
37944099b7bSPaul Traina 		/* the link count it zero */
38044099b7bSPaul Traina 
38144099b7bSPaul Traina 		/*
38244099b7bSPaul Traina 		 * Get individual info
38344099b7bSPaul Traina 		 */
38444099b7bSPaul Traina 		if (process_entry(hp, buffer) < 0) {
38544099b7bSPaul Traina 			hp->linkcount = 1;
38644099b7bSPaul Traina 			free_host((hash_datum *) hp);
38744099b7bSPaul Traina 			continue;
38844099b7bSPaul Traina 		}
38944099b7bSPaul Traina 		/*
39044099b7bSPaul Traina 		 * If this is not a dummy entry, and the IP or HW
39144099b7bSPaul Traina 		 * address is not yet set, try to get them here.
39244099b7bSPaul Traina 		 * Dummy entries have . as first char of name.
39344099b7bSPaul Traina 		 */
39444099b7bSPaul Traina 		if (goodname(hp->hostname->string)) {
39544099b7bSPaul Traina 			char *hn = hp->hostname->string;
39644099b7bSPaul Traina 			u_int32 value;
39744099b7bSPaul Traina 			if (hp->flags.iaddr == 0) {
39844099b7bSPaul Traina 				if (lookup_ipa(hn, &value)) {
39944099b7bSPaul Traina 					report(LOG_ERR, "can not get IP addr for %s", hn);
40044099b7bSPaul Traina 					report(LOG_ERR, "(dummy names should start with '.')");
40144099b7bSPaul Traina 				} else {
40244099b7bSPaul Traina 					hp->iaddr.s_addr = value;
40344099b7bSPaul Traina 					hp->flags.iaddr = TRUE;
40444099b7bSPaul Traina 				}
40544099b7bSPaul Traina 			}
40644099b7bSPaul Traina 			/* Set default subnet mask. */
40744099b7bSPaul Traina 			if (hp->flags.subnet_mask == 0) {
40844099b7bSPaul Traina 				if (lookup_netmask(hp->iaddr.s_addr, &value)) {
40944099b7bSPaul Traina 					report(LOG_ERR, "can not get netmask for %s", hn);
41044099b7bSPaul Traina 				} else {
41144099b7bSPaul Traina 					hp->subnet_mask.s_addr = value;
41244099b7bSPaul Traina 					hp->flags.subnet_mask = TRUE;
41344099b7bSPaul Traina 				}
41444099b7bSPaul Traina 			}
41544099b7bSPaul Traina 		}
41644099b7bSPaul Traina 		if (hp->flags.iaddr) {
41744099b7bSPaul Traina 			nhosts++;
41844099b7bSPaul Traina 		}
4199a9048e1SPedro F. Giffuni 		/* Register by HW addr if known. */
42044099b7bSPaul Traina 		if (hp->flags.htype && hp->flags.haddr) {
42144099b7bSPaul Traina 			/* We will either insert it or free it. */
42244099b7bSPaul Traina 			hp->linkcount++;
42344099b7bSPaul Traina 			hashcode = hash_HashFunction(hp->haddr, haddrlength(hp->htype));
42444099b7bSPaul Traina 			if (hash_Insert(hwhashtable, hashcode, hwinscmp, hp, hp) < 0) {
42544099b7bSPaul Traina 				report(LOG_NOTICE, "duplicate %s address: %s",
42644099b7bSPaul Traina 					   netname(hp->htype),
427e08ac58bSPaul Traina 					   haddrtoa(hp->haddr, haddrlength(hp->htype)));
42844099b7bSPaul Traina 				free_host((hash_datum *) hp);
42944099b7bSPaul Traina 				continue;
43044099b7bSPaul Traina 			}
43144099b7bSPaul Traina 		}
4329a9048e1SPedro F. Giffuni 		/* Register by IP addr if known. */
43344099b7bSPaul Traina 		if (hp->flags.iaddr) {
43444099b7bSPaul Traina 			hashcode = hash_HashFunction((u_char *) & (hp->iaddr.s_addr), 4);
43544099b7bSPaul Traina 			if (hash_Insert(iphashtable, hashcode, nullcmp, hp, hp) < 0) {
43644099b7bSPaul Traina 				report(LOG_ERR,
43744099b7bSPaul Traina 					   "hash_Insert() failed on IP address insertion");
43844099b7bSPaul Traina 			} else {
43944099b7bSPaul Traina 				/* Just inserted the host struct in a new hash list. */
44044099b7bSPaul Traina 				hp->linkcount++;
44144099b7bSPaul Traina 			}
44244099b7bSPaul Traina 		}
4439a9048e1SPedro F. Giffuni 		/* Register by Name (always known) */
44444099b7bSPaul Traina 		hashcode = hash_HashFunction((u_char *) hp->hostname->string,
44544099b7bSPaul Traina 									 strlen(hp->hostname->string));
44644099b7bSPaul Traina 		if (hash_Insert(nmhashtable, hashcode, nullcmp,
44744099b7bSPaul Traina 						hp->hostname->string, hp) < 0) {
44844099b7bSPaul Traina 			report(LOG_ERR,
44944099b7bSPaul Traina 				 "hash_Insert() failed on insertion of hostname: \"%s\"",
45044099b7bSPaul Traina 				   hp->hostname->string);
45144099b7bSPaul Traina 		} else {
45244099b7bSPaul Traina 			/* Just inserted the host struct in a new hash list. */
45344099b7bSPaul Traina 			hp->linkcount++;
45444099b7bSPaul Traina 		}
45544099b7bSPaul Traina 
45644099b7bSPaul Traina 		nentries++;
45744099b7bSPaul Traina 	}
45844099b7bSPaul Traina 
45944099b7bSPaul Traina 	fclose(fp);
46044099b7bSPaul Traina 	if (debug)
46144099b7bSPaul Traina 		report(LOG_INFO, "read %d entries (%d hosts) from \"%s\"",
46244099b7bSPaul Traina 			   nentries, nhosts, bootptab);
46344099b7bSPaul Traina 	return;
46444099b7bSPaul Traina }
46544099b7bSPaul Traina 
46644099b7bSPaul Traina 
46744099b7bSPaul Traina 
46844099b7bSPaul Traina /*
46944099b7bSPaul Traina  * Read an entire host entry from the file pointed to by "fp" and insert it
47044099b7bSPaul Traina  * into the memory pointed to by "buffer".  Leading whitespace and comments
47144099b7bSPaul Traina  * starting with "#" are ignored (removed).  Backslashes (\) always quote
4727c637968SJeroen Ruigrok van der Werven  * the next character except that newlines preceded by a backslash cause
47344099b7bSPaul Traina  * line-continuation onto the next line.  The entry is terminated by a
4747c637968SJeroen Ruigrok van der Werven  * newline character which is not preceded by a backslash.  Sequences
47544099b7bSPaul Traina  * surrounded by double quotes are taken literally (including newlines, but
47644099b7bSPaul Traina  * not backslashes).
47744099b7bSPaul Traina  *
47844099b7bSPaul Traina  * The "bufsiz" parameter points to an unsigned int which specifies the
47944099b7bSPaul Traina  * maximum permitted buffer size.  Upon return, this value will be replaced
48044099b7bSPaul Traina  * with the actual length of the entry (not including the null terminator).
48144099b7bSPaul Traina  *
48244099b7bSPaul Traina  * This code is a little scary. . . .  I don't like using gotos in C
48344099b7bSPaul Traina  * either, but I first wrote this as an FSM diagram and gotos seemed like
48444099b7bSPaul Traina  * the easiest way to implement it.  Maybe later I'll clean it up.
48544099b7bSPaul Traina  */
48644099b7bSPaul Traina 
48744099b7bSPaul Traina PRIVATE void
read_entry(FILE * fp,char * buffer,unsigned * bufsiz)488*8b356c88SJohn Baldwin read_entry(FILE *fp, char *buffer, unsigned *bufsiz)
48944099b7bSPaul Traina {
49044099b7bSPaul Traina 	int c, length;
49144099b7bSPaul Traina 
49244099b7bSPaul Traina 	length = 0;
49344099b7bSPaul Traina 
49444099b7bSPaul Traina 	/*
49544099b7bSPaul Traina 	 * Eat whitespace, blank lines, and comment lines.
49644099b7bSPaul Traina 	 */
49744099b7bSPaul Traina   top:
49844099b7bSPaul Traina 	c = fgetc(fp);
49944099b7bSPaul Traina 	if (c < 0) {
50044099b7bSPaul Traina 		goto done;				/* Exit if end-of-file */
50144099b7bSPaul Traina 	}
50244099b7bSPaul Traina 	if (isspace(c)) {
50344099b7bSPaul Traina 		goto top;				/* Skip over whitespace */
50444099b7bSPaul Traina 	}
50544099b7bSPaul Traina 	if (c == '#') {
50644099b7bSPaul Traina 		while (TRUE) {			/* Eat comments after # */
50744099b7bSPaul Traina 			c = fgetc(fp);
50844099b7bSPaul Traina 			if (c < 0) {
50944099b7bSPaul Traina 				goto done;		/* Exit if end-of-file */
51044099b7bSPaul Traina 			}
51144099b7bSPaul Traina 			if (c == '\n') {
51244099b7bSPaul Traina 				goto top;		/* Try to read the next line */
51344099b7bSPaul Traina 			}
51444099b7bSPaul Traina 		}
51544099b7bSPaul Traina 	}
51644099b7bSPaul Traina 	ungetc(c, fp);				/* Other character, push it back to reprocess it */
51744099b7bSPaul Traina 
51844099b7bSPaul Traina 
51944099b7bSPaul Traina 	/*
52044099b7bSPaul Traina 	 * Now we're actually reading a data entry.  Get each character and
52144099b7bSPaul Traina 	 * assemble it into the data buffer, processing special characters like
52244099b7bSPaul Traina 	 * double quotes (") and backslashes (\).
52344099b7bSPaul Traina 	 */
52444099b7bSPaul Traina 
52544099b7bSPaul Traina   mainloop:
52644099b7bSPaul Traina 	c = fgetc(fp);
52744099b7bSPaul Traina 	switch (c) {
52844099b7bSPaul Traina 	case EOF:
52944099b7bSPaul Traina 	case '\n':
53044099b7bSPaul Traina 		goto done;				/* Exit on EOF or newline */
53144099b7bSPaul Traina 	case '\\':
53244099b7bSPaul Traina 		c = fgetc(fp);			/* Backslash, read a new character */
53344099b7bSPaul Traina 		if (c < 0) {
53444099b7bSPaul Traina 			goto done;			/* Exit on EOF */
53544099b7bSPaul Traina 		}
53644099b7bSPaul Traina 		*buffer++ = c;			/* Store the literal character */
53744099b7bSPaul Traina 		length++;
53844099b7bSPaul Traina 		if (length < *bufsiz - 1) {
53944099b7bSPaul Traina 			goto mainloop;
54044099b7bSPaul Traina 		} else {
54144099b7bSPaul Traina 			goto done;
54244099b7bSPaul Traina 		}
54344099b7bSPaul Traina 	case '"':
54444099b7bSPaul Traina 		*buffer++ = '"';		/* Store double-quote */
54544099b7bSPaul Traina 		length++;
54644099b7bSPaul Traina 		if (length >= *bufsiz - 1) {
54744099b7bSPaul Traina 			goto done;
54844099b7bSPaul Traina 		}
54944099b7bSPaul Traina 		while (TRUE) {			/* Special quote processing loop */
55044099b7bSPaul Traina 			c = fgetc(fp);
55144099b7bSPaul Traina 			switch (c) {
55244099b7bSPaul Traina 			case EOF:
55344099b7bSPaul Traina 				goto done;		/* Exit on EOF . . . */
55444099b7bSPaul Traina 			case '"':
55544099b7bSPaul Traina 				*buffer++ = '"';/* Store matching quote */
55644099b7bSPaul Traina 				length++;
55744099b7bSPaul Traina 				if (length < *bufsiz - 1) {
55844099b7bSPaul Traina 					goto mainloop;	/* And continue main loop */
55944099b7bSPaul Traina 				} else {
56044099b7bSPaul Traina 					goto done;
56144099b7bSPaul Traina 				}
56244099b7bSPaul Traina 			case '\\':
56344099b7bSPaul Traina 				if ((c = fgetc(fp)) < 0) {	/* Backslash */
56444099b7bSPaul Traina 					goto done;	/* EOF. . . .*/
5657fed38d0SPhilippe Charnier 				}
5667fed38d0SPhilippe Charnier 				/* FALLTHROUGH */
56744099b7bSPaul Traina 			default:
56844099b7bSPaul Traina 				*buffer++ = c;	/* Other character, store it */
56944099b7bSPaul Traina 				length++;
57044099b7bSPaul Traina 				if (length >= *bufsiz - 1) {
57144099b7bSPaul Traina 					goto done;
57244099b7bSPaul Traina 				}
57344099b7bSPaul Traina 			}
57444099b7bSPaul Traina 		}
57544099b7bSPaul Traina 	case ':':
57644099b7bSPaul Traina 		*buffer++ = c;			/* Store colons */
57744099b7bSPaul Traina 		length++;
57844099b7bSPaul Traina 		if (length >= *bufsiz - 1) {
57944099b7bSPaul Traina 			goto done;
58044099b7bSPaul Traina 		}
58144099b7bSPaul Traina 		do {					/* But remove whitespace after them */
58244099b7bSPaul Traina 			c = fgetc(fp);
58344099b7bSPaul Traina 			if ((c < 0) || (c == '\n')) {
58444099b7bSPaul Traina 				goto done;
58544099b7bSPaul Traina 			}
58644099b7bSPaul Traina 		} while (isspace(c));	/* Skip whitespace */
58744099b7bSPaul Traina 
58844099b7bSPaul Traina 		if (c == '\\') {		/* Backslash quotes next character */
58944099b7bSPaul Traina 			c = fgetc(fp);
59044099b7bSPaul Traina 			if (c < 0) {
59144099b7bSPaul Traina 				goto done;
59244099b7bSPaul Traina 			}
59344099b7bSPaul Traina 			if (c == '\n') {
59444099b7bSPaul Traina 				goto top;		/* Backslash-newline continuation */
59544099b7bSPaul Traina 			}
59644099b7bSPaul Traina 		}
5977fed38d0SPhilippe Charnier 		/* FALLTHROUGH if "other" character */
59844099b7bSPaul Traina 	default:
59944099b7bSPaul Traina 		*buffer++ = c;			/* Store other characters */
60044099b7bSPaul Traina 		length++;
60144099b7bSPaul Traina 		if (length >= *bufsiz - 1) {
60244099b7bSPaul Traina 			goto done;
60344099b7bSPaul Traina 		}
60444099b7bSPaul Traina 	}
60544099b7bSPaul Traina 	goto mainloop;				/* Keep going */
60644099b7bSPaul Traina 
60744099b7bSPaul Traina   done:
60844099b7bSPaul Traina 	*buffer = '\0';				/* Terminate string */
60944099b7bSPaul Traina 	*bufsiz = length;			/* Tell the caller its length */
61044099b7bSPaul Traina }
61144099b7bSPaul Traina 
61244099b7bSPaul Traina 
61344099b7bSPaul Traina 
61444099b7bSPaul Traina /*
61544099b7bSPaul Traina  * Parse out all the various tags and parameters in the host entry pointed
61644099b7bSPaul Traina  * to by "src".  Stuff all the data into the appropriate fields of the
61744099b7bSPaul Traina  * host structure pointed to by "host".  If there is any problem with the
61844099b7bSPaul Traina  * entry, an error message is reported via report(), no further processing
61944099b7bSPaul Traina  * is done, and -1 is returned.  Successful calls return 0.
62044099b7bSPaul Traina  *
62144099b7bSPaul Traina  * (Some errors probably shouldn't be so completely fatal. . . .)
62244099b7bSPaul Traina  */
62344099b7bSPaul Traina 
62444099b7bSPaul Traina PRIVATE int
process_entry(struct host * host,char * src)625*8b356c88SJohn Baldwin process_entry(struct host *host, char *src)
62644099b7bSPaul Traina {
62744099b7bSPaul Traina 	int retval;
62844099b7bSPaul Traina 	char *msg;
62944099b7bSPaul Traina 
63044099b7bSPaul Traina 	if (!host || *src == '\0') {
63144099b7bSPaul Traina 		return -1;
63244099b7bSPaul Traina 	}
63344099b7bSPaul Traina 	host->hostname = get_shared_string(&src);
63444099b7bSPaul Traina #if 0
63544099b7bSPaul Traina 	/* Be more liberal for the benefit of dummy tag names. */
63644099b7bSPaul Traina 	if (!goodname(host->hostname->string)) {
63744099b7bSPaul Traina 		report(LOG_ERR, "bad hostname: \"%s\"", host->hostname->string);
63844099b7bSPaul Traina 		del_string(host->hostname);
63944099b7bSPaul Traina 		return -1;
64044099b7bSPaul Traina 	}
64144099b7bSPaul Traina #endif
64244099b7bSPaul Traina 	current_hostname = host->hostname->string;
64344099b7bSPaul Traina 	adjust(&src);
64444099b7bSPaul Traina 	while (TRUE) {
64544099b7bSPaul Traina 		retval = eval_symbol(&src, host);
64644099b7bSPaul Traina 		if (retval == SUCCESS) {
64744099b7bSPaul Traina 			adjust(&src);
64844099b7bSPaul Traina 			continue;
64944099b7bSPaul Traina 		}
65044099b7bSPaul Traina 		if (retval == E_END_OF_ENTRY) {
65144099b7bSPaul Traina 			/* The default subnet mask is set in readtab() */
65244099b7bSPaul Traina 			return 0;
65344099b7bSPaul Traina 		}
65444099b7bSPaul Traina 		/* Some kind of error. */
65544099b7bSPaul Traina 		switch (retval) {
65644099b7bSPaul Traina 		case E_SYNTAX_ERROR:
65744099b7bSPaul Traina 			msg = "bad syntax";
65844099b7bSPaul Traina 			break;
65944099b7bSPaul Traina 		case E_UNKNOWN_SYMBOL:
66044099b7bSPaul Traina 			msg = "unknown symbol";
66144099b7bSPaul Traina 			break;
66244099b7bSPaul Traina 		case E_BAD_IPADDR:
66344099b7bSPaul Traina 			msg = "bad INET address";
66444099b7bSPaul Traina 			break;
66544099b7bSPaul Traina 		case E_BAD_HWADDR:
66644099b7bSPaul Traina 			msg = "bad hardware address";
66744099b7bSPaul Traina 			break;
66844099b7bSPaul Traina 		case E_BAD_LONGWORD:
66944099b7bSPaul Traina 			msg = "bad longword value";
67044099b7bSPaul Traina 			break;
67144099b7bSPaul Traina 		case E_BAD_HWATYPE:
67244099b7bSPaul Traina 			msg = "bad HW address type";
67344099b7bSPaul Traina 			break;
67444099b7bSPaul Traina 		case E_BAD_PATHNAME:
67544099b7bSPaul Traina 			msg = "bad pathname (need leading '/')";
676c2c0f195SIan Dowse 			break;
67744099b7bSPaul Traina 		case E_BAD_VALUE:
67844099b7bSPaul Traina 			msg = "bad value";
679c2c0f195SIan Dowse 			break;
68044099b7bSPaul Traina 		default:
681c2c0f195SIan Dowse 			msg = "unknown error";
68244099b7bSPaul Traina 			break;
68344099b7bSPaul Traina 		}						/* switch */
68444099b7bSPaul Traina 		report(LOG_ERR, "in entry named \"%s\", symbol \"%s\": %s",
68544099b7bSPaul Traina 			   current_hostname, current_tagname, msg);
68644099b7bSPaul Traina 		return -1;
68744099b7bSPaul Traina 	}
68844099b7bSPaul Traina }
68944099b7bSPaul Traina 
69044099b7bSPaul Traina 
69144099b7bSPaul Traina /*
69244099b7bSPaul Traina  * Macros for use in the function below:
69344099b7bSPaul Traina  */
69444099b7bSPaul Traina 
69544099b7bSPaul Traina /* Parse one INET address stored directly in MEMBER. */
69644099b7bSPaul Traina #define PARSE_IA1(MEMBER) do \
69744099b7bSPaul Traina { \
69844099b7bSPaul Traina 	if (optype == OP_BOOLEAN) \
69944099b7bSPaul Traina 		return E_SYNTAX_ERROR; \
70044099b7bSPaul Traina 	hp->flags.MEMBER = FALSE; \
70144099b7bSPaul Traina 	if (optype == OP_ADDITION) { \
70244099b7bSPaul Traina 		if (prs_inetaddr(symbol, &value) < 0) \
70344099b7bSPaul Traina 			return E_BAD_IPADDR; \
70444099b7bSPaul Traina 		hp->MEMBER.s_addr = value; \
70544099b7bSPaul Traina 		hp->flags.MEMBER = TRUE; \
70644099b7bSPaul Traina 	} \
70744099b7bSPaul Traina } while (0)
70844099b7bSPaul Traina 
70944099b7bSPaul Traina /* Parse a list of INET addresses pointed to by MEMBER */
71044099b7bSPaul Traina #define PARSE_IAL(MEMBER) do \
71144099b7bSPaul Traina { \
71244099b7bSPaul Traina 	if (optype == OP_BOOLEAN) \
71344099b7bSPaul Traina 		return E_SYNTAX_ERROR; \
71444099b7bSPaul Traina 	if (hp->flags.MEMBER) { \
71544099b7bSPaul Traina 		hp->flags.MEMBER = FALSE; \
71644099b7bSPaul Traina 		assert(hp->MEMBER); \
71744099b7bSPaul Traina 		del_iplist(hp->MEMBER); \
71844099b7bSPaul Traina 		hp->MEMBER = NULL; \
71944099b7bSPaul Traina 	} \
72044099b7bSPaul Traina 	if (optype == OP_ADDITION) { \
72144099b7bSPaul Traina 		hp->MEMBER = get_addresses(symbol); \
72244099b7bSPaul Traina 		if (hp->MEMBER == NULL) \
72344099b7bSPaul Traina 			return E_SYNTAX_ERROR; \
72444099b7bSPaul Traina 		hp->flags.MEMBER = TRUE; \
72544099b7bSPaul Traina 	} \
72644099b7bSPaul Traina } while (0)
72744099b7bSPaul Traina 
72844099b7bSPaul Traina /* Parse a shared string pointed to by MEMBER */
72944099b7bSPaul Traina #define PARSE_STR(MEMBER) do \
73044099b7bSPaul Traina { \
73144099b7bSPaul Traina 	if (optype == OP_BOOLEAN) \
73244099b7bSPaul Traina 		return E_SYNTAX_ERROR; \
73344099b7bSPaul Traina 	if (hp->flags.MEMBER) { \
73444099b7bSPaul Traina 		hp->flags.MEMBER = FALSE; \
73544099b7bSPaul Traina 		assert(hp->MEMBER); \
73644099b7bSPaul Traina 		del_string(hp->MEMBER); \
73744099b7bSPaul Traina 		hp->MEMBER = NULL; \
73844099b7bSPaul Traina 	} \
73944099b7bSPaul Traina 	if (optype == OP_ADDITION) { \
74044099b7bSPaul Traina 		hp->MEMBER = get_shared_string(symbol); \
74144099b7bSPaul Traina 		if (hp->MEMBER == NULL) \
74244099b7bSPaul Traina 			return E_SYNTAX_ERROR; \
74344099b7bSPaul Traina 		hp->flags.MEMBER = TRUE; \
74444099b7bSPaul Traina 	} \
74544099b7bSPaul Traina } while (0)
74644099b7bSPaul Traina 
747e08ac58bSPaul Traina /* Parse an unsigned integer value for MEMBER */
748e08ac58bSPaul Traina #define PARSE_UINT(MEMBER) do \
74944099b7bSPaul Traina { \
75044099b7bSPaul Traina 	if (optype == OP_BOOLEAN) \
75144099b7bSPaul Traina 		return E_SYNTAX_ERROR; \
75244099b7bSPaul Traina 	hp->flags.MEMBER = FALSE; \
75344099b7bSPaul Traina 	if (optype == OP_ADDITION) { \
75444099b7bSPaul Traina 		value = get_u_long(symbol); \
75544099b7bSPaul Traina 		hp->MEMBER = value; \
75644099b7bSPaul Traina 		hp->flags.MEMBER = TRUE; \
75744099b7bSPaul Traina 	} \
75844099b7bSPaul Traina } while (0)
75944099b7bSPaul Traina 
76044099b7bSPaul Traina /*
76144099b7bSPaul Traina  * Evaluate the two-character tag symbol pointed to by "symbol" and place
76244099b7bSPaul Traina  * the data in the structure pointed to by "hp".  The pointer pointed to
76344099b7bSPaul Traina  * by "symbol" is updated to point past the source string (but may not
76444099b7bSPaul Traina  * point to the next tag entry).
76544099b7bSPaul Traina  *
76644099b7bSPaul Traina  * Obviously, this need a few more comments. . . .
76744099b7bSPaul Traina  */
76844099b7bSPaul Traina PRIVATE int
eval_symbol(char ** symbol,struct host * hp)769*8b356c88SJohn Baldwin eval_symbol(char **symbol, struct host *hp)
77044099b7bSPaul Traina {
77144099b7bSPaul Traina 	char tmpstr[MAXSTRINGLEN];
77244099b7bSPaul Traina 	byte *tmphaddr;
77344099b7bSPaul Traina 	struct symbolmap *symbolptr;
77444099b7bSPaul Traina 	u_int32 value;
77544099b7bSPaul Traina 	int32 timeoff;
77644099b7bSPaul Traina 	int i, numsymbols;
77744099b7bSPaul Traina 	unsigned len;
77844099b7bSPaul Traina 	int optype;					/* Indicates boolean, addition, or deletion */
77944099b7bSPaul Traina 
78044099b7bSPaul Traina 	eat_whitespace(symbol);
78144099b7bSPaul Traina 
78244099b7bSPaul Traina 	/* Make sure this is set before returning. */
78344099b7bSPaul Traina 	current_tagname[0] = (*symbol)[0];
78444099b7bSPaul Traina 	current_tagname[1] = (*symbol)[1];
78544099b7bSPaul Traina 	current_tagname[2] = 0;
78644099b7bSPaul Traina 
78744099b7bSPaul Traina 	if ((*symbol)[0] == '\0') {
78844099b7bSPaul Traina 		return E_END_OF_ENTRY;
78944099b7bSPaul Traina 	}
79044099b7bSPaul Traina 	if ((*symbol)[0] == ':') {
79144099b7bSPaul Traina 		return SUCCESS;
79244099b7bSPaul Traina 	}
79344099b7bSPaul Traina 	if ((*symbol)[0] == 'T') {	/* generic symbol */
79444099b7bSPaul Traina 		(*symbol)++;
79544099b7bSPaul Traina 		value = get_u_long(symbol);
7969bc34f7cSWarner Losh 		snprintf(current_tagname, sizeof(current_tagname),
7979bc34f7cSWarner Losh 			"T%d", (int)value);
79844099b7bSPaul Traina 		eat_whitespace(symbol);
79944099b7bSPaul Traina 		if ((*symbol)[0] != '=') {
80044099b7bSPaul Traina 			return E_SYNTAX_ERROR;
80144099b7bSPaul Traina 		}
80244099b7bSPaul Traina 		(*symbol)++;
80344099b7bSPaul Traina 		if (!(hp->generic)) {
80444099b7bSPaul Traina 			hp->generic = (struct shared_bindata *)
80544099b7bSPaul Traina 				smalloc(sizeof(struct shared_bindata));
80644099b7bSPaul Traina 		}
80744099b7bSPaul Traina 		if (process_generic(symbol, &(hp->generic), (byte) (value & 0xFF)))
80844099b7bSPaul Traina 			return E_SYNTAX_ERROR;
80944099b7bSPaul Traina 		hp->flags.generic = TRUE;
81044099b7bSPaul Traina 		return SUCCESS;
81144099b7bSPaul Traina 	}
81244099b7bSPaul Traina 	/*
81344099b7bSPaul Traina 	 * Determine the type of operation to be done on this symbol
81444099b7bSPaul Traina 	 */
81544099b7bSPaul Traina 	switch ((*symbol)[2]) {
81644099b7bSPaul Traina 	case '=':
81744099b7bSPaul Traina 		optype = OP_ADDITION;
81844099b7bSPaul Traina 		break;
81944099b7bSPaul Traina 	case '@':
82044099b7bSPaul Traina 		optype = OP_DELETION;
82144099b7bSPaul Traina 		break;
82244099b7bSPaul Traina 	case ':':
82344099b7bSPaul Traina 	case '\0':
82444099b7bSPaul Traina 		optype = OP_BOOLEAN;
82544099b7bSPaul Traina 		break;
82644099b7bSPaul Traina 	default:
82744099b7bSPaul Traina 		return E_SYNTAX_ERROR;
82844099b7bSPaul Traina 	}
82944099b7bSPaul Traina 
83044099b7bSPaul Traina 	symbolptr = symbol_list;
83144099b7bSPaul Traina 	numsymbols = sizeof(symbol_list) / sizeof(struct symbolmap);
83244099b7bSPaul Traina 	for (i = 0; i < numsymbols; i++) {
83344099b7bSPaul Traina 		if (((symbolptr->symbol)[0] == (*symbol)[0]) &&
83444099b7bSPaul Traina 			((symbolptr->symbol)[1] == (*symbol)[1])) {
83544099b7bSPaul Traina 			break;
83644099b7bSPaul Traina 		}
83744099b7bSPaul Traina 		symbolptr++;
83844099b7bSPaul Traina 	}
83944099b7bSPaul Traina 	if (i >= numsymbols) {
84044099b7bSPaul Traina 		return E_UNKNOWN_SYMBOL;
84144099b7bSPaul Traina 	}
84244099b7bSPaul Traina 	/*
84344099b7bSPaul Traina 	 * Skip past the = or @ character (to point to the data) if this
84444099b7bSPaul Traina 	 * isn't a boolean operation.  For boolean operations, just skip
84544099b7bSPaul Traina 	 * over the two-character tag symbol (and nothing else. . . .).
84644099b7bSPaul Traina 	 */
84744099b7bSPaul Traina 	(*symbol) += (optype == OP_BOOLEAN) ? 2 : 3;
84844099b7bSPaul Traina 
84944099b7bSPaul Traina 	eat_whitespace(symbol);
85044099b7bSPaul Traina 
85144099b7bSPaul Traina 	/* The cases below are in order by symbolcode value. */
85244099b7bSPaul Traina 	switch (symbolptr->symbolcode) {
85344099b7bSPaul Traina 
85444099b7bSPaul Traina 	case SYM_BOOTFILE:
85544099b7bSPaul Traina 		PARSE_STR(bootfile);
85644099b7bSPaul Traina 		break;
85744099b7bSPaul Traina 
85844099b7bSPaul Traina 	case SYM_COOKIE_SERVER:
85944099b7bSPaul Traina 		PARSE_IAL(cookie_server);
86044099b7bSPaul Traina 		break;
86144099b7bSPaul Traina 
86244099b7bSPaul Traina 	case SYM_DOMAIN_SERVER:
86344099b7bSPaul Traina 		PARSE_IAL(domain_server);
86444099b7bSPaul Traina 		break;
86544099b7bSPaul Traina 
86644099b7bSPaul Traina 	case SYM_GATEWAY:
86744099b7bSPaul Traina 		PARSE_IAL(gateway);
86844099b7bSPaul Traina 		break;
86944099b7bSPaul Traina 
87044099b7bSPaul Traina 	case SYM_HWADDR:
87144099b7bSPaul Traina 		if (optype == OP_BOOLEAN)
87244099b7bSPaul Traina 			return E_SYNTAX_ERROR;
87344099b7bSPaul Traina 		hp->flags.haddr = FALSE;
87444099b7bSPaul Traina 		if (optype == OP_ADDITION) {
87544099b7bSPaul Traina 			/* Default the HW type to Ethernet */
87644099b7bSPaul Traina 			if (hp->flags.htype == 0) {
87744099b7bSPaul Traina 				hp->flags.htype = TRUE;
87844099b7bSPaul Traina 				hp->htype = HTYPE_ETHERNET;
87944099b7bSPaul Traina 			}
88044099b7bSPaul Traina 			tmphaddr = prs_haddr(symbol, hp->htype);
88144099b7bSPaul Traina 			if (!tmphaddr)
88244099b7bSPaul Traina 				return E_BAD_HWADDR;
88344099b7bSPaul Traina 			bcopy(tmphaddr, hp->haddr, haddrlength(hp->htype));
88444099b7bSPaul Traina 			hp->flags.haddr = TRUE;
88544099b7bSPaul Traina 		}
88644099b7bSPaul Traina 		break;
88744099b7bSPaul Traina 
88844099b7bSPaul Traina 	case SYM_HOMEDIR:
88944099b7bSPaul Traina 		PARSE_STR(homedir);
89044099b7bSPaul Traina 		break;
89144099b7bSPaul Traina 
89244099b7bSPaul Traina 	case SYM_HTYPE:
89344099b7bSPaul Traina 		if (optype == OP_BOOLEAN)
89444099b7bSPaul Traina 			return E_SYNTAX_ERROR;
89544099b7bSPaul Traina 		hp->flags.htype = FALSE;
89644099b7bSPaul Traina 		if (optype == OP_ADDITION) {
89744099b7bSPaul Traina 			value = 0L;			/* Assume an illegal value */
89844099b7bSPaul Traina 			eat_whitespace(symbol);
89944099b7bSPaul Traina 			if (isdigit(**symbol)) {
90044099b7bSPaul Traina 				value = get_u_long(symbol);
90144099b7bSPaul Traina 			} else {
90244099b7bSPaul Traina 				len = sizeof(tmpstr);
90344099b7bSPaul Traina 				(void) get_string(symbol, tmpstr, &len);
90444099b7bSPaul Traina 				makelower(tmpstr);
90544099b7bSPaul Traina 				numsymbols = sizeof(htnamemap) /
90644099b7bSPaul Traina 					sizeof(struct htypename);
90744099b7bSPaul Traina 				for (i = 0; i < numsymbols; i++) {
90844099b7bSPaul Traina 					if (!strcmp(htnamemap[i].name, tmpstr)) {
90944099b7bSPaul Traina 						break;
91044099b7bSPaul Traina 					}
91144099b7bSPaul Traina 				}
91244099b7bSPaul Traina 				if (i < numsymbols) {
91344099b7bSPaul Traina 					value = htnamemap[i].htype;
91444099b7bSPaul Traina 				}
91544099b7bSPaul Traina 			}
91644099b7bSPaul Traina 			if (value >= hwinfocnt) {
91744099b7bSPaul Traina 				return E_BAD_HWATYPE;
91844099b7bSPaul Traina 			}
91944099b7bSPaul Traina 			hp->htype = (byte) (value & 0xFF);
92044099b7bSPaul Traina 			hp->flags.htype = TRUE;
92144099b7bSPaul Traina 		}
92244099b7bSPaul Traina 		break;
92344099b7bSPaul Traina 
92444099b7bSPaul Traina 	case SYM_IMPRESS_SERVER:
92544099b7bSPaul Traina 		PARSE_IAL(impress_server);
92644099b7bSPaul Traina 		break;
92744099b7bSPaul Traina 
92844099b7bSPaul Traina 	case SYM_IPADDR:
92944099b7bSPaul Traina 		PARSE_IA1(iaddr);
93044099b7bSPaul Traina 		break;
93144099b7bSPaul Traina 
93244099b7bSPaul Traina 	case SYM_LOG_SERVER:
93344099b7bSPaul Traina 		PARSE_IAL(log_server);
93444099b7bSPaul Traina 		break;
93544099b7bSPaul Traina 
93644099b7bSPaul Traina 	case SYM_LPR_SERVER:
93744099b7bSPaul Traina 		PARSE_IAL(lpr_server);
93844099b7bSPaul Traina 		break;
93944099b7bSPaul Traina 
94044099b7bSPaul Traina 	case SYM_NAME_SERVER:
94144099b7bSPaul Traina 		PARSE_IAL(name_server);
94244099b7bSPaul Traina 		break;
94344099b7bSPaul Traina 
94444099b7bSPaul Traina 	case SYM_RLP_SERVER:
94544099b7bSPaul Traina 		PARSE_IAL(rlp_server);
94644099b7bSPaul Traina 		break;
94744099b7bSPaul Traina 
94844099b7bSPaul Traina 	case SYM_SUBNET_MASK:
94944099b7bSPaul Traina 		PARSE_IA1(subnet_mask);
95044099b7bSPaul Traina 		break;
95144099b7bSPaul Traina 
95244099b7bSPaul Traina 	case SYM_TIME_OFFSET:
95344099b7bSPaul Traina 		if (optype == OP_BOOLEAN)
95444099b7bSPaul Traina 			return E_SYNTAX_ERROR;
95544099b7bSPaul Traina 		hp->flags.time_offset = FALSE;
95644099b7bSPaul Traina 		if (optype == OP_ADDITION) {
95744099b7bSPaul Traina 			len = sizeof(tmpstr);
95844099b7bSPaul Traina 			(void) get_string(symbol, tmpstr, &len);
95944099b7bSPaul Traina 			if (!strncmp(tmpstr, "auto", 4)) {
96044099b7bSPaul Traina 				hp->time_offset = secondswest;
96144099b7bSPaul Traina 			} else {
962e08ac58bSPaul Traina 				if (sscanf(tmpstr, "%d", (int*)&timeoff) != 1)
96344099b7bSPaul Traina 					return E_BAD_LONGWORD;
96444099b7bSPaul Traina 				hp->time_offset = timeoff;
96544099b7bSPaul Traina 			}
96644099b7bSPaul Traina 			hp->flags.time_offset = TRUE;
96744099b7bSPaul Traina 		}
96844099b7bSPaul Traina 		break;
96944099b7bSPaul Traina 
97044099b7bSPaul Traina 	case SYM_TIME_SERVER:
97144099b7bSPaul Traina 		PARSE_IAL(time_server);
97244099b7bSPaul Traina 		break;
97344099b7bSPaul Traina 
97444099b7bSPaul Traina 	case SYM_VENDOR_MAGIC:
97544099b7bSPaul Traina 		if (optype == OP_BOOLEAN)
97644099b7bSPaul Traina 			return E_SYNTAX_ERROR;
97744099b7bSPaul Traina 		hp->flags.vm_cookie = FALSE;
97844099b7bSPaul Traina 		if (optype == OP_ADDITION) {
97944099b7bSPaul Traina 			if (strncmp(*symbol, "auto", 4)) {
98044099b7bSPaul Traina 				/* The string is not "auto" */
98144099b7bSPaul Traina 				if (!strncmp(*symbol, "rfc", 3)) {
98244099b7bSPaul Traina 					bcopy(vm_rfc1048, hp->vm_cookie, 4);
98344099b7bSPaul Traina 				} else if (!strncmp(*symbol, "cmu", 3)) {
98444099b7bSPaul Traina 					bcopy(vm_cmu, hp->vm_cookie, 4);
98544099b7bSPaul Traina 				} else {
98644099b7bSPaul Traina 					if (!isdigit(**symbol))
98744099b7bSPaul Traina 						return E_BAD_IPADDR;
98844099b7bSPaul Traina 					if (prs_inetaddr(symbol, &value) < 0)
98944099b7bSPaul Traina 						return E_BAD_IPADDR;
99044099b7bSPaul Traina 					bcopy(&value, hp->vm_cookie, 4);
99144099b7bSPaul Traina 				}
99244099b7bSPaul Traina 				hp->flags.vm_cookie = TRUE;
99344099b7bSPaul Traina 			}
99444099b7bSPaul Traina 		}
99544099b7bSPaul Traina 		break;
99644099b7bSPaul Traina 
99744099b7bSPaul Traina 	case SYM_SIMILAR_ENTRY:
99844099b7bSPaul Traina 		switch (optype) {
99944099b7bSPaul Traina 		case OP_ADDITION:
100044099b7bSPaul Traina 			fill_defaults(hp, symbol);
100144099b7bSPaul Traina 			break;
100244099b7bSPaul Traina 		default:
100344099b7bSPaul Traina 			return E_SYNTAX_ERROR;
100444099b7bSPaul Traina 		}
100544099b7bSPaul Traina 		break;
100644099b7bSPaul Traina 
100744099b7bSPaul Traina 	case SYM_NAME_SWITCH:
100844099b7bSPaul Traina 		switch (optype) {
100944099b7bSPaul Traina 		case OP_ADDITION:
101044099b7bSPaul Traina 			return E_SYNTAX_ERROR;
101144099b7bSPaul Traina 		case OP_DELETION:
101244099b7bSPaul Traina 			hp->flags.send_name = FALSE;
101344099b7bSPaul Traina 			hp->flags.name_switch = FALSE;
101444099b7bSPaul Traina 			break;
101544099b7bSPaul Traina 		case OP_BOOLEAN:
101644099b7bSPaul Traina 			hp->flags.send_name = TRUE;
101744099b7bSPaul Traina 			hp->flags.name_switch = TRUE;
101844099b7bSPaul Traina 			break;
101944099b7bSPaul Traina 		}
102044099b7bSPaul Traina 		break;
102144099b7bSPaul Traina 
102244099b7bSPaul Traina 	case SYM_BOOTSIZE:
102344099b7bSPaul Traina 		switch (optype) {
102444099b7bSPaul Traina 		case OP_ADDITION:
102544099b7bSPaul Traina 			if (!strncmp(*symbol, "auto", 4)) {
102644099b7bSPaul Traina 				hp->flags.bootsize = TRUE;
102744099b7bSPaul Traina 				hp->flags.bootsize_auto = TRUE;
102844099b7bSPaul Traina 			} else {
102944099b7bSPaul Traina 				hp->bootsize = (unsigned int) get_u_long(symbol);
103044099b7bSPaul Traina 				hp->flags.bootsize = TRUE;
103144099b7bSPaul Traina 				hp->flags.bootsize_auto = FALSE;
103244099b7bSPaul Traina 			}
103344099b7bSPaul Traina 			break;
103444099b7bSPaul Traina 		case OP_DELETION:
103544099b7bSPaul Traina 			hp->flags.bootsize = FALSE;
103644099b7bSPaul Traina 			break;
103744099b7bSPaul Traina 		case OP_BOOLEAN:
103844099b7bSPaul Traina 			hp->flags.bootsize = TRUE;
103944099b7bSPaul Traina 			hp->flags.bootsize_auto = TRUE;
104044099b7bSPaul Traina 			break;
104144099b7bSPaul Traina 		}
104244099b7bSPaul Traina 		break;
104344099b7bSPaul Traina 
104444099b7bSPaul Traina 	case SYM_BOOT_SERVER:
104544099b7bSPaul Traina 		PARSE_IA1(bootserver);
104644099b7bSPaul Traina 		break;
104744099b7bSPaul Traina 
104844099b7bSPaul Traina 	case SYM_TFTPDIR:
104944099b7bSPaul Traina 		PARSE_STR(tftpdir);
105044099b7bSPaul Traina 		if ((hp->tftpdir != NULL) &&
105144099b7bSPaul Traina 			(hp->tftpdir->string[0] != '/'))
105244099b7bSPaul Traina 			return E_BAD_PATHNAME;
105344099b7bSPaul Traina 		break;
105444099b7bSPaul Traina 
105544099b7bSPaul Traina 	case SYM_DUMP_FILE:
105644099b7bSPaul Traina 		PARSE_STR(dump_file);
105744099b7bSPaul Traina 		break;
105844099b7bSPaul Traina 
105944099b7bSPaul Traina 	case SYM_DOMAIN_NAME:
106044099b7bSPaul Traina 		PARSE_STR(domain_name);
106144099b7bSPaul Traina 		break;
106244099b7bSPaul Traina 
106344099b7bSPaul Traina 	case SYM_SWAP_SERVER:
106444099b7bSPaul Traina 		PARSE_IA1(swap_server);
106544099b7bSPaul Traina 		break;
106644099b7bSPaul Traina 
106744099b7bSPaul Traina 	case SYM_ROOT_PATH:
106844099b7bSPaul Traina 		PARSE_STR(root_path);
106944099b7bSPaul Traina 		break;
107044099b7bSPaul Traina 
107144099b7bSPaul Traina 	case SYM_EXTEN_FILE:
107244099b7bSPaul Traina 		PARSE_STR(exten_file);
107344099b7bSPaul Traina 		break;
107444099b7bSPaul Traina 
107544099b7bSPaul Traina 	case SYM_REPLY_ADDR:
107644099b7bSPaul Traina 		PARSE_IA1(reply_addr);
107744099b7bSPaul Traina 		break;
107844099b7bSPaul Traina 
107944099b7bSPaul Traina 	case SYM_NIS_DOMAIN:
108044099b7bSPaul Traina 		PARSE_STR(nis_domain);
108144099b7bSPaul Traina 		break;
108244099b7bSPaul Traina 
108344099b7bSPaul Traina 	case SYM_NIS_SERVER:
108444099b7bSPaul Traina 		PARSE_IAL(nis_server);
108544099b7bSPaul Traina 		break;
108644099b7bSPaul Traina 
108744099b7bSPaul Traina 	case SYM_NTP_SERVER:
108844099b7bSPaul Traina 		PARSE_IAL(ntp_server);
108944099b7bSPaul Traina 		break;
109044099b7bSPaul Traina 
109144099b7bSPaul Traina #ifdef	YORK_EX_OPTION
109244099b7bSPaul Traina 	case SYM_EXEC_FILE:
109344099b7bSPaul Traina 		PARSE_STR(exec_file);
109444099b7bSPaul Traina 		break;
109544099b7bSPaul Traina #endif
109644099b7bSPaul Traina 
109744099b7bSPaul Traina 	case SYM_MSG_SIZE:
1098e08ac58bSPaul Traina 		PARSE_UINT(msg_size);
109944099b7bSPaul Traina 		if (hp->msg_size < BP_MINPKTSZ ||
110044099b7bSPaul Traina 			hp->msg_size > MAX_MSG_SIZE)
110144099b7bSPaul Traina 			return E_BAD_VALUE;
110244099b7bSPaul Traina 		break;
110344099b7bSPaul Traina 
110444099b7bSPaul Traina 	case SYM_MIN_WAIT:
1105e08ac58bSPaul Traina 		PARSE_UINT(min_wait);
110644099b7bSPaul Traina 		break;
110744099b7bSPaul Traina 
110844099b7bSPaul Traina 		/* XXX - Add new tags here */
110944099b7bSPaul Traina 
111044099b7bSPaul Traina 	default:
111144099b7bSPaul Traina 		return E_UNKNOWN_SYMBOL;
111244099b7bSPaul Traina 
111344099b7bSPaul Traina 	}							/* switch symbolcode */
111444099b7bSPaul Traina 
111544099b7bSPaul Traina 	return SUCCESS;
111644099b7bSPaul Traina }
111744099b7bSPaul Traina #undef	PARSE_IA1
111844099b7bSPaul Traina #undef	PARSE_IAL
111944099b7bSPaul Traina #undef	PARSE_STR
112044099b7bSPaul Traina 
112144099b7bSPaul Traina 
112244099b7bSPaul Traina 
112344099b7bSPaul Traina 
112444099b7bSPaul Traina /*
112544099b7bSPaul Traina  * Read a string from the buffer indirectly pointed to through "src" and
112644099b7bSPaul Traina  * move it into the buffer pointed to by "dest".  A pointer to the maximum
112744099b7bSPaul Traina  * allowable length of the string (including null-terminator) is passed as
112844099b7bSPaul Traina  * "length".  The actual length of the string which was read is returned in
112944099b7bSPaul Traina  * the unsigned integer pointed to by "length".  This value is the same as
113044099b7bSPaul Traina  * that which would be returned by applying the strlen() function on the
113144099b7bSPaul Traina  * destination string (i.e the terminating null is not counted as a
113244099b7bSPaul Traina  * character).  Trailing whitespace is removed from the string.  For
113344099b7bSPaul Traina  * convenience, the function returns the new value of "dest".
113444099b7bSPaul Traina  *
113544099b7bSPaul Traina  * The string is read until the maximum number of characters, an unquoted
113644099b7bSPaul Traina  * colon (:), or a null character is read.  The return string in "dest" is
113744099b7bSPaul Traina  * null-terminated.
113844099b7bSPaul Traina  */
113944099b7bSPaul Traina 
114044099b7bSPaul Traina PRIVATE char *
get_string(char ** src,char * dest,unsigned * length)1141*8b356c88SJohn Baldwin get_string(char **src, char *dest, unsigned *length)
114244099b7bSPaul Traina {
114344099b7bSPaul Traina 	int n, len, quoteflag;
114444099b7bSPaul Traina 
114544099b7bSPaul Traina 	quoteflag = FALSE;
114644099b7bSPaul Traina 	n = 0;
114744099b7bSPaul Traina 	len = *length - 1;
114844099b7bSPaul Traina 	while ((n < len) && (**src)) {
114944099b7bSPaul Traina 		if (!quoteflag && (**src == ':')) {
115044099b7bSPaul Traina 			break;
115144099b7bSPaul Traina 		}
115244099b7bSPaul Traina 		if (**src == '"') {
115344099b7bSPaul Traina 			(*src)++;
115444099b7bSPaul Traina 			quoteflag = !quoteflag;
115544099b7bSPaul Traina 			continue;
115644099b7bSPaul Traina 		}
115744099b7bSPaul Traina 		if (**src == '\\') {
115844099b7bSPaul Traina 			(*src)++;
115944099b7bSPaul Traina 			if (!**src) {
116044099b7bSPaul Traina 				break;
116144099b7bSPaul Traina 			}
116244099b7bSPaul Traina 		}
116344099b7bSPaul Traina 		*dest++ = *(*src)++;
116444099b7bSPaul Traina 		n++;
116544099b7bSPaul Traina 	}
116644099b7bSPaul Traina 
116744099b7bSPaul Traina 	/*
116844099b7bSPaul Traina 	 * Remove that troublesome trailing whitespace. . .
116944099b7bSPaul Traina 	 */
117044099b7bSPaul Traina 	while ((n > 0) && isspace(dest[-1])) {
117144099b7bSPaul Traina 		dest--;
117244099b7bSPaul Traina 		n--;
117344099b7bSPaul Traina 	}
117444099b7bSPaul Traina 
117544099b7bSPaul Traina 	*dest = '\0';
117644099b7bSPaul Traina 	*length = n;
117744099b7bSPaul Traina 	return dest;
117844099b7bSPaul Traina }
117944099b7bSPaul Traina 
118044099b7bSPaul Traina 
118144099b7bSPaul Traina 
118244099b7bSPaul Traina /*
118344099b7bSPaul Traina  * Read the string indirectly pointed to by "src", update the caller's
118444099b7bSPaul Traina  * pointer, and return a pointer to a malloc'ed shared_string structure
118544099b7bSPaul Traina  * containing the string.
118644099b7bSPaul Traina  *
118744099b7bSPaul Traina  * The string is read using the same rules as get_string() above.
118844099b7bSPaul Traina  */
118944099b7bSPaul Traina 
119044099b7bSPaul Traina PRIVATE struct shared_string *
get_shared_string(char ** src)1191*8b356c88SJohn Baldwin get_shared_string(char **src)
119244099b7bSPaul Traina {
119344099b7bSPaul Traina 	char retstring[MAXSTRINGLEN];
119444099b7bSPaul Traina 	struct shared_string *s;
119544099b7bSPaul Traina 	unsigned length;
119644099b7bSPaul Traina 
119744099b7bSPaul Traina 	length = sizeof(retstring);
119844099b7bSPaul Traina 	(void) get_string(src, retstring, &length);
119944099b7bSPaul Traina 
120044099b7bSPaul Traina 	s = (struct shared_string *) smalloc(sizeof(struct shared_string)
120144099b7bSPaul Traina 										 + length);
120244099b7bSPaul Traina 	s->linkcount = 1;
120344099b7bSPaul Traina 	strcpy(s->string, retstring);
120444099b7bSPaul Traina 
120544099b7bSPaul Traina 	return s;
120644099b7bSPaul Traina }
120744099b7bSPaul Traina 
120844099b7bSPaul Traina 
120944099b7bSPaul Traina 
121044099b7bSPaul Traina /*
121144099b7bSPaul Traina  * Load RFC1048 generic information directly into a memory buffer.
121244099b7bSPaul Traina  *
121344099b7bSPaul Traina  * "src" indirectly points to the ASCII representation of the generic data.
121444099b7bSPaul Traina  * "dest" points to a string structure which is updated to point to a new
121544099b7bSPaul Traina  * string with the new data appended to the old string.  The old string is
121644099b7bSPaul Traina  * freed.
121744099b7bSPaul Traina  *
121844099b7bSPaul Traina  * The given tag value is inserted with the new data.
121944099b7bSPaul Traina  *
122044099b7bSPaul Traina  * The data may be represented as either a stream of hexadecimal numbers
122144099b7bSPaul Traina  * representing bytes (any or all bytes may optionally start with '0x' and
122244099b7bSPaul Traina  * be separated with periods ".") or as a quoted string of ASCII
122344099b7bSPaul Traina  * characters (the quotes are required).
122444099b7bSPaul Traina  */
122544099b7bSPaul Traina 
122644099b7bSPaul Traina PRIVATE int
process_generic(char ** src,struct shared_bindata ** dest,u_int tagvalue)1227*8b356c88SJohn Baldwin process_generic(char **src, struct shared_bindata **dest, u_int tagvalue)
122844099b7bSPaul Traina {
122944099b7bSPaul Traina 	byte tmpbuf[MAXBUFLEN];
123044099b7bSPaul Traina 	byte *str;
123144099b7bSPaul Traina 	struct shared_bindata *bdata;
123244099b7bSPaul Traina 	u_int newlength, oldlength;
123344099b7bSPaul Traina 
123444099b7bSPaul Traina 	str = tmpbuf;
123544099b7bSPaul Traina 	*str++ = (tagvalue & 0xFF);	/* Store tag value */
123644099b7bSPaul Traina 	str++;						/* Skip over length field */
123744099b7bSPaul Traina 	if ((*src)[0] == '"') {		/* ASCII data */
123844099b7bSPaul Traina 		newlength = sizeof(tmpbuf) - 2;	/* Set maximum allowed length */
123944099b7bSPaul Traina 		(void) get_string(src, (char *) str, &newlength);
124044099b7bSPaul Traina 		newlength++;			/* null terminator */
124144099b7bSPaul Traina 	} else {					/* Numeric data */
124244099b7bSPaul Traina 		newlength = 0;
124344099b7bSPaul Traina 		while (newlength < sizeof(tmpbuf) - 2) {
124444099b7bSPaul Traina 			if (interp_byte(src, str++) < 0)
124544099b7bSPaul Traina 				break;
124644099b7bSPaul Traina 			newlength++;
124744099b7bSPaul Traina 			if (**src == '.') {
124844099b7bSPaul Traina 				(*src)++;
124944099b7bSPaul Traina 			}
125044099b7bSPaul Traina 		}
125144099b7bSPaul Traina 	}
125244099b7bSPaul Traina 	if ((*src)[0] != ':')
125344099b7bSPaul Traina 		return -1;
125444099b7bSPaul Traina 
125544099b7bSPaul Traina 	tmpbuf[1] = (newlength & 0xFF);
125644099b7bSPaul Traina 	oldlength = ((*dest)->length);
125744099b7bSPaul Traina 	bdata = (struct shared_bindata *) smalloc(sizeof(struct shared_bindata)
125844099b7bSPaul Traina 											+ oldlength + newlength + 1);
125944099b7bSPaul Traina 	if (oldlength > 0) {
126044099b7bSPaul Traina 		bcopy((*dest)->data, bdata->data, oldlength);
126144099b7bSPaul Traina 	}
126244099b7bSPaul Traina 	bcopy(tmpbuf, bdata->data + oldlength, newlength + 2);
126344099b7bSPaul Traina 	bdata->length = oldlength + newlength + 2;
126444099b7bSPaul Traina 	bdata->linkcount = 1;
126544099b7bSPaul Traina 	if (*dest) {
126644099b7bSPaul Traina 		del_bindata(*dest);
126744099b7bSPaul Traina 	}
126844099b7bSPaul Traina 	*dest = bdata;
126944099b7bSPaul Traina 	return 0;
127044099b7bSPaul Traina }
127144099b7bSPaul Traina 
127244099b7bSPaul Traina 
127344099b7bSPaul Traina 
127444099b7bSPaul Traina /*
127544099b7bSPaul Traina  * Verify that the given string makes sense as a hostname (according to
127644099b7bSPaul Traina  * Appendix 1, page 29 of RFC882).
127744099b7bSPaul Traina  *
127844099b7bSPaul Traina  * Return TRUE for good names, FALSE otherwise.
127944099b7bSPaul Traina  */
128044099b7bSPaul Traina 
128144099b7bSPaul Traina PRIVATE boolean
goodname(char * hostname)1282*8b356c88SJohn Baldwin goodname(char *hostname)
128344099b7bSPaul Traina {
128444099b7bSPaul Traina 	do {
128544099b7bSPaul Traina 		if (!isalpha(*hostname++)) {	/* First character must be a letter */
128644099b7bSPaul Traina 			return FALSE;
128744099b7bSPaul Traina 		}
128844099b7bSPaul Traina 		while (isalnum(*hostname) ||
128944099b7bSPaul Traina 			   (*hostname == '-') ||
129044099b7bSPaul Traina 			   (*hostname == '_') )
129144099b7bSPaul Traina 		{
129244099b7bSPaul Traina 			hostname++;			/* Alphanumeric or a hyphen */
129344099b7bSPaul Traina 		}
129444099b7bSPaul Traina 		if (!isalnum(hostname[-1])) {	/* Last must be alphanumeric */
129544099b7bSPaul Traina 			return FALSE;
129644099b7bSPaul Traina 		}
129744099b7bSPaul Traina 		if (*hostname == '\0') {/* Done? */
129844099b7bSPaul Traina 			return TRUE;
129944099b7bSPaul Traina 		}
130044099b7bSPaul Traina 	} while (*hostname++ == '.');	/* Dot, loop for next label */
130144099b7bSPaul Traina 
130244099b7bSPaul Traina 	return FALSE;				/* If it's not a dot, lose */
130344099b7bSPaul Traina }
130444099b7bSPaul Traina 
130544099b7bSPaul Traina 
130644099b7bSPaul Traina 
130744099b7bSPaul Traina /*
130844099b7bSPaul Traina  * Null compare function -- always returns FALSE so an element is always
130944099b7bSPaul Traina  * inserted into a hash table (i.e. there is never a collision with an
131044099b7bSPaul Traina  * existing element).
131144099b7bSPaul Traina  */
131244099b7bSPaul Traina 
131344099b7bSPaul Traina PRIVATE boolean
nullcmp(hash_datum * d1,hash_datum * d2)1314*8b356c88SJohn Baldwin nullcmp(hash_datum *d1, hash_datum *d2)
131544099b7bSPaul Traina {
131644099b7bSPaul Traina 	return FALSE;
131744099b7bSPaul Traina }
131844099b7bSPaul Traina 
131944099b7bSPaul Traina 
132044099b7bSPaul Traina /*
132144099b7bSPaul Traina  * Function for comparing a string with the hostname field of a host
132244099b7bSPaul Traina  * structure.
132344099b7bSPaul Traina  */
132444099b7bSPaul Traina 
132544099b7bSPaul Traina boolean
nmcmp(hash_datum * d1,hash_datum * d2)1326*8b356c88SJohn Baldwin nmcmp(hash_datum *d1, hash_datum *d2)
132744099b7bSPaul Traina {
132844099b7bSPaul Traina 	char *name = (char *) d1;	/* XXX - OK? */
132944099b7bSPaul Traina 	struct host *hp = (struct host *) d2;
133044099b7bSPaul Traina 
133144099b7bSPaul Traina 	return !strcmp(name, hp->hostname->string);
133244099b7bSPaul Traina }
133344099b7bSPaul Traina 
133444099b7bSPaul Traina 
133544099b7bSPaul Traina /*
133644099b7bSPaul Traina  * Compare function to determine whether two hardware addresses are
133744099b7bSPaul Traina  * equivalent.  Returns TRUE if "host1" and "host2" are equivalent, FALSE
133844099b7bSPaul Traina  * otherwise.
133944099b7bSPaul Traina  *
134044099b7bSPaul Traina  * If the hardware addresses of "host1" and "host2" are identical, but
134144099b7bSPaul Traina  * they are on different IP subnets, this function returns FALSE.
134244099b7bSPaul Traina  *
134344099b7bSPaul Traina  * This function is used when inserting elements into the hardware address
134444099b7bSPaul Traina  * hash table.
134544099b7bSPaul Traina  */
134644099b7bSPaul Traina 
134744099b7bSPaul Traina PRIVATE boolean
hwinscmp(hash_datum * d1,hash_datum * d2)1348*8b356c88SJohn Baldwin hwinscmp(hash_datum *d1, hash_datum *d2)
134944099b7bSPaul Traina {
135044099b7bSPaul Traina 	struct host *host1 = (struct host *) d1;
135144099b7bSPaul Traina 	struct host *host2 = (struct host *) d2;
135244099b7bSPaul Traina 
135344099b7bSPaul Traina 	if (host1->htype != host2->htype) {
135444099b7bSPaul Traina 		return FALSE;
135544099b7bSPaul Traina 	}
135644099b7bSPaul Traina 	if (bcmp(host1->haddr, host2->haddr, haddrlength(host1->htype))) {
135744099b7bSPaul Traina 		return FALSE;
135844099b7bSPaul Traina 	}
135944099b7bSPaul Traina 	/* XXX - Is the subnet_mask field set yet? */
136044099b7bSPaul Traina 	if ((host1->subnet_mask.s_addr) == (host2->subnet_mask.s_addr)) {
136144099b7bSPaul Traina 		if (((host1->iaddr.s_addr) & (host1->subnet_mask.s_addr)) !=
136244099b7bSPaul Traina 			((host2->iaddr.s_addr) & (host2->subnet_mask.s_addr)))
136344099b7bSPaul Traina 		{
136444099b7bSPaul Traina 			return FALSE;
136544099b7bSPaul Traina 		}
136644099b7bSPaul Traina 	}
136744099b7bSPaul Traina 	return TRUE;
136844099b7bSPaul Traina }
136944099b7bSPaul Traina 
137044099b7bSPaul Traina 
137144099b7bSPaul Traina /*
137244099b7bSPaul Traina  * Macros for use in the function below:
137344099b7bSPaul Traina  */
137444099b7bSPaul Traina 
137544099b7bSPaul Traina #define DUP_COPY(MEMBER) do \
137644099b7bSPaul Traina { \
137744099b7bSPaul Traina 	if (!hp->flags.MEMBER) { \
137844099b7bSPaul Traina 		if ((hp->flags.MEMBER = hp2->flags.MEMBER) != 0) { \
137944099b7bSPaul Traina 			hp->MEMBER = hp2->MEMBER; \
138044099b7bSPaul Traina 		} \
138144099b7bSPaul Traina 	} \
138244099b7bSPaul Traina } while (0)
138344099b7bSPaul Traina 
138444099b7bSPaul Traina #define DUP_LINK(MEMBER) do \
138544099b7bSPaul Traina { \
138644099b7bSPaul Traina 	if (!hp->flags.MEMBER) { \
138744099b7bSPaul Traina 		if ((hp->flags.MEMBER = hp2->flags.MEMBER) != 0) { \
138844099b7bSPaul Traina 			assert(hp2->MEMBER); \
138944099b7bSPaul Traina 			hp->MEMBER = hp2->MEMBER; \
139044099b7bSPaul Traina 			(hp->MEMBER->linkcount)++; \
139144099b7bSPaul Traina 		} \
139244099b7bSPaul Traina 	} \
139344099b7bSPaul Traina } while (0)
139444099b7bSPaul Traina 
139544099b7bSPaul Traina /*
139644099b7bSPaul Traina  * Process the "similar entry" symbol.
139744099b7bSPaul Traina  *
139844099b7bSPaul Traina  * The host specified as the value of the "tc" symbol is used as a template
139944099b7bSPaul Traina  * for the current host entry.  Symbol values not explicitly set in the
140044099b7bSPaul Traina  * current host entry are inferred from the template entry.
140144099b7bSPaul Traina  */
140244099b7bSPaul Traina PRIVATE void
fill_defaults(struct host * hp,char ** src)1403*8b356c88SJohn Baldwin fill_defaults(struct host *hp, char **src)
140444099b7bSPaul Traina {
140544099b7bSPaul Traina 	unsigned int tlen, hashcode;
140644099b7bSPaul Traina 	struct host *hp2;
140744099b7bSPaul Traina 	char tstring[MAXSTRINGLEN];
140844099b7bSPaul Traina 
140944099b7bSPaul Traina 	tlen = sizeof(tstring);
141044099b7bSPaul Traina 	(void) get_string(src, tstring, &tlen);
141144099b7bSPaul Traina 	hashcode = hash_HashFunction((u_char *) tstring, tlen);
141244099b7bSPaul Traina 	hp2 = (struct host *) hash_Lookup(nmhashtable, hashcode, nmcmp, tstring);
141344099b7bSPaul Traina 
141444099b7bSPaul Traina 	if (hp2 == NULL) {
141544099b7bSPaul Traina 		report(LOG_ERR, "can't find tc=\"%s\"", tstring);
141644099b7bSPaul Traina 		return;
141744099b7bSPaul Traina 	}
141844099b7bSPaul Traina 	DUP_LINK(bootfile);
141944099b7bSPaul Traina 	DUP_LINK(cookie_server);
142044099b7bSPaul Traina 	DUP_LINK(domain_server);
142144099b7bSPaul Traina 	DUP_LINK(gateway);
142244099b7bSPaul Traina 	/* haddr not copied */
142344099b7bSPaul Traina 	DUP_LINK(homedir);
142444099b7bSPaul Traina 	DUP_COPY(htype);
142544099b7bSPaul Traina 
142644099b7bSPaul Traina 	DUP_LINK(impress_server);
142744099b7bSPaul Traina 	/* iaddr not copied */
142844099b7bSPaul Traina 	DUP_LINK(log_server);
142944099b7bSPaul Traina 	DUP_LINK(lpr_server);
143044099b7bSPaul Traina 	DUP_LINK(name_server);
143144099b7bSPaul Traina 	DUP_LINK(rlp_server);
143244099b7bSPaul Traina 
143344099b7bSPaul Traina 	DUP_COPY(subnet_mask);
143444099b7bSPaul Traina 	DUP_COPY(time_offset);
143544099b7bSPaul Traina 	DUP_LINK(time_server);
143644099b7bSPaul Traina 
143744099b7bSPaul Traina 	if (!hp->flags.vm_cookie) {
143844099b7bSPaul Traina 		if ((hp->flags.vm_cookie = hp2->flags.vm_cookie)) {
143944099b7bSPaul Traina 			bcopy(hp2->vm_cookie, hp->vm_cookie, 4);
144044099b7bSPaul Traina 		}
144144099b7bSPaul Traina 	}
144244099b7bSPaul Traina 	if (!hp->flags.name_switch) {
144344099b7bSPaul Traina 		if ((hp->flags.name_switch = hp2->flags.name_switch)) {
144444099b7bSPaul Traina 			hp->flags.send_name = hp2->flags.send_name;
144544099b7bSPaul Traina 		}
144644099b7bSPaul Traina 	}
144744099b7bSPaul Traina 	if (!hp->flags.bootsize) {
144844099b7bSPaul Traina 		if ((hp->flags.bootsize = hp2->flags.bootsize)) {
144944099b7bSPaul Traina 			hp->flags.bootsize_auto = hp2->flags.bootsize_auto;
145044099b7bSPaul Traina 			hp->bootsize = hp2->bootsize;
145144099b7bSPaul Traina 		}
145244099b7bSPaul Traina 	}
145344099b7bSPaul Traina 	DUP_COPY(bootserver);
145444099b7bSPaul Traina 
145544099b7bSPaul Traina 	DUP_LINK(tftpdir);
145644099b7bSPaul Traina 	DUP_LINK(dump_file);
145744099b7bSPaul Traina 	DUP_LINK(domain_name);
145844099b7bSPaul Traina 
145944099b7bSPaul Traina 	DUP_COPY(swap_server);
146044099b7bSPaul Traina 	DUP_LINK(root_path);
146144099b7bSPaul Traina 	DUP_LINK(exten_file);
146244099b7bSPaul Traina 
146344099b7bSPaul Traina 	DUP_COPY(reply_addr);
146444099b7bSPaul Traina 
146544099b7bSPaul Traina 	DUP_LINK(nis_domain);
146644099b7bSPaul Traina 	DUP_LINK(nis_server);
146744099b7bSPaul Traina 	DUP_LINK(ntp_server);
146844099b7bSPaul Traina 
146944099b7bSPaul Traina #ifdef	YORK_EX_OPTION
147044099b7bSPaul Traina 	DUP_LINK(exec_file);
147144099b7bSPaul Traina #endif
147244099b7bSPaul Traina 
147344099b7bSPaul Traina 	DUP_COPY(msg_size);
147444099b7bSPaul Traina 	DUP_COPY(min_wait);
147544099b7bSPaul Traina 
147644099b7bSPaul Traina 	/* XXX - Add new tags here */
147744099b7bSPaul Traina 
147844099b7bSPaul Traina 	DUP_LINK(generic);
147944099b7bSPaul Traina 
148044099b7bSPaul Traina }
148144099b7bSPaul Traina #undef	DUP_COPY
148244099b7bSPaul Traina #undef	DUP_LINK
148344099b7bSPaul Traina 
148444099b7bSPaul Traina 
148544099b7bSPaul Traina 
148644099b7bSPaul Traina /*
148744099b7bSPaul Traina  * This function adjusts the caller's pointer to point just past the
148844099b7bSPaul Traina  * first-encountered colon.  If it runs into a null character, it leaves
148944099b7bSPaul Traina  * the pointer pointing to it.
149044099b7bSPaul Traina  */
149144099b7bSPaul Traina 
149244099b7bSPaul Traina PRIVATE void
adjust(char ** s)1493*8b356c88SJohn Baldwin adjust(char **s)
149444099b7bSPaul Traina {
149507ee9f80SPedro F. Giffuni 	char *t;
149644099b7bSPaul Traina 
149744099b7bSPaul Traina 	t = *s;
149844099b7bSPaul Traina 	while (*t && (*t != ':')) {
149944099b7bSPaul Traina 		t++;
150044099b7bSPaul Traina 	}
150144099b7bSPaul Traina 	if (*t) {
150244099b7bSPaul Traina 		t++;
150344099b7bSPaul Traina 	}
150444099b7bSPaul Traina 	*s = t;
150544099b7bSPaul Traina }
150644099b7bSPaul Traina 
150744099b7bSPaul Traina 
150844099b7bSPaul Traina 
150944099b7bSPaul Traina 
151044099b7bSPaul Traina /*
151144099b7bSPaul Traina  * This function adjusts the caller's pointer to point to the first
151244099b7bSPaul Traina  * non-whitespace character.  If it runs into a null character, it leaves
151344099b7bSPaul Traina  * the pointer pointing to it.
151444099b7bSPaul Traina  */
151544099b7bSPaul Traina 
151644099b7bSPaul Traina PRIVATE void
eat_whitespace(char ** s)1517*8b356c88SJohn Baldwin eat_whitespace(char **s)
151844099b7bSPaul Traina {
151907ee9f80SPedro F. Giffuni 	char *t;
152044099b7bSPaul Traina 
152144099b7bSPaul Traina 	t = *s;
152244099b7bSPaul Traina 	while (*t && isspace(*t)) {
152344099b7bSPaul Traina 		t++;
152444099b7bSPaul Traina 	}
152544099b7bSPaul Traina 	*s = t;
152644099b7bSPaul Traina }
152744099b7bSPaul Traina 
152844099b7bSPaul Traina 
152944099b7bSPaul Traina 
153044099b7bSPaul Traina /*
153144099b7bSPaul Traina  * This function converts the given string to all lowercase.
153244099b7bSPaul Traina  */
153344099b7bSPaul Traina 
153444099b7bSPaul Traina PRIVATE void
makelower(char * s)1535*8b356c88SJohn Baldwin makelower(char *s)
153644099b7bSPaul Traina {
153744099b7bSPaul Traina 	while (*s) {
153844099b7bSPaul Traina 		if (isupper(*s)) {
153944099b7bSPaul Traina 			*s = tolower(*s);
154044099b7bSPaul Traina 		}
154144099b7bSPaul Traina 		s++;
154244099b7bSPaul Traina 	}
154344099b7bSPaul Traina }
154444099b7bSPaul Traina 
154544099b7bSPaul Traina 
154644099b7bSPaul Traina 
154744099b7bSPaul Traina /*
154844099b7bSPaul Traina  *
154944099b7bSPaul Traina  *	N O T E :
155044099b7bSPaul Traina  *
155144099b7bSPaul Traina  *	In many of the functions which follow, a parameter such as "src" or
155244099b7bSPaul Traina  *	"symbol" is passed as a pointer to a pointer to something.  This is
155344099b7bSPaul Traina  *	done for the purpose of letting the called function update the
155444099b7bSPaul Traina  *	caller's copy of the parameter (i.e. to effect call-by-reference
155544099b7bSPaul Traina  *	parameter passing).  The value of the actual parameter is only used
155644099b7bSPaul Traina  *	to locate the real parameter of interest and then update this indirect
155744099b7bSPaul Traina  *	parameter.
155844099b7bSPaul Traina  *
155944099b7bSPaul Traina  *	I'm sure somebody out there won't like this. . . .
156044099b7bSPaul Traina  *  (Yea, because it usually makes code slower... -gwr)
156144099b7bSPaul Traina  *
156244099b7bSPaul Traina  */
156344099b7bSPaul Traina 
156444099b7bSPaul Traina 
156544099b7bSPaul Traina 
156644099b7bSPaul Traina /*
156744099b7bSPaul Traina  * "src" points to a character pointer which points to an ASCII string of
156844099b7bSPaul Traina  * whitespace-separated IP addresses.  A pointer to an in_addr_list
156944099b7bSPaul Traina  * structure containing the list of addresses is returned.  NULL is
157044099b7bSPaul Traina  * returned if no addresses were found at all.  The pointer pointed to by
157144099b7bSPaul Traina  * "src" is updated to point to the first non-address (illegal) character.
157244099b7bSPaul Traina  */
157344099b7bSPaul Traina 
157444099b7bSPaul Traina PRIVATE struct in_addr_list *
get_addresses(char ** src)1575*8b356c88SJohn Baldwin get_addresses(char **src)
157644099b7bSPaul Traina {
157744099b7bSPaul Traina 	struct in_addr tmpaddrlist[MAXINADDRS];
157844099b7bSPaul Traina 	struct in_addr *address1, *address2;
157944099b7bSPaul Traina 	struct in_addr_list *result;
158044099b7bSPaul Traina 	unsigned addrcount, totalsize;
158144099b7bSPaul Traina 
158244099b7bSPaul Traina 	address1 = tmpaddrlist;
158344099b7bSPaul Traina 	for (addrcount = 0; addrcount < MAXINADDRS; addrcount++) {
158444099b7bSPaul Traina 		while (isspace(**src) || (**src == ',')) {
158544099b7bSPaul Traina 			(*src)++;
158644099b7bSPaul Traina 		}
158744099b7bSPaul Traina 		if (!**src) {			/* Quit if nothing more */
158844099b7bSPaul Traina 			break;
158944099b7bSPaul Traina 		}
159044099b7bSPaul Traina 		if (prs_inetaddr(src, &(address1->s_addr)) < 0) {
159144099b7bSPaul Traina 			break;
159244099b7bSPaul Traina 		}
159344099b7bSPaul Traina 		address1++;				/* Point to next address slot */
159444099b7bSPaul Traina 	}
159544099b7bSPaul Traina 	if (addrcount < 1) {
159644099b7bSPaul Traina 		result = NULL;
159744099b7bSPaul Traina 	} else {
159844099b7bSPaul Traina 		totalsize = sizeof(struct in_addr_list)
159944099b7bSPaul Traina 		+			(addrcount - 1) * sizeof(struct in_addr);
160044099b7bSPaul Traina 		result = (struct in_addr_list *) smalloc(totalsize);
160144099b7bSPaul Traina 		result->linkcount = 1;
160244099b7bSPaul Traina 		result->addrcount = addrcount;
160344099b7bSPaul Traina 		address1 = tmpaddrlist;
160444099b7bSPaul Traina 		address2 = result->addr;
160544099b7bSPaul Traina 		for (; addrcount > 0; addrcount--) {
160644099b7bSPaul Traina 			address2->s_addr = address1->s_addr;
160744099b7bSPaul Traina 			address1++;
160844099b7bSPaul Traina 			address2++;
160944099b7bSPaul Traina 		}
161044099b7bSPaul Traina 	}
161144099b7bSPaul Traina 	return result;
161244099b7bSPaul Traina }
161344099b7bSPaul Traina 
161444099b7bSPaul Traina 
161544099b7bSPaul Traina 
161644099b7bSPaul Traina /*
161744099b7bSPaul Traina  * prs_inetaddr(src, result)
161844099b7bSPaul Traina  *
161944099b7bSPaul Traina  * "src" is a value-result parameter; the pointer it points to is updated
162044099b7bSPaul Traina  * to point to the next data position.   "result" points to an unsigned long
162144099b7bSPaul Traina  * in which an address is returned.
162244099b7bSPaul Traina  *
162344099b7bSPaul Traina  * This function parses the IP address string in ASCII "dot notation" pointed
162444099b7bSPaul Traina  * to by (*src) and places the result (in network byte order) in the unsigned
162544099b7bSPaul Traina  * long pointed to by "result".  For malformed addresses, -1 is returned,
162644099b7bSPaul Traina  * (*src) points to the first illegal character, and the unsigned long pointed
162744099b7bSPaul Traina  * to by "result" is unchanged.  Successful calls return 0.
162844099b7bSPaul Traina  */
162944099b7bSPaul Traina 
163044099b7bSPaul Traina PRIVATE int
prs_inetaddr(char ** src,u_int32 * result)1631*8b356c88SJohn Baldwin prs_inetaddr(char **src, u_int32 *result)
163244099b7bSPaul Traina {
163344099b7bSPaul Traina 	char tmpstr[MAXSTRINGLEN];
163407ee9f80SPedro F. Giffuni 	u_int32 value;
163544099b7bSPaul Traina 	u_int32 parts[4], *pp;
163644099b7bSPaul Traina 	int n;
163744099b7bSPaul Traina 	char *s, *t;
163844099b7bSPaul Traina 
163944099b7bSPaul Traina 	/* Leading alpha char causes IP addr lookup. */
164044099b7bSPaul Traina 	if (isalpha(**src)) {
164144099b7bSPaul Traina 		/* Lookup IP address. */
164244099b7bSPaul Traina 		s = *src;
164344099b7bSPaul Traina 		t = tmpstr;
164444099b7bSPaul Traina 		while ((isalnum(*s) || (*s == '.') ||
164544099b7bSPaul Traina 				(*s == '-') || (*s == '_') ) &&
164644099b7bSPaul Traina 			   (t < &tmpstr[MAXSTRINGLEN - 1]) )
164744099b7bSPaul Traina 			*t++ = *s++;
164844099b7bSPaul Traina 		*t = '\0';
164944099b7bSPaul Traina 		*src = s;
165044099b7bSPaul Traina 
165144099b7bSPaul Traina 		n = lookup_ipa(tmpstr, result);
165244099b7bSPaul Traina 		if (n < 0)
165344099b7bSPaul Traina 			report(LOG_ERR, "can not get IP addr for %s", tmpstr);
165444099b7bSPaul Traina 		return n;
165544099b7bSPaul Traina 	}
165644099b7bSPaul Traina 
165744099b7bSPaul Traina 	/*
165844099b7bSPaul Traina 	 * Parse an address in Internet format:
165944099b7bSPaul Traina 	 *	a.b.c.d
166044099b7bSPaul Traina 	 *	a.b.c	(with c treated as 16-bits)
166144099b7bSPaul Traina 	 *	a.b	(with b treated as 24 bits)
166244099b7bSPaul Traina 	 */
166344099b7bSPaul Traina 	pp = parts;
166444099b7bSPaul Traina   loop:
166544099b7bSPaul Traina 	/* If it's not a digit, return error. */
166644099b7bSPaul Traina 	if (!isdigit(**src))
166744099b7bSPaul Traina 		return -1;
166844099b7bSPaul Traina 	*pp++ = get_u_long(src);
166944099b7bSPaul Traina 	if (**src == '.') {
167044099b7bSPaul Traina 		if (pp < (parts + 4)) {
167144099b7bSPaul Traina 			(*src)++;
167244099b7bSPaul Traina 			goto loop;
167344099b7bSPaul Traina 		}
167444099b7bSPaul Traina 		return (-1);
167544099b7bSPaul Traina 	}
167644099b7bSPaul Traina #if 0
167744099b7bSPaul Traina 	/* This is handled by the caller. */
167844099b7bSPaul Traina 	if (**src && !(isspace(**src) || (**src == ':'))) {
167944099b7bSPaul Traina 		return (-1);
168044099b7bSPaul Traina 	}
168144099b7bSPaul Traina #endif
168244099b7bSPaul Traina 
168344099b7bSPaul Traina 	/*
168444099b7bSPaul Traina 	 * Construct the address according to
168544099b7bSPaul Traina 	 * the number of parts specified.
168644099b7bSPaul Traina 	 */
168744099b7bSPaul Traina 	n = pp - parts;
168844099b7bSPaul Traina 	switch (n) {
168944099b7bSPaul Traina 	case 1:					/* a -- 32 bits */
169044099b7bSPaul Traina 		value = parts[0];
169144099b7bSPaul Traina 		break;
169244099b7bSPaul Traina 	case 2:					/* a.b -- 8.24 bits */
169344099b7bSPaul Traina 		value = (parts[0] << 24) | (parts[1] & 0xFFFFFF);
169444099b7bSPaul Traina 		break;
169544099b7bSPaul Traina 	case 3:					/* a.b.c -- 8.8.16 bits */
169644099b7bSPaul Traina 		value = (parts[0] << 24) | ((parts[1] & 0xFF) << 16) |
169744099b7bSPaul Traina 			(parts[2] & 0xFFFF);
169844099b7bSPaul Traina 		break;
169944099b7bSPaul Traina 	case 4:					/* a.b.c.d -- 8.8.8.8 bits */
170044099b7bSPaul Traina 		value = (parts[0] << 24) | ((parts[1] & 0xFF) << 16) |
170144099b7bSPaul Traina 			((parts[2] & 0xFF) << 8) | (parts[3] & 0xFF);
170244099b7bSPaul Traina 		break;
170344099b7bSPaul Traina 	default:
170444099b7bSPaul Traina 		return (-1);
170544099b7bSPaul Traina 	}
170644099b7bSPaul Traina 	*result = htonl(value);
170744099b7bSPaul Traina 	return (0);
170844099b7bSPaul Traina }
170944099b7bSPaul Traina 
171044099b7bSPaul Traina 
171144099b7bSPaul Traina 
171244099b7bSPaul Traina /*
171344099b7bSPaul Traina  * "src" points to a pointer which in turn points to a hexadecimal ASCII
171444099b7bSPaul Traina  * string.  This string is interpreted as a hardware address and returned
171544099b7bSPaul Traina  * as a pointer to the actual hardware address, represented as an array of
171644099b7bSPaul Traina  * bytes.
171744099b7bSPaul Traina  *
171844099b7bSPaul Traina  * The ASCII string must have the proper number of digits for the specified
171944099b7bSPaul Traina  * hardware type (e.g. twelve digits for a 48-bit Ethernet address).
172044099b7bSPaul Traina  * Two-digit sequences (bytes) may be separated with periods (.)  and/or
172144099b7bSPaul Traina  * prefixed with '0x' for readability, but this is not required.
172244099b7bSPaul Traina  *
172344099b7bSPaul Traina  * For bad addresses, the pointer which "src" points to is updated to point
172444099b7bSPaul Traina  * to the start of the first two-digit sequence which was bad, and the
172544099b7bSPaul Traina  * function returns a NULL pointer.
172644099b7bSPaul Traina  */
172744099b7bSPaul Traina 
172844099b7bSPaul Traina PRIVATE byte *
prs_haddr(char ** src,u_int htype)1729*8b356c88SJohn Baldwin prs_haddr(char **src, u_int htype)
173044099b7bSPaul Traina {
173144099b7bSPaul Traina 	static byte haddr[MAXHADDRLEN];
173244099b7bSPaul Traina 	byte *hap;
173344099b7bSPaul Traina 	char tmpstr[MAXSTRINGLEN];
173444099b7bSPaul Traina 	u_int tmplen;
173544099b7bSPaul Traina 	unsigned hal;
173644099b7bSPaul Traina 	char *p;
173744099b7bSPaul Traina 
173844099b7bSPaul Traina 	hal = haddrlength(htype);	/* Get length of this address type */
173944099b7bSPaul Traina 	if (hal <= 0) {
174044099b7bSPaul Traina 		report(LOG_ERR, "Invalid addr type for HW addr parse");
174144099b7bSPaul Traina 		return NULL;
174244099b7bSPaul Traina 	}
174344099b7bSPaul Traina 	tmplen = sizeof(tmpstr);
174444099b7bSPaul Traina 	get_string(src, tmpstr, &tmplen);
174544099b7bSPaul Traina 	p = tmpstr;
174644099b7bSPaul Traina 
174744099b7bSPaul Traina 	/* If it's a valid host name, try to lookup the HW address. */
174844099b7bSPaul Traina 	if (goodname(p)) {
174944099b7bSPaul Traina 		/* Lookup Hardware Address for hostname. */
175044099b7bSPaul Traina 		if ((hap = lookup_hwa(p, htype)) != NULL)
175144099b7bSPaul Traina 			return hap; /* success */
175244099b7bSPaul Traina 		report(LOG_ERR, "Add 0x prefix if hex value starts with A-F");
175344099b7bSPaul Traina 		/* OK, assume it must be numeric. */
175444099b7bSPaul Traina 	}
175544099b7bSPaul Traina 
175644099b7bSPaul Traina 	hap = haddr;
175744099b7bSPaul Traina 	while (hap < haddr + hal) {
1758e08ac58bSPaul Traina 		if ((*p == '.') || (*p == ':'))
175944099b7bSPaul Traina 			p++;
176044099b7bSPaul Traina 		if (interp_byte(&p, hap++) < 0) {
176144099b7bSPaul Traina 			return NULL;
176244099b7bSPaul Traina 		}
176344099b7bSPaul Traina 	}
176444099b7bSPaul Traina 	return haddr;
176544099b7bSPaul Traina }
176644099b7bSPaul Traina 
176744099b7bSPaul Traina 
176844099b7bSPaul Traina 
176944099b7bSPaul Traina /*
177044099b7bSPaul Traina  * "src" is a pointer to a character pointer which in turn points to a
177144099b7bSPaul Traina  * hexadecimal ASCII representation of a byte.  This byte is read, the
177244099b7bSPaul Traina  * character pointer is updated, and the result is deposited into the
177344099b7bSPaul Traina  * byte pointed to by "retbyte".
177444099b7bSPaul Traina  *
177544099b7bSPaul Traina  * The usual '0x' notation is allowed but not required.  The number must be
177644099b7bSPaul Traina  * a two digit hexadecimal number.  If the number is invalid, "src" and
177744099b7bSPaul Traina  * "retbyte" are left untouched and -1 is returned as the function value.
177844099b7bSPaul Traina  * Successful calls return 0.
177944099b7bSPaul Traina  */
178044099b7bSPaul Traina 
178144099b7bSPaul Traina PRIVATE int
interp_byte(char ** src,byte * retbyte)1782*8b356c88SJohn Baldwin interp_byte(char **src, byte *retbyte)
178344099b7bSPaul Traina {
178444099b7bSPaul Traina 	int v;
178544099b7bSPaul Traina 
178644099b7bSPaul Traina 	if ((*src)[0] == '0' &&
178744099b7bSPaul Traina 		((*src)[1] == 'x' ||
178844099b7bSPaul Traina 		 (*src)[1] == 'X')) {
178944099b7bSPaul Traina 		(*src) += 2;			/* allow 0x for hex, but don't require it */
179044099b7bSPaul Traina 	}
179144099b7bSPaul Traina 	if (!isxdigit((*src)[0]) || !isxdigit((*src)[1])) {
179244099b7bSPaul Traina 		return -1;
179344099b7bSPaul Traina 	}
179444099b7bSPaul Traina 	if (sscanf(*src, "%2x", &v) != 1) {
179544099b7bSPaul Traina 		return -1;
179644099b7bSPaul Traina 	}
179744099b7bSPaul Traina 	(*src) += 2;
179844099b7bSPaul Traina 	*retbyte = (byte) (v & 0xFF);
179944099b7bSPaul Traina 	return 0;
180044099b7bSPaul Traina }
180144099b7bSPaul Traina 
180244099b7bSPaul Traina 
180344099b7bSPaul Traina 
180444099b7bSPaul Traina /*
180544099b7bSPaul Traina  * The parameter "src" points to a character pointer which points to an
180644099b7bSPaul Traina  * ASCII string representation of an unsigned number.  The number is
180744099b7bSPaul Traina  * returned as an unsigned long and the character pointer is updated to
180844099b7bSPaul Traina  * point to the first illegal character.
180944099b7bSPaul Traina  */
181044099b7bSPaul Traina 
181144099b7bSPaul Traina PRIVATE u_int32
get_u_long(char ** src)1812*8b356c88SJohn Baldwin get_u_long(char **src)
181344099b7bSPaul Traina {
181407ee9f80SPedro F. Giffuni 	u_int32 value, base;
181544099b7bSPaul Traina 	char c;
181644099b7bSPaul Traina 
181744099b7bSPaul Traina 	/*
181844099b7bSPaul Traina 	 * Collect number up to first illegal character.  Values are specified
181944099b7bSPaul Traina 	 * as for C:  0x=hex, 0=octal, other=decimal.
182044099b7bSPaul Traina 	 */
182144099b7bSPaul Traina 	value = 0;
182244099b7bSPaul Traina 	base = 10;
182344099b7bSPaul Traina 	if (**src == '0') {
182444099b7bSPaul Traina 		base = 8;
182544099b7bSPaul Traina 		(*src)++;
182644099b7bSPaul Traina 	}
182744099b7bSPaul Traina 	if (**src == 'x' || **src == 'X') {
182844099b7bSPaul Traina 		base = 16;
182944099b7bSPaul Traina 		(*src)++;
183044099b7bSPaul Traina 	}
183144099b7bSPaul Traina 	while ((c = **src)) {
183244099b7bSPaul Traina 		if (isdigit(c)) {
183344099b7bSPaul Traina 			value = (value * base) + (c - '0');
183444099b7bSPaul Traina 			(*src)++;
183544099b7bSPaul Traina 			continue;
183644099b7bSPaul Traina 		}
183744099b7bSPaul Traina 		if (base == 16 && isxdigit(c)) {
183844099b7bSPaul Traina 			value = (value << 4) + ((c & ~32) + 10 - 'A');
183944099b7bSPaul Traina 			(*src)++;
184044099b7bSPaul Traina 			continue;
184144099b7bSPaul Traina 		}
184244099b7bSPaul Traina 		break;
184344099b7bSPaul Traina 	}
184444099b7bSPaul Traina 	return value;
184544099b7bSPaul Traina }
184644099b7bSPaul Traina 
184744099b7bSPaul Traina 
184844099b7bSPaul Traina 
184944099b7bSPaul Traina /*
185044099b7bSPaul Traina  * Routines for deletion of data associated with the main data structure.
185144099b7bSPaul Traina  */
185244099b7bSPaul Traina 
185344099b7bSPaul Traina 
185444099b7bSPaul Traina /*
185544099b7bSPaul Traina  * Frees the entire host data structure given.  Does nothing if the passed
185644099b7bSPaul Traina  * pointer is NULL.
185744099b7bSPaul Traina  */
185844099b7bSPaul Traina 
185944099b7bSPaul Traina PRIVATE void
free_host(hash_datum * hmp)1860*8b356c88SJohn Baldwin free_host(hash_datum *hmp)
186144099b7bSPaul Traina {
186244099b7bSPaul Traina 	struct host *hostptr = (struct host *) hmp;
186344099b7bSPaul Traina 	if (hostptr == NULL)
186444099b7bSPaul Traina 		return;
186544099b7bSPaul Traina 	assert(hostptr->linkcount > 0);
186644099b7bSPaul Traina 	if (--(hostptr->linkcount))
186744099b7bSPaul Traina 		return;					/* Still has references */
186844099b7bSPaul Traina 	del_iplist(hostptr->cookie_server);
186944099b7bSPaul Traina 	del_iplist(hostptr->domain_server);
187044099b7bSPaul Traina 	del_iplist(hostptr->gateway);
187144099b7bSPaul Traina 	del_iplist(hostptr->impress_server);
187244099b7bSPaul Traina 	del_iplist(hostptr->log_server);
187344099b7bSPaul Traina 	del_iplist(hostptr->lpr_server);
187444099b7bSPaul Traina 	del_iplist(hostptr->name_server);
187544099b7bSPaul Traina 	del_iplist(hostptr->rlp_server);
187644099b7bSPaul Traina 	del_iplist(hostptr->time_server);
187744099b7bSPaul Traina 	del_iplist(hostptr->nis_server);
187844099b7bSPaul Traina 	del_iplist(hostptr->ntp_server);
187944099b7bSPaul Traina 
188044099b7bSPaul Traina 	/*
188144099b7bSPaul Traina 	 * XXX - Add new tags here
188244099b7bSPaul Traina 	 * (if the value is an IP list)
188344099b7bSPaul Traina 	 */
188444099b7bSPaul Traina 
188544099b7bSPaul Traina 	del_string(hostptr->hostname);
188644099b7bSPaul Traina 	del_string(hostptr->homedir);
188744099b7bSPaul Traina 	del_string(hostptr->bootfile);
188844099b7bSPaul Traina 	del_string(hostptr->tftpdir);
188944099b7bSPaul Traina 	del_string(hostptr->root_path);
189044099b7bSPaul Traina 	del_string(hostptr->domain_name);
189144099b7bSPaul Traina 	del_string(hostptr->dump_file);
189244099b7bSPaul Traina 	del_string(hostptr->exten_file);
189344099b7bSPaul Traina 	del_string(hostptr->nis_domain);
189444099b7bSPaul Traina 
189544099b7bSPaul Traina #ifdef	YORK_EX_OPTION
189644099b7bSPaul Traina 	del_string(hostptr->exec_file);
189744099b7bSPaul Traina #endif
189844099b7bSPaul Traina 
189944099b7bSPaul Traina 	/*
190044099b7bSPaul Traina 	 * XXX - Add new tags here
190144099b7bSPaul Traina 	 * (if it is a shared string)
190244099b7bSPaul Traina 	 */
190344099b7bSPaul Traina 
190444099b7bSPaul Traina 	del_bindata(hostptr->generic);
190544099b7bSPaul Traina 	free((char *) hostptr);
190644099b7bSPaul Traina }
190744099b7bSPaul Traina 
190844099b7bSPaul Traina 
190944099b7bSPaul Traina 
191044099b7bSPaul Traina /*
191144099b7bSPaul Traina  * Decrements the linkcount on the given IP address data structure.  If the
191244099b7bSPaul Traina  * linkcount goes to zero, the memory associated with the data is freed.
191344099b7bSPaul Traina  */
191444099b7bSPaul Traina 
191544099b7bSPaul Traina PRIVATE void
del_iplist(struct in_addr_list * iplist)1916*8b356c88SJohn Baldwin del_iplist(struct in_addr_list *iplist)
191744099b7bSPaul Traina {
191844099b7bSPaul Traina 	if (iplist) {
191944099b7bSPaul Traina 		if (!(--(iplist->linkcount))) {
192044099b7bSPaul Traina 			free((char *) iplist);
192144099b7bSPaul Traina 		}
192244099b7bSPaul Traina 	}
192344099b7bSPaul Traina }
192444099b7bSPaul Traina 
192544099b7bSPaul Traina 
192644099b7bSPaul Traina 
192744099b7bSPaul Traina /*
192844099b7bSPaul Traina  * Decrements the linkcount on a string data structure.  If the count
192944099b7bSPaul Traina  * goes to zero, the memory associated with the string is freed.  Does
193044099b7bSPaul Traina  * nothing if the passed pointer is NULL.
193144099b7bSPaul Traina  */
193244099b7bSPaul Traina 
193344099b7bSPaul Traina PRIVATE void
del_string(struct shared_string * stringptr)1934*8b356c88SJohn Baldwin del_string(struct shared_string *stringptr)
193544099b7bSPaul Traina {
193644099b7bSPaul Traina 	if (stringptr) {
193744099b7bSPaul Traina 		if (!(--(stringptr->linkcount))) {
193844099b7bSPaul Traina 			free((char *) stringptr);
193944099b7bSPaul Traina 		}
194044099b7bSPaul Traina 	}
194144099b7bSPaul Traina }
194244099b7bSPaul Traina 
194344099b7bSPaul Traina 
194444099b7bSPaul Traina 
194544099b7bSPaul Traina /*
194644099b7bSPaul Traina  * Decrements the linkcount on a shared_bindata data structure.  If the
194744099b7bSPaul Traina  * count goes to zero, the memory associated with the data is freed.  Does
194844099b7bSPaul Traina  * nothing if the passed pointer is NULL.
194944099b7bSPaul Traina  */
195044099b7bSPaul Traina 
195144099b7bSPaul Traina PRIVATE void
del_bindata(struct shared_bindata * dataptr)1952*8b356c88SJohn Baldwin del_bindata(struct shared_bindata *dataptr)
195344099b7bSPaul Traina {
195444099b7bSPaul Traina 	if (dataptr) {
195544099b7bSPaul Traina 		if (!(--(dataptr->linkcount))) {
195644099b7bSPaul Traina 			free((char *) dataptr);
195744099b7bSPaul Traina 		}
195844099b7bSPaul Traina 	}
195944099b7bSPaul Traina }
196044099b7bSPaul Traina 
196144099b7bSPaul Traina 
196244099b7bSPaul Traina 
196344099b7bSPaul Traina 
196444099b7bSPaul Traina /* smalloc()  --  safe malloc()
196544099b7bSPaul Traina  *
196644099b7bSPaul Traina  * Always returns a valid pointer (if it returns at all).  The allocated
196744099b7bSPaul Traina  * memory is initialized to all zeros.  If malloc() returns an error, a
196844099b7bSPaul Traina  * message is printed using the report() function and the program aborts
196944099b7bSPaul Traina  * with a status of 1.
197044099b7bSPaul Traina  */
197144099b7bSPaul Traina 
197244099b7bSPaul Traina PRIVATE char *
smalloc(unsigned nbytes)1973*8b356c88SJohn Baldwin smalloc(unsigned nbytes)
197444099b7bSPaul Traina {
197544099b7bSPaul Traina 	char *retvalue;
197644099b7bSPaul Traina 
197744099b7bSPaul Traina 	retvalue = malloc(nbytes);
197844099b7bSPaul Traina 	if (!retvalue) {
197944099b7bSPaul Traina 		report(LOG_ERR, "malloc() failure -- exiting");
198044099b7bSPaul Traina 		exit(1);
198144099b7bSPaul Traina 	}
198244099b7bSPaul Traina 	bzero(retvalue, nbytes);
198344099b7bSPaul Traina 	return retvalue;
198444099b7bSPaul Traina }
198544099b7bSPaul Traina 
198644099b7bSPaul Traina 
198744099b7bSPaul Traina /*
198844099b7bSPaul Traina  * Compare function to determine whether two hardware addresses are
198944099b7bSPaul Traina  * equivalent.  Returns TRUE if "host1" and "host2" are equivalent, FALSE
199044099b7bSPaul Traina  * otherwise.
199144099b7bSPaul Traina  *
199244099b7bSPaul Traina  * This function is used when retrieving elements from the hardware address
199344099b7bSPaul Traina  * hash table.
199444099b7bSPaul Traina  */
199544099b7bSPaul Traina 
199644099b7bSPaul Traina boolean
hwlookcmp(hash_datum * d1,hash_datum * d2)1997*8b356c88SJohn Baldwin hwlookcmp(hash_datum *d1, hash_datum *d2)
199844099b7bSPaul Traina {
199944099b7bSPaul Traina 	struct host *host1 = (struct host *) d1;
200044099b7bSPaul Traina 	struct host *host2 = (struct host *) d2;
200144099b7bSPaul Traina 
200244099b7bSPaul Traina 	if (host1->htype != host2->htype) {
200344099b7bSPaul Traina 		return FALSE;
200444099b7bSPaul Traina 	}
200544099b7bSPaul Traina 	if (bcmp(host1->haddr, host2->haddr, haddrlength(host1->htype))) {
200644099b7bSPaul Traina 		return FALSE;
200744099b7bSPaul Traina 	}
200844099b7bSPaul Traina 	return TRUE;
200944099b7bSPaul Traina }
201044099b7bSPaul Traina 
201144099b7bSPaul Traina 
201244099b7bSPaul Traina /*
201344099b7bSPaul Traina  * Compare function for doing IP address hash table lookup.
201444099b7bSPaul Traina  */
201544099b7bSPaul Traina 
201644099b7bSPaul Traina boolean
iplookcmp(hash_datum * d1,hash_datum * d2)2017*8b356c88SJohn Baldwin iplookcmp(hash_datum *d1, hash_datum *d2)
201844099b7bSPaul Traina {
201944099b7bSPaul Traina 	struct host *host1 = (struct host *) d1;
202044099b7bSPaul Traina 	struct host *host2 = (struct host *) d2;
202144099b7bSPaul Traina 
202244099b7bSPaul Traina 	return (host1->iaddr.s_addr == host2->iaddr.s_addr);
202344099b7bSPaul Traina }
202444099b7bSPaul Traina 
202544099b7bSPaul Traina /*
202644099b7bSPaul Traina  * Local Variables:
202744099b7bSPaul Traina  * tab-width: 4
202844099b7bSPaul Traina  * c-indent-level: 4
202944099b7bSPaul Traina  * c-argdecl-indent: 4
203044099b7bSPaul Traina  * c-continued-statement-offset: 4
203144099b7bSPaul Traina  * c-continued-brace-offset: -4
203244099b7bSPaul Traina  * c-label-offset: -4
203344099b7bSPaul Traina  * c-brace-offset: 0
203444099b7bSPaul Traina  * End:
203544099b7bSPaul Traina  */
2036