17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5004388ebScasper  * Common Development and Distribution License (the "License").
6004388ebScasper  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
2161961e0fSrobinson 
227c478bd9Sstevel@tonic-gate /*
23cb620785Sraf  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
287c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate /*
317c478bd9Sstevel@tonic-gate  * Portions of this source code were derived from Berkeley 4.3 BSD
327c478bd9Sstevel@tonic-gate  * under license from the Regents of the University of California.
337c478bd9Sstevel@tonic-gate  */
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate #include "mt.h"
367c478bd9Sstevel@tonic-gate #include "../rpc/rpc_mt.h"		/* for MT declarations only */
377c478bd9Sstevel@tonic-gate #include <rpc/types.h>
387c478bd9Sstevel@tonic-gate #include <stdio.h>
3961961e0fSrobinson #include <stdlib.h>
407c478bd9Sstevel@tonic-gate #include <string.h>
417c478bd9Sstevel@tonic-gate #include <ctype.h>
427c478bd9Sstevel@tonic-gate #include <netconfig.h>
437c478bd9Sstevel@tonic-gate #include <malloc.h>
4461961e0fSrobinson #include <libintl.h>
457c478bd9Sstevel@tonic-gate #include <syslog.h>
467c478bd9Sstevel@tonic-gate #include "netcspace.h"
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate #define	FAILURE  (unsigned)(-1)
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate /*
517c478bd9Sstevel@tonic-gate  *	Local routines used by the library procedures
527c478bd9Sstevel@tonic-gate  */
537c478bd9Sstevel@tonic-gate 
5461961e0fSrobinson static int blank(char *);
5561961e0fSrobinson static int comment(char *);
56004388ebScasper static struct netconfig *fgetnetconfig(FILE *, char *);
5761961e0fSrobinson static void netconfig_free(struct netconfig *);
5861961e0fSrobinson static unsigned int getflag(char *);
5961961e0fSrobinson static char **getlookups(char *);
6061961e0fSrobinson static struct netconfig **getnetlist(void);
6161961e0fSrobinson static unsigned int getnlookups(char *);
6261961e0fSrobinson static char *gettoken(char *, int);
6361961e0fSrobinson static unsigned int getvalue(char *, struct nc_data nc_data[]);
6461961e0fSrobinson static void shift1left(char *);
6561961e0fSrobinson static void netlist_free(struct netconfig ***);
6661961e0fSrobinson static void free_entry(void *);
6761961e0fSrobinson static struct netconfig *netconfig_dup(struct netconfig *);
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate extern const char __nsl_dom[];
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate /*
727c478bd9Sstevel@tonic-gate  *	Static global variables used by the library procedures:
737c478bd9Sstevel@tonic-gate  *
747c478bd9Sstevel@tonic-gate  *	netpp - points to the beginning of the list of netconfig
757c478bd9Sstevel@tonic-gate  *		entries used by setnetconfig() and setnetpath().
767c478bd9Sstevel@tonic-gate  *		Once netpp is initialized, that memory is *never*
777c478bd9Sstevel@tonic-gate  *		released.  This was necessary to improve performance.
787c478bd9Sstevel@tonic-gate  *
797c478bd9Sstevel@tonic-gate  *	linenum - the current line number of the /etc/netconfig
807c478bd9Sstevel@tonic-gate  *		  file (used for debugging and for nc_perror()).
817c478bd9Sstevel@tonic-gate  *
827c478bd9Sstevel@tonic-gate  *	fieldnum - the current field number of the current line
837c478bd9Sstevel@tonic-gate  *		   of /etc/netconfig (used for debugging and for
847c478bd9Sstevel@tonic-gate  *		   nc_perror()).
857c478bd9Sstevel@tonic-gate  *
867c478bd9Sstevel@tonic-gate  *	nc_error - the error condition encountered.
877c478bd9Sstevel@tonic-gate  */
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate static struct netconfig **netpp = NULL;
907c478bd9Sstevel@tonic-gate mutex_t netpp_mutex = DEFAULTMUTEX;
917c478bd9Sstevel@tonic-gate /*
927c478bd9Sstevel@tonic-gate  * The following two variables are used by the /etc/netconfig parsing
937c478bd9Sstevel@tonic-gate  * routines, which will always be executed once, and within the netpp_mutex.
947c478bd9Sstevel@tonic-gate  * They are global to allow the nc_sperror routine to provide better
957c478bd9Sstevel@tonic-gate  * information to the user about /etc/netconfig file problems.
967c478bd9Sstevel@tonic-gate  */
977c478bd9Sstevel@tonic-gate static int linenum = 0;			/* "owned" by getnetlist() */
987c478bd9Sstevel@tonic-gate static int fieldnum = 0;		/* "owned" by fgetnetconfig() */
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate static int *
__nc_error(void)10261961e0fSrobinson __nc_error(void)
1037c478bd9Sstevel@tonic-gate {
104cb620785Sraf 	static pthread_key_t nc_error_key = PTHREAD_ONCE_KEY_NP;
1057c478bd9Sstevel@tonic-gate 	static int nc_error = NC_NOERROR;
1067c478bd9Sstevel@tonic-gate 	int *ret;
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate 	if (thr_main())
1097c478bd9Sstevel@tonic-gate 		return (&nc_error);
1107c478bd9Sstevel@tonic-gate 	ret = thr_get_storage(&nc_error_key, sizeof (int), free);
1117c478bd9Sstevel@tonic-gate 	/* if thr_get_storage fails we return the address of nc_error */
1127c478bd9Sstevel@tonic-gate 	return (ret ? ret : &nc_error);
1137c478bd9Sstevel@tonic-gate }
1147c478bd9Sstevel@tonic-gate #define	nc_error	(*(__nc_error()))
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate /*
1177c478bd9Sstevel@tonic-gate  *	setnetconfig() has the effect of "initializing" the
1187c478bd9Sstevel@tonic-gate  *	network configuration database.   It reads in the
1197c478bd9Sstevel@tonic-gate  *	netcf entries (if not already read in).
1207c478bd9Sstevel@tonic-gate  */
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate void *
setnetconfig(void)12361961e0fSrobinson setnetconfig(void)
1247c478bd9Sstevel@tonic-gate {
1257c478bd9Sstevel@tonic-gate 	NCONF_HANDLE *retp;
1267c478bd9Sstevel@tonic-gate 
12761961e0fSrobinson 	(void) mutex_lock(&netpp_mutex);
1287c478bd9Sstevel@tonic-gate 	if ((netpp == NULL) && ((netpp = getnetlist()) == NULL)) {
12961961e0fSrobinson 		(void) mutex_unlock(&netpp_mutex);
1307c478bd9Sstevel@tonic-gate 		return (NULL);
1317c478bd9Sstevel@tonic-gate 	}
13261961e0fSrobinson 	(void) mutex_unlock(&netpp_mutex);
13361961e0fSrobinson 	if ((retp = malloc(sizeof (NCONF_HANDLE))) == NULL) {
1347c478bd9Sstevel@tonic-gate 		nc_error = NC_NOMEM;
1357c478bd9Sstevel@tonic-gate 		return (NULL);
1367c478bd9Sstevel@tonic-gate 	}
1377c478bd9Sstevel@tonic-gate 	nc_error = NC_NOERROR;
1387c478bd9Sstevel@tonic-gate 	retp->nc_head = retp->nc_curr = netpp;
1397c478bd9Sstevel@tonic-gate 	return ((void *)retp);
1407c478bd9Sstevel@tonic-gate }
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate /*
1437c478bd9Sstevel@tonic-gate  *	endnetconfig() frees up all data allocated by setnetconfig()
1447c478bd9Sstevel@tonic-gate  */
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate int
endnetconfig(void * vdata)14761961e0fSrobinson endnetconfig(void *vdata)
1487c478bd9Sstevel@tonic-gate {
1497c478bd9Sstevel@tonic-gate 	NCONF_HANDLE *nconf_handlep = (NCONF_HANDLE *)vdata;
1507c478bd9Sstevel@tonic-gate 
15161961e0fSrobinson 	(void) mutex_lock(&netpp_mutex);
1527c478bd9Sstevel@tonic-gate 	if (netpp == NULL || nconf_handlep == NULL) {
1537c478bd9Sstevel@tonic-gate 		nc_error = NC_NOSET;
15461961e0fSrobinson 		(void) mutex_unlock(&netpp_mutex);
1557c478bd9Sstevel@tonic-gate 		return (-1);
1567c478bd9Sstevel@tonic-gate 	}
15761961e0fSrobinson 	(void) mutex_unlock(&netpp_mutex);
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 	nc_error = NC_NOERROR;
16061961e0fSrobinson 	free(nconf_handlep);
1617c478bd9Sstevel@tonic-gate 	return (0);
1627c478bd9Sstevel@tonic-gate }
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate /*
1657c478bd9Sstevel@tonic-gate  *	getnetconfig() returns the current entry in the list
1667c478bd9Sstevel@tonic-gate  *	of netconfig structures.  It uses the nconf_handlep argument
1677c478bd9Sstevel@tonic-gate  *	to determine the current entry. If setnetconfig() was not
1687c478bd9Sstevel@tonic-gate  *	called previously to set up the list, return failure.
1697c478bd9Sstevel@tonic-gate  *      It also check if ipv6 interface is present(ipv6_present) and
1707c478bd9Sstevel@tonic-gate  *	skips udp6 & tcp6 entries if ipv6 is not supported.
1717c478bd9Sstevel@tonic-gate  */
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate struct netconfig *
getnetconfig(void * vdata)17461961e0fSrobinson getnetconfig(void *vdata)
1757c478bd9Sstevel@tonic-gate {
1767c478bd9Sstevel@tonic-gate 	NCONF_HANDLE *nconf_handlep = (NCONF_HANDLE *)vdata;
1777c478bd9Sstevel@tonic-gate 	struct netconfig *retp;  /* holds the return value */
1787c478bd9Sstevel@tonic-gate 	int ipv6_present = -1;
1797c478bd9Sstevel@tonic-gate 
18061961e0fSrobinson 	(void) mutex_lock(&netpp_mutex);
1817c478bd9Sstevel@tonic-gate 	if ((netpp == NULL) || (nconf_handlep == NULL)) {
1827c478bd9Sstevel@tonic-gate 		nc_error = NC_NOSET;
18361961e0fSrobinson 		(void) mutex_unlock(&netpp_mutex);
1847c478bd9Sstevel@tonic-gate 		return (NULL);
1857c478bd9Sstevel@tonic-gate 	}
18661961e0fSrobinson 	(void) mutex_unlock(&netpp_mutex);
1877c478bd9Sstevel@tonic-gate 	for (;;) {
1887c478bd9Sstevel@tonic-gate 		retp = *(nconf_handlep->nc_curr);
1897c478bd9Sstevel@tonic-gate 		if (retp && (strcmp(retp->nc_netid, "udp6") == 0 ||
1907c478bd9Sstevel@tonic-gate 		    strcmp(retp->nc_netid, "tcp6") == 0)) {
1917c478bd9Sstevel@tonic-gate 			if (ipv6_present == -1)
1927c478bd9Sstevel@tonic-gate 				ipv6_present = __can_use_af(AF_INET6);
1937c478bd9Sstevel@tonic-gate 			if (!ipv6_present) {
1947c478bd9Sstevel@tonic-gate 				++(nconf_handlep->nc_curr);
1957c478bd9Sstevel@tonic-gate 				continue;
1967c478bd9Sstevel@tonic-gate 			}
1977c478bd9Sstevel@tonic-gate 		}
1987c478bd9Sstevel@tonic-gate 		break;
1997c478bd9Sstevel@tonic-gate 	}
2007c478bd9Sstevel@tonic-gate 	if (retp != NULL) {
2017c478bd9Sstevel@tonic-gate 		++(nconf_handlep->nc_curr);
2027c478bd9Sstevel@tonic-gate 		nc_error = NC_NOERROR;
2037c478bd9Sstevel@tonic-gate 	} else {
2047c478bd9Sstevel@tonic-gate 		nc_error = NC_NOMOREENTRIES;
2057c478bd9Sstevel@tonic-gate 	}
2067c478bd9Sstevel@tonic-gate 	return (retp);
2077c478bd9Sstevel@tonic-gate }
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate /*
2107c478bd9Sstevel@tonic-gate  *	getnetconfig() searches the netconfig database for a
2117c478bd9Sstevel@tonic-gate  *	given network id.  Returns a pointer to the netconfig
2127c478bd9Sstevel@tonic-gate  *	structure or a NULL if not found.
2137c478bd9Sstevel@tonic-gate  *      It also check if ipv6 interface is present(ipv6_present) and
2147c478bd9Sstevel@tonic-gate  *	skips udp6 & tcp6 entries if ipv6 is not supported.
2157c478bd9Sstevel@tonic-gate  */
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate struct netconfig *
getnetconfigent(const char * netid)21861961e0fSrobinson getnetconfigent(const char *netid)
2197c478bd9Sstevel@tonic-gate {
2207c478bd9Sstevel@tonic-gate 	struct netconfig **tpp;
2217c478bd9Sstevel@tonic-gate 	int ipv6_present;
2227c478bd9Sstevel@tonic-gate 
22361961e0fSrobinson 	(void) mutex_lock(&netpp_mutex);
2247c478bd9Sstevel@tonic-gate 	if ((netpp == NULL) && ((netpp = getnetlist()) == NULL)) {
22561961e0fSrobinson 		(void) mutex_unlock(&netpp_mutex);
2267c478bd9Sstevel@tonic-gate 		return (NULL);
2277c478bd9Sstevel@tonic-gate 	}
22861961e0fSrobinson 	(void) mutex_unlock(&netpp_mutex);
2297c478bd9Sstevel@tonic-gate 	for (tpp = netpp; *tpp; tpp++) {
2307c478bd9Sstevel@tonic-gate 		if (strcmp((*tpp)->nc_netid, netid) == 0) {
2317c478bd9Sstevel@tonic-gate 			if (*tpp && (strcmp((*tpp)->nc_netid, "udp6") == 0 ||
2327c478bd9Sstevel@tonic-gate 			    strcmp((*tpp)->nc_netid, "tcp6") == 0)) {
2337c478bd9Sstevel@tonic-gate 				ipv6_present = __can_use_af(AF_INET6);
2347c478bd9Sstevel@tonic-gate 				if (!ipv6_present) {
2357c478bd9Sstevel@tonic-gate 					nc_error = NC_NOTFOUND;
2367c478bd9Sstevel@tonic-gate 					return (NULL);
2377c478bd9Sstevel@tonic-gate 				}
2387c478bd9Sstevel@tonic-gate 			}
2397c478bd9Sstevel@tonic-gate 			return (netconfig_dup(*tpp));
2407c478bd9Sstevel@tonic-gate 		}
2417c478bd9Sstevel@tonic-gate 	}
2427c478bd9Sstevel@tonic-gate 	nc_error = NC_NOTFOUND;
2437c478bd9Sstevel@tonic-gate 	return (NULL);
2447c478bd9Sstevel@tonic-gate }
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate /*
2477c478bd9Sstevel@tonic-gate  *	freenetconfigent frees the data allocated by getnetconfigent()
2487c478bd9Sstevel@tonic-gate  */
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate void
freenetconfigent(struct netconfig * netp)25161961e0fSrobinson freenetconfigent(struct netconfig *netp)
2527c478bd9Sstevel@tonic-gate {
2537c478bd9Sstevel@tonic-gate 	netconfig_free(netp);
2547c478bd9Sstevel@tonic-gate }
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate /*
2577c478bd9Sstevel@tonic-gate  *	getnetlist() reads the netconfig file and creates a
2587c478bd9Sstevel@tonic-gate  *	NULL-terminated list of entries.
2597c478bd9Sstevel@tonic-gate  *	Returns the pointer to the head of the list or a NULL
2607c478bd9Sstevel@tonic-gate  *	on failure.
2617c478bd9Sstevel@tonic-gate  */
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate static struct netconfig **
getnetlist(void)26461961e0fSrobinson getnetlist(void)
2657c478bd9Sstevel@tonic-gate {
2667c478bd9Sstevel@tonic-gate 	char line[BUFSIZ];	/* holds each line of NETCONFIG */
267004388ebScasper 	FILE *fp;		/* file stream for NETCONFIG */
2687c478bd9Sstevel@tonic-gate 	struct netconfig **listpp; /* the beginning of the netconfig list */
2697c478bd9Sstevel@tonic-gate 	struct netconfig **tpp;	/* used to traverse the netconfig list */
2707c478bd9Sstevel@tonic-gate 	int count;		/* the number of entries in file */
2717c478bd9Sstevel@tonic-gate 
272004388ebScasper 	if ((fp = fopen(NETCONFIG, "rF")) == NULL) {
2737c478bd9Sstevel@tonic-gate 		nc_error = NC_OPENFAIL;
2747c478bd9Sstevel@tonic-gate 		return (NULL);
2757c478bd9Sstevel@tonic-gate 	}
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate 	count = 0;
278004388ebScasper 	while (fgets(line, BUFSIZ, fp)) {
2797c478bd9Sstevel@tonic-gate 		if (!(blank(line) || comment(line))) {
2807c478bd9Sstevel@tonic-gate 			++count;
2817c478bd9Sstevel@tonic-gate 		}
2827c478bd9Sstevel@tonic-gate 	}
283004388ebScasper 	rewind(fp);
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 	if (count == 0) {
2867c478bd9Sstevel@tonic-gate 		nc_error = NC_NOTFOUND;
287004388ebScasper 		(void) fclose(fp);
2887c478bd9Sstevel@tonic-gate 		return (NULL);
2897c478bd9Sstevel@tonic-gate 	}
29061961e0fSrobinson 	if ((listpp = malloc((count + 1) *
2917c478bd9Sstevel@tonic-gate 	    sizeof (struct netconfig *))) == NULL) {
2927c478bd9Sstevel@tonic-gate 		nc_error = NC_NOMEM;
293004388ebScasper 		(void) fclose(fp);
2947c478bd9Sstevel@tonic-gate 		return (NULL);
2957c478bd9Sstevel@tonic-gate 	}
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 	/*
2987c478bd9Sstevel@tonic-gate 	 *	The following loop fills in the list (loops until
2997c478bd9Sstevel@tonic-gate 	 *	fgetnetconfig() returns a NULL) and counts the
3007c478bd9Sstevel@tonic-gate 	 *	number of entries placed in the list.  Note that
3017c478bd9Sstevel@tonic-gate 	 *	when the loop is completed, the last entry in the
3027c478bd9Sstevel@tonic-gate 	 *	list will contain a NULL (signifying the end of
3037c478bd9Sstevel@tonic-gate 	 *	the list).
3047c478bd9Sstevel@tonic-gate 	 */
3057c478bd9Sstevel@tonic-gate 	linenum = 0;
3067c478bd9Sstevel@tonic-gate 	for (tpp = listpp; *tpp = fgetnetconfig(fp, NULL); tpp++)
3077c478bd9Sstevel@tonic-gate 		;
308004388ebScasper 	(void) fclose(fp);
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate 	if (nc_error != NC_NOMOREENTRIES) /* Something is screwed up */
3117c478bd9Sstevel@tonic-gate 		netlist_free(&listpp);
3127c478bd9Sstevel@tonic-gate 	return (listpp);
3137c478bd9Sstevel@tonic-gate }
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate /*
3167c478bd9Sstevel@tonic-gate  *	fgetnetconfig() parses a line of the netconfig file into
3177c478bd9Sstevel@tonic-gate  *	a netconfig structure.  It returns a pointer to the
3187c478bd9Sstevel@tonic-gate  *	structure of success and a NULL on failure or EOF.
3197c478bd9Sstevel@tonic-gate  */
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate static struct netconfig *
fgetnetconfig(FILE * fp,char * netid)322004388ebScasper fgetnetconfig(FILE *fp, char *netid)
3237c478bd9Sstevel@tonic-gate {
3247c478bd9Sstevel@tonic-gate 	char linep[BUFSIZ];	/* pointer to a line in the file */
3257c478bd9Sstevel@tonic-gate 	struct netconfig *netconfigp; /* holds the new netconfig structure */
3267c478bd9Sstevel@tonic-gate 	char  *tok1, *tok2, *tok3; /* holds a token from the line */
3277c478bd9Sstevel@tonic-gate 	char  *retvalp;		/* the return value of fgets() */
3287c478bd9Sstevel@tonic-gate 	char *entnetid;		/* netid for the current entry */
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate 	/* skip past blank lines and comments. */
331004388ebScasper 	while (retvalp = fgets(linep, BUFSIZ, fp)) {
3327c478bd9Sstevel@tonic-gate 		linenum++;
3337c478bd9Sstevel@tonic-gate 		if (!(blank(linep) || comment(linep))) {
3347c478bd9Sstevel@tonic-gate 			break;
3357c478bd9Sstevel@tonic-gate 		}
3367c478bd9Sstevel@tonic-gate 		retvalp = NULL;
3377c478bd9Sstevel@tonic-gate 	}
3387c478bd9Sstevel@tonic-gate 	if (retvalp == NULL) {
3397c478bd9Sstevel@tonic-gate 		nc_error = NC_NOMOREENTRIES;
3407c478bd9Sstevel@tonic-gate 		return (NULL);
3417c478bd9Sstevel@tonic-gate 	}
3427c478bd9Sstevel@tonic-gate 	fieldnum = 0;
3437c478bd9Sstevel@tonic-gate 	if ((entnetid = gettoken(linep, FALSE)) == NULL) {
3447c478bd9Sstevel@tonic-gate 		nc_error = NC_BADLINE;
3457c478bd9Sstevel@tonic-gate 		return (NULL);
3467c478bd9Sstevel@tonic-gate 	}
3477c478bd9Sstevel@tonic-gate 	if (netid && (strcmp(netid, entnetid) != 0)) {
3487c478bd9Sstevel@tonic-gate 		free(entnetid);
3497c478bd9Sstevel@tonic-gate 		nc_error = NC_NOTFOUND;
3507c478bd9Sstevel@tonic-gate 		return (NULL);
3517c478bd9Sstevel@tonic-gate 	}
35261961e0fSrobinson 	if ((netconfigp = calloc(1, sizeof (struct netconfig))) == NULL) {
3537c478bd9Sstevel@tonic-gate 		free(entnetid);
3547c478bd9Sstevel@tonic-gate 		nc_error = NC_NOMEM;
3557c478bd9Sstevel@tonic-gate 		return (NULL);
3567c478bd9Sstevel@tonic-gate 	}
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate 	tok1 = tok2 = tok3 = NULL;
3597c478bd9Sstevel@tonic-gate 	netconfigp->nc_netid = entnetid;
3607c478bd9Sstevel@tonic-gate 	if (((tok1 = gettoken(NULL, FALSE)) == NULL) ||
3617c478bd9Sstevel@tonic-gate 	    ((netconfigp->nc_semantics =
3627c478bd9Sstevel@tonic-gate 		getvalue(tok1, nc_semantics)) == FAILURE) ||
3637c478bd9Sstevel@tonic-gate 	    ((tok2 = gettoken(NULL, FALSE)) == NULL) ||
3647c478bd9Sstevel@tonic-gate 	    ((netconfigp->nc_flag = getflag(tok2)) == FAILURE) ||
3657c478bd9Sstevel@tonic-gate 	    ((netconfigp->nc_protofmly = gettoken(NULL, FALSE)) == NULL) ||
3667c478bd9Sstevel@tonic-gate 	    ((netconfigp->nc_proto = gettoken(NULL, FALSE)) == NULL) ||
3677c478bd9Sstevel@tonic-gate 	    ((netconfigp->nc_device = gettoken(NULL, FALSE)) == NULL) ||
3687c478bd9Sstevel@tonic-gate 	    ((tok3 = gettoken(NULL, TRUE)) == NULL) ||
3697c478bd9Sstevel@tonic-gate 	    (((netconfigp->nc_nlookups = getnlookups(tok3)) != 0) &&
3707c478bd9Sstevel@tonic-gate 		((netconfigp->nc_lookups = getlookups(tok3)) == NULL))) {
3717c478bd9Sstevel@tonic-gate 		netconfig_free(netconfigp);
3727c478bd9Sstevel@tonic-gate 		nc_error = NC_BADLINE;
3737c478bd9Sstevel@tonic-gate 		netconfigp = NULL;
3747c478bd9Sstevel@tonic-gate 	}
3757c478bd9Sstevel@tonic-gate 	free(tok1);
3767c478bd9Sstevel@tonic-gate 	free(tok2);
3777c478bd9Sstevel@tonic-gate 	free(tok3);
3787c478bd9Sstevel@tonic-gate 	return (netconfigp);
3797c478bd9Sstevel@tonic-gate }
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate /*
3827c478bd9Sstevel@tonic-gate  *	setnetpath() has the effect of "initializing" the
3837c478bd9Sstevel@tonic-gate  *	NETPATH variable.  It reads in the netcf entries (if not
3847c478bd9Sstevel@tonic-gate  *	already read in), creates a list corresponding to the entries
3857c478bd9Sstevel@tonic-gate  *	in the NETPATH variable (or the "visible" entries og netconfig
3867c478bd9Sstevel@tonic-gate  *	if NETPATH is not set).
3877c478bd9Sstevel@tonic-gate  */
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate void *
setnetpath(void)39061961e0fSrobinson setnetpath(void)
3917c478bd9Sstevel@tonic-gate {
3927c478bd9Sstevel@tonic-gate 	int count;		    /* the number of entries in NETPATH	    */
3937c478bd9Sstevel@tonic-gate 	char valid_netpath[BUFSIZ]; /* holds the valid entries if NETPATH   */
3947c478bd9Sstevel@tonic-gate 	char templine[BUFSIZ];	    /* has value of NETPATH when scanning   */
3957c478bd9Sstevel@tonic-gate 	struct netconfig **curr_pp; /* scans the list from NETPATH	    */
3967c478bd9Sstevel@tonic-gate 	struct netconfig **tpp;	    /* scans the list from netconfig file   */
3977c478bd9Sstevel@tonic-gate 	struct netconfig **rnetpp;  /* the list of entries from NETPATH	    */
3987c478bd9Sstevel@tonic-gate 	char *netpath;		    /* value of NETPATH from environment    */
3997c478bd9Sstevel@tonic-gate 	char *netid;		    /* holds a component of NETPATH	    */
4007c478bd9Sstevel@tonic-gate 	char *tp;		    /* used to scan NETPATH string	    */
4017c478bd9Sstevel@tonic-gate 	NCONF_HANDLE *retp;	    /* the return value			    */
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 	/*
4047c478bd9Sstevel@tonic-gate 	 *	Read in the netconfig database if not already read in
4057c478bd9Sstevel@tonic-gate 	 */
40661961e0fSrobinson 	(void) mutex_lock(&netpp_mutex);
4077c478bd9Sstevel@tonic-gate 	if ((netpp == NULL) && ((netpp = getnetlist()) == NULL)) {
40861961e0fSrobinson 		(void) mutex_unlock(&netpp_mutex);
4097c478bd9Sstevel@tonic-gate 		return (NULL);
4107c478bd9Sstevel@tonic-gate 	}
41161961e0fSrobinson 	(void) mutex_unlock(&netpp_mutex);
4127c478bd9Sstevel@tonic-gate 
41361961e0fSrobinson 	if ((retp = malloc(sizeof (NCONF_HANDLE))) == NULL) {
4147c478bd9Sstevel@tonic-gate 		nc_error = NC_NOMEM;
4157c478bd9Sstevel@tonic-gate 		return (NULL);
4167c478bd9Sstevel@tonic-gate 	}
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 	/*
4197c478bd9Sstevel@tonic-gate 	 *	Get the valid entries of the NETPATH variable (and
4207c478bd9Sstevel@tonic-gate 	 *	count the number of entries while doing it).
4217c478bd9Sstevel@tonic-gate 	 *
4227c478bd9Sstevel@tonic-gate 	 *	This is done every time the procedure is called just
4237c478bd9Sstevel@tonic-gate 	 *	in case NETPATH has changed from call to call.
4247c478bd9Sstevel@tonic-gate 	 *
4257c478bd9Sstevel@tonic-gate 	 * 	If NETPATH is too long, we ignore it altogether as
4267c478bd9Sstevel@tonic-gate 	 *	it can only be a buffer overflow attack.
4277c478bd9Sstevel@tonic-gate 	 *	Since we add one colon for each entry, but colons only
4287c478bd9Sstevel@tonic-gate 	 *	need to exist between entries, we have to subtract one.
4297c478bd9Sstevel@tonic-gate 	 */
4307c478bd9Sstevel@tonic-gate 	count = 0;
4317c478bd9Sstevel@tonic-gate 	valid_netpath[0] = '\0';
4327c478bd9Sstevel@tonic-gate 	if ((netpath = getenv(NETPATH)) == NULL ||
4337c478bd9Sstevel@tonic-gate 	    strlen(netpath) >= sizeof (templine) - 1) {
4347c478bd9Sstevel@tonic-gate 		/*
4357c478bd9Sstevel@tonic-gate 		 *	If NETPATH variable is not set or invalid,
4367c478bd9Sstevel@tonic-gate 		 *	the valid NETPATH consist of all "visible"
4377c478bd9Sstevel@tonic-gate 		 *	netids from the netconfig database.
4387c478bd9Sstevel@tonic-gate 		 */
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate 		for (tpp = netpp; *tpp; tpp++) {
4417c478bd9Sstevel@tonic-gate 			if ((*tpp)->nc_flag & NC_VISIBLE) {
4427c478bd9Sstevel@tonic-gate 				(void) strcat(valid_netpath, (*tpp)->nc_netid);
4437c478bd9Sstevel@tonic-gate 				(void) strcat(valid_netpath, ":");
4447c478bd9Sstevel@tonic-gate 				count++;
4457c478bd9Sstevel@tonic-gate 			}
4467c478bd9Sstevel@tonic-gate 		}
4477c478bd9Sstevel@tonic-gate 	} else {
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 		/*
4507c478bd9Sstevel@tonic-gate 		 *	Copy the value of NETPATH (since '\0's will be
4517c478bd9Sstevel@tonic-gate 		 *	put into the string) and create the valid NETPATH
4527c478bd9Sstevel@tonic-gate 		 *	(by throwing away all netids not in the database).
4537c478bd9Sstevel@tonic-gate 		 *	If an entry appears more than one, it *will* be
4547c478bd9Sstevel@tonic-gate 		 *	listed twice in the list of valid netpath entries.
4557c478bd9Sstevel@tonic-gate 		 */
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 		(void) strcpy(templine, netpath);
4587c478bd9Sstevel@tonic-gate 		tp = templine;
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 		while (*tp) {
4617c478bd9Sstevel@tonic-gate 			/* Skip all leading ':'s */
4627c478bd9Sstevel@tonic-gate 			while (*tp && *tp == ':')
4637c478bd9Sstevel@tonic-gate 				tp++;
464*344db6f4SToomas Soome 			if (*tp == '\0')
4657c478bd9Sstevel@tonic-gate 				break;  /* last one */
4667c478bd9Sstevel@tonic-gate 			netid = tp;
4677c478bd9Sstevel@tonic-gate 			while (*tp && *tp != ':')
4687c478bd9Sstevel@tonic-gate 				tp++;
4697c478bd9Sstevel@tonic-gate 			if (*tp)
4707c478bd9Sstevel@tonic-gate 				*tp++ = '\0'; /* isolate netid */
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate 			for (tpp = netpp; *tpp; tpp++) {
4737c478bd9Sstevel@tonic-gate 				if (strcmp(netid, (*tpp)->nc_netid) == 0) {
4747c478bd9Sstevel@tonic-gate 					(void) strcat(valid_netpath,
4757c478bd9Sstevel@tonic-gate 						(*tpp)->nc_netid);
4767c478bd9Sstevel@tonic-gate 					(void) strcat(valid_netpath, ":");
4777c478bd9Sstevel@tonic-gate 					count++;
4787c478bd9Sstevel@tonic-gate 					break;
4797c478bd9Sstevel@tonic-gate 				}
4807c478bd9Sstevel@tonic-gate 			}
4817c478bd9Sstevel@tonic-gate 		}
4827c478bd9Sstevel@tonic-gate 	}
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate 	/* Get space to hold the valid list (+1 for the NULL) */
4857c478bd9Sstevel@tonic-gate 
48661961e0fSrobinson 	if ((rnetpp = malloc((count + 1) *
4877c478bd9Sstevel@tonic-gate 			sizeof (struct netconfig *))) == NULL) {
48861961e0fSrobinson 		free(retp);
4897c478bd9Sstevel@tonic-gate 		nc_error = NC_NOMEM;
4907c478bd9Sstevel@tonic-gate 		return (NULL);
4917c478bd9Sstevel@tonic-gate 	}
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate 	/*
4947c478bd9Sstevel@tonic-gate 	 *	Populate the NETPATH list, ending it with a NULL.
4957c478bd9Sstevel@tonic-gate 	 *	Each entry in the list points to the structure in the
4967c478bd9Sstevel@tonic-gate 	 *	"netpp" list (the entry must exist in the list, otherwise
4977c478bd9Sstevel@tonic-gate 	 *	it wouldn't appear in valid_netpath[]).
4987c478bd9Sstevel@tonic-gate 	 */
4997c478bd9Sstevel@tonic-gate 
5007c478bd9Sstevel@tonic-gate 	curr_pp = rnetpp;
5017c478bd9Sstevel@tonic-gate 	netid = tp = valid_netpath;
5027c478bd9Sstevel@tonic-gate 	while (*tp) {
5037c478bd9Sstevel@tonic-gate 		netid = tp;
5047c478bd9Sstevel@tonic-gate 		while (*tp && *tp != ':')
5057c478bd9Sstevel@tonic-gate 			tp++;
5067c478bd9Sstevel@tonic-gate 		if (*tp)
5077c478bd9Sstevel@tonic-gate 			*tp++ = '\0';
5087c478bd9Sstevel@tonic-gate 		for (tpp = netpp; *tpp; tpp++) {
5097c478bd9Sstevel@tonic-gate 			if (strcmp(netid, (*tpp)->nc_netid) == 0) {
5107c478bd9Sstevel@tonic-gate 				*curr_pp++ = *tpp;
5117c478bd9Sstevel@tonic-gate 				break;
5127c478bd9Sstevel@tonic-gate 			}
5137c478bd9Sstevel@tonic-gate 		}
5147c478bd9Sstevel@tonic-gate 	}
5157c478bd9Sstevel@tonic-gate 	*curr_pp = NULL;
5167c478bd9Sstevel@tonic-gate 
5177c478bd9Sstevel@tonic-gate 	retp->nc_curr = retp->nc_head = rnetpp;
5187c478bd9Sstevel@tonic-gate 	return ((void *)retp);
5197c478bd9Sstevel@tonic-gate }
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate /*
5227c478bd9Sstevel@tonic-gate  *	endnetpath() frees up all of the memory allocated by setnetpath().
5237c478bd9Sstevel@tonic-gate  *	It returns -1 (error) if setnetpath was never called.
5247c478bd9Sstevel@tonic-gate  */
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate int
endnetpath(void * vdata)52761961e0fSrobinson endnetpath(void *vdata)
5287c478bd9Sstevel@tonic-gate {
5297c478bd9Sstevel@tonic-gate 	/* The argument is really a NCONF_HANDLE;  cast it here */
5307c478bd9Sstevel@tonic-gate 	NCONF_HANDLE *nconf_handlep = (NCONF_HANDLE *)vdata;
5317c478bd9Sstevel@tonic-gate 
53261961e0fSrobinson 	(void) mutex_lock(&netpp_mutex);
5337c478bd9Sstevel@tonic-gate 	if (netpp == NULL || nconf_handlep == NULL) {
5347c478bd9Sstevel@tonic-gate 		nc_error = NC_NOSET;
53561961e0fSrobinson 		(void) mutex_unlock(&netpp_mutex);
5367c478bd9Sstevel@tonic-gate 		return (-1);
5377c478bd9Sstevel@tonic-gate 	}
53861961e0fSrobinson 	(void) mutex_unlock(&netpp_mutex);
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate 	free(nconf_handlep->nc_head);
5417c478bd9Sstevel@tonic-gate 	free(nconf_handlep);
5427c478bd9Sstevel@tonic-gate 	return (0);
5437c478bd9Sstevel@tonic-gate }
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate /*
5467c478bd9Sstevel@tonic-gate  *	getnetpath() returns the current entry in the list
5477c478bd9Sstevel@tonic-gate  *	from the NETPATH variable.  If setnetpath() was not called
5487c478bd9Sstevel@tonic-gate  *	previously to set up the list, return NULL.
5497c478bd9Sstevel@tonic-gate  */
5507c478bd9Sstevel@tonic-gate 
5517c478bd9Sstevel@tonic-gate struct netconfig *
getnetpath(void * vdata)55261961e0fSrobinson getnetpath(void *vdata)
5537c478bd9Sstevel@tonic-gate {
5547c478bd9Sstevel@tonic-gate 	/* The argument is really a NCONF_HANDLE;  cast it here */
5557c478bd9Sstevel@tonic-gate 	NCONF_HANDLE *nconf_handlep = (NCONF_HANDLE *)vdata;
5567c478bd9Sstevel@tonic-gate 	struct netconfig *retp;  /* holds the return value */
5577c478bd9Sstevel@tonic-gate 	int ipv6_present = -1;
5587c478bd9Sstevel@tonic-gate 
55961961e0fSrobinson 	(void) mutex_lock(&netpp_mutex);
5607c478bd9Sstevel@tonic-gate 	if (netpp == NULL) {
5617c478bd9Sstevel@tonic-gate 		nc_error = NC_NOSET;
56261961e0fSrobinson 		(void) mutex_unlock(&netpp_mutex);
5637c478bd9Sstevel@tonic-gate 		return (NULL);
5647c478bd9Sstevel@tonic-gate 	}
56561961e0fSrobinson 	(void) mutex_unlock(&netpp_mutex);
5667c478bd9Sstevel@tonic-gate 	for (;;) {
5677c478bd9Sstevel@tonic-gate 		retp = *(nconf_handlep->nc_curr);
5687c478bd9Sstevel@tonic-gate 		if (retp && (strcmp(retp->nc_netid, "udp6") == 0 ||
5697c478bd9Sstevel@tonic-gate 		    strcmp(retp->nc_netid, "tcp6") == 0)) {
5707c478bd9Sstevel@tonic-gate 			if (ipv6_present == -1)
5717c478bd9Sstevel@tonic-gate 				ipv6_present = __can_use_af(AF_INET6);
5727c478bd9Sstevel@tonic-gate 			if (!ipv6_present) {
5737c478bd9Sstevel@tonic-gate 				++(nconf_handlep->nc_curr);
5747c478bd9Sstevel@tonic-gate 				continue;
5757c478bd9Sstevel@tonic-gate 			}
5767c478bd9Sstevel@tonic-gate 		}
5777c478bd9Sstevel@tonic-gate 		break;
5787c478bd9Sstevel@tonic-gate 	}
5797c478bd9Sstevel@tonic-gate 	if (retp) {
5807c478bd9Sstevel@tonic-gate 		++(nconf_handlep->nc_curr);
5817c478bd9Sstevel@tonic-gate 		nc_error = NC_NOERROR;
5827c478bd9Sstevel@tonic-gate 	} else {
5837c478bd9Sstevel@tonic-gate 		nc_error = NC_NOMOREENTRIES;
5847c478bd9Sstevel@tonic-gate 	}
5857c478bd9Sstevel@tonic-gate 
5867c478bd9Sstevel@tonic-gate 	return (retp);
5877c478bd9Sstevel@tonic-gate }
5887c478bd9Sstevel@tonic-gate 
5897c478bd9Sstevel@tonic-gate /*
5907c478bd9Sstevel@tonic-gate  *	blank() returns true if the line is a blank line, 0 otherwise
5917c478bd9Sstevel@tonic-gate  */
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate static int
blank(char * cp)59461961e0fSrobinson blank(char *cp)
5957c478bd9Sstevel@tonic-gate {
5967c478bd9Sstevel@tonic-gate 	while (*cp && isspace(*cp)) {
5977c478bd9Sstevel@tonic-gate 		cp++;
5987c478bd9Sstevel@tonic-gate 	}
5997c478bd9Sstevel@tonic-gate 	return (*cp == '\0');
6007c478bd9Sstevel@tonic-gate }
6017c478bd9Sstevel@tonic-gate 
6027c478bd9Sstevel@tonic-gate /*
6037c478bd9Sstevel@tonic-gate  *	comment() returns true if the line is a comment, 0 otherwise.
6047c478bd9Sstevel@tonic-gate  */
6057c478bd9Sstevel@tonic-gate 
6067c478bd9Sstevel@tonic-gate static int
comment(char * cp)60761961e0fSrobinson comment(char *cp)
6087c478bd9Sstevel@tonic-gate {
6097c478bd9Sstevel@tonic-gate 	while (*cp && isspace(*cp)) {
6107c478bd9Sstevel@tonic-gate 		cp++;
6117c478bd9Sstevel@tonic-gate 	}
6127c478bd9Sstevel@tonic-gate 	return (*cp == '#');
6137c478bd9Sstevel@tonic-gate }
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate /*
6167c478bd9Sstevel@tonic-gate  *	getvalue() searches for the given string in the given array,
6177c478bd9Sstevel@tonic-gate  *	and return the integer value associated with the string.
6187c478bd9Sstevel@tonic-gate  */
6197c478bd9Sstevel@tonic-gate 
6207c478bd9Sstevel@tonic-gate static unsigned int
getvalue(char * cp,struct nc_data nc_data[])62161961e0fSrobinson getvalue(char *cp, struct nc_data nc_data[])
6227c478bd9Sstevel@tonic-gate {
6237c478bd9Sstevel@tonic-gate 	int i;	/* used to index through the given struct nc_data array */
6247c478bd9Sstevel@tonic-gate 
6257c478bd9Sstevel@tonic-gate 	for (i = 0; nc_data[i].string; i++) {
6267c478bd9Sstevel@tonic-gate 		if (strcmp(nc_data[i].string, cp) == 0) {
6277c478bd9Sstevel@tonic-gate 			break;
6287c478bd9Sstevel@tonic-gate 		}
6297c478bd9Sstevel@tonic-gate 	}
6307c478bd9Sstevel@tonic-gate 	return (nc_data[i].value);
6317c478bd9Sstevel@tonic-gate }
6327c478bd9Sstevel@tonic-gate 
6337c478bd9Sstevel@tonic-gate /*
6347c478bd9Sstevel@tonic-gate  *	getflag() creates a bitmap of the one-character flags in
6357c478bd9Sstevel@tonic-gate  *	the given string.  It uses nc_flags array to get the values.
6367c478bd9Sstevel@tonic-gate  */
6377c478bd9Sstevel@tonic-gate 
6387c478bd9Sstevel@tonic-gate static unsigned int
getflag(char * cp)63961961e0fSrobinson getflag(char *cp)
6407c478bd9Sstevel@tonic-gate {
6417c478bd9Sstevel@tonic-gate 	int i;			/* indexs through the nc_flag array */
6427c478bd9Sstevel@tonic-gate 	unsigned int mask = 0; /* holds bitmask of flags */
6437c478bd9Sstevel@tonic-gate 
6447c478bd9Sstevel@tonic-gate 	while (*cp) {
6457c478bd9Sstevel@tonic-gate 		for (i = 0; nc_flag[i].string; i++) {
6467c478bd9Sstevel@tonic-gate 			if (*nc_flag[i].string == *cp) {
6477c478bd9Sstevel@tonic-gate 				mask |= nc_flag[i].value;
6487c478bd9Sstevel@tonic-gate 				break;
6497c478bd9Sstevel@tonic-gate 			}
6507c478bd9Sstevel@tonic-gate 		}
6517c478bd9Sstevel@tonic-gate 		cp++;
6527c478bd9Sstevel@tonic-gate 	}
6537c478bd9Sstevel@tonic-gate 	return (mask);
6547c478bd9Sstevel@tonic-gate }
6557c478bd9Sstevel@tonic-gate 
6567c478bd9Sstevel@tonic-gate /*
6577c478bd9Sstevel@tonic-gate  *	getlookups() creates and returns an array of string representing
6587c478bd9Sstevel@tonic-gate  *	the directory lookup libraries, given as a comma-seperated list
6597c478bd9Sstevel@tonic-gate  *	in the argument "cp".
6607c478bd9Sstevel@tonic-gate  */
6617c478bd9Sstevel@tonic-gate 
6627c478bd9Sstevel@tonic-gate static char **
getlookups(char * cp)66361961e0fSrobinson getlookups(char *cp)
6647c478bd9Sstevel@tonic-gate {
6657c478bd9Sstevel@tonic-gate 	unsigned int num;	/* holds the number of entries in the list   */
6667c478bd9Sstevel@tonic-gate 	char **listpp;		/* the beginning of the list of dir routines */
6677c478bd9Sstevel@tonic-gate 	char **tpp;		/* traverses the list, populating it */
6687c478bd9Sstevel@tonic-gate 	char *start;
6697c478bd9Sstevel@tonic-gate 
6707c478bd9Sstevel@tonic-gate 	num = getnlookups(cp);
67161961e0fSrobinson 	if (num == 0)
6727c478bd9Sstevel@tonic-gate 		return (NULL);
67361961e0fSrobinson 	if ((listpp = malloc((num + 1) * sizeof (char *))) == NULL)
6747c478bd9Sstevel@tonic-gate 		return (NULL);
6757c478bd9Sstevel@tonic-gate 
6767c478bd9Sstevel@tonic-gate 	tpp = listpp;
6777c478bd9Sstevel@tonic-gate 	while (num--) {
6787c478bd9Sstevel@tonic-gate 		start  = cp;
6797c478bd9Sstevel@tonic-gate 
6807c478bd9Sstevel@tonic-gate 		/*
6817c478bd9Sstevel@tonic-gate 		 *	Traverse the string looking for the next entry
6827c478bd9Sstevel@tonic-gate 		 *	of the list (i.e, where the ',' or end of the
6837c478bd9Sstevel@tonic-gate 		 *	string appears).  If a "\" is found, shift the
6847c478bd9Sstevel@tonic-gate 		 *	token over 1 to the left (taking the next char
6857c478bd9Sstevel@tonic-gate 		 *	literally).
6867c478bd9Sstevel@tonic-gate 		 */
6877c478bd9Sstevel@tonic-gate 
6887c478bd9Sstevel@tonic-gate 		while (*cp && *cp != ',') {
6897c478bd9Sstevel@tonic-gate 			if (*cp == '\\' && *(cp + 1)) {
6907c478bd9Sstevel@tonic-gate 				shift1left(cp);
6917c478bd9Sstevel@tonic-gate 			}
6927c478bd9Sstevel@tonic-gate 			cp++;
6937c478bd9Sstevel@tonic-gate 		}
6947c478bd9Sstevel@tonic-gate 		if (*cp)
6957c478bd9Sstevel@tonic-gate 			*cp++ = '\0';
6967c478bd9Sstevel@tonic-gate 		if ((*tpp++ = strdup(start)) == NULL) {
6977c478bd9Sstevel@tonic-gate 			for (tpp = listpp; *tpp; tpp++)
6987c478bd9Sstevel@tonic-gate 				free(*tpp);
6997c478bd9Sstevel@tonic-gate 			free(listpp);
7007c478bd9Sstevel@tonic-gate 			return (NULL);
7017c478bd9Sstevel@tonic-gate 		}
7027c478bd9Sstevel@tonic-gate 	}
7037c478bd9Sstevel@tonic-gate 	*tpp = NULL;
7047c478bd9Sstevel@tonic-gate 	return (listpp);
7057c478bd9Sstevel@tonic-gate }
7067c478bd9Sstevel@tonic-gate 
7077c478bd9Sstevel@tonic-gate /*
7087c478bd9Sstevel@tonic-gate  *	getnlookups() returns the number of entries in a comma-separated
7097c478bd9Sstevel@tonic-gate  *	string of tokens.  A "-" means no strings are present.
7107c478bd9Sstevel@tonic-gate  */
7117c478bd9Sstevel@tonic-gate 
7127c478bd9Sstevel@tonic-gate static unsigned int
getnlookups(char * cp)71361961e0fSrobinson getnlookups(char *cp)
7147c478bd9Sstevel@tonic-gate {
7157c478bd9Sstevel@tonic-gate 	unsigned int count;	/* the number of tokens in the string */
7167c478bd9Sstevel@tonic-gate 
71761961e0fSrobinson 	if (strcmp(cp, "-") == 0)
7187c478bd9Sstevel@tonic-gate 		return (0);
7197c478bd9Sstevel@tonic-gate 
7207c478bd9Sstevel@tonic-gate 	count = 1;
7217c478bd9Sstevel@tonic-gate 	while (*cp) {
7227c478bd9Sstevel@tonic-gate 		if (*cp == ',') {
7237c478bd9Sstevel@tonic-gate 			count++;
7247c478bd9Sstevel@tonic-gate 		}
7257c478bd9Sstevel@tonic-gate 
7267c478bd9Sstevel@tonic-gate 		/*
7277c478bd9Sstevel@tonic-gate 		 *	If a "\" is in the string, take the next character
7287c478bd9Sstevel@tonic-gate 		 *	literally.  Onlly skip the character if "\" is
7297c478bd9Sstevel@tonic-gate 		 *	not the last character of the token.
7307c478bd9Sstevel@tonic-gate 		 */
7317c478bd9Sstevel@tonic-gate 		if (*cp == '\\' && *(cp + 1)) {
7327c478bd9Sstevel@tonic-gate 			cp++;
7337c478bd9Sstevel@tonic-gate 		}
7347c478bd9Sstevel@tonic-gate 		cp++;
7357c478bd9Sstevel@tonic-gate 	}
7367c478bd9Sstevel@tonic-gate 	return (count);
7377c478bd9Sstevel@tonic-gate }
7387c478bd9Sstevel@tonic-gate 
7397c478bd9Sstevel@tonic-gate /*
7407c478bd9Sstevel@tonic-gate  *	gettoken() behaves much like strtok(), except that
7417c478bd9Sstevel@tonic-gate  *	it knows about escaped space characters (i.e., space characters
7427c478bd9Sstevel@tonic-gate  *	preceeded by a '\' are taken literally).
7437c478bd9Sstevel@tonic-gate  */
7447c478bd9Sstevel@tonic-gate 
7457c478bd9Sstevel@tonic-gate static char *
gettoken(char * cp,int skip)74661961e0fSrobinson gettoken(char *cp, int skip)
7477c478bd9Sstevel@tonic-gate {
7487c478bd9Sstevel@tonic-gate 	static char	*savep;	/* the place where we left off    */
7497c478bd9Sstevel@tonic-gate 	char	*p;		/* the beginning of the new token */
7507c478bd9Sstevel@tonic-gate 	char	*retp;		/* the token to be returned	  */
7517c478bd9Sstevel@tonic-gate 
7527c478bd9Sstevel@tonic-gate 	fieldnum++;
7537c478bd9Sstevel@tonic-gate 
7547c478bd9Sstevel@tonic-gate 	/* Determine if first or subsequent call  */
7557c478bd9Sstevel@tonic-gate 	p = (cp == NULL)? savep: cp;
7567c478bd9Sstevel@tonic-gate 
7577c478bd9Sstevel@tonic-gate 	/* Return if no tokens remain.  */
75861961e0fSrobinson 	if (p == 0)
7597c478bd9Sstevel@tonic-gate 		return (NULL);
7607c478bd9Sstevel@tonic-gate 
7617c478bd9Sstevel@tonic-gate 	while (isspace(*p))
7627c478bd9Sstevel@tonic-gate 		p++;
7637c478bd9Sstevel@tonic-gate 
76461961e0fSrobinson 	if (*p == '\0')
7657c478bd9Sstevel@tonic-gate 		return (NULL);
7667c478bd9Sstevel@tonic-gate 
7677c478bd9Sstevel@tonic-gate 	/*
7687c478bd9Sstevel@tonic-gate 	 *	Save the location of the token and then skip past it
7697c478bd9Sstevel@tonic-gate 	 */
7707c478bd9Sstevel@tonic-gate 
7717c478bd9Sstevel@tonic-gate 	retp = p;
7727c478bd9Sstevel@tonic-gate 	while (*p) {
7737c478bd9Sstevel@tonic-gate 		if (isspace(*p))
7747c478bd9Sstevel@tonic-gate 			if (skip == TRUE) {
7757c478bd9Sstevel@tonic-gate 				shift1left(p);
7767c478bd9Sstevel@tonic-gate 				continue;
7777c478bd9Sstevel@tonic-gate 			} else
7787c478bd9Sstevel@tonic-gate 				break;
7797c478bd9Sstevel@tonic-gate 		/*
7807c478bd9Sstevel@tonic-gate 		 *	Only process the escape of the space seperator;
7817c478bd9Sstevel@tonic-gate 		 *	since the token may contain other separators,
7827c478bd9Sstevel@tonic-gate 		 *	let the other routines handle the escape of
7837c478bd9Sstevel@tonic-gate 		 *	specific characters in the token.
7847c478bd9Sstevel@tonic-gate 		 */
7857c478bd9Sstevel@tonic-gate 
7867c478bd9Sstevel@tonic-gate 		if (*p == '\\' && *(p + 1) != '\n' && isspace(*(p + 1))) {
7877c478bd9Sstevel@tonic-gate 			shift1left(p);
7887c478bd9Sstevel@tonic-gate 		}
7897c478bd9Sstevel@tonic-gate 		p++;
7907c478bd9Sstevel@tonic-gate 	}
7917c478bd9Sstevel@tonic-gate 	if (*p == '\0') {
7927c478bd9Sstevel@tonic-gate 		savep = 0;	/* indicate this is last token */
7937c478bd9Sstevel@tonic-gate 	} else {
7947c478bd9Sstevel@tonic-gate 		*p = '\0';
7957c478bd9Sstevel@tonic-gate 		savep = ++p;
7967c478bd9Sstevel@tonic-gate 	}
7977c478bd9Sstevel@tonic-gate 	return (strdup(retp));
7987c478bd9Sstevel@tonic-gate }
7997c478bd9Sstevel@tonic-gate 
8007c478bd9Sstevel@tonic-gate /*
8017c478bd9Sstevel@tonic-gate  *	shift1left() moves all characters in the string over 1 to
8027c478bd9Sstevel@tonic-gate  *	the left.
8037c478bd9Sstevel@tonic-gate  */
8047c478bd9Sstevel@tonic-gate 
8057c478bd9Sstevel@tonic-gate static void
shift1left(char * p)80661961e0fSrobinson shift1left(char *p)
8077c478bd9Sstevel@tonic-gate {
8087c478bd9Sstevel@tonic-gate 	for (; *p; p++)
8097c478bd9Sstevel@tonic-gate 		*p = *(p + 1);
8107c478bd9Sstevel@tonic-gate }
8117c478bd9Sstevel@tonic-gate 
8127c478bd9Sstevel@tonic-gate char *
nc_sperror(void)81361961e0fSrobinson nc_sperror(void)
8147c478bd9Sstevel@tonic-gate {
8157c478bd9Sstevel@tonic-gate 	static char buf_main[BUFSIZ];
816cb620785Sraf 	static pthread_key_t perror_key = PTHREAD_ONCE_KEY_NP;
8177c478bd9Sstevel@tonic-gate 	char *retstr = thr_main()?
8187c478bd9Sstevel@tonic-gate 		buf_main :
8197c478bd9Sstevel@tonic-gate 		thr_get_storage(&perror_key, BUFSIZ, free);
8207c478bd9Sstevel@tonic-gate 
8217c478bd9Sstevel@tonic-gate 	if (retstr == NULL) {
8227c478bd9Sstevel@tonic-gate 		syslog(LOG_WARNING,
8237c478bd9Sstevel@tonic-gate 		"nc_sperror: malloc failed when trying to create buffer\n");
8247c478bd9Sstevel@tonic-gate 		return (NULL);
8257c478bd9Sstevel@tonic-gate 	}
8267c478bd9Sstevel@tonic-gate 
8277c478bd9Sstevel@tonic-gate 	switch (nc_error) {
8287c478bd9Sstevel@tonic-gate 	case NC_NOERROR:
8297c478bd9Sstevel@tonic-gate 		(void) strlcpy(retstr, dgettext(__nsl_dom, "no error"), BUFSIZ);
8307c478bd9Sstevel@tonic-gate 		break;
8317c478bd9Sstevel@tonic-gate 	case NC_NOMEM:
8327c478bd9Sstevel@tonic-gate 		(void) strlcpy(retstr, dgettext(__nsl_dom, "out of memory"),
8337c478bd9Sstevel@tonic-gate 		    BUFSIZ);
8347c478bd9Sstevel@tonic-gate 		break;
8357c478bd9Sstevel@tonic-gate 	case NC_NOSET:
8367c478bd9Sstevel@tonic-gate 		(void) strlcpy(retstr, dgettext(__nsl_dom,
8377c478bd9Sstevel@tonic-gate 		    "routine called before calling \
8387c478bd9Sstevel@tonic-gate 		    setnetpath() or setnetconfig()"), BUFSIZ);
8397c478bd9Sstevel@tonic-gate 		break;
8407c478bd9Sstevel@tonic-gate 	case NC_OPENFAIL:
8417c478bd9Sstevel@tonic-gate 		(void) strlcpy(retstr,
8427c478bd9Sstevel@tonic-gate 			dgettext(__nsl_dom, "cannot open /etc/netconfig"),
8437c478bd9Sstevel@tonic-gate 			BUFSIZ);
8447c478bd9Sstevel@tonic-gate 		break;
8457c478bd9Sstevel@tonic-gate 	case NC_BADLINE:
8467c478bd9Sstevel@tonic-gate 		(void) snprintf(retstr, BUFSIZ, dgettext(__nsl_dom,
8477c478bd9Sstevel@tonic-gate 			"error in /etc/netconfig: field %d of line %d\n"),
8487c478bd9Sstevel@tonic-gate 				fieldnum, linenum);
8497c478bd9Sstevel@tonic-gate 		break;
8507c478bd9Sstevel@tonic-gate 	case NC_NOTFOUND:
8517c478bd9Sstevel@tonic-gate 		(void) snprintf(retstr, BUFSIZ,
8527c478bd9Sstevel@tonic-gate 			dgettext(__nsl_dom,
8537c478bd9Sstevel@tonic-gate 				"netid not found in /etc/netconfig"));
8547c478bd9Sstevel@tonic-gate 		break;
8557c478bd9Sstevel@tonic-gate 	case NC_NOMOREENTRIES:
8567c478bd9Sstevel@tonic-gate 		(void) snprintf(retstr, BUFSIZ,
8577c478bd9Sstevel@tonic-gate 			dgettext(__nsl_dom,
8587c478bd9Sstevel@tonic-gate 				"no more entries in /etc/netconfig"));
8597c478bd9Sstevel@tonic-gate 		break;
8607c478bd9Sstevel@tonic-gate 	default:
8617c478bd9Sstevel@tonic-gate 		(void) strlcpy(retstr, dgettext(__nsl_dom, "unknown error"),
8627c478bd9Sstevel@tonic-gate 		    BUFSIZ);
8637c478bd9Sstevel@tonic-gate 		break;
8647c478bd9Sstevel@tonic-gate 	}
8657c478bd9Sstevel@tonic-gate 	return (retstr);
8667c478bd9Sstevel@tonic-gate }
8677c478bd9Sstevel@tonic-gate 
8687c478bd9Sstevel@tonic-gate void
nc_perror(const char * string)8697c478bd9Sstevel@tonic-gate nc_perror(const char *string)
8707c478bd9Sstevel@tonic-gate {
8717c478bd9Sstevel@tonic-gate 	if (string)
87261961e0fSrobinson 		(void) fprintf(stderr, "%s: %s\n", string, nc_sperror());
8737c478bd9Sstevel@tonic-gate 	else
87461961e0fSrobinson 		(void) fprintf(stderr, "%s\n", nc_sperror());
8757c478bd9Sstevel@tonic-gate }
8767c478bd9Sstevel@tonic-gate 
8777c478bd9Sstevel@tonic-gate static void
netlist_free(struct netconfig *** netppp)87861961e0fSrobinson netlist_free(struct netconfig ***netppp)
8797c478bd9Sstevel@tonic-gate {
8807c478bd9Sstevel@tonic-gate 	struct netconfig **tpp;
8817c478bd9Sstevel@tonic-gate 
8827c478bd9Sstevel@tonic-gate 	for (tpp = *netppp; *tpp; tpp++) {
8837c478bd9Sstevel@tonic-gate 		netconfig_free(*tpp);
8847c478bd9Sstevel@tonic-gate 	}
8857c478bd9Sstevel@tonic-gate 	free(*netppp);
8867c478bd9Sstevel@tonic-gate 	*netppp = NULL;
8877c478bd9Sstevel@tonic-gate }
8887c478bd9Sstevel@tonic-gate 
8897c478bd9Sstevel@tonic-gate static void
netconfig_free(struct netconfig * netconfigp)89061961e0fSrobinson netconfig_free(struct netconfig *netconfigp)
8917c478bd9Sstevel@tonic-gate {
8927c478bd9Sstevel@tonic-gate 	int i;
8937c478bd9Sstevel@tonic-gate 
89461961e0fSrobinson 	if (netconfigp == NULL)
8957c478bd9Sstevel@tonic-gate 		return;
8967c478bd9Sstevel@tonic-gate 	free_entry(netconfigp->nc_netid);
8977c478bd9Sstevel@tonic-gate 	free_entry(netconfigp->nc_protofmly);
8987c478bd9Sstevel@tonic-gate 	free_entry(netconfigp->nc_proto);
8997c478bd9Sstevel@tonic-gate 	free_entry(netconfigp->nc_device);
9007c478bd9Sstevel@tonic-gate 	if (netconfigp->nc_lookups)
9017c478bd9Sstevel@tonic-gate 		for (i = 0; i < netconfigp->nc_nlookups; i++)
9027c478bd9Sstevel@tonic-gate 			free_entry(netconfigp->nc_lookups[i]);
9037c478bd9Sstevel@tonic-gate 	free_entry(netconfigp->nc_lookups);
9047c478bd9Sstevel@tonic-gate 	free(netconfigp);
9057c478bd9Sstevel@tonic-gate }
9067c478bd9Sstevel@tonic-gate 
9077c478bd9Sstevel@tonic-gate static struct netconfig *
netconfig_dup(struct netconfig * netconfigp)90861961e0fSrobinson netconfig_dup(struct netconfig *netconfigp)
9097c478bd9Sstevel@tonic-gate {
9107c478bd9Sstevel@tonic-gate 	struct netconfig *nconf;
9117c478bd9Sstevel@tonic-gate 	int i;
9127c478bd9Sstevel@tonic-gate 
91361961e0fSrobinson 	nconf = calloc(1, sizeof (struct netconfig));
9147c478bd9Sstevel@tonic-gate 	if (nconf == NULL) {
9157c478bd9Sstevel@tonic-gate 		nc_error = NC_NOMEM;
9167c478bd9Sstevel@tonic-gate 		return (NULL);
9177c478bd9Sstevel@tonic-gate 	}
9187c478bd9Sstevel@tonic-gate 	nconf->nc_netid = strdup(netconfigp->nc_netid);
9197c478bd9Sstevel@tonic-gate 	nconf->nc_protofmly = strdup(netconfigp->nc_protofmly);
9207c478bd9Sstevel@tonic-gate 	nconf->nc_proto = strdup(netconfigp->nc_proto);
9217c478bd9Sstevel@tonic-gate 	nconf->nc_device = strdup(netconfigp->nc_device);
92261961e0fSrobinson 	nconf->nc_lookups = malloc((netconfigp->nc_nlookups + 1)
9237c478bd9Sstevel@tonic-gate 					* sizeof (char *));
9247c478bd9Sstevel@tonic-gate 	if (!(nconf->nc_lookups && nconf->nc_netid &&
9257c478bd9Sstevel@tonic-gate 		nconf->nc_protofmly && nconf->nc_proto &&
9267c478bd9Sstevel@tonic-gate 		nconf->nc_device)) {
9277c478bd9Sstevel@tonic-gate 		nc_error = NC_NOMEM;
9287c478bd9Sstevel@tonic-gate 		netconfig_free(nconf);
9297c478bd9Sstevel@tonic-gate 		return (NULL);
9307c478bd9Sstevel@tonic-gate 	}
9317c478bd9Sstevel@tonic-gate 
9327c478bd9Sstevel@tonic-gate 	for (i = 0; i < netconfigp->nc_nlookups; i++) {
9337c478bd9Sstevel@tonic-gate 		nconf->nc_lookups[i] = strdup(netconfigp->nc_lookups[i]);
9347c478bd9Sstevel@tonic-gate 		if (nconf->nc_lookups[i] == NULL) {
9357c478bd9Sstevel@tonic-gate 			nconf->nc_nlookups = i;
9367c478bd9Sstevel@tonic-gate 			netconfig_free(nconf);
9377c478bd9Sstevel@tonic-gate 			nc_error = NC_NOMEM;
9387c478bd9Sstevel@tonic-gate 			return (NULL);
9397c478bd9Sstevel@tonic-gate 		}
9407c478bd9Sstevel@tonic-gate 	}
9417c478bd9Sstevel@tonic-gate 	nconf->nc_lookups[i] = NULL;
9427c478bd9Sstevel@tonic-gate 	nconf->nc_nlookups = netconfigp->nc_nlookups;
9437c478bd9Sstevel@tonic-gate 	nconf->nc_flag = netconfigp->nc_flag;
9447c478bd9Sstevel@tonic-gate 	nconf->nc_semantics = netconfigp->nc_semantics;
9457c478bd9Sstevel@tonic-gate 	return (nconf);
9467c478bd9Sstevel@tonic-gate }
9477c478bd9Sstevel@tonic-gate 
9487c478bd9Sstevel@tonic-gate static void
free_entry(void * foo)94961961e0fSrobinson free_entry(void *foo)
9507c478bd9Sstevel@tonic-gate {
9517c478bd9Sstevel@tonic-gate 	if (foo)
9527c478bd9Sstevel@tonic-gate 		free(foo);
9537c478bd9Sstevel@tonic-gate }
954