10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
51914Scasper * Common Development and Distribution License (the "License").
61914Scasper * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
21132Srobinson
220Sstevel@tonic-gate /*
23*3864Sraf * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
280Sstevel@tonic-gate /* All Rights Reserved */
290Sstevel@tonic-gate
300Sstevel@tonic-gate /*
310Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 4.3 BSD
320Sstevel@tonic-gate * under license from the Regents of the University of California.
330Sstevel@tonic-gate */
340Sstevel@tonic-gate
350Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
360Sstevel@tonic-gate
370Sstevel@tonic-gate #include "mt.h"
380Sstevel@tonic-gate #include "../rpc/rpc_mt.h" /* for MT declarations only */
390Sstevel@tonic-gate #include <rpc/types.h>
400Sstevel@tonic-gate #include <stdio.h>
41132Srobinson #include <stdlib.h>
420Sstevel@tonic-gate #include <string.h>
430Sstevel@tonic-gate #include <ctype.h>
440Sstevel@tonic-gate #include <netconfig.h>
450Sstevel@tonic-gate #include <malloc.h>
46132Srobinson #include <libintl.h>
470Sstevel@tonic-gate #include <syslog.h>
480Sstevel@tonic-gate #include "netcspace.h"
490Sstevel@tonic-gate
500Sstevel@tonic-gate #define FAILURE (unsigned)(-1)
510Sstevel@tonic-gate
520Sstevel@tonic-gate /*
530Sstevel@tonic-gate * Local routines used by the library procedures
540Sstevel@tonic-gate */
550Sstevel@tonic-gate
56132Srobinson static int blank(char *);
57132Srobinson static int comment(char *);
581914Scasper static struct netconfig *fgetnetconfig(FILE *, char *);
59132Srobinson static void netconfig_free(struct netconfig *);
60132Srobinson static unsigned int getflag(char *);
61132Srobinson static char **getlookups(char *);
62132Srobinson static struct netconfig **getnetlist(void);
63132Srobinson static unsigned int getnlookups(char *);
64132Srobinson static char *gettoken(char *, int);
65132Srobinson static unsigned int getvalue(char *, struct nc_data nc_data[]);
66132Srobinson static void shift1left(char *);
67132Srobinson static void netlist_free(struct netconfig ***);
68132Srobinson static void free_entry(void *);
69132Srobinson static struct netconfig *netconfig_dup(struct netconfig *);
700Sstevel@tonic-gate
710Sstevel@tonic-gate extern const char __nsl_dom[];
720Sstevel@tonic-gate
730Sstevel@tonic-gate /*
740Sstevel@tonic-gate * Static global variables used by the library procedures:
750Sstevel@tonic-gate *
760Sstevel@tonic-gate * netpp - points to the beginning of the list of netconfig
770Sstevel@tonic-gate * entries used by setnetconfig() and setnetpath().
780Sstevel@tonic-gate * Once netpp is initialized, that memory is *never*
790Sstevel@tonic-gate * released. This was necessary to improve performance.
800Sstevel@tonic-gate *
810Sstevel@tonic-gate * linenum - the current line number of the /etc/netconfig
820Sstevel@tonic-gate * file (used for debugging and for nc_perror()).
830Sstevel@tonic-gate *
840Sstevel@tonic-gate * fieldnum - the current field number of the current line
850Sstevel@tonic-gate * of /etc/netconfig (used for debugging and for
860Sstevel@tonic-gate * nc_perror()).
870Sstevel@tonic-gate *
880Sstevel@tonic-gate * nc_error - the error condition encountered.
890Sstevel@tonic-gate */
900Sstevel@tonic-gate
910Sstevel@tonic-gate static struct netconfig **netpp = NULL;
920Sstevel@tonic-gate mutex_t netpp_mutex = DEFAULTMUTEX;
930Sstevel@tonic-gate /*
940Sstevel@tonic-gate * The following two variables are used by the /etc/netconfig parsing
950Sstevel@tonic-gate * routines, which will always be executed once, and within the netpp_mutex.
960Sstevel@tonic-gate * They are global to allow the nc_sperror routine to provide better
970Sstevel@tonic-gate * information to the user about /etc/netconfig file problems.
980Sstevel@tonic-gate */
990Sstevel@tonic-gate static int linenum = 0; /* "owned" by getnetlist() */
1000Sstevel@tonic-gate static int fieldnum = 0; /* "owned" by fgetnetconfig() */
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate
1030Sstevel@tonic-gate static int *
__nc_error(void)104132Srobinson __nc_error(void)
1050Sstevel@tonic-gate {
106*3864Sraf static pthread_key_t nc_error_key = PTHREAD_ONCE_KEY_NP;
1070Sstevel@tonic-gate static int nc_error = NC_NOERROR;
1080Sstevel@tonic-gate int *ret;
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate if (thr_main())
1110Sstevel@tonic-gate return (&nc_error);
1120Sstevel@tonic-gate ret = thr_get_storage(&nc_error_key, sizeof (int), free);
1130Sstevel@tonic-gate /* if thr_get_storage fails we return the address of nc_error */
1140Sstevel@tonic-gate return (ret ? ret : &nc_error);
1150Sstevel@tonic-gate }
1160Sstevel@tonic-gate #define nc_error (*(__nc_error()))
1170Sstevel@tonic-gate
1180Sstevel@tonic-gate /*
1190Sstevel@tonic-gate * setnetconfig() has the effect of "initializing" the
1200Sstevel@tonic-gate * network configuration database. It reads in the
1210Sstevel@tonic-gate * netcf entries (if not already read in).
1220Sstevel@tonic-gate */
1230Sstevel@tonic-gate
1240Sstevel@tonic-gate void *
setnetconfig(void)125132Srobinson setnetconfig(void)
1260Sstevel@tonic-gate {
1270Sstevel@tonic-gate NCONF_HANDLE *retp;
1280Sstevel@tonic-gate
129132Srobinson (void) mutex_lock(&netpp_mutex);
1300Sstevel@tonic-gate if ((netpp == NULL) && ((netpp = getnetlist()) == NULL)) {
131132Srobinson (void) mutex_unlock(&netpp_mutex);
1320Sstevel@tonic-gate return (NULL);
1330Sstevel@tonic-gate }
134132Srobinson (void) mutex_unlock(&netpp_mutex);
135132Srobinson if ((retp = malloc(sizeof (NCONF_HANDLE))) == NULL) {
1360Sstevel@tonic-gate nc_error = NC_NOMEM;
1370Sstevel@tonic-gate return (NULL);
1380Sstevel@tonic-gate }
1390Sstevel@tonic-gate nc_error = NC_NOERROR;
1400Sstevel@tonic-gate retp->nc_head = retp->nc_curr = netpp;
1410Sstevel@tonic-gate return ((void *)retp);
1420Sstevel@tonic-gate }
1430Sstevel@tonic-gate
1440Sstevel@tonic-gate /*
1450Sstevel@tonic-gate * endnetconfig() frees up all data allocated by setnetconfig()
1460Sstevel@tonic-gate */
1470Sstevel@tonic-gate
1480Sstevel@tonic-gate int
endnetconfig(void * vdata)149132Srobinson endnetconfig(void *vdata)
1500Sstevel@tonic-gate {
1510Sstevel@tonic-gate NCONF_HANDLE *nconf_handlep = (NCONF_HANDLE *)vdata;
1520Sstevel@tonic-gate
153132Srobinson (void) mutex_lock(&netpp_mutex);
1540Sstevel@tonic-gate if (netpp == NULL || nconf_handlep == NULL) {
1550Sstevel@tonic-gate nc_error = NC_NOSET;
156132Srobinson (void) mutex_unlock(&netpp_mutex);
1570Sstevel@tonic-gate return (-1);
1580Sstevel@tonic-gate }
159132Srobinson (void) mutex_unlock(&netpp_mutex);
1600Sstevel@tonic-gate
1610Sstevel@tonic-gate nc_error = NC_NOERROR;
162132Srobinson free(nconf_handlep);
1630Sstevel@tonic-gate return (0);
1640Sstevel@tonic-gate }
1650Sstevel@tonic-gate
1660Sstevel@tonic-gate /*
1670Sstevel@tonic-gate * getnetconfig() returns the current entry in the list
1680Sstevel@tonic-gate * of netconfig structures. It uses the nconf_handlep argument
1690Sstevel@tonic-gate * to determine the current entry. If setnetconfig() was not
1700Sstevel@tonic-gate * called previously to set up the list, return failure.
1710Sstevel@tonic-gate * It also check if ipv6 interface is present(ipv6_present) and
1720Sstevel@tonic-gate * skips udp6 & tcp6 entries if ipv6 is not supported.
1730Sstevel@tonic-gate */
1740Sstevel@tonic-gate
1750Sstevel@tonic-gate struct netconfig *
getnetconfig(void * vdata)176132Srobinson getnetconfig(void *vdata)
1770Sstevel@tonic-gate {
1780Sstevel@tonic-gate NCONF_HANDLE *nconf_handlep = (NCONF_HANDLE *)vdata;
1790Sstevel@tonic-gate struct netconfig *retp; /* holds the return value */
1800Sstevel@tonic-gate int ipv6_present = -1;
1810Sstevel@tonic-gate
182132Srobinson (void) mutex_lock(&netpp_mutex);
1830Sstevel@tonic-gate if ((netpp == NULL) || (nconf_handlep == NULL)) {
1840Sstevel@tonic-gate nc_error = NC_NOSET;
185132Srobinson (void) mutex_unlock(&netpp_mutex);
1860Sstevel@tonic-gate return (NULL);
1870Sstevel@tonic-gate }
188132Srobinson (void) mutex_unlock(&netpp_mutex);
1890Sstevel@tonic-gate for (;;) {
1900Sstevel@tonic-gate retp = *(nconf_handlep->nc_curr);
1910Sstevel@tonic-gate if (retp && (strcmp(retp->nc_netid, "udp6") == 0 ||
1920Sstevel@tonic-gate strcmp(retp->nc_netid, "tcp6") == 0)) {
1930Sstevel@tonic-gate if (ipv6_present == -1)
1940Sstevel@tonic-gate ipv6_present = __can_use_af(AF_INET6);
1950Sstevel@tonic-gate if (!ipv6_present) {
1960Sstevel@tonic-gate ++(nconf_handlep->nc_curr);
1970Sstevel@tonic-gate continue;
1980Sstevel@tonic-gate }
1990Sstevel@tonic-gate }
2000Sstevel@tonic-gate break;
2010Sstevel@tonic-gate }
2020Sstevel@tonic-gate if (retp != NULL) {
2030Sstevel@tonic-gate ++(nconf_handlep->nc_curr);
2040Sstevel@tonic-gate nc_error = NC_NOERROR;
2050Sstevel@tonic-gate } else {
2060Sstevel@tonic-gate nc_error = NC_NOMOREENTRIES;
2070Sstevel@tonic-gate }
2080Sstevel@tonic-gate return (retp);
2090Sstevel@tonic-gate }
2100Sstevel@tonic-gate
2110Sstevel@tonic-gate /*
2120Sstevel@tonic-gate * getnetconfig() searches the netconfig database for a
2130Sstevel@tonic-gate * given network id. Returns a pointer to the netconfig
2140Sstevel@tonic-gate * structure or a NULL if not found.
2150Sstevel@tonic-gate * It also check if ipv6 interface is present(ipv6_present) and
2160Sstevel@tonic-gate * skips udp6 & tcp6 entries if ipv6 is not supported.
2170Sstevel@tonic-gate */
2180Sstevel@tonic-gate
2190Sstevel@tonic-gate struct netconfig *
getnetconfigent(const char * netid)220132Srobinson getnetconfigent(const char *netid)
2210Sstevel@tonic-gate {
2220Sstevel@tonic-gate struct netconfig **tpp;
2230Sstevel@tonic-gate int ipv6_present;
2240Sstevel@tonic-gate
225132Srobinson (void) mutex_lock(&netpp_mutex);
2260Sstevel@tonic-gate if ((netpp == NULL) && ((netpp = getnetlist()) == NULL)) {
227132Srobinson (void) mutex_unlock(&netpp_mutex);
2280Sstevel@tonic-gate return (NULL);
2290Sstevel@tonic-gate }
230132Srobinson (void) mutex_unlock(&netpp_mutex);
2310Sstevel@tonic-gate for (tpp = netpp; *tpp; tpp++) {
2320Sstevel@tonic-gate if (strcmp((*tpp)->nc_netid, netid) == 0) {
2330Sstevel@tonic-gate if (*tpp && (strcmp((*tpp)->nc_netid, "udp6") == 0 ||
2340Sstevel@tonic-gate strcmp((*tpp)->nc_netid, "tcp6") == 0)) {
2350Sstevel@tonic-gate ipv6_present = __can_use_af(AF_INET6);
2360Sstevel@tonic-gate if (!ipv6_present) {
2370Sstevel@tonic-gate nc_error = NC_NOTFOUND;
2380Sstevel@tonic-gate return (NULL);
2390Sstevel@tonic-gate }
2400Sstevel@tonic-gate }
2410Sstevel@tonic-gate return (netconfig_dup(*tpp));
2420Sstevel@tonic-gate }
2430Sstevel@tonic-gate }
2440Sstevel@tonic-gate nc_error = NC_NOTFOUND;
2450Sstevel@tonic-gate return (NULL);
2460Sstevel@tonic-gate }
2470Sstevel@tonic-gate
2480Sstevel@tonic-gate /*
2490Sstevel@tonic-gate * freenetconfigent frees the data allocated by getnetconfigent()
2500Sstevel@tonic-gate */
2510Sstevel@tonic-gate
2520Sstevel@tonic-gate void
freenetconfigent(struct netconfig * netp)253132Srobinson freenetconfigent(struct netconfig *netp)
2540Sstevel@tonic-gate {
2550Sstevel@tonic-gate netconfig_free(netp);
2560Sstevel@tonic-gate }
2570Sstevel@tonic-gate
2580Sstevel@tonic-gate /*
2590Sstevel@tonic-gate * getnetlist() reads the netconfig file and creates a
2600Sstevel@tonic-gate * NULL-terminated list of entries.
2610Sstevel@tonic-gate * Returns the pointer to the head of the list or a NULL
2620Sstevel@tonic-gate * on failure.
2630Sstevel@tonic-gate */
2640Sstevel@tonic-gate
2650Sstevel@tonic-gate static struct netconfig **
getnetlist(void)266132Srobinson getnetlist(void)
2670Sstevel@tonic-gate {
2680Sstevel@tonic-gate char line[BUFSIZ]; /* holds each line of NETCONFIG */
2691914Scasper FILE *fp; /* file stream for NETCONFIG */
2700Sstevel@tonic-gate struct netconfig **listpp; /* the beginning of the netconfig list */
2710Sstevel@tonic-gate struct netconfig **tpp; /* used to traverse the netconfig list */
2720Sstevel@tonic-gate int count; /* the number of entries in file */
2730Sstevel@tonic-gate
2741914Scasper if ((fp = fopen(NETCONFIG, "rF")) == NULL) {
2750Sstevel@tonic-gate nc_error = NC_OPENFAIL;
2760Sstevel@tonic-gate return (NULL);
2770Sstevel@tonic-gate }
2780Sstevel@tonic-gate
2790Sstevel@tonic-gate count = 0;
2801914Scasper while (fgets(line, BUFSIZ, fp)) {
2810Sstevel@tonic-gate if (!(blank(line) || comment(line))) {
2820Sstevel@tonic-gate ++count;
2830Sstevel@tonic-gate }
2840Sstevel@tonic-gate }
2851914Scasper rewind(fp);
2860Sstevel@tonic-gate
2870Sstevel@tonic-gate if (count == 0) {
2880Sstevel@tonic-gate nc_error = NC_NOTFOUND;
2891914Scasper (void) fclose(fp);
2900Sstevel@tonic-gate return (NULL);
2910Sstevel@tonic-gate }
292132Srobinson if ((listpp = malloc((count + 1) *
2930Sstevel@tonic-gate sizeof (struct netconfig *))) == NULL) {
2940Sstevel@tonic-gate nc_error = NC_NOMEM;
2951914Scasper (void) fclose(fp);
2960Sstevel@tonic-gate return (NULL);
2970Sstevel@tonic-gate }
2980Sstevel@tonic-gate
2990Sstevel@tonic-gate /*
3000Sstevel@tonic-gate * The following loop fills in the list (loops until
3010Sstevel@tonic-gate * fgetnetconfig() returns a NULL) and counts the
3020Sstevel@tonic-gate * number of entries placed in the list. Note that
3030Sstevel@tonic-gate * when the loop is completed, the last entry in the
3040Sstevel@tonic-gate * list will contain a NULL (signifying the end of
3050Sstevel@tonic-gate * the list).
3060Sstevel@tonic-gate */
3070Sstevel@tonic-gate linenum = 0;
3080Sstevel@tonic-gate for (tpp = listpp; *tpp = fgetnetconfig(fp, NULL); tpp++)
3090Sstevel@tonic-gate ;
3101914Scasper (void) fclose(fp);
3110Sstevel@tonic-gate
3120Sstevel@tonic-gate if (nc_error != NC_NOMOREENTRIES) /* Something is screwed up */
3130Sstevel@tonic-gate netlist_free(&listpp);
3140Sstevel@tonic-gate return (listpp);
3150Sstevel@tonic-gate }
3160Sstevel@tonic-gate
3170Sstevel@tonic-gate /*
3180Sstevel@tonic-gate * fgetnetconfig() parses a line of the netconfig file into
3190Sstevel@tonic-gate * a netconfig structure. It returns a pointer to the
3200Sstevel@tonic-gate * structure of success and a NULL on failure or EOF.
3210Sstevel@tonic-gate */
3220Sstevel@tonic-gate
3230Sstevel@tonic-gate static struct netconfig *
fgetnetconfig(FILE * fp,char * netid)3241914Scasper fgetnetconfig(FILE *fp, char *netid)
3250Sstevel@tonic-gate {
3260Sstevel@tonic-gate char linep[BUFSIZ]; /* pointer to a line in the file */
3270Sstevel@tonic-gate struct netconfig *netconfigp; /* holds the new netconfig structure */
3280Sstevel@tonic-gate char *tok1, *tok2, *tok3; /* holds a token from the line */
3290Sstevel@tonic-gate char *retvalp; /* the return value of fgets() */
3300Sstevel@tonic-gate char *entnetid; /* netid for the current entry */
3310Sstevel@tonic-gate
3320Sstevel@tonic-gate /* skip past blank lines and comments. */
3331914Scasper while (retvalp = fgets(linep, BUFSIZ, fp)) {
3340Sstevel@tonic-gate linenum++;
3350Sstevel@tonic-gate if (!(blank(linep) || comment(linep))) {
3360Sstevel@tonic-gate break;
3370Sstevel@tonic-gate }
3380Sstevel@tonic-gate retvalp = NULL;
3390Sstevel@tonic-gate }
3400Sstevel@tonic-gate if (retvalp == NULL) {
3410Sstevel@tonic-gate nc_error = NC_NOMOREENTRIES;
3420Sstevel@tonic-gate return (NULL);
3430Sstevel@tonic-gate }
3440Sstevel@tonic-gate fieldnum = 0;
3450Sstevel@tonic-gate if ((entnetid = gettoken(linep, FALSE)) == NULL) {
3460Sstevel@tonic-gate nc_error = NC_BADLINE;
3470Sstevel@tonic-gate return (NULL);
3480Sstevel@tonic-gate }
3490Sstevel@tonic-gate if (netid && (strcmp(netid, entnetid) != 0)) {
3500Sstevel@tonic-gate free(entnetid);
3510Sstevel@tonic-gate nc_error = NC_NOTFOUND;
3520Sstevel@tonic-gate return (NULL);
3530Sstevel@tonic-gate }
354132Srobinson if ((netconfigp = calloc(1, sizeof (struct netconfig))) == NULL) {
3550Sstevel@tonic-gate free(entnetid);
3560Sstevel@tonic-gate nc_error = NC_NOMEM;
3570Sstevel@tonic-gate return (NULL);
3580Sstevel@tonic-gate }
3590Sstevel@tonic-gate
3600Sstevel@tonic-gate tok1 = tok2 = tok3 = NULL;
3610Sstevel@tonic-gate netconfigp->nc_netid = entnetid;
3620Sstevel@tonic-gate if (((tok1 = gettoken(NULL, FALSE)) == NULL) ||
3630Sstevel@tonic-gate ((netconfigp->nc_semantics =
3640Sstevel@tonic-gate getvalue(tok1, nc_semantics)) == FAILURE) ||
3650Sstevel@tonic-gate ((tok2 = gettoken(NULL, FALSE)) == NULL) ||
3660Sstevel@tonic-gate ((netconfigp->nc_flag = getflag(tok2)) == FAILURE) ||
3670Sstevel@tonic-gate ((netconfigp->nc_protofmly = gettoken(NULL, FALSE)) == NULL) ||
3680Sstevel@tonic-gate ((netconfigp->nc_proto = gettoken(NULL, FALSE)) == NULL) ||
3690Sstevel@tonic-gate ((netconfigp->nc_device = gettoken(NULL, FALSE)) == NULL) ||
3700Sstevel@tonic-gate ((tok3 = gettoken(NULL, TRUE)) == NULL) ||
3710Sstevel@tonic-gate (((netconfigp->nc_nlookups = getnlookups(tok3)) != 0) &&
3720Sstevel@tonic-gate ((netconfigp->nc_lookups = getlookups(tok3)) == NULL))) {
3730Sstevel@tonic-gate netconfig_free(netconfigp);
3740Sstevel@tonic-gate nc_error = NC_BADLINE;
3750Sstevel@tonic-gate netconfigp = NULL;
3760Sstevel@tonic-gate }
3770Sstevel@tonic-gate free(tok1);
3780Sstevel@tonic-gate free(tok2);
3790Sstevel@tonic-gate free(tok3);
3800Sstevel@tonic-gate return (netconfigp);
3810Sstevel@tonic-gate }
3820Sstevel@tonic-gate
3830Sstevel@tonic-gate /*
3840Sstevel@tonic-gate * setnetpath() has the effect of "initializing" the
3850Sstevel@tonic-gate * NETPATH variable. It reads in the netcf entries (if not
3860Sstevel@tonic-gate * already read in), creates a list corresponding to the entries
3870Sstevel@tonic-gate * in the NETPATH variable (or the "visible" entries og netconfig
3880Sstevel@tonic-gate * if NETPATH is not set).
3890Sstevel@tonic-gate */
3900Sstevel@tonic-gate
3910Sstevel@tonic-gate void *
setnetpath(void)392132Srobinson setnetpath(void)
3930Sstevel@tonic-gate {
3940Sstevel@tonic-gate int count; /* the number of entries in NETPATH */
3950Sstevel@tonic-gate char valid_netpath[BUFSIZ]; /* holds the valid entries if NETPATH */
3960Sstevel@tonic-gate char templine[BUFSIZ]; /* has value of NETPATH when scanning */
3970Sstevel@tonic-gate struct netconfig **curr_pp; /* scans the list from NETPATH */
3980Sstevel@tonic-gate struct netconfig **tpp; /* scans the list from netconfig file */
3990Sstevel@tonic-gate struct netconfig **rnetpp; /* the list of entries from NETPATH */
4000Sstevel@tonic-gate char *netpath; /* value of NETPATH from environment */
4010Sstevel@tonic-gate char *netid; /* holds a component of NETPATH */
4020Sstevel@tonic-gate char *tp; /* used to scan NETPATH string */
4030Sstevel@tonic-gate NCONF_HANDLE *retp; /* the return value */
4040Sstevel@tonic-gate
4050Sstevel@tonic-gate /*
4060Sstevel@tonic-gate * Read in the netconfig database if not already read in
4070Sstevel@tonic-gate */
408132Srobinson (void) mutex_lock(&netpp_mutex);
4090Sstevel@tonic-gate if ((netpp == NULL) && ((netpp = getnetlist()) == NULL)) {
410132Srobinson (void) mutex_unlock(&netpp_mutex);
4110Sstevel@tonic-gate return (NULL);
4120Sstevel@tonic-gate }
413132Srobinson (void) mutex_unlock(&netpp_mutex);
4140Sstevel@tonic-gate
415132Srobinson if ((retp = malloc(sizeof (NCONF_HANDLE))) == NULL) {
4160Sstevel@tonic-gate nc_error = NC_NOMEM;
4170Sstevel@tonic-gate return (NULL);
4180Sstevel@tonic-gate }
4190Sstevel@tonic-gate
4200Sstevel@tonic-gate /*
4210Sstevel@tonic-gate * Get the valid entries of the NETPATH variable (and
4220Sstevel@tonic-gate * count the number of entries while doing it).
4230Sstevel@tonic-gate *
4240Sstevel@tonic-gate * This is done every time the procedure is called just
4250Sstevel@tonic-gate * in case NETPATH has changed from call to call.
4260Sstevel@tonic-gate *
4270Sstevel@tonic-gate * If NETPATH is too long, we ignore it altogether as
4280Sstevel@tonic-gate * it can only be a buffer overflow attack.
4290Sstevel@tonic-gate * Since we add one colon for each entry, but colons only
4300Sstevel@tonic-gate * need to exist between entries, we have to subtract one.
4310Sstevel@tonic-gate */
4320Sstevel@tonic-gate count = 0;
4330Sstevel@tonic-gate valid_netpath[0] = '\0';
4340Sstevel@tonic-gate if ((netpath = getenv(NETPATH)) == NULL ||
4350Sstevel@tonic-gate strlen(netpath) >= sizeof (templine) - 1) {
4360Sstevel@tonic-gate /*
4370Sstevel@tonic-gate * If NETPATH variable is not set or invalid,
4380Sstevel@tonic-gate * the valid NETPATH consist of all "visible"
4390Sstevel@tonic-gate * netids from the netconfig database.
4400Sstevel@tonic-gate */
4410Sstevel@tonic-gate
4420Sstevel@tonic-gate for (tpp = netpp; *tpp; tpp++) {
4430Sstevel@tonic-gate if ((*tpp)->nc_flag & NC_VISIBLE) {
4440Sstevel@tonic-gate (void) strcat(valid_netpath, (*tpp)->nc_netid);
4450Sstevel@tonic-gate (void) strcat(valid_netpath, ":");
4460Sstevel@tonic-gate count++;
4470Sstevel@tonic-gate }
4480Sstevel@tonic-gate }
4490Sstevel@tonic-gate } else {
4500Sstevel@tonic-gate
4510Sstevel@tonic-gate /*
4520Sstevel@tonic-gate * Copy the value of NETPATH (since '\0's will be
4530Sstevel@tonic-gate * put into the string) and create the valid NETPATH
4540Sstevel@tonic-gate * (by throwing away all netids not in the database).
4550Sstevel@tonic-gate * If an entry appears more than one, it *will* be
4560Sstevel@tonic-gate * listed twice in the list of valid netpath entries.
4570Sstevel@tonic-gate */
4580Sstevel@tonic-gate
4590Sstevel@tonic-gate (void) strcpy(templine, netpath);
4600Sstevel@tonic-gate tp = templine;
4610Sstevel@tonic-gate
4620Sstevel@tonic-gate while (*tp) {
4630Sstevel@tonic-gate /* Skip all leading ':'s */
4640Sstevel@tonic-gate while (*tp && *tp == ':')
4650Sstevel@tonic-gate tp++;
4660Sstevel@tonic-gate if (*tp == NULL)
4670Sstevel@tonic-gate break; /* last one */
4680Sstevel@tonic-gate netid = tp;
4690Sstevel@tonic-gate while (*tp && *tp != ':')
4700Sstevel@tonic-gate tp++;
4710Sstevel@tonic-gate if (*tp)
4720Sstevel@tonic-gate *tp++ = '\0'; /* isolate netid */
4730Sstevel@tonic-gate
4740Sstevel@tonic-gate for (tpp = netpp; *tpp; tpp++) {
4750Sstevel@tonic-gate if (strcmp(netid, (*tpp)->nc_netid) == 0) {
4760Sstevel@tonic-gate (void) strcat(valid_netpath,
4770Sstevel@tonic-gate (*tpp)->nc_netid);
4780Sstevel@tonic-gate (void) strcat(valid_netpath, ":");
4790Sstevel@tonic-gate count++;
4800Sstevel@tonic-gate break;
4810Sstevel@tonic-gate }
4820Sstevel@tonic-gate }
4830Sstevel@tonic-gate }
4840Sstevel@tonic-gate }
4850Sstevel@tonic-gate
4860Sstevel@tonic-gate /* Get space to hold the valid list (+1 for the NULL) */
4870Sstevel@tonic-gate
488132Srobinson if ((rnetpp = malloc((count + 1) *
4890Sstevel@tonic-gate sizeof (struct netconfig *))) == NULL) {
490132Srobinson free(retp);
4910Sstevel@tonic-gate nc_error = NC_NOMEM;
4920Sstevel@tonic-gate return (NULL);
4930Sstevel@tonic-gate }
4940Sstevel@tonic-gate
4950Sstevel@tonic-gate /*
4960Sstevel@tonic-gate * Populate the NETPATH list, ending it with a NULL.
4970Sstevel@tonic-gate * Each entry in the list points to the structure in the
4980Sstevel@tonic-gate * "netpp" list (the entry must exist in the list, otherwise
4990Sstevel@tonic-gate * it wouldn't appear in valid_netpath[]).
5000Sstevel@tonic-gate */
5010Sstevel@tonic-gate
5020Sstevel@tonic-gate curr_pp = rnetpp;
5030Sstevel@tonic-gate netid = tp = valid_netpath;
5040Sstevel@tonic-gate while (*tp) {
5050Sstevel@tonic-gate netid = tp;
5060Sstevel@tonic-gate while (*tp && *tp != ':')
5070Sstevel@tonic-gate tp++;
5080Sstevel@tonic-gate if (*tp)
5090Sstevel@tonic-gate *tp++ = '\0';
5100Sstevel@tonic-gate for (tpp = netpp; *tpp; tpp++) {
5110Sstevel@tonic-gate if (strcmp(netid, (*tpp)->nc_netid) == 0) {
5120Sstevel@tonic-gate *curr_pp++ = *tpp;
5130Sstevel@tonic-gate break;
5140Sstevel@tonic-gate }
5150Sstevel@tonic-gate }
5160Sstevel@tonic-gate }
5170Sstevel@tonic-gate *curr_pp = NULL;
5180Sstevel@tonic-gate
5190Sstevel@tonic-gate retp->nc_curr = retp->nc_head = rnetpp;
5200Sstevel@tonic-gate return ((void *)retp);
5210Sstevel@tonic-gate }
5220Sstevel@tonic-gate
5230Sstevel@tonic-gate /*
5240Sstevel@tonic-gate * endnetpath() frees up all of the memory allocated by setnetpath().
5250Sstevel@tonic-gate * It returns -1 (error) if setnetpath was never called.
5260Sstevel@tonic-gate */
5270Sstevel@tonic-gate
5280Sstevel@tonic-gate int
endnetpath(void * vdata)529132Srobinson endnetpath(void *vdata)
5300Sstevel@tonic-gate {
5310Sstevel@tonic-gate /* The argument is really a NCONF_HANDLE; cast it here */
5320Sstevel@tonic-gate NCONF_HANDLE *nconf_handlep = (NCONF_HANDLE *)vdata;
5330Sstevel@tonic-gate
534132Srobinson (void) mutex_lock(&netpp_mutex);
5350Sstevel@tonic-gate if (netpp == NULL || nconf_handlep == NULL) {
5360Sstevel@tonic-gate nc_error = NC_NOSET;
537132Srobinson (void) mutex_unlock(&netpp_mutex);
5380Sstevel@tonic-gate return (-1);
5390Sstevel@tonic-gate }
540132Srobinson (void) mutex_unlock(&netpp_mutex);
5410Sstevel@tonic-gate
5420Sstevel@tonic-gate free(nconf_handlep->nc_head);
5430Sstevel@tonic-gate free(nconf_handlep);
5440Sstevel@tonic-gate return (0);
5450Sstevel@tonic-gate }
5460Sstevel@tonic-gate
5470Sstevel@tonic-gate /*
5480Sstevel@tonic-gate * getnetpath() returns the current entry in the list
5490Sstevel@tonic-gate * from the NETPATH variable. If setnetpath() was not called
5500Sstevel@tonic-gate * previously to set up the list, return NULL.
5510Sstevel@tonic-gate */
5520Sstevel@tonic-gate
5530Sstevel@tonic-gate struct netconfig *
getnetpath(void * vdata)554132Srobinson getnetpath(void *vdata)
5550Sstevel@tonic-gate {
5560Sstevel@tonic-gate /* The argument is really a NCONF_HANDLE; cast it here */
5570Sstevel@tonic-gate NCONF_HANDLE *nconf_handlep = (NCONF_HANDLE *)vdata;
5580Sstevel@tonic-gate struct netconfig *retp; /* holds the return value */
5590Sstevel@tonic-gate int ipv6_present = -1;
5600Sstevel@tonic-gate
561132Srobinson (void) mutex_lock(&netpp_mutex);
5620Sstevel@tonic-gate if (netpp == NULL) {
5630Sstevel@tonic-gate nc_error = NC_NOSET;
564132Srobinson (void) mutex_unlock(&netpp_mutex);
5650Sstevel@tonic-gate return (NULL);
5660Sstevel@tonic-gate }
567132Srobinson (void) mutex_unlock(&netpp_mutex);
5680Sstevel@tonic-gate for (;;) {
5690Sstevel@tonic-gate retp = *(nconf_handlep->nc_curr);
5700Sstevel@tonic-gate if (retp && (strcmp(retp->nc_netid, "udp6") == 0 ||
5710Sstevel@tonic-gate strcmp(retp->nc_netid, "tcp6") == 0)) {
5720Sstevel@tonic-gate if (ipv6_present == -1)
5730Sstevel@tonic-gate ipv6_present = __can_use_af(AF_INET6);
5740Sstevel@tonic-gate if (!ipv6_present) {
5750Sstevel@tonic-gate ++(nconf_handlep->nc_curr);
5760Sstevel@tonic-gate continue;
5770Sstevel@tonic-gate }
5780Sstevel@tonic-gate }
5790Sstevel@tonic-gate break;
5800Sstevel@tonic-gate }
5810Sstevel@tonic-gate if (retp) {
5820Sstevel@tonic-gate ++(nconf_handlep->nc_curr);
5830Sstevel@tonic-gate nc_error = NC_NOERROR;
5840Sstevel@tonic-gate } else {
5850Sstevel@tonic-gate nc_error = NC_NOMOREENTRIES;
5860Sstevel@tonic-gate }
5870Sstevel@tonic-gate
5880Sstevel@tonic-gate return (retp);
5890Sstevel@tonic-gate }
5900Sstevel@tonic-gate
5910Sstevel@tonic-gate /*
5920Sstevel@tonic-gate * blank() returns true if the line is a blank line, 0 otherwise
5930Sstevel@tonic-gate */
5940Sstevel@tonic-gate
5950Sstevel@tonic-gate static int
blank(char * cp)596132Srobinson blank(char *cp)
5970Sstevel@tonic-gate {
5980Sstevel@tonic-gate while (*cp && isspace(*cp)) {
5990Sstevel@tonic-gate cp++;
6000Sstevel@tonic-gate }
6010Sstevel@tonic-gate return (*cp == '\0');
6020Sstevel@tonic-gate }
6030Sstevel@tonic-gate
6040Sstevel@tonic-gate /*
6050Sstevel@tonic-gate * comment() returns true if the line is a comment, 0 otherwise.
6060Sstevel@tonic-gate */
6070Sstevel@tonic-gate
6080Sstevel@tonic-gate static int
comment(char * cp)609132Srobinson comment(char *cp)
6100Sstevel@tonic-gate {
6110Sstevel@tonic-gate while (*cp && isspace(*cp)) {
6120Sstevel@tonic-gate cp++;
6130Sstevel@tonic-gate }
6140Sstevel@tonic-gate return (*cp == '#');
6150Sstevel@tonic-gate }
6160Sstevel@tonic-gate
6170Sstevel@tonic-gate /*
6180Sstevel@tonic-gate * getvalue() searches for the given string in the given array,
6190Sstevel@tonic-gate * and return the integer value associated with the string.
6200Sstevel@tonic-gate */
6210Sstevel@tonic-gate
6220Sstevel@tonic-gate static unsigned int
getvalue(char * cp,struct nc_data nc_data[])623132Srobinson getvalue(char *cp, struct nc_data nc_data[])
6240Sstevel@tonic-gate {
6250Sstevel@tonic-gate int i; /* used to index through the given struct nc_data array */
6260Sstevel@tonic-gate
6270Sstevel@tonic-gate for (i = 0; nc_data[i].string; i++) {
6280Sstevel@tonic-gate if (strcmp(nc_data[i].string, cp) == 0) {
6290Sstevel@tonic-gate break;
6300Sstevel@tonic-gate }
6310Sstevel@tonic-gate }
6320Sstevel@tonic-gate return (nc_data[i].value);
6330Sstevel@tonic-gate }
6340Sstevel@tonic-gate
6350Sstevel@tonic-gate /*
6360Sstevel@tonic-gate * getflag() creates a bitmap of the one-character flags in
6370Sstevel@tonic-gate * the given string. It uses nc_flags array to get the values.
6380Sstevel@tonic-gate */
6390Sstevel@tonic-gate
6400Sstevel@tonic-gate static unsigned int
getflag(char * cp)641132Srobinson getflag(char *cp)
6420Sstevel@tonic-gate {
6430Sstevel@tonic-gate int i; /* indexs through the nc_flag array */
6440Sstevel@tonic-gate unsigned int mask = 0; /* holds bitmask of flags */
6450Sstevel@tonic-gate
6460Sstevel@tonic-gate while (*cp) {
6470Sstevel@tonic-gate for (i = 0; nc_flag[i].string; i++) {
6480Sstevel@tonic-gate if (*nc_flag[i].string == *cp) {
6490Sstevel@tonic-gate mask |= nc_flag[i].value;
6500Sstevel@tonic-gate break;
6510Sstevel@tonic-gate }
6520Sstevel@tonic-gate }
6530Sstevel@tonic-gate cp++;
6540Sstevel@tonic-gate }
6550Sstevel@tonic-gate return (mask);
6560Sstevel@tonic-gate }
6570Sstevel@tonic-gate
6580Sstevel@tonic-gate /*
6590Sstevel@tonic-gate * getlookups() creates and returns an array of string representing
6600Sstevel@tonic-gate * the directory lookup libraries, given as a comma-seperated list
6610Sstevel@tonic-gate * in the argument "cp".
6620Sstevel@tonic-gate */
6630Sstevel@tonic-gate
6640Sstevel@tonic-gate static char **
getlookups(char * cp)665132Srobinson getlookups(char *cp)
6660Sstevel@tonic-gate {
6670Sstevel@tonic-gate unsigned int num; /* holds the number of entries in the list */
6680Sstevel@tonic-gate char **listpp; /* the beginning of the list of dir routines */
6690Sstevel@tonic-gate char **tpp; /* traverses the list, populating it */
6700Sstevel@tonic-gate char *start;
6710Sstevel@tonic-gate
6720Sstevel@tonic-gate num = getnlookups(cp);
673132Srobinson if (num == 0)
6740Sstevel@tonic-gate return (NULL);
675132Srobinson if ((listpp = malloc((num + 1) * sizeof (char *))) == NULL)
6760Sstevel@tonic-gate return (NULL);
6770Sstevel@tonic-gate
6780Sstevel@tonic-gate tpp = listpp;
6790Sstevel@tonic-gate while (num--) {
6800Sstevel@tonic-gate start = cp;
6810Sstevel@tonic-gate
6820Sstevel@tonic-gate /*
6830Sstevel@tonic-gate * Traverse the string looking for the next entry
6840Sstevel@tonic-gate * of the list (i.e, where the ',' or end of the
6850Sstevel@tonic-gate * string appears). If a "\" is found, shift the
6860Sstevel@tonic-gate * token over 1 to the left (taking the next char
6870Sstevel@tonic-gate * literally).
6880Sstevel@tonic-gate */
6890Sstevel@tonic-gate
6900Sstevel@tonic-gate while (*cp && *cp != ',') {
6910Sstevel@tonic-gate if (*cp == '\\' && *(cp + 1)) {
6920Sstevel@tonic-gate shift1left(cp);
6930Sstevel@tonic-gate }
6940Sstevel@tonic-gate cp++;
6950Sstevel@tonic-gate }
6960Sstevel@tonic-gate if (*cp)
6970Sstevel@tonic-gate *cp++ = '\0';
6980Sstevel@tonic-gate if ((*tpp++ = strdup(start)) == NULL) {
6990Sstevel@tonic-gate for (tpp = listpp; *tpp; tpp++)
7000Sstevel@tonic-gate free(*tpp);
7010Sstevel@tonic-gate free(listpp);
7020Sstevel@tonic-gate return (NULL);
7030Sstevel@tonic-gate }
7040Sstevel@tonic-gate }
7050Sstevel@tonic-gate *tpp = NULL;
7060Sstevel@tonic-gate return (listpp);
7070Sstevel@tonic-gate }
7080Sstevel@tonic-gate
7090Sstevel@tonic-gate /*
7100Sstevel@tonic-gate * getnlookups() returns the number of entries in a comma-separated
7110Sstevel@tonic-gate * string of tokens. A "-" means no strings are present.
7120Sstevel@tonic-gate */
7130Sstevel@tonic-gate
7140Sstevel@tonic-gate static unsigned int
getnlookups(char * cp)715132Srobinson getnlookups(char *cp)
7160Sstevel@tonic-gate {
7170Sstevel@tonic-gate unsigned int count; /* the number of tokens in the string */
7180Sstevel@tonic-gate
719132Srobinson if (strcmp(cp, "-") == 0)
7200Sstevel@tonic-gate return (0);
7210Sstevel@tonic-gate
7220Sstevel@tonic-gate count = 1;
7230Sstevel@tonic-gate while (*cp) {
7240Sstevel@tonic-gate if (*cp == ',') {
7250Sstevel@tonic-gate count++;
7260Sstevel@tonic-gate }
7270Sstevel@tonic-gate
7280Sstevel@tonic-gate /*
7290Sstevel@tonic-gate * If a "\" is in the string, take the next character
7300Sstevel@tonic-gate * literally. Onlly skip the character if "\" is
7310Sstevel@tonic-gate * not the last character of the token.
7320Sstevel@tonic-gate */
7330Sstevel@tonic-gate if (*cp == '\\' && *(cp + 1)) {
7340Sstevel@tonic-gate cp++;
7350Sstevel@tonic-gate }
7360Sstevel@tonic-gate cp++;
7370Sstevel@tonic-gate }
7380Sstevel@tonic-gate return (count);
7390Sstevel@tonic-gate }
7400Sstevel@tonic-gate
7410Sstevel@tonic-gate /*
7420Sstevel@tonic-gate * gettoken() behaves much like strtok(), except that
7430Sstevel@tonic-gate * it knows about escaped space characters (i.e., space characters
7440Sstevel@tonic-gate * preceeded by a '\' are taken literally).
7450Sstevel@tonic-gate */
7460Sstevel@tonic-gate
7470Sstevel@tonic-gate static char *
gettoken(char * cp,int skip)748132Srobinson gettoken(char *cp, int skip)
7490Sstevel@tonic-gate {
7500Sstevel@tonic-gate static char *savep; /* the place where we left off */
7510Sstevel@tonic-gate char *p; /* the beginning of the new token */
7520Sstevel@tonic-gate char *retp; /* the token to be returned */
7530Sstevel@tonic-gate
7540Sstevel@tonic-gate fieldnum++;
7550Sstevel@tonic-gate
7560Sstevel@tonic-gate /* Determine if first or subsequent call */
7570Sstevel@tonic-gate p = (cp == NULL)? savep: cp;
7580Sstevel@tonic-gate
7590Sstevel@tonic-gate /* Return if no tokens remain. */
760132Srobinson if (p == 0)
7610Sstevel@tonic-gate return (NULL);
7620Sstevel@tonic-gate
7630Sstevel@tonic-gate while (isspace(*p))
7640Sstevel@tonic-gate p++;
7650Sstevel@tonic-gate
766132Srobinson if (*p == '\0')
7670Sstevel@tonic-gate return (NULL);
7680Sstevel@tonic-gate
7690Sstevel@tonic-gate /*
7700Sstevel@tonic-gate * Save the location of the token and then skip past it
7710Sstevel@tonic-gate */
7720Sstevel@tonic-gate
7730Sstevel@tonic-gate retp = p;
7740Sstevel@tonic-gate while (*p) {
7750Sstevel@tonic-gate if (isspace(*p))
7760Sstevel@tonic-gate if (skip == TRUE) {
7770Sstevel@tonic-gate shift1left(p);
7780Sstevel@tonic-gate continue;
7790Sstevel@tonic-gate } else
7800Sstevel@tonic-gate break;
7810Sstevel@tonic-gate /*
7820Sstevel@tonic-gate * Only process the escape of the space seperator;
7830Sstevel@tonic-gate * since the token may contain other separators,
7840Sstevel@tonic-gate * let the other routines handle the escape of
7850Sstevel@tonic-gate * specific characters in the token.
7860Sstevel@tonic-gate */
7870Sstevel@tonic-gate
7880Sstevel@tonic-gate if (*p == '\\' && *(p + 1) != '\n' && isspace(*(p + 1))) {
7890Sstevel@tonic-gate shift1left(p);
7900Sstevel@tonic-gate }
7910Sstevel@tonic-gate p++;
7920Sstevel@tonic-gate }
7930Sstevel@tonic-gate if (*p == '\0') {
7940Sstevel@tonic-gate savep = 0; /* indicate this is last token */
7950Sstevel@tonic-gate } else {
7960Sstevel@tonic-gate *p = '\0';
7970Sstevel@tonic-gate savep = ++p;
7980Sstevel@tonic-gate }
7990Sstevel@tonic-gate return (strdup(retp));
8000Sstevel@tonic-gate }
8010Sstevel@tonic-gate
8020Sstevel@tonic-gate /*
8030Sstevel@tonic-gate * shift1left() moves all characters in the string over 1 to
8040Sstevel@tonic-gate * the left.
8050Sstevel@tonic-gate */
8060Sstevel@tonic-gate
8070Sstevel@tonic-gate static void
shift1left(char * p)808132Srobinson shift1left(char *p)
8090Sstevel@tonic-gate {
8100Sstevel@tonic-gate for (; *p; p++)
8110Sstevel@tonic-gate *p = *(p + 1);
8120Sstevel@tonic-gate }
8130Sstevel@tonic-gate
8140Sstevel@tonic-gate char *
nc_sperror(void)815132Srobinson nc_sperror(void)
8160Sstevel@tonic-gate {
8170Sstevel@tonic-gate static char buf_main[BUFSIZ];
818*3864Sraf static pthread_key_t perror_key = PTHREAD_ONCE_KEY_NP;
8190Sstevel@tonic-gate char *retstr = thr_main()?
8200Sstevel@tonic-gate buf_main :
8210Sstevel@tonic-gate thr_get_storage(&perror_key, BUFSIZ, free);
8220Sstevel@tonic-gate
8230Sstevel@tonic-gate if (retstr == NULL) {
8240Sstevel@tonic-gate syslog(LOG_WARNING,
8250Sstevel@tonic-gate "nc_sperror: malloc failed when trying to create buffer\n");
8260Sstevel@tonic-gate return (NULL);
8270Sstevel@tonic-gate }
8280Sstevel@tonic-gate
8290Sstevel@tonic-gate switch (nc_error) {
8300Sstevel@tonic-gate case NC_NOERROR:
8310Sstevel@tonic-gate (void) strlcpy(retstr, dgettext(__nsl_dom, "no error"), BUFSIZ);
8320Sstevel@tonic-gate break;
8330Sstevel@tonic-gate case NC_NOMEM:
8340Sstevel@tonic-gate (void) strlcpy(retstr, dgettext(__nsl_dom, "out of memory"),
8350Sstevel@tonic-gate BUFSIZ);
8360Sstevel@tonic-gate break;
8370Sstevel@tonic-gate case NC_NOSET:
8380Sstevel@tonic-gate (void) strlcpy(retstr, dgettext(__nsl_dom,
8390Sstevel@tonic-gate "routine called before calling \
8400Sstevel@tonic-gate setnetpath() or setnetconfig()"), BUFSIZ);
8410Sstevel@tonic-gate break;
8420Sstevel@tonic-gate case NC_OPENFAIL:
8430Sstevel@tonic-gate (void) strlcpy(retstr,
8440Sstevel@tonic-gate dgettext(__nsl_dom, "cannot open /etc/netconfig"),
8450Sstevel@tonic-gate BUFSIZ);
8460Sstevel@tonic-gate break;
8470Sstevel@tonic-gate case NC_BADLINE:
8480Sstevel@tonic-gate (void) snprintf(retstr, BUFSIZ, dgettext(__nsl_dom,
8490Sstevel@tonic-gate "error in /etc/netconfig: field %d of line %d\n"),
8500Sstevel@tonic-gate fieldnum, linenum);
8510Sstevel@tonic-gate break;
8520Sstevel@tonic-gate case NC_NOTFOUND:
8530Sstevel@tonic-gate (void) snprintf(retstr, BUFSIZ,
8540Sstevel@tonic-gate dgettext(__nsl_dom,
8550Sstevel@tonic-gate "netid not found in /etc/netconfig"));
8560Sstevel@tonic-gate break;
8570Sstevel@tonic-gate case NC_NOMOREENTRIES:
8580Sstevel@tonic-gate (void) snprintf(retstr, BUFSIZ,
8590Sstevel@tonic-gate dgettext(__nsl_dom,
8600Sstevel@tonic-gate "no more entries in /etc/netconfig"));
8610Sstevel@tonic-gate break;
8620Sstevel@tonic-gate default:
8630Sstevel@tonic-gate (void) strlcpy(retstr, dgettext(__nsl_dom, "unknown error"),
8640Sstevel@tonic-gate BUFSIZ);
8650Sstevel@tonic-gate break;
8660Sstevel@tonic-gate }
8670Sstevel@tonic-gate return (retstr);
8680Sstevel@tonic-gate }
8690Sstevel@tonic-gate
8700Sstevel@tonic-gate void
nc_perror(const char * string)8710Sstevel@tonic-gate nc_perror(const char *string)
8720Sstevel@tonic-gate {
8730Sstevel@tonic-gate if (string)
874132Srobinson (void) fprintf(stderr, "%s: %s\n", string, nc_sperror());
8750Sstevel@tonic-gate else
876132Srobinson (void) fprintf(stderr, "%s\n", nc_sperror());
8770Sstevel@tonic-gate }
8780Sstevel@tonic-gate
8790Sstevel@tonic-gate static void
netlist_free(struct netconfig *** netppp)880132Srobinson netlist_free(struct netconfig ***netppp)
8810Sstevel@tonic-gate {
8820Sstevel@tonic-gate struct netconfig **tpp;
8830Sstevel@tonic-gate
8840Sstevel@tonic-gate for (tpp = *netppp; *tpp; tpp++) {
8850Sstevel@tonic-gate netconfig_free(*tpp);
8860Sstevel@tonic-gate }
8870Sstevel@tonic-gate free(*netppp);
8880Sstevel@tonic-gate *netppp = NULL;
8890Sstevel@tonic-gate }
8900Sstevel@tonic-gate
8910Sstevel@tonic-gate static void
netconfig_free(struct netconfig * netconfigp)892132Srobinson netconfig_free(struct netconfig *netconfigp)
8930Sstevel@tonic-gate {
8940Sstevel@tonic-gate int i;
8950Sstevel@tonic-gate
896132Srobinson if (netconfigp == NULL)
8970Sstevel@tonic-gate return;
8980Sstevel@tonic-gate free_entry(netconfigp->nc_netid);
8990Sstevel@tonic-gate free_entry(netconfigp->nc_protofmly);
9000Sstevel@tonic-gate free_entry(netconfigp->nc_proto);
9010Sstevel@tonic-gate free_entry(netconfigp->nc_device);
9020Sstevel@tonic-gate if (netconfigp->nc_lookups)
9030Sstevel@tonic-gate for (i = 0; i < netconfigp->nc_nlookups; i++)
9040Sstevel@tonic-gate free_entry(netconfigp->nc_lookups[i]);
9050Sstevel@tonic-gate free_entry(netconfigp->nc_lookups);
9060Sstevel@tonic-gate free(netconfigp);
9070Sstevel@tonic-gate }
9080Sstevel@tonic-gate
9090Sstevel@tonic-gate static struct netconfig *
netconfig_dup(struct netconfig * netconfigp)910132Srobinson netconfig_dup(struct netconfig *netconfigp)
9110Sstevel@tonic-gate {
9120Sstevel@tonic-gate struct netconfig *nconf;
9130Sstevel@tonic-gate int i;
9140Sstevel@tonic-gate
915132Srobinson nconf = calloc(1, sizeof (struct netconfig));
9160Sstevel@tonic-gate if (nconf == NULL) {
9170Sstevel@tonic-gate nc_error = NC_NOMEM;
9180Sstevel@tonic-gate return (NULL);
9190Sstevel@tonic-gate }
9200Sstevel@tonic-gate nconf->nc_netid = strdup(netconfigp->nc_netid);
9210Sstevel@tonic-gate nconf->nc_protofmly = strdup(netconfigp->nc_protofmly);
9220Sstevel@tonic-gate nconf->nc_proto = strdup(netconfigp->nc_proto);
9230Sstevel@tonic-gate nconf->nc_device = strdup(netconfigp->nc_device);
924132Srobinson nconf->nc_lookups = malloc((netconfigp->nc_nlookups + 1)
9250Sstevel@tonic-gate * sizeof (char *));
9260Sstevel@tonic-gate if (!(nconf->nc_lookups && nconf->nc_netid &&
9270Sstevel@tonic-gate nconf->nc_protofmly && nconf->nc_proto &&
9280Sstevel@tonic-gate nconf->nc_device)) {
9290Sstevel@tonic-gate nc_error = NC_NOMEM;
9300Sstevel@tonic-gate netconfig_free(nconf);
9310Sstevel@tonic-gate return (NULL);
9320Sstevel@tonic-gate }
9330Sstevel@tonic-gate
9340Sstevel@tonic-gate for (i = 0; i < netconfigp->nc_nlookups; i++) {
9350Sstevel@tonic-gate nconf->nc_lookups[i] = strdup(netconfigp->nc_lookups[i]);
9360Sstevel@tonic-gate if (nconf->nc_lookups[i] == NULL) {
9370Sstevel@tonic-gate nconf->nc_nlookups = i;
9380Sstevel@tonic-gate netconfig_free(nconf);
9390Sstevel@tonic-gate nc_error = NC_NOMEM;
9400Sstevel@tonic-gate return (NULL);
9410Sstevel@tonic-gate }
9420Sstevel@tonic-gate }
9430Sstevel@tonic-gate nconf->nc_lookups[i] = NULL;
9440Sstevel@tonic-gate nconf->nc_nlookups = netconfigp->nc_nlookups;
9450Sstevel@tonic-gate nconf->nc_flag = netconfigp->nc_flag;
9460Sstevel@tonic-gate nconf->nc_semantics = netconfigp->nc_semantics;
9470Sstevel@tonic-gate return (nconf);
9480Sstevel@tonic-gate }
9490Sstevel@tonic-gate
9500Sstevel@tonic-gate static void
free_entry(void * foo)951132Srobinson free_entry(void *foo)
9520Sstevel@tonic-gate {
9530Sstevel@tonic-gate if (foo)
9540Sstevel@tonic-gate free(foo);
9550Sstevel@tonic-gate }
956