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