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 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 22*61961e0fSrobinson 237c478bd9Sstevel@tonic-gate /* 24*61961e0fSrobinson * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 257c478bd9Sstevel@tonic-gate * Use is subject to license terms. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 297c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate /* 327c478bd9Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 4.3 BSD 337c478bd9Sstevel@tonic-gate * under license from the Regents of the University of California. 347c478bd9Sstevel@tonic-gate */ 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate #include "mt.h" 397c478bd9Sstevel@tonic-gate #include "../rpc/rpc_mt.h" /* for MT declarations only */ 407c478bd9Sstevel@tonic-gate #include <rpc/types.h> 417c478bd9Sstevel@tonic-gate #include <stdio.h> 42*61961e0fSrobinson #include <stdlib.h> 437c478bd9Sstevel@tonic-gate #include <string.h> 447c478bd9Sstevel@tonic-gate #include <ctype.h> 457c478bd9Sstevel@tonic-gate #include <netconfig.h> 467c478bd9Sstevel@tonic-gate #include <malloc.h> 47*61961e0fSrobinson #include <libintl.h> 487c478bd9Sstevel@tonic-gate #include <syslog.h> 497c478bd9Sstevel@tonic-gate #include "netcspace.h" 507c478bd9Sstevel@tonic-gate #include "nsl_stdio_prv.h" 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate #define FAILURE (unsigned)(-1) 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate /* 557c478bd9Sstevel@tonic-gate * Local routines used by the library procedures 567c478bd9Sstevel@tonic-gate */ 577c478bd9Sstevel@tonic-gate 58*61961e0fSrobinson static int blank(char *); 59*61961e0fSrobinson static int comment(char *); 60*61961e0fSrobinson static struct netconfig *fgetnetconfig(__NSL_FILE *, char *); 61*61961e0fSrobinson static void netconfig_free(struct netconfig *); 62*61961e0fSrobinson static unsigned int getflag(char *); 63*61961e0fSrobinson static char **getlookups(char *); 64*61961e0fSrobinson static struct netconfig **getnetlist(void); 65*61961e0fSrobinson static unsigned int getnlookups(char *); 66*61961e0fSrobinson static char *gettoken(char *, int); 67*61961e0fSrobinson static unsigned int getvalue(char *, struct nc_data nc_data[]); 68*61961e0fSrobinson static void shift1left(char *); 69*61961e0fSrobinson static void netlist_free(struct netconfig ***); 70*61961e0fSrobinson static void free_entry(void *); 71*61961e0fSrobinson static struct netconfig *netconfig_dup(struct netconfig *); 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate extern const char __nsl_dom[]; 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate /* 767c478bd9Sstevel@tonic-gate * Static global variables used by the library procedures: 777c478bd9Sstevel@tonic-gate * 787c478bd9Sstevel@tonic-gate * netpp - points to the beginning of the list of netconfig 797c478bd9Sstevel@tonic-gate * entries used by setnetconfig() and setnetpath(). 807c478bd9Sstevel@tonic-gate * Once netpp is initialized, that memory is *never* 817c478bd9Sstevel@tonic-gate * released. This was necessary to improve performance. 827c478bd9Sstevel@tonic-gate * 837c478bd9Sstevel@tonic-gate * linenum - the current line number of the /etc/netconfig 847c478bd9Sstevel@tonic-gate * file (used for debugging and for nc_perror()). 857c478bd9Sstevel@tonic-gate * 867c478bd9Sstevel@tonic-gate * fieldnum - the current field number of the current line 877c478bd9Sstevel@tonic-gate * of /etc/netconfig (used for debugging and for 887c478bd9Sstevel@tonic-gate * nc_perror()). 897c478bd9Sstevel@tonic-gate * 907c478bd9Sstevel@tonic-gate * nc_error - the error condition encountered. 917c478bd9Sstevel@tonic-gate */ 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate static struct netconfig **netpp = NULL; 947c478bd9Sstevel@tonic-gate mutex_t netpp_mutex = DEFAULTMUTEX; 957c478bd9Sstevel@tonic-gate /* 967c478bd9Sstevel@tonic-gate * The following two variables are used by the /etc/netconfig parsing 977c478bd9Sstevel@tonic-gate * routines, which will always be executed once, and within the netpp_mutex. 987c478bd9Sstevel@tonic-gate * They are global to allow the nc_sperror routine to provide better 997c478bd9Sstevel@tonic-gate * information to the user about /etc/netconfig file problems. 1007c478bd9Sstevel@tonic-gate */ 1017c478bd9Sstevel@tonic-gate static int linenum = 0; /* "owned" by getnetlist() */ 1027c478bd9Sstevel@tonic-gate static int fieldnum = 0; /* "owned" by fgetnetconfig() */ 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate static int * 106*61961e0fSrobinson __nc_error(void) 1077c478bd9Sstevel@tonic-gate { 1087c478bd9Sstevel@tonic-gate static pthread_key_t nc_error_key = 0; 1097c478bd9Sstevel@tonic-gate static int nc_error = NC_NOERROR; 1107c478bd9Sstevel@tonic-gate int *ret; 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate if (thr_main()) 1137c478bd9Sstevel@tonic-gate return (&nc_error); 1147c478bd9Sstevel@tonic-gate ret = thr_get_storage(&nc_error_key, sizeof (int), free); 1157c478bd9Sstevel@tonic-gate /* if thr_get_storage fails we return the address of nc_error */ 1167c478bd9Sstevel@tonic-gate return (ret ? ret : &nc_error); 1177c478bd9Sstevel@tonic-gate } 1187c478bd9Sstevel@tonic-gate #define nc_error (*(__nc_error())) 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate /* 1217c478bd9Sstevel@tonic-gate * setnetconfig() has the effect of "initializing" the 1227c478bd9Sstevel@tonic-gate * network configuration database. It reads in the 1237c478bd9Sstevel@tonic-gate * netcf entries (if not already read in). 1247c478bd9Sstevel@tonic-gate */ 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate void * 127*61961e0fSrobinson setnetconfig(void) 1287c478bd9Sstevel@tonic-gate { 1297c478bd9Sstevel@tonic-gate NCONF_HANDLE *retp; 1307c478bd9Sstevel@tonic-gate 131*61961e0fSrobinson (void) mutex_lock(&netpp_mutex); 1327c478bd9Sstevel@tonic-gate if ((netpp == NULL) && ((netpp = getnetlist()) == NULL)) { 133*61961e0fSrobinson (void) mutex_unlock(&netpp_mutex); 1347c478bd9Sstevel@tonic-gate return (NULL); 1357c478bd9Sstevel@tonic-gate } 136*61961e0fSrobinson (void) mutex_unlock(&netpp_mutex); 137*61961e0fSrobinson if ((retp = malloc(sizeof (NCONF_HANDLE))) == NULL) { 1387c478bd9Sstevel@tonic-gate nc_error = NC_NOMEM; 1397c478bd9Sstevel@tonic-gate return (NULL); 1407c478bd9Sstevel@tonic-gate } 1417c478bd9Sstevel@tonic-gate nc_error = NC_NOERROR; 1427c478bd9Sstevel@tonic-gate retp->nc_head = retp->nc_curr = netpp; 1437c478bd9Sstevel@tonic-gate return ((void *)retp); 1447c478bd9Sstevel@tonic-gate } 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate /* 1477c478bd9Sstevel@tonic-gate * endnetconfig() frees up all data allocated by setnetconfig() 1487c478bd9Sstevel@tonic-gate */ 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate int 151*61961e0fSrobinson endnetconfig(void *vdata) 1527c478bd9Sstevel@tonic-gate { 1537c478bd9Sstevel@tonic-gate NCONF_HANDLE *nconf_handlep = (NCONF_HANDLE *)vdata; 1547c478bd9Sstevel@tonic-gate 155*61961e0fSrobinson (void) mutex_lock(&netpp_mutex); 1567c478bd9Sstevel@tonic-gate if (netpp == NULL || nconf_handlep == NULL) { 1577c478bd9Sstevel@tonic-gate nc_error = NC_NOSET; 158*61961e0fSrobinson (void) mutex_unlock(&netpp_mutex); 1597c478bd9Sstevel@tonic-gate return (-1); 1607c478bd9Sstevel@tonic-gate } 161*61961e0fSrobinson (void) mutex_unlock(&netpp_mutex); 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate nc_error = NC_NOERROR; 164*61961e0fSrobinson free(nconf_handlep); 1657c478bd9Sstevel@tonic-gate return (0); 1667c478bd9Sstevel@tonic-gate } 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate /* 1697c478bd9Sstevel@tonic-gate * getnetconfig() returns the current entry in the list 1707c478bd9Sstevel@tonic-gate * of netconfig structures. It uses the nconf_handlep argument 1717c478bd9Sstevel@tonic-gate * to determine the current entry. If setnetconfig() was not 1727c478bd9Sstevel@tonic-gate * called previously to set up the list, return failure. 1737c478bd9Sstevel@tonic-gate * It also check if ipv6 interface is present(ipv6_present) and 1747c478bd9Sstevel@tonic-gate * skips udp6 & tcp6 entries if ipv6 is not supported. 1757c478bd9Sstevel@tonic-gate */ 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate struct netconfig * 178*61961e0fSrobinson getnetconfig(void *vdata) 1797c478bd9Sstevel@tonic-gate { 1807c478bd9Sstevel@tonic-gate NCONF_HANDLE *nconf_handlep = (NCONF_HANDLE *)vdata; 1817c478bd9Sstevel@tonic-gate struct netconfig *retp; /* holds the return value */ 1827c478bd9Sstevel@tonic-gate int ipv6_present = -1; 1837c478bd9Sstevel@tonic-gate 184*61961e0fSrobinson (void) mutex_lock(&netpp_mutex); 1857c478bd9Sstevel@tonic-gate if ((netpp == NULL) || (nconf_handlep == NULL)) { 1867c478bd9Sstevel@tonic-gate nc_error = NC_NOSET; 187*61961e0fSrobinson (void) mutex_unlock(&netpp_mutex); 1887c478bd9Sstevel@tonic-gate return (NULL); 1897c478bd9Sstevel@tonic-gate } 190*61961e0fSrobinson (void) mutex_unlock(&netpp_mutex); 1917c478bd9Sstevel@tonic-gate for (;;) { 1927c478bd9Sstevel@tonic-gate retp = *(nconf_handlep->nc_curr); 1937c478bd9Sstevel@tonic-gate if (retp && (strcmp(retp->nc_netid, "udp6") == 0 || 1947c478bd9Sstevel@tonic-gate strcmp(retp->nc_netid, "tcp6") == 0)) { 1957c478bd9Sstevel@tonic-gate if (ipv6_present == -1) 1967c478bd9Sstevel@tonic-gate ipv6_present = __can_use_af(AF_INET6); 1977c478bd9Sstevel@tonic-gate if (!ipv6_present) { 1987c478bd9Sstevel@tonic-gate ++(nconf_handlep->nc_curr); 1997c478bd9Sstevel@tonic-gate continue; 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate } 2027c478bd9Sstevel@tonic-gate break; 2037c478bd9Sstevel@tonic-gate } 2047c478bd9Sstevel@tonic-gate if (retp != NULL) { 2057c478bd9Sstevel@tonic-gate ++(nconf_handlep->nc_curr); 2067c478bd9Sstevel@tonic-gate nc_error = NC_NOERROR; 2077c478bd9Sstevel@tonic-gate } else { 2087c478bd9Sstevel@tonic-gate nc_error = NC_NOMOREENTRIES; 2097c478bd9Sstevel@tonic-gate } 2107c478bd9Sstevel@tonic-gate return (retp); 2117c478bd9Sstevel@tonic-gate } 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate /* 2147c478bd9Sstevel@tonic-gate * getnetconfig() searches the netconfig database for a 2157c478bd9Sstevel@tonic-gate * given network id. Returns a pointer to the netconfig 2167c478bd9Sstevel@tonic-gate * structure or a NULL if not found. 2177c478bd9Sstevel@tonic-gate * It also check if ipv6 interface is present(ipv6_present) and 2187c478bd9Sstevel@tonic-gate * skips udp6 & tcp6 entries if ipv6 is not supported. 2197c478bd9Sstevel@tonic-gate */ 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate struct netconfig * 222*61961e0fSrobinson getnetconfigent(const char *netid) 2237c478bd9Sstevel@tonic-gate { 2247c478bd9Sstevel@tonic-gate struct netconfig **tpp; 2257c478bd9Sstevel@tonic-gate int ipv6_present; 2267c478bd9Sstevel@tonic-gate 227*61961e0fSrobinson (void) mutex_lock(&netpp_mutex); 2287c478bd9Sstevel@tonic-gate if ((netpp == NULL) && ((netpp = getnetlist()) == NULL)) { 229*61961e0fSrobinson (void) mutex_unlock(&netpp_mutex); 2307c478bd9Sstevel@tonic-gate return (NULL); 2317c478bd9Sstevel@tonic-gate } 232*61961e0fSrobinson (void) mutex_unlock(&netpp_mutex); 2337c478bd9Sstevel@tonic-gate for (tpp = netpp; *tpp; tpp++) { 2347c478bd9Sstevel@tonic-gate if (strcmp((*tpp)->nc_netid, netid) == 0) { 2357c478bd9Sstevel@tonic-gate if (*tpp && (strcmp((*tpp)->nc_netid, "udp6") == 0 || 2367c478bd9Sstevel@tonic-gate strcmp((*tpp)->nc_netid, "tcp6") == 0)) { 2377c478bd9Sstevel@tonic-gate ipv6_present = __can_use_af(AF_INET6); 2387c478bd9Sstevel@tonic-gate if (!ipv6_present) { 2397c478bd9Sstevel@tonic-gate nc_error = NC_NOTFOUND; 2407c478bd9Sstevel@tonic-gate return (NULL); 2417c478bd9Sstevel@tonic-gate } 2427c478bd9Sstevel@tonic-gate } 2437c478bd9Sstevel@tonic-gate return (netconfig_dup(*tpp)); 2447c478bd9Sstevel@tonic-gate } 2457c478bd9Sstevel@tonic-gate } 2467c478bd9Sstevel@tonic-gate nc_error = NC_NOTFOUND; 2477c478bd9Sstevel@tonic-gate return (NULL); 2487c478bd9Sstevel@tonic-gate } 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate /* 2517c478bd9Sstevel@tonic-gate * freenetconfigent frees the data allocated by getnetconfigent() 2527c478bd9Sstevel@tonic-gate */ 2537c478bd9Sstevel@tonic-gate 2547c478bd9Sstevel@tonic-gate void 255*61961e0fSrobinson freenetconfigent(struct netconfig *netp) 2567c478bd9Sstevel@tonic-gate { 2577c478bd9Sstevel@tonic-gate netconfig_free(netp); 2587c478bd9Sstevel@tonic-gate } 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate /* 2617c478bd9Sstevel@tonic-gate * getnetlist() reads the netconfig file and creates a 2627c478bd9Sstevel@tonic-gate * NULL-terminated list of entries. 2637c478bd9Sstevel@tonic-gate * Returns the pointer to the head of the list or a NULL 2647c478bd9Sstevel@tonic-gate * on failure. 2657c478bd9Sstevel@tonic-gate */ 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate static struct netconfig ** 268*61961e0fSrobinson getnetlist(void) 2697c478bd9Sstevel@tonic-gate { 2707c478bd9Sstevel@tonic-gate char line[BUFSIZ]; /* holds each line of NETCONFIG */ 2717c478bd9Sstevel@tonic-gate __NSL_FILE *fp; /* file stream for NETCONFIG */ 2727c478bd9Sstevel@tonic-gate struct netconfig **listpp; /* the beginning of the netconfig list */ 2737c478bd9Sstevel@tonic-gate struct netconfig **tpp; /* used to traverse the netconfig list */ 2747c478bd9Sstevel@tonic-gate int count; /* the number of entries in file */ 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate if ((fp = __nsl_fopen(NETCONFIG, "r")) == NULL) { 2777c478bd9Sstevel@tonic-gate nc_error = NC_OPENFAIL; 2787c478bd9Sstevel@tonic-gate return (NULL); 2797c478bd9Sstevel@tonic-gate } 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate count = 0; 2827c478bd9Sstevel@tonic-gate while (__nsl_fgets(line, BUFSIZ, fp)) { 2837c478bd9Sstevel@tonic-gate if (!(blank(line) || comment(line))) { 2847c478bd9Sstevel@tonic-gate ++count; 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate __nsl_rewind(fp); 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate if (count == 0) { 2907c478bd9Sstevel@tonic-gate nc_error = NC_NOTFOUND; 2917c478bd9Sstevel@tonic-gate (void) __nsl_fclose(fp); 2927c478bd9Sstevel@tonic-gate return (NULL); 2937c478bd9Sstevel@tonic-gate } 294*61961e0fSrobinson if ((listpp = malloc((count + 1) * 2957c478bd9Sstevel@tonic-gate sizeof (struct netconfig *))) == NULL) { 2967c478bd9Sstevel@tonic-gate nc_error = NC_NOMEM; 2977c478bd9Sstevel@tonic-gate (void) __nsl_fclose(fp); 2987c478bd9Sstevel@tonic-gate return (NULL); 2997c478bd9Sstevel@tonic-gate } 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate /* 3027c478bd9Sstevel@tonic-gate * The following loop fills in the list (loops until 3037c478bd9Sstevel@tonic-gate * fgetnetconfig() returns a NULL) and counts the 3047c478bd9Sstevel@tonic-gate * number of entries placed in the list. Note that 3057c478bd9Sstevel@tonic-gate * when the loop is completed, the last entry in the 3067c478bd9Sstevel@tonic-gate * list will contain a NULL (signifying the end of 3077c478bd9Sstevel@tonic-gate * the list). 3087c478bd9Sstevel@tonic-gate */ 3097c478bd9Sstevel@tonic-gate linenum = 0; 3107c478bd9Sstevel@tonic-gate for (tpp = listpp; *tpp = fgetnetconfig(fp, NULL); tpp++) 3117c478bd9Sstevel@tonic-gate ; 3127c478bd9Sstevel@tonic-gate (void) __nsl_fclose(fp); 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate if (nc_error != NC_NOMOREENTRIES) /* Something is screwed up */ 3157c478bd9Sstevel@tonic-gate netlist_free(&listpp); 3167c478bd9Sstevel@tonic-gate return (listpp); 3177c478bd9Sstevel@tonic-gate } 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate /* 3207c478bd9Sstevel@tonic-gate * fgetnetconfig() parses a line of the netconfig file into 3217c478bd9Sstevel@tonic-gate * a netconfig structure. It returns a pointer to the 3227c478bd9Sstevel@tonic-gate * structure of success and a NULL on failure or EOF. 3237c478bd9Sstevel@tonic-gate */ 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate static struct netconfig * 326*61961e0fSrobinson fgetnetconfig(__NSL_FILE *fp, char *netid) 3277c478bd9Sstevel@tonic-gate { 3287c478bd9Sstevel@tonic-gate char linep[BUFSIZ]; /* pointer to a line in the file */ 3297c478bd9Sstevel@tonic-gate struct netconfig *netconfigp; /* holds the new netconfig structure */ 3307c478bd9Sstevel@tonic-gate char *tok1, *tok2, *tok3; /* holds a token from the line */ 3317c478bd9Sstevel@tonic-gate char *retvalp; /* the return value of fgets() */ 3327c478bd9Sstevel@tonic-gate char *entnetid; /* netid for the current entry */ 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate /* skip past blank lines and comments. */ 3357c478bd9Sstevel@tonic-gate while (retvalp = __nsl_fgets(linep, BUFSIZ, fp)) { 3367c478bd9Sstevel@tonic-gate linenum++; 3377c478bd9Sstevel@tonic-gate if (!(blank(linep) || comment(linep))) { 3387c478bd9Sstevel@tonic-gate break; 3397c478bd9Sstevel@tonic-gate } 3407c478bd9Sstevel@tonic-gate retvalp = NULL; 3417c478bd9Sstevel@tonic-gate } 3427c478bd9Sstevel@tonic-gate if (retvalp == NULL) { 3437c478bd9Sstevel@tonic-gate nc_error = NC_NOMOREENTRIES; 3447c478bd9Sstevel@tonic-gate return (NULL); 3457c478bd9Sstevel@tonic-gate } 3467c478bd9Sstevel@tonic-gate fieldnum = 0; 3477c478bd9Sstevel@tonic-gate if ((entnetid = gettoken(linep, FALSE)) == NULL) { 3487c478bd9Sstevel@tonic-gate nc_error = NC_BADLINE; 3497c478bd9Sstevel@tonic-gate return (NULL); 3507c478bd9Sstevel@tonic-gate } 3517c478bd9Sstevel@tonic-gate if (netid && (strcmp(netid, entnetid) != 0)) { 3527c478bd9Sstevel@tonic-gate free(entnetid); 3537c478bd9Sstevel@tonic-gate nc_error = NC_NOTFOUND; 3547c478bd9Sstevel@tonic-gate return (NULL); 3557c478bd9Sstevel@tonic-gate } 356*61961e0fSrobinson if ((netconfigp = calloc(1, sizeof (struct netconfig))) == NULL) { 3577c478bd9Sstevel@tonic-gate free(entnetid); 3587c478bd9Sstevel@tonic-gate nc_error = NC_NOMEM; 3597c478bd9Sstevel@tonic-gate return (NULL); 3607c478bd9Sstevel@tonic-gate } 3617c478bd9Sstevel@tonic-gate 3627c478bd9Sstevel@tonic-gate tok1 = tok2 = tok3 = NULL; 3637c478bd9Sstevel@tonic-gate netconfigp->nc_netid = entnetid; 3647c478bd9Sstevel@tonic-gate if (((tok1 = gettoken(NULL, FALSE)) == NULL) || 3657c478bd9Sstevel@tonic-gate ((netconfigp->nc_semantics = 3667c478bd9Sstevel@tonic-gate getvalue(tok1, nc_semantics)) == FAILURE) || 3677c478bd9Sstevel@tonic-gate ((tok2 = gettoken(NULL, FALSE)) == NULL) || 3687c478bd9Sstevel@tonic-gate ((netconfigp->nc_flag = getflag(tok2)) == FAILURE) || 3697c478bd9Sstevel@tonic-gate ((netconfigp->nc_protofmly = gettoken(NULL, FALSE)) == NULL) || 3707c478bd9Sstevel@tonic-gate ((netconfigp->nc_proto = gettoken(NULL, FALSE)) == NULL) || 3717c478bd9Sstevel@tonic-gate ((netconfigp->nc_device = gettoken(NULL, FALSE)) == NULL) || 3727c478bd9Sstevel@tonic-gate ((tok3 = gettoken(NULL, TRUE)) == NULL) || 3737c478bd9Sstevel@tonic-gate (((netconfigp->nc_nlookups = getnlookups(tok3)) != 0) && 3747c478bd9Sstevel@tonic-gate ((netconfigp->nc_lookups = getlookups(tok3)) == NULL))) { 3757c478bd9Sstevel@tonic-gate netconfig_free(netconfigp); 3767c478bd9Sstevel@tonic-gate nc_error = NC_BADLINE; 3777c478bd9Sstevel@tonic-gate netconfigp = NULL; 3787c478bd9Sstevel@tonic-gate } 3797c478bd9Sstevel@tonic-gate free(tok1); 3807c478bd9Sstevel@tonic-gate free(tok2); 3817c478bd9Sstevel@tonic-gate free(tok3); 3827c478bd9Sstevel@tonic-gate return (netconfigp); 3837c478bd9Sstevel@tonic-gate } 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate /* 3867c478bd9Sstevel@tonic-gate * setnetpath() has the effect of "initializing" the 3877c478bd9Sstevel@tonic-gate * NETPATH variable. It reads in the netcf entries (if not 3887c478bd9Sstevel@tonic-gate * already read in), creates a list corresponding to the entries 3897c478bd9Sstevel@tonic-gate * in the NETPATH variable (or the "visible" entries og netconfig 3907c478bd9Sstevel@tonic-gate * if NETPATH is not set). 3917c478bd9Sstevel@tonic-gate */ 3927c478bd9Sstevel@tonic-gate 3937c478bd9Sstevel@tonic-gate void * 394*61961e0fSrobinson setnetpath(void) 3957c478bd9Sstevel@tonic-gate { 3967c478bd9Sstevel@tonic-gate int count; /* the number of entries in NETPATH */ 3977c478bd9Sstevel@tonic-gate char valid_netpath[BUFSIZ]; /* holds the valid entries if NETPATH */ 3987c478bd9Sstevel@tonic-gate char templine[BUFSIZ]; /* has value of NETPATH when scanning */ 3997c478bd9Sstevel@tonic-gate struct netconfig **curr_pp; /* scans the list from NETPATH */ 4007c478bd9Sstevel@tonic-gate struct netconfig **tpp; /* scans the list from netconfig file */ 4017c478bd9Sstevel@tonic-gate struct netconfig **rnetpp; /* the list of entries from NETPATH */ 4027c478bd9Sstevel@tonic-gate char *netpath; /* value of NETPATH from environment */ 4037c478bd9Sstevel@tonic-gate char *netid; /* holds a component of NETPATH */ 4047c478bd9Sstevel@tonic-gate char *tp; /* used to scan NETPATH string */ 4057c478bd9Sstevel@tonic-gate NCONF_HANDLE *retp; /* the return value */ 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate /* 4087c478bd9Sstevel@tonic-gate * Read in the netconfig database if not already read in 4097c478bd9Sstevel@tonic-gate */ 410*61961e0fSrobinson (void) mutex_lock(&netpp_mutex); 4117c478bd9Sstevel@tonic-gate if ((netpp == NULL) && ((netpp = getnetlist()) == NULL)) { 412*61961e0fSrobinson (void) mutex_unlock(&netpp_mutex); 4137c478bd9Sstevel@tonic-gate return (NULL); 4147c478bd9Sstevel@tonic-gate } 415*61961e0fSrobinson (void) mutex_unlock(&netpp_mutex); 4167c478bd9Sstevel@tonic-gate 417*61961e0fSrobinson if ((retp = malloc(sizeof (NCONF_HANDLE))) == NULL) { 4187c478bd9Sstevel@tonic-gate nc_error = NC_NOMEM; 4197c478bd9Sstevel@tonic-gate return (NULL); 4207c478bd9Sstevel@tonic-gate } 4217c478bd9Sstevel@tonic-gate 4227c478bd9Sstevel@tonic-gate /* 4237c478bd9Sstevel@tonic-gate * Get the valid entries of the NETPATH variable (and 4247c478bd9Sstevel@tonic-gate * count the number of entries while doing it). 4257c478bd9Sstevel@tonic-gate * 4267c478bd9Sstevel@tonic-gate * This is done every time the procedure is called just 4277c478bd9Sstevel@tonic-gate * in case NETPATH has changed from call to call. 4287c478bd9Sstevel@tonic-gate * 4297c478bd9Sstevel@tonic-gate * If NETPATH is too long, we ignore it altogether as 4307c478bd9Sstevel@tonic-gate * it can only be a buffer overflow attack. 4317c478bd9Sstevel@tonic-gate * Since we add one colon for each entry, but colons only 4327c478bd9Sstevel@tonic-gate * need to exist between entries, we have to subtract one. 4337c478bd9Sstevel@tonic-gate */ 4347c478bd9Sstevel@tonic-gate count = 0; 4357c478bd9Sstevel@tonic-gate valid_netpath[0] = '\0'; 4367c478bd9Sstevel@tonic-gate if ((netpath = getenv(NETPATH)) == NULL || 4377c478bd9Sstevel@tonic-gate strlen(netpath) >= sizeof (templine) - 1) { 4387c478bd9Sstevel@tonic-gate /* 4397c478bd9Sstevel@tonic-gate * If NETPATH variable is not set or invalid, 4407c478bd9Sstevel@tonic-gate * the valid NETPATH consist of all "visible" 4417c478bd9Sstevel@tonic-gate * netids from the netconfig database. 4427c478bd9Sstevel@tonic-gate */ 4437c478bd9Sstevel@tonic-gate 4447c478bd9Sstevel@tonic-gate for (tpp = netpp; *tpp; tpp++) { 4457c478bd9Sstevel@tonic-gate if ((*tpp)->nc_flag & NC_VISIBLE) { 4467c478bd9Sstevel@tonic-gate (void) strcat(valid_netpath, (*tpp)->nc_netid); 4477c478bd9Sstevel@tonic-gate (void) strcat(valid_netpath, ":"); 4487c478bd9Sstevel@tonic-gate count++; 4497c478bd9Sstevel@tonic-gate } 4507c478bd9Sstevel@tonic-gate } 4517c478bd9Sstevel@tonic-gate } else { 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate /* 4547c478bd9Sstevel@tonic-gate * Copy the value of NETPATH (since '\0's will be 4557c478bd9Sstevel@tonic-gate * put into the string) and create the valid NETPATH 4567c478bd9Sstevel@tonic-gate * (by throwing away all netids not in the database). 4577c478bd9Sstevel@tonic-gate * If an entry appears more than one, it *will* be 4587c478bd9Sstevel@tonic-gate * listed twice in the list of valid netpath entries. 4597c478bd9Sstevel@tonic-gate */ 4607c478bd9Sstevel@tonic-gate 4617c478bd9Sstevel@tonic-gate (void) strcpy(templine, netpath); 4627c478bd9Sstevel@tonic-gate tp = templine; 4637c478bd9Sstevel@tonic-gate 4647c478bd9Sstevel@tonic-gate while (*tp) { 4657c478bd9Sstevel@tonic-gate /* Skip all leading ':'s */ 4667c478bd9Sstevel@tonic-gate while (*tp && *tp == ':') 4677c478bd9Sstevel@tonic-gate tp++; 4687c478bd9Sstevel@tonic-gate if (*tp == NULL) 4697c478bd9Sstevel@tonic-gate break; /* last one */ 4707c478bd9Sstevel@tonic-gate netid = tp; 4717c478bd9Sstevel@tonic-gate while (*tp && *tp != ':') 4727c478bd9Sstevel@tonic-gate tp++; 4737c478bd9Sstevel@tonic-gate if (*tp) 4747c478bd9Sstevel@tonic-gate *tp++ = '\0'; /* isolate netid */ 4757c478bd9Sstevel@tonic-gate 4767c478bd9Sstevel@tonic-gate for (tpp = netpp; *tpp; tpp++) { 4777c478bd9Sstevel@tonic-gate if (strcmp(netid, (*tpp)->nc_netid) == 0) { 4787c478bd9Sstevel@tonic-gate (void) strcat(valid_netpath, 4797c478bd9Sstevel@tonic-gate (*tpp)->nc_netid); 4807c478bd9Sstevel@tonic-gate (void) strcat(valid_netpath, ":"); 4817c478bd9Sstevel@tonic-gate count++; 4827c478bd9Sstevel@tonic-gate break; 4837c478bd9Sstevel@tonic-gate } 4847c478bd9Sstevel@tonic-gate } 4857c478bd9Sstevel@tonic-gate } 4867c478bd9Sstevel@tonic-gate } 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate /* Get space to hold the valid list (+1 for the NULL) */ 4897c478bd9Sstevel@tonic-gate 490*61961e0fSrobinson if ((rnetpp = malloc((count + 1) * 4917c478bd9Sstevel@tonic-gate sizeof (struct netconfig *))) == NULL) { 492*61961e0fSrobinson free(retp); 4937c478bd9Sstevel@tonic-gate nc_error = NC_NOMEM; 4947c478bd9Sstevel@tonic-gate return (NULL); 4957c478bd9Sstevel@tonic-gate } 4967c478bd9Sstevel@tonic-gate 4977c478bd9Sstevel@tonic-gate /* 4987c478bd9Sstevel@tonic-gate * Populate the NETPATH list, ending it with a NULL. 4997c478bd9Sstevel@tonic-gate * Each entry in the list points to the structure in the 5007c478bd9Sstevel@tonic-gate * "netpp" list (the entry must exist in the list, otherwise 5017c478bd9Sstevel@tonic-gate * it wouldn't appear in valid_netpath[]). 5027c478bd9Sstevel@tonic-gate */ 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate curr_pp = rnetpp; 5057c478bd9Sstevel@tonic-gate netid = tp = valid_netpath; 5067c478bd9Sstevel@tonic-gate while (*tp) { 5077c478bd9Sstevel@tonic-gate netid = tp; 5087c478bd9Sstevel@tonic-gate while (*tp && *tp != ':') 5097c478bd9Sstevel@tonic-gate tp++; 5107c478bd9Sstevel@tonic-gate if (*tp) 5117c478bd9Sstevel@tonic-gate *tp++ = '\0'; 5127c478bd9Sstevel@tonic-gate for (tpp = netpp; *tpp; tpp++) { 5137c478bd9Sstevel@tonic-gate if (strcmp(netid, (*tpp)->nc_netid) == 0) { 5147c478bd9Sstevel@tonic-gate *curr_pp++ = *tpp; 5157c478bd9Sstevel@tonic-gate break; 5167c478bd9Sstevel@tonic-gate } 5177c478bd9Sstevel@tonic-gate } 5187c478bd9Sstevel@tonic-gate } 5197c478bd9Sstevel@tonic-gate *curr_pp = NULL; 5207c478bd9Sstevel@tonic-gate 5217c478bd9Sstevel@tonic-gate retp->nc_curr = retp->nc_head = rnetpp; 5227c478bd9Sstevel@tonic-gate return ((void *)retp); 5237c478bd9Sstevel@tonic-gate } 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate /* 5267c478bd9Sstevel@tonic-gate * endnetpath() frees up all of the memory allocated by setnetpath(). 5277c478bd9Sstevel@tonic-gate * It returns -1 (error) if setnetpath was never called. 5287c478bd9Sstevel@tonic-gate */ 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate int 531*61961e0fSrobinson endnetpath(void *vdata) 5327c478bd9Sstevel@tonic-gate { 5337c478bd9Sstevel@tonic-gate /* The argument is really a NCONF_HANDLE; cast it here */ 5347c478bd9Sstevel@tonic-gate NCONF_HANDLE *nconf_handlep = (NCONF_HANDLE *)vdata; 5357c478bd9Sstevel@tonic-gate 536*61961e0fSrobinson (void) mutex_lock(&netpp_mutex); 5377c478bd9Sstevel@tonic-gate if (netpp == NULL || nconf_handlep == NULL) { 5387c478bd9Sstevel@tonic-gate nc_error = NC_NOSET; 539*61961e0fSrobinson (void) mutex_unlock(&netpp_mutex); 5407c478bd9Sstevel@tonic-gate return (-1); 5417c478bd9Sstevel@tonic-gate } 542*61961e0fSrobinson (void) mutex_unlock(&netpp_mutex); 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate free(nconf_handlep->nc_head); 5457c478bd9Sstevel@tonic-gate free(nconf_handlep); 5467c478bd9Sstevel@tonic-gate return (0); 5477c478bd9Sstevel@tonic-gate } 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate /* 5507c478bd9Sstevel@tonic-gate * getnetpath() returns the current entry in the list 5517c478bd9Sstevel@tonic-gate * from the NETPATH variable. If setnetpath() was not called 5527c478bd9Sstevel@tonic-gate * previously to set up the list, return NULL. 5537c478bd9Sstevel@tonic-gate */ 5547c478bd9Sstevel@tonic-gate 5557c478bd9Sstevel@tonic-gate struct netconfig * 556*61961e0fSrobinson getnetpath(void *vdata) 5577c478bd9Sstevel@tonic-gate { 5587c478bd9Sstevel@tonic-gate /* The argument is really a NCONF_HANDLE; cast it here */ 5597c478bd9Sstevel@tonic-gate NCONF_HANDLE *nconf_handlep = (NCONF_HANDLE *)vdata; 5607c478bd9Sstevel@tonic-gate struct netconfig *retp; /* holds the return value */ 5617c478bd9Sstevel@tonic-gate int ipv6_present = -1; 5627c478bd9Sstevel@tonic-gate 563*61961e0fSrobinson (void) mutex_lock(&netpp_mutex); 5647c478bd9Sstevel@tonic-gate if (netpp == NULL) { 5657c478bd9Sstevel@tonic-gate nc_error = NC_NOSET; 566*61961e0fSrobinson (void) mutex_unlock(&netpp_mutex); 5677c478bd9Sstevel@tonic-gate return (NULL); 5687c478bd9Sstevel@tonic-gate } 569*61961e0fSrobinson (void) mutex_unlock(&netpp_mutex); 5707c478bd9Sstevel@tonic-gate for (;;) { 5717c478bd9Sstevel@tonic-gate retp = *(nconf_handlep->nc_curr); 5727c478bd9Sstevel@tonic-gate if (retp && (strcmp(retp->nc_netid, "udp6") == 0 || 5737c478bd9Sstevel@tonic-gate strcmp(retp->nc_netid, "tcp6") == 0)) { 5747c478bd9Sstevel@tonic-gate if (ipv6_present == -1) 5757c478bd9Sstevel@tonic-gate ipv6_present = __can_use_af(AF_INET6); 5767c478bd9Sstevel@tonic-gate if (!ipv6_present) { 5777c478bd9Sstevel@tonic-gate ++(nconf_handlep->nc_curr); 5787c478bd9Sstevel@tonic-gate continue; 5797c478bd9Sstevel@tonic-gate } 5807c478bd9Sstevel@tonic-gate } 5817c478bd9Sstevel@tonic-gate break; 5827c478bd9Sstevel@tonic-gate } 5837c478bd9Sstevel@tonic-gate if (retp) { 5847c478bd9Sstevel@tonic-gate ++(nconf_handlep->nc_curr); 5857c478bd9Sstevel@tonic-gate nc_error = NC_NOERROR; 5867c478bd9Sstevel@tonic-gate } else { 5877c478bd9Sstevel@tonic-gate nc_error = NC_NOMOREENTRIES; 5887c478bd9Sstevel@tonic-gate } 5897c478bd9Sstevel@tonic-gate 5907c478bd9Sstevel@tonic-gate return (retp); 5917c478bd9Sstevel@tonic-gate } 5927c478bd9Sstevel@tonic-gate 5937c478bd9Sstevel@tonic-gate /* 5947c478bd9Sstevel@tonic-gate * blank() returns true if the line is a blank line, 0 otherwise 5957c478bd9Sstevel@tonic-gate */ 5967c478bd9Sstevel@tonic-gate 5977c478bd9Sstevel@tonic-gate static int 598*61961e0fSrobinson blank(char *cp) 5997c478bd9Sstevel@tonic-gate { 6007c478bd9Sstevel@tonic-gate while (*cp && isspace(*cp)) { 6017c478bd9Sstevel@tonic-gate cp++; 6027c478bd9Sstevel@tonic-gate } 6037c478bd9Sstevel@tonic-gate return (*cp == '\0'); 6047c478bd9Sstevel@tonic-gate } 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate /* 6077c478bd9Sstevel@tonic-gate * comment() returns true if the line is a comment, 0 otherwise. 6087c478bd9Sstevel@tonic-gate */ 6097c478bd9Sstevel@tonic-gate 6107c478bd9Sstevel@tonic-gate static int 611*61961e0fSrobinson comment(char *cp) 6127c478bd9Sstevel@tonic-gate { 6137c478bd9Sstevel@tonic-gate while (*cp && isspace(*cp)) { 6147c478bd9Sstevel@tonic-gate cp++; 6157c478bd9Sstevel@tonic-gate } 6167c478bd9Sstevel@tonic-gate return (*cp == '#'); 6177c478bd9Sstevel@tonic-gate } 6187c478bd9Sstevel@tonic-gate 6197c478bd9Sstevel@tonic-gate /* 6207c478bd9Sstevel@tonic-gate * getvalue() searches for the given string in the given array, 6217c478bd9Sstevel@tonic-gate * and return the integer value associated with the string. 6227c478bd9Sstevel@tonic-gate */ 6237c478bd9Sstevel@tonic-gate 6247c478bd9Sstevel@tonic-gate static unsigned int 625*61961e0fSrobinson getvalue(char *cp, struct nc_data nc_data[]) 6267c478bd9Sstevel@tonic-gate { 6277c478bd9Sstevel@tonic-gate int i; /* used to index through the given struct nc_data array */ 6287c478bd9Sstevel@tonic-gate 6297c478bd9Sstevel@tonic-gate for (i = 0; nc_data[i].string; i++) { 6307c478bd9Sstevel@tonic-gate if (strcmp(nc_data[i].string, cp) == 0) { 6317c478bd9Sstevel@tonic-gate break; 6327c478bd9Sstevel@tonic-gate } 6337c478bd9Sstevel@tonic-gate } 6347c478bd9Sstevel@tonic-gate return (nc_data[i].value); 6357c478bd9Sstevel@tonic-gate } 6367c478bd9Sstevel@tonic-gate 6377c478bd9Sstevel@tonic-gate /* 6387c478bd9Sstevel@tonic-gate * getflag() creates a bitmap of the one-character flags in 6397c478bd9Sstevel@tonic-gate * the given string. It uses nc_flags array to get the values. 6407c478bd9Sstevel@tonic-gate */ 6417c478bd9Sstevel@tonic-gate 6427c478bd9Sstevel@tonic-gate static unsigned int 643*61961e0fSrobinson getflag(char *cp) 6447c478bd9Sstevel@tonic-gate { 6457c478bd9Sstevel@tonic-gate int i; /* indexs through the nc_flag array */ 6467c478bd9Sstevel@tonic-gate unsigned int mask = 0; /* holds bitmask of flags */ 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate while (*cp) { 6497c478bd9Sstevel@tonic-gate for (i = 0; nc_flag[i].string; i++) { 6507c478bd9Sstevel@tonic-gate if (*nc_flag[i].string == *cp) { 6517c478bd9Sstevel@tonic-gate mask |= nc_flag[i].value; 6527c478bd9Sstevel@tonic-gate break; 6537c478bd9Sstevel@tonic-gate } 6547c478bd9Sstevel@tonic-gate } 6557c478bd9Sstevel@tonic-gate cp++; 6567c478bd9Sstevel@tonic-gate } 6577c478bd9Sstevel@tonic-gate return (mask); 6587c478bd9Sstevel@tonic-gate } 6597c478bd9Sstevel@tonic-gate 6607c478bd9Sstevel@tonic-gate /* 6617c478bd9Sstevel@tonic-gate * getlookups() creates and returns an array of string representing 6627c478bd9Sstevel@tonic-gate * the directory lookup libraries, given as a comma-seperated list 6637c478bd9Sstevel@tonic-gate * in the argument "cp". 6647c478bd9Sstevel@tonic-gate */ 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate static char ** 667*61961e0fSrobinson getlookups(char *cp) 6687c478bd9Sstevel@tonic-gate { 6697c478bd9Sstevel@tonic-gate unsigned int num; /* holds the number of entries in the list */ 6707c478bd9Sstevel@tonic-gate char **listpp; /* the beginning of the list of dir routines */ 6717c478bd9Sstevel@tonic-gate char **tpp; /* traverses the list, populating it */ 6727c478bd9Sstevel@tonic-gate char *start; 6737c478bd9Sstevel@tonic-gate 6747c478bd9Sstevel@tonic-gate num = getnlookups(cp); 675*61961e0fSrobinson if (num == 0) 6767c478bd9Sstevel@tonic-gate return (NULL); 677*61961e0fSrobinson if ((listpp = malloc((num + 1) * sizeof (char *))) == NULL) 6787c478bd9Sstevel@tonic-gate return (NULL); 6797c478bd9Sstevel@tonic-gate 6807c478bd9Sstevel@tonic-gate tpp = listpp; 6817c478bd9Sstevel@tonic-gate while (num--) { 6827c478bd9Sstevel@tonic-gate start = cp; 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate /* 6857c478bd9Sstevel@tonic-gate * Traverse the string looking for the next entry 6867c478bd9Sstevel@tonic-gate * of the list (i.e, where the ',' or end of the 6877c478bd9Sstevel@tonic-gate * string appears). If a "\" is found, shift the 6887c478bd9Sstevel@tonic-gate * token over 1 to the left (taking the next char 6897c478bd9Sstevel@tonic-gate * literally). 6907c478bd9Sstevel@tonic-gate */ 6917c478bd9Sstevel@tonic-gate 6927c478bd9Sstevel@tonic-gate while (*cp && *cp != ',') { 6937c478bd9Sstevel@tonic-gate if (*cp == '\\' && *(cp + 1)) { 6947c478bd9Sstevel@tonic-gate shift1left(cp); 6957c478bd9Sstevel@tonic-gate } 6967c478bd9Sstevel@tonic-gate cp++; 6977c478bd9Sstevel@tonic-gate } 6987c478bd9Sstevel@tonic-gate if (*cp) 6997c478bd9Sstevel@tonic-gate *cp++ = '\0'; 7007c478bd9Sstevel@tonic-gate if ((*tpp++ = strdup(start)) == NULL) { 7017c478bd9Sstevel@tonic-gate for (tpp = listpp; *tpp; tpp++) 7027c478bd9Sstevel@tonic-gate free(*tpp); 7037c478bd9Sstevel@tonic-gate free(listpp); 7047c478bd9Sstevel@tonic-gate return (NULL); 7057c478bd9Sstevel@tonic-gate } 7067c478bd9Sstevel@tonic-gate } 7077c478bd9Sstevel@tonic-gate *tpp = NULL; 7087c478bd9Sstevel@tonic-gate return (listpp); 7097c478bd9Sstevel@tonic-gate } 7107c478bd9Sstevel@tonic-gate 7117c478bd9Sstevel@tonic-gate /* 7127c478bd9Sstevel@tonic-gate * getnlookups() returns the number of entries in a comma-separated 7137c478bd9Sstevel@tonic-gate * string of tokens. A "-" means no strings are present. 7147c478bd9Sstevel@tonic-gate */ 7157c478bd9Sstevel@tonic-gate 7167c478bd9Sstevel@tonic-gate static unsigned int 717*61961e0fSrobinson getnlookups(char *cp) 7187c478bd9Sstevel@tonic-gate { 7197c478bd9Sstevel@tonic-gate unsigned int count; /* the number of tokens in the string */ 7207c478bd9Sstevel@tonic-gate 721*61961e0fSrobinson if (strcmp(cp, "-") == 0) 7227c478bd9Sstevel@tonic-gate return (0); 7237c478bd9Sstevel@tonic-gate 7247c478bd9Sstevel@tonic-gate count = 1; 7257c478bd9Sstevel@tonic-gate while (*cp) { 7267c478bd9Sstevel@tonic-gate if (*cp == ',') { 7277c478bd9Sstevel@tonic-gate count++; 7287c478bd9Sstevel@tonic-gate } 7297c478bd9Sstevel@tonic-gate 7307c478bd9Sstevel@tonic-gate /* 7317c478bd9Sstevel@tonic-gate * If a "\" is in the string, take the next character 7327c478bd9Sstevel@tonic-gate * literally. Onlly skip the character if "\" is 7337c478bd9Sstevel@tonic-gate * not the last character of the token. 7347c478bd9Sstevel@tonic-gate */ 7357c478bd9Sstevel@tonic-gate if (*cp == '\\' && *(cp + 1)) { 7367c478bd9Sstevel@tonic-gate cp++; 7377c478bd9Sstevel@tonic-gate } 7387c478bd9Sstevel@tonic-gate cp++; 7397c478bd9Sstevel@tonic-gate } 7407c478bd9Sstevel@tonic-gate return (count); 7417c478bd9Sstevel@tonic-gate } 7427c478bd9Sstevel@tonic-gate 7437c478bd9Sstevel@tonic-gate /* 7447c478bd9Sstevel@tonic-gate * gettoken() behaves much like strtok(), except that 7457c478bd9Sstevel@tonic-gate * it knows about escaped space characters (i.e., space characters 7467c478bd9Sstevel@tonic-gate * preceeded by a '\' are taken literally). 7477c478bd9Sstevel@tonic-gate */ 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate static char * 750*61961e0fSrobinson gettoken(char *cp, int skip) 7517c478bd9Sstevel@tonic-gate { 7527c478bd9Sstevel@tonic-gate static char *savep; /* the place where we left off */ 7537c478bd9Sstevel@tonic-gate char *p; /* the beginning of the new token */ 7547c478bd9Sstevel@tonic-gate char *retp; /* the token to be returned */ 7557c478bd9Sstevel@tonic-gate 7567c478bd9Sstevel@tonic-gate fieldnum++; 7577c478bd9Sstevel@tonic-gate 7587c478bd9Sstevel@tonic-gate /* Determine if first or subsequent call */ 7597c478bd9Sstevel@tonic-gate p = (cp == NULL)? savep: cp; 7607c478bd9Sstevel@tonic-gate 7617c478bd9Sstevel@tonic-gate /* Return if no tokens remain. */ 762*61961e0fSrobinson if (p == 0) 7637c478bd9Sstevel@tonic-gate return (NULL); 7647c478bd9Sstevel@tonic-gate 7657c478bd9Sstevel@tonic-gate while (isspace(*p)) 7667c478bd9Sstevel@tonic-gate p++; 7677c478bd9Sstevel@tonic-gate 768*61961e0fSrobinson if (*p == '\0') 7697c478bd9Sstevel@tonic-gate return (NULL); 7707c478bd9Sstevel@tonic-gate 7717c478bd9Sstevel@tonic-gate /* 7727c478bd9Sstevel@tonic-gate * Save the location of the token and then skip past it 7737c478bd9Sstevel@tonic-gate */ 7747c478bd9Sstevel@tonic-gate 7757c478bd9Sstevel@tonic-gate retp = p; 7767c478bd9Sstevel@tonic-gate while (*p) { 7777c478bd9Sstevel@tonic-gate if (isspace(*p)) 7787c478bd9Sstevel@tonic-gate if (skip == TRUE) { 7797c478bd9Sstevel@tonic-gate shift1left(p); 7807c478bd9Sstevel@tonic-gate continue; 7817c478bd9Sstevel@tonic-gate } else 7827c478bd9Sstevel@tonic-gate break; 7837c478bd9Sstevel@tonic-gate /* 7847c478bd9Sstevel@tonic-gate * Only process the escape of the space seperator; 7857c478bd9Sstevel@tonic-gate * since the token may contain other separators, 7867c478bd9Sstevel@tonic-gate * let the other routines handle the escape of 7877c478bd9Sstevel@tonic-gate * specific characters in the token. 7887c478bd9Sstevel@tonic-gate */ 7897c478bd9Sstevel@tonic-gate 7907c478bd9Sstevel@tonic-gate if (*p == '\\' && *(p + 1) != '\n' && isspace(*(p + 1))) { 7917c478bd9Sstevel@tonic-gate shift1left(p); 7927c478bd9Sstevel@tonic-gate } 7937c478bd9Sstevel@tonic-gate p++; 7947c478bd9Sstevel@tonic-gate } 7957c478bd9Sstevel@tonic-gate if (*p == '\0') { 7967c478bd9Sstevel@tonic-gate savep = 0; /* indicate this is last token */ 7977c478bd9Sstevel@tonic-gate } else { 7987c478bd9Sstevel@tonic-gate *p = '\0'; 7997c478bd9Sstevel@tonic-gate savep = ++p; 8007c478bd9Sstevel@tonic-gate } 8017c478bd9Sstevel@tonic-gate return (strdup(retp)); 8027c478bd9Sstevel@tonic-gate } 8037c478bd9Sstevel@tonic-gate 8047c478bd9Sstevel@tonic-gate /* 8057c478bd9Sstevel@tonic-gate * shift1left() moves all characters in the string over 1 to 8067c478bd9Sstevel@tonic-gate * the left. 8077c478bd9Sstevel@tonic-gate */ 8087c478bd9Sstevel@tonic-gate 8097c478bd9Sstevel@tonic-gate static void 810*61961e0fSrobinson shift1left(char *p) 8117c478bd9Sstevel@tonic-gate { 8127c478bd9Sstevel@tonic-gate for (; *p; p++) 8137c478bd9Sstevel@tonic-gate *p = *(p + 1); 8147c478bd9Sstevel@tonic-gate } 8157c478bd9Sstevel@tonic-gate 8167c478bd9Sstevel@tonic-gate char * 817*61961e0fSrobinson nc_sperror(void) 8187c478bd9Sstevel@tonic-gate { 8197c478bd9Sstevel@tonic-gate static char buf_main[BUFSIZ]; 8207c478bd9Sstevel@tonic-gate static pthread_key_t perror_key; 8217c478bd9Sstevel@tonic-gate char *retstr = thr_main()? 8227c478bd9Sstevel@tonic-gate buf_main : 8237c478bd9Sstevel@tonic-gate thr_get_storage(&perror_key, BUFSIZ, free); 8247c478bd9Sstevel@tonic-gate 8257c478bd9Sstevel@tonic-gate if (retstr == NULL) { 8267c478bd9Sstevel@tonic-gate syslog(LOG_WARNING, 8277c478bd9Sstevel@tonic-gate "nc_sperror: malloc failed when trying to create buffer\n"); 8287c478bd9Sstevel@tonic-gate return (NULL); 8297c478bd9Sstevel@tonic-gate } 8307c478bd9Sstevel@tonic-gate 8317c478bd9Sstevel@tonic-gate switch (nc_error) { 8327c478bd9Sstevel@tonic-gate case NC_NOERROR: 8337c478bd9Sstevel@tonic-gate (void) strlcpy(retstr, dgettext(__nsl_dom, "no error"), BUFSIZ); 8347c478bd9Sstevel@tonic-gate break; 8357c478bd9Sstevel@tonic-gate case NC_NOMEM: 8367c478bd9Sstevel@tonic-gate (void) strlcpy(retstr, dgettext(__nsl_dom, "out of memory"), 8377c478bd9Sstevel@tonic-gate BUFSIZ); 8387c478bd9Sstevel@tonic-gate break; 8397c478bd9Sstevel@tonic-gate case NC_NOSET: 8407c478bd9Sstevel@tonic-gate (void) strlcpy(retstr, dgettext(__nsl_dom, 8417c478bd9Sstevel@tonic-gate "routine called before calling \ 8427c478bd9Sstevel@tonic-gate setnetpath() or setnetconfig()"), BUFSIZ); 8437c478bd9Sstevel@tonic-gate break; 8447c478bd9Sstevel@tonic-gate case NC_OPENFAIL: 8457c478bd9Sstevel@tonic-gate (void) strlcpy(retstr, 8467c478bd9Sstevel@tonic-gate dgettext(__nsl_dom, "cannot open /etc/netconfig"), 8477c478bd9Sstevel@tonic-gate BUFSIZ); 8487c478bd9Sstevel@tonic-gate break; 8497c478bd9Sstevel@tonic-gate case NC_BADLINE: 8507c478bd9Sstevel@tonic-gate (void) snprintf(retstr, BUFSIZ, dgettext(__nsl_dom, 8517c478bd9Sstevel@tonic-gate "error in /etc/netconfig: field %d of line %d\n"), 8527c478bd9Sstevel@tonic-gate fieldnum, linenum); 8537c478bd9Sstevel@tonic-gate break; 8547c478bd9Sstevel@tonic-gate case NC_NOTFOUND: 8557c478bd9Sstevel@tonic-gate (void) snprintf(retstr, BUFSIZ, 8567c478bd9Sstevel@tonic-gate dgettext(__nsl_dom, 8577c478bd9Sstevel@tonic-gate "netid not found in /etc/netconfig")); 8587c478bd9Sstevel@tonic-gate break; 8597c478bd9Sstevel@tonic-gate case NC_NOMOREENTRIES: 8607c478bd9Sstevel@tonic-gate (void) snprintf(retstr, BUFSIZ, 8617c478bd9Sstevel@tonic-gate dgettext(__nsl_dom, 8627c478bd9Sstevel@tonic-gate "no more entries in /etc/netconfig")); 8637c478bd9Sstevel@tonic-gate break; 8647c478bd9Sstevel@tonic-gate default: 8657c478bd9Sstevel@tonic-gate (void) strlcpy(retstr, dgettext(__nsl_dom, "unknown error"), 8667c478bd9Sstevel@tonic-gate BUFSIZ); 8677c478bd9Sstevel@tonic-gate break; 8687c478bd9Sstevel@tonic-gate } 8697c478bd9Sstevel@tonic-gate return (retstr); 8707c478bd9Sstevel@tonic-gate } 8717c478bd9Sstevel@tonic-gate 8727c478bd9Sstevel@tonic-gate void 8737c478bd9Sstevel@tonic-gate nc_perror(const char *string) 8747c478bd9Sstevel@tonic-gate { 8757c478bd9Sstevel@tonic-gate if (string) 876*61961e0fSrobinson (void) fprintf(stderr, "%s: %s\n", string, nc_sperror()); 8777c478bd9Sstevel@tonic-gate else 878*61961e0fSrobinson (void) fprintf(stderr, "%s\n", nc_sperror()); 8797c478bd9Sstevel@tonic-gate } 8807c478bd9Sstevel@tonic-gate 8817c478bd9Sstevel@tonic-gate static void 882*61961e0fSrobinson netlist_free(struct netconfig ***netppp) 8837c478bd9Sstevel@tonic-gate { 8847c478bd9Sstevel@tonic-gate struct netconfig **tpp; 8857c478bd9Sstevel@tonic-gate 8867c478bd9Sstevel@tonic-gate for (tpp = *netppp; *tpp; tpp++) { 8877c478bd9Sstevel@tonic-gate netconfig_free(*tpp); 8887c478bd9Sstevel@tonic-gate } 8897c478bd9Sstevel@tonic-gate free(*netppp); 8907c478bd9Sstevel@tonic-gate *netppp = NULL; 8917c478bd9Sstevel@tonic-gate } 8927c478bd9Sstevel@tonic-gate 8937c478bd9Sstevel@tonic-gate static void 894*61961e0fSrobinson netconfig_free(struct netconfig *netconfigp) 8957c478bd9Sstevel@tonic-gate { 8967c478bd9Sstevel@tonic-gate int i; 8977c478bd9Sstevel@tonic-gate 898*61961e0fSrobinson if (netconfigp == NULL) 8997c478bd9Sstevel@tonic-gate return; 9007c478bd9Sstevel@tonic-gate free_entry(netconfigp->nc_netid); 9017c478bd9Sstevel@tonic-gate free_entry(netconfigp->nc_protofmly); 9027c478bd9Sstevel@tonic-gate free_entry(netconfigp->nc_proto); 9037c478bd9Sstevel@tonic-gate free_entry(netconfigp->nc_device); 9047c478bd9Sstevel@tonic-gate if (netconfigp->nc_lookups) 9057c478bd9Sstevel@tonic-gate for (i = 0; i < netconfigp->nc_nlookups; i++) 9067c478bd9Sstevel@tonic-gate free_entry(netconfigp->nc_lookups[i]); 9077c478bd9Sstevel@tonic-gate free_entry(netconfigp->nc_lookups); 9087c478bd9Sstevel@tonic-gate free(netconfigp); 9097c478bd9Sstevel@tonic-gate } 9107c478bd9Sstevel@tonic-gate 9117c478bd9Sstevel@tonic-gate static struct netconfig * 912*61961e0fSrobinson netconfig_dup(struct netconfig *netconfigp) 9137c478bd9Sstevel@tonic-gate { 9147c478bd9Sstevel@tonic-gate struct netconfig *nconf; 9157c478bd9Sstevel@tonic-gate int i; 9167c478bd9Sstevel@tonic-gate 917*61961e0fSrobinson nconf = calloc(1, sizeof (struct netconfig)); 9187c478bd9Sstevel@tonic-gate if (nconf == NULL) { 9197c478bd9Sstevel@tonic-gate nc_error = NC_NOMEM; 9207c478bd9Sstevel@tonic-gate return (NULL); 9217c478bd9Sstevel@tonic-gate } 9227c478bd9Sstevel@tonic-gate nconf->nc_netid = strdup(netconfigp->nc_netid); 9237c478bd9Sstevel@tonic-gate nconf->nc_protofmly = strdup(netconfigp->nc_protofmly); 9247c478bd9Sstevel@tonic-gate nconf->nc_proto = strdup(netconfigp->nc_proto); 9257c478bd9Sstevel@tonic-gate nconf->nc_device = strdup(netconfigp->nc_device); 926*61961e0fSrobinson nconf->nc_lookups = malloc((netconfigp->nc_nlookups + 1) 9277c478bd9Sstevel@tonic-gate * sizeof (char *)); 9287c478bd9Sstevel@tonic-gate if (!(nconf->nc_lookups && nconf->nc_netid && 9297c478bd9Sstevel@tonic-gate nconf->nc_protofmly && nconf->nc_proto && 9307c478bd9Sstevel@tonic-gate nconf->nc_device)) { 9317c478bd9Sstevel@tonic-gate nc_error = NC_NOMEM; 9327c478bd9Sstevel@tonic-gate netconfig_free(nconf); 9337c478bd9Sstevel@tonic-gate return (NULL); 9347c478bd9Sstevel@tonic-gate } 9357c478bd9Sstevel@tonic-gate 9367c478bd9Sstevel@tonic-gate for (i = 0; i < netconfigp->nc_nlookups; i++) { 9377c478bd9Sstevel@tonic-gate nconf->nc_lookups[i] = strdup(netconfigp->nc_lookups[i]); 9387c478bd9Sstevel@tonic-gate if (nconf->nc_lookups[i] == NULL) { 9397c478bd9Sstevel@tonic-gate nconf->nc_nlookups = i; 9407c478bd9Sstevel@tonic-gate netconfig_free(nconf); 9417c478bd9Sstevel@tonic-gate nc_error = NC_NOMEM; 9427c478bd9Sstevel@tonic-gate return (NULL); 9437c478bd9Sstevel@tonic-gate } 9447c478bd9Sstevel@tonic-gate } 9457c478bd9Sstevel@tonic-gate nconf->nc_lookups[i] = NULL; 9467c478bd9Sstevel@tonic-gate nconf->nc_nlookups = netconfigp->nc_nlookups; 9477c478bd9Sstevel@tonic-gate nconf->nc_flag = netconfigp->nc_flag; 9487c478bd9Sstevel@tonic-gate nconf->nc_semantics = netconfigp->nc_semantics; 9497c478bd9Sstevel@tonic-gate return (nconf); 9507c478bd9Sstevel@tonic-gate } 9517c478bd9Sstevel@tonic-gate 9527c478bd9Sstevel@tonic-gate static void 953*61961e0fSrobinson free_entry(void *foo) 9547c478bd9Sstevel@tonic-gate { 9557c478bd9Sstevel@tonic-gate if (foo) 9567c478bd9Sstevel@tonic-gate free(foo); 9577c478bd9Sstevel@tonic-gate } 958