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