xref: /titanic_50/usr/src/lib/libc/port/gen/nsparse.c (revision 7257d1b4d25bfac0c802847390e98a464fd787ac)
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  */
21*7257d1b4Sraf 
227c478bd9Sstevel@tonic-gate /*
23*7257d1b4Sraf  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
287c478bd9Sstevel@tonic-gate 
29*7257d1b4Sraf #include "lint.h"
30004388ebScasper #include "file64.h"
317c478bd9Sstevel@tonic-gate #include "mtlib.h"
327c478bd9Sstevel@tonic-gate #include "libc.h"
337c478bd9Sstevel@tonic-gate #include <synch.h>
347c478bd9Sstevel@tonic-gate #include <sys/types.h>
357c478bd9Sstevel@tonic-gate #include <stdlib.h>
367c478bd9Sstevel@tonic-gate #include <stdio.h>
37004388ebScasper #include <stdio_ext.h>
387c478bd9Sstevel@tonic-gate #include <string.h>
397c478bd9Sstevel@tonic-gate #include <ctype.h>
407c478bd9Sstevel@tonic-gate #include <limits.h>
417c478bd9Sstevel@tonic-gate #include <dlfcn.h>
427c478bd9Sstevel@tonic-gate #include <errno.h>
43004388ebScasper #include "stdiom.h"
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate #define	__NSS_PRIVATE_INTERFACE
467c478bd9Sstevel@tonic-gate #include "nsswitch_priv.h"
477c478bd9Sstevel@tonic-gate #undef	__NSS_PRIVATE_INTERFACE
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate #include <syslog.h>
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate #define	islabel(c) 	(isalnum(c) || (c) == '_')
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate #define	LIBC_STRDUP(new, existing) \
547c478bd9Sstevel@tonic-gate 	if ((new = libc_strdup(existing)) == NULL) { \
557c478bd9Sstevel@tonic-gate 		dup_fail = 1; \
567c478bd9Sstevel@tonic-gate 		goto barf_line; \
577c478bd9Sstevel@tonic-gate 	}
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate /*
607c478bd9Sstevel@tonic-gate  * This file has all the routines that access the configuration
617c478bd9Sstevel@tonic-gate  * information.
627c478bd9Sstevel@tonic-gate  */
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate struct cons_cell_v1 { /* private to the parser */
657c478bd9Sstevel@tonic-gate 	struct __nsw_switchconfig_v1 *sw;
667c478bd9Sstevel@tonic-gate 	struct cons_cell_v1 *next;
677c478bd9Sstevel@tonic-gate };
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate struct cons_cell { /* private to the parser */
707c478bd9Sstevel@tonic-gate 	struct __nsw_switchconfig *sw;
717c478bd9Sstevel@tonic-gate 	struct cons_cell *next;
727c478bd9Sstevel@tonic-gate };
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate /*
757c478bd9Sstevel@tonic-gate  * Local routines
767c478bd9Sstevel@tonic-gate  */
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate static char *skip(char **, char);
797c478bd9Sstevel@tonic-gate static char *labelskip(char *);
807c478bd9Sstevel@tonic-gate static char *spaceskip(char *);
817c478bd9Sstevel@tonic-gate static struct __nsw_switchconfig_v1 *scrounge_cache_v1(const char *);
827c478bd9Sstevel@tonic-gate static struct __nsw_switchconfig *scrounge_cache(const char *);
837c478bd9Sstevel@tonic-gate static int add_concell_v1(struct __nsw_switchconfig_v1 *);
847c478bd9Sstevel@tonic-gate static int add_concell(struct __nsw_switchconfig *);
857c478bd9Sstevel@tonic-gate static void freeconf_v1(struct __nsw_switchconfig_v1 *);
867c478bd9Sstevel@tonic-gate static void freeconf(struct __nsw_switchconfig *);
877c478bd9Sstevel@tonic-gate static int alldigits(char *);
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate static struct cons_cell_v1 *concell_list_v1; /* stays with add_concell() */
907c478bd9Sstevel@tonic-gate static struct cons_cell *concell_list; /* stays with add_concell() */
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate /*
937c478bd9Sstevel@tonic-gate  *
947c478bd9Sstevel@tonic-gate  * With the "lookup control" feature, the default criteria for NIS, NIS+,
957c478bd9Sstevel@tonic-gate  * and any new services (e.g. ldap) will be:
967c478bd9Sstevel@tonic-gate  *     [SUCCESS=return  NOTFOUND=continue UNAVAIL=continue TRYAGAIN=forever]
977c478bd9Sstevel@tonic-gate  *
987c478bd9Sstevel@tonic-gate  * For backward compat, NIS via NIS server in DNS forwarding mode will be:
997c478bd9Sstevel@tonic-gate  *     [SUCCESS=return  NOTFOUND=continue UNAVAIL=continue TRYAGAIN=continue]
1007c478bd9Sstevel@tonic-gate  *
1017c478bd9Sstevel@tonic-gate  * And also for backward compat, the default criteria for DNS will be:
1027c478bd9Sstevel@tonic-gate  *     [SUCCESS=return  NOTFOUND=continue UNAVAIL=continue TRYAGAIN=continue]
1037c478bd9Sstevel@tonic-gate  */
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate /*
1087c478bd9Sstevel@tonic-gate  * The BIND resolver normally will retry several times on server non-response.
1097c478bd9Sstevel@tonic-gate  * But now with the "lookup control" feature, we don't want the resolver doing
1107c478bd9Sstevel@tonic-gate  * many retries, rather we want it to return control (reasonably) quickly back
1117c478bd9Sstevel@tonic-gate  * to the switch engine.  However, when TRYAGAIN=N or TRYAGAIN=forever is
1127c478bd9Sstevel@tonic-gate  * not explicitly set by the admin in the conf file, we want the old "resolver
1137c478bd9Sstevel@tonic-gate  * retry a few times" rather than no retries at all.
1147c478bd9Sstevel@tonic-gate  */
1157c478bd9Sstevel@tonic-gate static int 	dns_tryagain_retry = 3;
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate /*
1187c478bd9Sstevel@tonic-gate  * For backward compat (pre "lookup control"), the dns default behavior is
1197c478bd9Sstevel@tonic-gate  * soft lookup.
1207c478bd9Sstevel@tonic-gate  */
1217c478bd9Sstevel@tonic-gate static void
set_dns_default_lkp(struct __nsw_lookup_v1 * lkp)1227c478bd9Sstevel@tonic-gate set_dns_default_lkp(struct __nsw_lookup_v1 *lkp)
1237c478bd9Sstevel@tonic-gate {
1247c478bd9Sstevel@tonic-gate 	if (strcasecmp(lkp->service_name, "dns") == 0) {
125*7257d1b4Sraf 		lkp->actions[__NSW_TRYAGAIN] = __NSW_TRYAGAIN_NTIMES;
1267c478bd9Sstevel@tonic-gate 		lkp->max_retries = dns_tryagain_retry;
1277c478bd9Sstevel@tonic-gate 	}
1287c478bd9Sstevel@tonic-gate }
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate /*
1317c478bd9Sstevel@tonic-gate  * Private interface used by nss_common.c, hence this function is not static
1327c478bd9Sstevel@tonic-gate  */
1337c478bd9Sstevel@tonic-gate struct __nsw_switchconfig_v1 *
_nsw_getoneconfig_v1(const char * name,char * linep,enum __nsw_parse_err * errp)1347c478bd9Sstevel@tonic-gate _nsw_getoneconfig_v1(const char *name, char *linep, enum __nsw_parse_err *errp)
1357c478bd9Sstevel@tonic-gate 	/* linep   Nota Bene: not const char *	*/
1367c478bd9Sstevel@tonic-gate 	/* errp  Meanings are abused a bit	*/
1377c478bd9Sstevel@tonic-gate {
1387c478bd9Sstevel@tonic-gate 	struct __nsw_switchconfig_v1 *cfp;
1397c478bd9Sstevel@tonic-gate 	struct __nsw_lookup_v1 *lkp, **lkq;
1407c478bd9Sstevel@tonic-gate 	int end_crit, dup_fail = 0;
1417c478bd9Sstevel@tonic-gate 	action_t act;
1427c478bd9Sstevel@tonic-gate 	char *p, *tokenp;
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 	*errp = __NSW_CONF_PARSE_SUCCESS;
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 	if ((cfp = libc_malloc(sizeof (struct __nsw_switchconfig_v1)))
1477c478bd9Sstevel@tonic-gate 	    == NULL) {
1487c478bd9Sstevel@tonic-gate 		*errp = __NSW_CONF_PARSE_SYSERR;
1497c478bd9Sstevel@tonic-gate 		return (NULL);
1507c478bd9Sstevel@tonic-gate 	}
1517c478bd9Sstevel@tonic-gate 	LIBC_STRDUP(cfp->dbase, name);
1527c478bd9Sstevel@tonic-gate 	lkq = &cfp->lookups;
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 	/* linep points to a naming service name */
1557c478bd9Sstevel@tonic-gate 	for (;;) {
1567c478bd9Sstevel@tonic-gate 		int i;
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 		/* white space following the last service */
1597c478bd9Sstevel@tonic-gate 		if (*linep == '\0' || *linep == '\n') {
1607c478bd9Sstevel@tonic-gate 			return (cfp);
1617c478bd9Sstevel@tonic-gate 		}
1627c478bd9Sstevel@tonic-gate 		if ((lkp = libc_malloc(sizeof (struct __nsw_lookup_v1)))
1637c478bd9Sstevel@tonic-gate 		    == NULL) {
1647c478bd9Sstevel@tonic-gate 			*errp = __NSW_CONF_PARSE_SYSERR;
1657c478bd9Sstevel@tonic-gate 			freeconf_v1(cfp);
1667c478bd9Sstevel@tonic-gate 			return (NULL);
1677c478bd9Sstevel@tonic-gate 		}
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate 		*lkq = lkp;
1707c478bd9Sstevel@tonic-gate 		lkq = &lkp->next;
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate 		for (i = 0; i < __NSW_STD_ERRS_V1; i++)
1737c478bd9Sstevel@tonic-gate 			if (i == __NSW_SUCCESS)
1747c478bd9Sstevel@tonic-gate 				lkp->actions[i] = __NSW_RETURN;
1757c478bd9Sstevel@tonic-gate 			else if (i == __NSW_TRYAGAIN)
1767c478bd9Sstevel@tonic-gate 				lkp->actions[i] = __NSW_TRYAGAIN_FOREVER;
1777c478bd9Sstevel@tonic-gate 			else
1787c478bd9Sstevel@tonic-gate 				lkp->actions[i] = __NSW_CONTINUE;
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 		/* get criteria for the naming service */
1817c478bd9Sstevel@tonic-gate 		if (tokenp = skip(&linep, '[')) { /* got criteria */
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate 			/* premature end, illegal char following [ */
1847c478bd9Sstevel@tonic-gate 			if (!islabel(*linep))
1857c478bd9Sstevel@tonic-gate 				goto barf_line;
1867c478bd9Sstevel@tonic-gate 			LIBC_STRDUP(lkp->service_name, tokenp);
1877c478bd9Sstevel@tonic-gate 			cfp->num_lookups++;
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate 			set_dns_default_lkp(lkp);
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate 			end_crit = 0;
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate 			/* linep points to a switch_err */
1947c478bd9Sstevel@tonic-gate 			for (;;) {
1957c478bd9Sstevel@tonic-gate 				int ntimes = 0; /* try again max N times */
1967c478bd9Sstevel@tonic-gate 				int dns_continue = 0;
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 				if ((tokenp = skip(&linep, '=')) == NULL) {
1997c478bd9Sstevel@tonic-gate 					goto barf_line;
2007c478bd9Sstevel@tonic-gate 				}
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate 				/* premature end, ill char following = */
2037c478bd9Sstevel@tonic-gate 				if (!islabel(*linep))
2047c478bd9Sstevel@tonic-gate 					goto barf_line;
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 				/* linep points to the string following '=' */
2077c478bd9Sstevel@tonic-gate 				p = labelskip(linep);
2087c478bd9Sstevel@tonic-gate 				if (*p == ']')
2097c478bd9Sstevel@tonic-gate 					end_crit = 1;
2107c478bd9Sstevel@tonic-gate 				else if (*p != ' ' && *p != '\t')
2117c478bd9Sstevel@tonic-gate 					goto barf_line;
2127c478bd9Sstevel@tonic-gate 				*p++ = '\0'; /* null terminate linep */
2137c478bd9Sstevel@tonic-gate 				p = spaceskip(p);
2147c478bd9Sstevel@tonic-gate 				if (!end_crit) {
2157c478bd9Sstevel@tonic-gate 					if (*p == ']') {
2167c478bd9Sstevel@tonic-gate 					end_crit = 1;
2177c478bd9Sstevel@tonic-gate 					*p++ = '\0';
2187c478bd9Sstevel@tonic-gate 					} else if (*p == '\0' || *p == '\n') {
2197c478bd9Sstevel@tonic-gate 						return (cfp);
2207c478bd9Sstevel@tonic-gate 					} else if (!islabel(*p))
2217c478bd9Sstevel@tonic-gate 					/* p better be the next switch_err */
2227c478bd9Sstevel@tonic-gate 						goto barf_line;
2237c478bd9Sstevel@tonic-gate 				}
2247c478bd9Sstevel@tonic-gate 				if (strcasecmp(linep, __NSW_STR_RETURN) == 0)
2257c478bd9Sstevel@tonic-gate 					act = __NSW_RETURN;
2267c478bd9Sstevel@tonic-gate 				else if (strcasecmp(linep,
2277c478bd9Sstevel@tonic-gate 						    __NSW_STR_CONTINUE) == 0) {
2287c478bd9Sstevel@tonic-gate 					if (strcasecmp(lkp->service_name,
2297c478bd9Sstevel@tonic-gate 						    "dns") == 0 &&
2307c478bd9Sstevel@tonic-gate 						strcasecmp(tokenp,
2317c478bd9Sstevel@tonic-gate 							__NSW_STR_TRYAGAIN)
2327c478bd9Sstevel@tonic-gate 							== 0) {
2337c478bd9Sstevel@tonic-gate 						/*
2347c478bd9Sstevel@tonic-gate 						 * Add one more condition
2357c478bd9Sstevel@tonic-gate 						 * so it retries only if it's
2367c478bd9Sstevel@tonic-gate 						 * "dns [TRYAGAIN=continue]"
2377c478bd9Sstevel@tonic-gate 						 */
2387c478bd9Sstevel@tonic-gate 						dns_continue = 1;
2397c478bd9Sstevel@tonic-gate 						act = __NSW_TRYAGAIN_NTIMES;
2407c478bd9Sstevel@tonic-gate 					} else
2417c478bd9Sstevel@tonic-gate 						act = __NSW_CONTINUE;
2427c478bd9Sstevel@tonic-gate 				} else if (strcasecmp(linep,
2437c478bd9Sstevel@tonic-gate 					    __NSW_STR_FOREVER) == 0)
2447c478bd9Sstevel@tonic-gate 					act = __NSW_TRYAGAIN_FOREVER;
2457c478bd9Sstevel@tonic-gate 				else if (alldigits(linep)) {
2467c478bd9Sstevel@tonic-gate 					act = __NSW_TRYAGAIN_NTIMES;
2477c478bd9Sstevel@tonic-gate 					ntimes = atoi(linep);
2487c478bd9Sstevel@tonic-gate 					if (ntimes < 0 || ntimes > INT_MAX)
2497c478bd9Sstevel@tonic-gate 						ntimes = 0;
2507c478bd9Sstevel@tonic-gate 				}
2517c478bd9Sstevel@tonic-gate 				else
2527c478bd9Sstevel@tonic-gate 					goto barf_line;
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate 				if (__NSW_SUCCESS_ACTION(act) &&
2557c478bd9Sstevel@tonic-gate 				    strcasecmp(tokenp,
2567c478bd9Sstevel@tonic-gate 					    __NSW_STR_SUCCESS) == 0) {
2577c478bd9Sstevel@tonic-gate 					lkp->actions[__NSW_SUCCESS] = act;
2587c478bd9Sstevel@tonic-gate 				} else if (__NSW_NOTFOUND_ACTION(act) &&
2597c478bd9Sstevel@tonic-gate 					strcasecmp(tokenp,
2607c478bd9Sstevel@tonic-gate 					    __NSW_STR_NOTFOUND) == 0) {
2617c478bd9Sstevel@tonic-gate 					lkp->actions[__NSW_NOTFOUND] = act;
2627c478bd9Sstevel@tonic-gate 				} else if (__NSW_UNAVAIL_ACTION(act) &&
2637c478bd9Sstevel@tonic-gate 					strcasecmp(tokenp,
2647c478bd9Sstevel@tonic-gate 					    __NSW_STR_UNAVAIL) == 0) {
2657c478bd9Sstevel@tonic-gate 					lkp->actions[__NSW_UNAVAIL] = act;
2667c478bd9Sstevel@tonic-gate 				} else if (__NSW_TRYAGAIN_ACTION(act) &&
2677c478bd9Sstevel@tonic-gate 					strcasecmp(tokenp,
2687c478bd9Sstevel@tonic-gate 					    __NSW_STR_TRYAGAIN) == 0) {
2697c478bd9Sstevel@tonic-gate 					lkp->actions[__NSW_TRYAGAIN] = act;
2707c478bd9Sstevel@tonic-gate 					if (strcasecmp(lkp->service_name,
2717c478bd9Sstevel@tonic-gate 						    "nis") == 0)
2727c478bd9Sstevel@tonic-gate 						lkp->actions[
2737c478bd9Sstevel@tonic-gate 						    __NSW_NISSERVDNS_TRYAGAIN]
2747c478bd9Sstevel@tonic-gate 						    = act;
2757c478bd9Sstevel@tonic-gate 					if (act == __NSW_TRYAGAIN_NTIMES)
2767c478bd9Sstevel@tonic-gate 						lkp->max_retries =
2777c478bd9Sstevel@tonic-gate 						dns_continue ?
2787c478bd9Sstevel@tonic-gate 						dns_tryagain_retry : ntimes;
2797c478bd9Sstevel@tonic-gate 				} else {
2807c478bd9Sstevel@tonic-gate 					/*EMPTY*/
2817c478bd9Sstevel@tonic-gate 					/*
2827c478bd9Sstevel@tonic-gate 					 * convert string tokenp to integer
2837c478bd9Sstevel@tonic-gate 					 * and put in long_errs
2847c478bd9Sstevel@tonic-gate 					 */
2857c478bd9Sstevel@tonic-gate 				}
2867c478bd9Sstevel@tonic-gate 				if (end_crit) {
2877c478bd9Sstevel@tonic-gate 					linep = spaceskip(p);
2887c478bd9Sstevel@tonic-gate 					if (*linep == '\0' || *linep == '\n')
2897c478bd9Sstevel@tonic-gate 						return (cfp);
2907c478bd9Sstevel@tonic-gate 					break; /* process next naming service */
2917c478bd9Sstevel@tonic-gate 				}
2927c478bd9Sstevel@tonic-gate 				linep = p;
2937c478bd9Sstevel@tonic-gate 			} /* end of while loop for a name service's criteria */
2947c478bd9Sstevel@tonic-gate 		} else {
2957c478bd9Sstevel@tonic-gate 			/*
2967c478bd9Sstevel@tonic-gate 			 * no criteria for this naming service.
2977c478bd9Sstevel@tonic-gate 			 * linep points to name service, but not null
2987c478bd9Sstevel@tonic-gate 			 * terminated.
2997c478bd9Sstevel@tonic-gate 			 */
3007c478bd9Sstevel@tonic-gate 			p = labelskip(linep);
3017c478bd9Sstevel@tonic-gate 			if (*p == '\0' || *p == '\n') {
3027c478bd9Sstevel@tonic-gate 				*p = '\0';
3037c478bd9Sstevel@tonic-gate 				LIBC_STRDUP(lkp->service_name, linep);
3047c478bd9Sstevel@tonic-gate 				set_dns_default_lkp(lkp);
3057c478bd9Sstevel@tonic-gate 				cfp->num_lookups++;
3067c478bd9Sstevel@tonic-gate 				return (cfp);
3077c478bd9Sstevel@tonic-gate 			}
3087c478bd9Sstevel@tonic-gate 			if (*p != ' ' && *p != '\t')
3097c478bd9Sstevel@tonic-gate 				goto barf_line;
3107c478bd9Sstevel@tonic-gate 			*p++ = '\0';
3117c478bd9Sstevel@tonic-gate 			LIBC_STRDUP(lkp->service_name, linep);
3127c478bd9Sstevel@tonic-gate 			set_dns_default_lkp(lkp);
3137c478bd9Sstevel@tonic-gate 			cfp->num_lookups++;
3147c478bd9Sstevel@tonic-gate 			linep = spaceskip(p);
3157c478bd9Sstevel@tonic-gate 		}
3167c478bd9Sstevel@tonic-gate 	} /* end of while(1) loop for a name service */
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate barf_line:
3197c478bd9Sstevel@tonic-gate 	freeconf_v1(cfp);
3207c478bd9Sstevel@tonic-gate 	*errp = dup_fail ? __NSW_CONF_PARSE_SYSERR : __NSW_CONF_PARSE_NOPOLICY;
3217c478bd9Sstevel@tonic-gate 	return (NULL);
3227c478bd9Sstevel@tonic-gate }
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate /*
3257c478bd9Sstevel@tonic-gate  * Private interface used by nss_common.c, hence this function is not static
3267c478bd9Sstevel@tonic-gate  */
3277c478bd9Sstevel@tonic-gate struct __nsw_switchconfig *
_nsw_getoneconfig(const char * name,char * linep,enum __nsw_parse_err * errp)3287c478bd9Sstevel@tonic-gate _nsw_getoneconfig(const char *name, char *linep, enum __nsw_parse_err *errp)
3297c478bd9Sstevel@tonic-gate 	/* linep   Nota Bene: not const char *	*/
3307c478bd9Sstevel@tonic-gate 	/* errp  Meanings are abused a bit	*/
3317c478bd9Sstevel@tonic-gate {
3327c478bd9Sstevel@tonic-gate 	struct __nsw_switchconfig *cfp;
3337c478bd9Sstevel@tonic-gate 	struct __nsw_lookup *lkp, **lkq;
3347c478bd9Sstevel@tonic-gate 	int end_crit, dup_fail = 0;
3357c478bd9Sstevel@tonic-gate 	action_t act;
3367c478bd9Sstevel@tonic-gate 	char *p, *tokenp;
3377c478bd9Sstevel@tonic-gate 
3387c478bd9Sstevel@tonic-gate 	*errp = __NSW_CONF_PARSE_SUCCESS;
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 	if ((cfp = libc_malloc(sizeof (struct __nsw_switchconfig)))
3417c478bd9Sstevel@tonic-gate 	    == NULL) {
3427c478bd9Sstevel@tonic-gate 		*errp = __NSW_CONF_PARSE_SYSERR;
3437c478bd9Sstevel@tonic-gate 		return (NULL);
3447c478bd9Sstevel@tonic-gate 	}
3457c478bd9Sstevel@tonic-gate 	LIBC_STRDUP(cfp->dbase, name);
3467c478bd9Sstevel@tonic-gate 	lkq = &cfp->lookups;
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 	/* linep points to a naming service name */
3497c478bd9Sstevel@tonic-gate 	for (;;) {
3507c478bd9Sstevel@tonic-gate 		int i;
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate 		/* white space following the last service */
3537c478bd9Sstevel@tonic-gate 		if (*linep == '\0' || *linep == '\n') {
3547c478bd9Sstevel@tonic-gate 			return (cfp);
3557c478bd9Sstevel@tonic-gate 		}
3567c478bd9Sstevel@tonic-gate 		if ((lkp = libc_malloc(sizeof (struct __nsw_lookup)))
3577c478bd9Sstevel@tonic-gate 		    == NULL) {
3587c478bd9Sstevel@tonic-gate 			*errp = __NSW_CONF_PARSE_SYSERR;
3597c478bd9Sstevel@tonic-gate 			freeconf(cfp);
3607c478bd9Sstevel@tonic-gate 			return (NULL);
3617c478bd9Sstevel@tonic-gate 		}
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate 		*lkq = lkp;
3647c478bd9Sstevel@tonic-gate 		lkq = &lkp->next;
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 		for (i = 0; i < __NSW_STD_ERRS; i++)
3677c478bd9Sstevel@tonic-gate 			if (i == __NSW_SUCCESS)
3687c478bd9Sstevel@tonic-gate 				lkp->actions[i] = 1;
3697c478bd9Sstevel@tonic-gate 			else
3707c478bd9Sstevel@tonic-gate 				lkp->actions[i] = 0;
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate 		/* get criteria for the naming service */
3737c478bd9Sstevel@tonic-gate 		if (tokenp = skip(&linep, '[')) { /* got criteria */
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate 			/* premature end, illegal char following [ */
3767c478bd9Sstevel@tonic-gate 			if (!islabel(*linep))
3777c478bd9Sstevel@tonic-gate 				goto barf_line;
3787c478bd9Sstevel@tonic-gate 			LIBC_STRDUP(lkp->service_name, tokenp);
3797c478bd9Sstevel@tonic-gate 			cfp->num_lookups++;
3807c478bd9Sstevel@tonic-gate 			end_crit = 0;
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate 			/* linep points to a switch_err */
3837c478bd9Sstevel@tonic-gate 			for (;;) {
3847c478bd9Sstevel@tonic-gate 				if ((tokenp = skip(&linep, '=')) == NULL) {
3857c478bd9Sstevel@tonic-gate 					goto barf_line;
3867c478bd9Sstevel@tonic-gate 				}
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate 				/* premature end, ill char following = */
3897c478bd9Sstevel@tonic-gate 				if (!islabel(*linep))
3907c478bd9Sstevel@tonic-gate 					goto barf_line;
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 				/* linep points to the string following '=' */
3937c478bd9Sstevel@tonic-gate 				p = labelskip(linep);
3947c478bd9Sstevel@tonic-gate 				if (*p == ']')
3957c478bd9Sstevel@tonic-gate 					end_crit = 1;
3967c478bd9Sstevel@tonic-gate 				else if (*p != ' ' && *p != '\t')
3977c478bd9Sstevel@tonic-gate 					goto barf_line;
3987c478bd9Sstevel@tonic-gate 				*p++ = '\0'; /* null terminate linep */
3997c478bd9Sstevel@tonic-gate 				p = spaceskip(p);
4007c478bd9Sstevel@tonic-gate 				if (!end_crit) {
4017c478bd9Sstevel@tonic-gate 					if (*p == ']') {
4027c478bd9Sstevel@tonic-gate 					end_crit = 1;
4037c478bd9Sstevel@tonic-gate 					*p++ = '\0';
4047c478bd9Sstevel@tonic-gate 					} else if (*p == '\0' || *p == '\n')
4057c478bd9Sstevel@tonic-gate 						return (cfp);
4067c478bd9Sstevel@tonic-gate 					else if (!islabel(*p))
4077c478bd9Sstevel@tonic-gate 					/* p better be the next switch_err */
4087c478bd9Sstevel@tonic-gate 						goto barf_line;
4097c478bd9Sstevel@tonic-gate 				}
4107c478bd9Sstevel@tonic-gate 				if (strcasecmp(linep, __NSW_STR_RETURN) == 0)
4117c478bd9Sstevel@tonic-gate 					act = __NSW_RETURN;
4127c478bd9Sstevel@tonic-gate 				else if (strcasecmp(linep,
4137c478bd9Sstevel@tonic-gate 					    __NSW_STR_CONTINUE) == 0)
4147c478bd9Sstevel@tonic-gate 					act = __NSW_CONTINUE;
4157c478bd9Sstevel@tonic-gate 				else if (strcasecmp(linep,
4167c478bd9Sstevel@tonic-gate 					    __NSW_STR_FOREVER) == 0)
4177c478bd9Sstevel@tonic-gate 					/*
4187c478bd9Sstevel@tonic-gate 					 * =forever or =N might be in conf file
4197c478bd9Sstevel@tonic-gate 					 * but old progs won't expect it.
4207c478bd9Sstevel@tonic-gate 					 */
4217c478bd9Sstevel@tonic-gate 					act = __NSW_RETURN;
4227c478bd9Sstevel@tonic-gate 				else if (alldigits(linep))
4237c478bd9Sstevel@tonic-gate 					act = __NSW_CONTINUE;
4247c478bd9Sstevel@tonic-gate 				else
4257c478bd9Sstevel@tonic-gate 					goto barf_line;
4267c478bd9Sstevel@tonic-gate 				if (strcasecmp(tokenp,
4277c478bd9Sstevel@tonic-gate 					    __NSW_STR_SUCCESS) == 0) {
4287c478bd9Sstevel@tonic-gate 					lkp->actions[__NSW_SUCCESS] = act;
4297c478bd9Sstevel@tonic-gate 				} else if (strcasecmp(tokenp,
4307c478bd9Sstevel@tonic-gate 					    __NSW_STR_NOTFOUND) == 0) {
4317c478bd9Sstevel@tonic-gate 					lkp->actions[__NSW_NOTFOUND] = act;
4327c478bd9Sstevel@tonic-gate 				} else if (strcasecmp(tokenp,
4337c478bd9Sstevel@tonic-gate 					    __NSW_STR_UNAVAIL) == 0) {
4347c478bd9Sstevel@tonic-gate 					lkp->actions[__NSW_UNAVAIL] = act;
4357c478bd9Sstevel@tonic-gate 				} else if (strcasecmp(tokenp,
4367c478bd9Sstevel@tonic-gate 					    __NSW_STR_TRYAGAIN) == 0) {
4377c478bd9Sstevel@tonic-gate 					lkp->actions[__NSW_TRYAGAIN] = act;
4387c478bd9Sstevel@tonic-gate 				} else {
4397c478bd9Sstevel@tonic-gate 					/*EMPTY*/
4407c478bd9Sstevel@tonic-gate 					/*
4417c478bd9Sstevel@tonic-gate 					 * convert string tokenp to integer
4427c478bd9Sstevel@tonic-gate 					 * and put in long_errs
4437c478bd9Sstevel@tonic-gate 					 */
4447c478bd9Sstevel@tonic-gate 				}
4457c478bd9Sstevel@tonic-gate 				if (end_crit) {
4467c478bd9Sstevel@tonic-gate 					linep = spaceskip(p);
4477c478bd9Sstevel@tonic-gate 					if (*linep == '\0' || *linep == '\n')
4487c478bd9Sstevel@tonic-gate 						return (cfp);
4497c478bd9Sstevel@tonic-gate 					break; /* process next naming service */
4507c478bd9Sstevel@tonic-gate 				}
4517c478bd9Sstevel@tonic-gate 				linep = p;
4527c478bd9Sstevel@tonic-gate 			} /* end of while loop for a name service's criteria */
4537c478bd9Sstevel@tonic-gate 		} else {
4547c478bd9Sstevel@tonic-gate 			/*
4557c478bd9Sstevel@tonic-gate 			 * no criteria for this naming service.
4567c478bd9Sstevel@tonic-gate 			 * linep points to name service, but not null
4577c478bd9Sstevel@tonic-gate 			 * terminated.
4587c478bd9Sstevel@tonic-gate 			 */
4597c478bd9Sstevel@tonic-gate 			p = labelskip(linep);
4607c478bd9Sstevel@tonic-gate 			if (*p == '\0' || *p == '\n') {
4617c478bd9Sstevel@tonic-gate 				*p = '\0';
4627c478bd9Sstevel@tonic-gate 				LIBC_STRDUP(lkp->service_name, linep);
4637c478bd9Sstevel@tonic-gate 				cfp->num_lookups++;
4647c478bd9Sstevel@tonic-gate 				return (cfp);
4657c478bd9Sstevel@tonic-gate 			}
4667c478bd9Sstevel@tonic-gate 			if (*p != ' ' && *p != '\t')
4677c478bd9Sstevel@tonic-gate 				goto barf_line;
4687c478bd9Sstevel@tonic-gate 			*p++ = '\0';
4697c478bd9Sstevel@tonic-gate 			LIBC_STRDUP(lkp->service_name, linep);
4707c478bd9Sstevel@tonic-gate 			cfp->num_lookups++;
4717c478bd9Sstevel@tonic-gate 			linep = spaceskip(p);
4727c478bd9Sstevel@tonic-gate 		}
4737c478bd9Sstevel@tonic-gate 	} /* end of while(1) loop for a name service */
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate barf_line:
4767c478bd9Sstevel@tonic-gate 	freeconf(cfp);
4777c478bd9Sstevel@tonic-gate 	*errp = dup_fail ? __NSW_CONF_PARSE_SYSERR : __NSW_CONF_PARSE_NOPOLICY;
4787c478bd9Sstevel@tonic-gate 	return (NULL);
4797c478bd9Sstevel@tonic-gate }
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate static mutex_t serialize_config_v1 = DEFAULTMUTEX;
4827c478bd9Sstevel@tonic-gate static mutex_t serialize_config = DEFAULTMUTEX;
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate static void
syslog_warning(const char * dbase)4857c478bd9Sstevel@tonic-gate syslog_warning(const char *dbase)
4867c478bd9Sstevel@tonic-gate {
4877c478bd9Sstevel@tonic-gate 	syslog(LOG_WARNING,
4887c478bd9Sstevel@tonic-gate 	    "libc: bad lookup policy for %s in %s, using defaults..\n",
4897c478bd9Sstevel@tonic-gate 	    dbase, __NSW_CONFIG_FILE);
4907c478bd9Sstevel@tonic-gate }
4917c478bd9Sstevel@tonic-gate 
492004388ebScasper /*
493004388ebScasper  * Since we cannot call malloc() or lock any of the ordinary mutexes
494004388ebScasper  * while we hold an lmutex_lock(), we open the file outside the lock
495004388ebScasper  * and disable locking on the file; the latter is fine because we're
496004388ebScasper  * reading the fp only from a single thread.
497004388ebScasper  */
498004388ebScasper static FILE *
open_conf(void)499004388ebScasper open_conf(void)
500004388ebScasper {
501004388ebScasper 	FILE *fp = fopen(__NSW_CONFIG_FILE, "rF");
502004388ebScasper 
503004388ebScasper 	if (fp != NULL) {
504004388ebScasper 		if (_findbuf(fp) == NULL) {
505004388ebScasper 			(void) fclose(fp);
506004388ebScasper 			return (NULL);
507004388ebScasper 		}
508004388ebScasper 		SET_IONOLOCK(fp);
509004388ebScasper 	}
510004388ebScasper 	return (fp);
511004388ebScasper }
512004388ebScasper 
5137c478bd9Sstevel@tonic-gate struct __nsw_switchconfig_v1 *
__nsw_getconfig_v1(const char * dbase,enum __nsw_parse_err * errp)5147c478bd9Sstevel@tonic-gate __nsw_getconfig_v1(const char *dbase, enum __nsw_parse_err *errp)
5157c478bd9Sstevel@tonic-gate {
5167c478bd9Sstevel@tonic-gate 	struct __nsw_switchconfig_v1 *cfp, *retp = NULL;
5177c478bd9Sstevel@tonic-gate 	int syslog_error = 0;
518004388ebScasper 	FILE *fp = NULL;
5197c478bd9Sstevel@tonic-gate 	char *linep;
5207c478bd9Sstevel@tonic-gate 	char lineq[BUFSIZ];
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate 	lmutex_lock(&serialize_config_v1);
523004388ebScasper top:
5247c478bd9Sstevel@tonic-gate 	if (cfp = scrounge_cache_v1(dbase)) {
5257c478bd9Sstevel@tonic-gate 		*errp = __NSW_CONF_PARSE_SUCCESS;
5267c478bd9Sstevel@tonic-gate 		lmutex_unlock(&serialize_config_v1);
527004388ebScasper 		if (fp != NULL)
528004388ebScasper 			(void) fclose(fp);
5297c478bd9Sstevel@tonic-gate 		return (cfp);
5307c478bd9Sstevel@tonic-gate 	}
5317c478bd9Sstevel@tonic-gate 
532004388ebScasper 	if (fp == NULL) {
533004388ebScasper 		struct cons_cell_v1 *cp = concell_list_v1;
534004388ebScasper 
5357c478bd9Sstevel@tonic-gate 		lmutex_unlock(&serialize_config_v1);
536004388ebScasper 		/* open_conf() must be called w/o locks held */
537004388ebScasper 		if ((fp = open_conf()) == NULL) {
538004388ebScasper 			*errp = __NSW_CONF_PARSE_NOFILE;
5397c478bd9Sstevel@tonic-gate 			return (NULL);
5407c478bd9Sstevel@tonic-gate 		}
541004388ebScasper 		lmutex_lock(&serialize_config_v1);
542004388ebScasper 		/* Cache changed? */
543004388ebScasper 		if (cp != concell_list_v1)
544004388ebScasper 			goto top;
545004388ebScasper 	}
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate 	*errp = __NSW_CONF_PARSE_NOPOLICY;
548004388ebScasper 	while (linep = fgets(lineq, BUFSIZ, fp)) {
5497c478bd9Sstevel@tonic-gate 		enum __nsw_parse_err	line_err;
5507c478bd9Sstevel@tonic-gate 		char			*tokenp, *comment;
5517c478bd9Sstevel@tonic-gate 
5527c478bd9Sstevel@tonic-gate 		/*
5537c478bd9Sstevel@tonic-gate 		 * Ignore portion of line following the comment character '#'.
5547c478bd9Sstevel@tonic-gate 		 */
5557c478bd9Sstevel@tonic-gate 		if ((comment = strchr(linep, '#')) != NULL) {
5567c478bd9Sstevel@tonic-gate 			*comment = '\0';
5577c478bd9Sstevel@tonic-gate 		}
5587c478bd9Sstevel@tonic-gate 		/*
5597c478bd9Sstevel@tonic-gate 		 * skip past blank lines.
5607c478bd9Sstevel@tonic-gate 		 * otherwise, cache as a struct switchconfig.
5617c478bd9Sstevel@tonic-gate 		 */
5627c478bd9Sstevel@tonic-gate 		if ((*linep == '\0') || isspace(*linep)) {
5637c478bd9Sstevel@tonic-gate 			continue;
5647c478bd9Sstevel@tonic-gate 		}
5657c478bd9Sstevel@tonic-gate 		if ((tokenp = skip(&linep, ':')) == NULL) {
5667c478bd9Sstevel@tonic-gate 			continue; /* ignore this line */
5677c478bd9Sstevel@tonic-gate 		}
5687c478bd9Sstevel@tonic-gate 		if (cfp = scrounge_cache_v1(tokenp)) {
5697c478bd9Sstevel@tonic-gate 			continue; /* ? somehow this database is in the cache */
5707c478bd9Sstevel@tonic-gate 		}
5717c478bd9Sstevel@tonic-gate 		if (cfp = _nsw_getoneconfig_v1(tokenp, linep, &line_err)) {
5727c478bd9Sstevel@tonic-gate 			(void) add_concell_v1(cfp);
5737c478bd9Sstevel@tonic-gate 			if (strcmp(cfp->dbase, dbase) == 0) {
5747c478bd9Sstevel@tonic-gate 				*errp = __NSW_CONF_PARSE_SUCCESS;
5757c478bd9Sstevel@tonic-gate 				retp = cfp;
5767c478bd9Sstevel@tonic-gate 			}
5777c478bd9Sstevel@tonic-gate 		} else {
5787c478bd9Sstevel@tonic-gate 			/*
5797c478bd9Sstevel@tonic-gate 			 * Got an error on this line, if it is a system
5807c478bd9Sstevel@tonic-gate 			 * error we might as well give right now. If it
5817c478bd9Sstevel@tonic-gate 			 * is a parse error on the second entry of the
5827c478bd9Sstevel@tonic-gate 			 * database we are looking for and the first one
5837c478bd9Sstevel@tonic-gate 			 * was a good entry we end up logging the following
5847c478bd9Sstevel@tonic-gate 			 * syslog message and using a default policy instead.
5857c478bd9Sstevel@tonic-gate 			 */
5867c478bd9Sstevel@tonic-gate 			if (line_err == __NSW_CONF_PARSE_SYSERR) {
5877c478bd9Sstevel@tonic-gate 				*errp = __NSW_CONF_PARSE_SYSERR;
5887c478bd9Sstevel@tonic-gate 				break;
5897c478bd9Sstevel@tonic-gate 			} else if (line_err == __NSW_CONF_PARSE_NOPOLICY &&
5907c478bd9Sstevel@tonic-gate 			    strcmp(tokenp, dbase) == 0) {
5917c478bd9Sstevel@tonic-gate 				syslog_error = 1;
5927c478bd9Sstevel@tonic-gate 				*errp = __NSW_CONF_PARSE_NOPOLICY;
5937c478bd9Sstevel@tonic-gate 				break;
5947c478bd9Sstevel@tonic-gate 			}
5957c478bd9Sstevel@tonic-gate 			/*
5967c478bd9Sstevel@tonic-gate 			 * Else blithely ignore problems on this line and
5977c478bd9Sstevel@tonic-gate 			 *   go ahead with the next line.
5987c478bd9Sstevel@tonic-gate 			 */
5997c478bd9Sstevel@tonic-gate 		}
6007c478bd9Sstevel@tonic-gate 	}
6017c478bd9Sstevel@tonic-gate 	lmutex_unlock(&serialize_config_v1);
6027c478bd9Sstevel@tonic-gate 	/*
603004388ebScasper 	 * We have to drop the lock before calling fclose()/syslog().
6047c478bd9Sstevel@tonic-gate 	 */
605004388ebScasper 	(void) fclose(fp);
6067c478bd9Sstevel@tonic-gate 	if (syslog_error)
6077c478bd9Sstevel@tonic-gate 		syslog_warning(dbase);
6087c478bd9Sstevel@tonic-gate 	return (retp);
6097c478bd9Sstevel@tonic-gate }
6107c478bd9Sstevel@tonic-gate 
6117c478bd9Sstevel@tonic-gate struct __nsw_switchconfig *
__nsw_getconfig(const char * dbase,enum __nsw_parse_err * errp)6127c478bd9Sstevel@tonic-gate __nsw_getconfig(const char *dbase, enum __nsw_parse_err *errp)
6137c478bd9Sstevel@tonic-gate {
6147c478bd9Sstevel@tonic-gate 	struct __nsw_switchconfig *cfp, *retp = NULL;
6157c478bd9Sstevel@tonic-gate 	int syslog_error = 0;
616004388ebScasper 	FILE *fp = NULL;
6177c478bd9Sstevel@tonic-gate 	char *linep;
6187c478bd9Sstevel@tonic-gate 	char lineq[BUFSIZ];
6197c478bd9Sstevel@tonic-gate 
6207c478bd9Sstevel@tonic-gate 	lmutex_lock(&serialize_config);
621004388ebScasper top:
6227c478bd9Sstevel@tonic-gate 	if (cfp = scrounge_cache(dbase)) {
6237c478bd9Sstevel@tonic-gate 		*errp = __NSW_CONF_PARSE_SUCCESS;
6247c478bd9Sstevel@tonic-gate 		lmutex_unlock(&serialize_config);
625004388ebScasper 		if (fp != NULL)
626004388ebScasper 			(void) fclose(fp);
6277c478bd9Sstevel@tonic-gate 		return (cfp);
6287c478bd9Sstevel@tonic-gate 	}
6297c478bd9Sstevel@tonic-gate 
630004388ebScasper 	if (fp == NULL) {
631004388ebScasper 		struct cons_cell *cp = concell_list;
632004388ebScasper 		/* open_conf() must be called w/o locks held */
6337c478bd9Sstevel@tonic-gate 		lmutex_unlock(&serialize_config);
634004388ebScasper 		if ((fp = open_conf()) == NULL) {
635004388ebScasper 			*errp = __NSW_CONF_PARSE_NOFILE;
6367c478bd9Sstevel@tonic-gate 			return (NULL);
6377c478bd9Sstevel@tonic-gate 		}
638004388ebScasper 		lmutex_lock(&serialize_config);
639004388ebScasper 		/* Cache changed? */
640004388ebScasper 		if (cp != concell_list)
641004388ebScasper 			goto top;
642004388ebScasper 	}
6437c478bd9Sstevel@tonic-gate 
6447c478bd9Sstevel@tonic-gate 	*errp = __NSW_CONF_PARSE_NOPOLICY;
645004388ebScasper 	while (linep = fgets(lineq, BUFSIZ, fp)) {
6467c478bd9Sstevel@tonic-gate 		enum __nsw_parse_err	line_err;
6477c478bd9Sstevel@tonic-gate 		char			*tokenp, *comment;
6487c478bd9Sstevel@tonic-gate 
6497c478bd9Sstevel@tonic-gate 		/*
6507c478bd9Sstevel@tonic-gate 		 * Ignore portion of line following the comment character '#'.
6517c478bd9Sstevel@tonic-gate 		 */
6527c478bd9Sstevel@tonic-gate 		if ((comment = strchr(linep, '#')) != NULL) {
6537c478bd9Sstevel@tonic-gate 			*comment = '\0';
6547c478bd9Sstevel@tonic-gate 		}
6557c478bd9Sstevel@tonic-gate 		/*
6567c478bd9Sstevel@tonic-gate 		 * skip past blank lines.
6577c478bd9Sstevel@tonic-gate 		 * otherwise, cache as a struct switchconfig.
6587c478bd9Sstevel@tonic-gate 		 */
6597c478bd9Sstevel@tonic-gate 		if ((*linep == '\0') || isspace(*linep)) {
6607c478bd9Sstevel@tonic-gate 			continue;
6617c478bd9Sstevel@tonic-gate 		}
6627c478bd9Sstevel@tonic-gate 		if ((tokenp = skip(&linep, ':')) == NULL) {
6637c478bd9Sstevel@tonic-gate 			continue; /* ignore this line */
6647c478bd9Sstevel@tonic-gate 		}
6657c478bd9Sstevel@tonic-gate 		if (cfp = scrounge_cache(tokenp)) {
6667c478bd9Sstevel@tonic-gate 			continue; /* ? somehow this database is in the cache */
6677c478bd9Sstevel@tonic-gate 		}
6687c478bd9Sstevel@tonic-gate 		if (cfp = _nsw_getoneconfig(tokenp, linep, &line_err)) {
6697c478bd9Sstevel@tonic-gate 			(void) add_concell(cfp);
6707c478bd9Sstevel@tonic-gate 			if (strcmp(cfp->dbase, dbase) == 0) {
6717c478bd9Sstevel@tonic-gate 				*errp = __NSW_CONF_PARSE_SUCCESS;
6727c478bd9Sstevel@tonic-gate 				retp = cfp;
6737c478bd9Sstevel@tonic-gate 			}
6747c478bd9Sstevel@tonic-gate 		} else {
6757c478bd9Sstevel@tonic-gate 			/*
6767c478bd9Sstevel@tonic-gate 			 * Got an error on this line, if it is a system
6777c478bd9Sstevel@tonic-gate 			 * error we might as well give right now. If it
6787c478bd9Sstevel@tonic-gate 			 * is a parse error on the second entry of the
6797c478bd9Sstevel@tonic-gate 			 * database we are looking for and the first one
6807c478bd9Sstevel@tonic-gate 			 * was a good entry we end up logging the following
6817c478bd9Sstevel@tonic-gate 			 * syslog message and using a default policy instead.
6827c478bd9Sstevel@tonic-gate 			 */
6837c478bd9Sstevel@tonic-gate 			if (line_err == __NSW_CONF_PARSE_SYSERR) {
6847c478bd9Sstevel@tonic-gate 				*errp = __NSW_CONF_PARSE_SYSERR;
6857c478bd9Sstevel@tonic-gate 				break;
6867c478bd9Sstevel@tonic-gate 			} else if (line_err == __NSW_CONF_PARSE_NOPOLICY &&
6877c478bd9Sstevel@tonic-gate 			    strcmp(tokenp, dbase) == 0) {
6887c478bd9Sstevel@tonic-gate 				syslog_error = 1;
6897c478bd9Sstevel@tonic-gate 				*errp = __NSW_CONF_PARSE_NOPOLICY;
6907c478bd9Sstevel@tonic-gate 				break;
6917c478bd9Sstevel@tonic-gate 			}
6927c478bd9Sstevel@tonic-gate 			/*
6937c478bd9Sstevel@tonic-gate 			 * Else blithely ignore problems on this line and
6947c478bd9Sstevel@tonic-gate 			 *   go ahead with the next line.
6957c478bd9Sstevel@tonic-gate 			 */
6967c478bd9Sstevel@tonic-gate 		}
6977c478bd9Sstevel@tonic-gate 	}
6987c478bd9Sstevel@tonic-gate 	lmutex_unlock(&serialize_config);
6997c478bd9Sstevel@tonic-gate 	/*
700004388ebScasper 	 * We have to drop the lock before calling fclose()/syslog().
7017c478bd9Sstevel@tonic-gate 	 */
702004388ebScasper 	(void) fclose(fp);
7037c478bd9Sstevel@tonic-gate 	if (syslog_error)
7047c478bd9Sstevel@tonic-gate 		syslog_warning(dbase);
7057c478bd9Sstevel@tonic-gate 	return (retp);
7067c478bd9Sstevel@tonic-gate }
7077c478bd9Sstevel@tonic-gate 
7087c478bd9Sstevel@tonic-gate 
7097c478bd9Sstevel@tonic-gate static struct __nsw_switchconfig_v1 *
scrounge_cache_v1(const char * dbase)7107c478bd9Sstevel@tonic-gate scrounge_cache_v1(const char *dbase)
7117c478bd9Sstevel@tonic-gate {
7127c478bd9Sstevel@tonic-gate 	struct cons_cell_v1 *cellp = concell_list_v1;
7137c478bd9Sstevel@tonic-gate 
7147c478bd9Sstevel@tonic-gate 	for (; cellp; cellp = cellp->next)
7157c478bd9Sstevel@tonic-gate 		if (strcmp(dbase, cellp->sw->dbase) == 0)
7167c478bd9Sstevel@tonic-gate 			return (cellp->sw);
7177c478bd9Sstevel@tonic-gate 	return (NULL);
7187c478bd9Sstevel@tonic-gate }
7197c478bd9Sstevel@tonic-gate 
7207c478bd9Sstevel@tonic-gate static struct __nsw_switchconfig *
scrounge_cache(const char * dbase)7217c478bd9Sstevel@tonic-gate scrounge_cache(const char *dbase)
7227c478bd9Sstevel@tonic-gate {
7237c478bd9Sstevel@tonic-gate 	struct cons_cell *cellp = concell_list;
7247c478bd9Sstevel@tonic-gate 
7257c478bd9Sstevel@tonic-gate 	for (; cellp; cellp = cellp->next)
7267c478bd9Sstevel@tonic-gate 		if (strcmp(dbase, cellp->sw->dbase) == 0)
7277c478bd9Sstevel@tonic-gate 			return (cellp->sw);
7287c478bd9Sstevel@tonic-gate 	return (NULL);
7297c478bd9Sstevel@tonic-gate }
7307c478bd9Sstevel@tonic-gate 
7317c478bd9Sstevel@tonic-gate static void
freeconf_v1(struct __nsw_switchconfig_v1 * cfp)7327c478bd9Sstevel@tonic-gate freeconf_v1(struct __nsw_switchconfig_v1 *cfp)
7337c478bd9Sstevel@tonic-gate {
7347c478bd9Sstevel@tonic-gate 	if (cfp) {
7357c478bd9Sstevel@tonic-gate 		if (cfp->dbase)
7367c478bd9Sstevel@tonic-gate 			libc_free(cfp->dbase);
7377c478bd9Sstevel@tonic-gate 		if (cfp->lookups) {
7387c478bd9Sstevel@tonic-gate 			struct __nsw_lookup_v1 *nex, *cur;
7397c478bd9Sstevel@tonic-gate 			for (cur = cfp->lookups; cur; cur = nex) {
7407c478bd9Sstevel@tonic-gate 				libc_free(cur->service_name);
7417c478bd9Sstevel@tonic-gate 				nex = cur->next;
7427c478bd9Sstevel@tonic-gate 				libc_free(cur);
7437c478bd9Sstevel@tonic-gate 			}
7447c478bd9Sstevel@tonic-gate 		}
7457c478bd9Sstevel@tonic-gate 		libc_free(cfp);
7467c478bd9Sstevel@tonic-gate 	}
7477c478bd9Sstevel@tonic-gate }
7487c478bd9Sstevel@tonic-gate 
7497c478bd9Sstevel@tonic-gate static void
freeconf(struct __nsw_switchconfig * cfp)7507c478bd9Sstevel@tonic-gate freeconf(struct __nsw_switchconfig *cfp)
7517c478bd9Sstevel@tonic-gate {
7527c478bd9Sstevel@tonic-gate 	if (cfp) {
7537c478bd9Sstevel@tonic-gate 		if (cfp->dbase)
7547c478bd9Sstevel@tonic-gate 			libc_free(cfp->dbase);
7557c478bd9Sstevel@tonic-gate 		if (cfp->lookups) {
7567c478bd9Sstevel@tonic-gate 			struct __nsw_lookup *nex, *cur;
7577c478bd9Sstevel@tonic-gate 			for (cur = cfp->lookups; cur; cur = nex) {
7587c478bd9Sstevel@tonic-gate 				libc_free(cur->service_name);
7597c478bd9Sstevel@tonic-gate 				nex = cur->next;
7607c478bd9Sstevel@tonic-gate 				libc_free(cur);
7617c478bd9Sstevel@tonic-gate 			}
7627c478bd9Sstevel@tonic-gate 		}
7637c478bd9Sstevel@tonic-gate 		libc_free(cfp);
7647c478bd9Sstevel@tonic-gate 	}
7657c478bd9Sstevel@tonic-gate }
7667c478bd9Sstevel@tonic-gate 
7677c478bd9Sstevel@tonic-gate action_t
__nsw_extended_action_v1(struct __nsw_lookup_v1 * lkp,int err)7687c478bd9Sstevel@tonic-gate __nsw_extended_action_v1(struct __nsw_lookup_v1 *lkp, int err)
7697c478bd9Sstevel@tonic-gate {
7707c478bd9Sstevel@tonic-gate 	struct __nsw_long_err *lerrp;
7717c478bd9Sstevel@tonic-gate 
7727c478bd9Sstevel@tonic-gate 	for (lerrp = lkp->long_errs; lerrp; lerrp = lerrp->next) {
7737c478bd9Sstevel@tonic-gate 		if (lerrp->nsw_errno == err)
7747c478bd9Sstevel@tonic-gate 			return (lerrp->action);
7757c478bd9Sstevel@tonic-gate 	}
7767c478bd9Sstevel@tonic-gate 	return (__NSW_CONTINUE);
7777c478bd9Sstevel@tonic-gate }
7787c478bd9Sstevel@tonic-gate 
7797c478bd9Sstevel@tonic-gate action_t
__nsw_extended_action(struct __nsw_lookup * lkp,int err)7807c478bd9Sstevel@tonic-gate __nsw_extended_action(struct __nsw_lookup *lkp, int err)
7817c478bd9Sstevel@tonic-gate {
7827c478bd9Sstevel@tonic-gate 	struct __nsw_long_err *lerrp;
7837c478bd9Sstevel@tonic-gate 
7847c478bd9Sstevel@tonic-gate 	for (lerrp = lkp->long_errs; lerrp; lerrp = lerrp->next) {
7857c478bd9Sstevel@tonic-gate 		if (lerrp->nsw_errno == err)
7867c478bd9Sstevel@tonic-gate 			return (lerrp->action);
7877c478bd9Sstevel@tonic-gate 	}
7887c478bd9Sstevel@tonic-gate 	return (__NSW_CONTINUE);
7897c478bd9Sstevel@tonic-gate }
7907c478bd9Sstevel@tonic-gate 
7917c478bd9Sstevel@tonic-gate 
7927c478bd9Sstevel@tonic-gate /* give the next non-alpha character */
7937c478bd9Sstevel@tonic-gate static char *
labelskip(char * cur)7947c478bd9Sstevel@tonic-gate labelskip(char *cur)
7957c478bd9Sstevel@tonic-gate {
7967c478bd9Sstevel@tonic-gate 	char *p = cur;
7977c478bd9Sstevel@tonic-gate 	while (islabel(*p))
7987c478bd9Sstevel@tonic-gate 		++p;
7997c478bd9Sstevel@tonic-gate 	return (p);
8007c478bd9Sstevel@tonic-gate }
8017c478bd9Sstevel@tonic-gate 
8027c478bd9Sstevel@tonic-gate /* give the next non-space character */
8037c478bd9Sstevel@tonic-gate static char *
spaceskip(char * cur)8047c478bd9Sstevel@tonic-gate spaceskip(char *cur)
8057c478bd9Sstevel@tonic-gate {
8067c478bd9Sstevel@tonic-gate 	char *p = cur;
8077c478bd9Sstevel@tonic-gate 	while (*p == ' ' || *p == '\t')
8087c478bd9Sstevel@tonic-gate 		++p;
8097c478bd9Sstevel@tonic-gate 	return (p);
8107c478bd9Sstevel@tonic-gate }
8117c478bd9Sstevel@tonic-gate 
8127c478bd9Sstevel@tonic-gate /*
8137c478bd9Sstevel@tonic-gate  * terminate the *cur pointed string by null only if it is
8147c478bd9Sstevel@tonic-gate  * followed by "key" surrounded by zero or more spaces and
8157c478bd9Sstevel@tonic-gate  * return value is the same as the original *cur pointer and
8167c478bd9Sstevel@tonic-gate  * *cur pointer is advanced to the first non {space, key} char
8177c478bd9Sstevel@tonic-gate  * followed by the key. Otherwise, return NULL and keep
8187c478bd9Sstevel@tonic-gate  * *cur unchanged.
8197c478bd9Sstevel@tonic-gate  */
8207c478bd9Sstevel@tonic-gate static char *
skip(char ** cur,char key)8217c478bd9Sstevel@tonic-gate skip(char **cur, char key)
8227c478bd9Sstevel@tonic-gate {
8237c478bd9Sstevel@tonic-gate 	char *p, *tmp;
8247c478bd9Sstevel@tonic-gate 	char *q = *cur;
8257c478bd9Sstevel@tonic-gate 	int found, tmpfound;
8267c478bd9Sstevel@tonic-gate 
8277c478bd9Sstevel@tonic-gate 	tmp = labelskip(*cur);
8287c478bd9Sstevel@tonic-gate 	p = tmp;
8297c478bd9Sstevel@tonic-gate 	found = (*p == key);
8307c478bd9Sstevel@tonic-gate 	if (found) {
8317c478bd9Sstevel@tonic-gate 		*p++ = '\0'; /* overwrite the key */
8327c478bd9Sstevel@tonic-gate 		p = spaceskip(p);
8337c478bd9Sstevel@tonic-gate 	} else {
8347c478bd9Sstevel@tonic-gate 		while (*p == ' ' || *p == '\t') {
8357c478bd9Sstevel@tonic-gate 			tmpfound = (*++p == key);
8367c478bd9Sstevel@tonic-gate 			if (tmpfound) {
8377c478bd9Sstevel@tonic-gate 				found = tmpfound;
8387c478bd9Sstevel@tonic-gate 					/* null terminate the return token */
8397c478bd9Sstevel@tonic-gate 				*tmp = '\0';
8407c478bd9Sstevel@tonic-gate 				p++; /* skip the key */
8417c478bd9Sstevel@tonic-gate 			}
8427c478bd9Sstevel@tonic-gate 		}
8437c478bd9Sstevel@tonic-gate 	}
8447c478bd9Sstevel@tonic-gate 	if (!found)
8457c478bd9Sstevel@tonic-gate 		return (NULL); /* *cur unchanged */
8467c478bd9Sstevel@tonic-gate 	*cur = p;
8477c478bd9Sstevel@tonic-gate 	return (q);
8487c478bd9Sstevel@tonic-gate }
8497c478bd9Sstevel@tonic-gate 
8507c478bd9Sstevel@tonic-gate /* add to the front: LRU */
8517c478bd9Sstevel@tonic-gate static int
add_concell_v1(struct __nsw_switchconfig_v1 * cfp)8527c478bd9Sstevel@tonic-gate add_concell_v1(struct __nsw_switchconfig_v1 *cfp)
8537c478bd9Sstevel@tonic-gate {
8547c478bd9Sstevel@tonic-gate 	struct cons_cell_v1 *cp;
8557c478bd9Sstevel@tonic-gate 
8567c478bd9Sstevel@tonic-gate 	if (cfp == NULL)
8577c478bd9Sstevel@tonic-gate 		return (1);
8587c478bd9Sstevel@tonic-gate 	if ((cp = libc_malloc(sizeof (struct cons_cell_v1))) == NULL)
8597c478bd9Sstevel@tonic-gate 		return (1);
8607c478bd9Sstevel@tonic-gate 	cp->sw = cfp;
8617c478bd9Sstevel@tonic-gate 	cp->next = concell_list_v1;
8627c478bd9Sstevel@tonic-gate 	concell_list_v1 = cp;
8637c478bd9Sstevel@tonic-gate 	return (0);
8647c478bd9Sstevel@tonic-gate }
8657c478bd9Sstevel@tonic-gate 
8667c478bd9Sstevel@tonic-gate /* add to the front: LRU */
8677c478bd9Sstevel@tonic-gate static int
add_concell(struct __nsw_switchconfig * cfp)8687c478bd9Sstevel@tonic-gate add_concell(struct __nsw_switchconfig *cfp)
8697c478bd9Sstevel@tonic-gate {
8707c478bd9Sstevel@tonic-gate 	struct cons_cell *cp;
8717c478bd9Sstevel@tonic-gate 
8727c478bd9Sstevel@tonic-gate 	if (cfp == NULL)
8737c478bd9Sstevel@tonic-gate 		return (1);
8747c478bd9Sstevel@tonic-gate 	if ((cp = libc_malloc(sizeof (struct cons_cell))) == NULL)
8757c478bd9Sstevel@tonic-gate 		return (1);
8767c478bd9Sstevel@tonic-gate 	cp->sw = cfp;
8777c478bd9Sstevel@tonic-gate 	cp->next = concell_list;
8787c478bd9Sstevel@tonic-gate 	concell_list = cp;
8797c478bd9Sstevel@tonic-gate 	return (0);
8807c478bd9Sstevel@tonic-gate }
8817c478bd9Sstevel@tonic-gate 
8827c478bd9Sstevel@tonic-gate int
__nsw_freeconfig_v1(struct __nsw_switchconfig_v1 * conf)8837c478bd9Sstevel@tonic-gate __nsw_freeconfig_v1(struct __nsw_switchconfig_v1 *conf)
8847c478bd9Sstevel@tonic-gate {
8857c478bd9Sstevel@tonic-gate 	struct cons_cell_v1 *cellp;
8867c478bd9Sstevel@tonic-gate 
8877c478bd9Sstevel@tonic-gate 	if (conf == NULL) {
8887c478bd9Sstevel@tonic-gate 		return (-1);
8897c478bd9Sstevel@tonic-gate 	}
8907c478bd9Sstevel@tonic-gate 	/*
8917c478bd9Sstevel@tonic-gate 	 * Hacked to make life easy for the code in nss_common.c.  Free conf
8927c478bd9Sstevel@tonic-gate 	 *   iff it was created by calling _nsw_getoneconfig() directly
8937c478bd9Sstevel@tonic-gate 	 *   rather than by calling nsw_getconfig.
8947c478bd9Sstevel@tonic-gate 	 */
8957c478bd9Sstevel@tonic-gate 	lmutex_lock(&serialize_config_v1);
8967c478bd9Sstevel@tonic-gate 	for (cellp = concell_list_v1;  cellp;  cellp = cellp->next) {
8977c478bd9Sstevel@tonic-gate 		if (cellp->sw == conf) {
8987c478bd9Sstevel@tonic-gate 			break;
8997c478bd9Sstevel@tonic-gate 		}
9007c478bd9Sstevel@tonic-gate 	}
9017c478bd9Sstevel@tonic-gate 	lmutex_unlock(&serialize_config_v1);
9027c478bd9Sstevel@tonic-gate 	if (cellp == NULL) {
9037c478bd9Sstevel@tonic-gate 		/* Not in the cache;  free it */
9047c478bd9Sstevel@tonic-gate 		freeconf_v1(conf);
9057c478bd9Sstevel@tonic-gate 		return (1);
9067c478bd9Sstevel@tonic-gate 	} else {
9077c478bd9Sstevel@tonic-gate 		/* In the cache;  don't free it */
9087c478bd9Sstevel@tonic-gate 		return (0);
9097c478bd9Sstevel@tonic-gate 	}
9107c478bd9Sstevel@tonic-gate }
9117c478bd9Sstevel@tonic-gate 
9127c478bd9Sstevel@tonic-gate int
__nsw_freeconfig(struct __nsw_switchconfig * conf)9137c478bd9Sstevel@tonic-gate __nsw_freeconfig(struct __nsw_switchconfig *conf)
9147c478bd9Sstevel@tonic-gate {
9157c478bd9Sstevel@tonic-gate 	struct cons_cell *cellp;
9167c478bd9Sstevel@tonic-gate 
9177c478bd9Sstevel@tonic-gate 	if (conf == NULL) {
9187c478bd9Sstevel@tonic-gate 		return (-1);
9197c478bd9Sstevel@tonic-gate 	}
9207c478bd9Sstevel@tonic-gate 	/*
9217c478bd9Sstevel@tonic-gate 	 * Hacked to make life easy for the code in nss_common.c.  Free conf
9227c478bd9Sstevel@tonic-gate 	 *   iff it was created by calling _nsw_getoneconfig() directly
9237c478bd9Sstevel@tonic-gate 	 *   rather than by calling nsw_getconfig.
9247c478bd9Sstevel@tonic-gate 	 */
9257c478bd9Sstevel@tonic-gate 	lmutex_lock(&serialize_config);
9267c478bd9Sstevel@tonic-gate 	for (cellp = concell_list;  cellp;  cellp = cellp->next) {
9277c478bd9Sstevel@tonic-gate 		if (cellp->sw == conf) {
9287c478bd9Sstevel@tonic-gate 			break;
9297c478bd9Sstevel@tonic-gate 		}
9307c478bd9Sstevel@tonic-gate 	}
9317c478bd9Sstevel@tonic-gate 	lmutex_unlock(&serialize_config);
9327c478bd9Sstevel@tonic-gate 	if (cellp == NULL) {
9337c478bd9Sstevel@tonic-gate 		/* Not in the cache;  free it */
9347c478bd9Sstevel@tonic-gate 		freeconf(conf);
9357c478bd9Sstevel@tonic-gate 		return (1);
9367c478bd9Sstevel@tonic-gate 	} else {
9377c478bd9Sstevel@tonic-gate 		/* In the cache;  don't free it */
9387c478bd9Sstevel@tonic-gate 		return (0);
9397c478bd9Sstevel@tonic-gate 	}
9407c478bd9Sstevel@tonic-gate }
9417c478bd9Sstevel@tonic-gate 
9427c478bd9Sstevel@tonic-gate /* Return 1 if the string contains all digits, else return 0. */
9437c478bd9Sstevel@tonic-gate static int
alldigits(char * s)9447c478bd9Sstevel@tonic-gate alldigits(char *s)
9457c478bd9Sstevel@tonic-gate {
9467c478bd9Sstevel@tonic-gate 	for (; *s; s++)
9477c478bd9Sstevel@tonic-gate 		if (!isdigit(*s))
9487c478bd9Sstevel@tonic-gate 			return (0);
9497c478bd9Sstevel@tonic-gate 	return (1);
9507c478bd9Sstevel@tonic-gate }
951