18360efbdSAlfred Perlstein /* $NetBSD: getnetconfig.c,v 1.3 2000/07/06 03:10:34 christos Exp $ */ 28360efbdSAlfred Perlstein 32e322d37SHiroki Sato /*- 42e322d37SHiroki Sato * Copyright (c) 2009, Sun Microsystems, Inc. 52e322d37SHiroki Sato * All rights reserved. 68360efbdSAlfred Perlstein * 72e322d37SHiroki Sato * Redistribution and use in source and binary forms, with or without 82e322d37SHiroki Sato * modification, are permitted provided that the following conditions are met: 92e322d37SHiroki Sato * - Redistributions of source code must retain the above copyright notice, 102e322d37SHiroki Sato * this list of conditions and the following disclaimer. 112e322d37SHiroki Sato * - Redistributions in binary form must reproduce the above copyright notice, 122e322d37SHiroki Sato * this list of conditions and the following disclaimer in the documentation 132e322d37SHiroki Sato * and/or other materials provided with the distribution. 142e322d37SHiroki Sato * - Neither the name of Sun Microsystems, Inc. nor the names of its 152e322d37SHiroki Sato * contributors may be used to endorse or promote products derived 162e322d37SHiroki Sato * from this software without specific prior written permission. 178360efbdSAlfred Perlstein * 182e322d37SHiroki Sato * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 192e322d37SHiroki Sato * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 202e322d37SHiroki Sato * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 212e322d37SHiroki Sato * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 222e322d37SHiroki Sato * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 232e322d37SHiroki Sato * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 242e322d37SHiroki Sato * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 252e322d37SHiroki Sato * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 262e322d37SHiroki Sato * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 272e322d37SHiroki Sato * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 282e322d37SHiroki 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 * 150587cf682SCraig Rodrigues __nc_error(void) 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 free(nc_addr); 168b3a38fe3SIan Dowse return (&nc_error); 1698360efbdSAlfred Perlstein } 1708360efbdSAlfred Perlstein *nc_addr = 0; 1718360efbdSAlfred Perlstein } 172b3a38fe3SIan Dowse return (nc_addr); 1738360efbdSAlfred Perlstein } 1748360efbdSAlfred Perlstein 1758360efbdSAlfred Perlstein #define nc_error (*(__nc_error())) 1768360efbdSAlfred Perlstein /* 1778360efbdSAlfred Perlstein * A call to setnetconfig() establishes a /etc/netconfig "session". A session 1788360efbdSAlfred Perlstein * "handle" is returned on a successful call. At the start of a session (after 1798360efbdSAlfred Perlstein * a call to setnetconfig()) searches through the /etc/netconfig database will 1808360efbdSAlfred Perlstein * proceed from the start of the file. The session handle must be passed to 1818360efbdSAlfred Perlstein * getnetconfig() to parse the file. Each call to getnetconfig() using the 1828360efbdSAlfred Perlstein * current handle will process one subsequent entry in /etc/netconfig. 1838360efbdSAlfred Perlstein * setnetconfig() must be called before the first call to getnetconfig(). 1848360efbdSAlfred Perlstein * (Handles are used to allow for nested calls to setnetpath()). 1858360efbdSAlfred Perlstein * 1868360efbdSAlfred Perlstein * A new session is established with each call to setnetconfig(), with a new 1878360efbdSAlfred Perlstein * handle being returned on each call. Previously established sessions remain 1888360efbdSAlfred Perlstein * active until endnetconfig() is called with that session's handle as an 1898360efbdSAlfred Perlstein * argument. 1908360efbdSAlfred Perlstein * 1918360efbdSAlfred Perlstein * setnetconfig() need *not* be called before a call to getnetconfigent(). 1928360efbdSAlfred Perlstein * setnetconfig() returns a NULL pointer on failure (for example, if 1938360efbdSAlfred Perlstein * the netconfig database is not present). 1948360efbdSAlfred Perlstein */ 1958360efbdSAlfred Perlstein void * 196587cf682SCraig Rodrigues setnetconfig(void) 1978360efbdSAlfred Perlstein { 1988360efbdSAlfred Perlstein struct netconfig_vars *nc_vars; 1998360efbdSAlfred Perlstein 2008360efbdSAlfred Perlstein if ((nc_vars = (struct netconfig_vars *)malloc(sizeof 2018360efbdSAlfred Perlstein (struct netconfig_vars))) == NULL) { 2028360efbdSAlfred Perlstein return(NULL); 2038360efbdSAlfred Perlstein } 2048360efbdSAlfred Perlstein 2058360efbdSAlfred Perlstein /* 2068360efbdSAlfred Perlstein * For multiple calls, i.e. nc_file is not NULL, we just return the 2078360efbdSAlfred Perlstein * handle without reopening the netconfig db. 2088360efbdSAlfred Perlstein */ 2095f4faf74SXin LI mutex_lock(&ni_lock); 2108360efbdSAlfred Perlstein ni.ref++; 2115f4faf74SXin LI mutex_unlock(&ni_lock); 2125f4faf74SXin LI 2135f4faf74SXin LI mutex_lock(&nc_file_lock); 2148360efbdSAlfred Perlstein if ((nc_file != NULL) || (nc_file = fopen(NETCONFIG, "r")) != NULL) { 2158360efbdSAlfred Perlstein nc_vars->valid = NC_VALID; 2168360efbdSAlfred Perlstein nc_vars->flag = 0; 2178360efbdSAlfred Perlstein nc_vars->nc_configs = ni.head; 2185f4faf74SXin LI mutex_unlock(&nc_file_lock); 2198360efbdSAlfred Perlstein return ((void *)nc_vars); 2208360efbdSAlfred Perlstein } 2215f4faf74SXin LI mutex_unlock(&nc_file_lock); 2225f4faf74SXin LI 2235f4faf74SXin LI mutex_lock(&ni_lock); 2248360efbdSAlfred Perlstein ni.ref--; 2255f4faf74SXin LI mutex_unlock(&ni_lock); 2265f4faf74SXin LI 2278360efbdSAlfred Perlstein nc_error = NC_NONETCONFIG; 2288360efbdSAlfred Perlstein free(nc_vars); 2298360efbdSAlfred Perlstein return (NULL); 2308360efbdSAlfred Perlstein } 2318360efbdSAlfred Perlstein 2328360efbdSAlfred Perlstein 2338360efbdSAlfred Perlstein /* 2348360efbdSAlfred Perlstein * When first called, getnetconfig() returns a pointer to the first entry in 2358360efbdSAlfred Perlstein * the netconfig database, formatted as a struct netconfig. On each subsequent 2368360efbdSAlfred Perlstein * call, getnetconfig() returns a pointer to the next entry in the database. 2378360efbdSAlfred Perlstein * getnetconfig() can thus be used to search the entire netconfig file. 2388360efbdSAlfred Perlstein * getnetconfig() returns NULL at end of file. 2398360efbdSAlfred Perlstein */ 2408360efbdSAlfred Perlstein 2418360efbdSAlfred Perlstein struct netconfig * 242587cf682SCraig Rodrigues getnetconfig(void *handlep) 2438360efbdSAlfred Perlstein { 2448360efbdSAlfred Perlstein struct netconfig_vars *ncp = (struct netconfig_vars *)handlep; 2458360efbdSAlfred Perlstein char *stringp; /* tmp string pointer */ 2468360efbdSAlfred Perlstein struct netconfig_list *list; 2478360efbdSAlfred Perlstein struct netconfig *np; 2485f4faf74SXin LI struct netconfig *result; 2498360efbdSAlfred Perlstein 2508360efbdSAlfred Perlstein /* 2518360efbdSAlfred Perlstein * Verify that handle is valid 2528360efbdSAlfred Perlstein */ 2535f4faf74SXin LI mutex_lock(&nc_file_lock); 2548360efbdSAlfred Perlstein if (ncp == NULL || nc_file == NULL) { 2558360efbdSAlfred Perlstein nc_error = NC_NOTINIT; 2565f4faf74SXin LI mutex_unlock(&nc_file_lock); 2578360efbdSAlfred Perlstein return (NULL); 2588360efbdSAlfred Perlstein } 2595f4faf74SXin LI mutex_unlock(&nc_file_lock); 2608360efbdSAlfred Perlstein 2618360efbdSAlfred Perlstein switch (ncp->valid) { 2628360efbdSAlfred Perlstein case NC_VALID: 2638360efbdSAlfred Perlstein /* 2648360efbdSAlfred Perlstein * If entry has already been read into the list, 2658360efbdSAlfred Perlstein * we return the entry in the linked list. 2668360efbdSAlfred Perlstein * If this is the first time call, check if there are any entries in 2678360efbdSAlfred Perlstein * linked list. If no entries, we need to read the netconfig db. 2688360efbdSAlfred Perlstein * If we have been here and the next entry is there, we just return 2698360efbdSAlfred Perlstein * it. 2708360efbdSAlfred Perlstein */ 2718360efbdSAlfred Perlstein if (ncp->flag == 0) { /* first time */ 2728360efbdSAlfred Perlstein ncp->flag = 1; 2735f4faf74SXin LI mutex_lock(&ni_lock); 2748360efbdSAlfred Perlstein ncp->nc_configs = ni.head; 2755f4faf74SXin LI mutex_unlock(&ni_lock); 2768360efbdSAlfred Perlstein if (ncp->nc_configs != NULL) /* entry already exist */ 2778360efbdSAlfred Perlstein return(ncp->nc_configs->ncp); 2788360efbdSAlfred Perlstein } 2798360efbdSAlfred Perlstein else if (ncp->nc_configs != NULL && ncp->nc_configs->next != NULL) { 2808360efbdSAlfred Perlstein ncp->nc_configs = ncp->nc_configs->next; 2818360efbdSAlfred Perlstein return(ncp->nc_configs->ncp); 2828360efbdSAlfred Perlstein } 2838360efbdSAlfred Perlstein 2848360efbdSAlfred Perlstein /* 2858360efbdSAlfred Perlstein * If we cannot find the entry in the list and is end of file, 2868360efbdSAlfred Perlstein * we give up. 2878360efbdSAlfred Perlstein */ 2885f4faf74SXin LI mutex_lock(&ni_lock); 2895f4faf74SXin LI if (ni.eof == 1) { 2905f4faf74SXin LI mutex_unlock(&ni_lock); 2915f4faf74SXin LI return(NULL); 2925f4faf74SXin LI } 2935f4faf74SXin LI mutex_unlock(&ni_lock); 2945f4faf74SXin LI 2958360efbdSAlfred Perlstein break; 2968360efbdSAlfred Perlstein default: 2978360efbdSAlfred Perlstein nc_error = NC_NOTINIT; 2988360efbdSAlfred Perlstein return (NULL); 2998360efbdSAlfred Perlstein } 3008360efbdSAlfred Perlstein 3018360efbdSAlfred Perlstein stringp = (char *) malloc(MAXNETCONFIGLINE); 3028360efbdSAlfred Perlstein if (stringp == NULL) 3038360efbdSAlfred Perlstein return (NULL); 3048360efbdSAlfred Perlstein 3058360efbdSAlfred Perlstein #ifdef MEM_CHK 3068360efbdSAlfred Perlstein if (malloc_verify() == 0) { 3078360efbdSAlfred Perlstein fprintf(stderr, "memory heap corrupted in getnetconfig\n"); 3088360efbdSAlfred Perlstein exit(1); 3098360efbdSAlfred Perlstein } 3108360efbdSAlfred Perlstein #endif 3118360efbdSAlfred Perlstein 3128360efbdSAlfred Perlstein /* 3138360efbdSAlfred Perlstein * Read a line from netconfig file. 3148360efbdSAlfred Perlstein */ 3155f4faf74SXin LI mutex_lock(&nc_file_lock); 3168360efbdSAlfred Perlstein do { 3178360efbdSAlfred Perlstein if (fgets(stringp, MAXNETCONFIGLINE, nc_file) == NULL) { 3188360efbdSAlfred Perlstein free(stringp); 3195f4faf74SXin LI mutex_lock(&ni_lock); 3208360efbdSAlfred Perlstein ni.eof = 1; 3215f4faf74SXin LI mutex_unlock(&ni_lock); 3225f4faf74SXin LI mutex_unlock(&nc_file_lock); 3238360efbdSAlfred Perlstein return (NULL); 3248360efbdSAlfred Perlstein } 3258360efbdSAlfred Perlstein } while (*stringp == '#'); 3265f4faf74SXin LI mutex_unlock(&nc_file_lock); 3278360efbdSAlfred Perlstein 3288360efbdSAlfred Perlstein list = (struct netconfig_list *) malloc(sizeof (struct netconfig_list)); 3298360efbdSAlfred Perlstein if (list == NULL) { 3308360efbdSAlfred Perlstein free(stringp); 3318360efbdSAlfred Perlstein return(NULL); 3328360efbdSAlfred Perlstein } 3338360efbdSAlfred Perlstein np = (struct netconfig *) malloc(sizeof (struct netconfig)); 3348360efbdSAlfred Perlstein if (np == NULL) { 3358360efbdSAlfred Perlstein free(stringp); 3368360efbdSAlfred Perlstein free(list); 3378360efbdSAlfred Perlstein return(NULL); 3388360efbdSAlfred Perlstein } 3398360efbdSAlfred Perlstein list->ncp = np; 3408360efbdSAlfred Perlstein list->next = NULL; 3418360efbdSAlfred Perlstein list->ncp->nc_lookups = NULL; 3428360efbdSAlfred Perlstein list->linep = stringp; 3438360efbdSAlfred Perlstein if (parse_ncp(stringp, list->ncp) == -1) { 3448360efbdSAlfred Perlstein free(stringp); 3458360efbdSAlfred Perlstein free(np); 3468360efbdSAlfred Perlstein free(list); 3478360efbdSAlfred Perlstein return (NULL); 3488360efbdSAlfred Perlstein } 3498360efbdSAlfred Perlstein else { 3508360efbdSAlfred Perlstein /* 3518360efbdSAlfred Perlstein * If this is the first entry that's been read, it is the head of 3528360efbdSAlfred Perlstein * the list. If not, put the entry at the end of the list. 3538360efbdSAlfred Perlstein * Reposition the current pointer of the handle to the last entry 3548360efbdSAlfred Perlstein * in the list. 3558360efbdSAlfred Perlstein */ 3565f4faf74SXin LI mutex_lock(&ni_lock); 3578360efbdSAlfred Perlstein if (ni.head == NULL) { /* first entry */ 3588360efbdSAlfred Perlstein ni.head = ni.tail = list; 3598360efbdSAlfred Perlstein } 3608360efbdSAlfred Perlstein else { 3618360efbdSAlfred Perlstein ni.tail->next = list; 3628360efbdSAlfred Perlstein ni.tail = ni.tail->next; 3638360efbdSAlfred Perlstein } 3648360efbdSAlfred Perlstein ncp->nc_configs = ni.tail; 3655f4faf74SXin LI result = ni.tail->ncp; 3665f4faf74SXin LI mutex_unlock(&ni_lock); 3675f4faf74SXin LI return(result); 3688360efbdSAlfred Perlstein } 3698360efbdSAlfred Perlstein } 3708360efbdSAlfred Perlstein 3718360efbdSAlfred Perlstein /* 3728360efbdSAlfred Perlstein * endnetconfig() may be called to "unbind" or "close" the netconfig database 3738360efbdSAlfred Perlstein * when processing is complete, releasing resources for reuse. endnetconfig() 3748360efbdSAlfred Perlstein * may not be called before setnetconfig(). endnetconfig() returns 0 on 3758360efbdSAlfred Perlstein * success and -1 on failure (for example, if setnetconfig() was not called 3768360efbdSAlfred Perlstein * previously). 3778360efbdSAlfred Perlstein */ 3788360efbdSAlfred Perlstein int 379587cf682SCraig Rodrigues endnetconfig(void *handlep) 3808360efbdSAlfred Perlstein { 3818360efbdSAlfred Perlstein struct netconfig_vars *nc_handlep = (struct netconfig_vars *)handlep; 3828360efbdSAlfred Perlstein 3838360efbdSAlfred Perlstein struct netconfig_list *q, *p; 3848360efbdSAlfred Perlstein 3858360efbdSAlfred Perlstein /* 3868360efbdSAlfred Perlstein * Verify that handle is valid 3878360efbdSAlfred Perlstein */ 3888360efbdSAlfred Perlstein if (nc_handlep == NULL || (nc_handlep->valid != NC_VALID && 3898360efbdSAlfred Perlstein nc_handlep->valid != NC_STORAGE)) { 3908360efbdSAlfred Perlstein nc_error = NC_NOTINIT; 3918360efbdSAlfred Perlstein return (-1); 3928360efbdSAlfred Perlstein } 3938360efbdSAlfred Perlstein 3948360efbdSAlfred Perlstein /* 3958360efbdSAlfred Perlstein * Return 0 if anyone still needs it. 3968360efbdSAlfred Perlstein */ 3978360efbdSAlfred Perlstein nc_handlep->valid = NC_INVALID; 3988360efbdSAlfred Perlstein nc_handlep->flag = 0; 3998360efbdSAlfred Perlstein nc_handlep->nc_configs = NULL; 4005f4faf74SXin LI mutex_lock(&ni_lock); 4018360efbdSAlfred Perlstein if (--ni.ref > 0) { 4025f4faf74SXin LI mutex_unlock(&ni_lock); 4038360efbdSAlfred Perlstein free(nc_handlep); 4048360efbdSAlfred Perlstein return(0); 4058360efbdSAlfred Perlstein } 4068360efbdSAlfred Perlstein 4078360efbdSAlfred Perlstein /* 4088360efbdSAlfred Perlstein * No one needs these entries anymore, then frees them. 4098360efbdSAlfred Perlstein * Make sure all info in netconfig_info structure has been reinitialized. 4108360efbdSAlfred Perlstein */ 4110c0349bfSGarrett Wollman q = ni.head; 4128360efbdSAlfred Perlstein ni.eof = ni.ref = 0; 4138360efbdSAlfred Perlstein ni.head = NULL; 4148360efbdSAlfred Perlstein ni.tail = NULL; 4155f4faf74SXin LI mutex_unlock(&ni_lock); 4165f4faf74SXin LI 4170c0349bfSGarrett Wollman while (q != NULL) { 4188360efbdSAlfred Perlstein p = q->next; 419c7f7fdd2SEnji Cooper free(q->ncp->nc_lookups); 4208360efbdSAlfred Perlstein free(q->ncp); 4218360efbdSAlfred Perlstein free(q->linep); 4228360efbdSAlfred Perlstein free(q); 4238360efbdSAlfred Perlstein q = p; 4248360efbdSAlfred Perlstein } 4258360efbdSAlfred Perlstein free(nc_handlep); 4268360efbdSAlfred Perlstein 4275f4faf74SXin LI mutex_lock(&nc_file_lock); 4288360efbdSAlfred Perlstein fclose(nc_file); 4298360efbdSAlfred Perlstein nc_file = NULL; 4305f4faf74SXin LI mutex_unlock(&nc_file_lock); 4315f4faf74SXin LI 4328360efbdSAlfred Perlstein return (0); 4338360efbdSAlfred Perlstein } 4348360efbdSAlfred Perlstein 4358360efbdSAlfred Perlstein /* 4368360efbdSAlfred Perlstein * getnetconfigent(netid) returns a pointer to the struct netconfig structure 4378360efbdSAlfred Perlstein * corresponding to netid. It returns NULL if netid is invalid (that is, does 4388360efbdSAlfred Perlstein * not name an entry in the netconfig database). It returns NULL and sets 4398360efbdSAlfred Perlstein * errno in case of failure (for example, if the netconfig database cannot be 4408360efbdSAlfred Perlstein * opened). 4418360efbdSAlfred Perlstein */ 4428360efbdSAlfred Perlstein 4438360efbdSAlfred Perlstein struct netconfig * 444587cf682SCraig Rodrigues getnetconfigent(const char *netid) 4458360efbdSAlfred Perlstein { 4468360efbdSAlfred Perlstein FILE *file; /* NETCONFIG db's file pointer */ 4478360efbdSAlfred Perlstein char *linep; /* holds current netconfig line */ 4488360efbdSAlfred Perlstein char *stringp; /* temporary string pointer */ 4498360efbdSAlfred Perlstein struct netconfig *ncp = NULL; /* returned value */ 4508360efbdSAlfred Perlstein struct netconfig_list *list; /* pointer to cache list */ 4518360efbdSAlfred Perlstein 452b3a38fe3SIan Dowse nc_error = NC_NOTFOUND; /* default error. */ 4538360efbdSAlfred Perlstein if (netid == NULL || strlen(netid) == 0) { 4548360efbdSAlfred Perlstein return (NULL); 4558360efbdSAlfred Perlstein } 4568360efbdSAlfred Perlstein 4578360efbdSAlfred Perlstein /* 4588360efbdSAlfred Perlstein * Look up table if the entries have already been read and parsed in 4598360efbdSAlfred Perlstein * getnetconfig(), then copy this entry into a buffer and return it. 4608360efbdSAlfred Perlstein * If we cannot find the entry in the current list and there are more 4618360efbdSAlfred Perlstein * entries in the netconfig db that has not been read, we then read the 4628360efbdSAlfred Perlstein * db and try find the match netid. 4638360efbdSAlfred Perlstein * If all the netconfig db has been read and placed into the list and 4648360efbdSAlfred Perlstein * there is no match for the netid, return NULL. 4658360efbdSAlfred Perlstein */ 4665f4faf74SXin LI mutex_lock(&ni_lock); 4678360efbdSAlfred Perlstein if (ni.head != NULL) { 4688360efbdSAlfred Perlstein for (list = ni.head; list; list = list->next) { 4698360efbdSAlfred Perlstein if (strcmp(list->ncp->nc_netid, netid) == 0) { 4705f4faf74SXin LI mutex_unlock(&ni_lock); 4718360efbdSAlfred Perlstein return(dup_ncp(list->ncp)); 4728360efbdSAlfred Perlstein } 4738360efbdSAlfred Perlstein } 4745f4faf74SXin LI if (ni.eof == 1) { /* that's all the entries */ 4755f4faf74SXin LI mutex_unlock(&ni_lock); 4768360efbdSAlfred Perlstein return(NULL); 4778360efbdSAlfred Perlstein } 4785f4faf74SXin LI } 4795f4faf74SXin LI mutex_unlock(&ni_lock); 4808360efbdSAlfred Perlstein 4818360efbdSAlfred Perlstein 4828360efbdSAlfred Perlstein if ((file = fopen(NETCONFIG, "r")) == NULL) { 483b3a38fe3SIan Dowse nc_error = NC_NONETCONFIG; 4848360efbdSAlfred Perlstein return (NULL); 4858360efbdSAlfred Perlstein } 4868360efbdSAlfred Perlstein 4878360efbdSAlfred Perlstein if ((linep = malloc(MAXNETCONFIGLINE)) == NULL) { 4888360efbdSAlfred Perlstein fclose(file); 489b3a38fe3SIan Dowse nc_error = NC_NOMEM; 4908360efbdSAlfred Perlstein return (NULL); 4918360efbdSAlfred Perlstein } 4928360efbdSAlfred Perlstein do { 4933c788545SMartin Blapp ptrdiff_t len; 4948360efbdSAlfred Perlstein char *tmpp; /* tmp string pointer */ 4958360efbdSAlfred Perlstein 4968360efbdSAlfred Perlstein do { 4978360efbdSAlfred Perlstein if ((stringp = fgets(linep, MAXNETCONFIGLINE, file)) == NULL) { 4988360efbdSAlfred Perlstein break; 4998360efbdSAlfred Perlstein } 5008360efbdSAlfred Perlstein } while (*stringp == '#'); 5018360efbdSAlfred Perlstein if (stringp == NULL) { /* eof */ 5028360efbdSAlfred Perlstein break; 5038360efbdSAlfred Perlstein } 5048360efbdSAlfred Perlstein if ((tmpp = strpbrk(stringp, "\t ")) == NULL) { /* can't parse file */ 5058360efbdSAlfred Perlstein nc_error = NC_BADFILE; 5068360efbdSAlfred Perlstein break; 5078360efbdSAlfred Perlstein } 5083c788545SMartin Blapp if (strlen(netid) == (size_t) (len = tmpp - stringp) && /* a match */ 5098360efbdSAlfred Perlstein strncmp(stringp, netid, (size_t)len) == 0) { 5108360efbdSAlfred Perlstein if ((ncp = (struct netconfig *) 5118360efbdSAlfred Perlstein malloc(sizeof (struct netconfig))) == NULL) { 5128360efbdSAlfred Perlstein break; 5138360efbdSAlfred Perlstein } 5148360efbdSAlfred Perlstein ncp->nc_lookups = NULL; 5158360efbdSAlfred Perlstein if (parse_ncp(linep, ncp) == -1) { 5168360efbdSAlfred Perlstein free(ncp); 5178360efbdSAlfred Perlstein ncp = NULL; 5188360efbdSAlfred Perlstein } 5198360efbdSAlfred Perlstein break; 5208360efbdSAlfred Perlstein } 5218360efbdSAlfred Perlstein } while (stringp != NULL); 5228360efbdSAlfred Perlstein if (ncp == NULL) { 5238360efbdSAlfred Perlstein free(linep); 5248360efbdSAlfred Perlstein } 5258360efbdSAlfred Perlstein fclose(file); 5268360efbdSAlfred Perlstein return(ncp); 5278360efbdSAlfred Perlstein } 5288360efbdSAlfred Perlstein 5298360efbdSAlfred Perlstein /* 5308360efbdSAlfred Perlstein * freenetconfigent(netconfigp) frees the netconfig structure pointed to by 5318360efbdSAlfred Perlstein * netconfigp (previously returned by getnetconfigent()). 5328360efbdSAlfred Perlstein */ 5338360efbdSAlfred Perlstein 5348360efbdSAlfred Perlstein void 535587cf682SCraig Rodrigues freenetconfigent(struct netconfig *netconfigp) 5368360efbdSAlfred Perlstein { 5378360efbdSAlfred Perlstein if (netconfigp != NULL) { 5388360efbdSAlfred Perlstein free(netconfigp->nc_netid); /* holds all netconfigp's strings */ 5398360efbdSAlfred Perlstein free(netconfigp->nc_lookups); 5408360efbdSAlfred Perlstein free(netconfigp); 5418360efbdSAlfred Perlstein } 5428360efbdSAlfred Perlstein return; 5438360efbdSAlfred Perlstein } 5448360efbdSAlfred Perlstein 5458360efbdSAlfred Perlstein /* 5468360efbdSAlfred Perlstein * Parse line and stuff it in a struct netconfig 5478360efbdSAlfred Perlstein * Typical line might look like: 5488360efbdSAlfred Perlstein * udp tpi_cots vb inet udp /dev/udp /usr/lib/ip.so,/usr/local/ip.so 5498360efbdSAlfred Perlstein * 5508360efbdSAlfred Perlstein * We return -1 if any of the tokens don't parse, or malloc fails. 5518360efbdSAlfred Perlstein * 5528360efbdSAlfred Perlstein * Note that we modify stringp (putting NULLs after tokens) and 5538360efbdSAlfred Perlstein * we set the ncp's string field pointers to point to these tokens within 5548360efbdSAlfred Perlstein * stringp. 555587cf682SCraig Rodrigues * 556587cf682SCraig Rodrigues * stringp - string to parse 557587cf682SCraig Rodrigues * ncp - where to put results 5588360efbdSAlfred Perlstein */ 5598360efbdSAlfred Perlstein 5608360efbdSAlfred Perlstein static int 561587cf682SCraig Rodrigues parse_ncp(char *stringp, struct netconfig *ncp) 5628360efbdSAlfred Perlstein { 5638360efbdSAlfred Perlstein char *tokenp; /* for processing tokens */ 5648360efbdSAlfred Perlstein char *lasts; 565330e445cSMatteo Riondato char **nc_lookups; 5668360efbdSAlfred Perlstein 5678360efbdSAlfred Perlstein nc_error = NC_BADFILE; /* nearly anything that breaks is for this reason */ 5688360efbdSAlfred Perlstein stringp[strlen(stringp)-1] = '\0'; /* get rid of newline */ 5698360efbdSAlfred Perlstein /* netid */ 5708360efbdSAlfred Perlstein if ((ncp->nc_netid = strtok_r(stringp, "\t ", &lasts)) == NULL) { 5718360efbdSAlfred Perlstein return (-1); 5728360efbdSAlfred Perlstein } 5738360efbdSAlfred Perlstein 5748360efbdSAlfred Perlstein /* semantics */ 5758360efbdSAlfred Perlstein if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) { 5768360efbdSAlfred Perlstein return (-1); 5778360efbdSAlfred Perlstein } 5788360efbdSAlfred Perlstein if (strcmp(tokenp, NC_TPI_COTS_ORD_S) == 0) 5798360efbdSAlfred Perlstein ncp->nc_semantics = NC_TPI_COTS_ORD; 5808360efbdSAlfred Perlstein else if (strcmp(tokenp, NC_TPI_COTS_S) == 0) 5818360efbdSAlfred Perlstein ncp->nc_semantics = NC_TPI_COTS; 5828360efbdSAlfred Perlstein else if (strcmp(tokenp, NC_TPI_CLTS_S) == 0) 5838360efbdSAlfred Perlstein ncp->nc_semantics = NC_TPI_CLTS; 5848360efbdSAlfred Perlstein else if (strcmp(tokenp, NC_TPI_RAW_S) == 0) 5858360efbdSAlfred Perlstein ncp->nc_semantics = NC_TPI_RAW; 5868360efbdSAlfred Perlstein else 5878360efbdSAlfred Perlstein return (-1); 5888360efbdSAlfred Perlstein 5898360efbdSAlfred Perlstein /* flags */ 5908360efbdSAlfred Perlstein if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) { 5918360efbdSAlfred Perlstein return (-1); 5928360efbdSAlfred Perlstein } 5938360efbdSAlfred Perlstein for (ncp->nc_flag = NC_NOFLAG; *tokenp != '\0'; 5948360efbdSAlfred Perlstein tokenp++) { 5958360efbdSAlfred Perlstein switch (*tokenp) { 5968360efbdSAlfred Perlstein case NC_NOFLAG_C: 5978360efbdSAlfred Perlstein break; 5988360efbdSAlfred Perlstein case NC_VISIBLE_C: 5998360efbdSAlfred Perlstein ncp->nc_flag |= NC_VISIBLE; 6008360efbdSAlfred Perlstein break; 6018360efbdSAlfred Perlstein case NC_BROADCAST_C: 6028360efbdSAlfred Perlstein ncp->nc_flag |= NC_BROADCAST; 6038360efbdSAlfred Perlstein break; 6048360efbdSAlfred Perlstein default: 6058360efbdSAlfred Perlstein return (-1); 6068360efbdSAlfred Perlstein } 6078360efbdSAlfred Perlstein } 6088360efbdSAlfred Perlstein /* protocol family */ 6098360efbdSAlfred Perlstein if ((ncp->nc_protofmly = strtok_r(NULL, "\t ", &lasts)) == NULL) { 6108360efbdSAlfred Perlstein return (-1); 6118360efbdSAlfred Perlstein } 6128360efbdSAlfred Perlstein /* protocol name */ 6138360efbdSAlfred Perlstein if ((ncp->nc_proto = strtok_r(NULL, "\t ", &lasts)) == NULL) { 6148360efbdSAlfred Perlstein return (-1); 6158360efbdSAlfred Perlstein } 6168360efbdSAlfred Perlstein /* network device */ 6178360efbdSAlfred Perlstein if ((ncp->nc_device = strtok_r(NULL, "\t ", &lasts)) == NULL) { 6188360efbdSAlfred Perlstein return (-1); 6198360efbdSAlfred Perlstein } 6208360efbdSAlfred Perlstein if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) { 6218360efbdSAlfred Perlstein return (-1); 6228360efbdSAlfred Perlstein } 6238360efbdSAlfred Perlstein if (strcmp(tokenp, NC_NOLOOKUP) == 0) { 6248360efbdSAlfred Perlstein ncp->nc_nlookups = 0; 6258360efbdSAlfred Perlstein ncp->nc_lookups = NULL; 6268360efbdSAlfred Perlstein } else { 6278360efbdSAlfred Perlstein char *cp; /* tmp string */ 6288360efbdSAlfred Perlstein 629c7f7fdd2SEnji Cooper free(ncp->nc_lookups); /* from last visit */ 630330e445cSMatteo Riondato ncp->nc_lookups = NULL; 6318360efbdSAlfred Perlstein ncp->nc_nlookups = 0; 6328360efbdSAlfred Perlstein while ((cp = tokenp) != NULL) { 633*9f36610fSPedro F. Giffuni if ((nc_lookups = reallocarray(ncp->nc_lookups, 634*9f36610fSPedro F. Giffuni ncp->nc_nlookups + 1, sizeof(*ncp->nc_lookups))) == NULL) { 635330e445cSMatteo Riondato free(ncp->nc_lookups); 636330e445cSMatteo Riondato ncp->nc_lookups = NULL; 637330e445cSMatteo Riondato return (-1); 638330e445cSMatteo Riondato } 6398360efbdSAlfred Perlstein tokenp = _get_next_token(cp, ','); 640330e445cSMatteo Riondato ncp->nc_lookups = nc_lookups; 641330e445cSMatteo Riondato ncp->nc_lookups[ncp->nc_nlookups++] = cp; 6428360efbdSAlfred Perlstein } 6438360efbdSAlfred Perlstein } 6448360efbdSAlfred Perlstein return (0); 6458360efbdSAlfred Perlstein } 6468360efbdSAlfred Perlstein 6478360efbdSAlfred Perlstein 6488360efbdSAlfred Perlstein /* 6498360efbdSAlfred Perlstein * Returns a string describing the reason for failure. 6508360efbdSAlfred Perlstein */ 6518360efbdSAlfred Perlstein char * 652587cf682SCraig Rodrigues nc_sperror(void) 6538360efbdSAlfred Perlstein { 6548360efbdSAlfred Perlstein const char *message; 6558360efbdSAlfred Perlstein 6568360efbdSAlfred Perlstein switch(nc_error) { 6578360efbdSAlfred Perlstein case NC_NONETCONFIG: 6588360efbdSAlfred Perlstein message = _nc_errors[0]; 6598360efbdSAlfred Perlstein break; 6608360efbdSAlfred Perlstein case NC_NOMEM: 6618360efbdSAlfred Perlstein message = _nc_errors[1]; 6628360efbdSAlfred Perlstein break; 6638360efbdSAlfred Perlstein case NC_NOTINIT: 6648360efbdSAlfred Perlstein message = _nc_errors[2]; 6658360efbdSAlfred Perlstein break; 6668360efbdSAlfred Perlstein case NC_BADFILE: 6678360efbdSAlfred Perlstein message = _nc_errors[3]; 6688360efbdSAlfred Perlstein break; 669b3a38fe3SIan Dowse case NC_NOTFOUND: 670b3a38fe3SIan Dowse message = _nc_errors[4]; 671b3a38fe3SIan Dowse break; 6728360efbdSAlfred Perlstein default: 6738360efbdSAlfred Perlstein message = "Unknown network selection error"; 6748360efbdSAlfred Perlstein } 6758360efbdSAlfred Perlstein /* LINTED const castaway */ 6768360efbdSAlfred Perlstein return ((char *)message); 6778360efbdSAlfred Perlstein } 6788360efbdSAlfred Perlstein 6798360efbdSAlfred Perlstein /* 6808360efbdSAlfred Perlstein * Prints a message onto standard error describing the reason for failure. 6818360efbdSAlfred Perlstein */ 6828360efbdSAlfred Perlstein void 683587cf682SCraig Rodrigues nc_perror(const char *s) 6848360efbdSAlfred Perlstein { 685b3a38fe3SIan Dowse fprintf(stderr, "%s: %s\n", s, nc_sperror()); 6868360efbdSAlfred Perlstein } 6878360efbdSAlfred Perlstein 6888360efbdSAlfred Perlstein /* 6898360efbdSAlfred Perlstein * Duplicates the matched netconfig buffer. 6908360efbdSAlfred Perlstein */ 6918360efbdSAlfred Perlstein static struct netconfig * 692587cf682SCraig Rodrigues dup_ncp(struct netconfig *ncp) 6938360efbdSAlfred Perlstein { 6948360efbdSAlfred Perlstein struct netconfig *p; 6958f5cc690SEnji Cooper char *tmp, *tmp2; 6963c788545SMartin Blapp u_int i; 6978360efbdSAlfred Perlstein 6988360efbdSAlfred Perlstein if ((tmp=malloc(MAXNETCONFIGLINE)) == NULL) 6998360efbdSAlfred Perlstein return(NULL); 7008360efbdSAlfred Perlstein if ((p=(struct netconfig *)malloc(sizeof(struct netconfig))) == NULL) { 7018360efbdSAlfred Perlstein free(tmp); 7028360efbdSAlfred Perlstein return(NULL); 7038360efbdSAlfred Perlstein } 7048f5cc690SEnji Cooper tmp2 = tmp; 7058360efbdSAlfred Perlstein /* 7068360efbdSAlfred Perlstein * First we dup all the data from matched netconfig buffer. Then we 7078360efbdSAlfred Perlstein * adjust some of the member pointer to a pre-allocated buffer where 7088360efbdSAlfred Perlstein * contains part of the data. 7098360efbdSAlfred Perlstein * To follow the convention used in parse_ncp(), we store all the 7103c788545SMartin Blapp * necessary information in the pre-allocated buffer and let each 7118360efbdSAlfred Perlstein * of the netconfig char pointer member point to the right address 7128360efbdSAlfred Perlstein * in the buffer. 7138360efbdSAlfred Perlstein */ 7148360efbdSAlfred Perlstein *p = *ncp; 7158360efbdSAlfred Perlstein p->nc_netid = (char *)strcpy(tmp,ncp->nc_netid); 71616fc3635SMark Murray tmp = strchr(tmp, '\0') + 1; 7178360efbdSAlfred Perlstein p->nc_protofmly = (char *)strcpy(tmp,ncp->nc_protofmly); 71816fc3635SMark Murray tmp = strchr(tmp, '\0') + 1; 7198360efbdSAlfred Perlstein p->nc_proto = (char *)strcpy(tmp,ncp->nc_proto); 72016fc3635SMark Murray tmp = strchr(tmp, '\0') + 1; 7218360efbdSAlfred Perlstein p->nc_device = (char *)strcpy(tmp,ncp->nc_device); 7228360efbdSAlfred Perlstein p->nc_lookups = (char **)malloc((size_t)(p->nc_nlookups+1) * sizeof(char *)); 7238360efbdSAlfred Perlstein if (p->nc_lookups == NULL) { 7248360efbdSAlfred Perlstein free(p->nc_netid); 725b0718451SMartin Blapp free(p); 7268f5cc690SEnji Cooper free(tmp2); 7278360efbdSAlfred Perlstein return(NULL); 7288360efbdSAlfred Perlstein } 7298360efbdSAlfred Perlstein for (i=0; i < p->nc_nlookups; i++) { 73016fc3635SMark Murray tmp = strchr(tmp, '\0') + 1; 7318360efbdSAlfred Perlstein p->nc_lookups[i] = (char *)strcpy(tmp,ncp->nc_lookups[i]); 7328360efbdSAlfred Perlstein } 7338360efbdSAlfred Perlstein return(p); 7348360efbdSAlfred Perlstein } 735