174462Salfred/* $NetBSD: rpc_generic.c,v 1.4 2000/09/28 09:07:04 kleink Exp $ */ 274462Salfred 3261046Smav/*- 4261046Smav * Copyright (c) 2009, Sun Microsystems, Inc. 5261046Smav * All rights reserved. 6261046Smav * 7261046Smav * Redistribution and use in source and binary forms, with or without 8261046Smav * modification, are permitted provided that the following conditions are met: 9261046Smav * - Redistributions of source code must retain the above copyright notice, 10261046Smav * this list of conditions and the following disclaimer. 11261046Smav * - Redistributions in binary form must reproduce the above copyright notice, 12261046Smav * this list of conditions and the following disclaimer in the documentation 13261046Smav * and/or other materials provided with the distribution. 14261046Smav * - Neither the name of Sun Microsystems, Inc. nor the names of its 15261046Smav * contributors may be used to endorse or promote products derived 16261046Smav * from this software without specific prior written permission. 1774462Salfred * 18261046Smav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19261046Smav * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20261046Smav * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21261046Smav * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22261046Smav * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23261046Smav * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24261046Smav * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25261046Smav * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26261046Smav * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27261046Smav * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28261046Smav * POSSIBILITY OF SUCH DAMAGE. 2974462Salfred */ 3074462Salfred/* 3174462Salfred * Copyright (c) 1986-1991 by Sun Microsystems Inc. 3274462Salfred */ 3374462Salfred 3474462Salfred/* #pragma ident "@(#)rpc_generic.c 1.17 94/04/24 SMI" */ 3592990Sobrien#include <sys/cdefs.h> 3692990Sobrien__FBSDID("$FreeBSD$"); 3774462Salfred 3874462Salfred/* 3974462Salfred * rpc_generic.c, Miscl routines for RPC. 4074462Salfred * 4174462Salfred */ 4274462Salfred 4375094Siedowse#include "namespace.h" 4474462Salfred#include "reentrant.h" 4574462Salfred#include <sys/types.h> 4674462Salfred#include <sys/param.h> 4774462Salfred#include <sys/socket.h> 4874462Salfred#include <sys/time.h> 4974462Salfred#include <sys/un.h> 5074462Salfred#include <sys/resource.h> 5174462Salfred#include <netinet/in.h> 5274462Salfred#include <arpa/inet.h> 5374462Salfred#include <rpc/rpc.h> 5474462Salfred#include <ctype.h> 5576523Siedowse#include <stddef.h> 5674462Salfred#include <stdio.h> 5774462Salfred#include <netdb.h> 5874462Salfred#include <netconfig.h> 5974462Salfred#include <stdlib.h> 6074462Salfred#include <string.h> 6174462Salfred#include <syslog.h> 6274462Salfred#include <rpc/nettype.h> 6374462Salfred#include "un-namespace.h" 6474462Salfred#include "rpc_com.h" 65156090Sdeischen#include "mt_misc.h" 6674462Salfred 6774462Salfredstruct handle { 6874462Salfred NCONF_HANDLE *nhandle; 6974462Salfred int nflag; /* Whether NETPATH or NETCONFIG */ 7074462Salfred int nettype; 7174462Salfred}; 7274462Salfred 7374462Salfredstatic const struct _rpcnettype { 7474462Salfred const char *name; 7574462Salfred const int type; 7674462Salfred} _rpctypelist[] = { 7774462Salfred { "netpath", _RPC_NETPATH }, 7874462Salfred { "visible", _RPC_VISIBLE }, 7974462Salfred { "circuit_v", _RPC_CIRCUIT_V }, 8074462Salfred { "datagram_v", _RPC_DATAGRAM_V }, 8174462Salfred { "circuit_n", _RPC_CIRCUIT_N }, 8274462Salfred { "datagram_n", _RPC_DATAGRAM_N }, 8374462Salfred { "tcp", _RPC_TCP }, 8474462Salfred { "udp", _RPC_UDP }, 8574462Salfred { 0, _RPC_NONE } 8674462Salfred}; 8774462Salfred 8874462Salfredstruct netid_af { 8974462Salfred const char *netid; 9074462Salfred int af; 9174462Salfred int protocol; 9274462Salfred}; 9374462Salfred 9474462Salfredstatic const struct netid_af na_cvt[] = { 9574462Salfred { "udp", AF_INET, IPPROTO_UDP }, 9674462Salfred { "tcp", AF_INET, IPPROTO_TCP }, 9774462Salfred#ifdef INET6 9874462Salfred { "udp6", AF_INET6, IPPROTO_UDP }, 9974462Salfred { "tcp6", AF_INET6, IPPROTO_TCP }, 10074462Salfred#endif 101107952Smbr { "local", AF_LOCAL, 0 } 10274462Salfred}; 10374462Salfred 10474462Salfred#if 0 10592905Sobrienstatic char *strlocase(char *); 10674462Salfred#endif 10792905Sobrienstatic int getnettype(const char *); 10874462Salfred 10974462Salfred/* 11074462Salfred * Cache the result of getrlimit(), so we don't have to do an 11174462Salfred * expensive call every time. 11274462Salfred */ 11374462Salfredint 11474462Salfred__rpc_dtbsize() 11574462Salfred{ 11674462Salfred static int tbsize; 11774462Salfred struct rlimit rl; 11874462Salfred 11974462Salfred if (tbsize) { 12074462Salfred return (tbsize); 12174462Salfred } 12274462Salfred if (getrlimit(RLIMIT_NOFILE, &rl) == 0) { 12374462Salfred return (tbsize = (int)rl.rlim_max); 12474462Salfred } 12574462Salfred /* 12674462Salfred * Something wrong. I'll try to save face by returning a 12774462Salfred * pessimistic number. 12874462Salfred */ 12974462Salfred return (32); 13074462Salfred} 13174462Salfred 13274462Salfred 13374462Salfred/* 13474462Salfred * Find the appropriate buffer size 13574462Salfred */ 13674462Salfredu_int 13774462Salfred/*ARGSUSED*/ 13874462Salfred__rpc_get_t_size(af, proto, size) 13974462Salfred int af, proto; 14074462Salfred int size; /* Size requested */ 14174462Salfred{ 14275314Siedowse int maxsize, defsize; 14374462Salfred 14475314Siedowse maxsize = 256 * 1024; /* XXX */ 14574462Salfred switch (proto) { 14674462Salfred case IPPROTO_TCP: 14775314Siedowse defsize = 64 * 1024; /* XXX */ 14874462Salfred break; 14974462Salfred case IPPROTO_UDP: 15075314Siedowse defsize = UDPMSGSIZE; 15174462Salfred break; 15274462Salfred default: 15375314Siedowse defsize = RPC_MAXDATASIZE; 15474462Salfred break; 15574462Salfred } 15674462Salfred if (size == 0) 15775314Siedowse return defsize; 15874462Salfred 15974462Salfred /* Check whether the value is within the upper max limit */ 16074462Salfred return (size > maxsize ? (u_int)maxsize : (u_int)size); 16174462Salfred} 16274462Salfred 16374462Salfred/* 16474462Salfred * Find the appropriate address buffer size 16574462Salfred */ 16674462Salfredu_int 16774462Salfred__rpc_get_a_size(af) 16874462Salfred int af; 16974462Salfred{ 17074462Salfred switch (af) { 17174462Salfred case AF_INET: 17274462Salfred return sizeof (struct sockaddr_in); 17374462Salfred#ifdef INET6 17474462Salfred case AF_INET6: 17574462Salfred return sizeof (struct sockaddr_in6); 17674462Salfred#endif 17774462Salfred case AF_LOCAL: 17874462Salfred return sizeof (struct sockaddr_un); 17974462Salfred default: 18074462Salfred break; 18174462Salfred } 18274462Salfred return ((u_int)RPC_MAXADDRSIZE); 18374462Salfred} 18474462Salfred 18574462Salfred#if 0 18674462Salfredstatic char * 18774462Salfredstrlocase(p) 18874462Salfred char *p; 18974462Salfred{ 19074462Salfred char *t = p; 19174462Salfred 19274462Salfred for (; *p; p++) 19374462Salfred if (isupper(*p)) 19474462Salfred *p = tolower(*p); 19574462Salfred return (t); 19674462Salfred} 19774462Salfred#endif 19874462Salfred 19974462Salfred/* 20074462Salfred * Returns the type of the network as defined in <rpc/nettype.h> 20174462Salfred * If nettype is NULL, it defaults to NETPATH. 20274462Salfred */ 20374462Salfredstatic int 20474462Salfredgetnettype(nettype) 20574462Salfred const char *nettype; 20674462Salfred{ 20774462Salfred int i; 20874462Salfred 209121652Smbr if ((nettype == NULL) || (nettype[0] == 0)) { 21074462Salfred return (_RPC_NETPATH); /* Default */ 21174462Salfred } 21274462Salfred 21374462Salfred#if 0 21474462Salfred nettype = strlocase(nettype); 21574462Salfred#endif 21674462Salfred for (i = 0; _rpctypelist[i].name; i++) 21774462Salfred if (strcasecmp(nettype, _rpctypelist[i].name) == 0) { 21874462Salfred return (_rpctypelist[i].type); 21974462Salfred } 22074462Salfred return (_rpctypelist[i].type); 22174462Salfred} 22274462Salfred 223204950Sjhbstatic thread_key_t tcp_key, udp_key; 224204950Sjhbstatic once_t keys_once = ONCE_INITIALIZER; 225204950Sjhbstatic int tcp_key_error, udp_key_error; 226204950Sjhb 227204950Sjhbstatic void 228204950Sjhbkeys_init(void) 229204950Sjhb{ 230204950Sjhb 231204950Sjhb tcp_key_error = thr_keycreate(&tcp_key, free); 232204950Sjhb udp_key_error = thr_keycreate(&udp_key, free); 233204950Sjhb} 234204950Sjhb 23574462Salfred/* 23674462Salfred * For the given nettype (tcp or udp only), return the first structure found. 23774462Salfred * This should be freed by calling freenetconfigent() 23874462Salfred */ 23974462Salfredstruct netconfig * 24074462Salfred__rpc_getconfip(nettype) 24174462Salfred const char *nettype; 24274462Salfred{ 24374462Salfred char *netid; 24474462Salfred char *netid_tcp = (char *) NULL; 24574462Salfred char *netid_udp = (char *) NULL; 24674462Salfred static char *netid_tcp_main; 24774462Salfred static char *netid_udp_main; 24874462Salfred struct netconfig *dummy; 24974462Salfred int main_thread; 25074462Salfred 25174462Salfred if ((main_thread = thr_main())) { 25274462Salfred netid_udp = netid_udp_main; 25374462Salfred netid_tcp = netid_tcp_main; 25474462Salfred } else { 255204950Sjhb if (thr_once(&keys_once, keys_init) != 0 || 256204950Sjhb tcp_key_error != 0 || udp_key_error != 0) 257204950Sjhb return (NULL); 25874462Salfred netid_tcp = (char *)thr_getspecific(tcp_key); 25974462Salfred netid_udp = (char *)thr_getspecific(udp_key); 26074462Salfred } 26174462Salfred if (!netid_udp && !netid_tcp) { 26274462Salfred struct netconfig *nconf; 26374462Salfred void *confighandle; 26474462Salfred 26574462Salfred if (!(confighandle = setnetconfig())) { 26674462Salfred syslog (LOG_ERR, "rpc: failed to open " NETCONFIG); 26774462Salfred return (NULL); 26874462Salfred } 26974462Salfred while ((nconf = getnetconfig(confighandle)) != NULL) { 27074462Salfred if (strcmp(nconf->nc_protofmly, NC_INET) == 0) { 271241142Spfg if (strcmp(nconf->nc_proto, NC_TCP) == 0 && 272241142Spfg netid_tcp == NULL) { 27374462Salfred netid_tcp = strdup(nconf->nc_netid); 27474462Salfred if (main_thread) 27574462Salfred netid_tcp_main = netid_tcp; 27674462Salfred else 27774462Salfred thr_setspecific(tcp_key, 27874462Salfred (void *) netid_tcp); 27974462Salfred } else 280241142Spfg if (strcmp(nconf->nc_proto, NC_UDP) == 0 && 281241142Spfg netid_udp == NULL) { 28274462Salfred netid_udp = strdup(nconf->nc_netid); 28374462Salfred if (main_thread) 28474462Salfred netid_udp_main = netid_udp; 28574462Salfred else 28674462Salfred thr_setspecific(udp_key, 28774462Salfred (void *) netid_udp); 28874462Salfred } 28974462Salfred } 29074462Salfred } 29174462Salfred endnetconfig(confighandle); 29274462Salfred } 29374462Salfred if (strcmp(nettype, "udp") == 0) 29474462Salfred netid = netid_udp; 29574462Salfred else if (strcmp(nettype, "tcp") == 0) 29674462Salfred netid = netid_tcp; 29774462Salfred else { 29874462Salfred return (NULL); 29974462Salfred } 300121652Smbr if ((netid == NULL) || (netid[0] == 0)) { 30174462Salfred return (NULL); 30274462Salfred } 30374462Salfred dummy = getnetconfigent(netid); 30474462Salfred return (dummy); 30574462Salfred} 30674462Salfred 30774462Salfred/* 30874462Salfred * Returns the type of the nettype, which should then be used with 30974462Salfred * __rpc_getconf(). 31074462Salfred */ 31174462Salfredvoid * 31274462Salfred__rpc_setconf(nettype) 31374462Salfred const char *nettype; 31474462Salfred{ 31574462Salfred struct handle *handle; 31674462Salfred 31774462Salfred handle = (struct handle *) malloc(sizeof (struct handle)); 31874462Salfred if (handle == NULL) { 31974462Salfred return (NULL); 32074462Salfred } 32174462Salfred switch (handle->nettype = getnettype(nettype)) { 32274462Salfred case _RPC_NETPATH: 32374462Salfred case _RPC_CIRCUIT_N: 32474462Salfred case _RPC_DATAGRAM_N: 325172259Smatteo if (!(handle->nhandle = setnetpath())) 326172259Smatteo goto failed; 32774462Salfred handle->nflag = TRUE; 32874462Salfred break; 32974462Salfred case _RPC_VISIBLE: 33074462Salfred case _RPC_CIRCUIT_V: 33174462Salfred case _RPC_DATAGRAM_V: 33274462Salfred case _RPC_TCP: 33374462Salfred case _RPC_UDP: 33474462Salfred if (!(handle->nhandle = setnetconfig())) { 33574462Salfred syslog (LOG_ERR, "rpc: failed to open " NETCONFIG); 336172259Smatteo goto failed; 33774462Salfred } 33874462Salfred handle->nflag = FALSE; 33974462Salfred break; 34074462Salfred default: 341172259Smatteo goto failed; 34274462Salfred } 34374462Salfred 34474462Salfred return (handle); 345172259Smatteo 346172259Smatteofailed: 347172259Smatteo free(handle); 348172259Smatteo return (NULL); 34974462Salfred} 35074462Salfred 35174462Salfred/* 35274462Salfred * Returns the next netconfig struct for the given "net" type. 35374462Salfred * __rpc_setconf() should have been called previously. 35474462Salfred */ 35574462Salfredstruct netconfig * 35674462Salfred__rpc_getconf(vhandle) 35774462Salfred void *vhandle; 35874462Salfred{ 35974462Salfred struct handle *handle; 36074462Salfred struct netconfig *nconf; 36174462Salfred 36274462Salfred handle = (struct handle *)vhandle; 36374462Salfred if (handle == NULL) { 36474462Salfred return (NULL); 36574462Salfred } 36674462Salfred for (;;) { 36774462Salfred if (handle->nflag) 36874462Salfred nconf = getnetpath(handle->nhandle); 36974462Salfred else 37074462Salfred nconf = getnetconfig(handle->nhandle); 37174462Salfred if (nconf == NULL) 37274462Salfred break; 37374462Salfred if ((nconf->nc_semantics != NC_TPI_CLTS) && 37474462Salfred (nconf->nc_semantics != NC_TPI_COTS) && 37574462Salfred (nconf->nc_semantics != NC_TPI_COTS_ORD)) 37674462Salfred continue; 37774462Salfred switch (handle->nettype) { 37874462Salfred case _RPC_VISIBLE: 37974462Salfred if (!(nconf->nc_flag & NC_VISIBLE)) 38074462Salfred continue; 38174462Salfred /* FALLTHROUGH */ 38274462Salfred case _RPC_NETPATH: /* Be happy */ 38374462Salfred break; 38474462Salfred case _RPC_CIRCUIT_V: 38574462Salfred if (!(nconf->nc_flag & NC_VISIBLE)) 38674462Salfred continue; 38774462Salfred /* FALLTHROUGH */ 38874462Salfred case _RPC_CIRCUIT_N: 38974462Salfred if ((nconf->nc_semantics != NC_TPI_COTS) && 39074462Salfred (nconf->nc_semantics != NC_TPI_COTS_ORD)) 39174462Salfred continue; 39274462Salfred break; 39374462Salfred case _RPC_DATAGRAM_V: 39474462Salfred if (!(nconf->nc_flag & NC_VISIBLE)) 39574462Salfred continue; 39674462Salfred /* FALLTHROUGH */ 39774462Salfred case _RPC_DATAGRAM_N: 39874462Salfred if (nconf->nc_semantics != NC_TPI_CLTS) 39974462Salfred continue; 40074462Salfred break; 40174462Salfred case _RPC_TCP: 40274462Salfred if (((nconf->nc_semantics != NC_TPI_COTS) && 40374462Salfred (nconf->nc_semantics != NC_TPI_COTS_ORD)) || 40474462Salfred (strcmp(nconf->nc_protofmly, NC_INET) 40574462Salfred#ifdef INET6 40674462Salfred && strcmp(nconf->nc_protofmly, NC_INET6)) 40774462Salfred#else 40874462Salfred ) 40974462Salfred#endif 41074462Salfred || 41174462Salfred strcmp(nconf->nc_proto, NC_TCP)) 41274462Salfred continue; 41374462Salfred break; 41474462Salfred case _RPC_UDP: 41574462Salfred if ((nconf->nc_semantics != NC_TPI_CLTS) || 41674462Salfred (strcmp(nconf->nc_protofmly, NC_INET) 41774462Salfred#ifdef INET6 41874462Salfred && strcmp(nconf->nc_protofmly, NC_INET6)) 41974462Salfred#else 42074462Salfred ) 42174462Salfred#endif 42274462Salfred || 42374462Salfred strcmp(nconf->nc_proto, NC_UDP)) 42474462Salfred continue; 42574462Salfred break; 42674462Salfred } 42774462Salfred break; 42874462Salfred } 42974462Salfred return (nconf); 43074462Salfred} 43174462Salfred 43274462Salfredvoid 43374462Salfred__rpc_endconf(vhandle) 43474462Salfred void * vhandle; 43574462Salfred{ 43674462Salfred struct handle *handle; 43774462Salfred 43874462Salfred handle = (struct handle *) vhandle; 43974462Salfred if (handle == NULL) { 44074462Salfred return; 44174462Salfred } 44274462Salfred if (handle->nflag) { 44374462Salfred endnetpath(handle->nhandle); 44474462Salfred } else { 44574462Salfred endnetconfig(handle->nhandle); 44674462Salfred } 44774462Salfred free(handle); 44874462Salfred} 44974462Salfred 45074462Salfred/* 45174462Salfred * Used to ping the NULL procedure for clnt handle. 45274462Salfred * Returns NULL if fails, else a non-NULL pointer. 45374462Salfred */ 45474462Salfredvoid * 45574462Salfredrpc_nullproc(clnt) 45674462Salfred CLIENT *clnt; 45774462Salfred{ 45874462Salfred struct timeval TIMEOUT = {25, 0}; 45974462Salfred 46074462Salfred if (clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void, NULL, 46174462Salfred (xdrproc_t) xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) { 46274462Salfred return (NULL); 46374462Salfred } 46474462Salfred return ((void *) clnt); 46574462Salfred} 46674462Salfred 46774462Salfred/* 46874462Salfred * Try all possible transports until 46974462Salfred * one succeeds in finding the netconf for the given fd. 47074462Salfred */ 47174462Salfredstruct netconfig * 47274462Salfred__rpcgettp(fd) 47374462Salfred int fd; 47474462Salfred{ 47574462Salfred const char *netid; 47674462Salfred struct __rpc_sockinfo si; 47774462Salfred 47874462Salfred if (!__rpc_fd2sockinfo(fd, &si)) 47974462Salfred return NULL; 48074462Salfred 48174462Salfred if (!__rpc_sockinfo2netid(&si, &netid)) 48274462Salfred return NULL; 48374462Salfred 48474462Salfred /*LINTED const castaway*/ 48574462Salfred return getnetconfigent((char *)netid); 48674462Salfred} 48774462Salfred 48874462Salfredint 48974462Salfred__rpc_fd2sockinfo(int fd, struct __rpc_sockinfo *sip) 49074462Salfred{ 49174462Salfred socklen_t len; 49274462Salfred int type, proto; 49374462Salfred struct sockaddr_storage ss; 49474462Salfred 49574462Salfred len = sizeof ss; 49674462Salfred if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &len) < 0) 49774462Salfred return 0; 49874462Salfred sip->si_alen = len; 49974462Salfred 50074462Salfred len = sizeof type; 50174462Salfred if (_getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &len) < 0) 50274462Salfred return 0; 50374462Salfred 50474462Salfred /* XXX */ 50574462Salfred if (ss.ss_family != AF_LOCAL) { 50674462Salfred if (type == SOCK_STREAM) 50774462Salfred proto = IPPROTO_TCP; 50874462Salfred else if (type == SOCK_DGRAM) 50974462Salfred proto = IPPROTO_UDP; 51074462Salfred else 51174462Salfred return 0; 51274462Salfred } else 51374462Salfred proto = 0; 51474462Salfred 51574462Salfred sip->si_af = ss.ss_family; 51674462Salfred sip->si_proto = proto; 51774462Salfred sip->si_socktype = type; 51874462Salfred 51974462Salfred return 1; 52074462Salfred} 52174462Salfred 52274462Salfred/* 52374462Salfred * Linear search, but the number of entries is small. 52474462Salfred */ 52574462Salfredint 52674462Salfred__rpc_nconf2sockinfo(const struct netconfig *nconf, struct __rpc_sockinfo *sip) 52774462Salfred{ 52874462Salfred int i; 52974462Salfred 53074462Salfred for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++) 531107952Smbr if (strcmp(na_cvt[i].netid, nconf->nc_netid) == 0 || ( 532107952Smbr strcmp(nconf->nc_netid, "unix") == 0 && 533107952Smbr strcmp(na_cvt[i].netid, "local") == 0)) { 53474462Salfred sip->si_af = na_cvt[i].af; 53574462Salfred sip->si_proto = na_cvt[i].protocol; 53674462Salfred sip->si_socktype = 53774462Salfred __rpc_seman2socktype((int)nconf->nc_semantics); 53874462Salfred if (sip->si_socktype == -1) 53974462Salfred return 0; 54074462Salfred sip->si_alen = __rpc_get_a_size(sip->si_af); 54174462Salfred return 1; 54274462Salfred } 54374462Salfred 54474462Salfred return 0; 54574462Salfred} 54674462Salfred 54774462Salfredint 54874462Salfred__rpc_nconf2fd(const struct netconfig *nconf) 54974462Salfred{ 55074462Salfred struct __rpc_sockinfo si; 55174462Salfred 55274462Salfred if (!__rpc_nconf2sockinfo(nconf, &si)) 55374462Salfred return 0; 55474462Salfred 55574462Salfred return _socket(si.si_af, si.si_socktype, si.si_proto); 55674462Salfred} 55774462Salfred 55874462Salfredint 55974462Salfred__rpc_sockinfo2netid(struct __rpc_sockinfo *sip, const char **netid) 56074462Salfred{ 56174462Salfred int i; 562109384Smbr struct netconfig *nconf; 56374462Salfred 564109384Smbr nconf = getnetconfigent("local"); 565109384Smbr 566107952Smbr for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++) { 56774462Salfred if (na_cvt[i].af == sip->si_af && 56874462Salfred na_cvt[i].protocol == sip->si_proto) { 569109384Smbr if (strcmp(na_cvt[i].netid, "local") == 0 && nconf == NULL) { 570107952Smbr if (netid) 571107952Smbr *netid = "unix"; 572107952Smbr } else { 573107952Smbr if (netid) 574107952Smbr *netid = na_cvt[i].netid; 575107952Smbr } 576109384Smbr if (nconf != NULL) 577109384Smbr freenetconfigent(nconf); 57874462Salfred return 1; 57974462Salfred } 580107952Smbr } 581109384Smbr if (nconf != NULL) 582109384Smbr freenetconfigent(nconf); 58374462Salfred 58474462Salfred return 0; 58574462Salfred} 58674462Salfred 58774462Salfredchar * 58874462Salfredtaddr2uaddr(const struct netconfig *nconf, const struct netbuf *nbuf) 58974462Salfred{ 59074462Salfred struct __rpc_sockinfo si; 59174462Salfred 59274462Salfred if (!__rpc_nconf2sockinfo(nconf, &si)) 59374462Salfred return NULL; 59474462Salfred return __rpc_taddr2uaddr_af(si.si_af, nbuf); 59574462Salfred} 59674462Salfred 59774462Salfredstruct netbuf * 59874462Salfreduaddr2taddr(const struct netconfig *nconf, const char *uaddr) 59974462Salfred{ 60074462Salfred struct __rpc_sockinfo si; 60174462Salfred 60274462Salfred if (!__rpc_nconf2sockinfo(nconf, &si)) 60374462Salfred return NULL; 60474462Salfred return __rpc_uaddr2taddr_af(si.si_af, uaddr); 60574462Salfred} 60674462Salfred 60774462Salfredchar * 60874462Salfred__rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf) 60974462Salfred{ 61074462Salfred char *ret; 61174462Salfred struct sockaddr_in *sin; 61274462Salfred struct sockaddr_un *sun; 61374462Salfred char namebuf[INET_ADDRSTRLEN]; 61474462Salfred#ifdef INET6 61574462Salfred struct sockaddr_in6 *sin6; 61674462Salfred char namebuf6[INET6_ADDRSTRLEN]; 61774462Salfred#endif 61874462Salfred u_int16_t port; 61974462Salfred 62074462Salfred switch (af) { 62174462Salfred case AF_INET: 62274462Salfred sin = nbuf->buf; 62374462Salfred if (inet_ntop(af, &sin->sin_addr, namebuf, sizeof namebuf) 62474462Salfred == NULL) 62574462Salfred return NULL; 62674462Salfred port = ntohs(sin->sin_port); 62774462Salfred if (asprintf(&ret, "%s.%u.%u", namebuf, ((u_int32_t)port) >> 8, 62874462Salfred port & 0xff) < 0) 62974462Salfred return NULL; 63074462Salfred break; 63174462Salfred#ifdef INET6 63274462Salfred case AF_INET6: 63374462Salfred sin6 = nbuf->buf; 63474462Salfred if (inet_ntop(af, &sin6->sin6_addr, namebuf6, sizeof namebuf6) 63574462Salfred == NULL) 63674462Salfred return NULL; 63774462Salfred port = ntohs(sin6->sin6_port); 63874462Salfred if (asprintf(&ret, "%s.%u.%u", namebuf6, ((u_int32_t)port) >> 8, 63974462Salfred port & 0xff) < 0) 64074462Salfred return NULL; 64174462Salfred break; 64274462Salfred#endif 64374462Salfred case AF_LOCAL: 64474462Salfred sun = nbuf->buf; 64576523Siedowse if (asprintf(&ret, "%.*s", (int)(sun->sun_len - 64676523Siedowse offsetof(struct sockaddr_un, sun_path)), 64776523Siedowse sun->sun_path) < 0) 64876523Siedowse return (NULL); 64974462Salfred break; 65074462Salfred default: 65174462Salfred return NULL; 65274462Salfred } 65374462Salfred 65474462Salfred return ret; 65574462Salfred} 65674462Salfred 65774462Salfredstruct netbuf * 65874462Salfred__rpc_uaddr2taddr_af(int af, const char *uaddr) 65974462Salfred{ 66074462Salfred struct netbuf *ret = NULL; 66174462Salfred char *addrstr, *p; 66274462Salfred unsigned port, portlo, porthi; 66374462Salfred struct sockaddr_in *sin; 66474462Salfred#ifdef INET6 66574462Salfred struct sockaddr_in6 *sin6; 66674462Salfred#endif 66774462Salfred struct sockaddr_un *sun; 66874462Salfred 66990271Salfred port = 0; 67090271Salfred sin = NULL; 67174462Salfred addrstr = strdup(uaddr); 67274462Salfred if (addrstr == NULL) 67374462Salfred return NULL; 67474462Salfred 67574462Salfred /* 67674462Salfred * AF_LOCAL addresses are expected to be absolute 67774462Salfred * pathnames, anything else will be AF_INET or AF_INET6. 67874462Salfred */ 67974462Salfred if (*addrstr != '/') { 68074462Salfred p = strrchr(addrstr, '.'); 68174462Salfred if (p == NULL) 68274462Salfred goto out; 68374462Salfred portlo = (unsigned)atoi(p + 1); 68474462Salfred *p = '\0'; 68574462Salfred 68674462Salfred p = strrchr(addrstr, '.'); 68774462Salfred if (p == NULL) 68874462Salfred goto out; 68974462Salfred porthi = (unsigned)atoi(p + 1); 69074462Salfred *p = '\0'; 69174462Salfred port = (porthi << 8) | portlo; 69274462Salfred } 69374462Salfred 69474462Salfred ret = (struct netbuf *)malloc(sizeof *ret); 695109951Smbr if (ret == NULL) 696109951Smbr goto out; 69774462Salfred 69874462Salfred switch (af) { 69974462Salfred case AF_INET: 70074462Salfred sin = (struct sockaddr_in *)malloc(sizeof *sin); 70174462Salfred if (sin == NULL) 70274462Salfred goto out; 70374462Salfred memset(sin, 0, sizeof *sin); 70474462Salfred sin->sin_family = AF_INET; 70574462Salfred sin->sin_port = htons(port); 70674462Salfred if (inet_pton(AF_INET, addrstr, &sin->sin_addr) <= 0) { 70774462Salfred free(sin); 70874462Salfred free(ret); 70974462Salfred ret = NULL; 71074462Salfred goto out; 71174462Salfred } 71274462Salfred sin->sin_len = ret->maxlen = ret->len = sizeof *sin; 71374462Salfred ret->buf = sin; 71474462Salfred break; 71574462Salfred#ifdef INET6 71674462Salfred case AF_INET6: 71774462Salfred sin6 = (struct sockaddr_in6 *)malloc(sizeof *sin6); 71874462Salfred if (sin6 == NULL) 71974462Salfred goto out; 72074462Salfred memset(sin6, 0, sizeof *sin6); 72174462Salfred sin6->sin6_family = AF_INET6; 72274462Salfred sin6->sin6_port = htons(port); 72374462Salfred if (inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) <= 0) { 724109951Smbr free(sin6); 72574462Salfred free(ret); 72674462Salfred ret = NULL; 72774462Salfred goto out; 72874462Salfred } 72974462Salfred sin6->sin6_len = ret->maxlen = ret->len = sizeof *sin6; 73074462Salfred ret->buf = sin6; 73174462Salfred break; 73274462Salfred#endif 73374462Salfred case AF_LOCAL: 73474462Salfred sun = (struct sockaddr_un *)malloc(sizeof *sun); 73574462Salfred if (sun == NULL) 73674462Salfred goto out; 73774462Salfred memset(sun, 0, sizeof *sun); 73874462Salfred sun->sun_family = AF_LOCAL; 73974462Salfred strncpy(sun->sun_path, addrstr, sizeof(sun->sun_path) - 1); 74076044Siedowse ret->len = ret->maxlen = sun->sun_len = SUN_LEN(sun); 74176044Siedowse ret->buf = sun; 74274462Salfred break; 74374462Salfred default: 74474462Salfred break; 74574462Salfred } 74674462Salfredout: 74774462Salfred free(addrstr); 74874462Salfred return ret; 74974462Salfred} 75074462Salfred 75174462Salfredint 75274462Salfred__rpc_seman2socktype(int semantics) 75374462Salfred{ 75474462Salfred switch (semantics) { 75574462Salfred case NC_TPI_CLTS: 75674462Salfred return SOCK_DGRAM; 75774462Salfred case NC_TPI_COTS_ORD: 75874462Salfred return SOCK_STREAM; 75974462Salfred case NC_TPI_RAW: 76074462Salfred return SOCK_RAW; 76174462Salfred default: 76274462Salfred break; 76374462Salfred } 76474462Salfred 76574462Salfred return -1; 76674462Salfred} 76774462Salfred 76874462Salfredint 76974462Salfred__rpc_socktype2seman(int socktype) 77074462Salfred{ 77174462Salfred switch (socktype) { 77274462Salfred case SOCK_DGRAM: 77374462Salfred return NC_TPI_CLTS; 77474462Salfred case SOCK_STREAM: 77574462Salfred return NC_TPI_COTS_ORD; 77674462Salfred case SOCK_RAW: 77774462Salfred return NC_TPI_RAW; 77874462Salfred default: 77974462Salfred break; 78074462Salfred } 78174462Salfred 78274462Salfred return -1; 78374462Salfred} 78474462Salfred 78574462Salfred/* 78674462Salfred * XXXX - IPv6 scope IDs can't be handled in universal addresses. 78774462Salfred * Here, we compare the original server address to that of the RPC 78874462Salfred * service we just received back from a call to rpcbind on the remote 78974462Salfred * machine. If they are both "link local" or "site local", copy 79074462Salfred * the scope id of the server address over to the service address. 79174462Salfred */ 79274462Salfredint 79374462Salfred__rpc_fixup_addr(struct netbuf *new, const struct netbuf *svc) 79474462Salfred{ 79574462Salfred#ifdef INET6 79674462Salfred struct sockaddr *sa_new, *sa_svc; 79774462Salfred struct sockaddr_in6 *sin6_new, *sin6_svc; 79874462Salfred 79974462Salfred sa_svc = (struct sockaddr *)svc->buf; 80074462Salfred sa_new = (struct sockaddr *)new->buf; 80174462Salfred 80274462Salfred if (sa_new->sa_family == sa_svc->sa_family && 80374462Salfred sa_new->sa_family == AF_INET6) { 80474462Salfred sin6_new = (struct sockaddr_in6 *)new->buf; 80574462Salfred sin6_svc = (struct sockaddr_in6 *)svc->buf; 80674462Salfred 80774462Salfred if ((IN6_IS_ADDR_LINKLOCAL(&sin6_new->sin6_addr) && 80874462Salfred IN6_IS_ADDR_LINKLOCAL(&sin6_svc->sin6_addr)) || 80974462Salfred (IN6_IS_ADDR_SITELOCAL(&sin6_new->sin6_addr) && 81074462Salfred IN6_IS_ADDR_SITELOCAL(&sin6_svc->sin6_addr))) { 81174462Salfred sin6_new->sin6_scope_id = sin6_svc->sin6_scope_id; 81274462Salfred } 81374462Salfred } 81474462Salfred#endif 81574462Salfred return 1; 81674462Salfred} 81774462Salfred 81874462Salfredint 81974462Salfred__rpc_sockisbound(int fd) 82074462Salfred{ 82174462Salfred struct sockaddr_storage ss; 82274462Salfred socklen_t slen; 82374462Salfred 82474462Salfred slen = sizeof (struct sockaddr_storage); 82574462Salfred if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) 82674462Salfred return 0; 82774462Salfred 82874462Salfred switch (ss.ss_family) { 82974462Salfred case AF_INET: 83074462Salfred return (((struct sockaddr_in *) 83174462Salfred (void *)&ss)->sin_port != 0); 83274462Salfred#ifdef INET6 83374462Salfred case AF_INET6: 83474462Salfred return (((struct sockaddr_in6 *) 83574462Salfred (void *)&ss)->sin6_port != 0); 83674462Salfred#endif 83774462Salfred case AF_LOCAL: 83874462Salfred /* XXX check this */ 83974462Salfred return (((struct sockaddr_un *) 84074462Salfred (void *)&ss)->sun_path[0] != '\0'); 84174462Salfred default: 84274462Salfred break; 84374462Salfred } 84474462Salfred 84574462Salfred return 0; 84674462Salfred} 847