1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include "defs.h"
30*7c478bd9Sstevel@tonic-gate #include "tables.h"
31*7c478bd9Sstevel@tonic-gate 
32*7c478bd9Sstevel@tonic-gate /*
33*7c478bd9Sstevel@tonic-gate  * Parse the config file which consists of entries of the form:
34*7c478bd9Sstevel@tonic-gate  *	ifdefault	[<variable> <value>]*
35*7c478bd9Sstevel@tonic-gate  *	prefixdefault	[<variable> <value>]*
36*7c478bd9Sstevel@tonic-gate  *	if <ifname>	[<variable> <value>]*
37*7c478bd9Sstevel@tonic-gate  *	prefix <prefix>/<length> <ifname>	[<variable> <value>]*
38*7c478bd9Sstevel@tonic-gate  *
39*7c478bd9Sstevel@tonic-gate  * All "ifdefault" and "prefixdefault" entries must preceed any
40*7c478bd9Sstevel@tonic-gate  * "if" and "prefix" entries.
41*7c478bd9Sstevel@tonic-gate  *
42*7c478bd9Sstevel@tonic-gate  * Values (such as expiry dates) which contain white space
43*7c478bd9Sstevel@tonic-gate  * can be quoted with single or double quotes.
44*7c478bd9Sstevel@tonic-gate  */
45*7c478bd9Sstevel@tonic-gate 
46*7c478bd9Sstevel@tonic-gate /* maximum length of messages we send to syslog */
47*7c478bd9Sstevel@tonic-gate #define	NDPD_LOGMSGSIZE	1024
48*7c478bd9Sstevel@tonic-gate typedef	boolean_t	(*pfb_t)(char *, uint_t *);
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate struct configinfo {
51*7c478bd9Sstevel@tonic-gate 	char	*ci_name;
52*7c478bd9Sstevel@tonic-gate 	uint_t	ci_min;		/* 0: no min check */
53*7c478bd9Sstevel@tonic-gate 	uint_t	ci_max;		/* ~0U: no max check */
54*7c478bd9Sstevel@tonic-gate 	uint_t	ci_default;
55*7c478bd9Sstevel@tonic-gate 	uint_t	ci_index;	/* Into result array */
56*7c478bd9Sstevel@tonic-gate 	pfb_t	ci_parsefunc;	/* Parse function returns -1 on failure */
57*7c478bd9Sstevel@tonic-gate };
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate enum config_type { CONFIG_IF, CONFIG_PREFIX};
60*7c478bd9Sstevel@tonic-gate typedef enum config_type config_type_t;
61*7c478bd9Sstevel@tonic-gate 
62*7c478bd9Sstevel@tonic-gate static void set_protocol_defaults(void);
63*7c478bd9Sstevel@tonic-gate static void print_defaults(void);
64*7c478bd9Sstevel@tonic-gate static void parse_var_value(config_type_t, struct configinfo *, char *, char *,
65*7c478bd9Sstevel@tonic-gate     struct confvar *);
66*7c478bd9Sstevel@tonic-gate static void parse_default(config_type_t, struct configinfo *, char **, int,
67*7c478bd9Sstevel@tonic-gate     struct confvar *);
68*7c478bd9Sstevel@tonic-gate static void parse_if(struct configinfo *, char **, int);
69*7c478bd9Sstevel@tonic-gate static void parse_prefix(struct configinfo *, char **, int);
70*7c478bd9Sstevel@tonic-gate static boolean_t parse_onoff(char *, uint_t *);	/* boolean */
71*7c478bd9Sstevel@tonic-gate static boolean_t parse_int(char *, uint_t *);	/* integer */
72*7c478bd9Sstevel@tonic-gate static boolean_t parse_ms(char *, uint_t *);	/* milliseconds */
73*7c478bd9Sstevel@tonic-gate static boolean_t parse_s(char *, uint_t *);	/* seconds */
74*7c478bd9Sstevel@tonic-gate static boolean_t parse_date(char *, uint_t *);	/* date format */
75*7c478bd9Sstevel@tonic-gate static void conferr(char *fmt, ...);
76*7c478bd9Sstevel@tonic-gate static FILE *open_conffile(char *filename);
77*7c478bd9Sstevel@tonic-gate static int parse_line(char *line, char *argvec[], int argcount);
78*7c478bd9Sstevel@tonic-gate static int readline(FILE *fp, char *line, int length);
79*7c478bd9Sstevel@tonic-gate static int parse_addrprefix(char *strin, struct in6_addr *in6);
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate /*
82*7c478bd9Sstevel@tonic-gate  * Per interface configuration variables.
83*7c478bd9Sstevel@tonic-gate  * Min, max, and default values are from RFC 2461.
84*7c478bd9Sstevel@tonic-gate  */
85*7c478bd9Sstevel@tonic-gate static struct configinfo iflist[] = {
86*7c478bd9Sstevel@tonic-gate 	/* Name, Min, Max, Default, Index */
87*7c478bd9Sstevel@tonic-gate 	{ "DupAddrDetectTransmits", 0, 100, 1, I_DupAddrDetectTransmits,
88*7c478bd9Sstevel@tonic-gate 	parse_int },
89*7c478bd9Sstevel@tonic-gate 	{ "AdvSendAdvertisements", 0, 1, 0, I_AdvSendAdvertisements,
90*7c478bd9Sstevel@tonic-gate 	parse_onoff },
91*7c478bd9Sstevel@tonic-gate 	{ "MaxRtrAdvInterval", 4, 1800, 600, I_MaxRtrAdvInterval, parse_s },
92*7c478bd9Sstevel@tonic-gate 	{ "MinRtrAdvInterval", 3, 1350, 200, I_MinRtrAdvInterval, parse_s },
93*7c478bd9Sstevel@tonic-gate 	/*
94*7c478bd9Sstevel@tonic-gate 	 * No greater than .75 * MaxRtrAdvInterval.
95*7c478bd9Sstevel@tonic-gate 	 * Default: 0.33 * MaxRtrAdvInterval
96*7c478bd9Sstevel@tonic-gate 	 */
97*7c478bd9Sstevel@tonic-gate 	{ "AdvManagedFlag", 0, 1, 0, I_AdvManagedFlag, parse_onoff },
98*7c478bd9Sstevel@tonic-gate 	{ "AdvOtherConfigFlag", 0, 1, 0, I_AdvOtherConfigFlag, parse_onoff },
99*7c478bd9Sstevel@tonic-gate 	{ "AdvLinkMTU", IPV6_MIN_MTU, 65535, 0, I_AdvLinkMTU, parse_int },
100*7c478bd9Sstevel@tonic-gate 	{ "AdvReachableTime", 0, 3600000, 0, I_AdvReachableTime, parse_ms },
101*7c478bd9Sstevel@tonic-gate 	{ "AdvRetransTimer", 0, ~0U, 0, I_AdvRetransTimer, parse_ms },
102*7c478bd9Sstevel@tonic-gate 	{ "AdvCurHopLimit", 0, 255, 0, I_AdvCurHopLimit, parse_int },
103*7c478bd9Sstevel@tonic-gate 	{ "AdvDefaultLifetime", 0, 9000, 1800, I_AdvDefaultLifetime, parse_s },
104*7c478bd9Sstevel@tonic-gate 	/*
105*7c478bd9Sstevel@tonic-gate 	 * MUST be either zero or between MaxRtrAdvInterval and 9000 seconds.
106*7c478bd9Sstevel@tonic-gate 	 * Default: 3 * MaxRtrAdvInterval
107*7c478bd9Sstevel@tonic-gate 	 */
108*7c478bd9Sstevel@tonic-gate 	{ "StatelessAddrConf", 0, 1, 1, I_StatelessAddrConf, parse_onoff },
109*7c478bd9Sstevel@tonic-gate 	/*
110*7c478bd9Sstevel@tonic-gate 	 * Tmp* variables from RFC 3041, where defaults are defined.
111*7c478bd9Sstevel@tonic-gate 	 */
112*7c478bd9Sstevel@tonic-gate 	{ "TmpAddrsEnabled", 0, 1, 0, I_TmpAddrsEnabled, parse_onoff },
113*7c478bd9Sstevel@tonic-gate 	{ "TmpValidLifetime", 0, ~0U, 604800, I_TmpValidLifetime, parse_s },
114*7c478bd9Sstevel@tonic-gate 	{ "TmpPreferredLifetime", 0, ~0U, 86400, I_TmpPreferredLifetime,
115*7c478bd9Sstevel@tonic-gate 	parse_s },
116*7c478bd9Sstevel@tonic-gate 	{ "TmpRegenAdvance", 0, 60, 5, I_TmpRegenAdvance, parse_s },
117*7c478bd9Sstevel@tonic-gate 	{ "TmpMaxDesyncFactor", 0, 600, 600, I_TmpMaxDesyncFactor, parse_s },
118*7c478bd9Sstevel@tonic-gate 	{ NULL, 0, 0, 0, 0 }
119*7c478bd9Sstevel@tonic-gate };
120*7c478bd9Sstevel@tonic-gate 
121*7c478bd9Sstevel@tonic-gate /*
122*7c478bd9Sstevel@tonic-gate  * Per prefix: AdvPrefixList configuration variables.
123*7c478bd9Sstevel@tonic-gate  * Min, max, and default values are from RFC 2461.
124*7c478bd9Sstevel@tonic-gate  */
125*7c478bd9Sstevel@tonic-gate static struct configinfo prefixlist[] = {
126*7c478bd9Sstevel@tonic-gate 	/* Name, Min, Max, Default, Index */
127*7c478bd9Sstevel@tonic-gate 	{ "AdvValidLifetime", 0, ~0U, 2592000, I_AdvValidLifetime,
128*7c478bd9Sstevel@tonic-gate 	parse_s },
129*7c478bd9Sstevel@tonic-gate 	{ "AdvOnLinkFlag", 0, 1, 1, I_AdvOnLinkFlag, parse_onoff },
130*7c478bd9Sstevel@tonic-gate 	{ "AdvPreferredLifetime", 0, ~0U, 604800, I_AdvPreferredLifetime,
131*7c478bd9Sstevel@tonic-gate 	parse_s},
132*7c478bd9Sstevel@tonic-gate 	{ "AdvAutonomousFlag", 0, 1, 1, I_AdvAutonomousFlag, parse_onoff },
133*7c478bd9Sstevel@tonic-gate 	{ "AdvValidExpiration", 0, ~0U, 0, I_AdvValidExpiration,
134*7c478bd9Sstevel@tonic-gate 	parse_date },
135*7c478bd9Sstevel@tonic-gate 	{ "AdvPreferredExpiration", 0, ~0U, 0, I_AdvPreferredExpiration,
136*7c478bd9Sstevel@tonic-gate 	parse_date},
137*7c478bd9Sstevel@tonic-gate 	{ NULL, 0, 0, 0, 0 },
138*7c478bd9Sstevel@tonic-gate };
139*7c478bd9Sstevel@tonic-gate 
140*7c478bd9Sstevel@tonic-gate /*
141*7c478bd9Sstevel@tonic-gate  * Data structures used to merge above protocol defaults
142*7c478bd9Sstevel@tonic-gate  * with defaults specified in the configuration file.
143*7c478bd9Sstevel@tonic-gate  * ifdefault is not static because new interfaces can be
144*7c478bd9Sstevel@tonic-gate  * created outside of the configuration context.
145*7c478bd9Sstevel@tonic-gate  */
146*7c478bd9Sstevel@tonic-gate struct confvar ifdefaults[I_IFSIZE];
147*7c478bd9Sstevel@tonic-gate static struct confvar prefixdefaults[I_PREFIXSIZE];
148*7c478bd9Sstevel@tonic-gate 
149*7c478bd9Sstevel@tonic-gate static char	conf_filename[MAXPATHLEN];
150*7c478bd9Sstevel@tonic-gate static int	lineno;
151*7c478bd9Sstevel@tonic-gate 
152*7c478bd9Sstevel@tonic-gate /*
153*7c478bd9Sstevel@tonic-gate  * Checks for violations of section 5.5.3 (c) of RFC 2462.
154*7c478bd9Sstevel@tonic-gate  */
155*7c478bd9Sstevel@tonic-gate static void
156*7c478bd9Sstevel@tonic-gate check_var_consistency(struct confvar *cv, void *save, int size)
157*7c478bd9Sstevel@tonic-gate {
158*7c478bd9Sstevel@tonic-gate 	boolean_t rollback = _B_FALSE;
159*7c478bd9Sstevel@tonic-gate 	int prefl, prefe, valid;
160*7c478bd9Sstevel@tonic-gate 
161*7c478bd9Sstevel@tonic-gate 	prefl = cv[I_AdvPreferredLifetime].cf_value;
162*7c478bd9Sstevel@tonic-gate 	prefe = cv[I_AdvPreferredExpiration].cf_value;
163*7c478bd9Sstevel@tonic-gate 	valid = cv[I_AdvValidLifetime].cf_value;
164*7c478bd9Sstevel@tonic-gate 
165*7c478bd9Sstevel@tonic-gate 	if (prefl > valid) {
166*7c478bd9Sstevel@tonic-gate 		conferr("AdvPreferredLifetime (%u) is greater than "
167*7c478bd9Sstevel@tonic-gate 		    "valid lifetime (%u)\n", prefl, valid);
168*7c478bd9Sstevel@tonic-gate 		rollback = _B_TRUE;
169*7c478bd9Sstevel@tonic-gate 	}
170*7c478bd9Sstevel@tonic-gate 
171*7c478bd9Sstevel@tonic-gate 	if (prefe > valid) {
172*7c478bd9Sstevel@tonic-gate 		conferr("AdvPreferredExpiration (%u) is greater than "
173*7c478bd9Sstevel@tonic-gate 		    "valid lifetime (%u)\n", prefe, valid);
174*7c478bd9Sstevel@tonic-gate 		rollback = _B_TRUE;
175*7c478bd9Sstevel@tonic-gate 	}
176*7c478bd9Sstevel@tonic-gate 
177*7c478bd9Sstevel@tonic-gate 	if (rollback) {
178*7c478bd9Sstevel@tonic-gate 		(void) memcpy(cv, save, size);
179*7c478bd9Sstevel@tonic-gate 	}
180*7c478bd9Sstevel@tonic-gate }
181*7c478bd9Sstevel@tonic-gate 
182*7c478bd9Sstevel@tonic-gate /*
183*7c478bd9Sstevel@tonic-gate  * Check for invalid lifetime values for RFC3041 addresses
184*7c478bd9Sstevel@tonic-gate  */
185*7c478bd9Sstevel@tonic-gate static void
186*7c478bd9Sstevel@tonic-gate check_if_var_consistency(struct confvar *cv, void *save, int size)
187*7c478bd9Sstevel@tonic-gate {
188*7c478bd9Sstevel@tonic-gate 	boolean_t rollback = _B_FALSE;
189*7c478bd9Sstevel@tonic-gate 	int tpref, tvalid, tdesync, tregen;
190*7c478bd9Sstevel@tonic-gate 
191*7c478bd9Sstevel@tonic-gate 	tpref = cv[I_TmpPreferredLifetime].cf_value;
192*7c478bd9Sstevel@tonic-gate 	tvalid = cv[I_TmpValidLifetime].cf_value;
193*7c478bd9Sstevel@tonic-gate 	tdesync = cv[I_TmpMaxDesyncFactor].cf_value;
194*7c478bd9Sstevel@tonic-gate 	tregen = cv[I_TmpRegenAdvance].cf_value;
195*7c478bd9Sstevel@tonic-gate 
196*7c478bd9Sstevel@tonic-gate 	/*
197*7c478bd9Sstevel@tonic-gate 	 * Only need to do this if tmp addrs are enabled.
198*7c478bd9Sstevel@tonic-gate 	 */
199*7c478bd9Sstevel@tonic-gate 	if (cv[I_TmpAddrsEnabled].cf_value == 0)
200*7c478bd9Sstevel@tonic-gate 		return;
201*7c478bd9Sstevel@tonic-gate 
202*7c478bd9Sstevel@tonic-gate 	if (tdesync > tpref) {
203*7c478bd9Sstevel@tonic-gate 		conferr("TmpDesyncFactor (%u) is greater than "
204*7c478bd9Sstevel@tonic-gate 		    "TmpPreferredLifetime (%u)\n", tdesync, tpref);
205*7c478bd9Sstevel@tonic-gate 		rollback = _B_TRUE;
206*7c478bd9Sstevel@tonic-gate 	}
207*7c478bd9Sstevel@tonic-gate 
208*7c478bd9Sstevel@tonic-gate 	if (tpref > tvalid) {
209*7c478bd9Sstevel@tonic-gate 		conferr("TmpPreferredLifetime (%u) is greater than "
210*7c478bd9Sstevel@tonic-gate 		    "TmpValidLifetime (%u)\n", tpref, tvalid);
211*7c478bd9Sstevel@tonic-gate 		rollback = _B_TRUE;
212*7c478bd9Sstevel@tonic-gate 	}
213*7c478bd9Sstevel@tonic-gate 
214*7c478bd9Sstevel@tonic-gate 	if (tregen > tvalid) {
215*7c478bd9Sstevel@tonic-gate 		conferr("TmpRegenAdvance (%u) is greater than "
216*7c478bd9Sstevel@tonic-gate 		    "TmpValidLifetime (%u)\n", tregen, tvalid);
217*7c478bd9Sstevel@tonic-gate 		rollback = _B_TRUE;
218*7c478bd9Sstevel@tonic-gate 	}
219*7c478bd9Sstevel@tonic-gate 
220*7c478bd9Sstevel@tonic-gate 	if (rollback) {
221*7c478bd9Sstevel@tonic-gate 		(void) memcpy(cv, save, size);
222*7c478bd9Sstevel@tonic-gate 	}
223*7c478bd9Sstevel@tonic-gate }
224*7c478bd9Sstevel@tonic-gate 
225*7c478bd9Sstevel@tonic-gate int
226*7c478bd9Sstevel@tonic-gate parse_config(char *config_file, boolean_t file_required)
227*7c478bd9Sstevel@tonic-gate {
228*7c478bd9Sstevel@tonic-gate 	FILE *fp;
229*7c478bd9Sstevel@tonic-gate 	char line[MAXLINELEN];
230*7c478bd9Sstevel@tonic-gate 	char pline[MAXLINELEN];
231*7c478bd9Sstevel@tonic-gate 	int argcount;
232*7c478bd9Sstevel@tonic-gate 	char *argvec[MAXARGSPERLINE];
233*7c478bd9Sstevel@tonic-gate 	int defaultdone = 0;	/* Set when first non-default command found */
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate 	if (debug & D_CONFIG)
236*7c478bd9Sstevel@tonic-gate 		logmsg(LOG_DEBUG, "parse_config()\n");
237*7c478bd9Sstevel@tonic-gate 
238*7c478bd9Sstevel@tonic-gate 	set_protocol_defaults();
239*7c478bd9Sstevel@tonic-gate 	if (debug & D_DEFAULTS)
240*7c478bd9Sstevel@tonic-gate 		print_defaults();
241*7c478bd9Sstevel@tonic-gate 
242*7c478bd9Sstevel@tonic-gate 	fp = open_conffile(config_file);
243*7c478bd9Sstevel@tonic-gate 	if (fp == NULL) {
244*7c478bd9Sstevel@tonic-gate 		if (errno == ENOENT && !file_required)
245*7c478bd9Sstevel@tonic-gate 			return (0);
246*7c478bd9Sstevel@tonic-gate 		logperror(config_file);
247*7c478bd9Sstevel@tonic-gate 		return (-1);
248*7c478bd9Sstevel@tonic-gate 	}
249*7c478bd9Sstevel@tonic-gate 	while (readline(fp, line, sizeof (line)) != 0) {
250*7c478bd9Sstevel@tonic-gate 		(void) strncpy(pline, line, sizeof (pline));
251*7c478bd9Sstevel@tonic-gate 		pline[sizeof (pline) - 1] = '\0';	/* NULL terminate */
252*7c478bd9Sstevel@tonic-gate 		argcount = parse_line(pline, argvec,
253*7c478bd9Sstevel@tonic-gate 		    sizeof (argvec) / sizeof (argvec[0]));
254*7c478bd9Sstevel@tonic-gate 		if (debug & D_PARSE) {
255*7c478bd9Sstevel@tonic-gate 			int i;
256*7c478bd9Sstevel@tonic-gate 
257*7c478bd9Sstevel@tonic-gate 			logmsg(LOG_DEBUG, "scanned %d args\n", argcount);
258*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < argcount; i++)
259*7c478bd9Sstevel@tonic-gate 				logmsg(LOG_DEBUG, "arg[%d]: %s\n",
260*7c478bd9Sstevel@tonic-gate 				    i, argvec[i]);
261*7c478bd9Sstevel@tonic-gate 		}
262*7c478bd9Sstevel@tonic-gate 		if (argcount == 0) {
263*7c478bd9Sstevel@tonic-gate 			/* Empty line - or comment only line */
264*7c478bd9Sstevel@tonic-gate 			continue;
265*7c478bd9Sstevel@tonic-gate 		}
266*7c478bd9Sstevel@tonic-gate 		if (strcmp(argvec[0], "ifdefault") == 0) {
267*7c478bd9Sstevel@tonic-gate 			char save[sizeof (ifdefaults)];
268*7c478bd9Sstevel@tonic-gate 
269*7c478bd9Sstevel@tonic-gate 			if (defaultdone) {
270*7c478bd9Sstevel@tonic-gate 				conferr("ifdefault after non-default "
271*7c478bd9Sstevel@tonic-gate 				    "command\n");
272*7c478bd9Sstevel@tonic-gate 				continue;
273*7c478bd9Sstevel@tonic-gate 			}
274*7c478bd9Sstevel@tonic-gate 			/*
275*7c478bd9Sstevel@tonic-gate 			 * Save existing values in case what we read is
276*7c478bd9Sstevel@tonic-gate 			 * invalid and we need to restore previous settings.
277*7c478bd9Sstevel@tonic-gate 			 */
278*7c478bd9Sstevel@tonic-gate 			(void) memcpy(save, ifdefaults, sizeof (ifdefaults));
279*7c478bd9Sstevel@tonic-gate 			parse_default(CONFIG_IF, iflist, argvec+1, argcount-1,
280*7c478bd9Sstevel@tonic-gate 			    ifdefaults);
281*7c478bd9Sstevel@tonic-gate 			check_if_var_consistency(ifdefaults, save,
282*7c478bd9Sstevel@tonic-gate 			    sizeof (save));
283*7c478bd9Sstevel@tonic-gate 		} else if (strcmp(argvec[0], "prefixdefault") == 0) {
284*7c478bd9Sstevel@tonic-gate 			char save[sizeof (prefixdefaults)];
285*7c478bd9Sstevel@tonic-gate 
286*7c478bd9Sstevel@tonic-gate 			if (defaultdone) {
287*7c478bd9Sstevel@tonic-gate 				conferr("prefixdefault after non-default "
288*7c478bd9Sstevel@tonic-gate 				    "command\n");
289*7c478bd9Sstevel@tonic-gate 				continue;
290*7c478bd9Sstevel@tonic-gate 			}
291*7c478bd9Sstevel@tonic-gate 			/*
292*7c478bd9Sstevel@tonic-gate 			 * Save existing values in case what we read is
293*7c478bd9Sstevel@tonic-gate 			 * invalid and we need to restore previous settings.
294*7c478bd9Sstevel@tonic-gate 			 */
295*7c478bd9Sstevel@tonic-gate 			(void) memcpy(save, prefixdefaults,
296*7c478bd9Sstevel@tonic-gate 			    sizeof (prefixdefaults));
297*7c478bd9Sstevel@tonic-gate 			parse_default(CONFIG_PREFIX, prefixlist, argvec+1,
298*7c478bd9Sstevel@tonic-gate 			    argcount-1, prefixdefaults);
299*7c478bd9Sstevel@tonic-gate 			check_var_consistency(prefixdefaults, save,
300*7c478bd9Sstevel@tonic-gate 			    sizeof (save));
301*7c478bd9Sstevel@tonic-gate 		} else if (strcmp(argvec[0], "if") == 0) {
302*7c478bd9Sstevel@tonic-gate 			defaultdone = 1;
303*7c478bd9Sstevel@tonic-gate 			parse_if(iflist, argvec+1, argcount-1);
304*7c478bd9Sstevel@tonic-gate 		} else if (strcmp(argvec[0], "prefix") == 0) {
305*7c478bd9Sstevel@tonic-gate 			defaultdone = 1;
306*7c478bd9Sstevel@tonic-gate 			parse_prefix(prefixlist, argvec+1, argcount-1);
307*7c478bd9Sstevel@tonic-gate 		} else {
308*7c478bd9Sstevel@tonic-gate 			conferr("Unknown command: %s\n", argvec[0]);
309*7c478bd9Sstevel@tonic-gate 		}
310*7c478bd9Sstevel@tonic-gate 	}
311*7c478bd9Sstevel@tonic-gate 	(void) fclose(fp);
312*7c478bd9Sstevel@tonic-gate 	if (debug & D_DEFAULTS)
313*7c478bd9Sstevel@tonic-gate 		print_defaults();
314*7c478bd9Sstevel@tonic-gate 	return (0);
315*7c478bd9Sstevel@tonic-gate }
316*7c478bd9Sstevel@tonic-gate 
317*7c478bd9Sstevel@tonic-gate /*
318*7c478bd9Sstevel@tonic-gate  * Extract the defaults from the configinfo tables to initialize
319*7c478bd9Sstevel@tonic-gate  * the ifdefaults and prefixdefaults arrays.
320*7c478bd9Sstevel@tonic-gate  * The arrays are needed to track which defaults have been changed
321*7c478bd9Sstevel@tonic-gate  * by the config file.
322*7c478bd9Sstevel@tonic-gate  */
323*7c478bd9Sstevel@tonic-gate static void
324*7c478bd9Sstevel@tonic-gate set_protocol_defaults(void)
325*7c478bd9Sstevel@tonic-gate {
326*7c478bd9Sstevel@tonic-gate 	struct configinfo *cip;
327*7c478bd9Sstevel@tonic-gate 
328*7c478bd9Sstevel@tonic-gate 	if (debug & D_DEFAULTS)
329*7c478bd9Sstevel@tonic-gate 		logmsg(LOG_DEBUG, "extract_protocol_defaults\n");
330*7c478bd9Sstevel@tonic-gate 	for (cip = iflist; cip->ci_name != NULL; cip++) {
331*7c478bd9Sstevel@tonic-gate 		ifdefaults[cip->ci_index].cf_value = cip->ci_default;
332*7c478bd9Sstevel@tonic-gate 		ifdefaults[cip->ci_index].cf_notdefault = _B_FALSE;
333*7c478bd9Sstevel@tonic-gate 	}
334*7c478bd9Sstevel@tonic-gate 	for (cip = prefixlist; cip->ci_name != NULL; cip++) {
335*7c478bd9Sstevel@tonic-gate 		prefixdefaults[cip->ci_index].cf_value = cip->ci_default;
336*7c478bd9Sstevel@tonic-gate 		prefixdefaults[cip->ci_index].cf_notdefault = _B_FALSE;
337*7c478bd9Sstevel@tonic-gate 	}
338*7c478bd9Sstevel@tonic-gate }
339*7c478bd9Sstevel@tonic-gate 
340*7c478bd9Sstevel@tonic-gate void
341*7c478bd9Sstevel@tonic-gate print_iflist(struct confvar *confvar)
342*7c478bd9Sstevel@tonic-gate {
343*7c478bd9Sstevel@tonic-gate 	struct configinfo *cip;
344*7c478bd9Sstevel@tonic-gate 
345*7c478bd9Sstevel@tonic-gate 	for (cip = iflist; cip->ci_name != NULL; cip++) {
346*7c478bd9Sstevel@tonic-gate 		logmsg(LOG_DEBUG, "\t%s min %u max %u def %u value %u set %d\n",
347*7c478bd9Sstevel@tonic-gate 		    cip->ci_name, cip->ci_min, cip->ci_max, cip->ci_default,
348*7c478bd9Sstevel@tonic-gate 		    confvar[cip->ci_index].cf_value,
349*7c478bd9Sstevel@tonic-gate 		    confvar[cip->ci_index].cf_notdefault);
350*7c478bd9Sstevel@tonic-gate 	}
351*7c478bd9Sstevel@tonic-gate }
352*7c478bd9Sstevel@tonic-gate 
353*7c478bd9Sstevel@tonic-gate void
354*7c478bd9Sstevel@tonic-gate print_prefixlist(struct confvar *confvar)
355*7c478bd9Sstevel@tonic-gate {
356*7c478bd9Sstevel@tonic-gate 	struct configinfo *cip;
357*7c478bd9Sstevel@tonic-gate 
358*7c478bd9Sstevel@tonic-gate 	for (cip = prefixlist; cip->ci_name != NULL; cip++) {
359*7c478bd9Sstevel@tonic-gate 		logmsg(LOG_DEBUG, "\t%s min %u max %u def %u value %u set %d\n",
360*7c478bd9Sstevel@tonic-gate 		    cip->ci_name, cip->ci_min, cip->ci_max, cip->ci_default,
361*7c478bd9Sstevel@tonic-gate 		    confvar[cip->ci_index].cf_value,
362*7c478bd9Sstevel@tonic-gate 		    confvar[cip->ci_index].cf_notdefault);
363*7c478bd9Sstevel@tonic-gate 	}
364*7c478bd9Sstevel@tonic-gate }
365*7c478bd9Sstevel@tonic-gate 
366*7c478bd9Sstevel@tonic-gate 
367*7c478bd9Sstevel@tonic-gate static void
368*7c478bd9Sstevel@tonic-gate print_defaults(void)
369*7c478bd9Sstevel@tonic-gate {
370*7c478bd9Sstevel@tonic-gate 	logmsg(LOG_DEBUG, "Default interface variables:\n");
371*7c478bd9Sstevel@tonic-gate 	print_iflist(ifdefaults);
372*7c478bd9Sstevel@tonic-gate 	logmsg(LOG_DEBUG, "Default prefix variables:\n");
373*7c478bd9Sstevel@tonic-gate 	print_prefixlist(prefixdefaults);
374*7c478bd9Sstevel@tonic-gate }
375*7c478bd9Sstevel@tonic-gate 
376*7c478bd9Sstevel@tonic-gate /*
377*7c478bd9Sstevel@tonic-gate  * Read from fp. Handle \ at the end of the line by joining lines together.
378*7c478bd9Sstevel@tonic-gate  * Return 0 on EOF.
379*7c478bd9Sstevel@tonic-gate  */
380*7c478bd9Sstevel@tonic-gate static int
381*7c478bd9Sstevel@tonic-gate readline(FILE *fp, char *line, int length)
382*7c478bd9Sstevel@tonic-gate {
383*7c478bd9Sstevel@tonic-gate 	int got = 0;
384*7c478bd9Sstevel@tonic-gate 
385*7c478bd9Sstevel@tonic-gate retry:
386*7c478bd9Sstevel@tonic-gate 	errno = 0;
387*7c478bd9Sstevel@tonic-gate 	if (fgets(line, length, fp) == NULL) {
388*7c478bd9Sstevel@tonic-gate 		if (errno == EINTR)
389*7c478bd9Sstevel@tonic-gate 			goto retry;
390*7c478bd9Sstevel@tonic-gate 		if (got != 0)
391*7c478bd9Sstevel@tonic-gate 			return (1);
392*7c478bd9Sstevel@tonic-gate 		else
393*7c478bd9Sstevel@tonic-gate 			return (0);
394*7c478bd9Sstevel@tonic-gate 	}
395*7c478bd9Sstevel@tonic-gate 	lineno++;
396*7c478bd9Sstevel@tonic-gate 	got = strlen(line);
397*7c478bd9Sstevel@tonic-gate 	/* Look for trailing \. Note that fgets includes the linefeed. */
398*7c478bd9Sstevel@tonic-gate 	if (got >= 2 && line[got-2] == '\\') {
399*7c478bd9Sstevel@tonic-gate 		/* Skip \ and LF */
400*7c478bd9Sstevel@tonic-gate 		line += got - 2;
401*7c478bd9Sstevel@tonic-gate 		length -= got - 2;
402*7c478bd9Sstevel@tonic-gate 		goto retry;
403*7c478bd9Sstevel@tonic-gate 	}
404*7c478bd9Sstevel@tonic-gate 	/* Remove the trailing linefeed */
405*7c478bd9Sstevel@tonic-gate 	if (got > 0)
406*7c478bd9Sstevel@tonic-gate 		line[got-1] = '\0';
407*7c478bd9Sstevel@tonic-gate 
408*7c478bd9Sstevel@tonic-gate 	return (1);
409*7c478bd9Sstevel@tonic-gate }
410*7c478bd9Sstevel@tonic-gate 
411*7c478bd9Sstevel@tonic-gate /*
412*7c478bd9Sstevel@tonic-gate  * Parse a line splitting it off at whitspace characters.
413*7c478bd9Sstevel@tonic-gate  * Modifies the content of the string by inserting NULLs.
414*7c478bd9Sstevel@tonic-gate  * If more arguments than fits in argvec/argcount then ignore the last.
415*7c478bd9Sstevel@tonic-gate  * Returns argcount.
416*7c478bd9Sstevel@tonic-gate  * Handles single quotes and double quotes.
417*7c478bd9Sstevel@tonic-gate  */
418*7c478bd9Sstevel@tonic-gate static int
419*7c478bd9Sstevel@tonic-gate parse_line(char *line, char *argvec[], int argcount)
420*7c478bd9Sstevel@tonic-gate {
421*7c478bd9Sstevel@tonic-gate 	int i = 0;
422*7c478bd9Sstevel@tonic-gate 	char *cp;
423*7c478bd9Sstevel@tonic-gate 	boolean_t insingle_quote = _B_FALSE;
424*7c478bd9Sstevel@tonic-gate 	boolean_t indouble_quote = _B_FALSE;
425*7c478bd9Sstevel@tonic-gate 
426*7c478bd9Sstevel@tonic-gate 	/* Truncate at the beginning of a comment */
427*7c478bd9Sstevel@tonic-gate 	cp = strchr(line, '#');
428*7c478bd9Sstevel@tonic-gate 	if (cp != NULL)
429*7c478bd9Sstevel@tonic-gate 		*cp = '\0';
430*7c478bd9Sstevel@tonic-gate 
431*7c478bd9Sstevel@tonic-gate 	for (;;) {
432*7c478bd9Sstevel@tonic-gate 		/* Skip any whitespace */
433*7c478bd9Sstevel@tonic-gate 		while (isspace(*line) && *line != '\0')
434*7c478bd9Sstevel@tonic-gate 			line++;
435*7c478bd9Sstevel@tonic-gate 
436*7c478bd9Sstevel@tonic-gate 		if (*line == '\'') {
437*7c478bd9Sstevel@tonic-gate 			line++;
438*7c478bd9Sstevel@tonic-gate 			if (*line == '\0')
439*7c478bd9Sstevel@tonic-gate 				return (i);
440*7c478bd9Sstevel@tonic-gate 			insingle_quote = _B_TRUE;
441*7c478bd9Sstevel@tonic-gate 		} else if (*line == '"') {
442*7c478bd9Sstevel@tonic-gate 			line++;
443*7c478bd9Sstevel@tonic-gate 			if (*line == '\0')
444*7c478bd9Sstevel@tonic-gate 				return (i);
445*7c478bd9Sstevel@tonic-gate 			indouble_quote = _B_TRUE;
446*7c478bd9Sstevel@tonic-gate 		}
447*7c478bd9Sstevel@tonic-gate 		argvec[i] = line;
448*7c478bd9Sstevel@tonic-gate 		if (*line == '\0')
449*7c478bd9Sstevel@tonic-gate 			return (i);
450*7c478bd9Sstevel@tonic-gate 		i++;
451*7c478bd9Sstevel@tonic-gate 		/* Skip until next whitespace or end of quoted text */
452*7c478bd9Sstevel@tonic-gate 		if (insingle_quote) {
453*7c478bd9Sstevel@tonic-gate 			while (*line != '\'' && *line != '\0')
454*7c478bd9Sstevel@tonic-gate 				line++;
455*7c478bd9Sstevel@tonic-gate 			if (*line == '\'') {
456*7c478bd9Sstevel@tonic-gate 				*line = ' ';
457*7c478bd9Sstevel@tonic-gate 			} else {
458*7c478bd9Sstevel@tonic-gate 				/* Handle missing quote at end */
459*7c478bd9Sstevel@tonic-gate 				i--;
460*7c478bd9Sstevel@tonic-gate 				conferr("Missing end quote - ignoring <%s>\n",
461*7c478bd9Sstevel@tonic-gate 				    argvec[i]);
462*7c478bd9Sstevel@tonic-gate 				return (i);
463*7c478bd9Sstevel@tonic-gate 			}
464*7c478bd9Sstevel@tonic-gate 			insingle_quote = _B_FALSE;
465*7c478bd9Sstevel@tonic-gate 		} else if (indouble_quote) {
466*7c478bd9Sstevel@tonic-gate 			while (*line != '"' && *line != '\0')
467*7c478bd9Sstevel@tonic-gate 				line++;
468*7c478bd9Sstevel@tonic-gate 			if (*line == '"') {
469*7c478bd9Sstevel@tonic-gate 				*line = ' ';
470*7c478bd9Sstevel@tonic-gate 			} else {
471*7c478bd9Sstevel@tonic-gate 				/* Handle missing quote at end */
472*7c478bd9Sstevel@tonic-gate 				i--;
473*7c478bd9Sstevel@tonic-gate 				conferr("Missing end quote - ignoring <%s>\n",
474*7c478bd9Sstevel@tonic-gate 				    argvec[i]);
475*7c478bd9Sstevel@tonic-gate 				return (i);
476*7c478bd9Sstevel@tonic-gate 			}
477*7c478bd9Sstevel@tonic-gate 			indouble_quote = _B_FALSE;
478*7c478bd9Sstevel@tonic-gate 		} else {
479*7c478bd9Sstevel@tonic-gate 			while (!isspace(*line) && *line != '\0')
480*7c478bd9Sstevel@tonic-gate 				line++;
481*7c478bd9Sstevel@tonic-gate 		}
482*7c478bd9Sstevel@tonic-gate 		if (*line != '\0') {
483*7c478bd9Sstevel@tonic-gate 			/* Break off argument */
484*7c478bd9Sstevel@tonic-gate 			*line++ = '\0';
485*7c478bd9Sstevel@tonic-gate 		}
486*7c478bd9Sstevel@tonic-gate 		if (i > argcount)
487*7c478bd9Sstevel@tonic-gate 			return (argcount);
488*7c478bd9Sstevel@tonic-gate 	}
489*7c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
490*7c478bd9Sstevel@tonic-gate }
491*7c478bd9Sstevel@tonic-gate 
492*7c478bd9Sstevel@tonic-gate static void
493*7c478bd9Sstevel@tonic-gate parse_var_value(config_type_t type, struct configinfo *list, char *varstr,
494*7c478bd9Sstevel@tonic-gate     char *valstr, struct confvar *confvar)
495*7c478bd9Sstevel@tonic-gate {
496*7c478bd9Sstevel@tonic-gate 	struct configinfo *cip;
497*7c478bd9Sstevel@tonic-gate 	uint_t val;
498*7c478bd9Sstevel@tonic-gate 
499*7c478bd9Sstevel@tonic-gate 	if (debug & D_CONFIG) {
500*7c478bd9Sstevel@tonic-gate 		logmsg(LOG_DEBUG, "parse_var_value(%d, %s, %s)\n",
501*7c478bd9Sstevel@tonic-gate 		    (int)type, varstr, valstr);
502*7c478bd9Sstevel@tonic-gate 	}
503*7c478bd9Sstevel@tonic-gate 
504*7c478bd9Sstevel@tonic-gate 	for (cip = list; cip->ci_name != NULL; cip++) {
505*7c478bd9Sstevel@tonic-gate 		if (strcasecmp(cip->ci_name, varstr) == 0)
506*7c478bd9Sstevel@tonic-gate 			break;
507*7c478bd9Sstevel@tonic-gate 	}
508*7c478bd9Sstevel@tonic-gate 	if (cip->ci_name == NULL) {
509*7c478bd9Sstevel@tonic-gate 		conferr("Unknown variable: <%s>\n", varstr);
510*7c478bd9Sstevel@tonic-gate 		return;
511*7c478bd9Sstevel@tonic-gate 	}
512*7c478bd9Sstevel@tonic-gate 	if (!(*cip->ci_parsefunc)(valstr, &val)) {
513*7c478bd9Sstevel@tonic-gate 		conferr("Bad value: <%s>\n", valstr);
514*7c478bd9Sstevel@tonic-gate 		return;
515*7c478bd9Sstevel@tonic-gate 	}
516*7c478bd9Sstevel@tonic-gate 	if (cip->ci_min != 0 && val < cip->ci_min) {
517*7c478bd9Sstevel@tonic-gate 		conferr("Value %s is below minimum %u for %s\n",
518*7c478bd9Sstevel@tonic-gate 		    valstr, cip->ci_min, varstr);
519*7c478bd9Sstevel@tonic-gate 		return;
520*7c478bd9Sstevel@tonic-gate 	}
521*7c478bd9Sstevel@tonic-gate 	if (cip->ci_max != ~0U && val > cip->ci_max) {
522*7c478bd9Sstevel@tonic-gate 		conferr("Value %s is above maximum %u for %s\n",
523*7c478bd9Sstevel@tonic-gate 		    valstr, cip->ci_max, varstr);
524*7c478bd9Sstevel@tonic-gate 		return;
525*7c478bd9Sstevel@tonic-gate 	}
526*7c478bd9Sstevel@tonic-gate 	/* Check against dynamic/relative limits */
527*7c478bd9Sstevel@tonic-gate 	if (type == CONFIG_IF) {
528*7c478bd9Sstevel@tonic-gate 		if (cip->ci_index == I_MinRtrAdvInterval &&
529*7c478bd9Sstevel@tonic-gate 		    confvar[I_MaxRtrAdvInterval].cf_notdefault &&
530*7c478bd9Sstevel@tonic-gate 		    val > confvar[I_MaxRtrAdvInterval].cf_value * 0.75) {
531*7c478bd9Sstevel@tonic-gate 			conferr("MinRtrAdvInterval exceeds .75 * "
532*7c478bd9Sstevel@tonic-gate 			    "MaxRtrAdvInterval (%u)\n",
533*7c478bd9Sstevel@tonic-gate 			    confvar[I_MaxRtrAdvInterval].cf_value);
534*7c478bd9Sstevel@tonic-gate 			return;
535*7c478bd9Sstevel@tonic-gate 		}
536*7c478bd9Sstevel@tonic-gate 		if (cip->ci_index == I_MaxRtrAdvInterval &&
537*7c478bd9Sstevel@tonic-gate 		    confvar[I_MinRtrAdvInterval].cf_notdefault &&
538*7c478bd9Sstevel@tonic-gate 		    confvar[I_MinRtrAdvInterval].cf_value > val * 0.75) {
539*7c478bd9Sstevel@tonic-gate 			conferr("MinRtrAdvInterval (%u) exceeds .75 * "
540*7c478bd9Sstevel@tonic-gate 			    "MaxRtrAdvInterval\n",
541*7c478bd9Sstevel@tonic-gate 			    confvar[I_MinRtrAdvInterval].cf_value);
542*7c478bd9Sstevel@tonic-gate 			return;
543*7c478bd9Sstevel@tonic-gate 		}
544*7c478bd9Sstevel@tonic-gate 		if (cip->ci_index == I_AdvDefaultLifetime &&
545*7c478bd9Sstevel@tonic-gate 		    confvar[I_MaxRtrAdvInterval].cf_notdefault &&
546*7c478bd9Sstevel@tonic-gate 		    val != 0 &&
547*7c478bd9Sstevel@tonic-gate 		    val < confvar[I_MaxRtrAdvInterval].cf_value) {
548*7c478bd9Sstevel@tonic-gate 			conferr("AdvDefaultLifetime is not between "
549*7c478bd9Sstevel@tonic-gate 			    "MaxRtrAdrInterval (%u) and 9000 seconds\n",
550*7c478bd9Sstevel@tonic-gate 			    confvar[I_MaxRtrAdvInterval].cf_value);
551*7c478bd9Sstevel@tonic-gate 			return;
552*7c478bd9Sstevel@tonic-gate 		}
553*7c478bd9Sstevel@tonic-gate 		if (cip->ci_index == I_MaxRtrAdvInterval &&
554*7c478bd9Sstevel@tonic-gate 		    confvar[I_AdvDefaultLifetime].cf_notdefault &&
555*7c478bd9Sstevel@tonic-gate 		    confvar[I_AdvDefaultLifetime].cf_value < val) {
556*7c478bd9Sstevel@tonic-gate 			conferr("AdvDefaultLifetime (%u) is not between "
557*7c478bd9Sstevel@tonic-gate 			    "MaxRtrAdrInterval and 9000 seconds\n",
558*7c478bd9Sstevel@tonic-gate 			    confvar[I_AdvDefaultLifetime].cf_value);
559*7c478bd9Sstevel@tonic-gate 			return;
560*7c478bd9Sstevel@tonic-gate 		}
561*7c478bd9Sstevel@tonic-gate 	}
562*7c478bd9Sstevel@tonic-gate 	confvar[cip->ci_index].cf_value = val;
563*7c478bd9Sstevel@tonic-gate 	confvar[cip->ci_index].cf_notdefault = _B_TRUE;
564*7c478bd9Sstevel@tonic-gate 
565*7c478bd9Sstevel@tonic-gate 	/* Derive dynamic/relative variables based on this one */
566*7c478bd9Sstevel@tonic-gate 	if (type == CONFIG_IF) {
567*7c478bd9Sstevel@tonic-gate 		if (cip->ci_index == I_MaxRtrAdvInterval &&
568*7c478bd9Sstevel@tonic-gate 		    !confvar[I_MinRtrAdvInterval].cf_notdefault)
569*7c478bd9Sstevel@tonic-gate 			confvar[I_MinRtrAdvInterval].cf_value = val / 3;
570*7c478bd9Sstevel@tonic-gate 		if (cip->ci_index == I_MaxRtrAdvInterval &&
571*7c478bd9Sstevel@tonic-gate 		    !confvar[I_AdvDefaultLifetime].cf_notdefault)
572*7c478bd9Sstevel@tonic-gate 		    confvar[I_AdvDefaultLifetime].cf_value = 3 * val;
573*7c478bd9Sstevel@tonic-gate 	}
574*7c478bd9Sstevel@tonic-gate }
575*7c478bd9Sstevel@tonic-gate 
576*7c478bd9Sstevel@tonic-gate /*
577*7c478bd9Sstevel@tonic-gate  * Split up the line into <variable> <value> pairs
578*7c478bd9Sstevel@tonic-gate  */
579*7c478bd9Sstevel@tonic-gate static void
580*7c478bd9Sstevel@tonic-gate parse_default(config_type_t type, struct configinfo *list,
581*7c478bd9Sstevel@tonic-gate     char *argvec[], int argcount, struct confvar *defaults)
582*7c478bd9Sstevel@tonic-gate {
583*7c478bd9Sstevel@tonic-gate 	if (debug & D_CONFIG)
584*7c478bd9Sstevel@tonic-gate 		logmsg(LOG_DEBUG, "parse_default: argc %d\n", argcount);
585*7c478bd9Sstevel@tonic-gate 	while (argcount >= 2) {
586*7c478bd9Sstevel@tonic-gate 		parse_var_value(type, list, argvec[0], argvec[1], defaults);
587*7c478bd9Sstevel@tonic-gate 
588*7c478bd9Sstevel@tonic-gate 		argcount -= 2;
589*7c478bd9Sstevel@tonic-gate 		argvec += 2;
590*7c478bd9Sstevel@tonic-gate 	}
591*7c478bd9Sstevel@tonic-gate 	if (argcount != 0)
592*7c478bd9Sstevel@tonic-gate 		conferr("Trailing text <%s> ignored\n", argvec[0]);
593*7c478bd9Sstevel@tonic-gate }
594*7c478bd9Sstevel@tonic-gate 
595*7c478bd9Sstevel@tonic-gate /*
596*7c478bd9Sstevel@tonic-gate  * Returns true if ok; otherwise false.
597*7c478bd9Sstevel@tonic-gate  */
598*7c478bd9Sstevel@tonic-gate static void
599*7c478bd9Sstevel@tonic-gate parse_if(struct configinfo *list, char *argvec[], int argcount)
600*7c478bd9Sstevel@tonic-gate {
601*7c478bd9Sstevel@tonic-gate 	char *ifname;
602*7c478bd9Sstevel@tonic-gate 	struct phyint *pi;
603*7c478bd9Sstevel@tonic-gate 	char save[sizeof (pi->pi_config)];
604*7c478bd9Sstevel@tonic-gate 
605*7c478bd9Sstevel@tonic-gate 	if (debug & D_CONFIG)
606*7c478bd9Sstevel@tonic-gate 		logmsg(LOG_DEBUG, "parse_if: argc %d\n", argcount);
607*7c478bd9Sstevel@tonic-gate 
608*7c478bd9Sstevel@tonic-gate 	if (argcount < 1) {
609*7c478bd9Sstevel@tonic-gate 		conferr("Missing interface name\n");
610*7c478bd9Sstevel@tonic-gate 		return;
611*7c478bd9Sstevel@tonic-gate 	}
612*7c478bd9Sstevel@tonic-gate 	ifname = argvec[0];
613*7c478bd9Sstevel@tonic-gate 	argvec++;
614*7c478bd9Sstevel@tonic-gate 	argcount--;
615*7c478bd9Sstevel@tonic-gate 
616*7c478bd9Sstevel@tonic-gate 	pi = phyint_lookup(ifname);
617*7c478bd9Sstevel@tonic-gate 	if (pi == NULL) {
618*7c478bd9Sstevel@tonic-gate 		/*
619*7c478bd9Sstevel@tonic-gate 		 * Create the physical interface structure.
620*7c478bd9Sstevel@tonic-gate 		 * Note, phyint_create() sets the interface
621*7c478bd9Sstevel@tonic-gate 		 * defaults in pi_config.
622*7c478bd9Sstevel@tonic-gate 		 */
623*7c478bd9Sstevel@tonic-gate 		pi = phyint_create(ifname);
624*7c478bd9Sstevel@tonic-gate 		if (pi == NULL) {
625*7c478bd9Sstevel@tonic-gate 			conferr("Unable to use interface %s\n", ifname);
626*7c478bd9Sstevel@tonic-gate 			return;
627*7c478bd9Sstevel@tonic-gate 		}
628*7c478bd9Sstevel@tonic-gate 	}
629*7c478bd9Sstevel@tonic-gate 
630*7c478bd9Sstevel@tonic-gate 	(void) memcpy(save, pi->pi_config, sizeof (save));
631*7c478bd9Sstevel@tonic-gate 	while (argcount >= 2) {
632*7c478bd9Sstevel@tonic-gate 		parse_var_value(CONFIG_IF, list, argvec[0], argvec[1],
633*7c478bd9Sstevel@tonic-gate 		    pi->pi_config);
634*7c478bd9Sstevel@tonic-gate 
635*7c478bd9Sstevel@tonic-gate 		argcount -= 2;
636*7c478bd9Sstevel@tonic-gate 		argvec += 2;
637*7c478bd9Sstevel@tonic-gate 	}
638*7c478bd9Sstevel@tonic-gate 	if (argcount != 0)
639*7c478bd9Sstevel@tonic-gate 		logmsg(LOG_ERR, "Trailing text <%s> ignored\n", argvec[0]);
640*7c478bd9Sstevel@tonic-gate 	check_if_var_consistency(pi->pi_config, save, sizeof (save));
641*7c478bd9Sstevel@tonic-gate }
642*7c478bd9Sstevel@tonic-gate 
643*7c478bd9Sstevel@tonic-gate static void
644*7c478bd9Sstevel@tonic-gate parse_prefix(struct configinfo *list, char *argvec[], int argcount)
645*7c478bd9Sstevel@tonic-gate {
646*7c478bd9Sstevel@tonic-gate 	char *ifname, *prefix;
647*7c478bd9Sstevel@tonic-gate 	struct phyint *pi;
648*7c478bd9Sstevel@tonic-gate 	struct adv_prefix *adv_pr;
649*7c478bd9Sstevel@tonic-gate 	struct in6_addr in6;
650*7c478bd9Sstevel@tonic-gate 	int prefixlen;
651*7c478bd9Sstevel@tonic-gate 	char save[sizeof (adv_pr->adv_pr_config)];
652*7c478bd9Sstevel@tonic-gate 
653*7c478bd9Sstevel@tonic-gate 	if (debug & D_CONFIG)
654*7c478bd9Sstevel@tonic-gate 		logmsg(LOG_DEBUG, "parse_prefix: argc %d\n", argcount);
655*7c478bd9Sstevel@tonic-gate 
656*7c478bd9Sstevel@tonic-gate 	if (argcount < 2) {
657*7c478bd9Sstevel@tonic-gate 		conferr("Missing prefix and/or interface name\n");
658*7c478bd9Sstevel@tonic-gate 		return;
659*7c478bd9Sstevel@tonic-gate 	}
660*7c478bd9Sstevel@tonic-gate 	prefix = argvec[0];
661*7c478bd9Sstevel@tonic-gate 	ifname = argvec[1];
662*7c478bd9Sstevel@tonic-gate 	argvec += 2;
663*7c478bd9Sstevel@tonic-gate 	argcount -= 2;
664*7c478bd9Sstevel@tonic-gate 
665*7c478bd9Sstevel@tonic-gate 	prefixlen = parse_addrprefix(prefix, &in6);
666*7c478bd9Sstevel@tonic-gate 	if (prefixlen == -1) {
667*7c478bd9Sstevel@tonic-gate 		conferr("Bad prefix %s\n", prefix);
668*7c478bd9Sstevel@tonic-gate 		return;
669*7c478bd9Sstevel@tonic-gate 	}
670*7c478bd9Sstevel@tonic-gate 
671*7c478bd9Sstevel@tonic-gate 	pi = phyint_lookup(ifname);
672*7c478bd9Sstevel@tonic-gate 	if (pi == NULL) {
673*7c478bd9Sstevel@tonic-gate 		/*
674*7c478bd9Sstevel@tonic-gate 		 * Create the physical interface structure.
675*7c478bd9Sstevel@tonic-gate 		 * Note, phyint_create() sets the interface
676*7c478bd9Sstevel@tonic-gate 		 * defaults in pi_config.
677*7c478bd9Sstevel@tonic-gate 		 */
678*7c478bd9Sstevel@tonic-gate 		pi = phyint_create(ifname);
679*7c478bd9Sstevel@tonic-gate 		if (pi == NULL) {
680*7c478bd9Sstevel@tonic-gate 			conferr("Unable to use interface %s\n", ifname);
681*7c478bd9Sstevel@tonic-gate 			return;
682*7c478bd9Sstevel@tonic-gate 		}
683*7c478bd9Sstevel@tonic-gate 	}
684*7c478bd9Sstevel@tonic-gate 	adv_pr = adv_prefix_lookup(pi, in6, prefixlen);
685*7c478bd9Sstevel@tonic-gate 	if (adv_pr == NULL) {
686*7c478bd9Sstevel@tonic-gate 		int i;
687*7c478bd9Sstevel@tonic-gate 
688*7c478bd9Sstevel@tonic-gate 		adv_pr = adv_prefix_create(pi, in6, prefixlen);
689*7c478bd9Sstevel@tonic-gate 		if (adv_pr == NULL) {
690*7c478bd9Sstevel@tonic-gate 			conferr("Unable to create prefix %s\n", prefix);
691*7c478bd9Sstevel@tonic-gate 			return;
692*7c478bd9Sstevel@tonic-gate 		}
693*7c478bd9Sstevel@tonic-gate 		/*
694*7c478bd9Sstevel@tonic-gate 		 * Copy the defaults from the default array.
695*7c478bd9Sstevel@tonic-gate 		 */
696*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < I_PREFIXSIZE; i++) {
697*7c478bd9Sstevel@tonic-gate 			adv_pr->adv_pr_config[i].cf_value =
698*7c478bd9Sstevel@tonic-gate 			    prefixdefaults[i].cf_value;
699*7c478bd9Sstevel@tonic-gate 			adv_pr->adv_pr_config[i].cf_notdefault =
700*7c478bd9Sstevel@tonic-gate 			    prefixdefaults[i].cf_notdefault;
701*7c478bd9Sstevel@tonic-gate 		}
702*7c478bd9Sstevel@tonic-gate 	}
703*7c478bd9Sstevel@tonic-gate 
704*7c478bd9Sstevel@tonic-gate 	(void) memcpy(save, adv_pr->adv_pr_config, sizeof (save));
705*7c478bd9Sstevel@tonic-gate 	while (argcount >= 2) {
706*7c478bd9Sstevel@tonic-gate 		parse_var_value(CONFIG_PREFIX, list, argvec[0], argvec[1],
707*7c478bd9Sstevel@tonic-gate 		    adv_pr->adv_pr_config);
708*7c478bd9Sstevel@tonic-gate 
709*7c478bd9Sstevel@tonic-gate 		argcount -= 2;
710*7c478bd9Sstevel@tonic-gate 		argvec += 2;
711*7c478bd9Sstevel@tonic-gate 	}
712*7c478bd9Sstevel@tonic-gate 	check_var_consistency(adv_pr->adv_pr_config, save, sizeof (save));
713*7c478bd9Sstevel@tonic-gate 	if (argcount != 0)
714*7c478bd9Sstevel@tonic-gate 		logmsg(LOG_ERR, "Trailing text <%s> ignored\n", argvec[0]);
715*7c478bd9Sstevel@tonic-gate }
716*7c478bd9Sstevel@tonic-gate 
717*7c478bd9Sstevel@tonic-gate /*
718*7c478bd9Sstevel@tonic-gate  * Returns true if ok (and *resp updated) and false if failed.
719*7c478bd9Sstevel@tonic-gate  */
720*7c478bd9Sstevel@tonic-gate static boolean_t
721*7c478bd9Sstevel@tonic-gate parse_onoff(char *str, uint_t *resp)
722*7c478bd9Sstevel@tonic-gate {
723*7c478bd9Sstevel@tonic-gate 	if (strcasecmp(str, "on") == 0) {
724*7c478bd9Sstevel@tonic-gate 		*resp = 1;
725*7c478bd9Sstevel@tonic-gate 		return (_B_TRUE);
726*7c478bd9Sstevel@tonic-gate 	}
727*7c478bd9Sstevel@tonic-gate 	if (strcasecmp(str, "off") == 0) {
728*7c478bd9Sstevel@tonic-gate 		*resp = 0;
729*7c478bd9Sstevel@tonic-gate 		return (_B_TRUE);
730*7c478bd9Sstevel@tonic-gate 	}
731*7c478bd9Sstevel@tonic-gate 	if (strcasecmp(str, "true") == 0) {
732*7c478bd9Sstevel@tonic-gate 		*resp = 1;
733*7c478bd9Sstevel@tonic-gate 		return (_B_TRUE);
734*7c478bd9Sstevel@tonic-gate 	}
735*7c478bd9Sstevel@tonic-gate 	if (strcasecmp(str, "false") == 0) {
736*7c478bd9Sstevel@tonic-gate 		*resp = 0;
737*7c478bd9Sstevel@tonic-gate 		return (_B_TRUE);
738*7c478bd9Sstevel@tonic-gate 	}
739*7c478bd9Sstevel@tonic-gate 	if (parse_int(str, resp)) {
740*7c478bd9Sstevel@tonic-gate 		if (*resp == 0 || *resp == 1)
741*7c478bd9Sstevel@tonic-gate 			return (_B_TRUE);
742*7c478bd9Sstevel@tonic-gate 	}
743*7c478bd9Sstevel@tonic-gate 	return (_B_FALSE);
744*7c478bd9Sstevel@tonic-gate }
745*7c478bd9Sstevel@tonic-gate 
746*7c478bd9Sstevel@tonic-gate /*
747*7c478bd9Sstevel@tonic-gate  * Returns true if ok (and *resp updated) and false if failed.
748*7c478bd9Sstevel@tonic-gate  */
749*7c478bd9Sstevel@tonic-gate static boolean_t
750*7c478bd9Sstevel@tonic-gate parse_int(char *str, uint_t *resp)
751*7c478bd9Sstevel@tonic-gate {
752*7c478bd9Sstevel@tonic-gate 	char *end;
753*7c478bd9Sstevel@tonic-gate 	int res;
754*7c478bd9Sstevel@tonic-gate 
755*7c478bd9Sstevel@tonic-gate 	res = strtoul(str, &end, 0);
756*7c478bd9Sstevel@tonic-gate 	if (end == str)
757*7c478bd9Sstevel@tonic-gate 		return (_B_FALSE);
758*7c478bd9Sstevel@tonic-gate 	*resp = res;
759*7c478bd9Sstevel@tonic-gate 	return (_B_TRUE);
760*7c478bd9Sstevel@tonic-gate }
761*7c478bd9Sstevel@tonic-gate 
762*7c478bd9Sstevel@tonic-gate /*
763*7c478bd9Sstevel@tonic-gate  * Parse something with a unit of millseconds.
764*7c478bd9Sstevel@tonic-gate  * Regognizes the suffixes "ms", "s", "m", "h", and "d".
765*7c478bd9Sstevel@tonic-gate  *
766*7c478bd9Sstevel@tonic-gate  * Returns true if ok (and *resp updated) and false if failed.
767*7c478bd9Sstevel@tonic-gate  */
768*7c478bd9Sstevel@tonic-gate static boolean_t
769*7c478bd9Sstevel@tonic-gate parse_ms(char *str, uint_t *resp)
770*7c478bd9Sstevel@tonic-gate {
771*7c478bd9Sstevel@tonic-gate 	/* Look at the last and next to last character */
772*7c478bd9Sstevel@tonic-gate 	char *cp, *last, *nlast;
773*7c478bd9Sstevel@tonic-gate 	char str2[BUFSIZ];	/* For local modification */
774*7c478bd9Sstevel@tonic-gate 	int multiplier = 1;
775*7c478bd9Sstevel@tonic-gate 
776*7c478bd9Sstevel@tonic-gate 	(void) strncpy(str2, str, sizeof (str2));
777*7c478bd9Sstevel@tonic-gate 	str2[sizeof (str2) - 1] = '\0';
778*7c478bd9Sstevel@tonic-gate 
779*7c478bd9Sstevel@tonic-gate 	last = str2;
780*7c478bd9Sstevel@tonic-gate 	nlast = NULL;
781*7c478bd9Sstevel@tonic-gate 	for (cp = str2; *cp != '\0'; cp++) {
782*7c478bd9Sstevel@tonic-gate 		nlast = last;
783*7c478bd9Sstevel@tonic-gate 		last = cp;
784*7c478bd9Sstevel@tonic-gate 	}
785*7c478bd9Sstevel@tonic-gate 	if (debug & D_PARSE) {
786*7c478bd9Sstevel@tonic-gate 		logmsg(LOG_DEBUG, "parse_ms: last <%c> nlast <%c>\n",
787*7c478bd9Sstevel@tonic-gate 		    (last != NULL ? *last : ' '),
788*7c478bd9Sstevel@tonic-gate 		    (nlast != NULL ? *nlast : ' '));
789*7c478bd9Sstevel@tonic-gate 	}
790*7c478bd9Sstevel@tonic-gate 	switch (*last) {
791*7c478bd9Sstevel@tonic-gate 	case 'd':
792*7c478bd9Sstevel@tonic-gate 		multiplier *= 24;
793*7c478bd9Sstevel@tonic-gate 		/* FALLTHRU */
794*7c478bd9Sstevel@tonic-gate 	case 'h':
795*7c478bd9Sstevel@tonic-gate 		multiplier *= 60;
796*7c478bd9Sstevel@tonic-gate 		/* FALLTHRU */
797*7c478bd9Sstevel@tonic-gate 	case 'm':
798*7c478bd9Sstevel@tonic-gate 		multiplier *= 60;
799*7c478bd9Sstevel@tonic-gate 		*last = '\0';
800*7c478bd9Sstevel@tonic-gate 		multiplier *= 1000;	/* Convert to milliseconds */
801*7c478bd9Sstevel@tonic-gate 		break;
802*7c478bd9Sstevel@tonic-gate 	case 's':
803*7c478bd9Sstevel@tonic-gate 		/* Could be "ms" or "s" */
804*7c478bd9Sstevel@tonic-gate 		if (nlast != NULL && *nlast == 'm') {
805*7c478bd9Sstevel@tonic-gate 			/* "ms" */
806*7c478bd9Sstevel@tonic-gate 			*nlast = '\0';
807*7c478bd9Sstevel@tonic-gate 		} else {
808*7c478bd9Sstevel@tonic-gate 			*last = '\0';
809*7c478bd9Sstevel@tonic-gate 			multiplier *= 1000;	/* Convert to milliseconds */
810*7c478bd9Sstevel@tonic-gate 		}
811*7c478bd9Sstevel@tonic-gate 		break;
812*7c478bd9Sstevel@tonic-gate 	}
813*7c478bd9Sstevel@tonic-gate 
814*7c478bd9Sstevel@tonic-gate 	if (!parse_int(str2, resp))
815*7c478bd9Sstevel@tonic-gate 		return (_B_FALSE);
816*7c478bd9Sstevel@tonic-gate 
817*7c478bd9Sstevel@tonic-gate 	*resp *= multiplier;
818*7c478bd9Sstevel@tonic-gate 	return (_B_TRUE);
819*7c478bd9Sstevel@tonic-gate }
820*7c478bd9Sstevel@tonic-gate 
821*7c478bd9Sstevel@tonic-gate /*
822*7c478bd9Sstevel@tonic-gate  * Parse something with a unit of seconds.
823*7c478bd9Sstevel@tonic-gate  * Regognizes the suffixes "s", "m", "h", and "d".
824*7c478bd9Sstevel@tonic-gate  *
825*7c478bd9Sstevel@tonic-gate  * Returns true if ok (and *resp updated) and false if failed.
826*7c478bd9Sstevel@tonic-gate  */
827*7c478bd9Sstevel@tonic-gate static boolean_t
828*7c478bd9Sstevel@tonic-gate parse_s(char *str, uint_t *resp)
829*7c478bd9Sstevel@tonic-gate {
830*7c478bd9Sstevel@tonic-gate 	/* Look at the last character */
831*7c478bd9Sstevel@tonic-gate 	char *cp, *last;
832*7c478bd9Sstevel@tonic-gate 	char str2[BUFSIZ];	/* For local modification */
833*7c478bd9Sstevel@tonic-gate 	int multiplier = 1;
834*7c478bd9Sstevel@tonic-gate 
835*7c478bd9Sstevel@tonic-gate 	(void) strncpy(str2, str, sizeof (str2));
836*7c478bd9Sstevel@tonic-gate 	str2[sizeof (str2) - 1] = '\0';
837*7c478bd9Sstevel@tonic-gate 
838*7c478bd9Sstevel@tonic-gate 	last = str2;
839*7c478bd9Sstevel@tonic-gate 	for (cp = str2; *cp != '\0'; cp++) {
840*7c478bd9Sstevel@tonic-gate 		last = cp;
841*7c478bd9Sstevel@tonic-gate 	}
842*7c478bd9Sstevel@tonic-gate 	if (debug & D_PARSE) {
843*7c478bd9Sstevel@tonic-gate 		logmsg(LOG_DEBUG, "parse_s: last <%c>\n",
844*7c478bd9Sstevel@tonic-gate 		    (last != NULL ? *last : ' '));
845*7c478bd9Sstevel@tonic-gate 	}
846*7c478bd9Sstevel@tonic-gate 	switch (*last) {
847*7c478bd9Sstevel@tonic-gate 	case 'd':
848*7c478bd9Sstevel@tonic-gate 		multiplier *= 24;
849*7c478bd9Sstevel@tonic-gate 		/* FALLTHRU */
850*7c478bd9Sstevel@tonic-gate 	case 'h':
851*7c478bd9Sstevel@tonic-gate 		multiplier *= 60;
852*7c478bd9Sstevel@tonic-gate 		/* FALLTHRU */
853*7c478bd9Sstevel@tonic-gate 	case 'm':
854*7c478bd9Sstevel@tonic-gate 		multiplier *= 60;
855*7c478bd9Sstevel@tonic-gate 		/* FALLTHRU */
856*7c478bd9Sstevel@tonic-gate 	case 's':
857*7c478bd9Sstevel@tonic-gate 		*last = '\0';
858*7c478bd9Sstevel@tonic-gate 		break;
859*7c478bd9Sstevel@tonic-gate 	}
860*7c478bd9Sstevel@tonic-gate 	if (!parse_int(str2, resp))
861*7c478bd9Sstevel@tonic-gate 		return (_B_FALSE);
862*7c478bd9Sstevel@tonic-gate 
863*7c478bd9Sstevel@tonic-gate 	*resp *= multiplier;
864*7c478bd9Sstevel@tonic-gate 	return (_B_TRUE);
865*7c478bd9Sstevel@tonic-gate }
866*7c478bd9Sstevel@tonic-gate 
867*7c478bd9Sstevel@tonic-gate /*
868*7c478bd9Sstevel@tonic-gate  * Return prefixlen (0 to 128) if ok; -1 if failed.
869*7c478bd9Sstevel@tonic-gate  */
870*7c478bd9Sstevel@tonic-gate static int
871*7c478bd9Sstevel@tonic-gate parse_addrprefix(char *strin, struct in6_addr *in6)
872*7c478bd9Sstevel@tonic-gate {
873*7c478bd9Sstevel@tonic-gate 	char str[BUFSIZ];	/* Local copy for modification */
874*7c478bd9Sstevel@tonic-gate 	int prefixlen;
875*7c478bd9Sstevel@tonic-gate 	char *cp;
876*7c478bd9Sstevel@tonic-gate 	char *end;
877*7c478bd9Sstevel@tonic-gate 
878*7c478bd9Sstevel@tonic-gate 	(void) strncpy(str, strin, sizeof (str));
879*7c478bd9Sstevel@tonic-gate 	str[sizeof (str) - 1] = '\0';
880*7c478bd9Sstevel@tonic-gate 
881*7c478bd9Sstevel@tonic-gate 	cp = strchr(str, '/');
882*7c478bd9Sstevel@tonic-gate 	if (cp == NULL)
883*7c478bd9Sstevel@tonic-gate 		return (-1);
884*7c478bd9Sstevel@tonic-gate 	*cp = '\0';
885*7c478bd9Sstevel@tonic-gate 	cp++;
886*7c478bd9Sstevel@tonic-gate 
887*7c478bd9Sstevel@tonic-gate 	prefixlen = strtol(cp, &end, 10);
888*7c478bd9Sstevel@tonic-gate 	if (cp == end)
889*7c478bd9Sstevel@tonic-gate 		return (-1);
890*7c478bd9Sstevel@tonic-gate 
891*7c478bd9Sstevel@tonic-gate 	if (prefixlen < 0 || prefixlen > IPV6_ABITS)
892*7c478bd9Sstevel@tonic-gate 		return (-1);
893*7c478bd9Sstevel@tonic-gate 
894*7c478bd9Sstevel@tonic-gate 	if (inet_pton(AF_INET6, str, in6) != 1)
895*7c478bd9Sstevel@tonic-gate 		return (-1);
896*7c478bd9Sstevel@tonic-gate 
897*7c478bd9Sstevel@tonic-gate 	return (prefixlen);
898*7c478bd9Sstevel@tonic-gate }
899*7c478bd9Sstevel@tonic-gate 
900*7c478bd9Sstevel@tonic-gate /*
901*7c478bd9Sstevel@tonic-gate  * Parse an absolute date using a datemsk config file.
902*7c478bd9Sstevel@tonic-gate  * Return the difference (measured in seconds) between that date/time and
903*7c478bd9Sstevel@tonic-gate  * the current date/time.
904*7c478bd9Sstevel@tonic-gate  * If the date has passed return zero.
905*7c478bd9Sstevel@tonic-gate  *
906*7c478bd9Sstevel@tonic-gate  * Returns true if ok (and *resp updated) and false if failed.
907*7c478bd9Sstevel@tonic-gate  * XXX Due to getdate limitations can not exceed year 2038.
908*7c478bd9Sstevel@tonic-gate  */
909*7c478bd9Sstevel@tonic-gate static boolean_t
910*7c478bd9Sstevel@tonic-gate parse_date(char *str, uint_t *resp)
911*7c478bd9Sstevel@tonic-gate {
912*7c478bd9Sstevel@tonic-gate 	struct tm *tm;
913*7c478bd9Sstevel@tonic-gate 	struct timeval tvs;
914*7c478bd9Sstevel@tonic-gate 	time_t time, ntime;
915*7c478bd9Sstevel@tonic-gate 
916*7c478bd9Sstevel@tonic-gate 	if (getenv("DATEMSK") == NULL) {
917*7c478bd9Sstevel@tonic-gate 		(void) putenv("DATEMSK=/etc/inet/datemsk.ndpd");
918*7c478bd9Sstevel@tonic-gate 	}
919*7c478bd9Sstevel@tonic-gate 
920*7c478bd9Sstevel@tonic-gate 	if (gettimeofday(&tvs, NULL) < 0) {
921*7c478bd9Sstevel@tonic-gate 		logperror("gettimeofday");
922*7c478bd9Sstevel@tonic-gate 		return (_B_FALSE);
923*7c478bd9Sstevel@tonic-gate 	}
924*7c478bd9Sstevel@tonic-gate 	time = tvs.tv_sec;
925*7c478bd9Sstevel@tonic-gate 	tm = getdate(str);
926*7c478bd9Sstevel@tonic-gate 	if (tm == NULL) {
927*7c478bd9Sstevel@tonic-gate 		logmsg(LOG_ERR, "Bad date <%s> (error %d)\n",
928*7c478bd9Sstevel@tonic-gate 		    str, getdate_err);
929*7c478bd9Sstevel@tonic-gate 		return (_B_FALSE);
930*7c478bd9Sstevel@tonic-gate 	}
931*7c478bd9Sstevel@tonic-gate 
932*7c478bd9Sstevel@tonic-gate 	ntime = mktime(tm);
933*7c478bd9Sstevel@tonic-gate 
934*7c478bd9Sstevel@tonic-gate 	if (debug & D_PARSE) {
935*7c478bd9Sstevel@tonic-gate 		char buf[BUFSIZ];
936*7c478bd9Sstevel@tonic-gate 
937*7c478bd9Sstevel@tonic-gate 		(void) strftime(buf, sizeof (buf), "%Y-%m-%d %R %Z", tm);
938*7c478bd9Sstevel@tonic-gate 		logmsg(LOG_DEBUG, "parse_date: <%s>, delta %ld seconds\n",
939*7c478bd9Sstevel@tonic-gate 		    buf, ntime - time);
940*7c478bd9Sstevel@tonic-gate 	}
941*7c478bd9Sstevel@tonic-gate 	if (ntime < time) {
942*7c478bd9Sstevel@tonic-gate 		conferr("Date in the past <%s>\n", str);
943*7c478bd9Sstevel@tonic-gate 		*resp = 0;
944*7c478bd9Sstevel@tonic-gate 		return (_B_TRUE);
945*7c478bd9Sstevel@tonic-gate 	}
946*7c478bd9Sstevel@tonic-gate 	*resp = (ntime - time);
947*7c478bd9Sstevel@tonic-gate 	return (_B_TRUE);
948*7c478bd9Sstevel@tonic-gate }
949*7c478bd9Sstevel@tonic-gate 
950*7c478bd9Sstevel@tonic-gate /* PRINTFLIKE1 */
951*7c478bd9Sstevel@tonic-gate static void
952*7c478bd9Sstevel@tonic-gate conferr(char *fmt, ...)
953*7c478bd9Sstevel@tonic-gate {
954*7c478bd9Sstevel@tonic-gate 	char msg[NDPD_LOGMSGSIZE];
955*7c478bd9Sstevel@tonic-gate 	size_t slen;
956*7c478bd9Sstevel@tonic-gate 
957*7c478bd9Sstevel@tonic-gate 	va_list ap;
958*7c478bd9Sstevel@tonic-gate 	va_start(ap, fmt);
959*7c478bd9Sstevel@tonic-gate 
960*7c478bd9Sstevel@tonic-gate 	(void) snprintf(msg, NDPD_LOGMSGSIZE, "%s line %d: ",
961*7c478bd9Sstevel@tonic-gate 	    conf_filename, lineno);
962*7c478bd9Sstevel@tonic-gate 	slen = strlen(msg);
963*7c478bd9Sstevel@tonic-gate 	(void) vsnprintf(msg + slen, NDPD_LOGMSGSIZE - slen, fmt, ap);
964*7c478bd9Sstevel@tonic-gate 
965*7c478bd9Sstevel@tonic-gate 	logmsg(LOG_ERR, "%s", msg);
966*7c478bd9Sstevel@tonic-gate 
967*7c478bd9Sstevel@tonic-gate 	va_end(ap);
968*7c478bd9Sstevel@tonic-gate }
969*7c478bd9Sstevel@tonic-gate 
970*7c478bd9Sstevel@tonic-gate static FILE *
971*7c478bd9Sstevel@tonic-gate open_conffile(char *filename)
972*7c478bd9Sstevel@tonic-gate {
973*7c478bd9Sstevel@tonic-gate 	if (strlcpy(conf_filename, filename, MAXPATHLEN) >= MAXPATHLEN) {
974*7c478bd9Sstevel@tonic-gate 		logmsg(LOG_ERR, "config file pathname is too long\n");
975*7c478bd9Sstevel@tonic-gate 		return (NULL);
976*7c478bd9Sstevel@tonic-gate 	}
977*7c478bd9Sstevel@tonic-gate 
978*7c478bd9Sstevel@tonic-gate 	lineno = 0;
979*7c478bd9Sstevel@tonic-gate 
980*7c478bd9Sstevel@tonic-gate 	return (fopen(filename, "r"));
981*7c478bd9Sstevel@tonic-gate 
982*7c478bd9Sstevel@tonic-gate }
983