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: stable/10/lib/libc/rpc/rpc_generic.c 319615 2017-06-06 07:22:26Z delphij $"); 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 114309487Sngie__rpc_dtbsize(void) 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 135309487Sngie * 136309487Sngie * size - Size requested 13774462Salfred */ 13874462Salfredu_int 13974462Salfred/*ARGSUSED*/ 140309487Sngie__rpc_get_t_size(int af, int proto, int size) 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 167309487Sngie__rpc_get_a_size(int af) 16874462Salfred{ 16974462Salfred switch (af) { 17074462Salfred case AF_INET: 17174462Salfred return sizeof (struct sockaddr_in); 17274462Salfred#ifdef INET6 17374462Salfred case AF_INET6: 17474462Salfred return sizeof (struct sockaddr_in6); 17574462Salfred#endif 17674462Salfred case AF_LOCAL: 17774462Salfred return sizeof (struct sockaddr_un); 17874462Salfred default: 17974462Salfred break; 18074462Salfred } 18174462Salfred return ((u_int)RPC_MAXADDRSIZE); 18274462Salfred} 18374462Salfred 18474462Salfred#if 0 18574462Salfredstatic char * 186309487Sngiestrlocase(char *p) 18774462Salfred{ 18874462Salfred char *t = p; 18974462Salfred 19074462Salfred for (; *p; p++) 19174462Salfred if (isupper(*p)) 19274462Salfred *p = tolower(*p); 19374462Salfred return (t); 19474462Salfred} 19574462Salfred#endif 19674462Salfred 19774462Salfred/* 19874462Salfred * Returns the type of the network as defined in <rpc/nettype.h> 19974462Salfred * If nettype is NULL, it defaults to NETPATH. 20074462Salfred */ 20174462Salfredstatic int 202309487Sngiegetnettype(const char *nettype) 20374462Salfred{ 20474462Salfred int i; 20574462Salfred 206121652Smbr if ((nettype == NULL) || (nettype[0] == 0)) { 20774462Salfred return (_RPC_NETPATH); /* Default */ 20874462Salfred } 20974462Salfred 21074462Salfred#if 0 21174462Salfred nettype = strlocase(nettype); 21274462Salfred#endif 21374462Salfred for (i = 0; _rpctypelist[i].name; i++) 21474462Salfred if (strcasecmp(nettype, _rpctypelist[i].name) == 0) { 21574462Salfred return (_rpctypelist[i].type); 21674462Salfred } 21774462Salfred return (_rpctypelist[i].type); 21874462Salfred} 21974462Salfred 220204950Sjhbstatic thread_key_t tcp_key, udp_key; 221204950Sjhbstatic once_t keys_once = ONCE_INITIALIZER; 222204950Sjhbstatic int tcp_key_error, udp_key_error; 223204950Sjhb 224204950Sjhbstatic void 225204950Sjhbkeys_init(void) 226204950Sjhb{ 227204950Sjhb 228204950Sjhb tcp_key_error = thr_keycreate(&tcp_key, free); 229204950Sjhb udp_key_error = thr_keycreate(&udp_key, free); 230204950Sjhb} 231204950Sjhb 23274462Salfred/* 23374462Salfred * For the given nettype (tcp or udp only), return the first structure found. 23474462Salfred * This should be freed by calling freenetconfigent() 23574462Salfred */ 23674462Salfredstruct netconfig * 237309487Sngie__rpc_getconfip(const char *nettype) 23874462Salfred{ 23974462Salfred char *netid; 24074462Salfred char *netid_tcp = (char *) NULL; 24174462Salfred char *netid_udp = (char *) NULL; 24274462Salfred static char *netid_tcp_main; 24374462Salfred static char *netid_udp_main; 24474462Salfred struct netconfig *dummy; 24574462Salfred int main_thread; 24674462Salfred 24774462Salfred if ((main_thread = thr_main())) { 24874462Salfred netid_udp = netid_udp_main; 24974462Salfred netid_tcp = netid_tcp_main; 25074462Salfred } else { 251204950Sjhb if (thr_once(&keys_once, keys_init) != 0 || 252204950Sjhb tcp_key_error != 0 || udp_key_error != 0) 253204950Sjhb return (NULL); 25474462Salfred netid_tcp = (char *)thr_getspecific(tcp_key); 25574462Salfred netid_udp = (char *)thr_getspecific(udp_key); 25674462Salfred } 25774462Salfred if (!netid_udp && !netid_tcp) { 25874462Salfred struct netconfig *nconf; 25974462Salfred void *confighandle; 26074462Salfred 26174462Salfred if (!(confighandle = setnetconfig())) { 26274462Salfred syslog (LOG_ERR, "rpc: failed to open " NETCONFIG); 26374462Salfred return (NULL); 26474462Salfred } 26574462Salfred while ((nconf = getnetconfig(confighandle)) != NULL) { 26674462Salfred if (strcmp(nconf->nc_protofmly, NC_INET) == 0) { 267241142Spfg if (strcmp(nconf->nc_proto, NC_TCP) == 0 && 268241142Spfg netid_tcp == NULL) { 26974462Salfred netid_tcp = strdup(nconf->nc_netid); 27074462Salfred if (main_thread) 27174462Salfred netid_tcp_main = netid_tcp; 27274462Salfred else 27374462Salfred thr_setspecific(tcp_key, 27474462Salfred (void *) netid_tcp); 27574462Salfred } else 276241142Spfg if (strcmp(nconf->nc_proto, NC_UDP) == 0 && 277241142Spfg netid_udp == NULL) { 27874462Salfred netid_udp = strdup(nconf->nc_netid); 27974462Salfred if (main_thread) 28074462Salfred netid_udp_main = netid_udp; 28174462Salfred else 28274462Salfred thr_setspecific(udp_key, 28374462Salfred (void *) netid_udp); 28474462Salfred } 28574462Salfred } 28674462Salfred } 28774462Salfred endnetconfig(confighandle); 28874462Salfred } 28974462Salfred if (strcmp(nettype, "udp") == 0) 29074462Salfred netid = netid_udp; 29174462Salfred else if (strcmp(nettype, "tcp") == 0) 29274462Salfred netid = netid_tcp; 29374462Salfred else { 29474462Salfred return (NULL); 29574462Salfred } 296121652Smbr if ((netid == NULL) || (netid[0] == 0)) { 29774462Salfred return (NULL); 29874462Salfred } 29974462Salfred dummy = getnetconfigent(netid); 30074462Salfred return (dummy); 30174462Salfred} 30274462Salfred 30374462Salfred/* 30474462Salfred * Returns the type of the nettype, which should then be used with 30574462Salfred * __rpc_getconf(). 30674462Salfred */ 30774462Salfredvoid * 308309487Sngie__rpc_setconf(const char *nettype) 30974462Salfred{ 31074462Salfred struct handle *handle; 31174462Salfred 31274462Salfred handle = (struct handle *) malloc(sizeof (struct handle)); 31374462Salfred if (handle == NULL) { 31474462Salfred return (NULL); 31574462Salfred } 31674462Salfred switch (handle->nettype = getnettype(nettype)) { 31774462Salfred case _RPC_NETPATH: 31874462Salfred case _RPC_CIRCUIT_N: 31974462Salfred case _RPC_DATAGRAM_N: 320172259Smatteo if (!(handle->nhandle = setnetpath())) 321172259Smatteo goto failed; 32274462Salfred handle->nflag = TRUE; 32374462Salfred break; 32474462Salfred case _RPC_VISIBLE: 32574462Salfred case _RPC_CIRCUIT_V: 32674462Salfred case _RPC_DATAGRAM_V: 32774462Salfred case _RPC_TCP: 32874462Salfred case _RPC_UDP: 32974462Salfred if (!(handle->nhandle = setnetconfig())) { 33074462Salfred syslog (LOG_ERR, "rpc: failed to open " NETCONFIG); 331172259Smatteo goto failed; 33274462Salfred } 33374462Salfred handle->nflag = FALSE; 33474462Salfred break; 33574462Salfred default: 336172259Smatteo goto failed; 33774462Salfred } 33874462Salfred 33974462Salfred return (handle); 340172259Smatteo 341172259Smatteofailed: 342172259Smatteo free(handle); 343172259Smatteo return (NULL); 34474462Salfred} 34574462Salfred 34674462Salfred/* 34774462Salfred * Returns the next netconfig struct for the given "net" type. 34874462Salfred * __rpc_setconf() should have been called previously. 34974462Salfred */ 35074462Salfredstruct netconfig * 351309487Sngie__rpc_getconf(void *vhandle) 35274462Salfred{ 35374462Salfred struct handle *handle; 35474462Salfred struct netconfig *nconf; 35574462Salfred 35674462Salfred handle = (struct handle *)vhandle; 35774462Salfred if (handle == NULL) { 35874462Salfred return (NULL); 35974462Salfred } 36074462Salfred for (;;) { 36174462Salfred if (handle->nflag) 36274462Salfred nconf = getnetpath(handle->nhandle); 36374462Salfred else 36474462Salfred nconf = getnetconfig(handle->nhandle); 36574462Salfred if (nconf == NULL) 36674462Salfred break; 36774462Salfred if ((nconf->nc_semantics != NC_TPI_CLTS) && 36874462Salfred (nconf->nc_semantics != NC_TPI_COTS) && 36974462Salfred (nconf->nc_semantics != NC_TPI_COTS_ORD)) 37074462Salfred continue; 37174462Salfred switch (handle->nettype) { 37274462Salfred case _RPC_VISIBLE: 37374462Salfred if (!(nconf->nc_flag & NC_VISIBLE)) 37474462Salfred continue; 37574462Salfred /* FALLTHROUGH */ 37674462Salfred case _RPC_NETPATH: /* Be happy */ 37774462Salfred break; 37874462Salfred case _RPC_CIRCUIT_V: 37974462Salfred if (!(nconf->nc_flag & NC_VISIBLE)) 38074462Salfred continue; 38174462Salfred /* FALLTHROUGH */ 38274462Salfred case _RPC_CIRCUIT_N: 38374462Salfred if ((nconf->nc_semantics != NC_TPI_COTS) && 38474462Salfred (nconf->nc_semantics != NC_TPI_COTS_ORD)) 38574462Salfred continue; 38674462Salfred break; 38774462Salfred case _RPC_DATAGRAM_V: 38874462Salfred if (!(nconf->nc_flag & NC_VISIBLE)) 38974462Salfred continue; 39074462Salfred /* FALLTHROUGH */ 39174462Salfred case _RPC_DATAGRAM_N: 39274462Salfred if (nconf->nc_semantics != NC_TPI_CLTS) 39374462Salfred continue; 39474462Salfred break; 39574462Salfred case _RPC_TCP: 39674462Salfred if (((nconf->nc_semantics != NC_TPI_COTS) && 39774462Salfred (nconf->nc_semantics != NC_TPI_COTS_ORD)) || 39874462Salfred (strcmp(nconf->nc_protofmly, NC_INET) 39974462Salfred#ifdef INET6 40074462Salfred && strcmp(nconf->nc_protofmly, NC_INET6)) 40174462Salfred#else 40274462Salfred ) 40374462Salfred#endif 40474462Salfred || 40574462Salfred strcmp(nconf->nc_proto, NC_TCP)) 40674462Salfred continue; 40774462Salfred break; 40874462Salfred case _RPC_UDP: 40974462Salfred if ((nconf->nc_semantics != NC_TPI_CLTS) || 41074462Salfred (strcmp(nconf->nc_protofmly, NC_INET) 41174462Salfred#ifdef INET6 41274462Salfred && strcmp(nconf->nc_protofmly, NC_INET6)) 41374462Salfred#else 41474462Salfred ) 41574462Salfred#endif 41674462Salfred || 41774462Salfred strcmp(nconf->nc_proto, NC_UDP)) 41874462Salfred continue; 41974462Salfred break; 42074462Salfred } 42174462Salfred break; 42274462Salfred } 42374462Salfred return (nconf); 42474462Salfred} 42574462Salfred 42674462Salfredvoid 427309487Sngie__rpc_endconf(void *vhandle) 42874462Salfred{ 42974462Salfred struct handle *handle; 43074462Salfred 43174462Salfred handle = (struct handle *) vhandle; 43274462Salfred if (handle == NULL) { 43374462Salfred return; 43474462Salfred } 43574462Salfred if (handle->nflag) { 43674462Salfred endnetpath(handle->nhandle); 43774462Salfred } else { 43874462Salfred endnetconfig(handle->nhandle); 43974462Salfred } 44074462Salfred free(handle); 44174462Salfred} 44274462Salfred 44374462Salfred/* 44474462Salfred * Used to ping the NULL procedure for clnt handle. 44574462Salfred * Returns NULL if fails, else a non-NULL pointer. 44674462Salfred */ 44774462Salfredvoid * 448309487Sngierpc_nullproc(CLIENT *clnt) 44974462Salfred{ 45074462Salfred struct timeval TIMEOUT = {25, 0}; 45174462Salfred 45274462Salfred if (clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void, NULL, 45374462Salfred (xdrproc_t) xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) { 45474462Salfred return (NULL); 45574462Salfred } 45674462Salfred return ((void *) clnt); 45774462Salfred} 45874462Salfred 45974462Salfred/* 46074462Salfred * Try all possible transports until 46174462Salfred * one succeeds in finding the netconf for the given fd. 46274462Salfred */ 46374462Salfredstruct netconfig * 464309487Sngie__rpcgettp(int fd) 46574462Salfred{ 46674462Salfred const char *netid; 46774462Salfred struct __rpc_sockinfo si; 46874462Salfred 46974462Salfred if (!__rpc_fd2sockinfo(fd, &si)) 47074462Salfred return NULL; 47174462Salfred 47274462Salfred if (!__rpc_sockinfo2netid(&si, &netid)) 47374462Salfred return NULL; 47474462Salfred 47574462Salfred /*LINTED const castaway*/ 47674462Salfred return getnetconfigent((char *)netid); 47774462Salfred} 47874462Salfred 47974462Salfredint 48074462Salfred__rpc_fd2sockinfo(int fd, struct __rpc_sockinfo *sip) 48174462Salfred{ 48274462Salfred socklen_t len; 48374462Salfred int type, proto; 48474462Salfred struct sockaddr_storage ss; 48574462Salfred 48674462Salfred len = sizeof ss; 48774462Salfred if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &len) < 0) 48874462Salfred return 0; 48974462Salfred sip->si_alen = len; 49074462Salfred 49174462Salfred len = sizeof type; 49274462Salfred if (_getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &len) < 0) 49374462Salfred return 0; 49474462Salfred 49574462Salfred /* XXX */ 49674462Salfred if (ss.ss_family != AF_LOCAL) { 49774462Salfred if (type == SOCK_STREAM) 49874462Salfred proto = IPPROTO_TCP; 49974462Salfred else if (type == SOCK_DGRAM) 50074462Salfred proto = IPPROTO_UDP; 50174462Salfred else 50274462Salfred return 0; 50374462Salfred } else 50474462Salfred proto = 0; 50574462Salfred 50674462Salfred sip->si_af = ss.ss_family; 50774462Salfred sip->si_proto = proto; 50874462Salfred sip->si_socktype = type; 50974462Salfred 51074462Salfred return 1; 51174462Salfred} 51274462Salfred 51374462Salfred/* 51474462Salfred * Linear search, but the number of entries is small. 51574462Salfred */ 51674462Salfredint 51774462Salfred__rpc_nconf2sockinfo(const struct netconfig *nconf, struct __rpc_sockinfo *sip) 51874462Salfred{ 51974462Salfred int i; 52074462Salfred 52174462Salfred for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++) 522107952Smbr if (strcmp(na_cvt[i].netid, nconf->nc_netid) == 0 || ( 523107952Smbr strcmp(nconf->nc_netid, "unix") == 0 && 524107952Smbr strcmp(na_cvt[i].netid, "local") == 0)) { 52574462Salfred sip->si_af = na_cvt[i].af; 52674462Salfred sip->si_proto = na_cvt[i].protocol; 52774462Salfred sip->si_socktype = 52874462Salfred __rpc_seman2socktype((int)nconf->nc_semantics); 52974462Salfred if (sip->si_socktype == -1) 53074462Salfred return 0; 53174462Salfred sip->si_alen = __rpc_get_a_size(sip->si_af); 53274462Salfred return 1; 53374462Salfred } 53474462Salfred 53574462Salfred return 0; 53674462Salfred} 53774462Salfred 53874462Salfredint 53974462Salfred__rpc_nconf2fd(const struct netconfig *nconf) 54074462Salfred{ 54174462Salfred struct __rpc_sockinfo si; 54274462Salfred 54374462Salfred if (!__rpc_nconf2sockinfo(nconf, &si)) 54474462Salfred return 0; 54574462Salfred 54674462Salfred return _socket(si.si_af, si.si_socktype, si.si_proto); 54774462Salfred} 54874462Salfred 54974462Salfredint 55074462Salfred__rpc_sockinfo2netid(struct __rpc_sockinfo *sip, const char **netid) 55174462Salfred{ 55274462Salfred int i; 553109384Smbr struct netconfig *nconf; 55474462Salfred 555109384Smbr nconf = getnetconfigent("local"); 556109384Smbr 557107952Smbr for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++) { 55874462Salfred if (na_cvt[i].af == sip->si_af && 55974462Salfred na_cvt[i].protocol == sip->si_proto) { 560109384Smbr if (strcmp(na_cvt[i].netid, "local") == 0 && nconf == NULL) { 561107952Smbr if (netid) 562107952Smbr *netid = "unix"; 563107952Smbr } else { 564107952Smbr if (netid) 565107952Smbr *netid = na_cvt[i].netid; 566107952Smbr } 567109384Smbr if (nconf != NULL) 568109384Smbr freenetconfigent(nconf); 56974462Salfred return 1; 57074462Salfred } 571107952Smbr } 572109384Smbr if (nconf != NULL) 573109384Smbr freenetconfigent(nconf); 57474462Salfred 57574462Salfred return 0; 57674462Salfred} 57774462Salfred 57874462Salfredchar * 57974462Salfredtaddr2uaddr(const struct netconfig *nconf, const struct netbuf *nbuf) 58074462Salfred{ 58174462Salfred struct __rpc_sockinfo si; 58274462Salfred 58374462Salfred if (!__rpc_nconf2sockinfo(nconf, &si)) 58474462Salfred return NULL; 58574462Salfred return __rpc_taddr2uaddr_af(si.si_af, nbuf); 58674462Salfred} 58774462Salfred 58874462Salfredstruct netbuf * 58974462Salfreduaddr2taddr(const struct netconfig *nconf, const char *uaddr) 59074462Salfred{ 59174462Salfred struct __rpc_sockinfo si; 59274462Salfred 59374462Salfred if (!__rpc_nconf2sockinfo(nconf, &si)) 59474462Salfred return NULL; 59574462Salfred return __rpc_uaddr2taddr_af(si.si_af, uaddr); 59674462Salfred} 59774462Salfred 59874462Salfredchar * 59974462Salfred__rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf) 60074462Salfred{ 60174462Salfred char *ret; 60274462Salfred struct sockaddr_in *sin; 60374462Salfred struct sockaddr_un *sun; 60474462Salfred char namebuf[INET_ADDRSTRLEN]; 60574462Salfred#ifdef INET6 60674462Salfred struct sockaddr_in6 *sin6; 60774462Salfred char namebuf6[INET6_ADDRSTRLEN]; 60874462Salfred#endif 60974462Salfred u_int16_t port; 61074462Salfred 61174462Salfred switch (af) { 61274462Salfred case AF_INET: 613319615Sdelphij if (nbuf->len < sizeof(*sin)) 614319615Sdelphij return NULL; 61574462Salfred sin = nbuf->buf; 61674462Salfred if (inet_ntop(af, &sin->sin_addr, namebuf, sizeof namebuf) 61774462Salfred == NULL) 61874462Salfred return NULL; 61974462Salfred port = ntohs(sin->sin_port); 62074462Salfred if (asprintf(&ret, "%s.%u.%u", namebuf, ((u_int32_t)port) >> 8, 62174462Salfred port & 0xff) < 0) 62274462Salfred return NULL; 62374462Salfred break; 62474462Salfred#ifdef INET6 62574462Salfred case AF_INET6: 626319615Sdelphij if (nbuf->len < sizeof(*sin6)) 627319615Sdelphij return NULL; 62874462Salfred sin6 = nbuf->buf; 62974462Salfred if (inet_ntop(af, &sin6->sin6_addr, namebuf6, sizeof namebuf6) 63074462Salfred == NULL) 63174462Salfred return NULL; 63274462Salfred port = ntohs(sin6->sin6_port); 63374462Salfred if (asprintf(&ret, "%s.%u.%u", namebuf6, ((u_int32_t)port) >> 8, 63474462Salfred port & 0xff) < 0) 63574462Salfred return NULL; 63674462Salfred break; 63774462Salfred#endif 63874462Salfred case AF_LOCAL: 63974462Salfred sun = nbuf->buf; 64076523Siedowse if (asprintf(&ret, "%.*s", (int)(sun->sun_len - 64176523Siedowse offsetof(struct sockaddr_un, sun_path)), 64276523Siedowse sun->sun_path) < 0) 64376523Siedowse return (NULL); 64474462Salfred break; 64574462Salfred default: 64674462Salfred return NULL; 64774462Salfred } 64874462Salfred 64974462Salfred return ret; 65074462Salfred} 65174462Salfred 65274462Salfredstruct netbuf * 65374462Salfred__rpc_uaddr2taddr_af(int af, const char *uaddr) 65474462Salfred{ 65574462Salfred struct netbuf *ret = NULL; 65674462Salfred char *addrstr, *p; 65774462Salfred unsigned port, portlo, porthi; 65874462Salfred struct sockaddr_in *sin; 65974462Salfred#ifdef INET6 66074462Salfred struct sockaddr_in6 *sin6; 66174462Salfred#endif 66274462Salfred struct sockaddr_un *sun; 66374462Salfred 66490271Salfred port = 0; 66590271Salfred sin = NULL; 666319615Sdelphij 667319615Sdelphij if (uaddr == NULL) 668319615Sdelphij return NULL; 669319615Sdelphij 67074462Salfred addrstr = strdup(uaddr); 67174462Salfred if (addrstr == NULL) 67274462Salfred return NULL; 67374462Salfred 67474462Salfred /* 67574462Salfred * AF_LOCAL addresses are expected to be absolute 67674462Salfred * pathnames, anything else will be AF_INET or AF_INET6. 67774462Salfred */ 67874462Salfred if (*addrstr != '/') { 67974462Salfred p = strrchr(addrstr, '.'); 68074462Salfred if (p == NULL) 68174462Salfred goto out; 68274462Salfred portlo = (unsigned)atoi(p + 1); 68374462Salfred *p = '\0'; 68474462Salfred 68574462Salfred p = strrchr(addrstr, '.'); 68674462Salfred if (p == NULL) 68774462Salfred goto out; 68874462Salfred porthi = (unsigned)atoi(p + 1); 68974462Salfred *p = '\0'; 69074462Salfred port = (porthi << 8) | portlo; 69174462Salfred } 69274462Salfred 69374462Salfred ret = (struct netbuf *)malloc(sizeof *ret); 694109951Smbr if (ret == NULL) 695109951Smbr goto out; 69674462Salfred 69774462Salfred switch (af) { 69874462Salfred case AF_INET: 69974462Salfred sin = (struct sockaddr_in *)malloc(sizeof *sin); 70074462Salfred if (sin == NULL) 70174462Salfred goto out; 70274462Salfred memset(sin, 0, sizeof *sin); 70374462Salfred sin->sin_family = AF_INET; 70474462Salfred sin->sin_port = htons(port); 70574462Salfred if (inet_pton(AF_INET, addrstr, &sin->sin_addr) <= 0) { 70674462Salfred free(sin); 70774462Salfred free(ret); 70874462Salfred ret = NULL; 70974462Salfred goto out; 71074462Salfred } 71174462Salfred sin->sin_len = ret->maxlen = ret->len = sizeof *sin; 71274462Salfred ret->buf = sin; 71374462Salfred break; 71474462Salfred#ifdef INET6 71574462Salfred case AF_INET6: 71674462Salfred sin6 = (struct sockaddr_in6 *)malloc(sizeof *sin6); 71774462Salfred if (sin6 == NULL) 71874462Salfred goto out; 71974462Salfred memset(sin6, 0, sizeof *sin6); 72074462Salfred sin6->sin6_family = AF_INET6; 72174462Salfred sin6->sin6_port = htons(port); 72274462Salfred if (inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) <= 0) { 723109951Smbr free(sin6); 72474462Salfred free(ret); 72574462Salfred ret = NULL; 72674462Salfred goto out; 72774462Salfred } 72874462Salfred sin6->sin6_len = ret->maxlen = ret->len = sizeof *sin6; 72974462Salfred ret->buf = sin6; 73074462Salfred break; 73174462Salfred#endif 73274462Salfred case AF_LOCAL: 73374462Salfred sun = (struct sockaddr_un *)malloc(sizeof *sun); 73474462Salfred if (sun == NULL) 73574462Salfred goto out; 73674462Salfred memset(sun, 0, sizeof *sun); 73774462Salfred sun->sun_family = AF_LOCAL; 73874462Salfred strncpy(sun->sun_path, addrstr, sizeof(sun->sun_path) - 1); 73976044Siedowse ret->len = ret->maxlen = sun->sun_len = SUN_LEN(sun); 74076044Siedowse ret->buf = sun; 74174462Salfred break; 74274462Salfred default: 74374462Salfred break; 74474462Salfred } 74574462Salfredout: 74674462Salfred free(addrstr); 74774462Salfred return ret; 74874462Salfred} 74974462Salfred 75074462Salfredint 75174462Salfred__rpc_seman2socktype(int semantics) 75274462Salfred{ 75374462Salfred switch (semantics) { 75474462Salfred case NC_TPI_CLTS: 75574462Salfred return SOCK_DGRAM; 75674462Salfred case NC_TPI_COTS_ORD: 75774462Salfred return SOCK_STREAM; 75874462Salfred case NC_TPI_RAW: 75974462Salfred return SOCK_RAW; 76074462Salfred default: 76174462Salfred break; 76274462Salfred } 76374462Salfred 76474462Salfred return -1; 76574462Salfred} 76674462Salfred 76774462Salfredint 76874462Salfred__rpc_socktype2seman(int socktype) 76974462Salfred{ 77074462Salfred switch (socktype) { 77174462Salfred case SOCK_DGRAM: 77274462Salfred return NC_TPI_CLTS; 77374462Salfred case SOCK_STREAM: 77474462Salfred return NC_TPI_COTS_ORD; 77574462Salfred case SOCK_RAW: 77674462Salfred return NC_TPI_RAW; 77774462Salfred default: 77874462Salfred break; 77974462Salfred } 78074462Salfred 78174462Salfred return -1; 78274462Salfred} 78374462Salfred 78474462Salfred/* 78574462Salfred * XXXX - IPv6 scope IDs can't be handled in universal addresses. 78674462Salfred * Here, we compare the original server address to that of the RPC 78774462Salfred * service we just received back from a call to rpcbind on the remote 78874462Salfred * machine. If they are both "link local" or "site local", copy 78974462Salfred * the scope id of the server address over to the service address. 79074462Salfred */ 79174462Salfredint 79274462Salfred__rpc_fixup_addr(struct netbuf *new, const struct netbuf *svc) 79374462Salfred{ 79474462Salfred#ifdef INET6 79574462Salfred struct sockaddr *sa_new, *sa_svc; 79674462Salfred struct sockaddr_in6 *sin6_new, *sin6_svc; 79774462Salfred 79874462Salfred sa_svc = (struct sockaddr *)svc->buf; 79974462Salfred sa_new = (struct sockaddr *)new->buf; 80074462Salfred 80174462Salfred if (sa_new->sa_family == sa_svc->sa_family && 80274462Salfred sa_new->sa_family == AF_INET6) { 80374462Salfred sin6_new = (struct sockaddr_in6 *)new->buf; 80474462Salfred sin6_svc = (struct sockaddr_in6 *)svc->buf; 80574462Salfred 80674462Salfred if ((IN6_IS_ADDR_LINKLOCAL(&sin6_new->sin6_addr) && 80774462Salfred IN6_IS_ADDR_LINKLOCAL(&sin6_svc->sin6_addr)) || 80874462Salfred (IN6_IS_ADDR_SITELOCAL(&sin6_new->sin6_addr) && 80974462Salfred IN6_IS_ADDR_SITELOCAL(&sin6_svc->sin6_addr))) { 81074462Salfred sin6_new->sin6_scope_id = sin6_svc->sin6_scope_id; 81174462Salfred } 81274462Salfred } 81374462Salfred#endif 81474462Salfred return 1; 81574462Salfred} 81674462Salfred 81774462Salfredint 81874462Salfred__rpc_sockisbound(int fd) 81974462Salfred{ 82074462Salfred struct sockaddr_storage ss; 82174462Salfred socklen_t slen; 82274462Salfred 82374462Salfred slen = sizeof (struct sockaddr_storage); 82474462Salfred if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) 82574462Salfred return 0; 82674462Salfred 82774462Salfred switch (ss.ss_family) { 82874462Salfred case AF_INET: 82974462Salfred return (((struct sockaddr_in *) 83074462Salfred (void *)&ss)->sin_port != 0); 83174462Salfred#ifdef INET6 83274462Salfred case AF_INET6: 83374462Salfred return (((struct sockaddr_in6 *) 83474462Salfred (void *)&ss)->sin6_port != 0); 83574462Salfred#endif 83674462Salfred case AF_LOCAL: 83774462Salfred /* XXX check this */ 83874462Salfred return (((struct sockaddr_un *) 83974462Salfred (void *)&ss)->sun_path[0] != '\0'); 84074462Salfred default: 84174462Salfred break; 84274462Salfred } 84374462Salfred 84474462Salfred return 0; 84574462Salfred} 846