xref: /freebsd/lib/libc/rpc/getnetconfig.c (revision 6f88d2a870a280d1ee52ed56c970ea70dbe92dbf)
18360efbdSAlfred Perlstein /*	$NetBSD: getnetconfig.c,v 1.3 2000/07/06 03:10:34 christos Exp $	*/
28360efbdSAlfred Perlstein 
38360efbdSAlfred Perlstein /*
48360efbdSAlfred Perlstein  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
58360efbdSAlfred Perlstein  * unrestricted use provided that this legend is included on all tape
68360efbdSAlfred Perlstein  * media and as a part of the software program in whole or part.  Users
78360efbdSAlfred Perlstein  * may copy or modify Sun RPC without charge, but are not authorized
88360efbdSAlfred Perlstein  * to license or distribute it to anyone else except as part of a product or
98360efbdSAlfred Perlstein  * program developed by the user or with the express written consent of
108360efbdSAlfred Perlstein  * Sun Microsystems, Inc.
118360efbdSAlfred Perlstein  *
128360efbdSAlfred Perlstein  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
138360efbdSAlfred Perlstein  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
148360efbdSAlfred Perlstein  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
158360efbdSAlfred Perlstein  *
168360efbdSAlfred Perlstein  * Sun RPC is provided with no support and without any obligation on the
178360efbdSAlfred Perlstein  * part of Sun Microsystems, Inc. to assist in its use, correction,
188360efbdSAlfred Perlstein  * modification or enhancement.
198360efbdSAlfred Perlstein  *
208360efbdSAlfred Perlstein  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
218360efbdSAlfred Perlstein  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
228360efbdSAlfred Perlstein  * OR ANY PART THEREOF.
238360efbdSAlfred Perlstein  *
248360efbdSAlfred Perlstein  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
258360efbdSAlfred Perlstein  * or profits or other special, indirect and consequential damages, even if
268360efbdSAlfred Perlstein  * Sun has been advised of the possibility of such damages.
278360efbdSAlfred Perlstein  *
288360efbdSAlfred Perlstein  * Sun Microsystems, Inc.
298360efbdSAlfred Perlstein  * 2550 Garcia Avenue
308360efbdSAlfred Perlstein  * Mountain View, California  94043
318360efbdSAlfred Perlstein  */
32a986ef57SDavid E. O'Brien 
33a986ef57SDavid E. O'Brien #if defined(LIBC_SCCS) && !defined(lint)
348360efbdSAlfred Perlstein static char sccsid[] = "@(#)getnetconfig.c	1.12 91/12/19 SMI";
358360efbdSAlfred Perlstein #endif
36d3d20c82SDavid E. O'Brien #include <sys/cdefs.h>
37d3d20c82SDavid E. O'Brien __FBSDID("$FreeBSD$");
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 <stdio.h>
468360efbdSAlfred Perlstein #include <errno.h>
478360efbdSAlfred Perlstein #include <netconfig.h>
483c788545SMartin Blapp #include <stddef.h>
498360efbdSAlfred Perlstein #include <stdlib.h>
508360efbdSAlfred Perlstein #include <string.h>
518360efbdSAlfred Perlstein #include <rpc/rpc.h>
52e0554a53SJacques Vidrine #include <unistd.h>
538360efbdSAlfred Perlstein #include "un-namespace.h"
548360efbdSAlfred Perlstein #include "rpc_com.h"
558360efbdSAlfred Perlstein 
568360efbdSAlfred Perlstein /*
578360efbdSAlfred Perlstein  * The five library routines in this file provide application access to the
588360efbdSAlfred Perlstein  * system network configuration database, /etc/netconfig.  In addition to the
598360efbdSAlfred Perlstein  * netconfig database and the routines for accessing it, the environment
608360efbdSAlfred Perlstein  * variable NETPATH and its corresponding routines in getnetpath.c may also be
618360efbdSAlfred Perlstein  * used to specify the network transport to be used.
628360efbdSAlfred Perlstein  */
638360efbdSAlfred Perlstein 
648360efbdSAlfred Perlstein 
658360efbdSAlfred Perlstein /*
668360efbdSAlfred Perlstein  * netconfig errors
678360efbdSAlfred Perlstein  */
688360efbdSAlfred Perlstein 
698360efbdSAlfred Perlstein #define NC_NONETCONFIG	ENOENT
708360efbdSAlfred Perlstein #define NC_NOMEM	ENOMEM
718360efbdSAlfred Perlstein #define NC_NOTINIT	EINVAL	    /* setnetconfig was not called first */
728360efbdSAlfred Perlstein #define NC_BADFILE	EBADF	    /* format for netconfig file is bad */
73b3a38fe3SIan Dowse #define NC_NOTFOUND	ENOPROTOOPT /* specified netid was not found */
748360efbdSAlfred Perlstein 
758360efbdSAlfred Perlstein /*
768360efbdSAlfred Perlstein  * semantics as strings (should be in netconfig.h)
778360efbdSAlfred Perlstein  */
788360efbdSAlfred Perlstein #define NC_TPI_CLTS_S	    "tpi_clts"
798360efbdSAlfred Perlstein #define	NC_TPI_COTS_S	    "tpi_cots"
808360efbdSAlfred Perlstein #define	NC_TPI_COTS_ORD_S   "tpi_cots_ord"
818360efbdSAlfred Perlstein #define	NC_TPI_RAW_S        "tpi_raw"
828360efbdSAlfred Perlstein 
838360efbdSAlfred Perlstein /*
848360efbdSAlfred Perlstein  * flags as characters (also should be in netconfig.h)
858360efbdSAlfred Perlstein  */
868360efbdSAlfred Perlstein #define	NC_NOFLAG_C	'-'
878360efbdSAlfred Perlstein #define	NC_VISIBLE_C	'v'
888360efbdSAlfred Perlstein #define	NC_BROADCAST_C	'b'
898360efbdSAlfred Perlstein 
908360efbdSAlfred Perlstein /*
918360efbdSAlfred Perlstein  * Character used to indicate there is no name-to-address lookup library
928360efbdSAlfred Perlstein  */
938360efbdSAlfred Perlstein #define NC_NOLOOKUP	"-"
948360efbdSAlfred Perlstein 
958360efbdSAlfred Perlstein static const char * const _nc_errors[] = {
968360efbdSAlfred Perlstein     "Netconfig database not found",
978360efbdSAlfred Perlstein     "Not enough memory",
988360efbdSAlfred Perlstein     "Not initialized",
99b3a38fe3SIan Dowse     "Netconfig database has invalid format",
100b3a38fe3SIan Dowse     "Netid not found in netconfig database"
1018360efbdSAlfred Perlstein };
1028360efbdSAlfred Perlstein 
1038360efbdSAlfred Perlstein struct netconfig_info {
1048360efbdSAlfred Perlstein     int		eof;	/* all entries has been read */
1058360efbdSAlfred Perlstein     int		ref;	/* # of times setnetconfig() has been called */
1068360efbdSAlfred Perlstein     struct netconfig_list	*head;	/* head of the list */
1078360efbdSAlfred Perlstein     struct netconfig_list	*tail;	/* last of the list */
1088360efbdSAlfred Perlstein };
1098360efbdSAlfred Perlstein 
1108360efbdSAlfred Perlstein struct netconfig_list {
1118360efbdSAlfred Perlstein     char			*linep;	/* hold line read from netconfig */
1128360efbdSAlfred Perlstein     struct netconfig		*ncp;
1138360efbdSAlfred Perlstein     struct netconfig_list	*next;
1148360efbdSAlfred Perlstein };
1158360efbdSAlfred Perlstein 
1168360efbdSAlfred Perlstein struct netconfig_vars {
1178360efbdSAlfred Perlstein     int   valid;	/* token that indicates a valid netconfig_vars */
1188360efbdSAlfred Perlstein     int   flag;		/* first time flag */
1198360efbdSAlfred Perlstein     struct netconfig_list *nc_configs;  /* pointer to the current netconfig entry */
1208360efbdSAlfred Perlstein };
1218360efbdSAlfred Perlstein 
1228360efbdSAlfred Perlstein #define NC_VALID	0xfeed
1238360efbdSAlfred Perlstein #define NC_STORAGE	0xf00d
1248360efbdSAlfred Perlstein #define NC_INVALID	0
1258360efbdSAlfred Perlstein 
1268360efbdSAlfred Perlstein 
127c05ac53bSDavid E. O'Brien static int *__nc_error(void);
128c05ac53bSDavid E. O'Brien static int parse_ncp(char *, struct netconfig *);
129c05ac53bSDavid E. O'Brien static struct netconfig *dup_ncp(struct netconfig *);
1308360efbdSAlfred Perlstein 
1318360efbdSAlfred Perlstein 
1328360efbdSAlfred Perlstein static FILE *nc_file;		/* for netconfig db */
1336f88d2a8SJohn Baldwin static mutex_t nc_file_lock = MUTEX_INITIALIZER;
1345f4faf74SXin LI 
1358360efbdSAlfred Perlstein static struct netconfig_info	ni = { 0, 0, NULL, NULL};
1366f88d2a8SJohn Baldwin static mutex_t ni_lock = MUTEX_INITIALIZER;
1375f4faf74SXin LI 
1386f88d2a8SJohn Baldwin static thread_key_t nc_key;
1396f88d2a8SJohn Baldwin static once_t nc_once = ONCE_INITIALIZER;
1406f88d2a8SJohn Baldwin static int nc_key_error;
1416f88d2a8SJohn Baldwin 
1426f88d2a8SJohn Baldwin static void
1436f88d2a8SJohn Baldwin nc_key_init(void)
1446f88d2a8SJohn Baldwin {
1456f88d2a8SJohn Baldwin 
1466f88d2a8SJohn Baldwin 	nc_key_error = thr_keycreate(&nc_key, free);
1476f88d2a8SJohn Baldwin }
1488360efbdSAlfred Perlstein 
1498360efbdSAlfred Perlstein #define MAXNETCONFIGLINE    1000
1508360efbdSAlfred Perlstein 
1518360efbdSAlfred Perlstein static int *
1528360efbdSAlfred Perlstein __nc_error()
1538360efbdSAlfred Perlstein {
1548360efbdSAlfred Perlstein 	static int nc_error = 0;
1556f88d2a8SJohn Baldwin 	int *nc_addr;
1568360efbdSAlfred Perlstein 
157b3a38fe3SIan Dowse 	/*
158b3a38fe3SIan Dowse 	 * Use the static `nc_error' if we are the main thread
159b3a38fe3SIan Dowse 	 * (including non-threaded programs), or if an allocation
160b3a38fe3SIan Dowse 	 * fails.
161b3a38fe3SIan Dowse 	 */
162b3a38fe3SIan Dowse 	if (thr_main())
163b3a38fe3SIan Dowse 		return (&nc_error);
1646f88d2a8SJohn Baldwin 	if (thr_once(&nc_once, nc_key_init) != 0 || nc_key_error != 0)
165b3a38fe3SIan Dowse 		return (&nc_error);
166b3a38fe3SIan Dowse 	if ((nc_addr = (int *)thr_getspecific(nc_key)) == NULL) {
1678360efbdSAlfred Perlstein 		nc_addr = (int *)malloc(sizeof (int));
1688360efbdSAlfred Perlstein 		if (thr_setspecific(nc_key, (void *) nc_addr) != 0) {
1698360efbdSAlfred Perlstein 			if (nc_addr)
1708360efbdSAlfred Perlstein 				free(nc_addr);
171b3a38fe3SIan Dowse 			return (&nc_error);
1728360efbdSAlfred Perlstein 		}
1738360efbdSAlfred Perlstein 		*nc_addr = 0;
1748360efbdSAlfred Perlstein 	}
175b3a38fe3SIan Dowse 	return (nc_addr);
1768360efbdSAlfred Perlstein }
1778360efbdSAlfred Perlstein 
1788360efbdSAlfred Perlstein #define nc_error        (*(__nc_error()))
1798360efbdSAlfred Perlstein /*
1808360efbdSAlfred Perlstein  * A call to setnetconfig() establishes a /etc/netconfig "session".  A session
1818360efbdSAlfred Perlstein  * "handle" is returned on a successful call.  At the start of a session (after
1828360efbdSAlfred Perlstein  * a call to setnetconfig()) searches through the /etc/netconfig database will
1838360efbdSAlfred Perlstein  * proceed from the start of the file.  The session handle must be passed to
1848360efbdSAlfred Perlstein  * getnetconfig() to parse the file.  Each call to getnetconfig() using the
1858360efbdSAlfred Perlstein  * current handle will process one subsequent entry in /etc/netconfig.
1868360efbdSAlfred Perlstein  * setnetconfig() must be called before the first call to getnetconfig().
1878360efbdSAlfred Perlstein  * (Handles are used to allow for nested calls to setnetpath()).
1888360efbdSAlfred Perlstein  *
1898360efbdSAlfred Perlstein  * A new session is established with each call to setnetconfig(), with a new
1908360efbdSAlfred Perlstein  * handle being returned on each call.  Previously established sessions remain
1918360efbdSAlfred Perlstein  * active until endnetconfig() is called with that session's handle as an
1928360efbdSAlfred Perlstein  * argument.
1938360efbdSAlfred Perlstein  *
1948360efbdSAlfred Perlstein  * setnetconfig() need *not* be called before a call to getnetconfigent().
1958360efbdSAlfred Perlstein  * setnetconfig() returns a NULL pointer on failure (for example, if
1968360efbdSAlfred Perlstein  * the netconfig database is not present).
1978360efbdSAlfred Perlstein  */
1988360efbdSAlfred Perlstein void *
1998360efbdSAlfred Perlstein setnetconfig()
2008360efbdSAlfred Perlstein {
2018360efbdSAlfred Perlstein     struct netconfig_vars *nc_vars;
2028360efbdSAlfred Perlstein 
2038360efbdSAlfred Perlstein     if ((nc_vars = (struct netconfig_vars *)malloc(sizeof
2048360efbdSAlfred Perlstein 		(struct netconfig_vars))) == NULL) {
2058360efbdSAlfred Perlstein 	return(NULL);
2068360efbdSAlfred Perlstein     }
2078360efbdSAlfred Perlstein 
2088360efbdSAlfred Perlstein     /*
2098360efbdSAlfred Perlstein      * For multiple calls, i.e. nc_file is not NULL, we just return the
2108360efbdSAlfred Perlstein      * handle without reopening the netconfig db.
2118360efbdSAlfred Perlstein      */
2125f4faf74SXin LI     mutex_lock(&ni_lock);
2138360efbdSAlfred Perlstein     ni.ref++;
2145f4faf74SXin LI     mutex_unlock(&ni_lock);
2155f4faf74SXin LI 
2165f4faf74SXin LI     mutex_lock(&nc_file_lock);
2178360efbdSAlfred Perlstein     if ((nc_file != NULL) || (nc_file = fopen(NETCONFIG, "r")) != NULL) {
2188360efbdSAlfred Perlstein 	nc_vars->valid = NC_VALID;
2198360efbdSAlfred Perlstein 	nc_vars->flag = 0;
2208360efbdSAlfred Perlstein 	nc_vars->nc_configs = ni.head;
2215f4faf74SXin LI 	mutex_unlock(&nc_file_lock);
2228360efbdSAlfred Perlstein 	return ((void *)nc_vars);
2238360efbdSAlfred Perlstein     }
2245f4faf74SXin LI     mutex_unlock(&nc_file_lock);
2255f4faf74SXin LI 
2265f4faf74SXin LI     mutex_lock(&ni_lock);
2278360efbdSAlfred Perlstein     ni.ref--;
2285f4faf74SXin LI     mutex_unlock(&ni_lock);
2295f4faf74SXin LI 
2308360efbdSAlfred Perlstein     nc_error = NC_NONETCONFIG;
2318360efbdSAlfred Perlstein     free(nc_vars);
2328360efbdSAlfred Perlstein     return (NULL);
2338360efbdSAlfred Perlstein }
2348360efbdSAlfred Perlstein 
2358360efbdSAlfred Perlstein 
2368360efbdSAlfred Perlstein /*
2378360efbdSAlfred Perlstein  * When first called, getnetconfig() returns a pointer to the first entry in
2388360efbdSAlfred Perlstein  * the netconfig database, formatted as a struct netconfig.  On each subsequent
2398360efbdSAlfred Perlstein  * call, getnetconfig() returns a pointer to the next entry in the database.
2408360efbdSAlfred Perlstein  * getnetconfig() can thus be used to search the entire netconfig file.
2418360efbdSAlfred Perlstein  * getnetconfig() returns NULL at end of file.
2428360efbdSAlfred Perlstein  */
2438360efbdSAlfred Perlstein 
2448360efbdSAlfred Perlstein struct netconfig *
2458360efbdSAlfred Perlstein getnetconfig(handlep)
2468360efbdSAlfred Perlstein void *handlep;
2478360efbdSAlfred Perlstein {
2488360efbdSAlfred Perlstein     struct netconfig_vars *ncp = (struct netconfig_vars *)handlep;
2498360efbdSAlfred Perlstein     char *stringp;		/* tmp string pointer */
2508360efbdSAlfred Perlstein     struct netconfig_list	*list;
2518360efbdSAlfred Perlstein     struct netconfig *np;
2525f4faf74SXin LI     struct netconfig *result;
2538360efbdSAlfred Perlstein 
2548360efbdSAlfred Perlstein     /*
2558360efbdSAlfred Perlstein      * Verify that handle is valid
2568360efbdSAlfred Perlstein      */
2575f4faf74SXin LI     mutex_lock(&nc_file_lock);
2588360efbdSAlfred Perlstein     if (ncp == NULL || nc_file == NULL) {
2598360efbdSAlfred Perlstein 	nc_error = NC_NOTINIT;
2605f4faf74SXin LI 	mutex_unlock(&nc_file_lock);
2618360efbdSAlfred Perlstein 	return (NULL);
2628360efbdSAlfred Perlstein     }
2635f4faf74SXin LI     mutex_unlock(&nc_file_lock);
2648360efbdSAlfred Perlstein 
2658360efbdSAlfred Perlstein     switch (ncp->valid) {
2668360efbdSAlfred Perlstein     case NC_VALID:
2678360efbdSAlfred Perlstein 	/*
2688360efbdSAlfred Perlstein 	 * If entry has already been read into the list,
2698360efbdSAlfred Perlstein 	 * we return the entry in the linked list.
2708360efbdSAlfred Perlstein 	 * If this is the first time call, check if there are any entries in
2718360efbdSAlfred Perlstein 	 * linked list.  If no entries, we need to read the netconfig db.
2728360efbdSAlfred Perlstein 	 * If we have been here and the next entry is there, we just return
2738360efbdSAlfred Perlstein 	 * it.
2748360efbdSAlfred Perlstein 	 */
2758360efbdSAlfred Perlstein 	if (ncp->flag == 0) {	/* first time */
2768360efbdSAlfred Perlstein 	    ncp->flag = 1;
2775f4faf74SXin LI 	    mutex_lock(&ni_lock);
2788360efbdSAlfred Perlstein 	    ncp->nc_configs = ni.head;
2795f4faf74SXin LI 	    mutex_unlock(&ni_lock);
2808360efbdSAlfred Perlstein 	    if (ncp->nc_configs != NULL)	/* entry already exist */
2818360efbdSAlfred Perlstein 		return(ncp->nc_configs->ncp);
2828360efbdSAlfred Perlstein 	}
2838360efbdSAlfred Perlstein 	else if (ncp->nc_configs != NULL && ncp->nc_configs->next != NULL) {
2848360efbdSAlfred Perlstein 	    ncp->nc_configs = ncp->nc_configs->next;
2858360efbdSAlfred Perlstein 	    return(ncp->nc_configs->ncp);
2868360efbdSAlfred Perlstein 	}
2878360efbdSAlfred Perlstein 
2888360efbdSAlfred Perlstein 	/*
2898360efbdSAlfred Perlstein 	 * If we cannot find the entry in the list and is end of file,
2908360efbdSAlfred Perlstein 	 * we give up.
2918360efbdSAlfred Perlstein 	 */
2925f4faf74SXin LI 	mutex_lock(&ni_lock);
2935f4faf74SXin LI 	if (ni.eof == 1) {
2945f4faf74SXin LI 		mutex_unlock(&ni_lock);
2955f4faf74SXin LI 		return(NULL);
2965f4faf74SXin LI 	}
2975f4faf74SXin LI 	mutex_unlock(&ni_lock);
2985f4faf74SXin LI 
2998360efbdSAlfred Perlstein 	break;
3008360efbdSAlfred Perlstein     default:
3018360efbdSAlfred Perlstein 	nc_error = NC_NOTINIT;
3028360efbdSAlfred Perlstein 	return (NULL);
3038360efbdSAlfred Perlstein     }
3048360efbdSAlfred Perlstein 
3058360efbdSAlfred Perlstein     stringp = (char *) malloc(MAXNETCONFIGLINE);
3068360efbdSAlfred Perlstein     if (stringp == NULL)
3078360efbdSAlfred Perlstein     	return (NULL);
3088360efbdSAlfred Perlstein 
3098360efbdSAlfred Perlstein #ifdef MEM_CHK
3108360efbdSAlfred Perlstein     if (malloc_verify() == 0) {
3118360efbdSAlfred Perlstein 	fprintf(stderr, "memory heap corrupted in getnetconfig\n");
3128360efbdSAlfred Perlstein 	exit(1);
3138360efbdSAlfred Perlstein     }
3148360efbdSAlfred Perlstein #endif
3158360efbdSAlfred Perlstein 
3168360efbdSAlfred Perlstein     /*
3178360efbdSAlfred Perlstein      * Read a line from netconfig file.
3188360efbdSAlfred Perlstein      */
3195f4faf74SXin LI     mutex_lock(&nc_file_lock);
3208360efbdSAlfred Perlstein     do {
3218360efbdSAlfred Perlstein 	if (fgets(stringp, MAXNETCONFIGLINE, nc_file) == NULL) {
3228360efbdSAlfred Perlstein 	    free(stringp);
3235f4faf74SXin LI 	    mutex_lock(&ni_lock);
3248360efbdSAlfred Perlstein 	    ni.eof = 1;
3255f4faf74SXin LI 	    mutex_unlock(&ni_lock);
3265f4faf74SXin LI 	    mutex_unlock(&nc_file_lock);
3278360efbdSAlfred Perlstein 	    return (NULL);
3288360efbdSAlfred Perlstein         }
3298360efbdSAlfred Perlstein     } while (*stringp == '#');
3305f4faf74SXin LI     mutex_unlock(&nc_file_lock);
3318360efbdSAlfred Perlstein 
3328360efbdSAlfred Perlstein     list = (struct netconfig_list *) malloc(sizeof (struct netconfig_list));
3338360efbdSAlfred Perlstein     if (list == NULL) {
3348360efbdSAlfred Perlstein     	free(stringp);
3358360efbdSAlfred Perlstein     	return(NULL);
3368360efbdSAlfred Perlstein     }
3378360efbdSAlfred Perlstein     np = (struct netconfig *) malloc(sizeof (struct netconfig));
3388360efbdSAlfred Perlstein     if (np == NULL) {
3398360efbdSAlfred Perlstein     	free(stringp);
3408360efbdSAlfred Perlstein 	free(list);
3418360efbdSAlfred Perlstein     	return(NULL);
3428360efbdSAlfred Perlstein     }
3438360efbdSAlfred Perlstein     list->ncp = np;
3448360efbdSAlfred Perlstein     list->next = NULL;
3458360efbdSAlfred Perlstein     list->ncp->nc_lookups = NULL;
3468360efbdSAlfred Perlstein     list->linep = stringp;
3478360efbdSAlfred Perlstein     if (parse_ncp(stringp, list->ncp) == -1) {
3488360efbdSAlfred Perlstein 	free(stringp);
3498360efbdSAlfred Perlstein 	free(np);
3508360efbdSAlfred Perlstein 	free(list);
3518360efbdSAlfred Perlstein 	return (NULL);
3528360efbdSAlfred Perlstein     }
3538360efbdSAlfred Perlstein     else {
3548360efbdSAlfred Perlstein 	/*
3558360efbdSAlfred Perlstein 	 * If this is the first entry that's been read, it is the head of
3568360efbdSAlfred Perlstein 	 * the list.  If not, put the entry at the end of the list.
3578360efbdSAlfred Perlstein 	 * Reposition the current pointer of the handle to the last entry
3588360efbdSAlfred Perlstein 	 * in the list.
3598360efbdSAlfred Perlstein 	 */
3605f4faf74SXin LI 	mutex_lock(&ni_lock);
3618360efbdSAlfred Perlstein 	if (ni.head == NULL) {	/* first entry */
3628360efbdSAlfred Perlstein 	    ni.head = ni.tail = list;
3638360efbdSAlfred Perlstein 	}
3648360efbdSAlfred Perlstein     	else {
3658360efbdSAlfred Perlstein     	    ni.tail->next = list;
3668360efbdSAlfred Perlstein     	    ni.tail = ni.tail->next;
3678360efbdSAlfred Perlstein     	}
3688360efbdSAlfred Perlstein 	ncp->nc_configs = ni.tail;
3695f4faf74SXin LI 	result = ni.tail->ncp;
3705f4faf74SXin LI 	mutex_unlock(&ni_lock);
3715f4faf74SXin LI 	return(result);
3728360efbdSAlfred Perlstein     }
3738360efbdSAlfred Perlstein }
3748360efbdSAlfred Perlstein 
3758360efbdSAlfred Perlstein /*
3768360efbdSAlfred Perlstein  * endnetconfig() may be called to "unbind" or "close" the netconfig database
3778360efbdSAlfred Perlstein  * when processing is complete, releasing resources for reuse.  endnetconfig()
3788360efbdSAlfred Perlstein  * may not be called before setnetconfig().  endnetconfig() returns 0 on
3798360efbdSAlfred Perlstein  * success and -1 on failure (for example, if setnetconfig() was not called
3808360efbdSAlfred Perlstein  * previously).
3818360efbdSAlfred Perlstein  */
3828360efbdSAlfred Perlstein int
3838360efbdSAlfred Perlstein endnetconfig(handlep)
3848360efbdSAlfred Perlstein void *handlep;
3858360efbdSAlfred Perlstein {
3868360efbdSAlfred Perlstein     struct netconfig_vars *nc_handlep = (struct netconfig_vars *)handlep;
3878360efbdSAlfred Perlstein 
3888360efbdSAlfred Perlstein     struct netconfig_list *q, *p;
3898360efbdSAlfred Perlstein 
3908360efbdSAlfred Perlstein     /*
3918360efbdSAlfred Perlstein      * Verify that handle is valid
3928360efbdSAlfred Perlstein      */
3938360efbdSAlfred Perlstein     if (nc_handlep == NULL || (nc_handlep->valid != NC_VALID &&
3948360efbdSAlfred Perlstein 	    nc_handlep->valid != NC_STORAGE)) {
3958360efbdSAlfred Perlstein 	nc_error = NC_NOTINIT;
3968360efbdSAlfred Perlstein 	return (-1);
3978360efbdSAlfred Perlstein     }
3988360efbdSAlfred Perlstein 
3998360efbdSAlfred Perlstein     /*
4008360efbdSAlfred Perlstein      * Return 0 if anyone still needs it.
4018360efbdSAlfred Perlstein      */
4028360efbdSAlfred Perlstein     nc_handlep->valid = NC_INVALID;
4038360efbdSAlfred Perlstein     nc_handlep->flag = 0;
4048360efbdSAlfred Perlstein     nc_handlep->nc_configs = NULL;
4055f4faf74SXin LI     mutex_lock(&ni_lock);
4068360efbdSAlfred Perlstein     if (--ni.ref > 0) {
4075f4faf74SXin LI 	mutex_unlock(&ni_lock);
4088360efbdSAlfred Perlstein     	free(nc_handlep);
4098360efbdSAlfred Perlstein 	return(0);
4108360efbdSAlfred Perlstein     }
4118360efbdSAlfred Perlstein 
4128360efbdSAlfred Perlstein     /*
4138360efbdSAlfred Perlstein      * Noone needs these entries anymore, then frees them.
4148360efbdSAlfred Perlstein      * Make sure all info in netconfig_info structure has been reinitialized.
4158360efbdSAlfred Perlstein      */
4160c0349bfSGarrett Wollman     q = ni.head;
4178360efbdSAlfred Perlstein     ni.eof = ni.ref = 0;
4188360efbdSAlfred Perlstein     ni.head = NULL;
4198360efbdSAlfred Perlstein     ni.tail = NULL;
4205f4faf74SXin LI     mutex_unlock(&ni_lock);
4215f4faf74SXin LI 
4220c0349bfSGarrett Wollman     while (q != NULL) {
4238360efbdSAlfred Perlstein 	p = q->next;
4248360efbdSAlfred Perlstein 	if (q->ncp->nc_lookups != NULL) free(q->ncp->nc_lookups);
4258360efbdSAlfred Perlstein 	free(q->ncp);
4268360efbdSAlfred Perlstein 	free(q->linep);
4278360efbdSAlfred Perlstein 	free(q);
4288360efbdSAlfred Perlstein 	q = p;
4298360efbdSAlfred Perlstein     }
4308360efbdSAlfred Perlstein     free(nc_handlep);
4318360efbdSAlfred Perlstein 
4325f4faf74SXin LI     mutex_lock(&nc_file_lock);
4338360efbdSAlfred Perlstein     fclose(nc_file);
4348360efbdSAlfred Perlstein     nc_file = NULL;
4355f4faf74SXin LI     mutex_unlock(&nc_file_lock);
4365f4faf74SXin LI 
4378360efbdSAlfred Perlstein     return (0);
4388360efbdSAlfred Perlstein }
4398360efbdSAlfred Perlstein 
4408360efbdSAlfred Perlstein /*
4418360efbdSAlfred Perlstein  * getnetconfigent(netid) returns a pointer to the struct netconfig structure
4428360efbdSAlfred Perlstein  * corresponding to netid.  It returns NULL if netid is invalid (that is, does
4438360efbdSAlfred Perlstein  * not name an entry in the netconfig database).  It returns NULL and sets
4448360efbdSAlfred Perlstein  * errno in case of failure (for example, if the netconfig database cannot be
4458360efbdSAlfred Perlstein  * opened).
4468360efbdSAlfred Perlstein  */
4478360efbdSAlfred Perlstein 
4488360efbdSAlfred Perlstein struct netconfig *
4498360efbdSAlfred Perlstein getnetconfigent(netid)
45040c10ffdSAlfred Perlstein 	const char *netid;
4518360efbdSAlfred Perlstein {
4528360efbdSAlfred Perlstein     FILE *file;		/* NETCONFIG db's file pointer */
4538360efbdSAlfred Perlstein     char *linep;	/* holds current netconfig line */
4548360efbdSAlfred Perlstein     char *stringp;	/* temporary string pointer */
4558360efbdSAlfred Perlstein     struct netconfig *ncp = NULL;   /* returned value */
4568360efbdSAlfred Perlstein     struct netconfig_list *list;	/* pointer to cache list */
4578360efbdSAlfred Perlstein 
458b3a38fe3SIan Dowse     nc_error = NC_NOTFOUND;	/* default error. */
4598360efbdSAlfred Perlstein     if (netid == NULL || strlen(netid) == 0) {
4608360efbdSAlfred Perlstein 	return (NULL);
4618360efbdSAlfred Perlstein     }
4628360efbdSAlfred Perlstein 
4638360efbdSAlfred Perlstein     /*
4648360efbdSAlfred Perlstein      * Look up table if the entries have already been read and parsed in
4658360efbdSAlfred Perlstein      * getnetconfig(), then copy this entry into a buffer and return it.
4668360efbdSAlfred Perlstein      * If we cannot find the entry in the current list and there are more
4678360efbdSAlfred Perlstein      * entries in the netconfig db that has not been read, we then read the
4688360efbdSAlfred Perlstein      * db and try find the match netid.
4698360efbdSAlfred Perlstein      * If all the netconfig db has been read and placed into the list and
4708360efbdSAlfred Perlstein      * there is no match for the netid, return NULL.
4718360efbdSAlfred Perlstein      */
4725f4faf74SXin LI     mutex_lock(&ni_lock);
4738360efbdSAlfred Perlstein     if (ni.head != NULL) {
4748360efbdSAlfred Perlstein 	for (list = ni.head; list; list = list->next) {
4758360efbdSAlfred Perlstein 	    if (strcmp(list->ncp->nc_netid, netid) == 0) {
4765f4faf74SXin LI 		mutex_unlock(&ni_lock);
4778360efbdSAlfred Perlstein 	        return(dup_ncp(list->ncp));
4788360efbdSAlfred Perlstein 	    }
4798360efbdSAlfred Perlstein 	}
4805f4faf74SXin LI 	if (ni.eof == 1) {	/* that's all the entries */
4815f4faf74SXin LI 		mutex_unlock(&ni_lock);
4828360efbdSAlfred Perlstein 		return(NULL);
4838360efbdSAlfred Perlstein 	}
4845f4faf74SXin LI     }
4855f4faf74SXin LI     mutex_unlock(&ni_lock);
4868360efbdSAlfred Perlstein 
4878360efbdSAlfred Perlstein 
4888360efbdSAlfred Perlstein     if ((file = fopen(NETCONFIG, "r")) == NULL) {
489b3a38fe3SIan Dowse 	nc_error = NC_NONETCONFIG;
4908360efbdSAlfred Perlstein 	return (NULL);
4918360efbdSAlfred Perlstein     }
4928360efbdSAlfred Perlstein 
4938360efbdSAlfred Perlstein     if ((linep = malloc(MAXNETCONFIGLINE)) == NULL) {
4948360efbdSAlfred Perlstein 	fclose(file);
495b3a38fe3SIan Dowse 	nc_error = NC_NOMEM;
4968360efbdSAlfred Perlstein 	return (NULL);
4978360efbdSAlfred Perlstein     }
4988360efbdSAlfred Perlstein     do {
4993c788545SMartin Blapp 	ptrdiff_t len;
5008360efbdSAlfred Perlstein 	char *tmpp;	/* tmp string pointer */
5018360efbdSAlfred Perlstein 
5028360efbdSAlfred Perlstein 	do {
5038360efbdSAlfred Perlstein 	    if ((stringp = fgets(linep, MAXNETCONFIGLINE, file)) == NULL) {
5048360efbdSAlfred Perlstein 		break;
5058360efbdSAlfred Perlstein 	    }
5068360efbdSAlfred Perlstein 	} while (*stringp == '#');
5078360efbdSAlfred Perlstein 	if (stringp == NULL) {	    /* eof */
5088360efbdSAlfred Perlstein 	    break;
5098360efbdSAlfred Perlstein 	}
5108360efbdSAlfred Perlstein 	if ((tmpp = strpbrk(stringp, "\t ")) == NULL) {	/* can't parse file */
5118360efbdSAlfred Perlstein 	    nc_error = NC_BADFILE;
5128360efbdSAlfred Perlstein 	    break;
5138360efbdSAlfred Perlstein 	}
5143c788545SMartin Blapp 	if (strlen(netid) == (size_t) (len = tmpp - stringp) &&	/* a match */
5158360efbdSAlfred Perlstein 		strncmp(stringp, netid, (size_t)len) == 0) {
5168360efbdSAlfred Perlstein 	    if ((ncp = (struct netconfig *)
5178360efbdSAlfred Perlstein 		    malloc(sizeof (struct netconfig))) == NULL) {
5188360efbdSAlfred Perlstein 		break;
5198360efbdSAlfred Perlstein 	    }
5208360efbdSAlfred Perlstein 	    ncp->nc_lookups = NULL;
5218360efbdSAlfred Perlstein 	    if (parse_ncp(linep, ncp) == -1) {
5228360efbdSAlfred Perlstein 		free(ncp);
5238360efbdSAlfred Perlstein 		ncp = NULL;
5248360efbdSAlfred Perlstein 	    }
5258360efbdSAlfred Perlstein 	    break;
5268360efbdSAlfred Perlstein 	}
5278360efbdSAlfred Perlstein     } while (stringp != NULL);
5288360efbdSAlfred Perlstein     if (ncp == NULL) {
5298360efbdSAlfred Perlstein 	free(linep);
5308360efbdSAlfred Perlstein     }
5318360efbdSAlfred Perlstein     fclose(file);
5328360efbdSAlfred Perlstein     return(ncp);
5338360efbdSAlfred Perlstein }
5348360efbdSAlfred Perlstein 
5358360efbdSAlfred Perlstein /*
5368360efbdSAlfred Perlstein  * freenetconfigent(netconfigp) frees the netconfig structure pointed to by
5378360efbdSAlfred Perlstein  * netconfigp (previously returned by getnetconfigent()).
5388360efbdSAlfred Perlstein  */
5398360efbdSAlfred Perlstein 
5408360efbdSAlfred Perlstein void
5418360efbdSAlfred Perlstein freenetconfigent(netconfigp)
5428360efbdSAlfred Perlstein 	struct netconfig *netconfigp;
5438360efbdSAlfred Perlstein {
5448360efbdSAlfred Perlstein     if (netconfigp != NULL) {
5458360efbdSAlfred Perlstein 	free(netconfigp->nc_netid);	/* holds all netconfigp's strings */
5468360efbdSAlfred Perlstein 	if (netconfigp->nc_lookups != NULL)
5478360efbdSAlfred Perlstein 	    free(netconfigp->nc_lookups);
5488360efbdSAlfred Perlstein 	free(netconfigp);
5498360efbdSAlfred Perlstein     }
5508360efbdSAlfred Perlstein     return;
5518360efbdSAlfred Perlstein }
5528360efbdSAlfred Perlstein 
5538360efbdSAlfred Perlstein /*
5548360efbdSAlfred Perlstein  * Parse line and stuff it in a struct netconfig
5558360efbdSAlfred Perlstein  * Typical line might look like:
5568360efbdSAlfred Perlstein  *	udp tpi_cots vb inet udp /dev/udp /usr/lib/ip.so,/usr/local/ip.so
5578360efbdSAlfred Perlstein  *
5588360efbdSAlfred Perlstein  * We return -1 if any of the tokens don't parse, or malloc fails.
5598360efbdSAlfred Perlstein  *
5608360efbdSAlfred Perlstein  * Note that we modify stringp (putting NULLs after tokens) and
5618360efbdSAlfred Perlstein  * we set the ncp's string field pointers to point to these tokens within
5628360efbdSAlfred Perlstein  * stringp.
5638360efbdSAlfred Perlstein  */
5648360efbdSAlfred Perlstein 
5658360efbdSAlfred Perlstein static int
5668360efbdSAlfred Perlstein parse_ncp(stringp, ncp)
5678360efbdSAlfred Perlstein char *stringp;		/* string to parse */
5688360efbdSAlfred Perlstein struct netconfig *ncp;	/* where to put results */
5698360efbdSAlfred Perlstein {
5708360efbdSAlfred Perlstein     char    *tokenp;	/* for processing tokens */
5718360efbdSAlfred Perlstein     char    *lasts;
572330e445cSMatteo Riondato     char    **nc_lookups;
5738360efbdSAlfred Perlstein 
5748360efbdSAlfred Perlstein     nc_error = NC_BADFILE;	/* nearly anything that breaks is for this reason */
5758360efbdSAlfred Perlstein     stringp[strlen(stringp)-1] = '\0';	/* get rid of newline */
5768360efbdSAlfred Perlstein     /* netid */
5778360efbdSAlfred Perlstein     if ((ncp->nc_netid = strtok_r(stringp, "\t ", &lasts)) == NULL) {
5788360efbdSAlfred Perlstein 	return (-1);
5798360efbdSAlfred Perlstein     }
5808360efbdSAlfred Perlstein 
5818360efbdSAlfred Perlstein     /* semantics */
5828360efbdSAlfred Perlstein     if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) {
5838360efbdSAlfred Perlstein 	return (-1);
5848360efbdSAlfred Perlstein     }
5858360efbdSAlfred Perlstein     if (strcmp(tokenp, NC_TPI_COTS_ORD_S) == 0)
5868360efbdSAlfred Perlstein 	ncp->nc_semantics = NC_TPI_COTS_ORD;
5878360efbdSAlfred Perlstein     else if (strcmp(tokenp, NC_TPI_COTS_S) == 0)
5888360efbdSAlfred Perlstein 	ncp->nc_semantics = NC_TPI_COTS;
5898360efbdSAlfred Perlstein     else if (strcmp(tokenp, NC_TPI_CLTS_S) == 0)
5908360efbdSAlfred Perlstein 	ncp->nc_semantics = NC_TPI_CLTS;
5918360efbdSAlfred Perlstein     else if (strcmp(tokenp, NC_TPI_RAW_S) == 0)
5928360efbdSAlfred Perlstein 	ncp->nc_semantics = NC_TPI_RAW;
5938360efbdSAlfred Perlstein     else
5948360efbdSAlfred Perlstein 	return (-1);
5958360efbdSAlfred Perlstein 
5968360efbdSAlfred Perlstein     /* flags */
5978360efbdSAlfred Perlstein     if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) {
5988360efbdSAlfred Perlstein 	return (-1);
5998360efbdSAlfred Perlstein     }
6008360efbdSAlfred Perlstein     for (ncp->nc_flag = NC_NOFLAG; *tokenp != '\0';
6018360efbdSAlfred Perlstein 	    tokenp++) {
6028360efbdSAlfred Perlstein 	switch (*tokenp) {
6038360efbdSAlfred Perlstein 	case NC_NOFLAG_C:
6048360efbdSAlfred Perlstein 	    break;
6058360efbdSAlfred Perlstein 	case NC_VISIBLE_C:
6068360efbdSAlfred Perlstein 	    ncp->nc_flag |= NC_VISIBLE;
6078360efbdSAlfred Perlstein 	    break;
6088360efbdSAlfred Perlstein 	case NC_BROADCAST_C:
6098360efbdSAlfred Perlstein 	    ncp->nc_flag |= NC_BROADCAST;
6108360efbdSAlfred Perlstein 	    break;
6118360efbdSAlfred Perlstein 	default:
6128360efbdSAlfred Perlstein 	    return (-1);
6138360efbdSAlfred Perlstein 	}
6148360efbdSAlfred Perlstein     }
6158360efbdSAlfred Perlstein     /* protocol family */
6168360efbdSAlfred Perlstein     if ((ncp->nc_protofmly = strtok_r(NULL, "\t ", &lasts)) == NULL) {
6178360efbdSAlfred Perlstein 	return (-1);
6188360efbdSAlfred Perlstein     }
6198360efbdSAlfred Perlstein     /* protocol name */
6208360efbdSAlfred Perlstein     if ((ncp->nc_proto = strtok_r(NULL, "\t ", &lasts)) == NULL) {
6218360efbdSAlfred Perlstein 	return (-1);
6228360efbdSAlfred Perlstein     }
6238360efbdSAlfred Perlstein     /* network device */
6248360efbdSAlfred Perlstein     if ((ncp->nc_device = strtok_r(NULL, "\t ", &lasts)) == NULL) {
6258360efbdSAlfred Perlstein 	return (-1);
6268360efbdSAlfred Perlstein     }
6278360efbdSAlfred Perlstein     if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) {
6288360efbdSAlfred Perlstein 	return (-1);
6298360efbdSAlfred Perlstein     }
6308360efbdSAlfred Perlstein     if (strcmp(tokenp, NC_NOLOOKUP) == 0) {
6318360efbdSAlfred Perlstein 	ncp->nc_nlookups = 0;
6328360efbdSAlfred Perlstein 	ncp->nc_lookups = NULL;
6338360efbdSAlfred Perlstein     } else {
6348360efbdSAlfred Perlstein 	char *cp;	    /* tmp string */
6358360efbdSAlfred Perlstein 
6368360efbdSAlfred Perlstein 	if (ncp->nc_lookups != NULL)	/* from last visit */
6378360efbdSAlfred Perlstein 	    free(ncp->nc_lookups);
638330e445cSMatteo Riondato 	ncp->nc_lookups = NULL;
6398360efbdSAlfred Perlstein 	ncp->nc_nlookups = 0;
6408360efbdSAlfred Perlstein 	while ((cp = tokenp) != NULL) {
641330e445cSMatteo Riondato 	    if ((nc_lookups = realloc(ncp->nc_lookups,
642330e445cSMatteo Riondato 		(ncp->nc_nlookups + 1) * sizeof *ncp->nc_lookups)) == NULL) {
643330e445cSMatteo Riondato 		    free(ncp->nc_lookups);
644330e445cSMatteo Riondato 		    ncp->nc_lookups = NULL;
645330e445cSMatteo Riondato 		    return (-1);
646330e445cSMatteo Riondato 	    }
6478360efbdSAlfred Perlstein 	    tokenp = _get_next_token(cp, ',');
648330e445cSMatteo Riondato 	    ncp->nc_lookups = nc_lookups;
649330e445cSMatteo Riondato 	    ncp->nc_lookups[ncp->nc_nlookups++] = cp;
6508360efbdSAlfred Perlstein 	}
6518360efbdSAlfred Perlstein     }
6528360efbdSAlfred Perlstein     return (0);
6538360efbdSAlfred Perlstein }
6548360efbdSAlfred Perlstein 
6558360efbdSAlfred Perlstein 
6568360efbdSAlfred Perlstein /*
6578360efbdSAlfred Perlstein  * Returns a string describing the reason for failure.
6588360efbdSAlfred Perlstein  */
6598360efbdSAlfred Perlstein char *
6608360efbdSAlfred Perlstein nc_sperror()
6618360efbdSAlfred Perlstein {
6628360efbdSAlfred Perlstein     const char *message;
6638360efbdSAlfred Perlstein 
6648360efbdSAlfred Perlstein     switch(nc_error) {
6658360efbdSAlfred Perlstein     case NC_NONETCONFIG:
6668360efbdSAlfred Perlstein 	message = _nc_errors[0];
6678360efbdSAlfred Perlstein 	break;
6688360efbdSAlfred Perlstein     case NC_NOMEM:
6698360efbdSAlfred Perlstein 	message = _nc_errors[1];
6708360efbdSAlfred Perlstein 	break;
6718360efbdSAlfred Perlstein     case NC_NOTINIT:
6728360efbdSAlfred Perlstein 	message = _nc_errors[2];
6738360efbdSAlfred Perlstein 	break;
6748360efbdSAlfred Perlstein     case NC_BADFILE:
6758360efbdSAlfred Perlstein 	message = _nc_errors[3];
6768360efbdSAlfred Perlstein 	break;
677b3a38fe3SIan Dowse     case NC_NOTFOUND:
678b3a38fe3SIan Dowse 	message = _nc_errors[4];
679b3a38fe3SIan Dowse 	break;
6808360efbdSAlfred Perlstein     default:
6818360efbdSAlfred Perlstein 	message = "Unknown network selection error";
6828360efbdSAlfred Perlstein     }
6838360efbdSAlfred Perlstein     /* LINTED const castaway */
6848360efbdSAlfred Perlstein     return ((char *)message);
6858360efbdSAlfred Perlstein }
6868360efbdSAlfred Perlstein 
6878360efbdSAlfred Perlstein /*
6888360efbdSAlfred Perlstein  * Prints a message onto standard error describing the reason for failure.
6898360efbdSAlfred Perlstein  */
6908360efbdSAlfred Perlstein void
6918360efbdSAlfred Perlstein nc_perror(s)
6928360efbdSAlfred Perlstein 	const char *s;
6938360efbdSAlfred Perlstein {
694b3a38fe3SIan Dowse     fprintf(stderr, "%s: %s\n", s, nc_sperror());
6958360efbdSAlfred Perlstein }
6968360efbdSAlfred Perlstein 
6978360efbdSAlfred Perlstein /*
6988360efbdSAlfred Perlstein  * Duplicates the matched netconfig buffer.
6998360efbdSAlfred Perlstein  */
7008360efbdSAlfred Perlstein static struct netconfig *
7018360efbdSAlfred Perlstein dup_ncp(ncp)
7028360efbdSAlfred Perlstein struct netconfig	*ncp;
7038360efbdSAlfred Perlstein {
7048360efbdSAlfred Perlstein     struct netconfig	*p;
7058360efbdSAlfred Perlstein     char	*tmp;
7063c788545SMartin Blapp     u_int	i;
7078360efbdSAlfred Perlstein 
7088360efbdSAlfred Perlstein     if ((tmp=malloc(MAXNETCONFIGLINE)) == NULL)
7098360efbdSAlfred Perlstein 	return(NULL);
7108360efbdSAlfred Perlstein     if ((p=(struct netconfig *)malloc(sizeof(struct netconfig))) == NULL) {
7118360efbdSAlfred Perlstein 	free(tmp);
7128360efbdSAlfred Perlstein 	return(NULL);
7138360efbdSAlfred Perlstein     }
7148360efbdSAlfred Perlstein     /*
7158360efbdSAlfred Perlstein      * First we dup all the data from matched netconfig buffer.  Then we
7168360efbdSAlfred Perlstein      * adjust some of the member pointer to a pre-allocated buffer where
7178360efbdSAlfred Perlstein      * contains part of the data.
7188360efbdSAlfred Perlstein      * To follow the convention used in parse_ncp(), we store all the
7193c788545SMartin Blapp      * necessary information in the pre-allocated buffer and let each
7208360efbdSAlfred Perlstein      * of the netconfig char pointer member point to the right address
7218360efbdSAlfred Perlstein      * in the buffer.
7228360efbdSAlfred Perlstein      */
7238360efbdSAlfred Perlstein     *p = *ncp;
7248360efbdSAlfred Perlstein     p->nc_netid = (char *)strcpy(tmp,ncp->nc_netid);
72516fc3635SMark Murray     tmp = strchr(tmp, '\0') + 1;
7268360efbdSAlfred Perlstein     p->nc_protofmly = (char *)strcpy(tmp,ncp->nc_protofmly);
72716fc3635SMark Murray     tmp = strchr(tmp, '\0') + 1;
7288360efbdSAlfred Perlstein     p->nc_proto = (char *)strcpy(tmp,ncp->nc_proto);
72916fc3635SMark Murray     tmp = strchr(tmp, '\0') + 1;
7308360efbdSAlfred Perlstein     p->nc_device = (char *)strcpy(tmp,ncp->nc_device);
7318360efbdSAlfred Perlstein     p->nc_lookups = (char **)malloc((size_t)(p->nc_nlookups+1) * sizeof(char *));
7328360efbdSAlfred Perlstein     if (p->nc_lookups == NULL) {
7338360efbdSAlfred Perlstein 	free(p->nc_netid);
734b0718451SMartin Blapp 	free(p);
7358360efbdSAlfred Perlstein 	return(NULL);
7368360efbdSAlfred Perlstein     }
7378360efbdSAlfred Perlstein     for (i=0; i < p->nc_nlookups; i++) {
73816fc3635SMark Murray     	tmp = strchr(tmp, '\0') + 1;
7398360efbdSAlfred Perlstein     	p->nc_lookups[i] = (char *)strcpy(tmp,ncp->nc_lookups[i]);
7408360efbdSAlfred Perlstein     }
7418360efbdSAlfred Perlstein     return(p);
7428360efbdSAlfred Perlstein }
743