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