xref: /freebsd/lib/libc/rpc/getnetconfig.c (revision c05ac53b8bbbbd998e18c6544011dd90f0f082da)
18360efbdSAlfred Perlstein /*	$NetBSD: getnetconfig.c,v 1.3 2000/07/06 03:10:34 christos Exp $	*/
28360efbdSAlfred Perlstein /*	$FreeBSD$ */
38360efbdSAlfred Perlstein 
48360efbdSAlfred Perlstein /*
58360efbdSAlfred Perlstein  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
68360efbdSAlfred Perlstein  * unrestricted use provided that this legend is included on all tape
78360efbdSAlfred Perlstein  * media and as a part of the software program in whole or part.  Users
88360efbdSAlfred Perlstein  * may copy or modify Sun RPC without charge, but are not authorized
98360efbdSAlfred Perlstein  * to license or distribute it to anyone else except as part of a product or
108360efbdSAlfred Perlstein  * program developed by the user or with the express written consent of
118360efbdSAlfred Perlstein  * Sun Microsystems, Inc.
128360efbdSAlfred Perlstein  *
138360efbdSAlfred Perlstein  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
148360efbdSAlfred Perlstein  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
158360efbdSAlfred Perlstein  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
168360efbdSAlfred Perlstein  *
178360efbdSAlfred Perlstein  * Sun RPC is provided with no support and without any obligation on the
188360efbdSAlfred Perlstein  * part of Sun Microsystems, Inc. to assist in its use, correction,
198360efbdSAlfred Perlstein  * modification or enhancement.
208360efbdSAlfred Perlstein  *
218360efbdSAlfred Perlstein  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
228360efbdSAlfred Perlstein  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
238360efbdSAlfred Perlstein  * OR ANY PART THEREOF.
248360efbdSAlfred Perlstein  *
258360efbdSAlfred Perlstein  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
268360efbdSAlfred Perlstein  * or profits or other special, indirect and consequential damages, even if
278360efbdSAlfred Perlstein  * Sun has been advised of the possibility of such damages.
288360efbdSAlfred Perlstein  *
298360efbdSAlfred Perlstein  * Sun Microsystems, Inc.
308360efbdSAlfred Perlstein  * 2550 Garcia Avenue
318360efbdSAlfred Perlstein  * Mountain View, California  94043
328360efbdSAlfred Perlstein  */
338360efbdSAlfred Perlstein /*
348360efbdSAlfred Perlstein #ifndef lint
358360efbdSAlfred Perlstein static        char sccsid[] = "@(#)getnetconfig.c	1.12 91/12/19 SMI";
368360efbdSAlfred Perlstein #endif
378360efbdSAlfred Perlstein */
388360efbdSAlfred Perlstein 
398360efbdSAlfred Perlstein /*
408360efbdSAlfred Perlstein  * Copyright (c) 1989 by Sun Microsystems, Inc.
418360efbdSAlfred Perlstein  */
428360efbdSAlfred Perlstein 
438360efbdSAlfred Perlstein #include "namespace.h"
449f5afc13SIan Dowse #include "reentrant.h"
458360efbdSAlfred Perlstein #include <sys/cdefs.h>
468360efbdSAlfred Perlstein #include <stdio.h>
478360efbdSAlfred Perlstein #include <errno.h>
488360efbdSAlfred Perlstein #include <netconfig.h>
498360efbdSAlfred Perlstein #include <stdlib.h>
508360efbdSAlfred Perlstein #include <string.h>
518360efbdSAlfred Perlstein #include <rpc/rpc.h>
528360efbdSAlfred Perlstein #include "un-namespace.h"
538360efbdSAlfred Perlstein #include "rpc_com.h"
548360efbdSAlfred Perlstein 
558360efbdSAlfred Perlstein /*
568360efbdSAlfred Perlstein  * The five library routines in this file provide application access to the
578360efbdSAlfred Perlstein  * system network configuration database, /etc/netconfig.  In addition to the
588360efbdSAlfred Perlstein  * netconfig database and the routines for accessing it, the environment
598360efbdSAlfred Perlstein  * variable NETPATH and its corresponding routines in getnetpath.c may also be
608360efbdSAlfred Perlstein  * used to specify the network transport to be used.
618360efbdSAlfred Perlstein  */
628360efbdSAlfred Perlstein 
638360efbdSAlfred Perlstein 
648360efbdSAlfred Perlstein /*
658360efbdSAlfred Perlstein  * netconfig errors
668360efbdSAlfred Perlstein  */
678360efbdSAlfred Perlstein 
688360efbdSAlfred Perlstein #define NC_NONETCONFIG	ENOENT
698360efbdSAlfred Perlstein #define NC_NOMEM	ENOMEM
708360efbdSAlfred Perlstein #define NC_NOTINIT	EINVAL	    /* setnetconfig was not called first */
718360efbdSAlfred Perlstein #define NC_BADFILE	EBADF	    /* format for netconfig file is bad */
72b3a38fe3SIan Dowse #define NC_NOTFOUND	ENOPROTOOPT /* specified netid was not found */
738360efbdSAlfred Perlstein 
748360efbdSAlfred Perlstein /*
758360efbdSAlfred Perlstein  * semantics as strings (should be in netconfig.h)
768360efbdSAlfred Perlstein  */
778360efbdSAlfred Perlstein #define NC_TPI_CLTS_S	    "tpi_clts"
788360efbdSAlfred Perlstein #define	NC_TPI_COTS_S	    "tpi_cots"
798360efbdSAlfred Perlstein #define	NC_TPI_COTS_ORD_S   "tpi_cots_ord"
808360efbdSAlfred Perlstein #define	NC_TPI_RAW_S        "tpi_raw"
818360efbdSAlfred Perlstein 
828360efbdSAlfred Perlstein /*
838360efbdSAlfred Perlstein  * flags as characters (also should be in netconfig.h)
848360efbdSAlfred Perlstein  */
858360efbdSAlfred Perlstein #define	NC_NOFLAG_C	'-'
868360efbdSAlfred Perlstein #define	NC_VISIBLE_C	'v'
878360efbdSAlfred Perlstein #define	NC_BROADCAST_C	'b'
888360efbdSAlfred Perlstein 
898360efbdSAlfred Perlstein /*
908360efbdSAlfred Perlstein  * Character used to indicate there is no name-to-address lookup library
918360efbdSAlfred Perlstein  */
928360efbdSAlfred Perlstein #define NC_NOLOOKUP	"-"
938360efbdSAlfred Perlstein 
948360efbdSAlfred Perlstein static const char * const _nc_errors[] = {
958360efbdSAlfred Perlstein     "Netconfig database not found",
968360efbdSAlfred Perlstein     "Not enough memory",
978360efbdSAlfred Perlstein     "Not initialized",
98b3a38fe3SIan Dowse     "Netconfig database has invalid format",
99b3a38fe3SIan Dowse     "Netid not found in netconfig database"
1008360efbdSAlfred Perlstein };
1018360efbdSAlfred Perlstein 
1028360efbdSAlfred Perlstein struct netconfig_info {
1038360efbdSAlfred Perlstein     int		eof;	/* all entries has been read */
1048360efbdSAlfred Perlstein     int		ref;	/* # of times setnetconfig() has been called */
1058360efbdSAlfred Perlstein     struct netconfig_list	*head;	/* head of the list */
1068360efbdSAlfred Perlstein     struct netconfig_list	*tail;	/* last of the list */
1078360efbdSAlfred Perlstein };
1088360efbdSAlfred Perlstein 
1098360efbdSAlfred Perlstein struct netconfig_list {
1108360efbdSAlfred Perlstein     char			*linep;	/* hold line read from netconfig */
1118360efbdSAlfred Perlstein     struct netconfig		*ncp;
1128360efbdSAlfred Perlstein     struct netconfig_list	*next;
1138360efbdSAlfred Perlstein };
1148360efbdSAlfred Perlstein 
1158360efbdSAlfred Perlstein struct netconfig_vars {
1168360efbdSAlfred Perlstein     int   valid;	/* token that indicates a valid netconfig_vars */
1178360efbdSAlfred Perlstein     int   flag;		/* first time flag */
1188360efbdSAlfred Perlstein     struct netconfig_list *nc_configs;  /* pointer to the current netconfig entry */
1198360efbdSAlfred Perlstein };
1208360efbdSAlfred Perlstein 
1218360efbdSAlfred Perlstein #define NC_VALID	0xfeed
1228360efbdSAlfred Perlstein #define NC_STORAGE	0xf00d
1238360efbdSAlfred Perlstein #define NC_INVALID	0
1248360efbdSAlfred Perlstein 
1258360efbdSAlfred Perlstein 
126c05ac53bSDavid E. O'Brien static int *__nc_error(void);
127c05ac53bSDavid E. O'Brien static int parse_ncp(char *, struct netconfig *);
128c05ac53bSDavid E. O'Brien static struct netconfig *dup_ncp(struct netconfig *);
1298360efbdSAlfred Perlstein 
1308360efbdSAlfred Perlstein 
1318360efbdSAlfred Perlstein static FILE *nc_file;		/* for netconfig db */
1328360efbdSAlfred Perlstein static struct netconfig_info	ni = { 0, 0, NULL, NULL};
1338360efbdSAlfred Perlstein 
1348360efbdSAlfred Perlstein #define MAXNETCONFIGLINE    1000
1358360efbdSAlfred Perlstein 
1368360efbdSAlfred Perlstein static int *
1378360efbdSAlfred Perlstein __nc_error()
1388360efbdSAlfred Perlstein {
139b3a38fe3SIan Dowse 	static pthread_mutex_t nc_lock = PTHREAD_MUTEX_INITIALIZER;
1408360efbdSAlfred Perlstein 	static thread_key_t nc_key = 0;
1418360efbdSAlfred Perlstein 	static int nc_error = 0;
142b3a38fe3SIan Dowse 	int error, *nc_addr;
1438360efbdSAlfred Perlstein 
144b3a38fe3SIan Dowse 	/*
145b3a38fe3SIan Dowse 	 * Use the static `nc_error' if we are the main thread
146b3a38fe3SIan Dowse 	 * (including non-threaded programs), or if an allocation
147b3a38fe3SIan Dowse 	 * fails.
148b3a38fe3SIan Dowse 	 */
149b3a38fe3SIan Dowse 	if (thr_main())
150b3a38fe3SIan Dowse 		return (&nc_error);
151b3a38fe3SIan Dowse 	if (nc_key == 0) {
152b3a38fe3SIan Dowse 		error = 0;
1538360efbdSAlfred Perlstein 		mutex_lock(&nc_lock);
154b3a38fe3SIan Dowse 		if (nc_key == 0)
155b3a38fe3SIan Dowse 			error = thr_keycreate(&nc_key, free);
1568360efbdSAlfred Perlstein 		mutex_unlock(&nc_lock);
157b3a38fe3SIan Dowse 		if (error)
158b3a38fe3SIan Dowse 			return (&nc_error);
1598360efbdSAlfred Perlstein 	}
160b3a38fe3SIan Dowse 	if ((nc_addr = (int *)thr_getspecific(nc_key)) == NULL) {
1618360efbdSAlfred Perlstein 		nc_addr = (int *)malloc(sizeof (int));
1628360efbdSAlfred Perlstein 		if (thr_setspecific(nc_key, (void *) nc_addr) != 0) {
1638360efbdSAlfred Perlstein 			if (nc_addr)
1648360efbdSAlfred Perlstein 				free(nc_addr);
165b3a38fe3SIan Dowse 			return (&nc_error);
1668360efbdSAlfred Perlstein 		}
1678360efbdSAlfred Perlstein 		*nc_addr = 0;
1688360efbdSAlfred Perlstein 	}
169b3a38fe3SIan Dowse 	return (nc_addr);
1708360efbdSAlfred Perlstein }
1718360efbdSAlfred Perlstein 
1728360efbdSAlfred Perlstein #define nc_error        (*(__nc_error()))
1738360efbdSAlfred Perlstein /*
1748360efbdSAlfred Perlstein  * A call to setnetconfig() establishes a /etc/netconfig "session".  A session
1758360efbdSAlfred Perlstein  * "handle" is returned on a successful call.  At the start of a session (after
1768360efbdSAlfred Perlstein  * a call to setnetconfig()) searches through the /etc/netconfig database will
1778360efbdSAlfred Perlstein  * proceed from the start of the file.  The session handle must be passed to
1788360efbdSAlfred Perlstein  * getnetconfig() to parse the file.  Each call to getnetconfig() using the
1798360efbdSAlfred Perlstein  * current handle will process one subsequent entry in /etc/netconfig.
1808360efbdSAlfred Perlstein  * setnetconfig() must be called before the first call to getnetconfig().
1818360efbdSAlfred Perlstein  * (Handles are used to allow for nested calls to setnetpath()).
1828360efbdSAlfred Perlstein  *
1838360efbdSAlfred Perlstein  * A new session is established with each call to setnetconfig(), with a new
1848360efbdSAlfred Perlstein  * handle being returned on each call.  Previously established sessions remain
1858360efbdSAlfred Perlstein  * active until endnetconfig() is called with that session's handle as an
1868360efbdSAlfred Perlstein  * argument.
1878360efbdSAlfred Perlstein  *
1888360efbdSAlfred Perlstein  * setnetconfig() need *not* be called before a call to getnetconfigent().
1898360efbdSAlfred Perlstein  * setnetconfig() returns a NULL pointer on failure (for example, if
1908360efbdSAlfred Perlstein  * the netconfig database is not present).
1918360efbdSAlfred Perlstein  */
1928360efbdSAlfred Perlstein void *
1938360efbdSAlfred Perlstein setnetconfig()
1948360efbdSAlfred Perlstein {
1958360efbdSAlfred Perlstein     struct netconfig_vars *nc_vars;
1968360efbdSAlfred Perlstein 
1978360efbdSAlfred Perlstein     if ((nc_vars = (struct netconfig_vars *)malloc(sizeof
1988360efbdSAlfred Perlstein 		(struct netconfig_vars))) == NULL) {
1998360efbdSAlfred Perlstein 	return(NULL);
2008360efbdSAlfred Perlstein     }
2018360efbdSAlfred Perlstein 
2028360efbdSAlfred Perlstein     /*
2038360efbdSAlfred Perlstein      * For multiple calls, i.e. nc_file is not NULL, we just return the
2048360efbdSAlfred Perlstein      * handle without reopening the netconfig db.
2058360efbdSAlfred Perlstein      */
2068360efbdSAlfred Perlstein     ni.ref++;
2078360efbdSAlfred Perlstein     if ((nc_file != NULL) || (nc_file = fopen(NETCONFIG, "r")) != NULL) {
2088360efbdSAlfred Perlstein 	nc_vars->valid = NC_VALID;
2098360efbdSAlfred Perlstein 	nc_vars->flag = 0;
2108360efbdSAlfred Perlstein 	nc_vars->nc_configs = ni.head;
2118360efbdSAlfred Perlstein 	return ((void *)nc_vars);
2128360efbdSAlfred Perlstein     }
2138360efbdSAlfred Perlstein     ni.ref--;
2148360efbdSAlfred Perlstein     nc_error = NC_NONETCONFIG;
2158360efbdSAlfred Perlstein     free(nc_vars);
2168360efbdSAlfred Perlstein     return (NULL);
2178360efbdSAlfred Perlstein }
2188360efbdSAlfred Perlstein 
2198360efbdSAlfred Perlstein 
2208360efbdSAlfred Perlstein /*
2218360efbdSAlfred Perlstein  * When first called, getnetconfig() returns a pointer to the first entry in
2228360efbdSAlfred Perlstein  * the netconfig database, formatted as a struct netconfig.  On each subsequent
2238360efbdSAlfred Perlstein  * call, getnetconfig() returns a pointer to the next entry in the database.
2248360efbdSAlfred Perlstein  * getnetconfig() can thus be used to search the entire netconfig file.
2258360efbdSAlfred Perlstein  * getnetconfig() returns NULL at end of file.
2268360efbdSAlfred Perlstein  */
2278360efbdSAlfred Perlstein 
2288360efbdSAlfred Perlstein struct netconfig *
2298360efbdSAlfred Perlstein getnetconfig(handlep)
2308360efbdSAlfred Perlstein void *handlep;
2318360efbdSAlfred Perlstein {
2328360efbdSAlfred Perlstein     struct netconfig_vars *ncp = (struct netconfig_vars *)handlep;
2338360efbdSAlfred Perlstein     char *stringp;		/* tmp string pointer */
2348360efbdSAlfred Perlstein     struct netconfig_list	*list;
2358360efbdSAlfred Perlstein     struct netconfig *np;
2368360efbdSAlfred Perlstein 
2378360efbdSAlfred Perlstein     /*
2388360efbdSAlfred Perlstein      * Verify that handle is valid
2398360efbdSAlfred Perlstein      */
2408360efbdSAlfred Perlstein     if (ncp == NULL || nc_file == NULL) {
2418360efbdSAlfred Perlstein 	nc_error = NC_NOTINIT;
2428360efbdSAlfred Perlstein 	return (NULL);
2438360efbdSAlfred Perlstein     }
2448360efbdSAlfred Perlstein 
2458360efbdSAlfred Perlstein     switch (ncp->valid) {
2468360efbdSAlfred Perlstein     case NC_VALID:
2478360efbdSAlfred Perlstein 	/*
2488360efbdSAlfred Perlstein 	 * If entry has already been read into the list,
2498360efbdSAlfred Perlstein 	 * we return the entry in the linked list.
2508360efbdSAlfred Perlstein 	 * If this is the first time call, check if there are any entries in
2518360efbdSAlfred Perlstein 	 * linked list.  If no entries, we need to read the netconfig db.
2528360efbdSAlfred Perlstein 	 * If we have been here and the next entry is there, we just return
2538360efbdSAlfred Perlstein 	 * it.
2548360efbdSAlfred Perlstein 	 */
2558360efbdSAlfred Perlstein 	if (ncp->flag == 0) {	/* first time */
2568360efbdSAlfred Perlstein 	    ncp->flag = 1;
2578360efbdSAlfred Perlstein 	    ncp->nc_configs = ni.head;
2588360efbdSAlfred Perlstein 	    if (ncp->nc_configs != NULL)	/* entry already exist */
2598360efbdSAlfred Perlstein 		return(ncp->nc_configs->ncp);
2608360efbdSAlfred Perlstein 	}
2618360efbdSAlfred Perlstein 	else if (ncp->nc_configs != NULL && ncp->nc_configs->next != NULL) {
2628360efbdSAlfred Perlstein 	    ncp->nc_configs = ncp->nc_configs->next;
2638360efbdSAlfred Perlstein 	    return(ncp->nc_configs->ncp);
2648360efbdSAlfred Perlstein 	}
2658360efbdSAlfred Perlstein 
2668360efbdSAlfred Perlstein 	/*
2678360efbdSAlfred Perlstein 	 * If we cannot find the entry in the list and is end of file,
2688360efbdSAlfred Perlstein 	 * we give up.
2698360efbdSAlfred Perlstein 	 */
2708360efbdSAlfred Perlstein 	if (ni.eof == 1)	return(NULL);
2718360efbdSAlfred Perlstein 	break;
2728360efbdSAlfred Perlstein     default:
2738360efbdSAlfred Perlstein 	nc_error = NC_NOTINIT;
2748360efbdSAlfred Perlstein 	return (NULL);
2758360efbdSAlfred Perlstein     }
2768360efbdSAlfred Perlstein 
2778360efbdSAlfred Perlstein     stringp = (char *) malloc(MAXNETCONFIGLINE);
2788360efbdSAlfred Perlstein     if (stringp == NULL)
2798360efbdSAlfred Perlstein     	return (NULL);
2808360efbdSAlfred Perlstein 
2818360efbdSAlfred Perlstein #ifdef MEM_CHK
2828360efbdSAlfred Perlstein     if (malloc_verify() == 0) {
2838360efbdSAlfred Perlstein 	fprintf(stderr, "memory heap corrupted in getnetconfig\n");
2848360efbdSAlfred Perlstein 	exit(1);
2858360efbdSAlfred Perlstein     }
2868360efbdSAlfred Perlstein #endif
2878360efbdSAlfred Perlstein 
2888360efbdSAlfred Perlstein     /*
2898360efbdSAlfred Perlstein      * Read a line from netconfig file.
2908360efbdSAlfred Perlstein      */
2918360efbdSAlfred Perlstein     do {
2928360efbdSAlfred Perlstein 	if (fgets(stringp, MAXNETCONFIGLINE, nc_file) == NULL) {
2938360efbdSAlfred Perlstein 	    free(stringp);
2948360efbdSAlfred Perlstein 	    ni.eof = 1;
2958360efbdSAlfred Perlstein 	    return (NULL);
2968360efbdSAlfred Perlstein         }
2978360efbdSAlfred Perlstein     } while (*stringp == '#');
2988360efbdSAlfred Perlstein 
2998360efbdSAlfred Perlstein     list = (struct netconfig_list *) malloc(sizeof (struct netconfig_list));
3008360efbdSAlfred Perlstein     if (list == NULL) {
3018360efbdSAlfred Perlstein     	free(stringp);
3028360efbdSAlfred Perlstein     	return(NULL);
3038360efbdSAlfred Perlstein     }
3048360efbdSAlfred Perlstein     np = (struct netconfig *) malloc(sizeof (struct netconfig));
3058360efbdSAlfred Perlstein     if (np == NULL) {
3068360efbdSAlfred Perlstein     	free(stringp);
3078360efbdSAlfred Perlstein 	free(list);
3088360efbdSAlfred Perlstein     	return(NULL);
3098360efbdSAlfred Perlstein     }
3108360efbdSAlfred Perlstein     list->ncp = np;
3118360efbdSAlfred Perlstein     list->next = NULL;
3128360efbdSAlfred Perlstein     list->ncp->nc_lookups = NULL;
3138360efbdSAlfred Perlstein     list->linep = stringp;
3148360efbdSAlfred Perlstein     if (parse_ncp(stringp, list->ncp) == -1) {
3158360efbdSAlfred Perlstein 	free(stringp);
3168360efbdSAlfred Perlstein 	free(np);
3178360efbdSAlfred Perlstein 	free(list);
3188360efbdSAlfred Perlstein 	return (NULL);
3198360efbdSAlfred Perlstein     }
3208360efbdSAlfred Perlstein     else {
3218360efbdSAlfred Perlstein 	/*
3228360efbdSAlfred Perlstein 	 * If this is the first entry that's been read, it is the head of
3238360efbdSAlfred Perlstein 	 * the list.  If not, put the entry at the end of the list.
3248360efbdSAlfred Perlstein 	 * Reposition the current pointer of the handle to the last entry
3258360efbdSAlfred Perlstein 	 * in the list.
3268360efbdSAlfred Perlstein 	 */
3278360efbdSAlfred Perlstein 	if (ni.head == NULL) {	/* first entry */
3288360efbdSAlfred Perlstein 	    ni.head = ni.tail = list;
3298360efbdSAlfred Perlstein 	}
3308360efbdSAlfred Perlstein     	else {
3318360efbdSAlfred Perlstein     	    ni.tail->next = list;
3328360efbdSAlfred Perlstein     	    ni.tail = ni.tail->next;
3338360efbdSAlfred Perlstein     	}
3348360efbdSAlfred Perlstein 	ncp->nc_configs = ni.tail;
3358360efbdSAlfred Perlstein 	return(ni.tail->ncp);
3368360efbdSAlfred Perlstein     }
3378360efbdSAlfred Perlstein }
3388360efbdSAlfred Perlstein 
3398360efbdSAlfred Perlstein /*
3408360efbdSAlfred Perlstein  * endnetconfig() may be called to "unbind" or "close" the netconfig database
3418360efbdSAlfred Perlstein  * when processing is complete, releasing resources for reuse.  endnetconfig()
3428360efbdSAlfred Perlstein  * may not be called before setnetconfig().  endnetconfig() returns 0 on
3438360efbdSAlfred Perlstein  * success and -1 on failure (for example, if setnetconfig() was not called
3448360efbdSAlfred Perlstein  * previously).
3458360efbdSAlfred Perlstein  */
3468360efbdSAlfred Perlstein int
3478360efbdSAlfred Perlstein endnetconfig(handlep)
3488360efbdSAlfred Perlstein void *handlep;
3498360efbdSAlfred Perlstein {
3508360efbdSAlfred Perlstein     struct netconfig_vars *nc_handlep = (struct netconfig_vars *)handlep;
3518360efbdSAlfred Perlstein 
3528360efbdSAlfred Perlstein     struct netconfig_list *q, *p;
3538360efbdSAlfred Perlstein 
3548360efbdSAlfred Perlstein     /*
3558360efbdSAlfred Perlstein      * Verify that handle is valid
3568360efbdSAlfred Perlstein      */
3578360efbdSAlfred Perlstein     if (nc_handlep == NULL || (nc_handlep->valid != NC_VALID &&
3588360efbdSAlfred Perlstein 	    nc_handlep->valid != NC_STORAGE)) {
3598360efbdSAlfred Perlstein 	nc_error = NC_NOTINIT;
3608360efbdSAlfred Perlstein 	return (-1);
3618360efbdSAlfred Perlstein     }
3628360efbdSAlfred Perlstein 
3638360efbdSAlfred Perlstein     /*
3648360efbdSAlfred Perlstein      * Return 0 if anyone still needs it.
3658360efbdSAlfred Perlstein      */
3668360efbdSAlfred Perlstein     nc_handlep->valid = NC_INVALID;
3678360efbdSAlfred Perlstein     nc_handlep->flag = 0;
3688360efbdSAlfred Perlstein     nc_handlep->nc_configs = NULL;
3698360efbdSAlfred Perlstein     if (--ni.ref > 0) {
3708360efbdSAlfred Perlstein     	free(nc_handlep);
3718360efbdSAlfred Perlstein 	return(0);
3728360efbdSAlfred Perlstein     }
3738360efbdSAlfred Perlstein 
3748360efbdSAlfred Perlstein     /*
3758360efbdSAlfred Perlstein      * Noone needs these entries anymore, then frees them.
3768360efbdSAlfred Perlstein      * Make sure all info in netconfig_info structure has been reinitialized.
3778360efbdSAlfred Perlstein      */
3788360efbdSAlfred Perlstein     q = p = ni.head;
3798360efbdSAlfred Perlstein     ni.eof = ni.ref = 0;
3808360efbdSAlfred Perlstein     ni.head = NULL;
3818360efbdSAlfred Perlstein     ni.tail = NULL;
3828360efbdSAlfred Perlstein     while (q) {
3838360efbdSAlfred Perlstein 	p = q->next;
3848360efbdSAlfred Perlstein 	if (q->ncp->nc_lookups != NULL) free(q->ncp->nc_lookups);
3858360efbdSAlfred Perlstein 	free(q->ncp);
3868360efbdSAlfred Perlstein 	free(q->linep);
3878360efbdSAlfred Perlstein 	free(q);
3888360efbdSAlfred Perlstein 	q = p;
3898360efbdSAlfred Perlstein     }
3908360efbdSAlfred Perlstein     free(nc_handlep);
3918360efbdSAlfred Perlstein 
3928360efbdSAlfred Perlstein     fclose(nc_file);
3938360efbdSAlfred Perlstein     nc_file = NULL;
3948360efbdSAlfred Perlstein     return (0);
3958360efbdSAlfred Perlstein }
3968360efbdSAlfred Perlstein 
3978360efbdSAlfred Perlstein /*
3988360efbdSAlfred Perlstein  * getnetconfigent(netid) returns a pointer to the struct netconfig structure
3998360efbdSAlfred Perlstein  * corresponding to netid.  It returns NULL if netid is invalid (that is, does
4008360efbdSAlfred Perlstein  * not name an entry in the netconfig database).  It returns NULL and sets
4018360efbdSAlfred Perlstein  * errno in case of failure (for example, if the netconfig database cannot be
4028360efbdSAlfred Perlstein  * opened).
4038360efbdSAlfred Perlstein  */
4048360efbdSAlfred Perlstein 
4058360efbdSAlfred Perlstein struct netconfig *
4068360efbdSAlfred Perlstein getnetconfigent(netid)
40740c10ffdSAlfred Perlstein 	const char *netid;
4088360efbdSAlfred Perlstein {
4098360efbdSAlfred Perlstein     FILE *file;		/* NETCONFIG db's file pointer */
4108360efbdSAlfred Perlstein     char *linep;	/* holds current netconfig line */
4118360efbdSAlfred Perlstein     char *stringp;	/* temporary string pointer */
4128360efbdSAlfred Perlstein     struct netconfig *ncp = NULL;   /* returned value */
4138360efbdSAlfred Perlstein     struct netconfig_list *list;	/* pointer to cache list */
4148360efbdSAlfred Perlstein 
415b3a38fe3SIan Dowse     nc_error = NC_NOTFOUND;	/* default error. */
4168360efbdSAlfred Perlstein     if (netid == NULL || strlen(netid) == 0) {
4178360efbdSAlfred Perlstein 	return (NULL);
4188360efbdSAlfred Perlstein     }
4198360efbdSAlfred Perlstein 
4208360efbdSAlfred Perlstein     /*
4218360efbdSAlfred Perlstein      * Look up table if the entries have already been read and parsed in
4228360efbdSAlfred Perlstein      * getnetconfig(), then copy this entry into a buffer and return it.
4238360efbdSAlfred Perlstein      * If we cannot find the entry in the current list and there are more
4248360efbdSAlfred Perlstein      * entries in the netconfig db that has not been read, we then read the
4258360efbdSAlfred Perlstein      * db and try find the match netid.
4268360efbdSAlfred Perlstein      * If all the netconfig db has been read and placed into the list and
4278360efbdSAlfred Perlstein      * there is no match for the netid, return NULL.
4288360efbdSAlfred Perlstein      */
4298360efbdSAlfred Perlstein     if (ni.head != NULL) {
4308360efbdSAlfred Perlstein 	for (list = ni.head; list; list = list->next) {
4318360efbdSAlfred Perlstein 	    if (strcmp(list->ncp->nc_netid, netid) == 0) {
4328360efbdSAlfred Perlstein 	        return(dup_ncp(list->ncp));
4338360efbdSAlfred Perlstein 	    }
4348360efbdSAlfred Perlstein 	}
4358360efbdSAlfred Perlstein 	if (ni.eof == 1)	/* that's all the entries */
4368360efbdSAlfred Perlstein 		return(NULL);
4378360efbdSAlfred Perlstein     }
4388360efbdSAlfred Perlstein 
4398360efbdSAlfred Perlstein 
4408360efbdSAlfred Perlstein     if ((file = fopen(NETCONFIG, "r")) == NULL) {
441b3a38fe3SIan Dowse 	nc_error = NC_NONETCONFIG;
4428360efbdSAlfred Perlstein 	return (NULL);
4438360efbdSAlfred Perlstein     }
4448360efbdSAlfred Perlstein 
4458360efbdSAlfred Perlstein     if ((linep = malloc(MAXNETCONFIGLINE)) == NULL) {
4468360efbdSAlfred Perlstein 	fclose(file);
447b3a38fe3SIan Dowse 	nc_error = NC_NOMEM;
4488360efbdSAlfred Perlstein 	return (NULL);
4498360efbdSAlfred Perlstein     }
4508360efbdSAlfred Perlstein     do {
4518360efbdSAlfred Perlstein 	int len;
4528360efbdSAlfred Perlstein 	char *tmpp;	/* tmp string pointer */
4538360efbdSAlfred Perlstein 
4548360efbdSAlfred Perlstein 	do {
4558360efbdSAlfred Perlstein 	    if ((stringp = fgets(linep, MAXNETCONFIGLINE, file)) == NULL) {
4568360efbdSAlfred Perlstein 		break;
4578360efbdSAlfred Perlstein 	    }
4588360efbdSAlfred Perlstein 	} while (*stringp == '#');
4598360efbdSAlfred Perlstein 	if (stringp == NULL) {	    /* eof */
4608360efbdSAlfred Perlstein 	    break;
4618360efbdSAlfred Perlstein 	}
4628360efbdSAlfred Perlstein 	if ((tmpp = strpbrk(stringp, "\t ")) == NULL) {	/* can't parse file */
4638360efbdSAlfred Perlstein 	    nc_error = NC_BADFILE;
4648360efbdSAlfred Perlstein 	    break;
4658360efbdSAlfred Perlstein 	}
4668360efbdSAlfred Perlstein 	if (strlen(netid) == (len = tmpp - stringp) &&	/* a match */
4678360efbdSAlfred Perlstein 		strncmp(stringp, netid, (size_t)len) == 0) {
4688360efbdSAlfred Perlstein 	    if ((ncp = (struct netconfig *)
4698360efbdSAlfred Perlstein 		    malloc(sizeof (struct netconfig))) == NULL) {
4708360efbdSAlfred Perlstein 		break;
4718360efbdSAlfred Perlstein 	    }
4728360efbdSAlfred Perlstein 	    ncp->nc_lookups = NULL;
4738360efbdSAlfred Perlstein 	    if (parse_ncp(linep, ncp) == -1) {
4748360efbdSAlfred Perlstein 		free(ncp);
4758360efbdSAlfred Perlstein 		ncp = NULL;
4768360efbdSAlfred Perlstein 	    }
4778360efbdSAlfred Perlstein 	    break;
4788360efbdSAlfred Perlstein 	}
4798360efbdSAlfred Perlstein     } while (stringp != NULL);
4808360efbdSAlfred Perlstein     if (ncp == NULL) {
4818360efbdSAlfred Perlstein 	free(linep);
4828360efbdSAlfred Perlstein     }
4838360efbdSAlfred Perlstein     fclose(file);
4848360efbdSAlfred Perlstein     return(ncp);
4858360efbdSAlfred Perlstein }
4868360efbdSAlfred Perlstein 
4878360efbdSAlfred Perlstein /*
4888360efbdSAlfred Perlstein  * freenetconfigent(netconfigp) frees the netconfig structure pointed to by
4898360efbdSAlfred Perlstein  * netconfigp (previously returned by getnetconfigent()).
4908360efbdSAlfred Perlstein  */
4918360efbdSAlfred Perlstein 
4928360efbdSAlfred Perlstein void
4938360efbdSAlfred Perlstein freenetconfigent(netconfigp)
4948360efbdSAlfred Perlstein 	struct netconfig *netconfigp;
4958360efbdSAlfred Perlstein {
4968360efbdSAlfred Perlstein     if (netconfigp != NULL) {
4978360efbdSAlfred Perlstein 	free(netconfigp->nc_netid);	/* holds all netconfigp's strings */
4988360efbdSAlfred Perlstein 	if (netconfigp->nc_lookups != NULL)
4998360efbdSAlfred Perlstein 	    free(netconfigp->nc_lookups);
5008360efbdSAlfred Perlstein 	free(netconfigp);
5018360efbdSAlfred Perlstein     }
5028360efbdSAlfred Perlstein     return;
5038360efbdSAlfred Perlstein }
5048360efbdSAlfred Perlstein 
5058360efbdSAlfred Perlstein /*
5068360efbdSAlfred Perlstein  * Parse line and stuff it in a struct netconfig
5078360efbdSAlfred Perlstein  * Typical line might look like:
5088360efbdSAlfred Perlstein  *	udp tpi_cots vb inet udp /dev/udp /usr/lib/ip.so,/usr/local/ip.so
5098360efbdSAlfred Perlstein  *
5108360efbdSAlfred Perlstein  * We return -1 if any of the tokens don't parse, or malloc fails.
5118360efbdSAlfred Perlstein  *
5128360efbdSAlfred Perlstein  * Note that we modify stringp (putting NULLs after tokens) and
5138360efbdSAlfred Perlstein  * we set the ncp's string field pointers to point to these tokens within
5148360efbdSAlfred Perlstein  * stringp.
5158360efbdSAlfred Perlstein  */
5168360efbdSAlfred Perlstein 
5178360efbdSAlfred Perlstein static int
5188360efbdSAlfred Perlstein parse_ncp(stringp, ncp)
5198360efbdSAlfred Perlstein char *stringp;		/* string to parse */
5208360efbdSAlfred Perlstein struct netconfig *ncp;	/* where to put results */
5218360efbdSAlfred Perlstein {
5228360efbdSAlfred Perlstein     char    *tokenp;	/* for processing tokens */
5238360efbdSAlfred Perlstein     char    *lasts;
5248360efbdSAlfred Perlstein 
5258360efbdSAlfred Perlstein     nc_error = NC_BADFILE;	/* nearly anything that breaks is for this reason */
5268360efbdSAlfred Perlstein     stringp[strlen(stringp)-1] = '\0';	/* get rid of newline */
5278360efbdSAlfred Perlstein     /* netid */
5288360efbdSAlfred Perlstein     if ((ncp->nc_netid = strtok_r(stringp, "\t ", &lasts)) == NULL) {
5298360efbdSAlfred Perlstein 	return (-1);
5308360efbdSAlfred Perlstein     }
5318360efbdSAlfred Perlstein 
5328360efbdSAlfred Perlstein     /* semantics */
5338360efbdSAlfred Perlstein     if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) {
5348360efbdSAlfred Perlstein 	return (-1);
5358360efbdSAlfred Perlstein     }
5368360efbdSAlfred Perlstein     if (strcmp(tokenp, NC_TPI_COTS_ORD_S) == 0)
5378360efbdSAlfred Perlstein 	ncp->nc_semantics = NC_TPI_COTS_ORD;
5388360efbdSAlfred Perlstein     else if (strcmp(tokenp, NC_TPI_COTS_S) == 0)
5398360efbdSAlfred Perlstein 	ncp->nc_semantics = NC_TPI_COTS;
5408360efbdSAlfred Perlstein     else if (strcmp(tokenp, NC_TPI_CLTS_S) == 0)
5418360efbdSAlfred Perlstein 	ncp->nc_semantics = NC_TPI_CLTS;
5428360efbdSAlfred Perlstein     else if (strcmp(tokenp, NC_TPI_RAW_S) == 0)
5438360efbdSAlfred Perlstein 	ncp->nc_semantics = NC_TPI_RAW;
5448360efbdSAlfred Perlstein     else
5458360efbdSAlfred Perlstein 	return (-1);
5468360efbdSAlfred Perlstein 
5478360efbdSAlfred Perlstein     /* flags */
5488360efbdSAlfred Perlstein     if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) {
5498360efbdSAlfred Perlstein 	return (-1);
5508360efbdSAlfred Perlstein     }
5518360efbdSAlfred Perlstein     for (ncp->nc_flag = NC_NOFLAG; *tokenp != '\0';
5528360efbdSAlfred Perlstein 	    tokenp++) {
5538360efbdSAlfred Perlstein 	switch (*tokenp) {
5548360efbdSAlfred Perlstein 	case NC_NOFLAG_C:
5558360efbdSAlfred Perlstein 	    break;
5568360efbdSAlfred Perlstein 	case NC_VISIBLE_C:
5578360efbdSAlfred Perlstein 	    ncp->nc_flag |= NC_VISIBLE;
5588360efbdSAlfred Perlstein 	    break;
5598360efbdSAlfred Perlstein 	case NC_BROADCAST_C:
5608360efbdSAlfred Perlstein 	    ncp->nc_flag |= NC_BROADCAST;
5618360efbdSAlfred Perlstein 	    break;
5628360efbdSAlfred Perlstein 	default:
5638360efbdSAlfred Perlstein 	    return (-1);
5648360efbdSAlfred Perlstein 	}
5658360efbdSAlfred Perlstein     }
5668360efbdSAlfred Perlstein     /* protocol family */
5678360efbdSAlfred Perlstein     if ((ncp->nc_protofmly = strtok_r(NULL, "\t ", &lasts)) == NULL) {
5688360efbdSAlfred Perlstein 	return (-1);
5698360efbdSAlfred Perlstein     }
5708360efbdSAlfred Perlstein     /* protocol name */
5718360efbdSAlfred Perlstein     if ((ncp->nc_proto = strtok_r(NULL, "\t ", &lasts)) == NULL) {
5728360efbdSAlfred Perlstein 	return (-1);
5738360efbdSAlfred Perlstein     }
5748360efbdSAlfred Perlstein     /* network device */
5758360efbdSAlfred Perlstein     if ((ncp->nc_device = strtok_r(NULL, "\t ", &lasts)) == NULL) {
5768360efbdSAlfred Perlstein 	return (-1);
5778360efbdSAlfred Perlstein     }
5788360efbdSAlfred Perlstein     if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) {
5798360efbdSAlfred Perlstein 	return (-1);
5808360efbdSAlfred Perlstein     }
5818360efbdSAlfred Perlstein     if (strcmp(tokenp, NC_NOLOOKUP) == 0) {
5828360efbdSAlfred Perlstein 	ncp->nc_nlookups = 0;
5838360efbdSAlfred Perlstein 	ncp->nc_lookups = NULL;
5848360efbdSAlfred Perlstein     } else {
5858360efbdSAlfred Perlstein 	char *cp;	    /* tmp string */
5868360efbdSAlfred Perlstein 
5878360efbdSAlfred Perlstein 	if (ncp->nc_lookups != NULL)	/* from last visit */
5888360efbdSAlfred Perlstein 	    free(ncp->nc_lookups);
5898360efbdSAlfred Perlstein 	/* preallocate one string pointer */
5908360efbdSAlfred Perlstein 	ncp->nc_lookups = (char **)malloc(sizeof (char *));
5918360efbdSAlfred Perlstein 	ncp->nc_nlookups = 0;
5928360efbdSAlfred Perlstein 	while ((cp = tokenp) != NULL) {
5938360efbdSAlfred Perlstein 	    tokenp = _get_next_token(cp, ',');
5948360efbdSAlfred Perlstein 	    ncp->nc_lookups[(size_t)ncp->nc_nlookups++] = cp;
5958360efbdSAlfred Perlstein 	    ncp->nc_lookups = (char **)realloc(ncp->nc_lookups,
5968360efbdSAlfred Perlstein 		(size_t)(ncp->nc_nlookups+1) *sizeof(char *));	/* for next loop */
5978360efbdSAlfred Perlstein 	}
5988360efbdSAlfred Perlstein     }
5998360efbdSAlfred Perlstein     return (0);
6008360efbdSAlfred Perlstein }
6018360efbdSAlfred Perlstein 
6028360efbdSAlfred Perlstein 
6038360efbdSAlfred Perlstein /*
6048360efbdSAlfred Perlstein  * Returns a string describing the reason for failure.
6058360efbdSAlfred Perlstein  */
6068360efbdSAlfred Perlstein char *
6078360efbdSAlfred Perlstein nc_sperror()
6088360efbdSAlfred Perlstein {
6098360efbdSAlfred Perlstein     const char *message;
6108360efbdSAlfred Perlstein 
6118360efbdSAlfred Perlstein     switch(nc_error) {
6128360efbdSAlfred Perlstein     case NC_NONETCONFIG:
6138360efbdSAlfred Perlstein 	message = _nc_errors[0];
6148360efbdSAlfred Perlstein 	break;
6158360efbdSAlfred Perlstein     case NC_NOMEM:
6168360efbdSAlfred Perlstein 	message = _nc_errors[1];
6178360efbdSAlfred Perlstein 	break;
6188360efbdSAlfred Perlstein     case NC_NOTINIT:
6198360efbdSAlfred Perlstein 	message = _nc_errors[2];
6208360efbdSAlfred Perlstein 	break;
6218360efbdSAlfred Perlstein     case NC_BADFILE:
6228360efbdSAlfred Perlstein 	message = _nc_errors[3];
6238360efbdSAlfred Perlstein 	break;
624b3a38fe3SIan Dowse     case NC_NOTFOUND:
625b3a38fe3SIan Dowse 	message = _nc_errors[4];
626b3a38fe3SIan Dowse 	break;
6278360efbdSAlfred Perlstein     default:
6288360efbdSAlfred Perlstein 	message = "Unknown network selection error";
6298360efbdSAlfred Perlstein     }
6308360efbdSAlfred Perlstein     /* LINTED const castaway */
6318360efbdSAlfred Perlstein     return ((char *)message);
6328360efbdSAlfred Perlstein }
6338360efbdSAlfred Perlstein 
6348360efbdSAlfred Perlstein /*
6358360efbdSAlfred Perlstein  * Prints a message onto standard error describing the reason for failure.
6368360efbdSAlfred Perlstein  */
6378360efbdSAlfred Perlstein void
6388360efbdSAlfred Perlstein nc_perror(s)
6398360efbdSAlfred Perlstein 	const char *s;
6408360efbdSAlfred Perlstein {
641b3a38fe3SIan Dowse     fprintf(stderr, "%s: %s\n", s, nc_sperror());
6428360efbdSAlfred Perlstein }
6438360efbdSAlfred Perlstein 
6448360efbdSAlfred Perlstein /*
6458360efbdSAlfred Perlstein  * Duplicates the matched netconfig buffer.
6468360efbdSAlfred Perlstein  */
6478360efbdSAlfred Perlstein static struct netconfig *
6488360efbdSAlfred Perlstein dup_ncp(ncp)
6498360efbdSAlfred Perlstein struct netconfig	*ncp;
6508360efbdSAlfred Perlstein {
6518360efbdSAlfred Perlstein     struct netconfig	*p;
6528360efbdSAlfred Perlstein     char	*tmp;
6538360efbdSAlfred Perlstein     int	i;
6548360efbdSAlfred Perlstein 
6558360efbdSAlfred Perlstein     if ((tmp=malloc(MAXNETCONFIGLINE)) == NULL)
6568360efbdSAlfred Perlstein 	return(NULL);
6578360efbdSAlfred Perlstein     if ((p=(struct netconfig *)malloc(sizeof(struct netconfig))) == NULL) {
6588360efbdSAlfred Perlstein 	free(tmp);
6598360efbdSAlfred Perlstein 	return(NULL);
6608360efbdSAlfred Perlstein     }
6618360efbdSAlfred Perlstein     /*
6628360efbdSAlfred Perlstein      * First we dup all the data from matched netconfig buffer.  Then we
6638360efbdSAlfred Perlstein      * adjust some of the member pointer to a pre-allocated buffer where
6648360efbdSAlfred Perlstein      * contains part of the data.
6658360efbdSAlfred Perlstein      * To follow the convention used in parse_ncp(), we store all the
6668360efbdSAlfred Perlstein      * neccessary information in the pre-allocated buffer and let each
6678360efbdSAlfred Perlstein      * of the netconfig char pointer member point to the right address
6688360efbdSAlfred Perlstein      * in the buffer.
6698360efbdSAlfred Perlstein      */
6708360efbdSAlfred Perlstein     *p = *ncp;
6718360efbdSAlfred Perlstein     p->nc_netid = (char *)strcpy(tmp,ncp->nc_netid);
6728360efbdSAlfred Perlstein     tmp = strchr(tmp, NULL) + 1;
6738360efbdSAlfred Perlstein     p->nc_protofmly = (char *)strcpy(tmp,ncp->nc_protofmly);
6748360efbdSAlfred Perlstein     tmp = strchr(tmp, NULL) + 1;
6758360efbdSAlfred Perlstein     p->nc_proto = (char *)strcpy(tmp,ncp->nc_proto);
6768360efbdSAlfred Perlstein     tmp = strchr(tmp, NULL) + 1;
6778360efbdSAlfred Perlstein     p->nc_device = (char *)strcpy(tmp,ncp->nc_device);
6788360efbdSAlfred Perlstein     p->nc_lookups = (char **)malloc((size_t)(p->nc_nlookups+1) * sizeof(char *));
6798360efbdSAlfred Perlstein     if (p->nc_lookups == NULL) {
6808360efbdSAlfred Perlstein 	free(p->nc_netid);
6818360efbdSAlfred Perlstein 	return(NULL);
6828360efbdSAlfred Perlstein     }
6838360efbdSAlfred Perlstein     for (i=0; i < p->nc_nlookups; i++) {
6848360efbdSAlfred Perlstein     	tmp = strchr(tmp, NULL) + 1;
6858360efbdSAlfred Perlstein     	p->nc_lookups[i] = (char *)strcpy(tmp,ncp->nc_lookups[i]);
6868360efbdSAlfred Perlstein     }
6878360efbdSAlfred Perlstein     return(p);
6888360efbdSAlfred Perlstein }
689