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