xref: /freebsd/lib/libc/rpc/getnetconfig.c (revision 2e322d379631c3bd6107e295f3e5d814c7845fc7)
18360efbdSAlfred Perlstein /*	$NetBSD: getnetconfig.c,v 1.3 2000/07/06 03:10:34 christos Exp $	*/
28360efbdSAlfred Perlstein 
3*2e322d37SHiroki Sato /*-
4*2e322d37SHiroki Sato  * Copyright (c) 2009, Sun Microsystems, Inc.
5*2e322d37SHiroki Sato  * All rights reserved.
68360efbdSAlfred Perlstein  *
7*2e322d37SHiroki Sato  * Redistribution and use in source and binary forms, with or without
8*2e322d37SHiroki Sato  * modification, are permitted provided that the following conditions are met:
9*2e322d37SHiroki Sato  * - Redistributions of source code must retain the above copyright notice,
10*2e322d37SHiroki Sato  *   this list of conditions and the following disclaimer.
11*2e322d37SHiroki Sato  * - Redistributions in binary form must reproduce the above copyright notice,
12*2e322d37SHiroki Sato  *   this list of conditions and the following disclaimer in the documentation
13*2e322d37SHiroki Sato  *   and/or other materials provided with the distribution.
14*2e322d37SHiroki Sato  * - Neither the name of Sun Microsystems, Inc. nor the names of its
15*2e322d37SHiroki Sato  *   contributors may be used to endorse or promote products derived
16*2e322d37SHiroki Sato  *   from this software without specific prior written permission.
178360efbdSAlfred Perlstein  *
18*2e322d37SHiroki Sato  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19*2e322d37SHiroki Sato  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20*2e322d37SHiroki Sato  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21*2e322d37SHiroki Sato  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22*2e322d37SHiroki Sato  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23*2e322d37SHiroki Sato  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24*2e322d37SHiroki Sato  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25*2e322d37SHiroki Sato  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26*2e322d37SHiroki Sato  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27*2e322d37SHiroki Sato  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28*2e322d37SHiroki Sato  * POSSIBILITY OF SUCH DAMAGE.
298360efbdSAlfred Perlstein  */
30a986ef57SDavid E. O'Brien 
31a986ef57SDavid E. O'Brien #if defined(LIBC_SCCS) && !defined(lint)
328360efbdSAlfred Perlstein static char sccsid[] = "@(#)getnetconfig.c	1.12 91/12/19 SMI";
338360efbdSAlfred Perlstein #endif
34d3d20c82SDavid E. O'Brien #include <sys/cdefs.h>
35d3d20c82SDavid E. O'Brien __FBSDID("$FreeBSD$");
368360efbdSAlfred Perlstein 
378360efbdSAlfred Perlstein /*
388360efbdSAlfred Perlstein  * Copyright (c) 1989 by Sun Microsystems, Inc.
398360efbdSAlfred Perlstein  */
408360efbdSAlfred Perlstein 
418360efbdSAlfred Perlstein #include "namespace.h"
429f5afc13SIan Dowse #include "reentrant.h"
438360efbdSAlfred Perlstein #include <stdio.h>
448360efbdSAlfred Perlstein #include <errno.h>
458360efbdSAlfred Perlstein #include <netconfig.h>
463c788545SMartin Blapp #include <stddef.h>
478360efbdSAlfred Perlstein #include <stdlib.h>
488360efbdSAlfred Perlstein #include <string.h>
498360efbdSAlfred Perlstein #include <rpc/rpc.h>
50e0554a53SJacques Vidrine #include <unistd.h>
518360efbdSAlfred Perlstein #include "un-namespace.h"
528360efbdSAlfred Perlstein #include "rpc_com.h"
538360efbdSAlfred Perlstein 
548360efbdSAlfred Perlstein /*
558360efbdSAlfred Perlstein  * The five library routines in this file provide application access to the
568360efbdSAlfred Perlstein  * system network configuration database, /etc/netconfig.  In addition to the
578360efbdSAlfred Perlstein  * netconfig database and the routines for accessing it, the environment
588360efbdSAlfred Perlstein  * variable NETPATH and its corresponding routines in getnetpath.c may also be
598360efbdSAlfred Perlstein  * used to specify the network transport to be used.
608360efbdSAlfred Perlstein  */
618360efbdSAlfred Perlstein 
628360efbdSAlfred Perlstein 
638360efbdSAlfred Perlstein /*
648360efbdSAlfred Perlstein  * netconfig errors
658360efbdSAlfred Perlstein  */
668360efbdSAlfred Perlstein 
678360efbdSAlfred Perlstein #define NC_NONETCONFIG	ENOENT
688360efbdSAlfred Perlstein #define NC_NOMEM	ENOMEM
698360efbdSAlfred Perlstein #define NC_NOTINIT	EINVAL	    /* setnetconfig was not called first */
708360efbdSAlfred Perlstein #define NC_BADFILE	EBADF	    /* format for netconfig file is bad */
71b3a38fe3SIan Dowse #define NC_NOTFOUND	ENOPROTOOPT /* specified netid was not found */
728360efbdSAlfred Perlstein 
738360efbdSAlfred Perlstein /*
748360efbdSAlfred Perlstein  * semantics as strings (should be in netconfig.h)
758360efbdSAlfred Perlstein  */
768360efbdSAlfred Perlstein #define NC_TPI_CLTS_S	    "tpi_clts"
778360efbdSAlfred Perlstein #define	NC_TPI_COTS_S	    "tpi_cots"
788360efbdSAlfred Perlstein #define	NC_TPI_COTS_ORD_S   "tpi_cots_ord"
798360efbdSAlfred Perlstein #define	NC_TPI_RAW_S        "tpi_raw"
808360efbdSAlfred Perlstein 
818360efbdSAlfred Perlstein /*
828360efbdSAlfred Perlstein  * flags as characters (also should be in netconfig.h)
838360efbdSAlfred Perlstein  */
848360efbdSAlfred Perlstein #define	NC_NOFLAG_C	'-'
858360efbdSAlfred Perlstein #define	NC_VISIBLE_C	'v'
868360efbdSAlfred Perlstein #define	NC_BROADCAST_C	'b'
878360efbdSAlfred Perlstein 
888360efbdSAlfred Perlstein /*
898360efbdSAlfred Perlstein  * Character used to indicate there is no name-to-address lookup library
908360efbdSAlfred Perlstein  */
918360efbdSAlfred Perlstein #define NC_NOLOOKUP	"-"
928360efbdSAlfred Perlstein 
938360efbdSAlfred Perlstein static const char * const _nc_errors[] = {
948360efbdSAlfred Perlstein     "Netconfig database not found",
958360efbdSAlfred Perlstein     "Not enough memory",
968360efbdSAlfred Perlstein     "Not initialized",
97b3a38fe3SIan Dowse     "Netconfig database has invalid format",
98b3a38fe3SIan Dowse     "Netid not found in netconfig database"
998360efbdSAlfred Perlstein };
1008360efbdSAlfred Perlstein 
1018360efbdSAlfred Perlstein struct netconfig_info {
1028360efbdSAlfred Perlstein     int		eof;	/* all entries has been read */
1038360efbdSAlfred Perlstein     int		ref;	/* # of times setnetconfig() has been called */
1048360efbdSAlfred Perlstein     struct netconfig_list	*head;	/* head of the list */
1058360efbdSAlfred Perlstein     struct netconfig_list	*tail;	/* last of the list */
1068360efbdSAlfred Perlstein };
1078360efbdSAlfred Perlstein 
1088360efbdSAlfred Perlstein struct netconfig_list {
1098360efbdSAlfred Perlstein     char			*linep;	/* hold line read from netconfig */
1108360efbdSAlfred Perlstein     struct netconfig		*ncp;
1118360efbdSAlfred Perlstein     struct netconfig_list	*next;
1128360efbdSAlfred Perlstein };
1138360efbdSAlfred Perlstein 
1148360efbdSAlfred Perlstein struct netconfig_vars {
1158360efbdSAlfred Perlstein     int   valid;	/* token that indicates a valid netconfig_vars */
1168360efbdSAlfred Perlstein     int   flag;		/* first time flag */
1178360efbdSAlfred Perlstein     struct netconfig_list *nc_configs;  /* pointer to the current netconfig entry */
1188360efbdSAlfred Perlstein };
1198360efbdSAlfred Perlstein 
1208360efbdSAlfred Perlstein #define NC_VALID	0xfeed
1218360efbdSAlfred Perlstein #define NC_STORAGE	0xf00d
1228360efbdSAlfred Perlstein #define NC_INVALID	0
1238360efbdSAlfred Perlstein 
1248360efbdSAlfred Perlstein 
125c05ac53bSDavid E. O'Brien static int *__nc_error(void);
126c05ac53bSDavid E. O'Brien static int parse_ncp(char *, struct netconfig *);
127c05ac53bSDavid E. O'Brien static struct netconfig *dup_ncp(struct netconfig *);
1288360efbdSAlfred Perlstein 
1298360efbdSAlfred Perlstein 
1308360efbdSAlfred Perlstein static FILE *nc_file;		/* for netconfig db */
1316f88d2a8SJohn Baldwin static mutex_t nc_file_lock = MUTEX_INITIALIZER;
1325f4faf74SXin LI 
1338360efbdSAlfred Perlstein static struct netconfig_info	ni = { 0, 0, NULL, NULL};
1346f88d2a8SJohn Baldwin static mutex_t ni_lock = MUTEX_INITIALIZER;
1355f4faf74SXin LI 
1366f88d2a8SJohn Baldwin static thread_key_t nc_key;
1376f88d2a8SJohn Baldwin static once_t nc_once = ONCE_INITIALIZER;
1386f88d2a8SJohn Baldwin static int nc_key_error;
1396f88d2a8SJohn Baldwin 
1406f88d2a8SJohn Baldwin static void
1416f88d2a8SJohn Baldwin nc_key_init(void)
1426f88d2a8SJohn Baldwin {
1436f88d2a8SJohn Baldwin 
1446f88d2a8SJohn Baldwin 	nc_key_error = thr_keycreate(&nc_key, free);
1456f88d2a8SJohn Baldwin }
1468360efbdSAlfred Perlstein 
1478360efbdSAlfred Perlstein #define MAXNETCONFIGLINE    1000
1488360efbdSAlfred Perlstein 
1498360efbdSAlfred Perlstein static int *
1508360efbdSAlfred Perlstein __nc_error()
1518360efbdSAlfred Perlstein {
1528360efbdSAlfred Perlstein 	static int nc_error = 0;
1536f88d2a8SJohn Baldwin 	int *nc_addr;
1548360efbdSAlfred Perlstein 
155b3a38fe3SIan Dowse 	/*
156b3a38fe3SIan Dowse 	 * Use the static `nc_error' if we are the main thread
157b3a38fe3SIan Dowse 	 * (including non-threaded programs), or if an allocation
158b3a38fe3SIan Dowse 	 * fails.
159b3a38fe3SIan Dowse 	 */
160b3a38fe3SIan Dowse 	if (thr_main())
161b3a38fe3SIan Dowse 		return (&nc_error);
1626f88d2a8SJohn Baldwin 	if (thr_once(&nc_once, nc_key_init) != 0 || nc_key_error != 0)
163b3a38fe3SIan Dowse 		return (&nc_error);
164b3a38fe3SIan Dowse 	if ((nc_addr = (int *)thr_getspecific(nc_key)) == NULL) {
1658360efbdSAlfred Perlstein 		nc_addr = (int *)malloc(sizeof (int));
1668360efbdSAlfred Perlstein 		if (thr_setspecific(nc_key, (void *) nc_addr) != 0) {
1678360efbdSAlfred Perlstein 			if (nc_addr)
1688360efbdSAlfred Perlstein 				free(nc_addr);
169b3a38fe3SIan Dowse 			return (&nc_error);
1708360efbdSAlfred Perlstein 		}
1718360efbdSAlfred Perlstein 		*nc_addr = 0;
1728360efbdSAlfred Perlstein 	}
173b3a38fe3SIan Dowse 	return (nc_addr);
1748360efbdSAlfred Perlstein }
1758360efbdSAlfred Perlstein 
1768360efbdSAlfred Perlstein #define nc_error        (*(__nc_error()))
1778360efbdSAlfred Perlstein /*
1788360efbdSAlfred Perlstein  * A call to setnetconfig() establishes a /etc/netconfig "session".  A session
1798360efbdSAlfred Perlstein  * "handle" is returned on a successful call.  At the start of a session (after
1808360efbdSAlfred Perlstein  * a call to setnetconfig()) searches through the /etc/netconfig database will
1818360efbdSAlfred Perlstein  * proceed from the start of the file.  The session handle must be passed to
1828360efbdSAlfred Perlstein  * getnetconfig() to parse the file.  Each call to getnetconfig() using the
1838360efbdSAlfred Perlstein  * current handle will process one subsequent entry in /etc/netconfig.
1848360efbdSAlfred Perlstein  * setnetconfig() must be called before the first call to getnetconfig().
1858360efbdSAlfred Perlstein  * (Handles are used to allow for nested calls to setnetpath()).
1868360efbdSAlfred Perlstein  *
1878360efbdSAlfred Perlstein  * A new session is established with each call to setnetconfig(), with a new
1888360efbdSAlfred Perlstein  * handle being returned on each call.  Previously established sessions remain
1898360efbdSAlfred Perlstein  * active until endnetconfig() is called with that session's handle as an
1908360efbdSAlfred Perlstein  * argument.
1918360efbdSAlfred Perlstein  *
1928360efbdSAlfred Perlstein  * setnetconfig() need *not* be called before a call to getnetconfigent().
1938360efbdSAlfred Perlstein  * setnetconfig() returns a NULL pointer on failure (for example, if
1948360efbdSAlfred Perlstein  * the netconfig database is not present).
1958360efbdSAlfred Perlstein  */
1968360efbdSAlfred Perlstein void *
1978360efbdSAlfred Perlstein setnetconfig()
1988360efbdSAlfred Perlstein {
1998360efbdSAlfred Perlstein     struct netconfig_vars *nc_vars;
2008360efbdSAlfred Perlstein 
2018360efbdSAlfred Perlstein     if ((nc_vars = (struct netconfig_vars *)malloc(sizeof
2028360efbdSAlfred Perlstein 		(struct netconfig_vars))) == NULL) {
2038360efbdSAlfred Perlstein 	return(NULL);
2048360efbdSAlfred Perlstein     }
2058360efbdSAlfred Perlstein 
2068360efbdSAlfred Perlstein     /*
2078360efbdSAlfred Perlstein      * For multiple calls, i.e. nc_file is not NULL, we just return the
2088360efbdSAlfred Perlstein      * handle without reopening the netconfig db.
2098360efbdSAlfred Perlstein      */
2105f4faf74SXin LI     mutex_lock(&ni_lock);
2118360efbdSAlfred Perlstein     ni.ref++;
2125f4faf74SXin LI     mutex_unlock(&ni_lock);
2135f4faf74SXin LI 
2145f4faf74SXin LI     mutex_lock(&nc_file_lock);
2158360efbdSAlfred Perlstein     if ((nc_file != NULL) || (nc_file = fopen(NETCONFIG, "r")) != NULL) {
2168360efbdSAlfred Perlstein 	nc_vars->valid = NC_VALID;
2178360efbdSAlfred Perlstein 	nc_vars->flag = 0;
2188360efbdSAlfred Perlstein 	nc_vars->nc_configs = ni.head;
2195f4faf74SXin LI 	mutex_unlock(&nc_file_lock);
2208360efbdSAlfred Perlstein 	return ((void *)nc_vars);
2218360efbdSAlfred Perlstein     }
2225f4faf74SXin LI     mutex_unlock(&nc_file_lock);
2235f4faf74SXin LI 
2245f4faf74SXin LI     mutex_lock(&ni_lock);
2258360efbdSAlfred Perlstein     ni.ref--;
2265f4faf74SXin LI     mutex_unlock(&ni_lock);
2275f4faf74SXin LI 
2288360efbdSAlfred Perlstein     nc_error = NC_NONETCONFIG;
2298360efbdSAlfred Perlstein     free(nc_vars);
2308360efbdSAlfred Perlstein     return (NULL);
2318360efbdSAlfred Perlstein }
2328360efbdSAlfred Perlstein 
2338360efbdSAlfred Perlstein 
2348360efbdSAlfred Perlstein /*
2358360efbdSAlfred Perlstein  * When first called, getnetconfig() returns a pointer to the first entry in
2368360efbdSAlfred Perlstein  * the netconfig database, formatted as a struct netconfig.  On each subsequent
2378360efbdSAlfred Perlstein  * call, getnetconfig() returns a pointer to the next entry in the database.
2388360efbdSAlfred Perlstein  * getnetconfig() can thus be used to search the entire netconfig file.
2398360efbdSAlfred Perlstein  * getnetconfig() returns NULL at end of file.
2408360efbdSAlfred Perlstein  */
2418360efbdSAlfred Perlstein 
2428360efbdSAlfred Perlstein struct netconfig *
2438360efbdSAlfred Perlstein getnetconfig(handlep)
2448360efbdSAlfred Perlstein void *handlep;
2458360efbdSAlfred Perlstein {
2468360efbdSAlfred Perlstein     struct netconfig_vars *ncp = (struct netconfig_vars *)handlep;
2478360efbdSAlfred Perlstein     char *stringp;		/* tmp string pointer */
2488360efbdSAlfred Perlstein     struct netconfig_list	*list;
2498360efbdSAlfred Perlstein     struct netconfig *np;
2505f4faf74SXin LI     struct netconfig *result;
2518360efbdSAlfred Perlstein 
2528360efbdSAlfred Perlstein     /*
2538360efbdSAlfred Perlstein      * Verify that handle is valid
2548360efbdSAlfred Perlstein      */
2555f4faf74SXin LI     mutex_lock(&nc_file_lock);
2568360efbdSAlfred Perlstein     if (ncp == NULL || nc_file == NULL) {
2578360efbdSAlfred Perlstein 	nc_error = NC_NOTINIT;
2585f4faf74SXin LI 	mutex_unlock(&nc_file_lock);
2598360efbdSAlfred Perlstein 	return (NULL);
2608360efbdSAlfred Perlstein     }
2615f4faf74SXin LI     mutex_unlock(&nc_file_lock);
2628360efbdSAlfred Perlstein 
2638360efbdSAlfred Perlstein     switch (ncp->valid) {
2648360efbdSAlfred Perlstein     case NC_VALID:
2658360efbdSAlfred Perlstein 	/*
2668360efbdSAlfred Perlstein 	 * If entry has already been read into the list,
2678360efbdSAlfred Perlstein 	 * we return the entry in the linked list.
2688360efbdSAlfred Perlstein 	 * If this is the first time call, check if there are any entries in
2698360efbdSAlfred Perlstein 	 * linked list.  If no entries, we need to read the netconfig db.
2708360efbdSAlfred Perlstein 	 * If we have been here and the next entry is there, we just return
2718360efbdSAlfred Perlstein 	 * it.
2728360efbdSAlfred Perlstein 	 */
2738360efbdSAlfred Perlstein 	if (ncp->flag == 0) {	/* first time */
2748360efbdSAlfred Perlstein 	    ncp->flag = 1;
2755f4faf74SXin LI 	    mutex_lock(&ni_lock);
2768360efbdSAlfred Perlstein 	    ncp->nc_configs = ni.head;
2775f4faf74SXin LI 	    mutex_unlock(&ni_lock);
2788360efbdSAlfred Perlstein 	    if (ncp->nc_configs != NULL)	/* entry already exist */
2798360efbdSAlfred Perlstein 		return(ncp->nc_configs->ncp);
2808360efbdSAlfred Perlstein 	}
2818360efbdSAlfred Perlstein 	else if (ncp->nc_configs != NULL && ncp->nc_configs->next != NULL) {
2828360efbdSAlfred Perlstein 	    ncp->nc_configs = ncp->nc_configs->next;
2838360efbdSAlfred Perlstein 	    return(ncp->nc_configs->ncp);
2848360efbdSAlfred Perlstein 	}
2858360efbdSAlfred Perlstein 
2868360efbdSAlfred Perlstein 	/*
2878360efbdSAlfred Perlstein 	 * If we cannot find the entry in the list and is end of file,
2888360efbdSAlfred Perlstein 	 * we give up.
2898360efbdSAlfred Perlstein 	 */
2905f4faf74SXin LI 	mutex_lock(&ni_lock);
2915f4faf74SXin LI 	if (ni.eof == 1) {
2925f4faf74SXin LI 		mutex_unlock(&ni_lock);
2935f4faf74SXin LI 		return(NULL);
2945f4faf74SXin LI 	}
2955f4faf74SXin LI 	mutex_unlock(&ni_lock);
2965f4faf74SXin LI 
2978360efbdSAlfred Perlstein 	break;
2988360efbdSAlfred Perlstein     default:
2998360efbdSAlfred Perlstein 	nc_error = NC_NOTINIT;
3008360efbdSAlfred Perlstein 	return (NULL);
3018360efbdSAlfred Perlstein     }
3028360efbdSAlfred Perlstein 
3038360efbdSAlfred Perlstein     stringp = (char *) malloc(MAXNETCONFIGLINE);
3048360efbdSAlfred Perlstein     if (stringp == NULL)
3058360efbdSAlfred Perlstein     	return (NULL);
3068360efbdSAlfred Perlstein 
3078360efbdSAlfred Perlstein #ifdef MEM_CHK
3088360efbdSAlfred Perlstein     if (malloc_verify() == 0) {
3098360efbdSAlfred Perlstein 	fprintf(stderr, "memory heap corrupted in getnetconfig\n");
3108360efbdSAlfred Perlstein 	exit(1);
3118360efbdSAlfred Perlstein     }
3128360efbdSAlfred Perlstein #endif
3138360efbdSAlfred Perlstein 
3148360efbdSAlfred Perlstein     /*
3158360efbdSAlfred Perlstein      * Read a line from netconfig file.
3168360efbdSAlfred Perlstein      */
3175f4faf74SXin LI     mutex_lock(&nc_file_lock);
3188360efbdSAlfred Perlstein     do {
3198360efbdSAlfred Perlstein 	if (fgets(stringp, MAXNETCONFIGLINE, nc_file) == NULL) {
3208360efbdSAlfred Perlstein 	    free(stringp);
3215f4faf74SXin LI 	    mutex_lock(&ni_lock);
3228360efbdSAlfred Perlstein 	    ni.eof = 1;
3235f4faf74SXin LI 	    mutex_unlock(&ni_lock);
3245f4faf74SXin LI 	    mutex_unlock(&nc_file_lock);
3258360efbdSAlfred Perlstein 	    return (NULL);
3268360efbdSAlfred Perlstein         }
3278360efbdSAlfred Perlstein     } while (*stringp == '#');
3285f4faf74SXin LI     mutex_unlock(&nc_file_lock);
3298360efbdSAlfred Perlstein 
3308360efbdSAlfred Perlstein     list = (struct netconfig_list *) malloc(sizeof (struct netconfig_list));
3318360efbdSAlfred Perlstein     if (list == NULL) {
3328360efbdSAlfred Perlstein     	free(stringp);
3338360efbdSAlfred Perlstein     	return(NULL);
3348360efbdSAlfred Perlstein     }
3358360efbdSAlfred Perlstein     np = (struct netconfig *) malloc(sizeof (struct netconfig));
3368360efbdSAlfred Perlstein     if (np == NULL) {
3378360efbdSAlfred Perlstein     	free(stringp);
3388360efbdSAlfred Perlstein 	free(list);
3398360efbdSAlfred Perlstein     	return(NULL);
3408360efbdSAlfred Perlstein     }
3418360efbdSAlfred Perlstein     list->ncp = np;
3428360efbdSAlfred Perlstein     list->next = NULL;
3438360efbdSAlfred Perlstein     list->ncp->nc_lookups = NULL;
3448360efbdSAlfred Perlstein     list->linep = stringp;
3458360efbdSAlfred Perlstein     if (parse_ncp(stringp, list->ncp) == -1) {
3468360efbdSAlfred Perlstein 	free(stringp);
3478360efbdSAlfred Perlstein 	free(np);
3488360efbdSAlfred Perlstein 	free(list);
3498360efbdSAlfred Perlstein 	return (NULL);
3508360efbdSAlfred Perlstein     }
3518360efbdSAlfred Perlstein     else {
3528360efbdSAlfred Perlstein 	/*
3538360efbdSAlfred Perlstein 	 * If this is the first entry that's been read, it is the head of
3548360efbdSAlfred Perlstein 	 * the list.  If not, put the entry at the end of the list.
3558360efbdSAlfred Perlstein 	 * Reposition the current pointer of the handle to the last entry
3568360efbdSAlfred Perlstein 	 * in the list.
3578360efbdSAlfred Perlstein 	 */
3585f4faf74SXin LI 	mutex_lock(&ni_lock);
3598360efbdSAlfred Perlstein 	if (ni.head == NULL) {	/* first entry */
3608360efbdSAlfred Perlstein 	    ni.head = ni.tail = list;
3618360efbdSAlfred Perlstein 	}
3628360efbdSAlfred Perlstein     	else {
3638360efbdSAlfred Perlstein     	    ni.tail->next = list;
3648360efbdSAlfred Perlstein     	    ni.tail = ni.tail->next;
3658360efbdSAlfred Perlstein     	}
3668360efbdSAlfred Perlstein 	ncp->nc_configs = ni.tail;
3675f4faf74SXin LI 	result = ni.tail->ncp;
3685f4faf74SXin LI 	mutex_unlock(&ni_lock);
3695f4faf74SXin LI 	return(result);
3708360efbdSAlfred Perlstein     }
3718360efbdSAlfred Perlstein }
3728360efbdSAlfred Perlstein 
3738360efbdSAlfred Perlstein /*
3748360efbdSAlfred Perlstein  * endnetconfig() may be called to "unbind" or "close" the netconfig database
3758360efbdSAlfred Perlstein  * when processing is complete, releasing resources for reuse.  endnetconfig()
3768360efbdSAlfred Perlstein  * may not be called before setnetconfig().  endnetconfig() returns 0 on
3778360efbdSAlfred Perlstein  * success and -1 on failure (for example, if setnetconfig() was not called
3788360efbdSAlfred Perlstein  * previously).
3798360efbdSAlfred Perlstein  */
3808360efbdSAlfred Perlstein int
3818360efbdSAlfred Perlstein endnetconfig(handlep)
3828360efbdSAlfred Perlstein void *handlep;
3838360efbdSAlfred Perlstein {
3848360efbdSAlfred Perlstein     struct netconfig_vars *nc_handlep = (struct netconfig_vars *)handlep;
3858360efbdSAlfred Perlstein 
3868360efbdSAlfred Perlstein     struct netconfig_list *q, *p;
3878360efbdSAlfred Perlstein 
3888360efbdSAlfred Perlstein     /*
3898360efbdSAlfred Perlstein      * Verify that handle is valid
3908360efbdSAlfred Perlstein      */
3918360efbdSAlfred Perlstein     if (nc_handlep == NULL || (nc_handlep->valid != NC_VALID &&
3928360efbdSAlfred Perlstein 	    nc_handlep->valid != NC_STORAGE)) {
3938360efbdSAlfred Perlstein 	nc_error = NC_NOTINIT;
3948360efbdSAlfred Perlstein 	return (-1);
3958360efbdSAlfred Perlstein     }
3968360efbdSAlfred Perlstein 
3978360efbdSAlfred Perlstein     /*
3988360efbdSAlfred Perlstein      * Return 0 if anyone still needs it.
3998360efbdSAlfred Perlstein      */
4008360efbdSAlfred Perlstein     nc_handlep->valid = NC_INVALID;
4018360efbdSAlfred Perlstein     nc_handlep->flag = 0;
4028360efbdSAlfred Perlstein     nc_handlep->nc_configs = NULL;
4035f4faf74SXin LI     mutex_lock(&ni_lock);
4048360efbdSAlfred Perlstein     if (--ni.ref > 0) {
4055f4faf74SXin LI 	mutex_unlock(&ni_lock);
4068360efbdSAlfred Perlstein     	free(nc_handlep);
4078360efbdSAlfred Perlstein 	return(0);
4088360efbdSAlfred Perlstein     }
4098360efbdSAlfred Perlstein 
4108360efbdSAlfred Perlstein     /*
4118360efbdSAlfred Perlstein      * Noone needs these entries anymore, then frees them.
4128360efbdSAlfred Perlstein      * Make sure all info in netconfig_info structure has been reinitialized.
4138360efbdSAlfred Perlstein      */
4140c0349bfSGarrett Wollman     q = ni.head;
4158360efbdSAlfred Perlstein     ni.eof = ni.ref = 0;
4168360efbdSAlfred Perlstein     ni.head = NULL;
4178360efbdSAlfred Perlstein     ni.tail = NULL;
4185f4faf74SXin LI     mutex_unlock(&ni_lock);
4195f4faf74SXin LI 
4200c0349bfSGarrett Wollman     while (q != NULL) {
4218360efbdSAlfred Perlstein 	p = q->next;
4228360efbdSAlfred Perlstein 	if (q->ncp->nc_lookups != NULL) free(q->ncp->nc_lookups);
4238360efbdSAlfred Perlstein 	free(q->ncp);
4248360efbdSAlfred Perlstein 	free(q->linep);
4258360efbdSAlfred Perlstein 	free(q);
4268360efbdSAlfred Perlstein 	q = p;
4278360efbdSAlfred Perlstein     }
4288360efbdSAlfred Perlstein     free(nc_handlep);
4298360efbdSAlfred Perlstein 
4305f4faf74SXin LI     mutex_lock(&nc_file_lock);
4318360efbdSAlfred Perlstein     fclose(nc_file);
4328360efbdSAlfred Perlstein     nc_file = NULL;
4335f4faf74SXin LI     mutex_unlock(&nc_file_lock);
4345f4faf74SXin LI 
4358360efbdSAlfred Perlstein     return (0);
4368360efbdSAlfred Perlstein }
4378360efbdSAlfred Perlstein 
4388360efbdSAlfred Perlstein /*
4398360efbdSAlfred Perlstein  * getnetconfigent(netid) returns a pointer to the struct netconfig structure
4408360efbdSAlfred Perlstein  * corresponding to netid.  It returns NULL if netid is invalid (that is, does
4418360efbdSAlfred Perlstein  * not name an entry in the netconfig database).  It returns NULL and sets
4428360efbdSAlfred Perlstein  * errno in case of failure (for example, if the netconfig database cannot be
4438360efbdSAlfred Perlstein  * opened).
4448360efbdSAlfred Perlstein  */
4458360efbdSAlfred Perlstein 
4468360efbdSAlfred Perlstein struct netconfig *
4478360efbdSAlfred Perlstein getnetconfigent(netid)
44840c10ffdSAlfred Perlstein 	const char *netid;
4498360efbdSAlfred Perlstein {
4508360efbdSAlfred Perlstein     FILE *file;		/* NETCONFIG db's file pointer */
4518360efbdSAlfred Perlstein     char *linep;	/* holds current netconfig line */
4528360efbdSAlfred Perlstein     char *stringp;	/* temporary string pointer */
4538360efbdSAlfred Perlstein     struct netconfig *ncp = NULL;   /* returned value */
4548360efbdSAlfred Perlstein     struct netconfig_list *list;	/* pointer to cache list */
4558360efbdSAlfred Perlstein 
456b3a38fe3SIan Dowse     nc_error = NC_NOTFOUND;	/* default error. */
4578360efbdSAlfred Perlstein     if (netid == NULL || strlen(netid) == 0) {
4588360efbdSAlfred Perlstein 	return (NULL);
4598360efbdSAlfred Perlstein     }
4608360efbdSAlfred Perlstein 
4618360efbdSAlfred Perlstein     /*
4628360efbdSAlfred Perlstein      * Look up table if the entries have already been read and parsed in
4638360efbdSAlfred Perlstein      * getnetconfig(), then copy this entry into a buffer and return it.
4648360efbdSAlfred Perlstein      * If we cannot find the entry in the current list and there are more
4658360efbdSAlfred Perlstein      * entries in the netconfig db that has not been read, we then read the
4668360efbdSAlfred Perlstein      * db and try find the match netid.
4678360efbdSAlfred Perlstein      * If all the netconfig db has been read and placed into the list and
4688360efbdSAlfred Perlstein      * there is no match for the netid, return NULL.
4698360efbdSAlfred Perlstein      */
4705f4faf74SXin LI     mutex_lock(&ni_lock);
4718360efbdSAlfred Perlstein     if (ni.head != NULL) {
4728360efbdSAlfred Perlstein 	for (list = ni.head; list; list = list->next) {
4738360efbdSAlfred Perlstein 	    if (strcmp(list->ncp->nc_netid, netid) == 0) {
4745f4faf74SXin LI 		mutex_unlock(&ni_lock);
4758360efbdSAlfred Perlstein 	        return(dup_ncp(list->ncp));
4768360efbdSAlfred Perlstein 	    }
4778360efbdSAlfred Perlstein 	}
4785f4faf74SXin LI 	if (ni.eof == 1) {	/* that's all the entries */
4795f4faf74SXin LI 		mutex_unlock(&ni_lock);
4808360efbdSAlfred Perlstein 		return(NULL);
4818360efbdSAlfred Perlstein 	}
4825f4faf74SXin LI     }
4835f4faf74SXin LI     mutex_unlock(&ni_lock);
4848360efbdSAlfred Perlstein 
4858360efbdSAlfred Perlstein 
4868360efbdSAlfred Perlstein     if ((file = fopen(NETCONFIG, "r")) == NULL) {
487b3a38fe3SIan Dowse 	nc_error = NC_NONETCONFIG;
4888360efbdSAlfred Perlstein 	return (NULL);
4898360efbdSAlfred Perlstein     }
4908360efbdSAlfred Perlstein 
4918360efbdSAlfred Perlstein     if ((linep = malloc(MAXNETCONFIGLINE)) == NULL) {
4928360efbdSAlfred Perlstein 	fclose(file);
493b3a38fe3SIan Dowse 	nc_error = NC_NOMEM;
4948360efbdSAlfred Perlstein 	return (NULL);
4958360efbdSAlfred Perlstein     }
4968360efbdSAlfred Perlstein     do {
4973c788545SMartin Blapp 	ptrdiff_t len;
4988360efbdSAlfred Perlstein 	char *tmpp;	/* tmp string pointer */
4998360efbdSAlfred Perlstein 
5008360efbdSAlfred Perlstein 	do {
5018360efbdSAlfred Perlstein 	    if ((stringp = fgets(linep, MAXNETCONFIGLINE, file)) == NULL) {
5028360efbdSAlfred Perlstein 		break;
5038360efbdSAlfred Perlstein 	    }
5048360efbdSAlfred Perlstein 	} while (*stringp == '#');
5058360efbdSAlfred Perlstein 	if (stringp == NULL) {	    /* eof */
5068360efbdSAlfred Perlstein 	    break;
5078360efbdSAlfred Perlstein 	}
5088360efbdSAlfred Perlstein 	if ((tmpp = strpbrk(stringp, "\t ")) == NULL) {	/* can't parse file */
5098360efbdSAlfred Perlstein 	    nc_error = NC_BADFILE;
5108360efbdSAlfred Perlstein 	    break;
5118360efbdSAlfred Perlstein 	}
5123c788545SMartin Blapp 	if (strlen(netid) == (size_t) (len = tmpp - stringp) &&	/* a match */
5138360efbdSAlfred Perlstein 		strncmp(stringp, netid, (size_t)len) == 0) {
5148360efbdSAlfred Perlstein 	    if ((ncp = (struct netconfig *)
5158360efbdSAlfred Perlstein 		    malloc(sizeof (struct netconfig))) == NULL) {
5168360efbdSAlfred Perlstein 		break;
5178360efbdSAlfred Perlstein 	    }
5188360efbdSAlfred Perlstein 	    ncp->nc_lookups = NULL;
5198360efbdSAlfred Perlstein 	    if (parse_ncp(linep, ncp) == -1) {
5208360efbdSAlfred Perlstein 		free(ncp);
5218360efbdSAlfred Perlstein 		ncp = NULL;
5228360efbdSAlfred Perlstein 	    }
5238360efbdSAlfred Perlstein 	    break;
5248360efbdSAlfred Perlstein 	}
5258360efbdSAlfred Perlstein     } while (stringp != NULL);
5268360efbdSAlfred Perlstein     if (ncp == NULL) {
5278360efbdSAlfred Perlstein 	free(linep);
5288360efbdSAlfred Perlstein     }
5298360efbdSAlfred Perlstein     fclose(file);
5308360efbdSAlfred Perlstein     return(ncp);
5318360efbdSAlfred Perlstein }
5328360efbdSAlfred Perlstein 
5338360efbdSAlfred Perlstein /*
5348360efbdSAlfred Perlstein  * freenetconfigent(netconfigp) frees the netconfig structure pointed to by
5358360efbdSAlfred Perlstein  * netconfigp (previously returned by getnetconfigent()).
5368360efbdSAlfred Perlstein  */
5378360efbdSAlfred Perlstein 
5388360efbdSAlfred Perlstein void
5398360efbdSAlfred Perlstein freenetconfigent(netconfigp)
5408360efbdSAlfred Perlstein 	struct netconfig *netconfigp;
5418360efbdSAlfred Perlstein {
5428360efbdSAlfred Perlstein     if (netconfigp != NULL) {
5438360efbdSAlfred Perlstein 	free(netconfigp->nc_netid);	/* holds all netconfigp's strings */
5448360efbdSAlfred Perlstein 	if (netconfigp->nc_lookups != NULL)
5458360efbdSAlfred Perlstein 	    free(netconfigp->nc_lookups);
5468360efbdSAlfred Perlstein 	free(netconfigp);
5478360efbdSAlfred Perlstein     }
5488360efbdSAlfred Perlstein     return;
5498360efbdSAlfred Perlstein }
5508360efbdSAlfred Perlstein 
5518360efbdSAlfred Perlstein /*
5528360efbdSAlfred Perlstein  * Parse line and stuff it in a struct netconfig
5538360efbdSAlfred Perlstein  * Typical line might look like:
5548360efbdSAlfred Perlstein  *	udp tpi_cots vb inet udp /dev/udp /usr/lib/ip.so,/usr/local/ip.so
5558360efbdSAlfred Perlstein  *
5568360efbdSAlfred Perlstein  * We return -1 if any of the tokens don't parse, or malloc fails.
5578360efbdSAlfred Perlstein  *
5588360efbdSAlfred Perlstein  * Note that we modify stringp (putting NULLs after tokens) and
5598360efbdSAlfred Perlstein  * we set the ncp's string field pointers to point to these tokens within
5608360efbdSAlfred Perlstein  * stringp.
5618360efbdSAlfred Perlstein  */
5628360efbdSAlfred Perlstein 
5638360efbdSAlfred Perlstein static int
5648360efbdSAlfred Perlstein parse_ncp(stringp, ncp)
5658360efbdSAlfred Perlstein char *stringp;		/* string to parse */
5668360efbdSAlfred Perlstein struct netconfig *ncp;	/* where to put results */
5678360efbdSAlfred Perlstein {
5688360efbdSAlfred Perlstein     char    *tokenp;	/* for processing tokens */
5698360efbdSAlfred Perlstein     char    *lasts;
570330e445cSMatteo Riondato     char    **nc_lookups;
5718360efbdSAlfred Perlstein 
5728360efbdSAlfred Perlstein     nc_error = NC_BADFILE;	/* nearly anything that breaks is for this reason */
5738360efbdSAlfred Perlstein     stringp[strlen(stringp)-1] = '\0';	/* get rid of newline */
5748360efbdSAlfred Perlstein     /* netid */
5758360efbdSAlfred Perlstein     if ((ncp->nc_netid = strtok_r(stringp, "\t ", &lasts)) == NULL) {
5768360efbdSAlfred Perlstein 	return (-1);
5778360efbdSAlfred Perlstein     }
5788360efbdSAlfred Perlstein 
5798360efbdSAlfred Perlstein     /* semantics */
5808360efbdSAlfred Perlstein     if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) {
5818360efbdSAlfred Perlstein 	return (-1);
5828360efbdSAlfred Perlstein     }
5838360efbdSAlfred Perlstein     if (strcmp(tokenp, NC_TPI_COTS_ORD_S) == 0)
5848360efbdSAlfred Perlstein 	ncp->nc_semantics = NC_TPI_COTS_ORD;
5858360efbdSAlfred Perlstein     else if (strcmp(tokenp, NC_TPI_COTS_S) == 0)
5868360efbdSAlfred Perlstein 	ncp->nc_semantics = NC_TPI_COTS;
5878360efbdSAlfred Perlstein     else if (strcmp(tokenp, NC_TPI_CLTS_S) == 0)
5888360efbdSAlfred Perlstein 	ncp->nc_semantics = NC_TPI_CLTS;
5898360efbdSAlfred Perlstein     else if (strcmp(tokenp, NC_TPI_RAW_S) == 0)
5908360efbdSAlfred Perlstein 	ncp->nc_semantics = NC_TPI_RAW;
5918360efbdSAlfred Perlstein     else
5928360efbdSAlfred Perlstein 	return (-1);
5938360efbdSAlfred Perlstein 
5948360efbdSAlfred Perlstein     /* flags */
5958360efbdSAlfred Perlstein     if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) {
5968360efbdSAlfred Perlstein 	return (-1);
5978360efbdSAlfred Perlstein     }
5988360efbdSAlfred Perlstein     for (ncp->nc_flag = NC_NOFLAG; *tokenp != '\0';
5998360efbdSAlfred Perlstein 	    tokenp++) {
6008360efbdSAlfred Perlstein 	switch (*tokenp) {
6018360efbdSAlfred Perlstein 	case NC_NOFLAG_C:
6028360efbdSAlfred Perlstein 	    break;
6038360efbdSAlfred Perlstein 	case NC_VISIBLE_C:
6048360efbdSAlfred Perlstein 	    ncp->nc_flag |= NC_VISIBLE;
6058360efbdSAlfred Perlstein 	    break;
6068360efbdSAlfred Perlstein 	case NC_BROADCAST_C:
6078360efbdSAlfred Perlstein 	    ncp->nc_flag |= NC_BROADCAST;
6088360efbdSAlfred Perlstein 	    break;
6098360efbdSAlfred Perlstein 	default:
6108360efbdSAlfred Perlstein 	    return (-1);
6118360efbdSAlfred Perlstein 	}
6128360efbdSAlfred Perlstein     }
6138360efbdSAlfred Perlstein     /* protocol family */
6148360efbdSAlfred Perlstein     if ((ncp->nc_protofmly = strtok_r(NULL, "\t ", &lasts)) == NULL) {
6158360efbdSAlfred Perlstein 	return (-1);
6168360efbdSAlfred Perlstein     }
6178360efbdSAlfred Perlstein     /* protocol name */
6188360efbdSAlfred Perlstein     if ((ncp->nc_proto = strtok_r(NULL, "\t ", &lasts)) == NULL) {
6198360efbdSAlfred Perlstein 	return (-1);
6208360efbdSAlfred Perlstein     }
6218360efbdSAlfred Perlstein     /* network device */
6228360efbdSAlfred Perlstein     if ((ncp->nc_device = strtok_r(NULL, "\t ", &lasts)) == NULL) {
6238360efbdSAlfred Perlstein 	return (-1);
6248360efbdSAlfred Perlstein     }
6258360efbdSAlfred Perlstein     if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) {
6268360efbdSAlfred Perlstein 	return (-1);
6278360efbdSAlfred Perlstein     }
6288360efbdSAlfred Perlstein     if (strcmp(tokenp, NC_NOLOOKUP) == 0) {
6298360efbdSAlfred Perlstein 	ncp->nc_nlookups = 0;
6308360efbdSAlfred Perlstein 	ncp->nc_lookups = NULL;
6318360efbdSAlfred Perlstein     } else {
6328360efbdSAlfred Perlstein 	char *cp;	    /* tmp string */
6338360efbdSAlfred Perlstein 
6348360efbdSAlfred Perlstein 	if (ncp->nc_lookups != NULL)	/* from last visit */
6358360efbdSAlfred Perlstein 	    free(ncp->nc_lookups);
636330e445cSMatteo Riondato 	ncp->nc_lookups = NULL;
6378360efbdSAlfred Perlstein 	ncp->nc_nlookups = 0;
6388360efbdSAlfred Perlstein 	while ((cp = tokenp) != NULL) {
639330e445cSMatteo Riondato 	    if ((nc_lookups = realloc(ncp->nc_lookups,
640330e445cSMatteo Riondato 		(ncp->nc_nlookups + 1) * sizeof *ncp->nc_lookups)) == NULL) {
641330e445cSMatteo Riondato 		    free(ncp->nc_lookups);
642330e445cSMatteo Riondato 		    ncp->nc_lookups = NULL;
643330e445cSMatteo Riondato 		    return (-1);
644330e445cSMatteo Riondato 	    }
6458360efbdSAlfred Perlstein 	    tokenp = _get_next_token(cp, ',');
646330e445cSMatteo Riondato 	    ncp->nc_lookups = nc_lookups;
647330e445cSMatteo Riondato 	    ncp->nc_lookups[ncp->nc_nlookups++] = cp;
6488360efbdSAlfred Perlstein 	}
6498360efbdSAlfred Perlstein     }
6508360efbdSAlfred Perlstein     return (0);
6518360efbdSAlfred Perlstein }
6528360efbdSAlfred Perlstein 
6538360efbdSAlfred Perlstein 
6548360efbdSAlfred Perlstein /*
6558360efbdSAlfred Perlstein  * Returns a string describing the reason for failure.
6568360efbdSAlfred Perlstein  */
6578360efbdSAlfred Perlstein char *
6588360efbdSAlfred Perlstein nc_sperror()
6598360efbdSAlfred Perlstein {
6608360efbdSAlfred Perlstein     const char *message;
6618360efbdSAlfred Perlstein 
6628360efbdSAlfred Perlstein     switch(nc_error) {
6638360efbdSAlfred Perlstein     case NC_NONETCONFIG:
6648360efbdSAlfred Perlstein 	message = _nc_errors[0];
6658360efbdSAlfred Perlstein 	break;
6668360efbdSAlfred Perlstein     case NC_NOMEM:
6678360efbdSAlfred Perlstein 	message = _nc_errors[1];
6688360efbdSAlfred Perlstein 	break;
6698360efbdSAlfred Perlstein     case NC_NOTINIT:
6708360efbdSAlfred Perlstein 	message = _nc_errors[2];
6718360efbdSAlfred Perlstein 	break;
6728360efbdSAlfred Perlstein     case NC_BADFILE:
6738360efbdSAlfred Perlstein 	message = _nc_errors[3];
6748360efbdSAlfred Perlstein 	break;
675b3a38fe3SIan Dowse     case NC_NOTFOUND:
676b3a38fe3SIan Dowse 	message = _nc_errors[4];
677b3a38fe3SIan Dowse 	break;
6788360efbdSAlfred Perlstein     default:
6798360efbdSAlfred Perlstein 	message = "Unknown network selection error";
6808360efbdSAlfred Perlstein     }
6818360efbdSAlfred Perlstein     /* LINTED const castaway */
6828360efbdSAlfred Perlstein     return ((char *)message);
6838360efbdSAlfred Perlstein }
6848360efbdSAlfred Perlstein 
6858360efbdSAlfred Perlstein /*
6868360efbdSAlfred Perlstein  * Prints a message onto standard error describing the reason for failure.
6878360efbdSAlfred Perlstein  */
6888360efbdSAlfred Perlstein void
6898360efbdSAlfred Perlstein nc_perror(s)
6908360efbdSAlfred Perlstein 	const char *s;
6918360efbdSAlfred Perlstein {
692b3a38fe3SIan Dowse     fprintf(stderr, "%s: %s\n", s, nc_sperror());
6938360efbdSAlfred Perlstein }
6948360efbdSAlfred Perlstein 
6958360efbdSAlfred Perlstein /*
6968360efbdSAlfred Perlstein  * Duplicates the matched netconfig buffer.
6978360efbdSAlfred Perlstein  */
6988360efbdSAlfred Perlstein static struct netconfig *
6998360efbdSAlfred Perlstein dup_ncp(ncp)
7008360efbdSAlfred Perlstein struct netconfig	*ncp;
7018360efbdSAlfred Perlstein {
7028360efbdSAlfred Perlstein     struct netconfig	*p;
7038360efbdSAlfred Perlstein     char	*tmp;
7043c788545SMartin Blapp     u_int	i;
7058360efbdSAlfred Perlstein 
7068360efbdSAlfred Perlstein     if ((tmp=malloc(MAXNETCONFIGLINE)) == NULL)
7078360efbdSAlfred Perlstein 	return(NULL);
7088360efbdSAlfred Perlstein     if ((p=(struct netconfig *)malloc(sizeof(struct netconfig))) == NULL) {
7098360efbdSAlfred Perlstein 	free(tmp);
7108360efbdSAlfred Perlstein 	return(NULL);
7118360efbdSAlfred Perlstein     }
7128360efbdSAlfred Perlstein     /*
7138360efbdSAlfred Perlstein      * First we dup all the data from matched netconfig buffer.  Then we
7148360efbdSAlfred Perlstein      * adjust some of the member pointer to a pre-allocated buffer where
7158360efbdSAlfred Perlstein      * contains part of the data.
7168360efbdSAlfred Perlstein      * To follow the convention used in parse_ncp(), we store all the
7173c788545SMartin Blapp      * necessary information in the pre-allocated buffer and let each
7188360efbdSAlfred Perlstein      * of the netconfig char pointer member point to the right address
7198360efbdSAlfred Perlstein      * in the buffer.
7208360efbdSAlfred Perlstein      */
7218360efbdSAlfred Perlstein     *p = *ncp;
7228360efbdSAlfred Perlstein     p->nc_netid = (char *)strcpy(tmp,ncp->nc_netid);
72316fc3635SMark Murray     tmp = strchr(tmp, '\0') + 1;
7248360efbdSAlfred Perlstein     p->nc_protofmly = (char *)strcpy(tmp,ncp->nc_protofmly);
72516fc3635SMark Murray     tmp = strchr(tmp, '\0') + 1;
7268360efbdSAlfred Perlstein     p->nc_proto = (char *)strcpy(tmp,ncp->nc_proto);
72716fc3635SMark Murray     tmp = strchr(tmp, '\0') + 1;
7288360efbdSAlfred Perlstein     p->nc_device = (char *)strcpy(tmp,ncp->nc_device);
7298360efbdSAlfred Perlstein     p->nc_lookups = (char **)malloc((size_t)(p->nc_nlookups+1) * sizeof(char *));
7308360efbdSAlfred Perlstein     if (p->nc_lookups == NULL) {
7318360efbdSAlfred Perlstein 	free(p->nc_netid);
732b0718451SMartin Blapp 	free(p);
7338360efbdSAlfred Perlstein 	return(NULL);
7348360efbdSAlfred Perlstein     }
7358360efbdSAlfred Perlstein     for (i=0; i < p->nc_nlookups; i++) {
73616fc3635SMark Murray     	tmp = strchr(tmp, '\0') + 1;
7378360efbdSAlfred Perlstein     	p->nc_lookups[i] = (char *)strcpy(tmp,ncp->nc_lookups[i]);
7388360efbdSAlfred Perlstein     }
7398360efbdSAlfred Perlstein     return(p);
7408360efbdSAlfred Perlstein }
741