xref: /titanic_51/usr/src/lib/libnsl/netselect/netselect.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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 2004 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 /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
28*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate /*
31*7c478bd9Sstevel@tonic-gate  * Portions of this source code were derived from Berkeley 4.3 BSD
32*7c478bd9Sstevel@tonic-gate  * under license from the Regents of the University of California.
33*7c478bd9Sstevel@tonic-gate  */
34*7c478bd9Sstevel@tonic-gate 
35*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
36*7c478bd9Sstevel@tonic-gate 
37*7c478bd9Sstevel@tonic-gate #include "mt.h"
38*7c478bd9Sstevel@tonic-gate #include "../rpc/rpc_mt.h"		/* for MT declarations only */
39*7c478bd9Sstevel@tonic-gate #include <rpc/types.h>
40*7c478bd9Sstevel@tonic-gate #include <stdio.h>
41*7c478bd9Sstevel@tonic-gate #include <string.h>
42*7c478bd9Sstevel@tonic-gate #include <ctype.h>
43*7c478bd9Sstevel@tonic-gate #include <rpc/trace.h>
44*7c478bd9Sstevel@tonic-gate #include <netconfig.h>
45*7c478bd9Sstevel@tonic-gate #include <malloc.h>
46*7c478bd9Sstevel@tonic-gate #include <syslog.h>
47*7c478bd9Sstevel@tonic-gate #include "netcspace.h"
48*7c478bd9Sstevel@tonic-gate #include "nsl_stdio_prv.h"
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate #define	FAILURE  (unsigned)(-1)
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate /*
53*7c478bd9Sstevel@tonic-gate  *	Local routines used by the library procedures
54*7c478bd9Sstevel@tonic-gate  */
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate static int blank();
57*7c478bd9Sstevel@tonic-gate static int comment();
58*7c478bd9Sstevel@tonic-gate static struct netconfig *fgetnetconfig();
59*7c478bd9Sstevel@tonic-gate static void netconfig_free();
60*7c478bd9Sstevel@tonic-gate static unsigned int getflag();
61*7c478bd9Sstevel@tonic-gate static char **getlookups();
62*7c478bd9Sstevel@tonic-gate static struct netconfig **getnetlist();
63*7c478bd9Sstevel@tonic-gate static unsigned int getnlookups();
64*7c478bd9Sstevel@tonic-gate static char *gettoken();
65*7c478bd9Sstevel@tonic-gate static unsigned int getvalue();
66*7c478bd9Sstevel@tonic-gate static void shift1left();
67*7c478bd9Sstevel@tonic-gate static void netlist_free();
68*7c478bd9Sstevel@tonic-gate static void free_entry();
69*7c478bd9Sstevel@tonic-gate static struct netconfig *netconfig_dup();
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate /*
72*7c478bd9Sstevel@tonic-gate  *	System V routines used by the library procedures.
73*7c478bd9Sstevel@tonic-gate  */
74*7c478bd9Sstevel@tonic-gate extern char *getenv();
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate /* messaging stuff. */
77*7c478bd9Sstevel@tonic-gate 
78*7c478bd9Sstevel@tonic-gate extern const char __nsl_dom[];
79*7c478bd9Sstevel@tonic-gate extern char *dgettext(const char *, const char *);
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate /*
82*7c478bd9Sstevel@tonic-gate  *	Static global variables used by the library procedures:
83*7c478bd9Sstevel@tonic-gate  *
84*7c478bd9Sstevel@tonic-gate  *	netpp - points to the beginning of the list of netconfig
85*7c478bd9Sstevel@tonic-gate  *		entries used by setnetconfig() and setnetpath().
86*7c478bd9Sstevel@tonic-gate  *		Once netpp is initialized, that memory is *never*
87*7c478bd9Sstevel@tonic-gate  *		released.  This was necessary to improve performance.
88*7c478bd9Sstevel@tonic-gate  *
89*7c478bd9Sstevel@tonic-gate  *	linenum - the current line number of the /etc/netconfig
90*7c478bd9Sstevel@tonic-gate  *		  file (used for debugging and for nc_perror()).
91*7c478bd9Sstevel@tonic-gate  *
92*7c478bd9Sstevel@tonic-gate  *	fieldnum - the current field number of the current line
93*7c478bd9Sstevel@tonic-gate  *		   of /etc/netconfig (used for debugging and for
94*7c478bd9Sstevel@tonic-gate  *		   nc_perror()).
95*7c478bd9Sstevel@tonic-gate  *
96*7c478bd9Sstevel@tonic-gate  *	nc_error - the error condition encountered.
97*7c478bd9Sstevel@tonic-gate  */
98*7c478bd9Sstevel@tonic-gate 
99*7c478bd9Sstevel@tonic-gate static struct netconfig **netpp = NULL;
100*7c478bd9Sstevel@tonic-gate mutex_t netpp_mutex = DEFAULTMUTEX;
101*7c478bd9Sstevel@tonic-gate /*
102*7c478bd9Sstevel@tonic-gate  * The following two variables are used by the /etc/netconfig parsing
103*7c478bd9Sstevel@tonic-gate  * routines, which will always be executed once, and within the netpp_mutex.
104*7c478bd9Sstevel@tonic-gate  * They are global to allow the nc_sperror routine to provide better
105*7c478bd9Sstevel@tonic-gate  * information to the user about /etc/netconfig file problems.
106*7c478bd9Sstevel@tonic-gate  */
107*7c478bd9Sstevel@tonic-gate static int linenum = 0;			/* "owned" by getnetlist() */
108*7c478bd9Sstevel@tonic-gate static int fieldnum = 0;		/* "owned" by fgetnetconfig() */
109*7c478bd9Sstevel@tonic-gate 
110*7c478bd9Sstevel@tonic-gate 
111*7c478bd9Sstevel@tonic-gate static int *
112*7c478bd9Sstevel@tonic-gate __nc_error()
113*7c478bd9Sstevel@tonic-gate {
114*7c478bd9Sstevel@tonic-gate 	static pthread_key_t nc_error_key = 0;
115*7c478bd9Sstevel@tonic-gate 	static int nc_error = NC_NOERROR;
116*7c478bd9Sstevel@tonic-gate 	int *ret;
117*7c478bd9Sstevel@tonic-gate 
118*7c478bd9Sstevel@tonic-gate 	if (thr_main())
119*7c478bd9Sstevel@tonic-gate 		return (&nc_error);
120*7c478bd9Sstevel@tonic-gate 	ret = thr_get_storage(&nc_error_key, sizeof (int), free);
121*7c478bd9Sstevel@tonic-gate 	/* if thr_get_storage fails we return the address of nc_error */
122*7c478bd9Sstevel@tonic-gate 	return (ret ? ret : &nc_error);
123*7c478bd9Sstevel@tonic-gate }
124*7c478bd9Sstevel@tonic-gate #define	nc_error	(*(__nc_error()))
125*7c478bd9Sstevel@tonic-gate 
126*7c478bd9Sstevel@tonic-gate /*
127*7c478bd9Sstevel@tonic-gate  *	setnetconfig() has the effect of "initializing" the
128*7c478bd9Sstevel@tonic-gate  *	network configuration database.   It reads in the
129*7c478bd9Sstevel@tonic-gate  *	netcf entries (if not already read in).
130*7c478bd9Sstevel@tonic-gate  */
131*7c478bd9Sstevel@tonic-gate 
132*7c478bd9Sstevel@tonic-gate void *
133*7c478bd9Sstevel@tonic-gate setnetconfig()
134*7c478bd9Sstevel@tonic-gate {
135*7c478bd9Sstevel@tonic-gate 	NCONF_HANDLE *retp;
136*7c478bd9Sstevel@tonic-gate 
137*7c478bd9Sstevel@tonic-gate 	trace1(TR_setnetconfig, 0);
138*7c478bd9Sstevel@tonic-gate 	mutex_lock(&netpp_mutex);
139*7c478bd9Sstevel@tonic-gate 	if ((netpp == NULL) && ((netpp = getnetlist()) == NULL)) {
140*7c478bd9Sstevel@tonic-gate 		mutex_unlock(&netpp_mutex);
141*7c478bd9Sstevel@tonic-gate 		trace1(TR_setnetconfig, 1);
142*7c478bd9Sstevel@tonic-gate 		return (NULL);
143*7c478bd9Sstevel@tonic-gate 	}
144*7c478bd9Sstevel@tonic-gate 	mutex_unlock(&netpp_mutex);
145*7c478bd9Sstevel@tonic-gate 	if ((retp = (NCONF_HANDLE *) malloc(sizeof (NCONF_HANDLE))) == NULL) {
146*7c478bd9Sstevel@tonic-gate 		nc_error = NC_NOMEM;
147*7c478bd9Sstevel@tonic-gate 		trace1(TR_setnetconfig, 1);
148*7c478bd9Sstevel@tonic-gate 		return (NULL);
149*7c478bd9Sstevel@tonic-gate 	}
150*7c478bd9Sstevel@tonic-gate 	nc_error = NC_NOERROR;
151*7c478bd9Sstevel@tonic-gate 	retp->nc_head = retp->nc_curr = netpp;
152*7c478bd9Sstevel@tonic-gate 	trace1(TR_setnetconfig, 1);
153*7c478bd9Sstevel@tonic-gate 	return ((void *)retp);
154*7c478bd9Sstevel@tonic-gate }
155*7c478bd9Sstevel@tonic-gate 
156*7c478bd9Sstevel@tonic-gate /*
157*7c478bd9Sstevel@tonic-gate  *	endnetconfig() frees up all data allocated by setnetconfig()
158*7c478bd9Sstevel@tonic-gate  */
159*7c478bd9Sstevel@tonic-gate 
160*7c478bd9Sstevel@tonic-gate int
161*7c478bd9Sstevel@tonic-gate endnetconfig(vdata)
162*7c478bd9Sstevel@tonic-gate void  *vdata;
163*7c478bd9Sstevel@tonic-gate {
164*7c478bd9Sstevel@tonic-gate 	NCONF_HANDLE *nconf_handlep = (NCONF_HANDLE *)vdata;
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate 	trace1(TR_endnetconfig, 0);
167*7c478bd9Sstevel@tonic-gate 	mutex_lock(&netpp_mutex);
168*7c478bd9Sstevel@tonic-gate 	if (netpp == NULL || nconf_handlep == NULL) {
169*7c478bd9Sstevel@tonic-gate 		nc_error = NC_NOSET;
170*7c478bd9Sstevel@tonic-gate 		mutex_unlock(&netpp_mutex);
171*7c478bd9Sstevel@tonic-gate 		trace1(TR_endnetconfig, 1);
172*7c478bd9Sstevel@tonic-gate 		return (-1);
173*7c478bd9Sstevel@tonic-gate 	}
174*7c478bd9Sstevel@tonic-gate 	mutex_unlock(&netpp_mutex);
175*7c478bd9Sstevel@tonic-gate 
176*7c478bd9Sstevel@tonic-gate 	nc_error = NC_NOERROR;
177*7c478bd9Sstevel@tonic-gate 	free((void *)nconf_handlep);
178*7c478bd9Sstevel@tonic-gate 	trace1(TR_endnetconfig, 1);
179*7c478bd9Sstevel@tonic-gate 	return (0);
180*7c478bd9Sstevel@tonic-gate }
181*7c478bd9Sstevel@tonic-gate 
182*7c478bd9Sstevel@tonic-gate /*
183*7c478bd9Sstevel@tonic-gate  *	getnetconfig() returns the current entry in the list
184*7c478bd9Sstevel@tonic-gate  *	of netconfig structures.  It uses the nconf_handlep argument
185*7c478bd9Sstevel@tonic-gate  *	to determine the current entry. If setnetconfig() was not
186*7c478bd9Sstevel@tonic-gate  *	called previously to set up the list, return failure.
187*7c478bd9Sstevel@tonic-gate  *      It also check if ipv6 interface is present(ipv6_present) and
188*7c478bd9Sstevel@tonic-gate  *	skips udp6 & tcp6 entries if ipv6 is not supported.
189*7c478bd9Sstevel@tonic-gate  */
190*7c478bd9Sstevel@tonic-gate 
191*7c478bd9Sstevel@tonic-gate struct netconfig *
192*7c478bd9Sstevel@tonic-gate getnetconfig(vdata)
193*7c478bd9Sstevel@tonic-gate void *vdata;
194*7c478bd9Sstevel@tonic-gate {
195*7c478bd9Sstevel@tonic-gate 	NCONF_HANDLE *nconf_handlep = (NCONF_HANDLE *)vdata;
196*7c478bd9Sstevel@tonic-gate 	struct netconfig *retp;  /* holds the return value */
197*7c478bd9Sstevel@tonic-gate 	int ipv6_present = -1;
198*7c478bd9Sstevel@tonic-gate 
199*7c478bd9Sstevel@tonic-gate 	trace1(TR_getnetconfig, 0);
200*7c478bd9Sstevel@tonic-gate 	mutex_lock(&netpp_mutex);
201*7c478bd9Sstevel@tonic-gate 	if ((netpp == NULL) || (nconf_handlep == NULL)) {
202*7c478bd9Sstevel@tonic-gate 		nc_error = NC_NOSET;
203*7c478bd9Sstevel@tonic-gate 		mutex_unlock(&netpp_mutex);
204*7c478bd9Sstevel@tonic-gate 		trace1(TR_getnetconfig, 1);
205*7c478bd9Sstevel@tonic-gate 		return (NULL);
206*7c478bd9Sstevel@tonic-gate 	}
207*7c478bd9Sstevel@tonic-gate 	mutex_unlock(&netpp_mutex);
208*7c478bd9Sstevel@tonic-gate 	for (;;) {
209*7c478bd9Sstevel@tonic-gate 		retp = *(nconf_handlep->nc_curr);
210*7c478bd9Sstevel@tonic-gate 		if (retp && (strcmp(retp->nc_netid, "udp6") == 0 ||
211*7c478bd9Sstevel@tonic-gate 		    strcmp(retp->nc_netid, "tcp6") == 0)) {
212*7c478bd9Sstevel@tonic-gate 			if (ipv6_present == -1)
213*7c478bd9Sstevel@tonic-gate 				ipv6_present = __can_use_af(AF_INET6);
214*7c478bd9Sstevel@tonic-gate 			if (!ipv6_present) {
215*7c478bd9Sstevel@tonic-gate 				++(nconf_handlep->nc_curr);
216*7c478bd9Sstevel@tonic-gate 				continue;
217*7c478bd9Sstevel@tonic-gate 			}
218*7c478bd9Sstevel@tonic-gate 		}
219*7c478bd9Sstevel@tonic-gate 		break;
220*7c478bd9Sstevel@tonic-gate 	}
221*7c478bd9Sstevel@tonic-gate 	if (retp != NULL) {
222*7c478bd9Sstevel@tonic-gate 		++(nconf_handlep->nc_curr);
223*7c478bd9Sstevel@tonic-gate 		nc_error = NC_NOERROR;
224*7c478bd9Sstevel@tonic-gate 	} else {
225*7c478bd9Sstevel@tonic-gate 		nc_error = NC_NOMOREENTRIES;
226*7c478bd9Sstevel@tonic-gate 	}
227*7c478bd9Sstevel@tonic-gate 	trace1(TR_getnetconfig, 1);
228*7c478bd9Sstevel@tonic-gate 	return (retp);
229*7c478bd9Sstevel@tonic-gate }
230*7c478bd9Sstevel@tonic-gate 
231*7c478bd9Sstevel@tonic-gate /*
232*7c478bd9Sstevel@tonic-gate  *	getnetconfig() searches the netconfig database for a
233*7c478bd9Sstevel@tonic-gate  *	given network id.  Returns a pointer to the netconfig
234*7c478bd9Sstevel@tonic-gate  *	structure or a NULL if not found.
235*7c478bd9Sstevel@tonic-gate  *      It also check if ipv6 interface is present(ipv6_present) and
236*7c478bd9Sstevel@tonic-gate  *	skips udp6 & tcp6 entries if ipv6 is not supported.
237*7c478bd9Sstevel@tonic-gate  */
238*7c478bd9Sstevel@tonic-gate 
239*7c478bd9Sstevel@tonic-gate struct netconfig *
240*7c478bd9Sstevel@tonic-gate getnetconfigent(netid)
241*7c478bd9Sstevel@tonic-gate const char *netid;
242*7c478bd9Sstevel@tonic-gate {
243*7c478bd9Sstevel@tonic-gate 	struct netconfig **tpp;
244*7c478bd9Sstevel@tonic-gate 	int ipv6_present;
245*7c478bd9Sstevel@tonic-gate 
246*7c478bd9Sstevel@tonic-gate 	trace1(TR_getnetconfigent, 0);
247*7c478bd9Sstevel@tonic-gate 	mutex_lock(&netpp_mutex);
248*7c478bd9Sstevel@tonic-gate 	if ((netpp == NULL) && ((netpp = getnetlist()) == NULL)) {
249*7c478bd9Sstevel@tonic-gate 		mutex_unlock(&netpp_mutex);
250*7c478bd9Sstevel@tonic-gate 		trace1(TR_getnetconfigent, 1);
251*7c478bd9Sstevel@tonic-gate 		return (NULL);
252*7c478bd9Sstevel@tonic-gate 	}
253*7c478bd9Sstevel@tonic-gate 	mutex_unlock(&netpp_mutex);
254*7c478bd9Sstevel@tonic-gate 	for (tpp = netpp; *tpp; tpp++) {
255*7c478bd9Sstevel@tonic-gate 		if (strcmp((*tpp)->nc_netid, netid) == 0) {
256*7c478bd9Sstevel@tonic-gate 			if (*tpp && (strcmp((*tpp)->nc_netid, "udp6") == 0 ||
257*7c478bd9Sstevel@tonic-gate 			    strcmp((*tpp)->nc_netid, "tcp6") == 0)) {
258*7c478bd9Sstevel@tonic-gate 				ipv6_present = __can_use_af(AF_INET6);
259*7c478bd9Sstevel@tonic-gate 				if (!ipv6_present) {
260*7c478bd9Sstevel@tonic-gate 					nc_error = NC_NOTFOUND;
261*7c478bd9Sstevel@tonic-gate 					trace1(TR_getnetconfigent, 1);
262*7c478bd9Sstevel@tonic-gate 					return (NULL);
263*7c478bd9Sstevel@tonic-gate 				}
264*7c478bd9Sstevel@tonic-gate 			}
265*7c478bd9Sstevel@tonic-gate 			trace1(TR_getnetconfigent, 1);
266*7c478bd9Sstevel@tonic-gate 			return (netconfig_dup(*tpp));
267*7c478bd9Sstevel@tonic-gate 		}
268*7c478bd9Sstevel@tonic-gate 	}
269*7c478bd9Sstevel@tonic-gate 	nc_error = NC_NOTFOUND;
270*7c478bd9Sstevel@tonic-gate 	trace1(TR_getnetconfigent, 1);
271*7c478bd9Sstevel@tonic-gate 	return (NULL);
272*7c478bd9Sstevel@tonic-gate }
273*7c478bd9Sstevel@tonic-gate 
274*7c478bd9Sstevel@tonic-gate /*
275*7c478bd9Sstevel@tonic-gate  *	freenetconfigent frees the data allocated by getnetconfigent()
276*7c478bd9Sstevel@tonic-gate  */
277*7c478bd9Sstevel@tonic-gate 
278*7c478bd9Sstevel@tonic-gate void
279*7c478bd9Sstevel@tonic-gate freenetconfigent(netp)
280*7c478bd9Sstevel@tonic-gate struct netconfig *netp;
281*7c478bd9Sstevel@tonic-gate {
282*7c478bd9Sstevel@tonic-gate 	trace1(TR_freenetconfigent, 0);
283*7c478bd9Sstevel@tonic-gate 	netconfig_free(netp);
284*7c478bd9Sstevel@tonic-gate 	trace1(TR_freenetconfigent, 1);
285*7c478bd9Sstevel@tonic-gate }
286*7c478bd9Sstevel@tonic-gate 
287*7c478bd9Sstevel@tonic-gate /*
288*7c478bd9Sstevel@tonic-gate  *	getnetlist() reads the netconfig file and creates a
289*7c478bd9Sstevel@tonic-gate  *	NULL-terminated list of entries.
290*7c478bd9Sstevel@tonic-gate  *	Returns the pointer to the head of the list or a NULL
291*7c478bd9Sstevel@tonic-gate  *	on failure.
292*7c478bd9Sstevel@tonic-gate  */
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate static struct netconfig **
295*7c478bd9Sstevel@tonic-gate getnetlist()
296*7c478bd9Sstevel@tonic-gate {
297*7c478bd9Sstevel@tonic-gate 	char line[BUFSIZ];	/* holds each line of NETCONFIG */
298*7c478bd9Sstevel@tonic-gate 	__NSL_FILE *fp;		/* file stream for NETCONFIG */
299*7c478bd9Sstevel@tonic-gate 	struct netconfig **listpp; /* the beginning of the netconfig list */
300*7c478bd9Sstevel@tonic-gate 	struct netconfig **tpp;	/* used to traverse the netconfig list */
301*7c478bd9Sstevel@tonic-gate 	int count;		/* the number of entries in file */
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate 	trace1(TR_getnetlist, 0);
304*7c478bd9Sstevel@tonic-gate 	if ((fp = __nsl_fopen(NETCONFIG, "r")) == NULL) {
305*7c478bd9Sstevel@tonic-gate 		nc_error = NC_OPENFAIL;
306*7c478bd9Sstevel@tonic-gate 		trace1(TR_getnetlist, 1);
307*7c478bd9Sstevel@tonic-gate 		return (NULL);
308*7c478bd9Sstevel@tonic-gate 	}
309*7c478bd9Sstevel@tonic-gate 
310*7c478bd9Sstevel@tonic-gate 	count = 0;
311*7c478bd9Sstevel@tonic-gate 	while (__nsl_fgets(line, BUFSIZ, fp)) {
312*7c478bd9Sstevel@tonic-gate 		if (!(blank(line) || comment(line))) {
313*7c478bd9Sstevel@tonic-gate 			++count;
314*7c478bd9Sstevel@tonic-gate 		}
315*7c478bd9Sstevel@tonic-gate 	}
316*7c478bd9Sstevel@tonic-gate 	__nsl_rewind(fp);
317*7c478bd9Sstevel@tonic-gate 
318*7c478bd9Sstevel@tonic-gate 	if (count == 0) {
319*7c478bd9Sstevel@tonic-gate 		nc_error = NC_NOTFOUND;
320*7c478bd9Sstevel@tonic-gate 		(void) __nsl_fclose(fp);
321*7c478bd9Sstevel@tonic-gate 		trace1(TR_getnetlist, 1);
322*7c478bd9Sstevel@tonic-gate 		return (NULL);
323*7c478bd9Sstevel@tonic-gate 	}
324*7c478bd9Sstevel@tonic-gate 	if ((listpp = (struct netconfig **)malloc((count + 1) *
325*7c478bd9Sstevel@tonic-gate 	    sizeof (struct netconfig *))) == NULL) {
326*7c478bd9Sstevel@tonic-gate 		nc_error = NC_NOMEM;
327*7c478bd9Sstevel@tonic-gate 		(void) __nsl_fclose(fp);
328*7c478bd9Sstevel@tonic-gate 		trace1(TR_getnetlist, 1);
329*7c478bd9Sstevel@tonic-gate 		return (NULL);
330*7c478bd9Sstevel@tonic-gate 	}
331*7c478bd9Sstevel@tonic-gate 
332*7c478bd9Sstevel@tonic-gate 	/*
333*7c478bd9Sstevel@tonic-gate 	 *	The following loop fills in the list (loops until
334*7c478bd9Sstevel@tonic-gate 	 *	fgetnetconfig() returns a NULL) and counts the
335*7c478bd9Sstevel@tonic-gate 	 *	number of entries placed in the list.  Note that
336*7c478bd9Sstevel@tonic-gate 	 *	when the loop is completed, the last entry in the
337*7c478bd9Sstevel@tonic-gate 	 *	list will contain a NULL (signifying the end of
338*7c478bd9Sstevel@tonic-gate 	 *	the list).
339*7c478bd9Sstevel@tonic-gate 	 */
340*7c478bd9Sstevel@tonic-gate 	linenum = 0;
341*7c478bd9Sstevel@tonic-gate 	for (tpp = listpp; *tpp = fgetnetconfig(fp, NULL); tpp++)
342*7c478bd9Sstevel@tonic-gate 		;
343*7c478bd9Sstevel@tonic-gate 	(void) __nsl_fclose(fp);
344*7c478bd9Sstevel@tonic-gate 
345*7c478bd9Sstevel@tonic-gate 	if (nc_error != NC_NOMOREENTRIES) /* Something is screwed up */
346*7c478bd9Sstevel@tonic-gate 		netlist_free(&listpp);
347*7c478bd9Sstevel@tonic-gate 	trace1(TR_getnetlist, 1);
348*7c478bd9Sstevel@tonic-gate 	return (listpp);
349*7c478bd9Sstevel@tonic-gate }
350*7c478bd9Sstevel@tonic-gate 
351*7c478bd9Sstevel@tonic-gate /*
352*7c478bd9Sstevel@tonic-gate  *	fgetnetconfig() parses a line of the netconfig file into
353*7c478bd9Sstevel@tonic-gate  *	a netconfig structure.  It returns a pointer to the
354*7c478bd9Sstevel@tonic-gate  *	structure of success and a NULL on failure or EOF.
355*7c478bd9Sstevel@tonic-gate  */
356*7c478bd9Sstevel@tonic-gate 
357*7c478bd9Sstevel@tonic-gate static struct netconfig *
358*7c478bd9Sstevel@tonic-gate fgetnetconfig(fp, netid)
359*7c478bd9Sstevel@tonic-gate __NSL_FILE *fp;
360*7c478bd9Sstevel@tonic-gate char *netid;
361*7c478bd9Sstevel@tonic-gate {
362*7c478bd9Sstevel@tonic-gate 	char linep[BUFSIZ];	/* pointer to a line in the file */
363*7c478bd9Sstevel@tonic-gate 	struct netconfig *netconfigp; /* holds the new netconfig structure */
364*7c478bd9Sstevel@tonic-gate 	char  *tok1, *tok2, *tok3; /* holds a token from the line */
365*7c478bd9Sstevel@tonic-gate 	char  *retvalp;		/* the return value of fgets() */
366*7c478bd9Sstevel@tonic-gate 	char *entnetid;		/* netid for the current entry */
367*7c478bd9Sstevel@tonic-gate 
368*7c478bd9Sstevel@tonic-gate 	trace1(TR_fgetnetconfig, 0);
369*7c478bd9Sstevel@tonic-gate 	/* skip past blank lines and comments. */
370*7c478bd9Sstevel@tonic-gate 	while (retvalp = __nsl_fgets(linep, BUFSIZ, fp)) {
371*7c478bd9Sstevel@tonic-gate 		linenum++;
372*7c478bd9Sstevel@tonic-gate 		if (!(blank(linep) || comment(linep))) {
373*7c478bd9Sstevel@tonic-gate 			break;
374*7c478bd9Sstevel@tonic-gate 		}
375*7c478bd9Sstevel@tonic-gate 		retvalp = NULL;
376*7c478bd9Sstevel@tonic-gate 	}
377*7c478bd9Sstevel@tonic-gate 	if (retvalp == NULL) {
378*7c478bd9Sstevel@tonic-gate 		nc_error = NC_NOMOREENTRIES;
379*7c478bd9Sstevel@tonic-gate 		trace1(TR_fgetnetconfig, 1);
380*7c478bd9Sstevel@tonic-gate 		return (NULL);
381*7c478bd9Sstevel@tonic-gate 	}
382*7c478bd9Sstevel@tonic-gate 	fieldnum = 0;
383*7c478bd9Sstevel@tonic-gate 	if ((entnetid = gettoken(linep, FALSE)) == NULL) {
384*7c478bd9Sstevel@tonic-gate 		nc_error = NC_BADLINE;
385*7c478bd9Sstevel@tonic-gate 		trace1(TR_fgetnetconfig, 1);
386*7c478bd9Sstevel@tonic-gate 		return (NULL);
387*7c478bd9Sstevel@tonic-gate 	}
388*7c478bd9Sstevel@tonic-gate 	if (netid && (strcmp(netid, entnetid) != 0)) {
389*7c478bd9Sstevel@tonic-gate 		free(entnetid);
390*7c478bd9Sstevel@tonic-gate 		nc_error = NC_NOTFOUND;
391*7c478bd9Sstevel@tonic-gate 		trace1(TR_fgetnetconfig, 1);
392*7c478bd9Sstevel@tonic-gate 		return (NULL);
393*7c478bd9Sstevel@tonic-gate 	}
394*7c478bd9Sstevel@tonic-gate 	if ((netconfigp = (struct netconfig *)
395*7c478bd9Sstevel@tonic-gate 		calloc(1, sizeof (struct netconfig))) == NULL) {
396*7c478bd9Sstevel@tonic-gate 		free(entnetid);
397*7c478bd9Sstevel@tonic-gate 		nc_error = NC_NOMEM;
398*7c478bd9Sstevel@tonic-gate 		trace1(TR_fgetnetconfig, 1);
399*7c478bd9Sstevel@tonic-gate 		return (NULL);
400*7c478bd9Sstevel@tonic-gate 	}
401*7c478bd9Sstevel@tonic-gate 
402*7c478bd9Sstevel@tonic-gate 	tok1 = tok2 = tok3 = NULL;
403*7c478bd9Sstevel@tonic-gate 	netconfigp->nc_netid = entnetid;
404*7c478bd9Sstevel@tonic-gate 	if (((tok1 = gettoken(NULL, FALSE)) == NULL) ||
405*7c478bd9Sstevel@tonic-gate 	    ((netconfigp->nc_semantics =
406*7c478bd9Sstevel@tonic-gate 		getvalue(tok1, nc_semantics)) == FAILURE) ||
407*7c478bd9Sstevel@tonic-gate 	    ((tok2 = gettoken(NULL, FALSE)) == NULL) ||
408*7c478bd9Sstevel@tonic-gate 	    ((netconfigp->nc_flag = getflag(tok2)) == FAILURE) ||
409*7c478bd9Sstevel@tonic-gate 	    ((netconfigp->nc_protofmly = gettoken(NULL, FALSE)) == NULL) ||
410*7c478bd9Sstevel@tonic-gate 	    ((netconfigp->nc_proto = gettoken(NULL, FALSE)) == NULL) ||
411*7c478bd9Sstevel@tonic-gate 	    ((netconfigp->nc_device = gettoken(NULL, FALSE)) == NULL) ||
412*7c478bd9Sstevel@tonic-gate 	    ((tok3 = gettoken(NULL, TRUE)) == NULL) ||
413*7c478bd9Sstevel@tonic-gate 	    (((netconfigp->nc_nlookups = getnlookups(tok3)) != 0) &&
414*7c478bd9Sstevel@tonic-gate 		((netconfigp->nc_lookups = getlookups(tok3)) == NULL))) {
415*7c478bd9Sstevel@tonic-gate 		netconfig_free(netconfigp);
416*7c478bd9Sstevel@tonic-gate 		nc_error = NC_BADLINE;
417*7c478bd9Sstevel@tonic-gate 		netconfigp = NULL;
418*7c478bd9Sstevel@tonic-gate 	}
419*7c478bd9Sstevel@tonic-gate 	free(tok1);
420*7c478bd9Sstevel@tonic-gate 	free(tok2);
421*7c478bd9Sstevel@tonic-gate 	free(tok3);
422*7c478bd9Sstevel@tonic-gate 	trace1(TR_fgetnetconfig, 1);
423*7c478bd9Sstevel@tonic-gate 	return (netconfigp);
424*7c478bd9Sstevel@tonic-gate }
425*7c478bd9Sstevel@tonic-gate 
426*7c478bd9Sstevel@tonic-gate /*
427*7c478bd9Sstevel@tonic-gate  *	setnetpath() has the effect of "initializing" the
428*7c478bd9Sstevel@tonic-gate  *	NETPATH variable.  It reads in the netcf entries (if not
429*7c478bd9Sstevel@tonic-gate  *	already read in), creates a list corresponding to the entries
430*7c478bd9Sstevel@tonic-gate  *	in the NETPATH variable (or the "visible" entries og netconfig
431*7c478bd9Sstevel@tonic-gate  *	if NETPATH is not set).
432*7c478bd9Sstevel@tonic-gate  */
433*7c478bd9Sstevel@tonic-gate 
434*7c478bd9Sstevel@tonic-gate void *
435*7c478bd9Sstevel@tonic-gate setnetpath()
436*7c478bd9Sstevel@tonic-gate {
437*7c478bd9Sstevel@tonic-gate 	int count;		    /* the number of entries in NETPATH	    */
438*7c478bd9Sstevel@tonic-gate 	char valid_netpath[BUFSIZ]; /* holds the valid entries if NETPATH   */
439*7c478bd9Sstevel@tonic-gate 	char templine[BUFSIZ];	    /* has value of NETPATH when scanning   */
440*7c478bd9Sstevel@tonic-gate 	struct netconfig **curr_pp; /* scans the list from NETPATH	    */
441*7c478bd9Sstevel@tonic-gate 	struct netconfig **tpp;	    /* scans the list from netconfig file   */
442*7c478bd9Sstevel@tonic-gate 	struct netconfig **rnetpp;  /* the list of entries from NETPATH	    */
443*7c478bd9Sstevel@tonic-gate 	char *netpath;		    /* value of NETPATH from environment    */
444*7c478bd9Sstevel@tonic-gate 	char *netid;		    /* holds a component of NETPATH	    */
445*7c478bd9Sstevel@tonic-gate 	char *tp;		    /* used to scan NETPATH string	    */
446*7c478bd9Sstevel@tonic-gate 	NCONF_HANDLE *retp;	    /* the return value			    */
447*7c478bd9Sstevel@tonic-gate 
448*7c478bd9Sstevel@tonic-gate 	trace1(TR_setnetpath, 0);
449*7c478bd9Sstevel@tonic-gate 	/*
450*7c478bd9Sstevel@tonic-gate 	 *	Read in the netconfig database if not already read in
451*7c478bd9Sstevel@tonic-gate 	 */
452*7c478bd9Sstevel@tonic-gate 	mutex_lock(&netpp_mutex);
453*7c478bd9Sstevel@tonic-gate 	if ((netpp == NULL) && ((netpp = getnetlist()) == NULL)) {
454*7c478bd9Sstevel@tonic-gate 		mutex_unlock(&netpp_mutex);
455*7c478bd9Sstevel@tonic-gate 		trace1(TR_setnetpath, 1);
456*7c478bd9Sstevel@tonic-gate 		return (NULL);
457*7c478bd9Sstevel@tonic-gate 	}
458*7c478bd9Sstevel@tonic-gate 	mutex_unlock(&netpp_mutex);
459*7c478bd9Sstevel@tonic-gate 
460*7c478bd9Sstevel@tonic-gate 	if ((retp = (NCONF_HANDLE *) malloc(sizeof (NCONF_HANDLE))) == NULL) {
461*7c478bd9Sstevel@tonic-gate 		nc_error = NC_NOMEM;
462*7c478bd9Sstevel@tonic-gate 		trace1(TR_setnetpath, 1);
463*7c478bd9Sstevel@tonic-gate 		return (NULL);
464*7c478bd9Sstevel@tonic-gate 	}
465*7c478bd9Sstevel@tonic-gate 
466*7c478bd9Sstevel@tonic-gate 	/*
467*7c478bd9Sstevel@tonic-gate 	 *	Get the valid entries of the NETPATH variable (and
468*7c478bd9Sstevel@tonic-gate 	 *	count the number of entries while doing it).
469*7c478bd9Sstevel@tonic-gate 	 *
470*7c478bd9Sstevel@tonic-gate 	 *	This is done every time the procedure is called just
471*7c478bd9Sstevel@tonic-gate 	 *	in case NETPATH has changed from call to call.
472*7c478bd9Sstevel@tonic-gate 	 *
473*7c478bd9Sstevel@tonic-gate 	 * 	If NETPATH is too long, we ignore it altogether as
474*7c478bd9Sstevel@tonic-gate 	 *	it can only be a buffer overflow attack.
475*7c478bd9Sstevel@tonic-gate 	 *	Since we add one colon for each entry, but colons only
476*7c478bd9Sstevel@tonic-gate 	 *	need to exist between entries, we have to subtract one.
477*7c478bd9Sstevel@tonic-gate 	 */
478*7c478bd9Sstevel@tonic-gate 	count = 0;
479*7c478bd9Sstevel@tonic-gate 	valid_netpath[0] = '\0';
480*7c478bd9Sstevel@tonic-gate 	if ((netpath = getenv(NETPATH)) == NULL ||
481*7c478bd9Sstevel@tonic-gate 	    strlen(netpath) >= sizeof (templine) - 1) {
482*7c478bd9Sstevel@tonic-gate 		/*
483*7c478bd9Sstevel@tonic-gate 		 *	If NETPATH variable is not set or invalid,
484*7c478bd9Sstevel@tonic-gate 		 *	the valid NETPATH consist of all "visible"
485*7c478bd9Sstevel@tonic-gate 		 *	netids from the netconfig database.
486*7c478bd9Sstevel@tonic-gate 		 */
487*7c478bd9Sstevel@tonic-gate 
488*7c478bd9Sstevel@tonic-gate 		for (tpp = netpp; *tpp; tpp++) {
489*7c478bd9Sstevel@tonic-gate 			if ((*tpp)->nc_flag & NC_VISIBLE) {
490*7c478bd9Sstevel@tonic-gate 				(void) strcat(valid_netpath, (*tpp)->nc_netid);
491*7c478bd9Sstevel@tonic-gate 				(void) strcat(valid_netpath, ":");
492*7c478bd9Sstevel@tonic-gate 				count++;
493*7c478bd9Sstevel@tonic-gate 			}
494*7c478bd9Sstevel@tonic-gate 		}
495*7c478bd9Sstevel@tonic-gate 	} else {
496*7c478bd9Sstevel@tonic-gate 
497*7c478bd9Sstevel@tonic-gate 		/*
498*7c478bd9Sstevel@tonic-gate 		 *	Copy the value of NETPATH (since '\0's will be
499*7c478bd9Sstevel@tonic-gate 		 *	put into the string) and create the valid NETPATH
500*7c478bd9Sstevel@tonic-gate 		 *	(by throwing away all netids not in the database).
501*7c478bd9Sstevel@tonic-gate 		 *	If an entry appears more than one, it *will* be
502*7c478bd9Sstevel@tonic-gate 		 *	listed twice in the list of valid netpath entries.
503*7c478bd9Sstevel@tonic-gate 		 */
504*7c478bd9Sstevel@tonic-gate 
505*7c478bd9Sstevel@tonic-gate 		(void) strcpy(templine, netpath);
506*7c478bd9Sstevel@tonic-gate 		tp = templine;
507*7c478bd9Sstevel@tonic-gate 
508*7c478bd9Sstevel@tonic-gate 		while (*tp) {
509*7c478bd9Sstevel@tonic-gate 			/* Skip all leading ':'s */
510*7c478bd9Sstevel@tonic-gate 			while (*tp && *tp == ':')
511*7c478bd9Sstevel@tonic-gate 				tp++;
512*7c478bd9Sstevel@tonic-gate 			if (*tp == NULL)
513*7c478bd9Sstevel@tonic-gate 				break;  /* last one */
514*7c478bd9Sstevel@tonic-gate 			netid = tp;
515*7c478bd9Sstevel@tonic-gate 			while (*tp && *tp != ':')
516*7c478bd9Sstevel@tonic-gate 				tp++;
517*7c478bd9Sstevel@tonic-gate 			if (*tp)
518*7c478bd9Sstevel@tonic-gate 				*tp++ = '\0'; /* isolate netid */
519*7c478bd9Sstevel@tonic-gate 
520*7c478bd9Sstevel@tonic-gate 			for (tpp = netpp; *tpp; tpp++) {
521*7c478bd9Sstevel@tonic-gate 				if (strcmp(netid, (*tpp)->nc_netid) == 0) {
522*7c478bd9Sstevel@tonic-gate 					(void) strcat(valid_netpath,
523*7c478bd9Sstevel@tonic-gate 						(*tpp)->nc_netid);
524*7c478bd9Sstevel@tonic-gate 					(void) strcat(valid_netpath, ":");
525*7c478bd9Sstevel@tonic-gate 					count++;
526*7c478bd9Sstevel@tonic-gate 					break;
527*7c478bd9Sstevel@tonic-gate 				}
528*7c478bd9Sstevel@tonic-gate 			}
529*7c478bd9Sstevel@tonic-gate 		}
530*7c478bd9Sstevel@tonic-gate 	}
531*7c478bd9Sstevel@tonic-gate 
532*7c478bd9Sstevel@tonic-gate 	/* Get space to hold the valid list (+1 for the NULL) */
533*7c478bd9Sstevel@tonic-gate 
534*7c478bd9Sstevel@tonic-gate 	if ((rnetpp = (struct netconfig **)malloc((count + 1) *
535*7c478bd9Sstevel@tonic-gate 			sizeof (struct netconfig *))) == NULL) {
536*7c478bd9Sstevel@tonic-gate 		free((void *) retp);
537*7c478bd9Sstevel@tonic-gate 		nc_error = NC_NOMEM;
538*7c478bd9Sstevel@tonic-gate 		trace1(TR_setnetpath, 1);
539*7c478bd9Sstevel@tonic-gate 		return (NULL);
540*7c478bd9Sstevel@tonic-gate 	}
541*7c478bd9Sstevel@tonic-gate 
542*7c478bd9Sstevel@tonic-gate 	/*
543*7c478bd9Sstevel@tonic-gate 	 *	Populate the NETPATH list, ending it with a NULL.
544*7c478bd9Sstevel@tonic-gate 	 *	Each entry in the list points to the structure in the
545*7c478bd9Sstevel@tonic-gate 	 *	"netpp" list (the entry must exist in the list, otherwise
546*7c478bd9Sstevel@tonic-gate 	 *	it wouldn't appear in valid_netpath[]).
547*7c478bd9Sstevel@tonic-gate 	 */
548*7c478bd9Sstevel@tonic-gate 
549*7c478bd9Sstevel@tonic-gate 	curr_pp = rnetpp;
550*7c478bd9Sstevel@tonic-gate 	netid = tp = valid_netpath;
551*7c478bd9Sstevel@tonic-gate 	while (*tp) {
552*7c478bd9Sstevel@tonic-gate 		netid = tp;
553*7c478bd9Sstevel@tonic-gate 		while (*tp && *tp != ':')
554*7c478bd9Sstevel@tonic-gate 			tp++;
555*7c478bd9Sstevel@tonic-gate 		if (*tp)
556*7c478bd9Sstevel@tonic-gate 			*tp++ = '\0';
557*7c478bd9Sstevel@tonic-gate 		for (tpp = netpp; *tpp; tpp++) {
558*7c478bd9Sstevel@tonic-gate 			if (strcmp(netid, (*tpp)->nc_netid) == 0) {
559*7c478bd9Sstevel@tonic-gate 				*curr_pp++ = *tpp;
560*7c478bd9Sstevel@tonic-gate 				break;
561*7c478bd9Sstevel@tonic-gate 			}
562*7c478bd9Sstevel@tonic-gate 		}
563*7c478bd9Sstevel@tonic-gate 	}
564*7c478bd9Sstevel@tonic-gate 	*curr_pp = NULL;
565*7c478bd9Sstevel@tonic-gate 
566*7c478bd9Sstevel@tonic-gate 	retp->nc_curr = retp->nc_head = rnetpp;
567*7c478bd9Sstevel@tonic-gate 	trace1(TR_setnetpath, 1);
568*7c478bd9Sstevel@tonic-gate 	return ((void *)retp);
569*7c478bd9Sstevel@tonic-gate }
570*7c478bd9Sstevel@tonic-gate 
571*7c478bd9Sstevel@tonic-gate /*
572*7c478bd9Sstevel@tonic-gate  *	endnetpath() frees up all of the memory allocated by setnetpath().
573*7c478bd9Sstevel@tonic-gate  *	It returns -1 (error) if setnetpath was never called.
574*7c478bd9Sstevel@tonic-gate  */
575*7c478bd9Sstevel@tonic-gate 
576*7c478bd9Sstevel@tonic-gate int
577*7c478bd9Sstevel@tonic-gate endnetpath(vdata)
578*7c478bd9Sstevel@tonic-gate void *vdata;
579*7c478bd9Sstevel@tonic-gate {
580*7c478bd9Sstevel@tonic-gate 	/* The argument is really a NCONF_HANDLE;  cast it here */
581*7c478bd9Sstevel@tonic-gate 	NCONF_HANDLE *nconf_handlep = (NCONF_HANDLE *)vdata;
582*7c478bd9Sstevel@tonic-gate 
583*7c478bd9Sstevel@tonic-gate 	trace1(TR_endnetpath, 0);
584*7c478bd9Sstevel@tonic-gate 	mutex_lock(&netpp_mutex);
585*7c478bd9Sstevel@tonic-gate 	if (netpp == NULL || nconf_handlep == NULL) {
586*7c478bd9Sstevel@tonic-gate 		nc_error = NC_NOSET;
587*7c478bd9Sstevel@tonic-gate 		mutex_unlock(&netpp_mutex);
588*7c478bd9Sstevel@tonic-gate 		trace1(TR_endnetpath, 1);
589*7c478bd9Sstevel@tonic-gate 		return (-1);
590*7c478bd9Sstevel@tonic-gate 	}
591*7c478bd9Sstevel@tonic-gate 	mutex_unlock(&netpp_mutex);
592*7c478bd9Sstevel@tonic-gate 
593*7c478bd9Sstevel@tonic-gate 	free(nconf_handlep->nc_head);
594*7c478bd9Sstevel@tonic-gate 	free(nconf_handlep);
595*7c478bd9Sstevel@tonic-gate 	trace1(TR_endnetpath, 1);
596*7c478bd9Sstevel@tonic-gate 	return (0);
597*7c478bd9Sstevel@tonic-gate }
598*7c478bd9Sstevel@tonic-gate 
599*7c478bd9Sstevel@tonic-gate /*
600*7c478bd9Sstevel@tonic-gate  *	getnetpath() returns the current entry in the list
601*7c478bd9Sstevel@tonic-gate  *	from the NETPATH variable.  If setnetpath() was not called
602*7c478bd9Sstevel@tonic-gate  *	previously to set up the list, return NULL.
603*7c478bd9Sstevel@tonic-gate  */
604*7c478bd9Sstevel@tonic-gate 
605*7c478bd9Sstevel@tonic-gate struct netconfig *
606*7c478bd9Sstevel@tonic-gate getnetpath(vdata)
607*7c478bd9Sstevel@tonic-gate void *vdata;
608*7c478bd9Sstevel@tonic-gate {
609*7c478bd9Sstevel@tonic-gate 	/* The argument is really a NCONF_HANDLE;  cast it here */
610*7c478bd9Sstevel@tonic-gate 	NCONF_HANDLE *nconf_handlep = (NCONF_HANDLE *)vdata;
611*7c478bd9Sstevel@tonic-gate 	struct netconfig *retp;  /* holds the return value */
612*7c478bd9Sstevel@tonic-gate 	int ipv6_present = -1;
613*7c478bd9Sstevel@tonic-gate 
614*7c478bd9Sstevel@tonic-gate 	trace1(TR_getnetpath, 0);
615*7c478bd9Sstevel@tonic-gate 	mutex_lock(&netpp_mutex);
616*7c478bd9Sstevel@tonic-gate 	if (netpp == NULL) {
617*7c478bd9Sstevel@tonic-gate 		nc_error = NC_NOSET;
618*7c478bd9Sstevel@tonic-gate 		mutex_unlock(&netpp_mutex);
619*7c478bd9Sstevel@tonic-gate 		trace1(TR_getnetpath, 1);
620*7c478bd9Sstevel@tonic-gate 		return (NULL);
621*7c478bd9Sstevel@tonic-gate 	}
622*7c478bd9Sstevel@tonic-gate 	mutex_unlock(&netpp_mutex);
623*7c478bd9Sstevel@tonic-gate 	for (;;) {
624*7c478bd9Sstevel@tonic-gate 		retp = *(nconf_handlep->nc_curr);
625*7c478bd9Sstevel@tonic-gate 		if (retp && (strcmp(retp->nc_netid, "udp6") == 0 ||
626*7c478bd9Sstevel@tonic-gate 		    strcmp(retp->nc_netid, "tcp6") == 0)) {
627*7c478bd9Sstevel@tonic-gate 			if (ipv6_present == -1)
628*7c478bd9Sstevel@tonic-gate 				ipv6_present = __can_use_af(AF_INET6);
629*7c478bd9Sstevel@tonic-gate 			if (!ipv6_present) {
630*7c478bd9Sstevel@tonic-gate 				++(nconf_handlep->nc_curr);
631*7c478bd9Sstevel@tonic-gate 				continue;
632*7c478bd9Sstevel@tonic-gate 			}
633*7c478bd9Sstevel@tonic-gate 		}
634*7c478bd9Sstevel@tonic-gate 		break;
635*7c478bd9Sstevel@tonic-gate 	}
636*7c478bd9Sstevel@tonic-gate 	if (retp) {
637*7c478bd9Sstevel@tonic-gate 		++(nconf_handlep->nc_curr);
638*7c478bd9Sstevel@tonic-gate 		nc_error = NC_NOERROR;
639*7c478bd9Sstevel@tonic-gate 	} else {
640*7c478bd9Sstevel@tonic-gate 		nc_error = NC_NOMOREENTRIES;
641*7c478bd9Sstevel@tonic-gate 	}
642*7c478bd9Sstevel@tonic-gate 
643*7c478bd9Sstevel@tonic-gate 	trace1(TR_getnetpath, 1);
644*7c478bd9Sstevel@tonic-gate 	return (retp);
645*7c478bd9Sstevel@tonic-gate }
646*7c478bd9Sstevel@tonic-gate 
647*7c478bd9Sstevel@tonic-gate /*
648*7c478bd9Sstevel@tonic-gate  *	blank() returns true if the line is a blank line, 0 otherwise
649*7c478bd9Sstevel@tonic-gate  */
650*7c478bd9Sstevel@tonic-gate 
651*7c478bd9Sstevel@tonic-gate static int
652*7c478bd9Sstevel@tonic-gate blank(cp)
653*7c478bd9Sstevel@tonic-gate char *cp;
654*7c478bd9Sstevel@tonic-gate {
655*7c478bd9Sstevel@tonic-gate 	trace1(TR_blank, 0);
656*7c478bd9Sstevel@tonic-gate 	while (*cp && isspace(*cp)) {
657*7c478bd9Sstevel@tonic-gate 		cp++;
658*7c478bd9Sstevel@tonic-gate 	}
659*7c478bd9Sstevel@tonic-gate 	trace1(TR_blank, 1);
660*7c478bd9Sstevel@tonic-gate 	return (*cp == '\0');
661*7c478bd9Sstevel@tonic-gate }
662*7c478bd9Sstevel@tonic-gate 
663*7c478bd9Sstevel@tonic-gate /*
664*7c478bd9Sstevel@tonic-gate  *	comment() returns true if the line is a comment, 0 otherwise.
665*7c478bd9Sstevel@tonic-gate  */
666*7c478bd9Sstevel@tonic-gate 
667*7c478bd9Sstevel@tonic-gate static int
668*7c478bd9Sstevel@tonic-gate comment(cp)
669*7c478bd9Sstevel@tonic-gate char *cp;
670*7c478bd9Sstevel@tonic-gate {
671*7c478bd9Sstevel@tonic-gate 	trace1(TR_comment, 0);
672*7c478bd9Sstevel@tonic-gate 	while (*cp && isspace(*cp)) {
673*7c478bd9Sstevel@tonic-gate 		cp++;
674*7c478bd9Sstevel@tonic-gate 	}
675*7c478bd9Sstevel@tonic-gate 	trace1(TR_comment, 1);
676*7c478bd9Sstevel@tonic-gate 	return (*cp == '#');
677*7c478bd9Sstevel@tonic-gate }
678*7c478bd9Sstevel@tonic-gate 
679*7c478bd9Sstevel@tonic-gate /*
680*7c478bd9Sstevel@tonic-gate  *	getvalue() searches for the given string in the given array,
681*7c478bd9Sstevel@tonic-gate  *	and return the integer value associated with the string.
682*7c478bd9Sstevel@tonic-gate  */
683*7c478bd9Sstevel@tonic-gate 
684*7c478bd9Sstevel@tonic-gate static unsigned int
685*7c478bd9Sstevel@tonic-gate getvalue(cp, nc_data)
686*7c478bd9Sstevel@tonic-gate char *cp;
687*7c478bd9Sstevel@tonic-gate struct nc_data nc_data[];
688*7c478bd9Sstevel@tonic-gate {
689*7c478bd9Sstevel@tonic-gate 	int i;	/* used to index through the given struct nc_data array */
690*7c478bd9Sstevel@tonic-gate 
691*7c478bd9Sstevel@tonic-gate 	trace1(TR_getvalue, 0);
692*7c478bd9Sstevel@tonic-gate 	for (i = 0; nc_data[i].string; i++) {
693*7c478bd9Sstevel@tonic-gate 		if (strcmp(nc_data[i].string, cp) == 0) {
694*7c478bd9Sstevel@tonic-gate 			break;
695*7c478bd9Sstevel@tonic-gate 		}
696*7c478bd9Sstevel@tonic-gate 	}
697*7c478bd9Sstevel@tonic-gate 	trace1(TR_getvalue, 1);
698*7c478bd9Sstevel@tonic-gate 	return (nc_data[i].value);
699*7c478bd9Sstevel@tonic-gate }
700*7c478bd9Sstevel@tonic-gate 
701*7c478bd9Sstevel@tonic-gate /*
702*7c478bd9Sstevel@tonic-gate  *	getflag() creates a bitmap of the one-character flags in
703*7c478bd9Sstevel@tonic-gate  *	the given string.  It uses nc_flags array to get the values.
704*7c478bd9Sstevel@tonic-gate  */
705*7c478bd9Sstevel@tonic-gate 
706*7c478bd9Sstevel@tonic-gate static unsigned int
707*7c478bd9Sstevel@tonic-gate getflag(cp)
708*7c478bd9Sstevel@tonic-gate char *cp;
709*7c478bd9Sstevel@tonic-gate {
710*7c478bd9Sstevel@tonic-gate 	int i;			/* indexs through the nc_flag array */
711*7c478bd9Sstevel@tonic-gate 	unsigned int mask = 0; /* holds bitmask of flags */
712*7c478bd9Sstevel@tonic-gate 
713*7c478bd9Sstevel@tonic-gate 	trace1(TR_getflag, 0);
714*7c478bd9Sstevel@tonic-gate 	while (*cp) {
715*7c478bd9Sstevel@tonic-gate 		for (i = 0; nc_flag[i].string; i++) {
716*7c478bd9Sstevel@tonic-gate 			if (*nc_flag[i].string == *cp) {
717*7c478bd9Sstevel@tonic-gate 				mask |= nc_flag[i].value;
718*7c478bd9Sstevel@tonic-gate 				break;
719*7c478bd9Sstevel@tonic-gate 			}
720*7c478bd9Sstevel@tonic-gate 		}
721*7c478bd9Sstevel@tonic-gate 		cp++;
722*7c478bd9Sstevel@tonic-gate 	}
723*7c478bd9Sstevel@tonic-gate 	trace1(TR_getflag, 1);
724*7c478bd9Sstevel@tonic-gate 	return (mask);
725*7c478bd9Sstevel@tonic-gate }
726*7c478bd9Sstevel@tonic-gate 
727*7c478bd9Sstevel@tonic-gate /*
728*7c478bd9Sstevel@tonic-gate  *	getlookups() creates and returns an array of string representing
729*7c478bd9Sstevel@tonic-gate  *	the directory lookup libraries, given as a comma-seperated list
730*7c478bd9Sstevel@tonic-gate  *	in the argument "cp".
731*7c478bd9Sstevel@tonic-gate  */
732*7c478bd9Sstevel@tonic-gate 
733*7c478bd9Sstevel@tonic-gate static char **
734*7c478bd9Sstevel@tonic-gate getlookups(cp)
735*7c478bd9Sstevel@tonic-gate char *cp;
736*7c478bd9Sstevel@tonic-gate {
737*7c478bd9Sstevel@tonic-gate 	unsigned int num;	/* holds the number of entries in the list   */
738*7c478bd9Sstevel@tonic-gate 	char **listpp;		/* the beginning of the list of dir routines */
739*7c478bd9Sstevel@tonic-gate 	char **tpp;		/* traverses the list, populating it */
740*7c478bd9Sstevel@tonic-gate 	char *start;
741*7c478bd9Sstevel@tonic-gate 
742*7c478bd9Sstevel@tonic-gate 	trace1(TR_getlookups, 0);
743*7c478bd9Sstevel@tonic-gate 	num = getnlookups(cp);
744*7c478bd9Sstevel@tonic-gate 	if (num == 0) {
745*7c478bd9Sstevel@tonic-gate 		trace1(TR_getlookups, 1);
746*7c478bd9Sstevel@tonic-gate 		return (NULL);
747*7c478bd9Sstevel@tonic-gate 	}
748*7c478bd9Sstevel@tonic-gate 	if ((listpp = (char **)malloc((num + 1) * sizeof (char *))) == NULL) {
749*7c478bd9Sstevel@tonic-gate 		trace1(TR_getlookups, 1);
750*7c478bd9Sstevel@tonic-gate 		return (NULL);
751*7c478bd9Sstevel@tonic-gate 	}
752*7c478bd9Sstevel@tonic-gate 
753*7c478bd9Sstevel@tonic-gate 	tpp = listpp;
754*7c478bd9Sstevel@tonic-gate 	while (num--) {
755*7c478bd9Sstevel@tonic-gate 		start  = cp;
756*7c478bd9Sstevel@tonic-gate 
757*7c478bd9Sstevel@tonic-gate 		/*
758*7c478bd9Sstevel@tonic-gate 		 *	Traverse the string looking for the next entry
759*7c478bd9Sstevel@tonic-gate 		 *	of the list (i.e, where the ',' or end of the
760*7c478bd9Sstevel@tonic-gate 		 *	string appears).  If a "\" is found, shift the
761*7c478bd9Sstevel@tonic-gate 		 *	token over 1 to the left (taking the next char
762*7c478bd9Sstevel@tonic-gate 		 *	literally).
763*7c478bd9Sstevel@tonic-gate 		 */
764*7c478bd9Sstevel@tonic-gate 
765*7c478bd9Sstevel@tonic-gate 		while (*cp && *cp != ',') {
766*7c478bd9Sstevel@tonic-gate 			if (*cp == '\\' && *(cp + 1)) {
767*7c478bd9Sstevel@tonic-gate 				shift1left(cp);
768*7c478bd9Sstevel@tonic-gate 			}
769*7c478bd9Sstevel@tonic-gate 			cp++;
770*7c478bd9Sstevel@tonic-gate 		}
771*7c478bd9Sstevel@tonic-gate 		if (*cp)
772*7c478bd9Sstevel@tonic-gate 			*cp++ = '\0';
773*7c478bd9Sstevel@tonic-gate 		if ((*tpp++ = strdup(start)) == NULL) {
774*7c478bd9Sstevel@tonic-gate 			for (tpp = listpp; *tpp; tpp++)
775*7c478bd9Sstevel@tonic-gate 				free(*tpp);
776*7c478bd9Sstevel@tonic-gate 			free(listpp);
777*7c478bd9Sstevel@tonic-gate 			trace1(TR_getlookups, 1);
778*7c478bd9Sstevel@tonic-gate 			return (NULL);
779*7c478bd9Sstevel@tonic-gate 		}
780*7c478bd9Sstevel@tonic-gate 	}
781*7c478bd9Sstevel@tonic-gate 	*tpp = NULL;
782*7c478bd9Sstevel@tonic-gate 	trace1(TR_getlookups, 1);
783*7c478bd9Sstevel@tonic-gate 	return (listpp);
784*7c478bd9Sstevel@tonic-gate }
785*7c478bd9Sstevel@tonic-gate 
786*7c478bd9Sstevel@tonic-gate /*
787*7c478bd9Sstevel@tonic-gate  *	getnlookups() returns the number of entries in a comma-separated
788*7c478bd9Sstevel@tonic-gate  *	string of tokens.  A "-" means no strings are present.
789*7c478bd9Sstevel@tonic-gate  */
790*7c478bd9Sstevel@tonic-gate 
791*7c478bd9Sstevel@tonic-gate static unsigned int
792*7c478bd9Sstevel@tonic-gate getnlookups(cp)
793*7c478bd9Sstevel@tonic-gate char *cp;
794*7c478bd9Sstevel@tonic-gate {
795*7c478bd9Sstevel@tonic-gate 	unsigned int count;	/* the number of tokens in the string */
796*7c478bd9Sstevel@tonic-gate 
797*7c478bd9Sstevel@tonic-gate 	trace1(TR_getnlookups, 0);
798*7c478bd9Sstevel@tonic-gate 	if (strcmp(cp, "-") == 0) {
799*7c478bd9Sstevel@tonic-gate 		trace1(TR_getnlookups, 1);
800*7c478bd9Sstevel@tonic-gate 		return (0);
801*7c478bd9Sstevel@tonic-gate 	}
802*7c478bd9Sstevel@tonic-gate 
803*7c478bd9Sstevel@tonic-gate 	count = 1;
804*7c478bd9Sstevel@tonic-gate 	while (*cp) {
805*7c478bd9Sstevel@tonic-gate 		if (*cp == ',') {
806*7c478bd9Sstevel@tonic-gate 			count++;
807*7c478bd9Sstevel@tonic-gate 		}
808*7c478bd9Sstevel@tonic-gate 
809*7c478bd9Sstevel@tonic-gate 		/*
810*7c478bd9Sstevel@tonic-gate 		 *	If a "\" is in the string, take the next character
811*7c478bd9Sstevel@tonic-gate 		 *	literally.  Onlly skip the character if "\" is
812*7c478bd9Sstevel@tonic-gate 		 *	not the last character of the token.
813*7c478bd9Sstevel@tonic-gate 		 */
814*7c478bd9Sstevel@tonic-gate 		if (*cp == '\\' && *(cp + 1)) {
815*7c478bd9Sstevel@tonic-gate 			cp++;
816*7c478bd9Sstevel@tonic-gate 		}
817*7c478bd9Sstevel@tonic-gate 		cp++;
818*7c478bd9Sstevel@tonic-gate 	}
819*7c478bd9Sstevel@tonic-gate 	trace1(TR_getnlookups, 1);
820*7c478bd9Sstevel@tonic-gate 	return (count);
821*7c478bd9Sstevel@tonic-gate }
822*7c478bd9Sstevel@tonic-gate 
823*7c478bd9Sstevel@tonic-gate /*
824*7c478bd9Sstevel@tonic-gate  *	gettoken() behaves much like strtok(), except that
825*7c478bd9Sstevel@tonic-gate  *	it knows about escaped space characters (i.e., space characters
826*7c478bd9Sstevel@tonic-gate  *	preceeded by a '\' are taken literally).
827*7c478bd9Sstevel@tonic-gate  */
828*7c478bd9Sstevel@tonic-gate 
829*7c478bd9Sstevel@tonic-gate static char *
830*7c478bd9Sstevel@tonic-gate gettoken(cp, skip)
831*7c478bd9Sstevel@tonic-gate char	*cp;
832*7c478bd9Sstevel@tonic-gate int skip;
833*7c478bd9Sstevel@tonic-gate {
834*7c478bd9Sstevel@tonic-gate 	static char	*savep;	/* the place where we left off    */
835*7c478bd9Sstevel@tonic-gate 	char	*p;		/* the beginning of the new token */
836*7c478bd9Sstevel@tonic-gate 	char	*retp;		/* the token to be returned	  */
837*7c478bd9Sstevel@tonic-gate 
838*7c478bd9Sstevel@tonic-gate 	trace1(TR_gettoken, 0);
839*7c478bd9Sstevel@tonic-gate 	fieldnum++;
840*7c478bd9Sstevel@tonic-gate 
841*7c478bd9Sstevel@tonic-gate 	/* Determine if first or subsequent call  */
842*7c478bd9Sstevel@tonic-gate 	p = (cp == NULL)? savep: cp;
843*7c478bd9Sstevel@tonic-gate 
844*7c478bd9Sstevel@tonic-gate 	/* Return if no tokens remain.  */
845*7c478bd9Sstevel@tonic-gate 	if (p == 0) {
846*7c478bd9Sstevel@tonic-gate 		trace1(TR_gettoken, 1);
847*7c478bd9Sstevel@tonic-gate 		return (NULL);
848*7c478bd9Sstevel@tonic-gate 	}
849*7c478bd9Sstevel@tonic-gate 
850*7c478bd9Sstevel@tonic-gate 	while (isspace(*p))
851*7c478bd9Sstevel@tonic-gate 		p++;
852*7c478bd9Sstevel@tonic-gate 
853*7c478bd9Sstevel@tonic-gate 	if (*p == '\0') {
854*7c478bd9Sstevel@tonic-gate 		trace1(TR_gettoken, 1);
855*7c478bd9Sstevel@tonic-gate 		return (NULL);
856*7c478bd9Sstevel@tonic-gate 	}
857*7c478bd9Sstevel@tonic-gate 
858*7c478bd9Sstevel@tonic-gate 	/*
859*7c478bd9Sstevel@tonic-gate 	 *	Save the location of the token and then skip past it
860*7c478bd9Sstevel@tonic-gate 	 */
861*7c478bd9Sstevel@tonic-gate 
862*7c478bd9Sstevel@tonic-gate 	retp = p;
863*7c478bd9Sstevel@tonic-gate 	while (*p) {
864*7c478bd9Sstevel@tonic-gate 		if (isspace(*p))
865*7c478bd9Sstevel@tonic-gate 			if (skip == TRUE) {
866*7c478bd9Sstevel@tonic-gate 				shift1left(p);
867*7c478bd9Sstevel@tonic-gate 				continue;
868*7c478bd9Sstevel@tonic-gate 			} else
869*7c478bd9Sstevel@tonic-gate 				break;
870*7c478bd9Sstevel@tonic-gate 		/*
871*7c478bd9Sstevel@tonic-gate 		 *	Only process the escape of the space seperator;
872*7c478bd9Sstevel@tonic-gate 		 *	since the token may contain other separators,
873*7c478bd9Sstevel@tonic-gate 		 *	let the other routines handle the escape of
874*7c478bd9Sstevel@tonic-gate 		 *	specific characters in the token.
875*7c478bd9Sstevel@tonic-gate 		 */
876*7c478bd9Sstevel@tonic-gate 
877*7c478bd9Sstevel@tonic-gate 		if (*p == '\\' && *(p + 1) != '\n' && isspace(*(p + 1))) {
878*7c478bd9Sstevel@tonic-gate 			shift1left(p);
879*7c478bd9Sstevel@tonic-gate 		}
880*7c478bd9Sstevel@tonic-gate 		p++;
881*7c478bd9Sstevel@tonic-gate 	}
882*7c478bd9Sstevel@tonic-gate 	if (*p == '\0') {
883*7c478bd9Sstevel@tonic-gate 		savep = 0;	/* indicate this is last token */
884*7c478bd9Sstevel@tonic-gate 	} else {
885*7c478bd9Sstevel@tonic-gate 		*p = '\0';
886*7c478bd9Sstevel@tonic-gate 		savep = ++p;
887*7c478bd9Sstevel@tonic-gate 	}
888*7c478bd9Sstevel@tonic-gate 	trace1(TR_gettoken, 1);
889*7c478bd9Sstevel@tonic-gate 	return (strdup(retp));
890*7c478bd9Sstevel@tonic-gate }
891*7c478bd9Sstevel@tonic-gate 
892*7c478bd9Sstevel@tonic-gate /*
893*7c478bd9Sstevel@tonic-gate  *	shift1left() moves all characters in the string over 1 to
894*7c478bd9Sstevel@tonic-gate  *	the left.
895*7c478bd9Sstevel@tonic-gate  */
896*7c478bd9Sstevel@tonic-gate 
897*7c478bd9Sstevel@tonic-gate static void
898*7c478bd9Sstevel@tonic-gate shift1left(p)
899*7c478bd9Sstevel@tonic-gate char *p;
900*7c478bd9Sstevel@tonic-gate {
901*7c478bd9Sstevel@tonic-gate 	trace1(TR_shift1left, 0);
902*7c478bd9Sstevel@tonic-gate 	for (; *p; p++)
903*7c478bd9Sstevel@tonic-gate 		*p = *(p + 1);
904*7c478bd9Sstevel@tonic-gate 	trace1(TR_shift1left, 1);
905*7c478bd9Sstevel@tonic-gate }
906*7c478bd9Sstevel@tonic-gate 
907*7c478bd9Sstevel@tonic-gate char *
908*7c478bd9Sstevel@tonic-gate nc_sperror()
909*7c478bd9Sstevel@tonic-gate {
910*7c478bd9Sstevel@tonic-gate 	static char buf_main[BUFSIZ];
911*7c478bd9Sstevel@tonic-gate 	static pthread_key_t perror_key;
912*7c478bd9Sstevel@tonic-gate 	char *retstr = thr_main()?
913*7c478bd9Sstevel@tonic-gate 		buf_main :
914*7c478bd9Sstevel@tonic-gate 		thr_get_storage(&perror_key, BUFSIZ, free);
915*7c478bd9Sstevel@tonic-gate 
916*7c478bd9Sstevel@tonic-gate 	trace1(TR_nc_sperror, 0);
917*7c478bd9Sstevel@tonic-gate 
918*7c478bd9Sstevel@tonic-gate 	if (retstr == NULL) {
919*7c478bd9Sstevel@tonic-gate 		syslog(LOG_WARNING,
920*7c478bd9Sstevel@tonic-gate 		"nc_sperror: malloc failed when trying to create buffer\n");
921*7c478bd9Sstevel@tonic-gate 		return (NULL);
922*7c478bd9Sstevel@tonic-gate 	}
923*7c478bd9Sstevel@tonic-gate 
924*7c478bd9Sstevel@tonic-gate 	switch (nc_error) {
925*7c478bd9Sstevel@tonic-gate 	case NC_NOERROR:
926*7c478bd9Sstevel@tonic-gate 		(void) strlcpy(retstr, dgettext(__nsl_dom, "no error"), BUFSIZ);
927*7c478bd9Sstevel@tonic-gate 		break;
928*7c478bd9Sstevel@tonic-gate 	case NC_NOMEM:
929*7c478bd9Sstevel@tonic-gate 		(void) strlcpy(retstr, dgettext(__nsl_dom, "out of memory"),
930*7c478bd9Sstevel@tonic-gate 		    BUFSIZ);
931*7c478bd9Sstevel@tonic-gate 		break;
932*7c478bd9Sstevel@tonic-gate 	case NC_NOSET:
933*7c478bd9Sstevel@tonic-gate 		(void) strlcpy(retstr, dgettext(__nsl_dom,
934*7c478bd9Sstevel@tonic-gate 		    "routine called before calling \
935*7c478bd9Sstevel@tonic-gate 		    setnetpath() or setnetconfig()"), BUFSIZ);
936*7c478bd9Sstevel@tonic-gate 		break;
937*7c478bd9Sstevel@tonic-gate 	case NC_OPENFAIL:
938*7c478bd9Sstevel@tonic-gate 		(void) strlcpy(retstr,
939*7c478bd9Sstevel@tonic-gate 			dgettext(__nsl_dom, "cannot open /etc/netconfig"),
940*7c478bd9Sstevel@tonic-gate 			BUFSIZ);
941*7c478bd9Sstevel@tonic-gate 		break;
942*7c478bd9Sstevel@tonic-gate 	case NC_BADLINE:
943*7c478bd9Sstevel@tonic-gate 		(void) snprintf(retstr, BUFSIZ, dgettext(__nsl_dom,
944*7c478bd9Sstevel@tonic-gate 			"error in /etc/netconfig: field %d of line %d\n"),
945*7c478bd9Sstevel@tonic-gate 				fieldnum, linenum);
946*7c478bd9Sstevel@tonic-gate 		break;
947*7c478bd9Sstevel@tonic-gate 	case NC_NOTFOUND:
948*7c478bd9Sstevel@tonic-gate 		(void) snprintf(retstr, BUFSIZ,
949*7c478bd9Sstevel@tonic-gate 			dgettext(__nsl_dom,
950*7c478bd9Sstevel@tonic-gate 				"netid not found in /etc/netconfig"));
951*7c478bd9Sstevel@tonic-gate 		break;
952*7c478bd9Sstevel@tonic-gate 	case NC_NOMOREENTRIES:
953*7c478bd9Sstevel@tonic-gate 		(void) snprintf(retstr, BUFSIZ,
954*7c478bd9Sstevel@tonic-gate 			dgettext(__nsl_dom,
955*7c478bd9Sstevel@tonic-gate 				"no more entries in /etc/netconfig"));
956*7c478bd9Sstevel@tonic-gate 		break;
957*7c478bd9Sstevel@tonic-gate 	default:
958*7c478bd9Sstevel@tonic-gate 		(void) strlcpy(retstr, dgettext(__nsl_dom, "unknown error"),
959*7c478bd9Sstevel@tonic-gate 		    BUFSIZ);
960*7c478bd9Sstevel@tonic-gate 		break;
961*7c478bd9Sstevel@tonic-gate 	}
962*7c478bd9Sstevel@tonic-gate 	trace1(TR_nc_sperror, 1);
963*7c478bd9Sstevel@tonic-gate 	return (retstr);
964*7c478bd9Sstevel@tonic-gate }
965*7c478bd9Sstevel@tonic-gate 
966*7c478bd9Sstevel@tonic-gate void
967*7c478bd9Sstevel@tonic-gate nc_perror(const char *string)
968*7c478bd9Sstevel@tonic-gate {
969*7c478bd9Sstevel@tonic-gate 	trace1(TR_nc_perror, 0);
970*7c478bd9Sstevel@tonic-gate 	if (string)
971*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%s: %s\n", string, nc_sperror());
972*7c478bd9Sstevel@tonic-gate 	else
973*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%s\n", nc_sperror());
974*7c478bd9Sstevel@tonic-gate 	trace1(TR_nc_perror, 1);
975*7c478bd9Sstevel@tonic-gate }
976*7c478bd9Sstevel@tonic-gate 
977*7c478bd9Sstevel@tonic-gate static void
978*7c478bd9Sstevel@tonic-gate netlist_free(netppp)
979*7c478bd9Sstevel@tonic-gate 	struct netconfig ***netppp;
980*7c478bd9Sstevel@tonic-gate {
981*7c478bd9Sstevel@tonic-gate 	struct netconfig **tpp;
982*7c478bd9Sstevel@tonic-gate 
983*7c478bd9Sstevel@tonic-gate 	trace1(TR_netlist_free, 0);
984*7c478bd9Sstevel@tonic-gate 	for (tpp = *netppp; *tpp; tpp++) {
985*7c478bd9Sstevel@tonic-gate 		netconfig_free(*tpp);
986*7c478bd9Sstevel@tonic-gate 	}
987*7c478bd9Sstevel@tonic-gate 	free(*netppp);
988*7c478bd9Sstevel@tonic-gate 	*netppp = NULL;
989*7c478bd9Sstevel@tonic-gate 	trace1(TR_netlist_free, 1);
990*7c478bd9Sstevel@tonic-gate }
991*7c478bd9Sstevel@tonic-gate 
992*7c478bd9Sstevel@tonic-gate static void
993*7c478bd9Sstevel@tonic-gate netconfig_free(netconfigp)
994*7c478bd9Sstevel@tonic-gate struct netconfig *netconfigp;
995*7c478bd9Sstevel@tonic-gate {
996*7c478bd9Sstevel@tonic-gate 	int i;
997*7c478bd9Sstevel@tonic-gate 
998*7c478bd9Sstevel@tonic-gate 	trace1(TR_netconfig_free, 0);
999*7c478bd9Sstevel@tonic-gate 	if (netconfigp == NULL) {
1000*7c478bd9Sstevel@tonic-gate 		trace1(TR_netconfig_free, 1);
1001*7c478bd9Sstevel@tonic-gate 		return;
1002*7c478bd9Sstevel@tonic-gate 	}
1003*7c478bd9Sstevel@tonic-gate 	free_entry(netconfigp->nc_netid);
1004*7c478bd9Sstevel@tonic-gate 	free_entry(netconfigp->nc_protofmly);
1005*7c478bd9Sstevel@tonic-gate 	free_entry(netconfigp->nc_proto);
1006*7c478bd9Sstevel@tonic-gate 	free_entry(netconfigp->nc_device);
1007*7c478bd9Sstevel@tonic-gate 	if (netconfigp->nc_lookups)
1008*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < netconfigp->nc_nlookups; i++)
1009*7c478bd9Sstevel@tonic-gate 			free_entry(netconfigp->nc_lookups[i]);
1010*7c478bd9Sstevel@tonic-gate 	free_entry(netconfigp->nc_lookups);
1011*7c478bd9Sstevel@tonic-gate 	free(netconfigp);
1012*7c478bd9Sstevel@tonic-gate 	trace1(TR_netconfig_free, 1);
1013*7c478bd9Sstevel@tonic-gate }
1014*7c478bd9Sstevel@tonic-gate 
1015*7c478bd9Sstevel@tonic-gate static struct netconfig *
1016*7c478bd9Sstevel@tonic-gate netconfig_dup(netconfigp)
1017*7c478bd9Sstevel@tonic-gate struct netconfig *netconfigp;
1018*7c478bd9Sstevel@tonic-gate {
1019*7c478bd9Sstevel@tonic-gate 	struct netconfig *nconf;
1020*7c478bd9Sstevel@tonic-gate 	int i;
1021*7c478bd9Sstevel@tonic-gate 
1022*7c478bd9Sstevel@tonic-gate 	trace1(TR_netconfig_dup, 0);
1023*7c478bd9Sstevel@tonic-gate 	nconf = (struct netconfig *)calloc(1, sizeof (struct netconfig));
1024*7c478bd9Sstevel@tonic-gate 	if (nconf == NULL) {
1025*7c478bd9Sstevel@tonic-gate 		trace1(TR_netconfig_dup, 1);
1026*7c478bd9Sstevel@tonic-gate 		nc_error = NC_NOMEM;
1027*7c478bd9Sstevel@tonic-gate 		return (NULL);
1028*7c478bd9Sstevel@tonic-gate 	}
1029*7c478bd9Sstevel@tonic-gate 	nconf->nc_netid = strdup(netconfigp->nc_netid);
1030*7c478bd9Sstevel@tonic-gate 	nconf->nc_protofmly = strdup(netconfigp->nc_protofmly);
1031*7c478bd9Sstevel@tonic-gate 	nconf->nc_proto = strdup(netconfigp->nc_proto);
1032*7c478bd9Sstevel@tonic-gate 	nconf->nc_device = strdup(netconfigp->nc_device);
1033*7c478bd9Sstevel@tonic-gate 	nconf->nc_lookups = (char **)malloc((netconfigp->nc_nlookups + 1)
1034*7c478bd9Sstevel@tonic-gate 					* sizeof (char *));
1035*7c478bd9Sstevel@tonic-gate 	if (!(nconf->nc_lookups && nconf->nc_netid &&
1036*7c478bd9Sstevel@tonic-gate 		nconf->nc_protofmly && nconf->nc_proto &&
1037*7c478bd9Sstevel@tonic-gate 		nconf->nc_device)) {
1038*7c478bd9Sstevel@tonic-gate 		nc_error = NC_NOMEM;
1039*7c478bd9Sstevel@tonic-gate 		netconfig_free(nconf);
1040*7c478bd9Sstevel@tonic-gate 		trace1(TR_netconfig_dup, 1);
1041*7c478bd9Sstevel@tonic-gate 		return (NULL);
1042*7c478bd9Sstevel@tonic-gate 	}
1043*7c478bd9Sstevel@tonic-gate 
1044*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < netconfigp->nc_nlookups; i++) {
1045*7c478bd9Sstevel@tonic-gate 		nconf->nc_lookups[i] = strdup(netconfigp->nc_lookups[i]);
1046*7c478bd9Sstevel@tonic-gate 		if (nconf->nc_lookups[i] == NULL) {
1047*7c478bd9Sstevel@tonic-gate 			nconf->nc_nlookups = i;
1048*7c478bd9Sstevel@tonic-gate 			netconfig_free(nconf);
1049*7c478bd9Sstevel@tonic-gate 			nc_error = NC_NOMEM;
1050*7c478bd9Sstevel@tonic-gate 			trace1(TR_netconfig_dup, 1);
1051*7c478bd9Sstevel@tonic-gate 			return (NULL);
1052*7c478bd9Sstevel@tonic-gate 		}
1053*7c478bd9Sstevel@tonic-gate 	}
1054*7c478bd9Sstevel@tonic-gate 	nconf->nc_lookups[i] = NULL;
1055*7c478bd9Sstevel@tonic-gate 	nconf->nc_nlookups = netconfigp->nc_nlookups;
1056*7c478bd9Sstevel@tonic-gate 	nconf->nc_flag = netconfigp->nc_flag;
1057*7c478bd9Sstevel@tonic-gate 	nconf->nc_semantics = netconfigp->nc_semantics;
1058*7c478bd9Sstevel@tonic-gate 	trace1(TR_netconfig_dup, 1);
1059*7c478bd9Sstevel@tonic-gate 	return (nconf);
1060*7c478bd9Sstevel@tonic-gate }
1061*7c478bd9Sstevel@tonic-gate 
1062*7c478bd9Sstevel@tonic-gate static void
1063*7c478bd9Sstevel@tonic-gate free_entry(foo)
1064*7c478bd9Sstevel@tonic-gate 	void *foo;
1065*7c478bd9Sstevel@tonic-gate {
1066*7c478bd9Sstevel@tonic-gate 	trace1(TR_free_entry, 0);
1067*7c478bd9Sstevel@tonic-gate 	if (foo)
1068*7c478bd9Sstevel@tonic-gate 		free(foo);
1069*7c478bd9Sstevel@tonic-gate 	trace1(TR_free_entry, 1);
1070*7c478bd9Sstevel@tonic-gate }
1071