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 */ 1338360efbdSAlfred Perlstein static struct netconfig_info ni = { 0, 0, NULL, NULL}; 1348360efbdSAlfred Perlstein 1358360efbdSAlfred Perlstein #define MAXNETCONFIGLINE 1000 1368360efbdSAlfred Perlstein 1378360efbdSAlfred Perlstein static int * 1388360efbdSAlfred Perlstein __nc_error() 1398360efbdSAlfred Perlstein { 140b3a38fe3SIan Dowse static pthread_mutex_t nc_lock = PTHREAD_MUTEX_INITIALIZER; 1418360efbdSAlfred Perlstein static thread_key_t nc_key = 0; 1428360efbdSAlfred Perlstein static int nc_error = 0; 143b3a38fe3SIan Dowse int error, *nc_addr; 1448360efbdSAlfred Perlstein 145b3a38fe3SIan Dowse /* 146b3a38fe3SIan Dowse * Use the static `nc_error' if we are the main thread 147b3a38fe3SIan Dowse * (including non-threaded programs), or if an allocation 148b3a38fe3SIan Dowse * fails. 149b3a38fe3SIan Dowse */ 150b3a38fe3SIan Dowse if (thr_main()) 151b3a38fe3SIan Dowse return (&nc_error); 152b3a38fe3SIan Dowse if (nc_key == 0) { 153b3a38fe3SIan Dowse error = 0; 1548360efbdSAlfred Perlstein mutex_lock(&nc_lock); 155b3a38fe3SIan Dowse if (nc_key == 0) 156b3a38fe3SIan Dowse error = thr_keycreate(&nc_key, free); 1578360efbdSAlfred Perlstein mutex_unlock(&nc_lock); 158b3a38fe3SIan Dowse if (error) 159b3a38fe3SIan Dowse return (&nc_error); 1608360efbdSAlfred Perlstein } 161b3a38fe3SIan Dowse if ((nc_addr = (int *)thr_getspecific(nc_key)) == NULL) { 1628360efbdSAlfred Perlstein nc_addr = (int *)malloc(sizeof (int)); 1638360efbdSAlfred Perlstein if (thr_setspecific(nc_key, (void *) nc_addr) != 0) { 1648360efbdSAlfred Perlstein if (nc_addr) 1658360efbdSAlfred Perlstein free(nc_addr); 166b3a38fe3SIan Dowse return (&nc_error); 1678360efbdSAlfred Perlstein } 1688360efbdSAlfred Perlstein *nc_addr = 0; 1698360efbdSAlfred Perlstein } 170b3a38fe3SIan Dowse return (nc_addr); 1718360efbdSAlfred Perlstein } 1728360efbdSAlfred Perlstein 1738360efbdSAlfred Perlstein #define nc_error (*(__nc_error())) 1748360efbdSAlfred Perlstein /* 1758360efbdSAlfred Perlstein * A call to setnetconfig() establishes a /etc/netconfig "session". A session 1768360efbdSAlfred Perlstein * "handle" is returned on a successful call. At the start of a session (after 1778360efbdSAlfred Perlstein * a call to setnetconfig()) searches through the /etc/netconfig database will 1788360efbdSAlfred Perlstein * proceed from the start of the file. The session handle must be passed to 1798360efbdSAlfred Perlstein * getnetconfig() to parse the file. Each call to getnetconfig() using the 1808360efbdSAlfred Perlstein * current handle will process one subsequent entry in /etc/netconfig. 1818360efbdSAlfred Perlstein * setnetconfig() must be called before the first call to getnetconfig(). 1828360efbdSAlfred Perlstein * (Handles are used to allow for nested calls to setnetpath()). 1838360efbdSAlfred Perlstein * 1848360efbdSAlfred Perlstein * A new session is established with each call to setnetconfig(), with a new 1858360efbdSAlfred Perlstein * handle being returned on each call. Previously established sessions remain 1868360efbdSAlfred Perlstein * active until endnetconfig() is called with that session's handle as an 1878360efbdSAlfred Perlstein * argument. 1888360efbdSAlfred Perlstein * 1898360efbdSAlfred Perlstein * setnetconfig() need *not* be called before a call to getnetconfigent(). 1908360efbdSAlfred Perlstein * setnetconfig() returns a NULL pointer on failure (for example, if 1918360efbdSAlfred Perlstein * the netconfig database is not present). 1928360efbdSAlfred Perlstein */ 1938360efbdSAlfred Perlstein void * 1948360efbdSAlfred Perlstein setnetconfig() 1958360efbdSAlfred Perlstein { 1968360efbdSAlfred Perlstein struct netconfig_vars *nc_vars; 1978360efbdSAlfred Perlstein 1988360efbdSAlfred Perlstein if ((nc_vars = (struct netconfig_vars *)malloc(sizeof 1998360efbdSAlfred Perlstein (struct netconfig_vars))) == NULL) { 2008360efbdSAlfred Perlstein return(NULL); 2018360efbdSAlfred Perlstein } 2028360efbdSAlfred Perlstein 2038360efbdSAlfred Perlstein /* 2048360efbdSAlfred Perlstein * For multiple calls, i.e. nc_file is not NULL, we just return the 2058360efbdSAlfred Perlstein * handle without reopening the netconfig db. 2068360efbdSAlfred Perlstein */ 2078360efbdSAlfred Perlstein ni.ref++; 2088360efbdSAlfred Perlstein if ((nc_file != NULL) || (nc_file = fopen(NETCONFIG, "r")) != NULL) { 2098360efbdSAlfred Perlstein nc_vars->valid = NC_VALID; 2108360efbdSAlfred Perlstein nc_vars->flag = 0; 2118360efbdSAlfred Perlstein nc_vars->nc_configs = ni.head; 2128360efbdSAlfred Perlstein return ((void *)nc_vars); 2138360efbdSAlfred Perlstein } 2148360efbdSAlfred Perlstein ni.ref--; 2158360efbdSAlfred Perlstein nc_error = NC_NONETCONFIG; 2168360efbdSAlfred Perlstein free(nc_vars); 2178360efbdSAlfred Perlstein return (NULL); 2188360efbdSAlfred Perlstein } 2198360efbdSAlfred Perlstein 2208360efbdSAlfred Perlstein 2218360efbdSAlfred Perlstein /* 2228360efbdSAlfred Perlstein * When first called, getnetconfig() returns a pointer to the first entry in 2238360efbdSAlfred Perlstein * the netconfig database, formatted as a struct netconfig. On each subsequent 2248360efbdSAlfred Perlstein * call, getnetconfig() returns a pointer to the next entry in the database. 2258360efbdSAlfred Perlstein * getnetconfig() can thus be used to search the entire netconfig file. 2268360efbdSAlfred Perlstein * getnetconfig() returns NULL at end of file. 2278360efbdSAlfred Perlstein */ 2288360efbdSAlfred Perlstein 2298360efbdSAlfred Perlstein struct netconfig * 2308360efbdSAlfred Perlstein getnetconfig(handlep) 2318360efbdSAlfred Perlstein void *handlep; 2328360efbdSAlfred Perlstein { 2338360efbdSAlfred Perlstein struct netconfig_vars *ncp = (struct netconfig_vars *)handlep; 2348360efbdSAlfred Perlstein char *stringp; /* tmp string pointer */ 2358360efbdSAlfred Perlstein struct netconfig_list *list; 2368360efbdSAlfred Perlstein struct netconfig *np; 2378360efbdSAlfred Perlstein 2388360efbdSAlfred Perlstein /* 2398360efbdSAlfred Perlstein * Verify that handle is valid 2408360efbdSAlfred Perlstein */ 2418360efbdSAlfred Perlstein if (ncp == NULL || nc_file == NULL) { 2428360efbdSAlfred Perlstein nc_error = NC_NOTINIT; 2438360efbdSAlfred Perlstein return (NULL); 2448360efbdSAlfred Perlstein } 2458360efbdSAlfred Perlstein 2468360efbdSAlfred Perlstein switch (ncp->valid) { 2478360efbdSAlfred Perlstein case NC_VALID: 2488360efbdSAlfred Perlstein /* 2498360efbdSAlfred Perlstein * If entry has already been read into the list, 2508360efbdSAlfred Perlstein * we return the entry in the linked list. 2518360efbdSAlfred Perlstein * If this is the first time call, check if there are any entries in 2528360efbdSAlfred Perlstein * linked list. If no entries, we need to read the netconfig db. 2538360efbdSAlfred Perlstein * If we have been here and the next entry is there, we just return 2548360efbdSAlfred Perlstein * it. 2558360efbdSAlfred Perlstein */ 2568360efbdSAlfred Perlstein if (ncp->flag == 0) { /* first time */ 2578360efbdSAlfred Perlstein ncp->flag = 1; 2588360efbdSAlfred Perlstein ncp->nc_configs = ni.head; 2598360efbdSAlfred Perlstein if (ncp->nc_configs != NULL) /* entry already exist */ 2608360efbdSAlfred Perlstein return(ncp->nc_configs->ncp); 2618360efbdSAlfred Perlstein } 2628360efbdSAlfred Perlstein else if (ncp->nc_configs != NULL && ncp->nc_configs->next != NULL) { 2638360efbdSAlfred Perlstein ncp->nc_configs = ncp->nc_configs->next; 2648360efbdSAlfred Perlstein return(ncp->nc_configs->ncp); 2658360efbdSAlfred Perlstein } 2668360efbdSAlfred Perlstein 2678360efbdSAlfred Perlstein /* 2688360efbdSAlfred Perlstein * If we cannot find the entry in the list and is end of file, 2698360efbdSAlfred Perlstein * we give up. 2708360efbdSAlfred Perlstein */ 2718360efbdSAlfred Perlstein if (ni.eof == 1) return(NULL); 2728360efbdSAlfred Perlstein break; 2738360efbdSAlfred Perlstein default: 2748360efbdSAlfred Perlstein nc_error = NC_NOTINIT; 2758360efbdSAlfred Perlstein return (NULL); 2768360efbdSAlfred Perlstein } 2778360efbdSAlfred Perlstein 2788360efbdSAlfred Perlstein stringp = (char *) malloc(MAXNETCONFIGLINE); 2798360efbdSAlfred Perlstein if (stringp == NULL) 2808360efbdSAlfred Perlstein return (NULL); 2818360efbdSAlfred Perlstein 2828360efbdSAlfred Perlstein #ifdef MEM_CHK 2838360efbdSAlfred Perlstein if (malloc_verify() == 0) { 2848360efbdSAlfred Perlstein fprintf(stderr, "memory heap corrupted in getnetconfig\n"); 2858360efbdSAlfred Perlstein exit(1); 2868360efbdSAlfred Perlstein } 2878360efbdSAlfred Perlstein #endif 2888360efbdSAlfred Perlstein 2898360efbdSAlfred Perlstein /* 2908360efbdSAlfred Perlstein * Read a line from netconfig file. 2918360efbdSAlfred Perlstein */ 2928360efbdSAlfred Perlstein do { 2938360efbdSAlfred Perlstein if (fgets(stringp, MAXNETCONFIGLINE, nc_file) == NULL) { 2948360efbdSAlfred Perlstein free(stringp); 2958360efbdSAlfred Perlstein ni.eof = 1; 2968360efbdSAlfred Perlstein return (NULL); 2978360efbdSAlfred Perlstein } 2988360efbdSAlfred Perlstein } while (*stringp == '#'); 2998360efbdSAlfred Perlstein 3008360efbdSAlfred Perlstein list = (struct netconfig_list *) malloc(sizeof (struct netconfig_list)); 3018360efbdSAlfred Perlstein if (list == NULL) { 3028360efbdSAlfred Perlstein free(stringp); 3038360efbdSAlfred Perlstein return(NULL); 3048360efbdSAlfred Perlstein } 3058360efbdSAlfred Perlstein np = (struct netconfig *) malloc(sizeof (struct netconfig)); 3068360efbdSAlfred Perlstein if (np == NULL) { 3078360efbdSAlfred Perlstein free(stringp); 3088360efbdSAlfred Perlstein free(list); 3098360efbdSAlfred Perlstein return(NULL); 3108360efbdSAlfred Perlstein } 3118360efbdSAlfred Perlstein list->ncp = np; 3128360efbdSAlfred Perlstein list->next = NULL; 3138360efbdSAlfred Perlstein list->ncp->nc_lookups = NULL; 3148360efbdSAlfred Perlstein list->linep = stringp; 3158360efbdSAlfred Perlstein if (parse_ncp(stringp, list->ncp) == -1) { 3168360efbdSAlfred Perlstein free(stringp); 3178360efbdSAlfred Perlstein free(np); 3188360efbdSAlfred Perlstein free(list); 3198360efbdSAlfred Perlstein return (NULL); 3208360efbdSAlfred Perlstein } 3218360efbdSAlfred Perlstein else { 3228360efbdSAlfred Perlstein /* 3238360efbdSAlfred Perlstein * If this is the first entry that's been read, it is the head of 3248360efbdSAlfred Perlstein * the list. If not, put the entry at the end of the list. 3258360efbdSAlfred Perlstein * Reposition the current pointer of the handle to the last entry 3268360efbdSAlfred Perlstein * in the list. 3278360efbdSAlfred Perlstein */ 3288360efbdSAlfred Perlstein if (ni.head == NULL) { /* first entry */ 3298360efbdSAlfred Perlstein ni.head = ni.tail = list; 3308360efbdSAlfred Perlstein } 3318360efbdSAlfred Perlstein else { 3328360efbdSAlfred Perlstein ni.tail->next = list; 3338360efbdSAlfred Perlstein ni.tail = ni.tail->next; 3348360efbdSAlfred Perlstein } 3358360efbdSAlfred Perlstein ncp->nc_configs = ni.tail; 3368360efbdSAlfred Perlstein return(ni.tail->ncp); 3378360efbdSAlfred Perlstein } 3388360efbdSAlfred Perlstein } 3398360efbdSAlfred Perlstein 3408360efbdSAlfred Perlstein /* 3418360efbdSAlfred Perlstein * endnetconfig() may be called to "unbind" or "close" the netconfig database 3428360efbdSAlfred Perlstein * when processing is complete, releasing resources for reuse. endnetconfig() 3438360efbdSAlfred Perlstein * may not be called before setnetconfig(). endnetconfig() returns 0 on 3448360efbdSAlfred Perlstein * success and -1 on failure (for example, if setnetconfig() was not called 3458360efbdSAlfred Perlstein * previously). 3468360efbdSAlfred Perlstein */ 3478360efbdSAlfred Perlstein int 3488360efbdSAlfred Perlstein endnetconfig(handlep) 3498360efbdSAlfred Perlstein void *handlep; 3508360efbdSAlfred Perlstein { 3518360efbdSAlfred Perlstein struct netconfig_vars *nc_handlep = (struct netconfig_vars *)handlep; 3528360efbdSAlfred Perlstein 3538360efbdSAlfred Perlstein struct netconfig_list *q, *p; 3548360efbdSAlfred Perlstein 3558360efbdSAlfred Perlstein /* 3568360efbdSAlfred Perlstein * Verify that handle is valid 3578360efbdSAlfred Perlstein */ 3588360efbdSAlfred Perlstein if (nc_handlep == NULL || (nc_handlep->valid != NC_VALID && 3598360efbdSAlfred Perlstein nc_handlep->valid != NC_STORAGE)) { 3608360efbdSAlfred Perlstein nc_error = NC_NOTINIT; 3618360efbdSAlfred Perlstein return (-1); 3628360efbdSAlfred Perlstein } 3638360efbdSAlfred Perlstein 3648360efbdSAlfred Perlstein /* 3658360efbdSAlfred Perlstein * Return 0 if anyone still needs it. 3668360efbdSAlfred Perlstein */ 3678360efbdSAlfred Perlstein nc_handlep->valid = NC_INVALID; 3688360efbdSAlfred Perlstein nc_handlep->flag = 0; 3698360efbdSAlfred Perlstein nc_handlep->nc_configs = NULL; 3708360efbdSAlfred Perlstein if (--ni.ref > 0) { 3718360efbdSAlfred Perlstein free(nc_handlep); 3728360efbdSAlfred Perlstein return(0); 3738360efbdSAlfred Perlstein } 3748360efbdSAlfred Perlstein 3758360efbdSAlfred Perlstein /* 3768360efbdSAlfred Perlstein * Noone needs these entries anymore, then frees them. 3778360efbdSAlfred Perlstein * Make sure all info in netconfig_info structure has been reinitialized. 3788360efbdSAlfred Perlstein */ 3798360efbdSAlfred Perlstein q = p = ni.head; 3808360efbdSAlfred Perlstein ni.eof = ni.ref = 0; 3818360efbdSAlfred Perlstein ni.head = NULL; 3828360efbdSAlfred Perlstein ni.tail = NULL; 3838360efbdSAlfred Perlstein while (q) { 3848360efbdSAlfred Perlstein p = q->next; 3858360efbdSAlfred Perlstein if (q->ncp->nc_lookups != NULL) free(q->ncp->nc_lookups); 3868360efbdSAlfred Perlstein free(q->ncp); 3878360efbdSAlfred Perlstein free(q->linep); 3888360efbdSAlfred Perlstein free(q); 3898360efbdSAlfred Perlstein q = p; 3908360efbdSAlfred Perlstein } 3918360efbdSAlfred Perlstein free(nc_handlep); 3928360efbdSAlfred Perlstein 3938360efbdSAlfred Perlstein fclose(nc_file); 3948360efbdSAlfred Perlstein nc_file = NULL; 3958360efbdSAlfred Perlstein return (0); 3968360efbdSAlfred Perlstein } 3978360efbdSAlfred Perlstein 3988360efbdSAlfred Perlstein /* 3998360efbdSAlfred Perlstein * getnetconfigent(netid) returns a pointer to the struct netconfig structure 4008360efbdSAlfred Perlstein * corresponding to netid. It returns NULL if netid is invalid (that is, does 4018360efbdSAlfred Perlstein * not name an entry in the netconfig database). It returns NULL and sets 4028360efbdSAlfred Perlstein * errno in case of failure (for example, if the netconfig database cannot be 4038360efbdSAlfred Perlstein * opened). 4048360efbdSAlfred Perlstein */ 4058360efbdSAlfred Perlstein 4068360efbdSAlfred Perlstein struct netconfig * 4078360efbdSAlfred Perlstein getnetconfigent(netid) 40840c10ffdSAlfred Perlstein const char *netid; 4098360efbdSAlfred Perlstein { 4108360efbdSAlfred Perlstein FILE *file; /* NETCONFIG db's file pointer */ 4118360efbdSAlfred Perlstein char *linep; /* holds current netconfig line */ 4128360efbdSAlfred Perlstein char *stringp; /* temporary string pointer */ 4138360efbdSAlfred Perlstein struct netconfig *ncp = NULL; /* returned value */ 4148360efbdSAlfred Perlstein struct netconfig_list *list; /* pointer to cache list */ 4158360efbdSAlfred Perlstein 416b3a38fe3SIan Dowse nc_error = NC_NOTFOUND; /* default error. */ 4178360efbdSAlfred Perlstein if (netid == NULL || strlen(netid) == 0) { 4188360efbdSAlfred Perlstein return (NULL); 4198360efbdSAlfred Perlstein } 4208360efbdSAlfred Perlstein 421fb4c8061SMartin Blapp if (strcmp(netid, "unix") == 0) { 422fb4c8061SMartin Blapp fprintf(stderr, "The local transport is called \"unix\" "); 423fb4c8061SMartin Blapp fprintf(stderr, "in /etc/netconfig.\n"); 424fb4c8061SMartin Blapp fprintf(stderr, "Please change this to \"local\" manually "); 425fb4c8061SMartin Blapp fprintf(stderr, "or run mergemaster(8).\n"); 426fb4c8061SMartin Blapp fprintf(stderr, "See UPDATING entry 20021216 for details.\n"); 427fb4c8061SMartin Blapp fprintf(stderr, "Continuing in 10 seconds\n\n"); 428fb4c8061SMartin Blapp fprintf(stderr, "This warning will be removed 20030301\n"); 429fb4c8061SMartin Blapp sleep(10); 430fb4c8061SMartin Blapp 431fb4c8061SMartin Blapp } 432fb4c8061SMartin Blapp 4338360efbdSAlfred Perlstein /* 4348360efbdSAlfred Perlstein * Look up table if the entries have already been read and parsed in 4358360efbdSAlfred Perlstein * getnetconfig(), then copy this entry into a buffer and return it. 4368360efbdSAlfred Perlstein * If we cannot find the entry in the current list and there are more 4378360efbdSAlfred Perlstein * entries in the netconfig db that has not been read, we then read the 4388360efbdSAlfred Perlstein * db and try find the match netid. 4398360efbdSAlfred Perlstein * If all the netconfig db has been read and placed into the list and 4408360efbdSAlfred Perlstein * there is no match for the netid, return NULL. 4418360efbdSAlfred Perlstein */ 4428360efbdSAlfred Perlstein if (ni.head != NULL) { 4438360efbdSAlfred Perlstein for (list = ni.head; list; list = list->next) { 4448360efbdSAlfred Perlstein if (strcmp(list->ncp->nc_netid, netid) == 0) { 4458360efbdSAlfred Perlstein return(dup_ncp(list->ncp)); 4468360efbdSAlfred Perlstein } 4478360efbdSAlfred Perlstein } 4488360efbdSAlfred Perlstein if (ni.eof == 1) /* that's all the entries */ 4498360efbdSAlfred Perlstein return(NULL); 4508360efbdSAlfred Perlstein } 4518360efbdSAlfred Perlstein 4528360efbdSAlfred Perlstein 4538360efbdSAlfred Perlstein if ((file = fopen(NETCONFIG, "r")) == NULL) { 454b3a38fe3SIan Dowse nc_error = NC_NONETCONFIG; 4558360efbdSAlfred Perlstein return (NULL); 4568360efbdSAlfred Perlstein } 4578360efbdSAlfred Perlstein 4588360efbdSAlfred Perlstein if ((linep = malloc(MAXNETCONFIGLINE)) == NULL) { 4598360efbdSAlfred Perlstein fclose(file); 460b3a38fe3SIan Dowse nc_error = NC_NOMEM; 4618360efbdSAlfred Perlstein return (NULL); 4628360efbdSAlfred Perlstein } 4638360efbdSAlfred Perlstein do { 4643c788545SMartin Blapp ptrdiff_t len; 4658360efbdSAlfred Perlstein char *tmpp; /* tmp string pointer */ 4668360efbdSAlfred Perlstein 4678360efbdSAlfred Perlstein do { 4688360efbdSAlfred Perlstein if ((stringp = fgets(linep, MAXNETCONFIGLINE, file)) == NULL) { 4698360efbdSAlfred Perlstein break; 4708360efbdSAlfred Perlstein } 4718360efbdSAlfred Perlstein } while (*stringp == '#'); 4728360efbdSAlfred Perlstein if (stringp == NULL) { /* eof */ 4738360efbdSAlfred Perlstein break; 4748360efbdSAlfred Perlstein } 4758360efbdSAlfred Perlstein if ((tmpp = strpbrk(stringp, "\t ")) == NULL) { /* can't parse file */ 4768360efbdSAlfred Perlstein nc_error = NC_BADFILE; 4778360efbdSAlfred Perlstein break; 4788360efbdSAlfred Perlstein } 4793c788545SMartin Blapp if (strlen(netid) == (size_t) (len = tmpp - stringp) && /* a match */ 4808360efbdSAlfred Perlstein strncmp(stringp, netid, (size_t)len) == 0) { 4818360efbdSAlfred Perlstein if ((ncp = (struct netconfig *) 4828360efbdSAlfred Perlstein malloc(sizeof (struct netconfig))) == NULL) { 4838360efbdSAlfred Perlstein break; 4848360efbdSAlfred Perlstein } 4858360efbdSAlfred Perlstein ncp->nc_lookups = NULL; 4868360efbdSAlfred Perlstein if (parse_ncp(linep, ncp) == -1) { 4878360efbdSAlfred Perlstein free(ncp); 4888360efbdSAlfred Perlstein ncp = NULL; 4898360efbdSAlfred Perlstein } 4908360efbdSAlfred Perlstein break; 4918360efbdSAlfred Perlstein } 4928360efbdSAlfred Perlstein } while (stringp != NULL); 4938360efbdSAlfred Perlstein if (ncp == NULL) { 4948360efbdSAlfred Perlstein free(linep); 4958360efbdSAlfred Perlstein } 4968360efbdSAlfred Perlstein fclose(file); 4978360efbdSAlfred Perlstein return(ncp); 4988360efbdSAlfred Perlstein } 4998360efbdSAlfred Perlstein 5008360efbdSAlfred Perlstein /* 5018360efbdSAlfred Perlstein * freenetconfigent(netconfigp) frees the netconfig structure pointed to by 5028360efbdSAlfred Perlstein * netconfigp (previously returned by getnetconfigent()). 5038360efbdSAlfred Perlstein */ 5048360efbdSAlfred Perlstein 5058360efbdSAlfred Perlstein void 5068360efbdSAlfred Perlstein freenetconfigent(netconfigp) 5078360efbdSAlfred Perlstein struct netconfig *netconfigp; 5088360efbdSAlfred Perlstein { 5098360efbdSAlfred Perlstein if (netconfigp != NULL) { 5108360efbdSAlfred Perlstein free(netconfigp->nc_netid); /* holds all netconfigp's strings */ 5118360efbdSAlfred Perlstein if (netconfigp->nc_lookups != NULL) 5128360efbdSAlfred Perlstein free(netconfigp->nc_lookups); 5138360efbdSAlfred Perlstein free(netconfigp); 5148360efbdSAlfred Perlstein } 5158360efbdSAlfred Perlstein return; 5168360efbdSAlfred Perlstein } 5178360efbdSAlfred Perlstein 5188360efbdSAlfred Perlstein /* 5198360efbdSAlfred Perlstein * Parse line and stuff it in a struct netconfig 5208360efbdSAlfred Perlstein * Typical line might look like: 5218360efbdSAlfred Perlstein * udp tpi_cots vb inet udp /dev/udp /usr/lib/ip.so,/usr/local/ip.so 5228360efbdSAlfred Perlstein * 5238360efbdSAlfred Perlstein * We return -1 if any of the tokens don't parse, or malloc fails. 5248360efbdSAlfred Perlstein * 5258360efbdSAlfred Perlstein * Note that we modify stringp (putting NULLs after tokens) and 5268360efbdSAlfred Perlstein * we set the ncp's string field pointers to point to these tokens within 5278360efbdSAlfred Perlstein * stringp. 5288360efbdSAlfred Perlstein */ 5298360efbdSAlfred Perlstein 5308360efbdSAlfred Perlstein static int 5318360efbdSAlfred Perlstein parse_ncp(stringp, ncp) 5328360efbdSAlfred Perlstein char *stringp; /* string to parse */ 5338360efbdSAlfred Perlstein struct netconfig *ncp; /* where to put results */ 5348360efbdSAlfred Perlstein { 5358360efbdSAlfred Perlstein char *tokenp; /* for processing tokens */ 5368360efbdSAlfred Perlstein char *lasts; 537330e445cSMatteo Riondato char **nc_lookups; 5388360efbdSAlfred Perlstein 5398360efbdSAlfred Perlstein nc_error = NC_BADFILE; /* nearly anything that breaks is for this reason */ 5408360efbdSAlfred Perlstein stringp[strlen(stringp)-1] = '\0'; /* get rid of newline */ 5418360efbdSAlfred Perlstein /* netid */ 5428360efbdSAlfred Perlstein if ((ncp->nc_netid = strtok_r(stringp, "\t ", &lasts)) == NULL) { 5438360efbdSAlfred Perlstein return (-1); 5448360efbdSAlfred Perlstein } 5458360efbdSAlfred Perlstein 5468360efbdSAlfred Perlstein /* semantics */ 5478360efbdSAlfred Perlstein if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) { 5488360efbdSAlfred Perlstein return (-1); 5498360efbdSAlfred Perlstein } 5508360efbdSAlfred Perlstein if (strcmp(tokenp, NC_TPI_COTS_ORD_S) == 0) 5518360efbdSAlfred Perlstein ncp->nc_semantics = NC_TPI_COTS_ORD; 5528360efbdSAlfred Perlstein else if (strcmp(tokenp, NC_TPI_COTS_S) == 0) 5538360efbdSAlfred Perlstein ncp->nc_semantics = NC_TPI_COTS; 5548360efbdSAlfred Perlstein else if (strcmp(tokenp, NC_TPI_CLTS_S) == 0) 5558360efbdSAlfred Perlstein ncp->nc_semantics = NC_TPI_CLTS; 5568360efbdSAlfred Perlstein else if (strcmp(tokenp, NC_TPI_RAW_S) == 0) 5578360efbdSAlfred Perlstein ncp->nc_semantics = NC_TPI_RAW; 5588360efbdSAlfred Perlstein else 5598360efbdSAlfred Perlstein return (-1); 5608360efbdSAlfred Perlstein 5618360efbdSAlfred Perlstein /* flags */ 5628360efbdSAlfred Perlstein if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) { 5638360efbdSAlfred Perlstein return (-1); 5648360efbdSAlfred Perlstein } 5658360efbdSAlfred Perlstein for (ncp->nc_flag = NC_NOFLAG; *tokenp != '\0'; 5668360efbdSAlfred Perlstein tokenp++) { 5678360efbdSAlfred Perlstein switch (*tokenp) { 5688360efbdSAlfred Perlstein case NC_NOFLAG_C: 5698360efbdSAlfred Perlstein break; 5708360efbdSAlfred Perlstein case NC_VISIBLE_C: 5718360efbdSAlfred Perlstein ncp->nc_flag |= NC_VISIBLE; 5728360efbdSAlfred Perlstein break; 5738360efbdSAlfred Perlstein case NC_BROADCAST_C: 5748360efbdSAlfred Perlstein ncp->nc_flag |= NC_BROADCAST; 5758360efbdSAlfred Perlstein break; 5768360efbdSAlfred Perlstein default: 5778360efbdSAlfred Perlstein return (-1); 5788360efbdSAlfred Perlstein } 5798360efbdSAlfred Perlstein } 5808360efbdSAlfred Perlstein /* protocol family */ 5818360efbdSAlfred Perlstein if ((ncp->nc_protofmly = strtok_r(NULL, "\t ", &lasts)) == NULL) { 5828360efbdSAlfred Perlstein return (-1); 5838360efbdSAlfred Perlstein } 5848360efbdSAlfred Perlstein /* protocol name */ 5858360efbdSAlfred Perlstein if ((ncp->nc_proto = strtok_r(NULL, "\t ", &lasts)) == NULL) { 5868360efbdSAlfred Perlstein return (-1); 5878360efbdSAlfred Perlstein } 5888360efbdSAlfred Perlstein /* network device */ 5898360efbdSAlfred Perlstein if ((ncp->nc_device = strtok_r(NULL, "\t ", &lasts)) == NULL) { 5908360efbdSAlfred Perlstein return (-1); 5918360efbdSAlfred Perlstein } 5928360efbdSAlfred Perlstein if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) { 5938360efbdSAlfred Perlstein return (-1); 5948360efbdSAlfred Perlstein } 5958360efbdSAlfred Perlstein if (strcmp(tokenp, NC_NOLOOKUP) == 0) { 5968360efbdSAlfred Perlstein ncp->nc_nlookups = 0; 5978360efbdSAlfred Perlstein ncp->nc_lookups = NULL; 5988360efbdSAlfred Perlstein } else { 5998360efbdSAlfred Perlstein char *cp; /* tmp string */ 6008360efbdSAlfred Perlstein 6018360efbdSAlfred Perlstein if (ncp->nc_lookups != NULL) /* from last visit */ 6028360efbdSAlfred Perlstein free(ncp->nc_lookups); 603330e445cSMatteo Riondato ncp->nc_lookups = NULL; 6048360efbdSAlfred Perlstein ncp->nc_nlookups = 0; 6058360efbdSAlfred Perlstein while ((cp = tokenp) != NULL) { 606330e445cSMatteo Riondato if ((nc_lookups = realloc(ncp->nc_lookups, 607330e445cSMatteo Riondato (ncp->nc_nlookups + 1) * sizeof *ncp->nc_lookups)) == NULL) { 608330e445cSMatteo Riondato free(ncp->nc_lookups); 609330e445cSMatteo Riondato ncp->nc_lookups = NULL; 610330e445cSMatteo Riondato return (-1); 611330e445cSMatteo Riondato } 6128360efbdSAlfred Perlstein tokenp = _get_next_token(cp, ','); 613330e445cSMatteo Riondato ncp->nc_lookups = nc_lookups; 614330e445cSMatteo Riondato ncp->nc_lookups[ncp->nc_nlookups++] = cp; 6158360efbdSAlfred Perlstein } 6168360efbdSAlfred Perlstein } 6178360efbdSAlfred Perlstein return (0); 6188360efbdSAlfred Perlstein } 6198360efbdSAlfred Perlstein 6208360efbdSAlfred Perlstein 6218360efbdSAlfred Perlstein /* 6228360efbdSAlfred Perlstein * Returns a string describing the reason for failure. 6238360efbdSAlfred Perlstein */ 6248360efbdSAlfred Perlstein char * 6258360efbdSAlfred Perlstein nc_sperror() 6268360efbdSAlfred Perlstein { 6278360efbdSAlfred Perlstein const char *message; 6288360efbdSAlfred Perlstein 6298360efbdSAlfred Perlstein switch(nc_error) { 6308360efbdSAlfred Perlstein case NC_NONETCONFIG: 6318360efbdSAlfred Perlstein message = _nc_errors[0]; 6328360efbdSAlfred Perlstein break; 6338360efbdSAlfred Perlstein case NC_NOMEM: 6348360efbdSAlfred Perlstein message = _nc_errors[1]; 6358360efbdSAlfred Perlstein break; 6368360efbdSAlfred Perlstein case NC_NOTINIT: 6378360efbdSAlfred Perlstein message = _nc_errors[2]; 6388360efbdSAlfred Perlstein break; 6398360efbdSAlfred Perlstein case NC_BADFILE: 6408360efbdSAlfred Perlstein message = _nc_errors[3]; 6418360efbdSAlfred Perlstein break; 642b3a38fe3SIan Dowse case NC_NOTFOUND: 643b3a38fe3SIan Dowse message = _nc_errors[4]; 644b3a38fe3SIan Dowse break; 6458360efbdSAlfred Perlstein default: 6468360efbdSAlfred Perlstein message = "Unknown network selection error"; 6478360efbdSAlfred Perlstein } 6488360efbdSAlfred Perlstein /* LINTED const castaway */ 6498360efbdSAlfred Perlstein return ((char *)message); 6508360efbdSAlfred Perlstein } 6518360efbdSAlfred Perlstein 6528360efbdSAlfred Perlstein /* 6538360efbdSAlfred Perlstein * Prints a message onto standard error describing the reason for failure. 6548360efbdSAlfred Perlstein */ 6558360efbdSAlfred Perlstein void 6568360efbdSAlfred Perlstein nc_perror(s) 6578360efbdSAlfred Perlstein const char *s; 6588360efbdSAlfred Perlstein { 659b3a38fe3SIan Dowse fprintf(stderr, "%s: %s\n", s, nc_sperror()); 6608360efbdSAlfred Perlstein } 6618360efbdSAlfred Perlstein 6628360efbdSAlfred Perlstein /* 6638360efbdSAlfred Perlstein * Duplicates the matched netconfig buffer. 6648360efbdSAlfred Perlstein */ 6658360efbdSAlfred Perlstein static struct netconfig * 6668360efbdSAlfred Perlstein dup_ncp(ncp) 6678360efbdSAlfred Perlstein struct netconfig *ncp; 6688360efbdSAlfred Perlstein { 6698360efbdSAlfred Perlstein struct netconfig *p; 6708360efbdSAlfred Perlstein char *tmp; 6713c788545SMartin Blapp u_int i; 6728360efbdSAlfred Perlstein 6738360efbdSAlfred Perlstein if ((tmp=malloc(MAXNETCONFIGLINE)) == NULL) 6748360efbdSAlfred Perlstein return(NULL); 6758360efbdSAlfred Perlstein if ((p=(struct netconfig *)malloc(sizeof(struct netconfig))) == NULL) { 6768360efbdSAlfred Perlstein free(tmp); 6778360efbdSAlfred Perlstein return(NULL); 6788360efbdSAlfred Perlstein } 6798360efbdSAlfred Perlstein /* 6808360efbdSAlfred Perlstein * First we dup all the data from matched netconfig buffer. Then we 6818360efbdSAlfred Perlstein * adjust some of the member pointer to a pre-allocated buffer where 6828360efbdSAlfred Perlstein * contains part of the data. 6838360efbdSAlfred Perlstein * To follow the convention used in parse_ncp(), we store all the 6843c788545SMartin Blapp * necessary information in the pre-allocated buffer and let each 6858360efbdSAlfred Perlstein * of the netconfig char pointer member point to the right address 6868360efbdSAlfred Perlstein * in the buffer. 6878360efbdSAlfred Perlstein */ 6888360efbdSAlfred Perlstein *p = *ncp; 6898360efbdSAlfred Perlstein p->nc_netid = (char *)strcpy(tmp,ncp->nc_netid); 69016fc3635SMark Murray tmp = strchr(tmp, '\0') + 1; 6918360efbdSAlfred Perlstein p->nc_protofmly = (char *)strcpy(tmp,ncp->nc_protofmly); 69216fc3635SMark Murray tmp = strchr(tmp, '\0') + 1; 6938360efbdSAlfred Perlstein p->nc_proto = (char *)strcpy(tmp,ncp->nc_proto); 69416fc3635SMark Murray tmp = strchr(tmp, '\0') + 1; 6958360efbdSAlfred Perlstein p->nc_device = (char *)strcpy(tmp,ncp->nc_device); 6968360efbdSAlfred Perlstein p->nc_lookups = (char **)malloc((size_t)(p->nc_nlookups+1) * sizeof(char *)); 6978360efbdSAlfred Perlstein if (p->nc_lookups == NULL) { 6988360efbdSAlfred Perlstein free(p->nc_netid); 699b0718451SMartin Blapp free(p); 7008360efbdSAlfred Perlstein return(NULL); 7018360efbdSAlfred Perlstein } 7028360efbdSAlfred Perlstein for (i=0; i < p->nc_nlookups; i++) { 70316fc3635SMark Murray tmp = strchr(tmp, '\0') + 1; 7048360efbdSAlfred Perlstein p->nc_lookups[i] = (char *)strcpy(tmp,ncp->nc_lookups[i]); 7058360efbdSAlfred Perlstein } 7068360efbdSAlfred Perlstein return(p); 7078360efbdSAlfred Perlstein } 708