18360efbdSAlfred Perlstein /* $NetBSD: getnetconfig.c,v 1.3 2000/07/06 03:10:34 christos Exp $ */
28360efbdSAlfred Perlstein
32e322d37SHiroki Sato /*-
4*8a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause
5*8a16b7a1SPedro F. Giffuni *
62e322d37SHiroki Sato * Copyright (c) 2009, Sun Microsystems, Inc.
72e322d37SHiroki Sato * All rights reserved.
88360efbdSAlfred Perlstein *
92e322d37SHiroki Sato * Redistribution and use in source and binary forms, with or without
102e322d37SHiroki Sato * modification, are permitted provided that the following conditions are met:
112e322d37SHiroki Sato * - Redistributions of source code must retain the above copyright notice,
122e322d37SHiroki Sato * this list of conditions and the following disclaimer.
132e322d37SHiroki Sato * - Redistributions in binary form must reproduce the above copyright notice,
142e322d37SHiroki Sato * this list of conditions and the following disclaimer in the documentation
152e322d37SHiroki Sato * and/or other materials provided with the distribution.
162e322d37SHiroki Sato * - Neither the name of Sun Microsystems, Inc. nor the names of its
172e322d37SHiroki Sato * contributors may be used to endorse or promote products derived
182e322d37SHiroki Sato * from this software without specific prior written permission.
198360efbdSAlfred Perlstein *
202e322d37SHiroki Sato * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
212e322d37SHiroki Sato * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
222e322d37SHiroki Sato * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
232e322d37SHiroki Sato * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
242e322d37SHiroki Sato * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
252e322d37SHiroki Sato * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
262e322d37SHiroki Sato * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
272e322d37SHiroki Sato * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
282e322d37SHiroki Sato * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
292e322d37SHiroki Sato * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
302e322d37SHiroki Sato * POSSIBILITY OF SUCH DAMAGE.
318360efbdSAlfred Perlstein */
32a986ef57SDavid E. O'Brien
338360efbdSAlfred Perlstein /*
348360efbdSAlfred Perlstein * Copyright (c) 1989 by Sun Microsystems, Inc.
358360efbdSAlfred Perlstein */
368360efbdSAlfred Perlstein
378360efbdSAlfred Perlstein #include "namespace.h"
389f5afc13SIan Dowse #include "reentrant.h"
398360efbdSAlfred Perlstein #include <stdio.h>
408360efbdSAlfred Perlstein #include <errno.h>
418360efbdSAlfred Perlstein #include <netconfig.h>
423c788545SMartin Blapp #include <stddef.h>
438360efbdSAlfred Perlstein #include <stdlib.h>
448360efbdSAlfred Perlstein #include <string.h>
458360efbdSAlfred Perlstein #include <rpc/rpc.h>
46e0554a53SJacques Vidrine #include <unistd.h>
478360efbdSAlfred Perlstein #include "un-namespace.h"
488360efbdSAlfred Perlstein #include "rpc_com.h"
498360efbdSAlfred Perlstein
508360efbdSAlfred Perlstein /*
518360efbdSAlfred Perlstein * The five library routines in this file provide application access to the
528360efbdSAlfred Perlstein * system network configuration database, /etc/netconfig. In addition to the
538360efbdSAlfred Perlstein * netconfig database and the routines for accessing it, the environment
548360efbdSAlfred Perlstein * variable NETPATH and its corresponding routines in getnetpath.c may also be
558360efbdSAlfred Perlstein * used to specify the network transport to be used.
568360efbdSAlfred Perlstein */
578360efbdSAlfred Perlstein
588360efbdSAlfred Perlstein
598360efbdSAlfred Perlstein /*
608360efbdSAlfred Perlstein * netconfig errors
618360efbdSAlfred Perlstein */
628360efbdSAlfred Perlstein
638360efbdSAlfred Perlstein #define NC_NONETCONFIG ENOENT
648360efbdSAlfred Perlstein #define NC_NOMEM ENOMEM
658360efbdSAlfred Perlstein #define NC_NOTINIT EINVAL /* setnetconfig was not called first */
668360efbdSAlfred Perlstein #define NC_BADFILE EBADF /* format for netconfig file is bad */
67b3a38fe3SIan Dowse #define NC_NOTFOUND ENOPROTOOPT /* specified netid was not found */
688360efbdSAlfred Perlstein
698360efbdSAlfred Perlstein /*
708360efbdSAlfred Perlstein * semantics as strings (should be in netconfig.h)
718360efbdSAlfred Perlstein */
728360efbdSAlfred Perlstein #define NC_TPI_CLTS_S "tpi_clts"
738360efbdSAlfred Perlstein #define NC_TPI_COTS_S "tpi_cots"
748360efbdSAlfred Perlstein #define NC_TPI_COTS_ORD_S "tpi_cots_ord"
758360efbdSAlfred Perlstein #define NC_TPI_RAW_S "tpi_raw"
768360efbdSAlfred Perlstein
778360efbdSAlfred Perlstein /*
788360efbdSAlfred Perlstein * flags as characters (also should be in netconfig.h)
798360efbdSAlfred Perlstein */
808360efbdSAlfred Perlstein #define NC_NOFLAG_C '-'
818360efbdSAlfred Perlstein #define NC_VISIBLE_C 'v'
828360efbdSAlfred Perlstein #define NC_BROADCAST_C 'b'
838360efbdSAlfred Perlstein
848360efbdSAlfred Perlstein /*
858360efbdSAlfred Perlstein * Character used to indicate there is no name-to-address lookup library
868360efbdSAlfred Perlstein */
878360efbdSAlfred Perlstein #define NC_NOLOOKUP "-"
888360efbdSAlfred Perlstein
898360efbdSAlfred Perlstein static const char * const _nc_errors[] = {
908360efbdSAlfred Perlstein "Netconfig database not found",
918360efbdSAlfred Perlstein "Not enough memory",
928360efbdSAlfred Perlstein "Not initialized",
93b3a38fe3SIan Dowse "Netconfig database has invalid format",
94b3a38fe3SIan Dowse "Netid not found in netconfig database"
958360efbdSAlfred Perlstein };
968360efbdSAlfred Perlstein
978360efbdSAlfred Perlstein struct netconfig_info {
988360efbdSAlfred Perlstein int eof; /* all entries has been read */
998360efbdSAlfred Perlstein int ref; /* # of times setnetconfig() has been called */
1008360efbdSAlfred Perlstein struct netconfig_list *head; /* head of the list */
1018360efbdSAlfred Perlstein struct netconfig_list *tail; /* last of the list */
1028360efbdSAlfred Perlstein };
1038360efbdSAlfred Perlstein
1048360efbdSAlfred Perlstein struct netconfig_list {
1058360efbdSAlfred Perlstein char *linep; /* hold line read from netconfig */
1068360efbdSAlfred Perlstein struct netconfig *ncp;
1078360efbdSAlfred Perlstein struct netconfig_list *next;
1088360efbdSAlfred Perlstein };
1098360efbdSAlfred Perlstein
1108360efbdSAlfred Perlstein struct netconfig_vars {
1118360efbdSAlfred Perlstein int valid; /* token that indicates a valid netconfig_vars */
1128360efbdSAlfred Perlstein int flag; /* first time flag */
1138360efbdSAlfred Perlstein struct netconfig_list *nc_configs; /* pointer to the current netconfig entry */
1148360efbdSAlfred Perlstein };
1158360efbdSAlfred Perlstein
1168360efbdSAlfred Perlstein #define NC_VALID 0xfeed
1178360efbdSAlfred Perlstein #define NC_STORAGE 0xf00d
1188360efbdSAlfred Perlstein #define NC_INVALID 0
1198360efbdSAlfred Perlstein
1208360efbdSAlfred Perlstein
121c05ac53bSDavid E. O'Brien static int *__nc_error(void);
122c05ac53bSDavid E. O'Brien static int parse_ncp(char *, struct netconfig *);
123c05ac53bSDavid E. O'Brien static struct netconfig *dup_ncp(struct netconfig *);
1248360efbdSAlfred Perlstein
1258360efbdSAlfred Perlstein
1268360efbdSAlfred Perlstein static FILE *nc_file; /* for netconfig db */
1276f88d2a8SJohn Baldwin static mutex_t nc_file_lock = MUTEX_INITIALIZER;
1285f4faf74SXin LI
1298360efbdSAlfred Perlstein static struct netconfig_info ni = { 0, 0, NULL, NULL};
1306f88d2a8SJohn Baldwin static mutex_t ni_lock = MUTEX_INITIALIZER;
1315f4faf74SXin LI
1326f88d2a8SJohn Baldwin static thread_key_t nc_key;
1336f88d2a8SJohn Baldwin static once_t nc_once = ONCE_INITIALIZER;
1346f88d2a8SJohn Baldwin static int nc_key_error;
1356f88d2a8SJohn Baldwin
1366f88d2a8SJohn Baldwin static void
nc_key_init(void)1376f88d2a8SJohn Baldwin nc_key_init(void)
1386f88d2a8SJohn Baldwin {
1396f88d2a8SJohn Baldwin
1406f88d2a8SJohn Baldwin nc_key_error = thr_keycreate(&nc_key, free);
1416f88d2a8SJohn Baldwin }
1428360efbdSAlfred Perlstein
1438360efbdSAlfred Perlstein #define MAXNETCONFIGLINE 1000
1448360efbdSAlfred Perlstein
1458360efbdSAlfred Perlstein static int *
__nc_error(void)146587cf682SCraig Rodrigues __nc_error(void)
1478360efbdSAlfred Perlstein {
1488360efbdSAlfred Perlstein static int nc_error = 0;
1496f88d2a8SJohn Baldwin int *nc_addr;
1508360efbdSAlfred Perlstein
151b3a38fe3SIan Dowse /*
152b3a38fe3SIan Dowse * Use the static `nc_error' if we are the main thread
153b3a38fe3SIan Dowse * (including non-threaded programs), or if an allocation
154b3a38fe3SIan Dowse * fails.
155b3a38fe3SIan Dowse */
156b3a38fe3SIan Dowse if (thr_main())
157b3a38fe3SIan Dowse return (&nc_error);
1586f88d2a8SJohn Baldwin if (thr_once(&nc_once, nc_key_init) != 0 || nc_key_error != 0)
159b3a38fe3SIan Dowse return (&nc_error);
160b3a38fe3SIan Dowse if ((nc_addr = (int *)thr_getspecific(nc_key)) == NULL) {
1618360efbdSAlfred Perlstein nc_addr = (int *)malloc(sizeof (int));
1628360efbdSAlfred Perlstein if (thr_setspecific(nc_key, (void *) nc_addr) != 0) {
1638360efbdSAlfred Perlstein free(nc_addr);
164b3a38fe3SIan Dowse return (&nc_error);
1658360efbdSAlfred Perlstein }
1668360efbdSAlfred Perlstein *nc_addr = 0;
1678360efbdSAlfred Perlstein }
168b3a38fe3SIan Dowse return (nc_addr);
1698360efbdSAlfred Perlstein }
1708360efbdSAlfred Perlstein
1718360efbdSAlfred Perlstein #define nc_error (*(__nc_error()))
1728360efbdSAlfred Perlstein /*
1738360efbdSAlfred Perlstein * A call to setnetconfig() establishes a /etc/netconfig "session". A session
1748360efbdSAlfred Perlstein * "handle" is returned on a successful call. At the start of a session (after
1758360efbdSAlfred Perlstein * a call to setnetconfig()) searches through the /etc/netconfig database will
1768360efbdSAlfred Perlstein * proceed from the start of the file. The session handle must be passed to
1778360efbdSAlfred Perlstein * getnetconfig() to parse the file. Each call to getnetconfig() using the
1788360efbdSAlfred Perlstein * current handle will process one subsequent entry in /etc/netconfig.
1798360efbdSAlfred Perlstein * setnetconfig() must be called before the first call to getnetconfig().
1808360efbdSAlfred Perlstein * (Handles are used to allow for nested calls to setnetpath()).
1818360efbdSAlfred Perlstein *
1828360efbdSAlfred Perlstein * A new session is established with each call to setnetconfig(), with a new
1838360efbdSAlfred Perlstein * handle being returned on each call. Previously established sessions remain
1848360efbdSAlfred Perlstein * active until endnetconfig() is called with that session's handle as an
1858360efbdSAlfred Perlstein * argument.
1868360efbdSAlfred Perlstein *
1878360efbdSAlfred Perlstein * setnetconfig() need *not* be called before a call to getnetconfigent().
1888360efbdSAlfred Perlstein * setnetconfig() returns a NULL pointer on failure (for example, if
1898360efbdSAlfred Perlstein * the netconfig database is not present).
1908360efbdSAlfred Perlstein */
1918360efbdSAlfred Perlstein void *
setnetconfig(void)192587cf682SCraig Rodrigues setnetconfig(void)
1938360efbdSAlfred Perlstein {
1948360efbdSAlfred Perlstein struct netconfig_vars *nc_vars;
1958360efbdSAlfred Perlstein
1968360efbdSAlfred Perlstein if ((nc_vars = (struct netconfig_vars *)malloc(sizeof
1978360efbdSAlfred Perlstein (struct netconfig_vars))) == NULL) {
1988360efbdSAlfred Perlstein return(NULL);
1998360efbdSAlfred Perlstein }
2008360efbdSAlfred Perlstein
2018360efbdSAlfred Perlstein /*
2028360efbdSAlfred Perlstein * For multiple calls, i.e. nc_file is not NULL, we just return the
2038360efbdSAlfred Perlstein * handle without reopening the netconfig db.
2048360efbdSAlfred Perlstein */
2055f4faf74SXin LI mutex_lock(&ni_lock);
2068360efbdSAlfred Perlstein ni.ref++;
2075f4faf74SXin LI mutex_unlock(&ni_lock);
2085f4faf74SXin LI
2095f4faf74SXin LI mutex_lock(&nc_file_lock);
2108360efbdSAlfred Perlstein if ((nc_file != NULL) || (nc_file = fopen(NETCONFIG, "r")) != NULL) {
2118360efbdSAlfred Perlstein nc_vars->valid = NC_VALID;
2128360efbdSAlfred Perlstein nc_vars->flag = 0;
2138360efbdSAlfred Perlstein nc_vars->nc_configs = ni.head;
2145f4faf74SXin LI mutex_unlock(&nc_file_lock);
2158360efbdSAlfred Perlstein return ((void *)nc_vars);
2168360efbdSAlfred Perlstein }
2175f4faf74SXin LI mutex_unlock(&nc_file_lock);
2185f4faf74SXin LI
2195f4faf74SXin LI mutex_lock(&ni_lock);
2208360efbdSAlfred Perlstein ni.ref--;
2215f4faf74SXin LI mutex_unlock(&ni_lock);
2225f4faf74SXin LI
2238360efbdSAlfred Perlstein nc_error = NC_NONETCONFIG;
2248360efbdSAlfred Perlstein free(nc_vars);
2258360efbdSAlfred Perlstein return (NULL);
2268360efbdSAlfred Perlstein }
2278360efbdSAlfred Perlstein
2288360efbdSAlfred Perlstein
2298360efbdSAlfred Perlstein /*
2308360efbdSAlfred Perlstein * When first called, getnetconfig() returns a pointer to the first entry in
2318360efbdSAlfred Perlstein * the netconfig database, formatted as a struct netconfig. On each subsequent
2328360efbdSAlfred Perlstein * call, getnetconfig() returns a pointer to the next entry in the database.
2338360efbdSAlfred Perlstein * getnetconfig() can thus be used to search the entire netconfig file.
2348360efbdSAlfred Perlstein * getnetconfig() returns NULL at end of file.
2358360efbdSAlfred Perlstein */
2368360efbdSAlfred Perlstein
2378360efbdSAlfred Perlstein struct netconfig *
getnetconfig(void * handlep)238587cf682SCraig Rodrigues getnetconfig(void *handlep)
2398360efbdSAlfred Perlstein {
2408360efbdSAlfred Perlstein struct netconfig_vars *ncp = (struct netconfig_vars *)handlep;
2418360efbdSAlfred Perlstein char *stringp; /* tmp string pointer */
2428360efbdSAlfred Perlstein struct netconfig_list *list;
2438360efbdSAlfred Perlstein struct netconfig *np;
2445f4faf74SXin LI struct netconfig *result;
2458360efbdSAlfred Perlstein
2468360efbdSAlfred Perlstein /*
2478360efbdSAlfred Perlstein * Verify that handle is valid
2488360efbdSAlfred Perlstein */
2495f4faf74SXin LI mutex_lock(&nc_file_lock);
2508360efbdSAlfred Perlstein if (ncp == NULL || nc_file == NULL) {
2518360efbdSAlfred Perlstein nc_error = NC_NOTINIT;
2525f4faf74SXin LI mutex_unlock(&nc_file_lock);
2538360efbdSAlfred Perlstein return (NULL);
2548360efbdSAlfred Perlstein }
2555f4faf74SXin LI mutex_unlock(&nc_file_lock);
2568360efbdSAlfred Perlstein
2578360efbdSAlfred Perlstein switch (ncp->valid) {
2588360efbdSAlfred Perlstein case NC_VALID:
2598360efbdSAlfred Perlstein /*
2608360efbdSAlfred Perlstein * If entry has already been read into the list,
2618360efbdSAlfred Perlstein * we return the entry in the linked list.
2628360efbdSAlfred Perlstein * If this is the first time call, check if there are any entries in
2638360efbdSAlfred Perlstein * linked list. If no entries, we need to read the netconfig db.
2648360efbdSAlfred Perlstein * If we have been here and the next entry is there, we just return
2658360efbdSAlfred Perlstein * it.
2668360efbdSAlfred Perlstein */
2678360efbdSAlfred Perlstein if (ncp->flag == 0) { /* first time */
2688360efbdSAlfred Perlstein ncp->flag = 1;
2695f4faf74SXin LI mutex_lock(&ni_lock);
2708360efbdSAlfred Perlstein ncp->nc_configs = ni.head;
2715f4faf74SXin LI mutex_unlock(&ni_lock);
2728360efbdSAlfred Perlstein if (ncp->nc_configs != NULL) /* entry already exist */
2738360efbdSAlfred Perlstein return(ncp->nc_configs->ncp);
2748360efbdSAlfred Perlstein }
2758360efbdSAlfred Perlstein else if (ncp->nc_configs != NULL && ncp->nc_configs->next != NULL) {
2768360efbdSAlfred Perlstein ncp->nc_configs = ncp->nc_configs->next;
2778360efbdSAlfred Perlstein return(ncp->nc_configs->ncp);
2788360efbdSAlfred Perlstein }
2798360efbdSAlfred Perlstein
2808360efbdSAlfred Perlstein /*
2818360efbdSAlfred Perlstein * If we cannot find the entry in the list and is end of file,
2828360efbdSAlfred Perlstein * we give up.
2838360efbdSAlfred Perlstein */
2845f4faf74SXin LI mutex_lock(&ni_lock);
2855f4faf74SXin LI if (ni.eof == 1) {
2865f4faf74SXin LI mutex_unlock(&ni_lock);
2875f4faf74SXin LI return(NULL);
2885f4faf74SXin LI }
2895f4faf74SXin LI mutex_unlock(&ni_lock);
2905f4faf74SXin LI
2918360efbdSAlfred Perlstein break;
2928360efbdSAlfred Perlstein default:
2938360efbdSAlfred Perlstein nc_error = NC_NOTINIT;
2948360efbdSAlfred Perlstein return (NULL);
2958360efbdSAlfred Perlstein }
2968360efbdSAlfred Perlstein
2978360efbdSAlfred Perlstein stringp = (char *) malloc(MAXNETCONFIGLINE);
2988360efbdSAlfred Perlstein if (stringp == NULL)
2998360efbdSAlfred Perlstein return (NULL);
3008360efbdSAlfred Perlstein
3018360efbdSAlfred Perlstein #ifdef MEM_CHK
3028360efbdSAlfred Perlstein if (malloc_verify() == 0) {
3038360efbdSAlfred Perlstein fprintf(stderr, "memory heap corrupted in getnetconfig\n");
3048360efbdSAlfred Perlstein exit(1);
3058360efbdSAlfred Perlstein }
3068360efbdSAlfred Perlstein #endif
3078360efbdSAlfred Perlstein
3088360efbdSAlfred Perlstein /*
3098360efbdSAlfred Perlstein * Read a line from netconfig file.
3108360efbdSAlfred Perlstein */
3115f4faf74SXin LI mutex_lock(&nc_file_lock);
3128360efbdSAlfred Perlstein do {
3138360efbdSAlfred Perlstein if (fgets(stringp, MAXNETCONFIGLINE, nc_file) == NULL) {
3148360efbdSAlfred Perlstein free(stringp);
3155f4faf74SXin LI mutex_lock(&ni_lock);
3168360efbdSAlfred Perlstein ni.eof = 1;
3175f4faf74SXin LI mutex_unlock(&ni_lock);
3185f4faf74SXin LI mutex_unlock(&nc_file_lock);
3198360efbdSAlfred Perlstein return (NULL);
3208360efbdSAlfred Perlstein }
3218360efbdSAlfred Perlstein } while (*stringp == '#');
3225f4faf74SXin LI mutex_unlock(&nc_file_lock);
3238360efbdSAlfred Perlstein
3248360efbdSAlfred Perlstein list = (struct netconfig_list *) malloc(sizeof (struct netconfig_list));
3258360efbdSAlfred Perlstein if (list == NULL) {
3268360efbdSAlfred Perlstein free(stringp);
3278360efbdSAlfred Perlstein return(NULL);
3288360efbdSAlfred Perlstein }
3298360efbdSAlfred Perlstein np = (struct netconfig *) malloc(sizeof (struct netconfig));
3308360efbdSAlfred Perlstein if (np == NULL) {
3318360efbdSAlfred Perlstein free(stringp);
3328360efbdSAlfred Perlstein free(list);
3338360efbdSAlfred Perlstein return(NULL);
3348360efbdSAlfred Perlstein }
3358360efbdSAlfred Perlstein list->ncp = np;
3368360efbdSAlfred Perlstein list->next = NULL;
3378360efbdSAlfred Perlstein list->ncp->nc_lookups = NULL;
3388360efbdSAlfred Perlstein list->linep = stringp;
3398360efbdSAlfred Perlstein if (parse_ncp(stringp, list->ncp) == -1) {
3408360efbdSAlfred Perlstein free(stringp);
3418360efbdSAlfred Perlstein free(np);
3428360efbdSAlfred Perlstein free(list);
3438360efbdSAlfred Perlstein return (NULL);
3448360efbdSAlfred Perlstein }
3458360efbdSAlfred Perlstein else {
3468360efbdSAlfred Perlstein /*
3478360efbdSAlfred Perlstein * If this is the first entry that's been read, it is the head of
3488360efbdSAlfred Perlstein * the list. If not, put the entry at the end of the list.
3498360efbdSAlfred Perlstein * Reposition the current pointer of the handle to the last entry
3508360efbdSAlfred Perlstein * in the list.
3518360efbdSAlfred Perlstein */
3525f4faf74SXin LI mutex_lock(&ni_lock);
3538360efbdSAlfred Perlstein if (ni.head == NULL) { /* first entry */
3548360efbdSAlfred Perlstein ni.head = ni.tail = list;
3558360efbdSAlfred Perlstein }
3568360efbdSAlfred Perlstein else {
3578360efbdSAlfred Perlstein ni.tail->next = list;
3588360efbdSAlfred Perlstein ni.tail = ni.tail->next;
3598360efbdSAlfred Perlstein }
3608360efbdSAlfred Perlstein ncp->nc_configs = ni.tail;
3615f4faf74SXin LI result = ni.tail->ncp;
3625f4faf74SXin LI mutex_unlock(&ni_lock);
3635f4faf74SXin LI return(result);
3648360efbdSAlfred Perlstein }
3658360efbdSAlfred Perlstein }
3668360efbdSAlfred Perlstein
3678360efbdSAlfred Perlstein /*
3688360efbdSAlfred Perlstein * endnetconfig() may be called to "unbind" or "close" the netconfig database
3698360efbdSAlfred Perlstein * when processing is complete, releasing resources for reuse. endnetconfig()
3708360efbdSAlfred Perlstein * may not be called before setnetconfig(). endnetconfig() returns 0 on
3718360efbdSAlfred Perlstein * success and -1 on failure (for example, if setnetconfig() was not called
3728360efbdSAlfred Perlstein * previously).
3738360efbdSAlfred Perlstein */
3748360efbdSAlfred Perlstein int
endnetconfig(void * handlep)375587cf682SCraig Rodrigues endnetconfig(void *handlep)
3768360efbdSAlfred Perlstein {
3778360efbdSAlfred Perlstein struct netconfig_vars *nc_handlep = (struct netconfig_vars *)handlep;
3788360efbdSAlfred Perlstein
3798360efbdSAlfred Perlstein struct netconfig_list *q, *p;
3808360efbdSAlfred Perlstein
3818360efbdSAlfred Perlstein /*
3828360efbdSAlfred Perlstein * Verify that handle is valid
3838360efbdSAlfred Perlstein */
3848360efbdSAlfred Perlstein if (nc_handlep == NULL || (nc_handlep->valid != NC_VALID &&
3858360efbdSAlfred Perlstein nc_handlep->valid != NC_STORAGE)) {
3868360efbdSAlfred Perlstein nc_error = NC_NOTINIT;
3878360efbdSAlfred Perlstein return (-1);
3888360efbdSAlfred Perlstein }
3898360efbdSAlfred Perlstein
3908360efbdSAlfred Perlstein /*
3918360efbdSAlfred Perlstein * Return 0 if anyone still needs it.
3928360efbdSAlfred Perlstein */
3938360efbdSAlfred Perlstein nc_handlep->valid = NC_INVALID;
3948360efbdSAlfred Perlstein nc_handlep->flag = 0;
3958360efbdSAlfred Perlstein nc_handlep->nc_configs = NULL;
3965f4faf74SXin LI mutex_lock(&ni_lock);
3978360efbdSAlfred Perlstein if (--ni.ref > 0) {
3985f4faf74SXin LI mutex_unlock(&ni_lock);
3998360efbdSAlfred Perlstein free(nc_handlep);
4008360efbdSAlfred Perlstein return(0);
4018360efbdSAlfred Perlstein }
4028360efbdSAlfred Perlstein
4038360efbdSAlfred Perlstein /*
4048360efbdSAlfred Perlstein * No one needs these entries anymore, then frees them.
4058360efbdSAlfred Perlstein * Make sure all info in netconfig_info structure has been reinitialized.
4068360efbdSAlfred Perlstein */
4070c0349bfSGarrett Wollman q = ni.head;
4088360efbdSAlfred Perlstein ni.eof = ni.ref = 0;
4098360efbdSAlfred Perlstein ni.head = NULL;
4108360efbdSAlfred Perlstein ni.tail = NULL;
4115f4faf74SXin LI mutex_unlock(&ni_lock);
4125f4faf74SXin LI
4130c0349bfSGarrett Wollman while (q != NULL) {
4148360efbdSAlfred Perlstein p = q->next;
415c7f7fdd2SEnji Cooper free(q->ncp->nc_lookups);
4168360efbdSAlfred Perlstein free(q->ncp);
4178360efbdSAlfred Perlstein free(q->linep);
4188360efbdSAlfred Perlstein free(q);
4198360efbdSAlfred Perlstein q = p;
4208360efbdSAlfred Perlstein }
4218360efbdSAlfred Perlstein free(nc_handlep);
4228360efbdSAlfred Perlstein
4235f4faf74SXin LI mutex_lock(&nc_file_lock);
4248360efbdSAlfred Perlstein fclose(nc_file);
4258360efbdSAlfred Perlstein nc_file = NULL;
4265f4faf74SXin LI mutex_unlock(&nc_file_lock);
4275f4faf74SXin LI
4288360efbdSAlfred Perlstein return (0);
4298360efbdSAlfred Perlstein }
4308360efbdSAlfred Perlstein
4318360efbdSAlfred Perlstein /*
4328360efbdSAlfred Perlstein * getnetconfigent(netid) returns a pointer to the struct netconfig structure
4338360efbdSAlfred Perlstein * corresponding to netid. It returns NULL if netid is invalid (that is, does
4348360efbdSAlfred Perlstein * not name an entry in the netconfig database). It returns NULL and sets
4358360efbdSAlfred Perlstein * errno in case of failure (for example, if the netconfig database cannot be
4368360efbdSAlfred Perlstein * opened).
4378360efbdSAlfred Perlstein */
4388360efbdSAlfred Perlstein
4398360efbdSAlfred Perlstein struct netconfig *
getnetconfigent(const char * netid)440587cf682SCraig Rodrigues getnetconfigent(const char *netid)
4418360efbdSAlfred Perlstein {
4428360efbdSAlfred Perlstein FILE *file; /* NETCONFIG db's file pointer */
4438360efbdSAlfred Perlstein char *linep; /* holds current netconfig line */
4448360efbdSAlfred Perlstein char *stringp; /* temporary string pointer */
4458360efbdSAlfred Perlstein struct netconfig *ncp = NULL; /* returned value */
4468360efbdSAlfred Perlstein struct netconfig_list *list; /* pointer to cache list */
4478360efbdSAlfred Perlstein
448b3a38fe3SIan Dowse nc_error = NC_NOTFOUND; /* default error. */
4498360efbdSAlfred Perlstein if (netid == NULL || strlen(netid) == 0) {
4508360efbdSAlfred Perlstein return (NULL);
4518360efbdSAlfred Perlstein }
4528360efbdSAlfred Perlstein
4538360efbdSAlfred Perlstein /*
4548360efbdSAlfred Perlstein * Look up table if the entries have already been read and parsed in
4558360efbdSAlfred Perlstein * getnetconfig(), then copy this entry into a buffer and return it.
4568360efbdSAlfred Perlstein * If we cannot find the entry in the current list and there are more
4578360efbdSAlfred Perlstein * entries in the netconfig db that has not been read, we then read the
4588360efbdSAlfred Perlstein * db and try find the match netid.
4598360efbdSAlfred Perlstein * If all the netconfig db has been read and placed into the list and
4608360efbdSAlfred Perlstein * there is no match for the netid, return NULL.
4618360efbdSAlfred Perlstein */
4625f4faf74SXin LI mutex_lock(&ni_lock);
4638360efbdSAlfred Perlstein if (ni.head != NULL) {
4648360efbdSAlfred Perlstein for (list = ni.head; list; list = list->next) {
4658360efbdSAlfred Perlstein if (strcmp(list->ncp->nc_netid, netid) == 0) {
4665f4faf74SXin LI mutex_unlock(&ni_lock);
4678360efbdSAlfred Perlstein return(dup_ncp(list->ncp));
4688360efbdSAlfred Perlstein }
4698360efbdSAlfred Perlstein }
4705f4faf74SXin LI if (ni.eof == 1) { /* that's all the entries */
4715f4faf74SXin LI mutex_unlock(&ni_lock);
4728360efbdSAlfred Perlstein return(NULL);
4738360efbdSAlfred Perlstein }
4745f4faf74SXin LI }
4755f4faf74SXin LI mutex_unlock(&ni_lock);
4768360efbdSAlfred Perlstein
4778360efbdSAlfred Perlstein
4788360efbdSAlfred Perlstein if ((file = fopen(NETCONFIG, "r")) == NULL) {
479b3a38fe3SIan Dowse nc_error = NC_NONETCONFIG;
4808360efbdSAlfred Perlstein return (NULL);
4818360efbdSAlfred Perlstein }
4828360efbdSAlfred Perlstein
4838360efbdSAlfred Perlstein if ((linep = malloc(MAXNETCONFIGLINE)) == NULL) {
4848360efbdSAlfred Perlstein fclose(file);
485b3a38fe3SIan Dowse nc_error = NC_NOMEM;
4868360efbdSAlfred Perlstein return (NULL);
4878360efbdSAlfred Perlstein }
4888360efbdSAlfred Perlstein do {
4893c788545SMartin Blapp ptrdiff_t len;
4908360efbdSAlfred Perlstein char *tmpp; /* tmp string pointer */
4918360efbdSAlfred Perlstein
4928360efbdSAlfred Perlstein do {
4938360efbdSAlfred Perlstein if ((stringp = fgets(linep, MAXNETCONFIGLINE, file)) == NULL) {
4948360efbdSAlfred Perlstein break;
4958360efbdSAlfred Perlstein }
4968360efbdSAlfred Perlstein } while (*stringp == '#');
4978360efbdSAlfred Perlstein if (stringp == NULL) { /* eof */
4988360efbdSAlfred Perlstein break;
4998360efbdSAlfred Perlstein }
5008360efbdSAlfred Perlstein if ((tmpp = strpbrk(stringp, "\t ")) == NULL) { /* can't parse file */
5018360efbdSAlfred Perlstein nc_error = NC_BADFILE;
5028360efbdSAlfred Perlstein break;
5038360efbdSAlfred Perlstein }
5043c788545SMartin Blapp if (strlen(netid) == (size_t) (len = tmpp - stringp) && /* a match */
5058360efbdSAlfred Perlstein strncmp(stringp, netid, (size_t)len) == 0) {
5068360efbdSAlfred Perlstein if ((ncp = (struct netconfig *)
5078360efbdSAlfred Perlstein malloc(sizeof (struct netconfig))) == NULL) {
5088360efbdSAlfred Perlstein break;
5098360efbdSAlfred Perlstein }
5108360efbdSAlfred Perlstein ncp->nc_lookups = NULL;
5118360efbdSAlfred Perlstein if (parse_ncp(linep, ncp) == -1) {
5128360efbdSAlfred Perlstein free(ncp);
5138360efbdSAlfred Perlstein ncp = NULL;
5148360efbdSAlfred Perlstein }
5158360efbdSAlfred Perlstein break;
5168360efbdSAlfred Perlstein }
5178360efbdSAlfred Perlstein } while (stringp != NULL);
5188360efbdSAlfred Perlstein if (ncp == NULL) {
5198360efbdSAlfred Perlstein free(linep);
5208360efbdSAlfred Perlstein }
5218360efbdSAlfred Perlstein fclose(file);
5228360efbdSAlfred Perlstein return(ncp);
5238360efbdSAlfred Perlstein }
5248360efbdSAlfred Perlstein
5258360efbdSAlfred Perlstein /*
5268360efbdSAlfred Perlstein * freenetconfigent(netconfigp) frees the netconfig structure pointed to by
5278360efbdSAlfred Perlstein * netconfigp (previously returned by getnetconfigent()).
5288360efbdSAlfred Perlstein */
5298360efbdSAlfred Perlstein
5308360efbdSAlfred Perlstein void
freenetconfigent(struct netconfig * netconfigp)531587cf682SCraig Rodrigues freenetconfigent(struct netconfig *netconfigp)
5328360efbdSAlfred Perlstein {
5338360efbdSAlfred Perlstein if (netconfigp != NULL) {
5348360efbdSAlfred Perlstein free(netconfigp->nc_netid); /* holds all netconfigp's strings */
5358360efbdSAlfred Perlstein free(netconfigp->nc_lookups);
5368360efbdSAlfred Perlstein free(netconfigp);
5378360efbdSAlfred Perlstein }
5388360efbdSAlfred Perlstein return;
5398360efbdSAlfred Perlstein }
5408360efbdSAlfred Perlstein
5418360efbdSAlfred Perlstein /*
5428360efbdSAlfred Perlstein * Parse line and stuff it in a struct netconfig
5438360efbdSAlfred Perlstein * Typical line might look like:
5448360efbdSAlfred Perlstein * udp tpi_cots vb inet udp /dev/udp /usr/lib/ip.so,/usr/local/ip.so
5458360efbdSAlfred Perlstein *
5468360efbdSAlfred Perlstein * We return -1 if any of the tokens don't parse, or malloc fails.
5478360efbdSAlfred Perlstein *
5488360efbdSAlfred Perlstein * Note that we modify stringp (putting NULLs after tokens) and
5498360efbdSAlfred Perlstein * we set the ncp's string field pointers to point to these tokens within
5508360efbdSAlfred Perlstein * stringp.
551587cf682SCraig Rodrigues *
552587cf682SCraig Rodrigues * stringp - string to parse
553587cf682SCraig Rodrigues * ncp - where to put results
5548360efbdSAlfred Perlstein */
5558360efbdSAlfred Perlstein
5568360efbdSAlfred Perlstein static int
parse_ncp(char * stringp,struct netconfig * ncp)557587cf682SCraig Rodrigues parse_ncp(char *stringp, struct netconfig *ncp)
5588360efbdSAlfred Perlstein {
5598360efbdSAlfred Perlstein char *tokenp; /* for processing tokens */
5608360efbdSAlfred Perlstein char *lasts;
561330e445cSMatteo Riondato char **nc_lookups;
5628360efbdSAlfred Perlstein
5638360efbdSAlfred Perlstein nc_error = NC_BADFILE; /* nearly anything that breaks is for this reason */
5648360efbdSAlfred Perlstein stringp[strlen(stringp)-1] = '\0'; /* get rid of newline */
5658360efbdSAlfred Perlstein /* netid */
5668360efbdSAlfred Perlstein if ((ncp->nc_netid = strtok_r(stringp, "\t ", &lasts)) == NULL) {
5678360efbdSAlfred Perlstein return (-1);
5688360efbdSAlfred Perlstein }
5698360efbdSAlfred Perlstein
5708360efbdSAlfred Perlstein /* semantics */
5718360efbdSAlfred Perlstein if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) {
5728360efbdSAlfred Perlstein return (-1);
5738360efbdSAlfred Perlstein }
5748360efbdSAlfred Perlstein if (strcmp(tokenp, NC_TPI_COTS_ORD_S) == 0)
5758360efbdSAlfred Perlstein ncp->nc_semantics = NC_TPI_COTS_ORD;
5768360efbdSAlfred Perlstein else if (strcmp(tokenp, NC_TPI_COTS_S) == 0)
5778360efbdSAlfred Perlstein ncp->nc_semantics = NC_TPI_COTS;
5788360efbdSAlfred Perlstein else if (strcmp(tokenp, NC_TPI_CLTS_S) == 0)
5798360efbdSAlfred Perlstein ncp->nc_semantics = NC_TPI_CLTS;
5808360efbdSAlfred Perlstein else if (strcmp(tokenp, NC_TPI_RAW_S) == 0)
5818360efbdSAlfred Perlstein ncp->nc_semantics = NC_TPI_RAW;
5828360efbdSAlfred Perlstein else
5838360efbdSAlfred Perlstein return (-1);
5848360efbdSAlfred Perlstein
5858360efbdSAlfred Perlstein /* flags */
5868360efbdSAlfred Perlstein if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) {
5878360efbdSAlfred Perlstein return (-1);
5888360efbdSAlfred Perlstein }
5898360efbdSAlfred Perlstein for (ncp->nc_flag = NC_NOFLAG; *tokenp != '\0';
5908360efbdSAlfred Perlstein tokenp++) {
5918360efbdSAlfred Perlstein switch (*tokenp) {
5928360efbdSAlfred Perlstein case NC_NOFLAG_C:
5938360efbdSAlfred Perlstein break;
5948360efbdSAlfred Perlstein case NC_VISIBLE_C:
5958360efbdSAlfred Perlstein ncp->nc_flag |= NC_VISIBLE;
5968360efbdSAlfred Perlstein break;
5978360efbdSAlfred Perlstein case NC_BROADCAST_C:
5988360efbdSAlfred Perlstein ncp->nc_flag |= NC_BROADCAST;
5998360efbdSAlfred Perlstein break;
6008360efbdSAlfred Perlstein default:
6018360efbdSAlfred Perlstein return (-1);
6028360efbdSAlfred Perlstein }
6038360efbdSAlfred Perlstein }
6048360efbdSAlfred Perlstein /* protocol family */
6058360efbdSAlfred Perlstein if ((ncp->nc_protofmly = strtok_r(NULL, "\t ", &lasts)) == NULL) {
6068360efbdSAlfred Perlstein return (-1);
6078360efbdSAlfred Perlstein }
6088360efbdSAlfred Perlstein /* protocol name */
6098360efbdSAlfred Perlstein if ((ncp->nc_proto = strtok_r(NULL, "\t ", &lasts)) == NULL) {
6108360efbdSAlfred Perlstein return (-1);
6118360efbdSAlfred Perlstein }
6128360efbdSAlfred Perlstein /* network device */
6138360efbdSAlfred Perlstein if ((ncp->nc_device = strtok_r(NULL, "\t ", &lasts)) == NULL) {
6148360efbdSAlfred Perlstein return (-1);
6158360efbdSAlfred Perlstein }
6168360efbdSAlfred Perlstein if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) {
6178360efbdSAlfred Perlstein return (-1);
6188360efbdSAlfred Perlstein }
6198360efbdSAlfred Perlstein if (strcmp(tokenp, NC_NOLOOKUP) == 0) {
6208360efbdSAlfred Perlstein ncp->nc_nlookups = 0;
6218360efbdSAlfred Perlstein ncp->nc_lookups = NULL;
6228360efbdSAlfred Perlstein } else {
6238360efbdSAlfred Perlstein char *cp; /* tmp string */
6248360efbdSAlfred Perlstein
625c7f7fdd2SEnji Cooper free(ncp->nc_lookups); /* from last visit */
626330e445cSMatteo Riondato ncp->nc_lookups = NULL;
6278360efbdSAlfred Perlstein ncp->nc_nlookups = 0;
6288360efbdSAlfred Perlstein while ((cp = tokenp) != NULL) {
6299f36610fSPedro F. Giffuni if ((nc_lookups = reallocarray(ncp->nc_lookups,
6309f36610fSPedro F. Giffuni ncp->nc_nlookups + 1, sizeof(*ncp->nc_lookups))) == NULL) {
631330e445cSMatteo Riondato free(ncp->nc_lookups);
632330e445cSMatteo Riondato ncp->nc_lookups = NULL;
633330e445cSMatteo Riondato return (-1);
634330e445cSMatteo Riondato }
6358360efbdSAlfred Perlstein tokenp = _get_next_token(cp, ',');
636330e445cSMatteo Riondato ncp->nc_lookups = nc_lookups;
637330e445cSMatteo Riondato ncp->nc_lookups[ncp->nc_nlookups++] = cp;
6388360efbdSAlfred Perlstein }
6398360efbdSAlfred Perlstein }
6408360efbdSAlfred Perlstein return (0);
6418360efbdSAlfred Perlstein }
6428360efbdSAlfred Perlstein
6438360efbdSAlfred Perlstein
6448360efbdSAlfred Perlstein /*
6458360efbdSAlfred Perlstein * Returns a string describing the reason for failure.
6468360efbdSAlfred Perlstein */
6478360efbdSAlfred Perlstein char *
nc_sperror(void)648587cf682SCraig Rodrigues nc_sperror(void)
6498360efbdSAlfred Perlstein {
6508360efbdSAlfred Perlstein const char *message;
6518360efbdSAlfred Perlstein
6528360efbdSAlfred Perlstein switch(nc_error) {
6538360efbdSAlfred Perlstein case NC_NONETCONFIG:
6548360efbdSAlfred Perlstein message = _nc_errors[0];
6558360efbdSAlfred Perlstein break;
6568360efbdSAlfred Perlstein case NC_NOMEM:
6578360efbdSAlfred Perlstein message = _nc_errors[1];
6588360efbdSAlfred Perlstein break;
6598360efbdSAlfred Perlstein case NC_NOTINIT:
6608360efbdSAlfred Perlstein message = _nc_errors[2];
6618360efbdSAlfred Perlstein break;
6628360efbdSAlfred Perlstein case NC_BADFILE:
6638360efbdSAlfred Perlstein message = _nc_errors[3];
6648360efbdSAlfred Perlstein break;
665b3a38fe3SIan Dowse case NC_NOTFOUND:
666b3a38fe3SIan Dowse message = _nc_errors[4];
667b3a38fe3SIan Dowse break;
6688360efbdSAlfred Perlstein default:
6698360efbdSAlfred Perlstein message = "Unknown network selection error";
6708360efbdSAlfred Perlstein }
6718360efbdSAlfred Perlstein /* LINTED const castaway */
6728360efbdSAlfred Perlstein return ((char *)message);
6738360efbdSAlfred Perlstein }
6748360efbdSAlfred Perlstein
6758360efbdSAlfred Perlstein /*
6768360efbdSAlfred Perlstein * Prints a message onto standard error describing the reason for failure.
6778360efbdSAlfred Perlstein */
6788360efbdSAlfred Perlstein void
nc_perror(const char * s)679587cf682SCraig Rodrigues nc_perror(const char *s)
6808360efbdSAlfred Perlstein {
681b3a38fe3SIan Dowse fprintf(stderr, "%s: %s\n", s, nc_sperror());
6828360efbdSAlfred Perlstein }
6838360efbdSAlfred Perlstein
6848360efbdSAlfred Perlstein /*
6858360efbdSAlfred Perlstein * Duplicates the matched netconfig buffer.
6868360efbdSAlfred Perlstein */
6878360efbdSAlfred Perlstein static struct netconfig *
dup_ncp(struct netconfig * ncp)688587cf682SCraig Rodrigues dup_ncp(struct netconfig *ncp)
6898360efbdSAlfred Perlstein {
6908360efbdSAlfred Perlstein struct netconfig *p;
69194c5b2d1SXin LI char *tmp;
6923c788545SMartin Blapp u_int i;
6938360efbdSAlfred Perlstein
6948360efbdSAlfred Perlstein if ((tmp=malloc(MAXNETCONFIGLINE)) == NULL)
6958360efbdSAlfred Perlstein return(NULL);
6968360efbdSAlfred Perlstein if ((p=(struct netconfig *)malloc(sizeof(struct netconfig))) == NULL) {
6978360efbdSAlfred Perlstein free(tmp);
6988360efbdSAlfred Perlstein return(NULL);
6998360efbdSAlfred Perlstein }
7008360efbdSAlfred Perlstein /*
7018360efbdSAlfred Perlstein * First we dup all the data from matched netconfig buffer. Then we
7028360efbdSAlfred Perlstein * adjust some of the member pointer to a pre-allocated buffer where
7038360efbdSAlfred Perlstein * contains part of the data.
7048360efbdSAlfred Perlstein * To follow the convention used in parse_ncp(), we store all the
7053c788545SMartin Blapp * necessary information in the pre-allocated buffer and let each
7068360efbdSAlfred Perlstein * of the netconfig char pointer member point to the right address
7078360efbdSAlfred Perlstein * in the buffer.
7088360efbdSAlfred Perlstein */
7098360efbdSAlfred Perlstein *p = *ncp;
7108360efbdSAlfred Perlstein p->nc_netid = (char *)strcpy(tmp,ncp->nc_netid);
71116fc3635SMark Murray tmp = strchr(tmp, '\0') + 1;
7128360efbdSAlfred Perlstein p->nc_protofmly = (char *)strcpy(tmp,ncp->nc_protofmly);
71316fc3635SMark Murray tmp = strchr(tmp, '\0') + 1;
7148360efbdSAlfred Perlstein p->nc_proto = (char *)strcpy(tmp,ncp->nc_proto);
71516fc3635SMark Murray tmp = strchr(tmp, '\0') + 1;
7168360efbdSAlfred Perlstein p->nc_device = (char *)strcpy(tmp,ncp->nc_device);
7178360efbdSAlfred Perlstein p->nc_lookups = (char **)malloc((size_t)(p->nc_nlookups+1) * sizeof(char *));
7188360efbdSAlfred Perlstein if (p->nc_lookups == NULL) {
7198360efbdSAlfred Perlstein free(p->nc_netid);
720b0718451SMartin Blapp free(p);
7218360efbdSAlfred Perlstein return(NULL);
7228360efbdSAlfred Perlstein }
7238360efbdSAlfred Perlstein for (i=0; i < p->nc_nlookups; i++) {
72416fc3635SMark Murray tmp = strchr(tmp, '\0') + 1;
7258360efbdSAlfred Perlstein p->nc_lookups[i] = (char *)strcpy(tmp,ncp->nc_lookups[i]);
7268360efbdSAlfred Perlstein }
7278360efbdSAlfred Perlstein return(p);
7288360efbdSAlfred Perlstein }
729