174462Salfred/* $NetBSD: rpc_generic.c,v 1.4 2000/09/28 09:07:04 kleink Exp $ */ 274462Salfred 374462Salfred/* 474462Salfred * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 574462Salfred * unrestricted use provided that this legend is included on all tape 674462Salfred * media and as a part of the software program in whole or part. Users 774462Salfred * may copy or modify Sun RPC without charge, but are not authorized 874462Salfred * to license or distribute it to anyone else except as part of a product or 974462Salfred * program developed by the user. 1074462Salfred * 1174462Salfred * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 1274462Salfred * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 1374462Salfred * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 1474462Salfred * 1574462Salfred * Sun RPC is provided with no support and without any obligation on the 1674462Salfred * part of Sun Microsystems, Inc. to assist in its use, correction, 1774462Salfred * modification or enhancement. 1874462Salfred * 1974462Salfred * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 2074462Salfred * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 2174462Salfred * OR ANY PART THEREOF. 2274462Salfred * 2374462Salfred * In no event will Sun Microsystems, Inc. be liable for any lost revenue 2474462Salfred * or profits or other special, indirect and consequential damages, even if 2574462Salfred * Sun has been advised of the possibility of such damages. 2674462Salfred * 2774462Salfred * Sun Microsystems, Inc. 2874462Salfred * 2550 Garcia Avenue 2974462Salfred * Mountain View, California 94043 3074462Salfred */ 3174462Salfred/* 3274462Salfred * Copyright (c) 1986-1991 by Sun Microsystems Inc. 3374462Salfred */ 3474462Salfred 3574462Salfred/* #pragma ident "@(#)rpc_generic.c 1.17 94/04/24 SMI" */ 3692990Sobrien#include <sys/cdefs.h> 3792990Sobrien__FBSDID("$FreeBSD$"); 3874462Salfred 3974462Salfred/* 4074462Salfred * rpc_generic.c, Miscl routines for RPC. 4174462Salfred * 4274462Salfred */ 4374462Salfred 4475094Siedowse#include "namespace.h" 4574462Salfred#include "reentrant.h" 4674462Salfred#include <sys/types.h> 4774462Salfred#include <sys/param.h> 4874462Salfred#include <sys/socket.h> 4974462Salfred#include <sys/time.h> 5074462Salfred#include <sys/un.h> 5174462Salfred#include <sys/resource.h> 5274462Salfred#include <netinet/in.h> 5374462Salfred#include <arpa/inet.h> 5474462Salfred#include <rpc/rpc.h> 5574462Salfred#include <ctype.h> 5676523Siedowse#include <stddef.h> 5774462Salfred#include <stdio.h> 5874462Salfred#include <netdb.h> 5974462Salfred#include <netconfig.h> 6074462Salfred#include <stdlib.h> 6174462Salfred#include <string.h> 6274462Salfred#include <syslog.h> 6374462Salfred#include <rpc/nettype.h> 6474462Salfred#include "un-namespace.h" 6574462Salfred#include "rpc_com.h" 66156090Sdeischen#include "mt_misc.h" 6774462Salfred 6874462Salfredstruct handle { 6974462Salfred NCONF_HANDLE *nhandle; 7074462Salfred int nflag; /* Whether NETPATH or NETCONFIG */ 7174462Salfred int nettype; 7274462Salfred}; 7374462Salfred 7474462Salfredstatic const struct _rpcnettype { 7574462Salfred const char *name; 7674462Salfred const int type; 7774462Salfred} _rpctypelist[] = { 7874462Salfred { "netpath", _RPC_NETPATH }, 7974462Salfred { "visible", _RPC_VISIBLE }, 8074462Salfred { "circuit_v", _RPC_CIRCUIT_V }, 8174462Salfred { "datagram_v", _RPC_DATAGRAM_V }, 8274462Salfred { "circuit_n", _RPC_CIRCUIT_N }, 8374462Salfred { "datagram_n", _RPC_DATAGRAM_N }, 8474462Salfred { "tcp", _RPC_TCP }, 8574462Salfred { "udp", _RPC_UDP }, 8674462Salfred { 0, _RPC_NONE } 8774462Salfred}; 8874462Salfred 8974462Salfredstruct netid_af { 9074462Salfred const char *netid; 9174462Salfred int af; 9274462Salfred int protocol; 9374462Salfred}; 9474462Salfred 9574462Salfredstatic const struct netid_af na_cvt[] = { 9674462Salfred { "udp", AF_INET, IPPROTO_UDP }, 9774462Salfred { "tcp", AF_INET, IPPROTO_TCP }, 9874462Salfred#ifdef INET6 9974462Salfred { "udp6", AF_INET6, IPPROTO_UDP }, 10074462Salfred { "tcp6", AF_INET6, IPPROTO_TCP }, 10174462Salfred#endif 102107952Smbr { "local", AF_LOCAL, 0 } 10374462Salfred}; 10474462Salfred 10574462Salfred#if 0 10692905Sobrienstatic char *strlocase(char *); 10774462Salfred#endif 10892905Sobrienstatic int getnettype(const char *); 10974462Salfred 11074462Salfred/* 11174462Salfred * Cache the result of getrlimit(), so we don't have to do an 11274462Salfred * expensive call every time. 11374462Salfred */ 11474462Salfredint 11574462Salfred__rpc_dtbsize() 11674462Salfred{ 11774462Salfred static int tbsize; 11874462Salfred struct rlimit rl; 11974462Salfred 12074462Salfred if (tbsize) { 12174462Salfred return (tbsize); 12274462Salfred } 12374462Salfred if (getrlimit(RLIMIT_NOFILE, &rl) == 0) { 12474462Salfred return (tbsize = (int)rl.rlim_max); 12574462Salfred } 12674462Salfred /* 12774462Salfred * Something wrong. I'll try to save face by returning a 12874462Salfred * pessimistic number. 12974462Salfred */ 13074462Salfred return (32); 13174462Salfred} 13274462Salfred 13374462Salfred 13474462Salfred/* 13574462Salfred * Find the appropriate buffer size 13674462Salfred */ 13774462Salfredu_int 13874462Salfred/*ARGSUSED*/ 13974462Salfred__rpc_get_t_size(af, proto, size) 14074462Salfred int af, proto; 14174462Salfred int size; /* Size requested */ 14274462Salfred{ 14375314Siedowse int maxsize, defsize; 14474462Salfred 14575314Siedowse maxsize = 256 * 1024; /* XXX */ 14674462Salfred switch (proto) { 14774462Salfred case IPPROTO_TCP: 14875314Siedowse defsize = 64 * 1024; /* XXX */ 14974462Salfred break; 15074462Salfred case IPPROTO_UDP: 15175314Siedowse defsize = UDPMSGSIZE; 15274462Salfred break; 15374462Salfred default: 15475314Siedowse defsize = RPC_MAXDATASIZE; 15574462Salfred break; 15674462Salfred } 15774462Salfred if (size == 0) 15875314Siedowse return defsize; 15974462Salfred 16074462Salfred /* Check whether the value is within the upper max limit */ 16174462Salfred return (size > maxsize ? (u_int)maxsize : (u_int)size); 16274462Salfred} 16374462Salfred 16474462Salfred/* 16574462Salfred * Find the appropriate address buffer size 16674462Salfred */ 16774462Salfredu_int 16874462Salfred__rpc_get_a_size(af) 16974462Salfred int af; 17074462Salfred{ 17174462Salfred switch (af) { 17274462Salfred case AF_INET: 17374462Salfred return sizeof (struct sockaddr_in); 17474462Salfred#ifdef INET6 17574462Salfred case AF_INET6: 17674462Salfred return sizeof (struct sockaddr_in6); 17774462Salfred#endif 17874462Salfred case AF_LOCAL: 17974462Salfred return sizeof (struct sockaddr_un); 18074462Salfred default: 18174462Salfred break; 18274462Salfred } 18374462Salfred return ((u_int)RPC_MAXADDRSIZE); 18474462Salfred} 18574462Salfred 18674462Salfred#if 0 18774462Salfredstatic char * 18874462Salfredstrlocase(p) 18974462Salfred char *p; 19074462Salfred{ 19174462Salfred char *t = p; 19274462Salfred 19374462Salfred for (; *p; p++) 19474462Salfred if (isupper(*p)) 19574462Salfred *p = tolower(*p); 19674462Salfred return (t); 19774462Salfred} 19874462Salfred#endif 19974462Salfred 20074462Salfred/* 20174462Salfred * Returns the type of the network as defined in <rpc/nettype.h> 20274462Salfred * If nettype is NULL, it defaults to NETPATH. 20374462Salfred */ 20474462Salfredstatic int 20574462Salfredgetnettype(nettype) 20674462Salfred const char *nettype; 20774462Salfred{ 20874462Salfred int i; 20974462Salfred 210121652Smbr if ((nettype == NULL) || (nettype[0] == 0)) { 21174462Salfred return (_RPC_NETPATH); /* Default */ 21274462Salfred } 21374462Salfred 21474462Salfred#if 0 21574462Salfred nettype = strlocase(nettype); 21674462Salfred#endif 21774462Salfred for (i = 0; _rpctypelist[i].name; i++) 21874462Salfred if (strcasecmp(nettype, _rpctypelist[i].name) == 0) { 21974462Salfred return (_rpctypelist[i].type); 22074462Salfred } 22174462Salfred return (_rpctypelist[i].type); 22274462Salfred} 22374462Salfred 224204950Sjhbstatic thread_key_t tcp_key, udp_key; 225204950Sjhbstatic once_t keys_once = ONCE_INITIALIZER; 226204950Sjhbstatic int tcp_key_error, udp_key_error; 227204950Sjhb 228204950Sjhbstatic void 229204950Sjhbkeys_init(void) 230204950Sjhb{ 231204950Sjhb 232204950Sjhb tcp_key_error = thr_keycreate(&tcp_key, free); 233204950Sjhb udp_key_error = thr_keycreate(&udp_key, free); 234204950Sjhb} 235204950Sjhb 23674462Salfred/* 23774462Salfred * For the given nettype (tcp or udp only), return the first structure found. 23874462Salfred * This should be freed by calling freenetconfigent() 23974462Salfred */ 24074462Salfredstruct netconfig * 24174462Salfred__rpc_getconfip(nettype) 24274462Salfred const char *nettype; 24374462Salfred{ 24474462Salfred char *netid; 24574462Salfred char *netid_tcp = (char *) NULL; 24674462Salfred char *netid_udp = (char *) NULL; 24774462Salfred static char *netid_tcp_main; 24874462Salfred static char *netid_udp_main; 24974462Salfred struct netconfig *dummy; 25074462Salfred int main_thread; 25174462Salfred 25274462Salfred if ((main_thread = thr_main())) { 25374462Salfred netid_udp = netid_udp_main; 25474462Salfred netid_tcp = netid_tcp_main; 25574462Salfred } else { 256204950Sjhb if (thr_once(&keys_once, keys_init) != 0 || 257204950Sjhb tcp_key_error != 0 || udp_key_error != 0) 258204950Sjhb return (NULL); 25974462Salfred netid_tcp = (char *)thr_getspecific(tcp_key); 26074462Salfred netid_udp = (char *)thr_getspecific(udp_key); 26174462Salfred } 26274462Salfred if (!netid_udp && !netid_tcp) { 26374462Salfred struct netconfig *nconf; 26474462Salfred void *confighandle; 26574462Salfred 26674462Salfred if (!(confighandle = setnetconfig())) { 26774462Salfred syslog (LOG_ERR, "rpc: failed to open " NETCONFIG); 26874462Salfred return (NULL); 26974462Salfred } 27074462Salfred while ((nconf = getnetconfig(confighandle)) != NULL) { 27174462Salfred if (strcmp(nconf->nc_protofmly, NC_INET) == 0) { 272241142Spfg if (strcmp(nconf->nc_proto, NC_TCP) == 0 && 273241142Spfg netid_tcp == NULL) { 27474462Salfred netid_tcp = strdup(nconf->nc_netid); 27574462Salfred if (main_thread) 27674462Salfred netid_tcp_main = netid_tcp; 27774462Salfred else 27874462Salfred thr_setspecific(tcp_key, 27974462Salfred (void *) netid_tcp); 28074462Salfred } else 281241142Spfg if (strcmp(nconf->nc_proto, NC_UDP) == 0 && 282241142Spfg netid_udp == NULL) { 28374462Salfred netid_udp = strdup(nconf->nc_netid); 28474462Salfred if (main_thread) 28574462Salfred netid_udp_main = netid_udp; 28674462Salfred else 28774462Salfred thr_setspecific(udp_key, 28874462Salfred (void *) netid_udp); 28974462Salfred } 29074462Salfred } 29174462Salfred } 29274462Salfred endnetconfig(confighandle); 29374462Salfred } 29474462Salfred if (strcmp(nettype, "udp") == 0) 29574462Salfred netid = netid_udp; 29674462Salfred else if (strcmp(nettype, "tcp") == 0) 29774462Salfred netid = netid_tcp; 29874462Salfred else { 29974462Salfred return (NULL); 30074462Salfred } 301121652Smbr if ((netid == NULL) || (netid[0] == 0)) { 30274462Salfred return (NULL); 30374462Salfred } 30474462Salfred dummy = getnetconfigent(netid); 30574462Salfred return (dummy); 30674462Salfred} 30774462Salfred 30874462Salfred/* 30974462Salfred * Returns the type of the nettype, which should then be used with 31074462Salfred * __rpc_getconf(). 31174462Salfred */ 31274462Salfredvoid * 31374462Salfred__rpc_setconf(nettype) 31474462Salfred const char *nettype; 31574462Salfred{ 31674462Salfred struct handle *handle; 31774462Salfred 31874462Salfred handle = (struct handle *) malloc(sizeof (struct handle)); 31974462Salfred if (handle == NULL) { 32074462Salfred return (NULL); 32174462Salfred } 32274462Salfred switch (handle->nettype = getnettype(nettype)) { 32374462Salfred case _RPC_NETPATH: 32474462Salfred case _RPC_CIRCUIT_N: 32574462Salfred case _RPC_DATAGRAM_N: 326172259Smatteo if (!(handle->nhandle = setnetpath())) 327172259Smatteo goto failed; 32874462Salfred handle->nflag = TRUE; 32974462Salfred break; 33074462Salfred case _RPC_VISIBLE: 33174462Salfred case _RPC_CIRCUIT_V: 33274462Salfred case _RPC_DATAGRAM_V: 33374462Salfred case _RPC_TCP: 33474462Salfred case _RPC_UDP: 33574462Salfred if (!(handle->nhandle = setnetconfig())) { 33674462Salfred syslog (LOG_ERR, "rpc: failed to open " NETCONFIG); 337172259Smatteo goto failed; 33874462Salfred } 33974462Salfred handle->nflag = FALSE; 34074462Salfred break; 34174462Salfred default: 342172259Smatteo goto failed; 34374462Salfred } 34474462Salfred 34574462Salfred return (handle); 346172259Smatteo 347172259Smatteofailed: 348172259Smatteo free(handle); 349172259Smatteo return (NULL); 35074462Salfred} 35174462Salfred 35274462Salfred/* 35374462Salfred * Returns the next netconfig struct for the given "net" type. 35474462Salfred * __rpc_setconf() should have been called previously. 35574462Salfred */ 35674462Salfredstruct netconfig * 35774462Salfred__rpc_getconf(vhandle) 35874462Salfred void *vhandle; 35974462Salfred{ 36074462Salfred struct handle *handle; 36174462Salfred struct netconfig *nconf; 36274462Salfred 36374462Salfred handle = (struct handle *)vhandle; 36474462Salfred if (handle == NULL) { 36574462Salfred return (NULL); 36674462Salfred } 36774462Salfred for (;;) { 36874462Salfred if (handle->nflag) 36974462Salfred nconf = getnetpath(handle->nhandle); 37074462Salfred else 37174462Salfred nconf = getnetconfig(handle->nhandle); 37274462Salfred if (nconf == NULL) 37374462Salfred break; 37474462Salfred if ((nconf->nc_semantics != NC_TPI_CLTS) && 37574462Salfred (nconf->nc_semantics != NC_TPI_COTS) && 37674462Salfred (nconf->nc_semantics != NC_TPI_COTS_ORD)) 37774462Salfred continue; 37874462Salfred switch (handle->nettype) { 37974462Salfred case _RPC_VISIBLE: 38074462Salfred if (!(nconf->nc_flag & NC_VISIBLE)) 38174462Salfred continue; 38274462Salfred /* FALLTHROUGH */ 38374462Salfred case _RPC_NETPATH: /* Be happy */ 38474462Salfred break; 38574462Salfred case _RPC_CIRCUIT_V: 38674462Salfred if (!(nconf->nc_flag & NC_VISIBLE)) 38774462Salfred continue; 38874462Salfred /* FALLTHROUGH */ 38974462Salfred case _RPC_CIRCUIT_N: 39074462Salfred if ((nconf->nc_semantics != NC_TPI_COTS) && 39174462Salfred (nconf->nc_semantics != NC_TPI_COTS_ORD)) 39274462Salfred continue; 39374462Salfred break; 39474462Salfred case _RPC_DATAGRAM_V: 39574462Salfred if (!(nconf->nc_flag & NC_VISIBLE)) 39674462Salfred continue; 39774462Salfred /* FALLTHROUGH */ 39874462Salfred case _RPC_DATAGRAM_N: 39974462Salfred if (nconf->nc_semantics != NC_TPI_CLTS) 40074462Salfred continue; 40174462Salfred break; 40274462Salfred case _RPC_TCP: 40374462Salfred if (((nconf->nc_semantics != NC_TPI_COTS) && 40474462Salfred (nconf->nc_semantics != NC_TPI_COTS_ORD)) || 40574462Salfred (strcmp(nconf->nc_protofmly, NC_INET) 40674462Salfred#ifdef INET6 40774462Salfred && strcmp(nconf->nc_protofmly, NC_INET6)) 40874462Salfred#else 40974462Salfred ) 41074462Salfred#endif 41174462Salfred || 41274462Salfred strcmp(nconf->nc_proto, NC_TCP)) 41374462Salfred continue; 41474462Salfred break; 41574462Salfred case _RPC_UDP: 41674462Salfred if ((nconf->nc_semantics != NC_TPI_CLTS) || 41774462Salfred (strcmp(nconf->nc_protofmly, NC_INET) 41874462Salfred#ifdef INET6 41974462Salfred && strcmp(nconf->nc_protofmly, NC_INET6)) 42074462Salfred#else 42174462Salfred ) 42274462Salfred#endif 42374462Salfred || 42474462Salfred strcmp(nconf->nc_proto, NC_UDP)) 42574462Salfred continue; 42674462Salfred break; 42774462Salfred } 42874462Salfred break; 42974462Salfred } 43074462Salfred return (nconf); 43174462Salfred} 43274462Salfred 43374462Salfredvoid 43474462Salfred__rpc_endconf(vhandle) 43574462Salfred void * vhandle; 43674462Salfred{ 43774462Salfred struct handle *handle; 43874462Salfred 43974462Salfred handle = (struct handle *) vhandle; 44074462Salfred if (handle == NULL) { 44174462Salfred return; 44274462Salfred } 44374462Salfred if (handle->nflag) { 44474462Salfred endnetpath(handle->nhandle); 44574462Salfred } else { 44674462Salfred endnetconfig(handle->nhandle); 44774462Salfred } 44874462Salfred free(handle); 44974462Salfred} 45074462Salfred 45174462Salfred/* 45274462Salfred * Used to ping the NULL procedure for clnt handle. 45374462Salfred * Returns NULL if fails, else a non-NULL pointer. 45474462Salfred */ 45574462Salfredvoid * 45674462Salfredrpc_nullproc(clnt) 45774462Salfred CLIENT *clnt; 45874462Salfred{ 45974462Salfred struct timeval TIMEOUT = {25, 0}; 46074462Salfred 46174462Salfred if (clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void, NULL, 46274462Salfred (xdrproc_t) xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) { 46374462Salfred return (NULL); 46474462Salfred } 46574462Salfred return ((void *) clnt); 46674462Salfred} 46774462Salfred 46874462Salfred/* 46974462Salfred * Try all possible transports until 47074462Salfred * one succeeds in finding the netconf for the given fd. 47174462Salfred */ 47274462Salfredstruct netconfig * 47374462Salfred__rpcgettp(fd) 47474462Salfred int fd; 47574462Salfred{ 47674462Salfred const char *netid; 47774462Salfred struct __rpc_sockinfo si; 47874462Salfred 47974462Salfred if (!__rpc_fd2sockinfo(fd, &si)) 48074462Salfred return NULL; 48174462Salfred 48274462Salfred if (!__rpc_sockinfo2netid(&si, &netid)) 48374462Salfred return NULL; 48474462Salfred 48574462Salfred /*LINTED const castaway*/ 48674462Salfred return getnetconfigent((char *)netid); 48774462Salfred} 48874462Salfred 48974462Salfredint 49074462Salfred__rpc_fd2sockinfo(int fd, struct __rpc_sockinfo *sip) 49174462Salfred{ 49274462Salfred socklen_t len; 49374462Salfred int type, proto; 49474462Salfred struct sockaddr_storage ss; 49574462Salfred 49674462Salfred len = sizeof ss; 49774462Salfred if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &len) < 0) 49874462Salfred return 0; 49974462Salfred sip->si_alen = len; 50074462Salfred 50174462Salfred len = sizeof type; 50274462Salfred if (_getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &len) < 0) 50374462Salfred return 0; 50474462Salfred 50574462Salfred /* XXX */ 50674462Salfred if (ss.ss_family != AF_LOCAL) { 50774462Salfred if (type == SOCK_STREAM) 50874462Salfred proto = IPPROTO_TCP; 50974462Salfred else if (type == SOCK_DGRAM) 51074462Salfred proto = IPPROTO_UDP; 51174462Salfred else 51274462Salfred return 0; 51374462Salfred } else 51474462Salfred proto = 0; 51574462Salfred 51674462Salfred sip->si_af = ss.ss_family; 51774462Salfred sip->si_proto = proto; 51874462Salfred sip->si_socktype = type; 51974462Salfred 52074462Salfred return 1; 52174462Salfred} 52274462Salfred 52374462Salfred/* 52474462Salfred * Linear search, but the number of entries is small. 52574462Salfred */ 52674462Salfredint 52774462Salfred__rpc_nconf2sockinfo(const struct netconfig *nconf, struct __rpc_sockinfo *sip) 52874462Salfred{ 52974462Salfred int i; 53074462Salfred 53174462Salfred for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++) 532107952Smbr if (strcmp(na_cvt[i].netid, nconf->nc_netid) == 0 || ( 533107952Smbr strcmp(nconf->nc_netid, "unix") == 0 && 534107952Smbr strcmp(na_cvt[i].netid, "local") == 0)) { 53574462Salfred sip->si_af = na_cvt[i].af; 53674462Salfred sip->si_proto = na_cvt[i].protocol; 53774462Salfred sip->si_socktype = 53874462Salfred __rpc_seman2socktype((int)nconf->nc_semantics); 53974462Salfred if (sip->si_socktype == -1) 54074462Salfred return 0; 54174462Salfred sip->si_alen = __rpc_get_a_size(sip->si_af); 54274462Salfred return 1; 54374462Salfred } 54474462Salfred 54574462Salfred return 0; 54674462Salfred} 54774462Salfred 54874462Salfredint 54974462Salfred__rpc_nconf2fd(const struct netconfig *nconf) 55074462Salfred{ 55174462Salfred struct __rpc_sockinfo si; 55274462Salfred 55374462Salfred if (!__rpc_nconf2sockinfo(nconf, &si)) 55474462Salfred return 0; 55574462Salfred 55674462Salfred return _socket(si.si_af, si.si_socktype, si.si_proto); 55774462Salfred} 55874462Salfred 55974462Salfredint 56074462Salfred__rpc_sockinfo2netid(struct __rpc_sockinfo *sip, const char **netid) 56174462Salfred{ 56274462Salfred int i; 563109384Smbr struct netconfig *nconf; 56474462Salfred 565109384Smbr nconf = getnetconfigent("local"); 566109384Smbr 567107952Smbr for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++) { 56874462Salfred if (na_cvt[i].af == sip->si_af && 56974462Salfred na_cvt[i].protocol == sip->si_proto) { 570109384Smbr if (strcmp(na_cvt[i].netid, "local") == 0 && nconf == NULL) { 571107952Smbr if (netid) 572107952Smbr *netid = "unix"; 573107952Smbr } else { 574107952Smbr if (netid) 575107952Smbr *netid = na_cvt[i].netid; 576107952Smbr } 577109384Smbr if (nconf != NULL) 578109384Smbr freenetconfigent(nconf); 57974462Salfred return 1; 58074462Salfred } 581107952Smbr } 582109384Smbr if (nconf != NULL) 583109384Smbr freenetconfigent(nconf); 58474462Salfred 58574462Salfred return 0; 58674462Salfred} 58774462Salfred 58874462Salfredchar * 58974462Salfredtaddr2uaddr(const struct netconfig *nconf, const struct netbuf *nbuf) 59074462Salfred{ 59174462Salfred struct __rpc_sockinfo si; 59274462Salfred 59374462Salfred if (!__rpc_nconf2sockinfo(nconf, &si)) 59474462Salfred return NULL; 59574462Salfred return __rpc_taddr2uaddr_af(si.si_af, nbuf); 59674462Salfred} 59774462Salfred 59874462Salfredstruct netbuf * 59974462Salfreduaddr2taddr(const struct netconfig *nconf, const char *uaddr) 60074462Salfred{ 60174462Salfred struct __rpc_sockinfo si; 60274462Salfred 60374462Salfred if (!__rpc_nconf2sockinfo(nconf, &si)) 60474462Salfred return NULL; 60574462Salfred return __rpc_uaddr2taddr_af(si.si_af, uaddr); 60674462Salfred} 60774462Salfred 60874462Salfredchar * 60974462Salfred__rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf) 61074462Salfred{ 61174462Salfred char *ret; 61274462Salfred struct sockaddr_in *sin; 61374462Salfred struct sockaddr_un *sun; 61474462Salfred char namebuf[INET_ADDRSTRLEN]; 61574462Salfred#ifdef INET6 61674462Salfred struct sockaddr_in6 *sin6; 61774462Salfred char namebuf6[INET6_ADDRSTRLEN]; 61874462Salfred#endif 61974462Salfred u_int16_t port; 62074462Salfred 62174462Salfred switch (af) { 62274462Salfred case AF_INET: 62374462Salfred sin = nbuf->buf; 62474462Salfred if (inet_ntop(af, &sin->sin_addr, namebuf, sizeof namebuf) 62574462Salfred == NULL) 62674462Salfred return NULL; 62774462Salfred port = ntohs(sin->sin_port); 62874462Salfred if (asprintf(&ret, "%s.%u.%u", namebuf, ((u_int32_t)port) >> 8, 62974462Salfred port & 0xff) < 0) 63074462Salfred return NULL; 63174462Salfred break; 63274462Salfred#ifdef INET6 63374462Salfred case AF_INET6: 63474462Salfred sin6 = nbuf->buf; 63574462Salfred if (inet_ntop(af, &sin6->sin6_addr, namebuf6, sizeof namebuf6) 63674462Salfred == NULL) 63774462Salfred return NULL; 63874462Salfred port = ntohs(sin6->sin6_port); 63974462Salfred if (asprintf(&ret, "%s.%u.%u", namebuf6, ((u_int32_t)port) >> 8, 64074462Salfred port & 0xff) < 0) 64174462Salfred return NULL; 64274462Salfred break; 64374462Salfred#endif 64474462Salfred case AF_LOCAL: 64574462Salfred sun = nbuf->buf; 64676523Siedowse if (asprintf(&ret, "%.*s", (int)(sun->sun_len - 64776523Siedowse offsetof(struct sockaddr_un, sun_path)), 64876523Siedowse sun->sun_path) < 0) 64976523Siedowse return (NULL); 65074462Salfred break; 65174462Salfred default: 65274462Salfred return NULL; 65374462Salfred } 65474462Salfred 65574462Salfred return ret; 65674462Salfred} 65774462Salfred 65874462Salfredstruct netbuf * 65974462Salfred__rpc_uaddr2taddr_af(int af, const char *uaddr) 66074462Salfred{ 66174462Salfred struct netbuf *ret = NULL; 66274462Salfred char *addrstr, *p; 66374462Salfred unsigned port, portlo, porthi; 66474462Salfred struct sockaddr_in *sin; 66574462Salfred#ifdef INET6 66674462Salfred struct sockaddr_in6 *sin6; 66774462Salfred#endif 66874462Salfred struct sockaddr_un *sun; 66974462Salfred 67090271Salfred port = 0; 67190271Salfred sin = NULL; 67274462Salfred addrstr = strdup(uaddr); 67374462Salfred if (addrstr == NULL) 67474462Salfred return NULL; 67574462Salfred 67674462Salfred /* 67774462Salfred * AF_LOCAL addresses are expected to be absolute 67874462Salfred * pathnames, anything else will be AF_INET or AF_INET6. 67974462Salfred */ 68074462Salfred if (*addrstr != '/') { 68174462Salfred p = strrchr(addrstr, '.'); 68274462Salfred if (p == NULL) 68374462Salfred goto out; 68474462Salfred portlo = (unsigned)atoi(p + 1); 68574462Salfred *p = '\0'; 68674462Salfred 68774462Salfred p = strrchr(addrstr, '.'); 68874462Salfred if (p == NULL) 68974462Salfred goto out; 69074462Salfred porthi = (unsigned)atoi(p + 1); 69174462Salfred *p = '\0'; 69274462Salfred port = (porthi << 8) | portlo; 69374462Salfred } 69474462Salfred 69574462Salfred ret = (struct netbuf *)malloc(sizeof *ret); 696109951Smbr if (ret == NULL) 697109951Smbr goto out; 69874462Salfred 69974462Salfred switch (af) { 70074462Salfred case AF_INET: 70174462Salfred sin = (struct sockaddr_in *)malloc(sizeof *sin); 70274462Salfred if (sin == NULL) 70374462Salfred goto out; 70474462Salfred memset(sin, 0, sizeof *sin); 70574462Salfred sin->sin_family = AF_INET; 70674462Salfred sin->sin_port = htons(port); 70774462Salfred if (inet_pton(AF_INET, addrstr, &sin->sin_addr) <= 0) { 70874462Salfred free(sin); 70974462Salfred free(ret); 71074462Salfred ret = NULL; 71174462Salfred goto out; 71274462Salfred } 71374462Salfred sin->sin_len = ret->maxlen = ret->len = sizeof *sin; 71474462Salfred ret->buf = sin; 71574462Salfred break; 71674462Salfred#ifdef INET6 71774462Salfred case AF_INET6: 71874462Salfred sin6 = (struct sockaddr_in6 *)malloc(sizeof *sin6); 71974462Salfred if (sin6 == NULL) 72074462Salfred goto out; 72174462Salfred memset(sin6, 0, sizeof *sin6); 72274462Salfred sin6->sin6_family = AF_INET6; 72374462Salfred sin6->sin6_port = htons(port); 72474462Salfred if (inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) <= 0) { 725109951Smbr free(sin6); 72674462Salfred free(ret); 72774462Salfred ret = NULL; 72874462Salfred goto out; 72974462Salfred } 73074462Salfred sin6->sin6_len = ret->maxlen = ret->len = sizeof *sin6; 73174462Salfred ret->buf = sin6; 73274462Salfred break; 73374462Salfred#endif 73474462Salfred case AF_LOCAL: 73574462Salfred sun = (struct sockaddr_un *)malloc(sizeof *sun); 73674462Salfred if (sun == NULL) 73774462Salfred goto out; 73874462Salfred memset(sun, 0, sizeof *sun); 73974462Salfred sun->sun_family = AF_LOCAL; 74074462Salfred strncpy(sun->sun_path, addrstr, sizeof(sun->sun_path) - 1); 74176044Siedowse ret->len = ret->maxlen = sun->sun_len = SUN_LEN(sun); 74276044Siedowse ret->buf = sun; 74374462Salfred break; 74474462Salfred default: 74574462Salfred break; 74674462Salfred } 74774462Salfredout: 74874462Salfred free(addrstr); 74974462Salfred return ret; 75074462Salfred} 75174462Salfred 75274462Salfredint 75374462Salfred__rpc_seman2socktype(int semantics) 75474462Salfred{ 75574462Salfred switch (semantics) { 75674462Salfred case NC_TPI_CLTS: 75774462Salfred return SOCK_DGRAM; 75874462Salfred case NC_TPI_COTS_ORD: 75974462Salfred return SOCK_STREAM; 76074462Salfred case NC_TPI_RAW: 76174462Salfred return SOCK_RAW; 76274462Salfred default: 76374462Salfred break; 76474462Salfred } 76574462Salfred 76674462Salfred return -1; 76774462Salfred} 76874462Salfred 76974462Salfredint 77074462Salfred__rpc_socktype2seman(int socktype) 77174462Salfred{ 77274462Salfred switch (socktype) { 77374462Salfred case SOCK_DGRAM: 77474462Salfred return NC_TPI_CLTS; 77574462Salfred case SOCK_STREAM: 77674462Salfred return NC_TPI_COTS_ORD; 77774462Salfred case SOCK_RAW: 77874462Salfred return NC_TPI_RAW; 77974462Salfred default: 78074462Salfred break; 78174462Salfred } 78274462Salfred 78374462Salfred return -1; 78474462Salfred} 78574462Salfred 78674462Salfred/* 78774462Salfred * XXXX - IPv6 scope IDs can't be handled in universal addresses. 78874462Salfred * Here, we compare the original server address to that of the RPC 78974462Salfred * service we just received back from a call to rpcbind on the remote 79074462Salfred * machine. If they are both "link local" or "site local", copy 79174462Salfred * the scope id of the server address over to the service address. 79274462Salfred */ 79374462Salfredint 79474462Salfred__rpc_fixup_addr(struct netbuf *new, const struct netbuf *svc) 79574462Salfred{ 79674462Salfred#ifdef INET6 79774462Salfred struct sockaddr *sa_new, *sa_svc; 79874462Salfred struct sockaddr_in6 *sin6_new, *sin6_svc; 79974462Salfred 80074462Salfred sa_svc = (struct sockaddr *)svc->buf; 80174462Salfred sa_new = (struct sockaddr *)new->buf; 80274462Salfred 80374462Salfred if (sa_new->sa_family == sa_svc->sa_family && 80474462Salfred sa_new->sa_family == AF_INET6) { 80574462Salfred sin6_new = (struct sockaddr_in6 *)new->buf; 80674462Salfred sin6_svc = (struct sockaddr_in6 *)svc->buf; 80774462Salfred 80874462Salfred if ((IN6_IS_ADDR_LINKLOCAL(&sin6_new->sin6_addr) && 80974462Salfred IN6_IS_ADDR_LINKLOCAL(&sin6_svc->sin6_addr)) || 81074462Salfred (IN6_IS_ADDR_SITELOCAL(&sin6_new->sin6_addr) && 81174462Salfred IN6_IS_ADDR_SITELOCAL(&sin6_svc->sin6_addr))) { 81274462Salfred sin6_new->sin6_scope_id = sin6_svc->sin6_scope_id; 81374462Salfred } 81474462Salfred } 81574462Salfred#endif 81674462Salfred return 1; 81774462Salfred} 81874462Salfred 81974462Salfredint 82074462Salfred__rpc_sockisbound(int fd) 82174462Salfred{ 82274462Salfred struct sockaddr_storage ss; 82374462Salfred socklen_t slen; 82474462Salfred 82574462Salfred slen = sizeof (struct sockaddr_storage); 82674462Salfred if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) 82774462Salfred return 0; 82874462Salfred 82974462Salfred switch (ss.ss_family) { 83074462Salfred case AF_INET: 83174462Salfred return (((struct sockaddr_in *) 83274462Salfred (void *)&ss)->sin_port != 0); 83374462Salfred#ifdef INET6 83474462Salfred case AF_INET6: 83574462Salfred return (((struct sockaddr_in6 *) 83674462Salfred (void *)&ss)->sin6_port != 0); 83774462Salfred#endif 83874462Salfred case AF_LOCAL: 83974462Salfred /* XXX check this */ 84074462Salfred return (((struct sockaddr_un *) 84174462Salfred (void *)&ss)->sun_path[0] != '\0'); 84274462Salfred default: 84374462Salfred break; 84474462Salfred } 84574462Salfred 84674462Salfred return 0; 84774462Salfred} 848