xref: /dflybsd-src/lib/libc/rpc/getnetpath.c (revision 678e8cc6002ecd3a79cdae95ac8b454437219fc5)
1ce0e08e2SPeter Avalos /*
2ce0e08e2SPeter Avalos  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
3ce0e08e2SPeter Avalos  * unrestricted use provided that this legend is included on all tape
4ce0e08e2SPeter Avalos  * media and as a part of the software program in whole or part.  Users
5ce0e08e2SPeter Avalos  * may copy or modify Sun RPC without charge, but are not authorized
6ce0e08e2SPeter Avalos  * to license or distribute it to anyone else except as part of a product or
7ce0e08e2SPeter Avalos  * program developed by the user or with the express written consent of
8ce0e08e2SPeter Avalos  * Sun Microsystems, Inc.
9ce0e08e2SPeter Avalos  *
10ce0e08e2SPeter Avalos  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
11ce0e08e2SPeter Avalos  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
12ce0e08e2SPeter Avalos  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
13ce0e08e2SPeter Avalos  *
14ce0e08e2SPeter Avalos  * Sun RPC is provided with no support and without any obligation on the
15ce0e08e2SPeter Avalos  * part of Sun Microsystems, Inc. to assist in its use, correction,
16ce0e08e2SPeter Avalos  * modification or enhancement.
17ce0e08e2SPeter Avalos  *
18ce0e08e2SPeter Avalos  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
19ce0e08e2SPeter Avalos  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
20ce0e08e2SPeter Avalos  * OR ANY PART THEREOF.
21ce0e08e2SPeter Avalos  *
22ce0e08e2SPeter Avalos  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
23ce0e08e2SPeter Avalos  * or profits or other special, indirect and consequential damages, even if
24ce0e08e2SPeter Avalos  * Sun has been advised of the possibility of such damages.
25ce0e08e2SPeter Avalos  *
26ce0e08e2SPeter Avalos  * Sun Microsystems, Inc.
27ce0e08e2SPeter Avalos  * 2550 Garcia Avenue
28ce0e08e2SPeter Avalos  * Mountain View, California  94043
29ce0e08e2SPeter Avalos  *
30ce0e08e2SPeter Avalos  * @(#)getnetpath.c	1.11 91/12/19 SMI
31ce0e08e2SPeter Avalos  * $NetBSD: getnetpath.c,v 1.3 2000/07/06 03:10:34 christos Exp $
32ce0e08e2SPeter Avalos  * $FreeBSD: src/lib/libc/rpc/getnetpath.c,v 1.8 2007/09/20 22:35:24 matteo Exp $
33ce0e08e2SPeter Avalos  */
34ce0e08e2SPeter Avalos 
35ce0e08e2SPeter Avalos /*
36ce0e08e2SPeter Avalos  * Copyright (c) 1989 by Sun Microsystems, Inc.
37ce0e08e2SPeter Avalos  */
38ce0e08e2SPeter Avalos 
39ce0e08e2SPeter Avalos #include "namespace.h"
40ce0e08e2SPeter Avalos #include <stdio.h>
41ce0e08e2SPeter Avalos #include <errno.h>
42ce0e08e2SPeter Avalos #include <netconfig.h>
43ce0e08e2SPeter Avalos #include <stdlib.h>
44ce0e08e2SPeter Avalos #include <string.h>
45ce0e08e2SPeter Avalos #include <syslog.h>
46ce0e08e2SPeter Avalos #include "un-namespace.h"
47ce0e08e2SPeter Avalos 
48ce0e08e2SPeter Avalos /*
49ce0e08e2SPeter Avalos  * internal structure to keep track of a netpath "session"
50ce0e08e2SPeter Avalos  */
51ce0e08e2SPeter Avalos struct netpath_chain {
52ce0e08e2SPeter Avalos     struct netconfig *ncp;  /* an nconf entry */
53ce0e08e2SPeter Avalos     struct netpath_chain *nchain_next;	/* next nconf entry allocated */
54ce0e08e2SPeter Avalos };
55ce0e08e2SPeter Avalos 
56ce0e08e2SPeter Avalos 
57ce0e08e2SPeter Avalos struct netpath_vars {
58ce0e08e2SPeter Avalos     int   valid;	    /* token that indicates a valid netpath_vars */
59ce0e08e2SPeter Avalos     void *nc_handlep;	    /* handle for current netconfig "session" */
60ce0e08e2SPeter Avalos     char *netpath;	    /* pointer to current view-point in NETPATH */
61ce0e08e2SPeter Avalos     char *netpath_start;    /* pointer to start of our copy of NETPATH */
62ce0e08e2SPeter Avalos     struct netpath_chain *ncp_list;  /* list of nconfs allocated this session*/
63ce0e08e2SPeter Avalos };
64ce0e08e2SPeter Avalos 
65ce0e08e2SPeter Avalos #define NP_VALID	0xf00d
66ce0e08e2SPeter Avalos #define NP_INVALID	0
67ce0e08e2SPeter Avalos 
68ce0e08e2SPeter Avalos char *_get_next_token(char *, int);
69ce0e08e2SPeter Avalos 
70ce0e08e2SPeter Avalos 
71ce0e08e2SPeter Avalos /*
72ce0e08e2SPeter Avalos  * A call to setnetpath() establishes a NETPATH "session".  setnetpath()
73ce0e08e2SPeter Avalos  * must be called before the first call to getnetpath().  A "handle" is
74ce0e08e2SPeter Avalos  * returned to distinguish the session; this handle should be passed
75ce0e08e2SPeter Avalos  * subsequently to getnetpath().  (Handles are used to allow for nested calls
76ce0e08e2SPeter Avalos  * to setnetpath()).
77ce0e08e2SPeter Avalos  * If setnetpath() is unable to establish a session (due to lack of memory
78ce0e08e2SPeter Avalos  * resources, or the absence of the /etc/netconfig file), a NULL pointer is
79ce0e08e2SPeter Avalos  * returned.
80ce0e08e2SPeter Avalos  */
81ce0e08e2SPeter Avalos 
82ce0e08e2SPeter Avalos void *
83ce0e08e2SPeter Avalos setnetpath(void)
84ce0e08e2SPeter Avalos {
85ce0e08e2SPeter Avalos 
86ce0e08e2SPeter Avalos     struct netpath_vars *np_sessionp;   /* this session's variables */
87ce0e08e2SPeter Avalos     char *npp;				/* NETPATH env variable */
88ce0e08e2SPeter Avalos 
89ce0e08e2SPeter Avalos #ifdef MEM_CHK
90ce0e08e2SPeter Avalos     malloc_debug(1);
91ce0e08e2SPeter Avalos #endif
92ce0e08e2SPeter Avalos 
93ce0e08e2SPeter Avalos     if ((np_sessionp =
94ce0e08e2SPeter Avalos 	(struct netpath_vars *)malloc(sizeof (struct netpath_vars))) == NULL) {
95ce0e08e2SPeter Avalos 	return (NULL);
96ce0e08e2SPeter Avalos     }
97ce0e08e2SPeter Avalos     if ((np_sessionp->nc_handlep = setnetconfig()) == NULL) {
98ce0e08e2SPeter Avalos 	free(np_sessionp);
99ce0e08e2SPeter Avalos 	syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
100ce0e08e2SPeter Avalos 	goto failed;
101ce0e08e2SPeter Avalos     }
102ce0e08e2SPeter Avalos     np_sessionp->valid = NP_VALID;
103ce0e08e2SPeter Avalos     np_sessionp->ncp_list = NULL;
104ce0e08e2SPeter Avalos     if ((npp = getenv(NETPATH)) == NULL) {
105ce0e08e2SPeter Avalos 	np_sessionp->netpath = NULL;
106ce0e08e2SPeter Avalos     } else {
107ce0e08e2SPeter Avalos 	endnetconfig(np_sessionp->nc_handlep);/* won't need nc session*/
108ce0e08e2SPeter Avalos 	np_sessionp->nc_handlep = NULL;
109ce0e08e2SPeter Avalos 	if ((np_sessionp->netpath = malloc(strlen(npp)+1)) == NULL)
110ce0e08e2SPeter Avalos 		goto failed;
111ce0e08e2SPeter Avalos 	else {
112ce0e08e2SPeter Avalos 	    strcpy(np_sessionp->netpath, npp);
113ce0e08e2SPeter Avalos 	}
114ce0e08e2SPeter Avalos     }
115ce0e08e2SPeter Avalos     np_sessionp->netpath_start = np_sessionp->netpath;
116ce0e08e2SPeter Avalos     return ((void *)np_sessionp);
117ce0e08e2SPeter Avalos 
118ce0e08e2SPeter Avalos failed:
119ce0e08e2SPeter Avalos     free(np_sessionp);
120ce0e08e2SPeter Avalos     return (NULL);
121ce0e08e2SPeter Avalos }
122ce0e08e2SPeter Avalos 
123ce0e08e2SPeter Avalos /*
124ce0e08e2SPeter Avalos  * When first called, getnetpath() returns a pointer to the netconfig
125ce0e08e2SPeter Avalos  * database entry corresponding to the first valid NETPATH component.  The
126ce0e08e2SPeter Avalos  * netconfig entry is formatted as a struct netconfig.
127ce0e08e2SPeter Avalos  * On each subsequent call, getnetpath returns a pointer to the netconfig
128ce0e08e2SPeter Avalos  * entry that corresponds to the next valid NETPATH component.  getnetpath
129ce0e08e2SPeter Avalos  * can thus be used to search the netconfig database for all networks
130ce0e08e2SPeter Avalos  * included in the NETPATH variable.
131ce0e08e2SPeter Avalos  * When NETPATH has been exhausted, getnetpath() returns NULL.  It returns
132ce0e08e2SPeter Avalos  * NULL and sets errno in case of an error (e.g., setnetpath was not called
133ce0e08e2SPeter Avalos  * previously).
134ce0e08e2SPeter Avalos  * getnetpath() silently ignores invalid NETPATH components.  A NETPATH
135ce0e08e2SPeter Avalos  * compnent is invalid if there is no corresponding entry in the netconfig
136ce0e08e2SPeter Avalos  * database.
137ce0e08e2SPeter Avalos  * If the NETPATH variable is unset, getnetpath() behaves as if NETPATH
138ce0e08e2SPeter Avalos  * were set to the sequence of default or visible networks in the netconfig
139ce0e08e2SPeter Avalos  * database, in the order in which they are listed.
140ce0e08e2SPeter Avalos  */
141ce0e08e2SPeter Avalos 
142ce0e08e2SPeter Avalos struct netconfig *
143ce0e08e2SPeter Avalos getnetpath(void *handlep)
144ce0e08e2SPeter Avalos {
145ce0e08e2SPeter Avalos     struct netpath_vars *np_sessionp = (struct netpath_vars *)handlep;
146ce0e08e2SPeter Avalos     struct netconfig *ncp = NULL;   /* temp. holds a netconfig session */
147ce0e08e2SPeter Avalos     struct netpath_chain *chainp;   /* holds chain of ncp's we alloc */
148ce0e08e2SPeter Avalos     char  *npp;		/* holds current NETPATH */
149ce0e08e2SPeter Avalos 
150ce0e08e2SPeter Avalos     if (np_sessionp == NULL || np_sessionp->valid != NP_VALID) {
151ce0e08e2SPeter Avalos 	errno = EINVAL;
152ce0e08e2SPeter Avalos 	return (NULL);
153ce0e08e2SPeter Avalos     }
154ce0e08e2SPeter Avalos     if (np_sessionp->netpath_start == NULL) {	/* NETPATH was not set */
155ce0e08e2SPeter Avalos 	do {                /* select next visible network */
156ce0e08e2SPeter Avalos 	    if (np_sessionp->nc_handlep == NULL) {
157ce0e08e2SPeter Avalos 		np_sessionp->nc_handlep = setnetconfig();
158ce0e08e2SPeter Avalos 		if (np_sessionp->nc_handlep == NULL)
159ce0e08e2SPeter Avalos 		    syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
160ce0e08e2SPeter Avalos 	    }
161ce0e08e2SPeter Avalos 	    if ((ncp = getnetconfig(np_sessionp->nc_handlep)) == NULL) {
162ce0e08e2SPeter Avalos 		return(NULL);
163ce0e08e2SPeter Avalos 	    }
164ce0e08e2SPeter Avalos 	} while ((ncp->nc_flag & NC_VISIBLE) == 0);
165ce0e08e2SPeter Avalos 	return (ncp);
166ce0e08e2SPeter Avalos     }
167ce0e08e2SPeter Avalos     /*
168ce0e08e2SPeter Avalos      * Find first valid network ID in netpath.
169ce0e08e2SPeter Avalos      */
170ce0e08e2SPeter Avalos     while ((npp = np_sessionp->netpath) != NULL && strlen(npp) != 0) {
171ce0e08e2SPeter Avalos 	np_sessionp->netpath = _get_next_token(npp, ':');
172ce0e08e2SPeter Avalos 	/*
173ce0e08e2SPeter Avalos 	 * npp is a network identifier.
174ce0e08e2SPeter Avalos 	 */
175ce0e08e2SPeter Avalos 	if ((ncp = getnetconfigent(npp)) != NULL) {
176ce0e08e2SPeter Avalos 	    chainp = (struct netpath_chain *)	/* cobble alloc chain entry */
177ce0e08e2SPeter Avalos 		    malloc(sizeof (struct netpath_chain));
178ce0e08e2SPeter Avalos 	    chainp->ncp = ncp;
179ce0e08e2SPeter Avalos 	    chainp->nchain_next = NULL;
180ce0e08e2SPeter Avalos 	    if (np_sessionp->ncp_list == NULL) {
181ce0e08e2SPeter Avalos 		np_sessionp->ncp_list = chainp;
182ce0e08e2SPeter Avalos 	    } else {
183ce0e08e2SPeter Avalos 		np_sessionp->ncp_list->nchain_next = chainp;
184ce0e08e2SPeter Avalos 	    }
185ce0e08e2SPeter Avalos 	    return (ncp);
186ce0e08e2SPeter Avalos 	}
187ce0e08e2SPeter Avalos 	/* couldn't find this token in the database; go to next one. */
188ce0e08e2SPeter Avalos     }
189ce0e08e2SPeter Avalos     return (NULL);
190ce0e08e2SPeter Avalos }
191ce0e08e2SPeter Avalos 
192ce0e08e2SPeter Avalos /*
193ce0e08e2SPeter Avalos  * endnetpath() may be called to unbind NETPATH when processing is complete,
194ce0e08e2SPeter Avalos  * releasing resources for reuse.  It returns 0 on success and -1 on failure
195ce0e08e2SPeter Avalos  * (e.g. if setnetpath() was not called previously.
196ce0e08e2SPeter Avalos  */
197ce0e08e2SPeter Avalos int
198ce0e08e2SPeter Avalos endnetpath(void *handlep)
199ce0e08e2SPeter Avalos {
200ce0e08e2SPeter Avalos     struct netpath_vars *np_sessionp = (struct netpath_vars *)handlep;
201ce0e08e2SPeter Avalos     struct netpath_chain *chainp, *lastp;
202ce0e08e2SPeter Avalos 
203ce0e08e2SPeter Avalos     if (np_sessionp == NULL || np_sessionp->valid != NP_VALID) {
204ce0e08e2SPeter Avalos 	errno = EINVAL;
205ce0e08e2SPeter Avalos 	return (-1);
206ce0e08e2SPeter Avalos     }
207ce0e08e2SPeter Avalos     if (np_sessionp->nc_handlep != NULL)
208ce0e08e2SPeter Avalos 	endnetconfig(np_sessionp->nc_handlep);
209ce0e08e2SPeter Avalos     if (np_sessionp->netpath_start != NULL)
210ce0e08e2SPeter Avalos 	free(np_sessionp->netpath_start);
211ce0e08e2SPeter Avalos     for (chainp = np_sessionp->ncp_list; chainp != NULL;
212ce0e08e2SPeter Avalos 	    lastp=chainp, chainp=chainp->nchain_next, free(lastp)) {
213ce0e08e2SPeter Avalos 	freenetconfigent(chainp->ncp);
214ce0e08e2SPeter Avalos     }
215ce0e08e2SPeter Avalos     free(np_sessionp);
216ce0e08e2SPeter Avalos #ifdef MEM_CHK
217ce0e08e2SPeter Avalos     if (malloc_verify() == 0) {
218ce0e08e2SPeter Avalos 	fprintf(stderr, "memory heap corrupted in endnetpath\n");
219ce0e08e2SPeter Avalos 	exit(1);
220ce0e08e2SPeter Avalos     }
221ce0e08e2SPeter Avalos #endif
222ce0e08e2SPeter Avalos     return (0);
223ce0e08e2SPeter Avalos }
224ce0e08e2SPeter Avalos 
225ce0e08e2SPeter Avalos 
226ce0e08e2SPeter Avalos 
227ce0e08e2SPeter Avalos /*
228ce0e08e2SPeter Avalos  * Returns pointer to the rest-of-the-string after the current token.
229ce0e08e2SPeter Avalos  * The token itself starts at arg, and we null terminate it.  We return NULL
230ce0e08e2SPeter Avalos  * if either the arg is empty, or if this is the last token.
231ce0e08e2SPeter Avalos  */
232ce0e08e2SPeter Avalos 
233ce0e08e2SPeter Avalos char *
234ce0e08e2SPeter Avalos _get_next_token(char *npp,		/* string */
235ce0e08e2SPeter Avalos 		int token)		/* char to parse string for */
236ce0e08e2SPeter Avalos {
237ce0e08e2SPeter Avalos     char  *cp;		/* char pointer */
238ce0e08e2SPeter Avalos     char  *np;		/* netpath pointer */
239ce0e08e2SPeter Avalos     char  *ep;		/* escape pointer */
240ce0e08e2SPeter Avalos 
241ce0e08e2SPeter Avalos     if ((cp = strchr(npp, token)) == NULL) {
242ce0e08e2SPeter Avalos 	return (NULL);
243ce0e08e2SPeter Avalos     }
244ce0e08e2SPeter Avalos     /*
245ce0e08e2SPeter Avalos      * did find a token, but it might be escaped.
246ce0e08e2SPeter Avalos      */
247ce0e08e2SPeter Avalos     if ((cp > npp) && (cp[-1] == '\\')) {
248ce0e08e2SPeter Avalos         /* if slash was also escaped, carry on, otherwise find next token */
249ce0e08e2SPeter Avalos 	if ((cp > npp + 1) && (cp[-2] != '\\')) {
250ce0e08e2SPeter Avalos 	    /* shift r-o-s  onto the escaped token */
251ce0e08e2SPeter Avalos 	    strcpy(&cp[-1], cp);    /* XXX: overlapping string copy */
252ce0e08e2SPeter Avalos 	    /*
253ce0e08e2SPeter Avalos 	     * Do a recursive call.
254ce0e08e2SPeter Avalos 	     * We don't know how many escaped tokens there might be.
255ce0e08e2SPeter Avalos 	     */
256ce0e08e2SPeter Avalos 	    return (_get_next_token(cp, token));
257ce0e08e2SPeter Avalos 	}
258ce0e08e2SPeter Avalos     }
259ce0e08e2SPeter Avalos 
260ce0e08e2SPeter Avalos     *cp++ = '\0';		/* null-terminate token */
261ce0e08e2SPeter Avalos     /* get rid of any backslash escapes */
262ce0e08e2SPeter Avalos     ep = npp;
263*678e8cc6SSascha Wildner     while ((np = strchr(ep, '\\')) != NULL) {
264ce0e08e2SPeter Avalos 	if (np[1] == '\\')
265ce0e08e2SPeter Avalos 	    np++;
266ce0e08e2SPeter Avalos 	strcpy(np, (ep = &np[1]));  /* XXX: overlapping string copy */
267ce0e08e2SPeter Avalos     }
268ce0e08e2SPeter Avalos     return (cp);		/* return ptr to r-o-s */
269ce0e08e2SPeter Avalos }
270