174462Salfred/* $NetBSD: getnetconfig.c,v 1.3 2000/07/06 03:10:34 christos Exp $ */ 274462Salfred 3261046Smav/*- 4261046Smav * Copyright (c) 2009, Sun Microsystems, Inc. 5261046Smav * All rights reserved. 674462Salfred * 7261046Smav * Redistribution and use in source and binary forms, with or without 8261046Smav * modification, are permitted provided that the following conditions are met: 9261046Smav * - Redistributions of source code must retain the above copyright notice, 10261046Smav * this list of conditions and the following disclaimer. 11261046Smav * - Redistributions in binary form must reproduce the above copyright notice, 12261046Smav * this list of conditions and the following disclaimer in the documentation 13261046Smav * and/or other materials provided with the distribution. 14261046Smav * - Neither the name of Sun Microsystems, Inc. nor the names of its 15261046Smav * contributors may be used to endorse or promote products derived 16261046Smav * from this software without specific prior written permission. 17261046Smav * 18261046Smav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19261046Smav * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20261046Smav * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21261046Smav * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22261046Smav * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23261046Smav * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24261046Smav * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25261046Smav * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26261046Smav * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27261046Smav * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28261046Smav * POSSIBILITY OF SUCH DAMAGE. 2974462Salfred */ 30136581Sobrien 31136581Sobrien#if defined(LIBC_SCCS) && !defined(lint) 32136581Sobrienstatic char sccsid[] = "@(#)getnetconfig.c 1.12 91/12/19 SMI"; 3374462Salfred#endif 3492990Sobrien#include <sys/cdefs.h> 3592990Sobrien__FBSDID("$FreeBSD: releng/10.3/lib/libc/rpc/getnetconfig.c 290899 2015-11-16 01:09:25Z ngie $"); 3674462Salfred 3774462Salfred/* 3874462Salfred * Copyright (c) 1989 by Sun Microsystems, Inc. 3974462Salfred */ 4074462Salfred 4175094Siedowse#include "namespace.h" 4274462Salfred#include "reentrant.h" 4374462Salfred#include <stdio.h> 4474462Salfred#include <errno.h> 4574462Salfred#include <netconfig.h> 46109956Smbr#include <stddef.h> 4774462Salfred#include <stdlib.h> 4874462Salfred#include <string.h> 4974462Salfred#include <rpc/rpc.h> 50111010Snectar#include <unistd.h> 5174462Salfred#include "un-namespace.h" 5274462Salfred#include "rpc_com.h" 5374462Salfred 5474462Salfred/* 5574462Salfred * The five library routines in this file provide application access to the 5674462Salfred * system network configuration database, /etc/netconfig. In addition to the 5774462Salfred * netconfig database and the routines for accessing it, the environment 5874462Salfred * variable NETPATH and its corresponding routines in getnetpath.c may also be 5974462Salfred * used to specify the network transport to be used. 6074462Salfred */ 6174462Salfred 6274462Salfred 6374462Salfred/* 6474462Salfred * netconfig errors 6574462Salfred */ 6674462Salfred 6774462Salfred#define NC_NONETCONFIG ENOENT 6874462Salfred#define NC_NOMEM ENOMEM 6974462Salfred#define NC_NOTINIT EINVAL /* setnetconfig was not called first */ 7074462Salfred#define NC_BADFILE EBADF /* format for netconfig file is bad */ 7175146Siedowse#define NC_NOTFOUND ENOPROTOOPT /* specified netid was not found */ 7274462Salfred 7374462Salfred/* 7474462Salfred * semantics as strings (should be in netconfig.h) 7574462Salfred */ 7674462Salfred#define NC_TPI_CLTS_S "tpi_clts" 7774462Salfred#define NC_TPI_COTS_S "tpi_cots" 7874462Salfred#define NC_TPI_COTS_ORD_S "tpi_cots_ord" 7974462Salfred#define NC_TPI_RAW_S "tpi_raw" 8074462Salfred 8174462Salfred/* 8274462Salfred * flags as characters (also should be in netconfig.h) 8374462Salfred */ 8474462Salfred#define NC_NOFLAG_C '-' 8574462Salfred#define NC_VISIBLE_C 'v' 8674462Salfred#define NC_BROADCAST_C 'b' 8774462Salfred 8874462Salfred/* 8974462Salfred * Character used to indicate there is no name-to-address lookup library 9074462Salfred */ 9174462Salfred#define NC_NOLOOKUP "-" 9274462Salfred 9374462Salfredstatic const char * const _nc_errors[] = { 9474462Salfred "Netconfig database not found", 9574462Salfred "Not enough memory", 9674462Salfred "Not initialized", 9775146Siedowse "Netconfig database has invalid format", 9875146Siedowse "Netid not found in netconfig database" 9974462Salfred}; 10074462Salfred 10174462Salfredstruct netconfig_info { 10274462Salfred int eof; /* all entries has been read */ 10374462Salfred int ref; /* # of times setnetconfig() has been called */ 10474462Salfred struct netconfig_list *head; /* head of the list */ 10574462Salfred struct netconfig_list *tail; /* last of the list */ 10674462Salfred}; 10774462Salfred 10874462Salfredstruct netconfig_list { 10974462Salfred char *linep; /* hold line read from netconfig */ 11074462Salfred struct netconfig *ncp; 11174462Salfred struct netconfig_list *next; 11274462Salfred}; 11374462Salfred 11474462Salfredstruct netconfig_vars { 11574462Salfred int valid; /* token that indicates a valid netconfig_vars */ 11674462Salfred int flag; /* first time flag */ 11774462Salfred struct netconfig_list *nc_configs; /* pointer to the current netconfig entry */ 11874462Salfred}; 11974462Salfred 12074462Salfred#define NC_VALID 0xfeed 12174462Salfred#define NC_STORAGE 0xf00d 12274462Salfred#define NC_INVALID 0 12374462Salfred 12474462Salfred 12592905Sobrienstatic int *__nc_error(void); 12692905Sobrienstatic int parse_ncp(char *, struct netconfig *); 12792905Sobrienstatic struct netconfig *dup_ncp(struct netconfig *); 12874462Salfred 12974462Salfred 13074462Salfredstatic FILE *nc_file; /* for netconfig db */ 131204950Sjhbstatic mutex_t nc_file_lock = MUTEX_INITIALIZER; 132194932Sdelphij 13374462Salfredstatic struct netconfig_info ni = { 0, 0, NULL, NULL}; 134204950Sjhbstatic mutex_t ni_lock = MUTEX_INITIALIZER; 13574462Salfred 136204950Sjhbstatic thread_key_t nc_key; 137204950Sjhbstatic once_t nc_once = ONCE_INITIALIZER; 138204950Sjhbstatic int nc_key_error; 139194932Sdelphij 140204950Sjhbstatic void 141204950Sjhbnc_key_init(void) 142204950Sjhb{ 143204950Sjhb 144204950Sjhb nc_key_error = thr_keycreate(&nc_key, free); 145204950Sjhb} 146204950Sjhb 14774462Salfred#define MAXNETCONFIGLINE 1000 14874462Salfred 14974462Salfredstatic int * 15074462Salfred__nc_error() 15174462Salfred{ 15274462Salfred static int nc_error = 0; 153204950Sjhb int *nc_addr; 15474462Salfred 15575146Siedowse /* 15675146Siedowse * Use the static `nc_error' if we are the main thread 15775146Siedowse * (including non-threaded programs), or if an allocation 15875146Siedowse * fails. 15975146Siedowse */ 16075146Siedowse if (thr_main()) 16175146Siedowse return (&nc_error); 162204950Sjhb if (thr_once(&nc_once, nc_key_init) != 0 || nc_key_error != 0) 163204950Sjhb return (&nc_error); 16475146Siedowse if ((nc_addr = (int *)thr_getspecific(nc_key)) == NULL) { 16574462Salfred nc_addr = (int *)malloc(sizeof (int)); 16674462Salfred if (thr_setspecific(nc_key, (void *) nc_addr) != 0) { 167290899Sngie free(nc_addr); 16875146Siedowse return (&nc_error); 16974462Salfred } 17074462Salfred *nc_addr = 0; 17174462Salfred } 17275146Siedowse return (nc_addr); 17374462Salfred} 17474462Salfred 17574462Salfred#define nc_error (*(__nc_error())) 17674462Salfred/* 17774462Salfred * A call to setnetconfig() establishes a /etc/netconfig "session". A session 17874462Salfred * "handle" is returned on a successful call. At the start of a session (after 17974462Salfred * a call to setnetconfig()) searches through the /etc/netconfig database will 18074462Salfred * proceed from the start of the file. The session handle must be passed to 18174462Salfred * getnetconfig() to parse the file. Each call to getnetconfig() using the 18274462Salfred * current handle will process one subsequent entry in /etc/netconfig. 18374462Salfred * setnetconfig() must be called before the first call to getnetconfig(). 18474462Salfred * (Handles are used to allow for nested calls to setnetpath()). 18574462Salfred * 18674462Salfred * A new session is established with each call to setnetconfig(), with a new 18774462Salfred * handle being returned on each call. Previously established sessions remain 18874462Salfred * active until endnetconfig() is called with that session's handle as an 18974462Salfred * argument. 19074462Salfred * 19174462Salfred * setnetconfig() need *not* be called before a call to getnetconfigent(). 19274462Salfred * setnetconfig() returns a NULL pointer on failure (for example, if 19374462Salfred * the netconfig database is not present). 19474462Salfred */ 19574462Salfredvoid * 19674462Salfredsetnetconfig() 19774462Salfred{ 19874462Salfred struct netconfig_vars *nc_vars; 19974462Salfred 20074462Salfred if ((nc_vars = (struct netconfig_vars *)malloc(sizeof 20174462Salfred (struct netconfig_vars))) == NULL) { 20274462Salfred return(NULL); 20374462Salfred } 20474462Salfred 20574462Salfred /* 20674462Salfred * For multiple calls, i.e. nc_file is not NULL, we just return the 20774462Salfred * handle without reopening the netconfig db. 20874462Salfred */ 209194932Sdelphij mutex_lock(&ni_lock); 21074462Salfred ni.ref++; 211194932Sdelphij mutex_unlock(&ni_lock); 212194932Sdelphij 213194932Sdelphij mutex_lock(&nc_file_lock); 21474462Salfred if ((nc_file != NULL) || (nc_file = fopen(NETCONFIG, "r")) != NULL) { 21574462Salfred nc_vars->valid = NC_VALID; 21674462Salfred nc_vars->flag = 0; 21774462Salfred nc_vars->nc_configs = ni.head; 218194932Sdelphij mutex_unlock(&nc_file_lock); 21974462Salfred return ((void *)nc_vars); 22074462Salfred } 221194932Sdelphij mutex_unlock(&nc_file_lock); 222194932Sdelphij 223194932Sdelphij mutex_lock(&ni_lock); 22474462Salfred ni.ref--; 225194932Sdelphij mutex_unlock(&ni_lock); 226194932Sdelphij 22774462Salfred nc_error = NC_NONETCONFIG; 22874462Salfred free(nc_vars); 22974462Salfred return (NULL); 23074462Salfred} 23174462Salfred 23274462Salfred 23374462Salfred/* 23474462Salfred * When first called, getnetconfig() returns a pointer to the first entry in 23574462Salfred * the netconfig database, formatted as a struct netconfig. On each subsequent 23674462Salfred * call, getnetconfig() returns a pointer to the next entry in the database. 23774462Salfred * getnetconfig() can thus be used to search the entire netconfig file. 23874462Salfred * getnetconfig() returns NULL at end of file. 23974462Salfred */ 24074462Salfred 24174462Salfredstruct netconfig * 24274462Salfredgetnetconfig(handlep) 24374462Salfredvoid *handlep; 24474462Salfred{ 24574462Salfred struct netconfig_vars *ncp = (struct netconfig_vars *)handlep; 24674462Salfred char *stringp; /* tmp string pointer */ 24774462Salfred struct netconfig_list *list; 24874462Salfred struct netconfig *np; 249194932Sdelphij struct netconfig *result; 25074462Salfred 25174462Salfred /* 25274462Salfred * Verify that handle is valid 25374462Salfred */ 254194932Sdelphij mutex_lock(&nc_file_lock); 25574462Salfred if (ncp == NULL || nc_file == NULL) { 25674462Salfred nc_error = NC_NOTINIT; 257194932Sdelphij mutex_unlock(&nc_file_lock); 25874462Salfred return (NULL); 25974462Salfred } 260194932Sdelphij mutex_unlock(&nc_file_lock); 26174462Salfred 26274462Salfred switch (ncp->valid) { 26374462Salfred case NC_VALID: 26474462Salfred /* 26574462Salfred * If entry has already been read into the list, 26674462Salfred * we return the entry in the linked list. 26774462Salfred * If this is the first time call, check if there are any entries in 26874462Salfred * linked list. If no entries, we need to read the netconfig db. 26974462Salfred * If we have been here and the next entry is there, we just return 27074462Salfred * it. 27174462Salfred */ 27274462Salfred if (ncp->flag == 0) { /* first time */ 27374462Salfred ncp->flag = 1; 274194932Sdelphij mutex_lock(&ni_lock); 27574462Salfred ncp->nc_configs = ni.head; 276194932Sdelphij mutex_unlock(&ni_lock); 27774462Salfred if (ncp->nc_configs != NULL) /* entry already exist */ 27874462Salfred return(ncp->nc_configs->ncp); 27974462Salfred } 28074462Salfred else if (ncp->nc_configs != NULL && ncp->nc_configs->next != NULL) { 28174462Salfred ncp->nc_configs = ncp->nc_configs->next; 28274462Salfred return(ncp->nc_configs->ncp); 28374462Salfred } 28474462Salfred 28574462Salfred /* 28674462Salfred * If we cannot find the entry in the list and is end of file, 28774462Salfred * we give up. 28874462Salfred */ 289194932Sdelphij mutex_lock(&ni_lock); 290194932Sdelphij if (ni.eof == 1) { 291194932Sdelphij mutex_unlock(&ni_lock); 292194932Sdelphij return(NULL); 293194932Sdelphij } 294194932Sdelphij mutex_unlock(&ni_lock); 295194932Sdelphij 29674462Salfred break; 29774462Salfred default: 29874462Salfred nc_error = NC_NOTINIT; 29974462Salfred return (NULL); 30074462Salfred } 30174462Salfred 30274462Salfred stringp = (char *) malloc(MAXNETCONFIGLINE); 30374462Salfred if (stringp == NULL) 30474462Salfred return (NULL); 30574462Salfred 30674462Salfred#ifdef MEM_CHK 30774462Salfred if (malloc_verify() == 0) { 30874462Salfred fprintf(stderr, "memory heap corrupted in getnetconfig\n"); 30974462Salfred exit(1); 31074462Salfred } 31174462Salfred#endif 31274462Salfred 31374462Salfred /* 31474462Salfred * Read a line from netconfig file. 31574462Salfred */ 316194932Sdelphij mutex_lock(&nc_file_lock); 31774462Salfred do { 31874462Salfred if (fgets(stringp, MAXNETCONFIGLINE, nc_file) == NULL) { 31974462Salfred free(stringp); 320194932Sdelphij mutex_lock(&ni_lock); 32174462Salfred ni.eof = 1; 322194932Sdelphij mutex_unlock(&ni_lock); 323194932Sdelphij mutex_unlock(&nc_file_lock); 32474462Salfred return (NULL); 32574462Salfred } 32674462Salfred } while (*stringp == '#'); 327194932Sdelphij mutex_unlock(&nc_file_lock); 32874462Salfred 32974462Salfred list = (struct netconfig_list *) malloc(sizeof (struct netconfig_list)); 33074462Salfred if (list == NULL) { 33174462Salfred free(stringp); 33274462Salfred return(NULL); 33374462Salfred } 33474462Salfred np = (struct netconfig *) malloc(sizeof (struct netconfig)); 33574462Salfred if (np == NULL) { 33674462Salfred free(stringp); 33774462Salfred free(list); 33874462Salfred return(NULL); 33974462Salfred } 34074462Salfred list->ncp = np; 34174462Salfred list->next = NULL; 34274462Salfred list->ncp->nc_lookups = NULL; 34374462Salfred list->linep = stringp; 34474462Salfred if (parse_ncp(stringp, list->ncp) == -1) { 34574462Salfred free(stringp); 34674462Salfred free(np); 34774462Salfred free(list); 34874462Salfred return (NULL); 34974462Salfred } 35074462Salfred else { 35174462Salfred /* 35274462Salfred * If this is the first entry that's been read, it is the head of 35374462Salfred * the list. If not, put the entry at the end of the list. 35474462Salfred * Reposition the current pointer of the handle to the last entry 35574462Salfred * in the list. 35674462Salfred */ 357194932Sdelphij mutex_lock(&ni_lock); 35874462Salfred if (ni.head == NULL) { /* first entry */ 35974462Salfred ni.head = ni.tail = list; 36074462Salfred } 36174462Salfred else { 36274462Salfred ni.tail->next = list; 36374462Salfred ni.tail = ni.tail->next; 36474462Salfred } 36574462Salfred ncp->nc_configs = ni.tail; 366194932Sdelphij result = ni.tail->ncp; 367194932Sdelphij mutex_unlock(&ni_lock); 368194932Sdelphij return(result); 36974462Salfred } 37074462Salfred} 37174462Salfred 37274462Salfred/* 37374462Salfred * endnetconfig() may be called to "unbind" or "close" the netconfig database 37474462Salfred * when processing is complete, releasing resources for reuse. endnetconfig() 37574462Salfred * may not be called before setnetconfig(). endnetconfig() returns 0 on 37674462Salfred * success and -1 on failure (for example, if setnetconfig() was not called 37774462Salfred * previously). 37874462Salfred */ 37974462Salfredint 38074462Salfredendnetconfig(handlep) 38174462Salfredvoid *handlep; 38274462Salfred{ 38374462Salfred struct netconfig_vars *nc_handlep = (struct netconfig_vars *)handlep; 38474462Salfred 38574462Salfred struct netconfig_list *q, *p; 38674462Salfred 38774462Salfred /* 38874462Salfred * Verify that handle is valid 38974462Salfred */ 39074462Salfred if (nc_handlep == NULL || (nc_handlep->valid != NC_VALID && 39174462Salfred nc_handlep->valid != NC_STORAGE)) { 39274462Salfred nc_error = NC_NOTINIT; 39374462Salfred return (-1); 39474462Salfred } 39574462Salfred 39674462Salfred /* 39774462Salfred * Return 0 if anyone still needs it. 39874462Salfred */ 39974462Salfred nc_handlep->valid = NC_INVALID; 40074462Salfred nc_handlep->flag = 0; 40174462Salfred nc_handlep->nc_configs = NULL; 402194932Sdelphij mutex_lock(&ni_lock); 40374462Salfred if (--ni.ref > 0) { 404194932Sdelphij mutex_unlock(&ni_lock); 40574462Salfred free(nc_handlep); 40674462Salfred return(0); 40774462Salfred } 40874462Salfred 40974462Salfred /* 41074462Salfred * Noone needs these entries anymore, then frees them. 41174462Salfred * Make sure all info in netconfig_info structure has been reinitialized. 41274462Salfred */ 413199784Swollman q = ni.head; 41474462Salfred ni.eof = ni.ref = 0; 41574462Salfred ni.head = NULL; 41674462Salfred ni.tail = NULL; 417194932Sdelphij mutex_unlock(&ni_lock); 418194932Sdelphij 419199784Swollman while (q != NULL) { 42074462Salfred p = q->next; 421290899Sngie free(q->ncp->nc_lookups); 42274462Salfred free(q->ncp); 42374462Salfred free(q->linep); 42474462Salfred free(q); 42574462Salfred q = p; 42674462Salfred } 42774462Salfred free(nc_handlep); 42874462Salfred 429194932Sdelphij mutex_lock(&nc_file_lock); 43074462Salfred fclose(nc_file); 43174462Salfred nc_file = NULL; 432194932Sdelphij mutex_unlock(&nc_file_lock); 433194932Sdelphij 43474462Salfred return (0); 43574462Salfred} 43674462Salfred 43774462Salfred/* 43874462Salfred * getnetconfigent(netid) returns a pointer to the struct netconfig structure 43974462Salfred * corresponding to netid. It returns NULL if netid is invalid (that is, does 44074462Salfred * not name an entry in the netconfig database). It returns NULL and sets 44174462Salfred * errno in case of failure (for example, if the netconfig database cannot be 44274462Salfred * opened). 44374462Salfred */ 44474462Salfred 44574462Salfredstruct netconfig * 44674462Salfredgetnetconfigent(netid) 44774843Salfred const char *netid; 44874462Salfred{ 44974462Salfred FILE *file; /* NETCONFIG db's file pointer */ 45074462Salfred char *linep; /* holds current netconfig line */ 45174462Salfred char *stringp; /* temporary string pointer */ 45274462Salfred struct netconfig *ncp = NULL; /* returned value */ 45374462Salfred struct netconfig_list *list; /* pointer to cache list */ 45474462Salfred 45575146Siedowse nc_error = NC_NOTFOUND; /* default error. */ 45674462Salfred if (netid == NULL || strlen(netid) == 0) { 45774462Salfred return (NULL); 45874462Salfred } 45974462Salfred 46074462Salfred /* 46174462Salfred * Look up table if the entries have already been read and parsed in 46274462Salfred * getnetconfig(), then copy this entry into a buffer and return it. 46374462Salfred * If we cannot find the entry in the current list and there are more 46474462Salfred * entries in the netconfig db that has not been read, we then read the 46574462Salfred * db and try find the match netid. 46674462Salfred * If all the netconfig db has been read and placed into the list and 46774462Salfred * there is no match for the netid, return NULL. 46874462Salfred */ 469194932Sdelphij mutex_lock(&ni_lock); 47074462Salfred if (ni.head != NULL) { 47174462Salfred for (list = ni.head; list; list = list->next) { 47274462Salfred if (strcmp(list->ncp->nc_netid, netid) == 0) { 473194932Sdelphij mutex_unlock(&ni_lock); 47474462Salfred return(dup_ncp(list->ncp)); 47574462Salfred } 47674462Salfred } 477194932Sdelphij if (ni.eof == 1) { /* that's all the entries */ 478194932Sdelphij mutex_unlock(&ni_lock); 47974462Salfred return(NULL); 480194932Sdelphij } 48174462Salfred } 482194932Sdelphij mutex_unlock(&ni_lock); 48374462Salfred 48474462Salfred 48574462Salfred if ((file = fopen(NETCONFIG, "r")) == NULL) { 48675146Siedowse nc_error = NC_NONETCONFIG; 48774462Salfred return (NULL); 48874462Salfred } 48974462Salfred 49074462Salfred if ((linep = malloc(MAXNETCONFIGLINE)) == NULL) { 49174462Salfred fclose(file); 49275146Siedowse nc_error = NC_NOMEM; 49374462Salfred return (NULL); 49474462Salfred } 49574462Salfred do { 496109956Smbr ptrdiff_t len; 49774462Salfred char *tmpp; /* tmp string pointer */ 49874462Salfred 49974462Salfred do { 50074462Salfred if ((stringp = fgets(linep, MAXNETCONFIGLINE, file)) == NULL) { 50174462Salfred break; 50274462Salfred } 50374462Salfred } while (*stringp == '#'); 50474462Salfred if (stringp == NULL) { /* eof */ 50574462Salfred break; 50674462Salfred } 50774462Salfred if ((tmpp = strpbrk(stringp, "\t ")) == NULL) { /* can't parse file */ 50874462Salfred nc_error = NC_BADFILE; 50974462Salfred break; 51074462Salfred } 511109956Smbr if (strlen(netid) == (size_t) (len = tmpp - stringp) && /* a match */ 51274462Salfred strncmp(stringp, netid, (size_t)len) == 0) { 51374462Salfred if ((ncp = (struct netconfig *) 51474462Salfred malloc(sizeof (struct netconfig))) == NULL) { 51574462Salfred break; 51674462Salfred } 51774462Salfred ncp->nc_lookups = NULL; 51874462Salfred if (parse_ncp(linep, ncp) == -1) { 51974462Salfred free(ncp); 52074462Salfred ncp = NULL; 52174462Salfred } 52274462Salfred break; 52374462Salfred } 52474462Salfred } while (stringp != NULL); 52574462Salfred if (ncp == NULL) { 52674462Salfred free(linep); 52774462Salfred } 52874462Salfred fclose(file); 52974462Salfred return(ncp); 53074462Salfred} 53174462Salfred 53274462Salfred/* 53374462Salfred * freenetconfigent(netconfigp) frees the netconfig structure pointed to by 53474462Salfred * netconfigp (previously returned by getnetconfigent()). 53574462Salfred */ 53674462Salfred 53774462Salfredvoid 53874462Salfredfreenetconfigent(netconfigp) 53974462Salfred struct netconfig *netconfigp; 54074462Salfred{ 54174462Salfred if (netconfigp != NULL) { 54274462Salfred free(netconfigp->nc_netid); /* holds all netconfigp's strings */ 543290899Sngie free(netconfigp->nc_lookups); 54474462Salfred free(netconfigp); 54574462Salfred } 54674462Salfred return; 54774462Salfred} 54874462Salfred 54974462Salfred/* 55074462Salfred * Parse line and stuff it in a struct netconfig 55174462Salfred * Typical line might look like: 55274462Salfred * udp tpi_cots vb inet udp /dev/udp /usr/lib/ip.so,/usr/local/ip.so 55374462Salfred * 55474462Salfred * We return -1 if any of the tokens don't parse, or malloc fails. 55574462Salfred * 55674462Salfred * Note that we modify stringp (putting NULLs after tokens) and 55774462Salfred * we set the ncp's string field pointers to point to these tokens within 55874462Salfred * stringp. 55974462Salfred */ 56074462Salfred 56174462Salfredstatic int 56274462Salfredparse_ncp(stringp, ncp) 56374462Salfredchar *stringp; /* string to parse */ 56474462Salfredstruct netconfig *ncp; /* where to put results */ 56574462Salfred{ 56674462Salfred char *tokenp; /* for processing tokens */ 56774462Salfred char *lasts; 568172259Smatteo char **nc_lookups; 56974462Salfred 57074462Salfred nc_error = NC_BADFILE; /* nearly anything that breaks is for this reason */ 57174462Salfred stringp[strlen(stringp)-1] = '\0'; /* get rid of newline */ 57274462Salfred /* netid */ 57374462Salfred if ((ncp->nc_netid = strtok_r(stringp, "\t ", &lasts)) == NULL) { 57474462Salfred return (-1); 57574462Salfred } 57674462Salfred 57774462Salfred /* semantics */ 57874462Salfred if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) { 57974462Salfred return (-1); 58074462Salfred } 58174462Salfred if (strcmp(tokenp, NC_TPI_COTS_ORD_S) == 0) 58274462Salfred ncp->nc_semantics = NC_TPI_COTS_ORD; 58374462Salfred else if (strcmp(tokenp, NC_TPI_COTS_S) == 0) 58474462Salfred ncp->nc_semantics = NC_TPI_COTS; 58574462Salfred else if (strcmp(tokenp, NC_TPI_CLTS_S) == 0) 58674462Salfred ncp->nc_semantics = NC_TPI_CLTS; 58774462Salfred else if (strcmp(tokenp, NC_TPI_RAW_S) == 0) 58874462Salfred ncp->nc_semantics = NC_TPI_RAW; 58974462Salfred else 59074462Salfred return (-1); 59174462Salfred 59274462Salfred /* flags */ 59374462Salfred if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) { 59474462Salfred return (-1); 59574462Salfred } 59674462Salfred for (ncp->nc_flag = NC_NOFLAG; *tokenp != '\0'; 59774462Salfred tokenp++) { 59874462Salfred switch (*tokenp) { 59974462Salfred case NC_NOFLAG_C: 60074462Salfred break; 60174462Salfred case NC_VISIBLE_C: 60274462Salfred ncp->nc_flag |= NC_VISIBLE; 60374462Salfred break; 60474462Salfred case NC_BROADCAST_C: 60574462Salfred ncp->nc_flag |= NC_BROADCAST; 60674462Salfred break; 60774462Salfred default: 60874462Salfred return (-1); 60974462Salfred } 61074462Salfred } 61174462Salfred /* protocol family */ 61274462Salfred if ((ncp->nc_protofmly = strtok_r(NULL, "\t ", &lasts)) == NULL) { 61374462Salfred return (-1); 61474462Salfred } 61574462Salfred /* protocol name */ 61674462Salfred if ((ncp->nc_proto = strtok_r(NULL, "\t ", &lasts)) == NULL) { 61774462Salfred return (-1); 61874462Salfred } 61974462Salfred /* network device */ 62074462Salfred if ((ncp->nc_device = strtok_r(NULL, "\t ", &lasts)) == NULL) { 62174462Salfred return (-1); 62274462Salfred } 62374462Salfred if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) { 62474462Salfred return (-1); 62574462Salfred } 62674462Salfred if (strcmp(tokenp, NC_NOLOOKUP) == 0) { 62774462Salfred ncp->nc_nlookups = 0; 62874462Salfred ncp->nc_lookups = NULL; 62974462Salfred } else { 63074462Salfred char *cp; /* tmp string */ 63174462Salfred 632290899Sngie free(ncp->nc_lookups); /* from last visit */ 633172259Smatteo ncp->nc_lookups = NULL; 63474462Salfred ncp->nc_nlookups = 0; 63574462Salfred while ((cp = tokenp) != NULL) { 636172259Smatteo if ((nc_lookups = realloc(ncp->nc_lookups, 637172259Smatteo (ncp->nc_nlookups + 1) * sizeof *ncp->nc_lookups)) == NULL) { 638172259Smatteo free(ncp->nc_lookups); 639172259Smatteo ncp->nc_lookups = NULL; 640172259Smatteo return (-1); 641172259Smatteo } 64274462Salfred tokenp = _get_next_token(cp, ','); 643172259Smatteo ncp->nc_lookups = nc_lookups; 644172259Smatteo ncp->nc_lookups[ncp->nc_nlookups++] = cp; 64574462Salfred } 64674462Salfred } 64774462Salfred return (0); 64874462Salfred} 64974462Salfred 65074462Salfred 65174462Salfred/* 65274462Salfred * Returns a string describing the reason for failure. 65374462Salfred */ 65474462Salfredchar * 65574462Salfrednc_sperror() 65674462Salfred{ 65774462Salfred const char *message; 65874462Salfred 65974462Salfred switch(nc_error) { 66074462Salfred case NC_NONETCONFIG: 66174462Salfred message = _nc_errors[0]; 66274462Salfred break; 66374462Salfred case NC_NOMEM: 66474462Salfred message = _nc_errors[1]; 66574462Salfred break; 66674462Salfred case NC_NOTINIT: 66774462Salfred message = _nc_errors[2]; 66874462Salfred break; 66974462Salfred case NC_BADFILE: 67074462Salfred message = _nc_errors[3]; 67174462Salfred break; 67275146Siedowse case NC_NOTFOUND: 67375146Siedowse message = _nc_errors[4]; 67475146Siedowse break; 67574462Salfred default: 67674462Salfred message = "Unknown network selection error"; 67774462Salfred } 67874462Salfred /* LINTED const castaway */ 67974462Salfred return ((char *)message); 68074462Salfred} 68174462Salfred 68274462Salfred/* 68374462Salfred * Prints a message onto standard error describing the reason for failure. 68474462Salfred */ 68574462Salfredvoid 68674462Salfrednc_perror(s) 68774462Salfred const char *s; 68874462Salfred{ 68975146Siedowse fprintf(stderr, "%s: %s\n", s, nc_sperror()); 69074462Salfred} 69174462Salfred 69274462Salfred/* 69374462Salfred * Duplicates the matched netconfig buffer. 69474462Salfred */ 69574462Salfredstatic struct netconfig * 69674462Salfreddup_ncp(ncp) 69774462Salfredstruct netconfig *ncp; 69874462Salfred{ 69974462Salfred struct netconfig *p; 70074462Salfred char *tmp; 701109956Smbr u_int i; 70274462Salfred 70374462Salfred if ((tmp=malloc(MAXNETCONFIGLINE)) == NULL) 70474462Salfred return(NULL); 70574462Salfred if ((p=(struct netconfig *)malloc(sizeof(struct netconfig))) == NULL) { 70674462Salfred free(tmp); 70774462Salfred return(NULL); 70874462Salfred } 70974462Salfred /* 71074462Salfred * First we dup all the data from matched netconfig buffer. Then we 71174462Salfred * adjust some of the member pointer to a pre-allocated buffer where 71274462Salfred * contains part of the data. 71374462Salfred * To follow the convention used in parse_ncp(), we store all the 714109956Smbr * necessary information in the pre-allocated buffer and let each 71574462Salfred * of the netconfig char pointer member point to the right address 71674462Salfred * in the buffer. 71774462Salfred */ 71874462Salfred *p = *ncp; 71974462Salfred p->nc_netid = (char *)strcpy(tmp,ncp->nc_netid); 720126643Smarkm tmp = strchr(tmp, '\0') + 1; 72174462Salfred p->nc_protofmly = (char *)strcpy(tmp,ncp->nc_protofmly); 722126643Smarkm tmp = strchr(tmp, '\0') + 1; 72374462Salfred p->nc_proto = (char *)strcpy(tmp,ncp->nc_proto); 724126643Smarkm tmp = strchr(tmp, '\0') + 1; 72574462Salfred p->nc_device = (char *)strcpy(tmp,ncp->nc_device); 72674462Salfred p->nc_lookups = (char **)malloc((size_t)(p->nc_nlookups+1) * sizeof(char *)); 72774462Salfred if (p->nc_lookups == NULL) { 72874462Salfred free(p->nc_netid); 729162191Smbr free(p); 73074462Salfred return(NULL); 73174462Salfred } 73274462Salfred for (i=0; i < p->nc_nlookups; i++) { 733126643Smarkm tmp = strchr(tmp, '\0') + 1; 73474462Salfred p->nc_lookups[i] = (char *)strcpy(tmp,ncp->nc_lookups[i]); 73574462Salfred } 73674462Salfred return(p); 73774462Salfred} 738