xref: /minix3/lib/libc/rpc/getnetpath.c (revision 84d9c625bfea59e274550651111ae9edfdc40fbd)
1*84d9c625SLionel Sambuc /*	$NetBSD: getnetpath.c,v 1.17 2013/03/11 20:19:29 tron Exp $	*/
22fe8fb19SBen Gras 
32fe8fb19SBen Gras /*
4*84d9c625SLionel Sambuc  * Copyright (c) 2010, Oracle America, Inc.
52fe8fb19SBen Gras  *
6*84d9c625SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
7*84d9c625SLionel Sambuc  * modification, are permitted provided that the following conditions are
8*84d9c625SLionel Sambuc  * met:
92fe8fb19SBen Gras  *
10*84d9c625SLionel Sambuc  *     * Redistributions of source code must retain the above copyright
11*84d9c625SLionel Sambuc  *       notice, this list of conditions and the following disclaimer.
12*84d9c625SLionel Sambuc  *     * Redistributions in binary form must reproduce the above
13*84d9c625SLionel Sambuc  *       copyright notice, this list of conditions and the following
14*84d9c625SLionel Sambuc  *       disclaimer in the documentation and/or other materials
15*84d9c625SLionel Sambuc  *       provided with the distribution.
16*84d9c625SLionel Sambuc  *     * Neither the name of the "Oracle America, Inc." nor the names of its
17*84d9c625SLionel Sambuc  *       contributors may be used to endorse or promote products derived
18*84d9c625SLionel Sambuc  *       from this software without specific prior written permission.
192fe8fb19SBen Gras  *
20*84d9c625SLionel Sambuc  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21*84d9c625SLionel Sambuc  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*84d9c625SLionel Sambuc  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23*84d9c625SLionel Sambuc  *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24*84d9c625SLionel Sambuc  *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25*84d9c625SLionel Sambuc  *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26*84d9c625SLionel Sambuc  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27*84d9c625SLionel Sambuc  *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28*84d9c625SLionel Sambuc  *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29*84d9c625SLionel Sambuc  *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30*84d9c625SLionel Sambuc  *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31*84d9c625SLionel Sambuc  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
322fe8fb19SBen Gras  */
332fe8fb19SBen Gras 
342fe8fb19SBen Gras #include <sys/cdefs.h>
352fe8fb19SBen Gras #if defined(LIBC_SCCS) && !defined(lint)
362fe8fb19SBen Gras #if 0
372fe8fb19SBen Gras static        char sccsid[] = "@(#)getnetpath.c	1.11 91/12/19 SMI";
382fe8fb19SBen Gras #else
39*84d9c625SLionel Sambuc __RCSID("$NetBSD: getnetpath.c,v 1.17 2013/03/11 20:19:29 tron Exp $");
402fe8fb19SBen Gras #endif
412fe8fb19SBen Gras #endif
422fe8fb19SBen Gras 
432fe8fb19SBen Gras /*
442fe8fb19SBen Gras  * Copyright (c) 1989 by Sun Microsystems, Inc.
452fe8fb19SBen Gras  */
462fe8fb19SBen Gras 
472fe8fb19SBen Gras #include "namespace.h"
482fe8fb19SBen Gras #include <stdio.h>
492fe8fb19SBen Gras #include <assert.h>
502fe8fb19SBen Gras #include <errno.h>
512fe8fb19SBen Gras #include <netconfig.h>
522fe8fb19SBen Gras #include <stdlib.h>
532fe8fb19SBen Gras #include <string.h>
542fe8fb19SBen Gras #include <syslog.h>
552fe8fb19SBen Gras 
562fe8fb19SBen Gras #ifdef __weak_alias
572fe8fb19SBen Gras __weak_alias(getnetpath,_getnetpath)
582fe8fb19SBen Gras __weak_alias(setnetpath,_setnetpath)
592fe8fb19SBen Gras __weak_alias(endnetpath,_endnetpath)
602fe8fb19SBen Gras #endif
612fe8fb19SBen Gras 
622fe8fb19SBen Gras /*
632fe8fb19SBen Gras  * internal structure to keep track of a netpath "session"
642fe8fb19SBen Gras  */
652fe8fb19SBen Gras struct netpath_chain {
662fe8fb19SBen Gras 	struct netconfig *ncp;  		/* an nconf entry */
672fe8fb19SBen Gras 	struct netpath_chain *nchain_next;	/* next nconf entry allocated */
682fe8fb19SBen Gras };
692fe8fb19SBen Gras 
702fe8fb19SBen Gras 
712fe8fb19SBen Gras struct netpath_vars {
722fe8fb19SBen Gras 	int   valid;		/* token that indicates a valid netpath_vars */
732fe8fb19SBen Gras 	void *nc_handlep;	/* handle for current netconfig "session" */
742fe8fb19SBen Gras 	char *netpath;		/* pointer to current view-point in NETPATH */
752fe8fb19SBen Gras 	char *netpath_start;	/* pointer to start of our copy of NETPATH */
762fe8fb19SBen Gras 	struct netpath_chain *ncp_list;  /* list of nconfs allocated this session*/
772fe8fb19SBen Gras };
782fe8fb19SBen Gras 
792fe8fb19SBen Gras #define NP_VALID	0xf00d
802fe8fb19SBen Gras #define NP_INVALID	0
812fe8fb19SBen Gras 
82f14fb602SLionel Sambuc char *_get_next_token(char *, int);
832fe8fb19SBen Gras 
842fe8fb19SBen Gras 
852fe8fb19SBen Gras /*
862fe8fb19SBen Gras  * A call to setnetpath() establishes a NETPATH "session".  setnetpath()
872fe8fb19SBen Gras  * must be called before the first call to getnetpath().  A "handle" is
882fe8fb19SBen Gras  * returned to distinguish the session; this handle should be passed
892fe8fb19SBen Gras  * subsequently to getnetpath().  (Handles are used to allow for nested calls
902fe8fb19SBen Gras  * to setnetpath()).
912fe8fb19SBen Gras  * If setnetpath() is unable to establish a session (due to lack of memory
922fe8fb19SBen Gras  * resources, or the absence of the /etc/netconfig file), a NULL pointer is
932fe8fb19SBen Gras  * returned.
942fe8fb19SBen Gras  */
952fe8fb19SBen Gras 
962fe8fb19SBen Gras void *
setnetpath(void)97f14fb602SLionel Sambuc setnetpath(void)
982fe8fb19SBen Gras {
992fe8fb19SBen Gras 	struct netpath_vars *np_sessionp;   /* this session's variables */
1002fe8fb19SBen Gras 	char *npp;				/* NETPATH env variable */
1012fe8fb19SBen Gras 
1022fe8fb19SBen Gras #ifdef MEM_CHK
1032fe8fb19SBen Gras 	malloc_debug(1);
1042fe8fb19SBen Gras #endif
1052fe8fb19SBen Gras 
1062fe8fb19SBen Gras 	if ((np_sessionp = malloc(sizeof(*np_sessionp))) == NULL)
1072fe8fb19SBen Gras 		return (NULL);
1082fe8fb19SBen Gras 	if ((np_sessionp->nc_handlep = setnetconfig()) == NULL) {
1092fe8fb19SBen Gras 		free(np_sessionp);
1102fe8fb19SBen Gras 		syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
1112fe8fb19SBen Gras 		return (NULL);
1122fe8fb19SBen Gras 	}
1132fe8fb19SBen Gras 	np_sessionp->valid = NP_VALID;
1142fe8fb19SBen Gras 	np_sessionp->ncp_list = NULL;
1152fe8fb19SBen Gras 	if ((npp = getenv(NETPATH)) == NULL)
1162fe8fb19SBen Gras 		np_sessionp->netpath = NULL;
1172fe8fb19SBen Gras 	else {
1182fe8fb19SBen Gras 		(void) endnetconfig(np_sessionp->nc_handlep);
1192fe8fb19SBen Gras 					/* won't need nc session*/
1202fe8fb19SBen Gras 		np_sessionp->nc_handlep = NULL;
1212fe8fb19SBen Gras 		if ((np_sessionp->netpath = malloc(strlen(npp)+1)) == NULL) {
1222fe8fb19SBen Gras 			free(np_sessionp);
1232fe8fb19SBen Gras 			return (NULL);
1242fe8fb19SBen Gras 		} else
1252fe8fb19SBen Gras 			(void) strcpy(np_sessionp->netpath, npp);
1262fe8fb19SBen Gras 	}
1272fe8fb19SBen Gras 	np_sessionp->netpath_start = np_sessionp->netpath;
1282fe8fb19SBen Gras 	return ((void *)np_sessionp);
1292fe8fb19SBen Gras }
1302fe8fb19SBen Gras 
1312fe8fb19SBen Gras /*
1322fe8fb19SBen Gras  * When first called, getnetpath() returns a pointer to the netconfig
1332fe8fb19SBen Gras  * database entry corresponding to the first valid NETPATH component.  The
1342fe8fb19SBen Gras  * netconfig entry is formatted as a struct netconfig.
1352fe8fb19SBen Gras  * On each subsequent call, getnetpath returns a pointer to the netconfig
1362fe8fb19SBen Gras  * entry that corresponds to the next valid NETPATH component.  getnetpath
1372fe8fb19SBen Gras  * can thus be used to search the netconfig database for all networks
1382fe8fb19SBen Gras  * included in the NETPATH variable.
1392fe8fb19SBen Gras  * When NETPATH has been exhausted, getnetpath() returns NULL.  It returns
1402fe8fb19SBen Gras  * NULL and sets errno in case of an error (e.g., setnetpath was not called
1412fe8fb19SBen Gras  * previously).
1422fe8fb19SBen Gras  * getnetpath() silently ignores invalid NETPATH components.  A NETPATH
1432fe8fb19SBen Gras  * compnent is invalid if there is no corresponding entry in the netconfig
1442fe8fb19SBen Gras  * database.
1452fe8fb19SBen Gras  * If the NETPATH variable is unset, getnetpath() behaves as if NETPATH
1462fe8fb19SBen Gras  * were set to the sequence of default or visible networks in the netconfig
1472fe8fb19SBen Gras  * database, in the order in which they are listed.
1482fe8fb19SBen Gras  */
1492fe8fb19SBen Gras 
1502fe8fb19SBen Gras struct netconfig *
getnetpath(void * handlep)151f14fb602SLionel Sambuc getnetpath(void *handlep)
1522fe8fb19SBen Gras {
1532fe8fb19SBen Gras 	struct netpath_vars *np_sessionp = (struct netpath_vars *)handlep;
1542fe8fb19SBen Gras 	struct netconfig *ncp = NULL;   /* temp. holds a netconfig session */
1552fe8fb19SBen Gras 	struct netpath_chain *chainp;   /* holds chain of ncp's we alloc */
1562fe8fb19SBen Gras 	char  *npp;		/* holds current NETPATH */
1572fe8fb19SBen Gras 
1582fe8fb19SBen Gras 	if (np_sessionp == NULL || np_sessionp->valid != NP_VALID) {
1592fe8fb19SBen Gras 		errno = EINVAL;
1602fe8fb19SBen Gras 		return (NULL);
1612fe8fb19SBen Gras 	}
1622fe8fb19SBen Gras 	if (np_sessionp->netpath_start == NULL) { /* NETPATH was not set */
1632fe8fb19SBen Gras 		do {                /* select next visible network */
1642fe8fb19SBen Gras 			if (np_sessionp->nc_handlep == NULL) {
1652fe8fb19SBen Gras 				np_sessionp->nc_handlep = setnetconfig();
1662fe8fb19SBen Gras 				if (np_sessionp->nc_handlep == NULL)
1672fe8fb19SBen Gras 					syslog (LOG_ERR,
1682fe8fb19SBen Gras 					    "rpc: failed to open " NETCONFIG);
1692fe8fb19SBen Gras 			}
1702fe8fb19SBen Gras 			if ((ncp = getnetconfig(np_sessionp->nc_handlep))
1712fe8fb19SBen Gras 			    == NULL)
1722fe8fb19SBen Gras 				return(NULL);
1732fe8fb19SBen Gras 		} while ((ncp->nc_flag & NC_VISIBLE) == 0);
1742fe8fb19SBen Gras 		return (ncp);
1752fe8fb19SBen Gras 	}
1762fe8fb19SBen Gras 	/*
1772fe8fb19SBen Gras 	 * Find first valid network ID in netpath.
1782fe8fb19SBen Gras 	 */
1792fe8fb19SBen Gras 	while ((npp = np_sessionp->netpath) != NULL && strlen(npp) != 0) {
1802fe8fb19SBen Gras 		np_sessionp->netpath = _get_next_token(npp, ':');
1812fe8fb19SBen Gras 		/*
1822fe8fb19SBen Gras 		 * npp is a network identifier.
1832fe8fb19SBen Gras 		 */
1842fe8fb19SBen Gras 		if ((ncp = getnetconfigent(npp)) != NULL) {
1852fe8fb19SBen Gras 					/* cobble alloc chain entry */
1862fe8fb19SBen Gras 			chainp = malloc(sizeof (struct netpath_chain));
1872fe8fb19SBen Gras 			if (chainp == NULL) {
1882fe8fb19SBen Gras 				freenetconfigent(ncp);
1892fe8fb19SBen Gras 				return NULL;
1902fe8fb19SBen Gras 			}
1912fe8fb19SBen Gras 			chainp->ncp = ncp;
1922fe8fb19SBen Gras 			chainp->nchain_next = NULL;
1932fe8fb19SBen Gras 			if (np_sessionp->ncp_list == NULL)
1942fe8fb19SBen Gras 				np_sessionp->ncp_list = chainp;
1952fe8fb19SBen Gras 			else
1962fe8fb19SBen Gras 				np_sessionp->ncp_list->nchain_next = chainp;
1972fe8fb19SBen Gras 			return (ncp);
1982fe8fb19SBen Gras 		}
1992fe8fb19SBen Gras 		/* couldn't find this token in the database; go to next one. */
2002fe8fb19SBen Gras 	}
2012fe8fb19SBen Gras 	return (NULL);
2022fe8fb19SBen Gras }
2032fe8fb19SBen Gras 
2042fe8fb19SBen Gras /*
2052fe8fb19SBen Gras  * endnetpath() may be called to unbind NETPATH when processing is complete,
2062fe8fb19SBen Gras  * releasing resources for reuse.  It returns 0 on success and -1 on failure
2072fe8fb19SBen Gras  * (e.g. if setnetpath() was not called previously.
2082fe8fb19SBen Gras  */
2092fe8fb19SBen Gras int
endnetpath(void * handlep)210f14fb602SLionel Sambuc endnetpath(void *handlep)
2112fe8fb19SBen Gras {
2122fe8fb19SBen Gras 	struct netpath_vars *np_sessionp = (struct netpath_vars *)handlep;
2132fe8fb19SBen Gras 	struct netpath_chain *chainp, *lastp;
2142fe8fb19SBen Gras 
2152fe8fb19SBen Gras 	if (np_sessionp == NULL || np_sessionp->valid != NP_VALID) {
2162fe8fb19SBen Gras 		errno = EINVAL;
2172fe8fb19SBen Gras 		return (-1);
2182fe8fb19SBen Gras 	}
2192fe8fb19SBen Gras 	if (np_sessionp->nc_handlep != NULL)
2202fe8fb19SBen Gras 		endnetconfig(np_sessionp->nc_handlep);
2212fe8fb19SBen Gras 	if (np_sessionp->netpath_start != NULL)
2222fe8fb19SBen Gras 		free(np_sessionp->netpath_start);
2232fe8fb19SBen Gras 	for (chainp = np_sessionp->ncp_list; chainp != NULL;
2242fe8fb19SBen Gras 	    lastp=chainp, chainp=chainp->nchain_next, free(lastp)) {
2252fe8fb19SBen Gras 		freenetconfigent(chainp->ncp);
2262fe8fb19SBen Gras 	}
2272fe8fb19SBen Gras 	free(np_sessionp);
2282fe8fb19SBen Gras #ifdef MEM_CHK
2292fe8fb19SBen Gras 	if (malloc_verify() == 0) {
2302fe8fb19SBen Gras 		fprintf(stderr, "memory heap corrupted in endnetpath\n");
2312fe8fb19SBen Gras 		exit(1);
2322fe8fb19SBen Gras 	}
2332fe8fb19SBen Gras #endif
2342fe8fb19SBen Gras 	return (0);
2352fe8fb19SBen Gras }
2362fe8fb19SBen Gras 
2372fe8fb19SBen Gras 
2382fe8fb19SBen Gras /*
2392fe8fb19SBen Gras  * Returns pointer to the rest-of-the-string after the current token.
2402fe8fb19SBen Gras  * The token itself starts at arg, and we null terminate it.  We return NULL
2412fe8fb19SBen Gras  * if either the arg is empty, or if this is the last token.
2422fe8fb19SBen Gras  */
2432fe8fb19SBen Gras 
2442fe8fb19SBen Gras char *
_get_next_token(char * npp,int token)2452fe8fb19SBen Gras _get_next_token(
2462fe8fb19SBen Gras 	char *npp,		/* string */
2472fe8fb19SBen Gras 	int token		/* char to parse string for */
2482fe8fb19SBen Gras )
2492fe8fb19SBen Gras {
2502fe8fb19SBen Gras 	char  *cp;		/* char pointer */
2512fe8fb19SBen Gras 	char  *np;		/* netpath pointer */
2522fe8fb19SBen Gras 	char  *ep;		/* escape pointer */
2532fe8fb19SBen Gras 
2542fe8fb19SBen Gras 	_DIAGASSERT(npp != NULL);
2552fe8fb19SBen Gras 
2562fe8fb19SBen Gras 	if ((cp = strchr(npp, token)) == NULL)
2572fe8fb19SBen Gras 		return (NULL);
2582fe8fb19SBen Gras 	/*
2592fe8fb19SBen Gras 	 * did find a token, but it might be escaped.
2602fe8fb19SBen Gras 	 */
2612fe8fb19SBen Gras 	if ((cp > npp) && (cp[-1] == '\\')) {
2622fe8fb19SBen Gras 		/*
2632fe8fb19SBen Gras 		 * if slash was also escaped, carry on, otherwise find
2642fe8fb19SBen Gras 		 * next token
2652fe8fb19SBen Gras 		 */
2662fe8fb19SBen Gras 		if ((cp > npp + 1) && (cp[-2] != '\\')) {
2672fe8fb19SBen Gras 			/* shift r-o-s  onto the escaped token */
2682fe8fb19SBen Gras 			strcpy(&cp[-1], cp);  /* XXX: overlapping string copy */
2692fe8fb19SBen Gras 			/*
2702fe8fb19SBen Gras 			 * Do a recursive call.
2712fe8fb19SBen Gras 			 * We don't know how many escaped tokens there might be.
2722fe8fb19SBen Gras 			 */
2732fe8fb19SBen Gras 			return (_get_next_token(cp, token));
2742fe8fb19SBen Gras 		}
2752fe8fb19SBen Gras 	}
2762fe8fb19SBen Gras 
2772fe8fb19SBen Gras 	*cp++ = '\0';		/* null-terminate token */
2782fe8fb19SBen Gras 	/* get rid of any backslash escapes */
2792fe8fb19SBen Gras 	ep = npp;
2802fe8fb19SBen Gras 	while ((np = strchr(ep, '\\')) != 0) {
2812fe8fb19SBen Gras 		if (np[1] == '\\')
2822fe8fb19SBen Gras 			np++;
2832fe8fb19SBen Gras 		strcpy(np, (ep = &np[1]));  /* XXX: overlapping string copy */
2842fe8fb19SBen Gras 	}
2852fe8fb19SBen Gras 	return (cp);		/* return ptr to r-o-s */
2862fe8fb19SBen Gras }
287