17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5004388ebScasper * Common Development and Distribution License (the "License"). 6004388ebScasper * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 2161961e0fSrobinson 227c478bd9Sstevel@tonic-gate /* 23*cb620785Sraf * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 26*cb620785Sraf 277c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 287c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 297c478bd9Sstevel@tonic-gate /* 307c478bd9Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 317c478bd9Sstevel@tonic-gate * 4.3 BSD under license from the Regents of the University of 327c478bd9Sstevel@tonic-gate * California. 337c478bd9Sstevel@tonic-gate */ 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate #ifdef PORTMAP 387c478bd9Sstevel@tonic-gate /* 397c478bd9Sstevel@tonic-gate * rpc_soc.c 407c478bd9Sstevel@tonic-gate * 417c478bd9Sstevel@tonic-gate * The backward compatibility routines for the earlier implementation 427c478bd9Sstevel@tonic-gate * of RPC, where the only transports supported were tcp/ip and udp/ip. 437c478bd9Sstevel@tonic-gate * Based on berkeley socket abstraction, now implemented on the top 447c478bd9Sstevel@tonic-gate * of TLI/Streams 457c478bd9Sstevel@tonic-gate */ 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate #include "mt.h" 487c478bd9Sstevel@tonic-gate #include "rpc_mt.h" 497c478bd9Sstevel@tonic-gate #include <stdio.h> 507c478bd9Sstevel@tonic-gate #include <sys/types.h> 517c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 527c478bd9Sstevel@tonic-gate #include <netinet/in.h> 537c478bd9Sstevel@tonic-gate #include <sys/socket.h> 547c478bd9Sstevel@tonic-gate #include <netdb.h> 557c478bd9Sstevel@tonic-gate #include <netdir.h> 567c478bd9Sstevel@tonic-gate #include <errno.h> 577c478bd9Sstevel@tonic-gate #include <sys/syslog.h> 587c478bd9Sstevel@tonic-gate #include <rpc/pmap_clnt.h> 597c478bd9Sstevel@tonic-gate #include <rpc/pmap_prot.h> 607c478bd9Sstevel@tonic-gate #include <rpc/nettype.h> 617c478bd9Sstevel@tonic-gate #include <syslog.h> 627c478bd9Sstevel@tonic-gate #include <string.h> 637c478bd9Sstevel@tonic-gate #include <stdlib.h> 647c478bd9Sstevel@tonic-gate #include <unistd.h> 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate int __rpc_bindresvport(int, struct sockaddr_in *, int *, int); 677c478bd9Sstevel@tonic-gate int __rpc_bindresvport_ipv6(int, struct sockaddr *, int *, int, char *); 687c478bd9Sstevel@tonic-gate void get_myaddress_ipv6(char *, struct sockaddr *); 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate extern mutex_t rpcsoc_lock; 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate /* 737c478bd9Sstevel@tonic-gate * A common clnt create routine 747c478bd9Sstevel@tonic-gate */ 757c478bd9Sstevel@tonic-gate static CLIENT * 7661961e0fSrobinson clnt_com_create(struct sockaddr_in *raddr, rpcprog_t prog, rpcvers_t vers, 7761961e0fSrobinson int *sockp, uint_t sendsz, uint_t recvsz, char *tp) 787c478bd9Sstevel@tonic-gate { 797c478bd9Sstevel@tonic-gate CLIENT *cl; 807c478bd9Sstevel@tonic-gate int madefd = FALSE; 817c478bd9Sstevel@tonic-gate int fd = *sockp; 827c478bd9Sstevel@tonic-gate struct t_info tinfo; 837c478bd9Sstevel@tonic-gate struct netconfig *nconf; 847c478bd9Sstevel@tonic-gate int port; 857c478bd9Sstevel@tonic-gate struct netbuf bindaddr; 867c478bd9Sstevel@tonic-gate bool_t locked = TRUE; 877c478bd9Sstevel@tonic-gate 8861961e0fSrobinson (void) mutex_lock(&rpcsoc_lock); 897c478bd9Sstevel@tonic-gate if ((nconf = __rpc_getconfip(tp)) == NULL) { 907c478bd9Sstevel@tonic-gate rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 9161961e0fSrobinson (void) mutex_unlock(&rpcsoc_lock); 9261961e0fSrobinson return (NULL); 937c478bd9Sstevel@tonic-gate } 947c478bd9Sstevel@tonic-gate if (fd == RPC_ANYSOCK) { 957c478bd9Sstevel@tonic-gate fd = t_open(nconf->nc_device, O_RDWR, &tinfo); 967c478bd9Sstevel@tonic-gate if (fd == -1) 977c478bd9Sstevel@tonic-gate goto syserror; 98004388ebScasper RPC_RAISEFD(fd); 997c478bd9Sstevel@tonic-gate madefd = TRUE; 1007c478bd9Sstevel@tonic-gate } else { 1017c478bd9Sstevel@tonic-gate if (t_getinfo(fd, &tinfo) == -1) 1027c478bd9Sstevel@tonic-gate goto syserror; 1037c478bd9Sstevel@tonic-gate } 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate if (raddr->sin_port == 0) { 1067c478bd9Sstevel@tonic-gate uint_t proto; 1077c478bd9Sstevel@tonic-gate ushort_t sport; 1087c478bd9Sstevel@tonic-gate 10961961e0fSrobinson /* pmap_getport is recursive */ 11061961e0fSrobinson (void) mutex_unlock(&rpcsoc_lock); 1117c478bd9Sstevel@tonic-gate proto = strcmp(tp, "udp") == 0 ? IPPROTO_UDP : IPPROTO_TCP; 1127c478bd9Sstevel@tonic-gate sport = pmap_getport(raddr, prog, vers, proto); 1137c478bd9Sstevel@tonic-gate if (sport == 0) { 1147c478bd9Sstevel@tonic-gate locked = FALSE; 1157c478bd9Sstevel@tonic-gate goto err; 1167c478bd9Sstevel@tonic-gate } 1177c478bd9Sstevel@tonic-gate raddr->sin_port = htons(sport); 11861961e0fSrobinson /* pmap_getport is recursive */ 11961961e0fSrobinson (void) mutex_lock(&rpcsoc_lock); 1207c478bd9Sstevel@tonic-gate } 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate /* Transform sockaddr_in to netbuf */ 1237c478bd9Sstevel@tonic-gate bindaddr.maxlen = bindaddr.len = __rpc_get_a_size(tinfo.addr); 1247c478bd9Sstevel@tonic-gate bindaddr.buf = (char *)raddr; 1257c478bd9Sstevel@tonic-gate 12661961e0fSrobinson (void) __rpc_bindresvport(fd, NULL, &port, 0); 1277c478bd9Sstevel@tonic-gate cl = clnt_tli_create(fd, nconf, &bindaddr, prog, vers, 1287c478bd9Sstevel@tonic-gate sendsz, recvsz); 1297c478bd9Sstevel@tonic-gate if (cl) { 1307c478bd9Sstevel@tonic-gate if (madefd == TRUE) { 1317c478bd9Sstevel@tonic-gate /* 1327c478bd9Sstevel@tonic-gate * The fd should be closed while destroying the handle. 1337c478bd9Sstevel@tonic-gate */ 13461961e0fSrobinson (void) CLNT_CONTROL(cl, CLSET_FD_CLOSE, NULL); 1357c478bd9Sstevel@tonic-gate *sockp = fd; 1367c478bd9Sstevel@tonic-gate } 1377c478bd9Sstevel@tonic-gate (void) freenetconfigent(nconf); 13861961e0fSrobinson (void) mutex_unlock(&rpcsoc_lock); 1397c478bd9Sstevel@tonic-gate return (cl); 1407c478bd9Sstevel@tonic-gate } 1417c478bd9Sstevel@tonic-gate goto err; 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate syserror: 1447c478bd9Sstevel@tonic-gate rpc_createerr.cf_stat = RPC_SYSTEMERROR; 1457c478bd9Sstevel@tonic-gate rpc_createerr.cf_error.re_errno = errno; 1467c478bd9Sstevel@tonic-gate rpc_createerr.cf_error.re_terrno = t_errno; 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate err: if (madefd == TRUE) 1497c478bd9Sstevel@tonic-gate (void) t_close(fd); 1507c478bd9Sstevel@tonic-gate (void) freenetconfigent(nconf); 1517c478bd9Sstevel@tonic-gate if (locked == TRUE) 15261961e0fSrobinson (void) mutex_unlock(&rpcsoc_lock); 15361961e0fSrobinson return (NULL); 1547c478bd9Sstevel@tonic-gate } 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate CLIENT * 15761961e0fSrobinson clntudp_bufcreate(struct sockaddr_in *raddr, rpcprog_t prog, rpcvers_t vers, 15861961e0fSrobinson struct timeval wait, int *sockp, uint_t sendsz, uint_t recvsz) 1597c478bd9Sstevel@tonic-gate { 1607c478bd9Sstevel@tonic-gate CLIENT *cl; 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate cl = clnt_com_create(raddr, prog, vers, sockp, sendsz, recvsz, "udp"); 16361961e0fSrobinson if (cl == NULL) 16461961e0fSrobinson return (NULL); 1657c478bd9Sstevel@tonic-gate (void) CLNT_CONTROL(cl, CLSET_RETRY_TIMEOUT, (char *)&wait); 1667c478bd9Sstevel@tonic-gate return (cl); 1677c478bd9Sstevel@tonic-gate } 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate CLIENT * 17061961e0fSrobinson clntudp_create(struct sockaddr_in *raddr, rpcprog_t program, rpcvers_t version, 17161961e0fSrobinson struct timeval wait, int *sockp) 1727c478bd9Sstevel@tonic-gate { 17361961e0fSrobinson return (clntudp_bufcreate(raddr, program, version, wait, sockp, 17461961e0fSrobinson UDPMSGSIZE, UDPMSGSIZE)); 1757c478bd9Sstevel@tonic-gate } 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate CLIENT * 17861961e0fSrobinson clnttcp_create(struct sockaddr_in *raddr, rpcprog_t prog, rpcvers_t vers, 17961961e0fSrobinson int *sockp, uint_t sendsz, uint_t recvsz) 1807c478bd9Sstevel@tonic-gate { 18161961e0fSrobinson return (clnt_com_create(raddr, prog, vers, sockp, sendsz, 18261961e0fSrobinson recvsz, "tcp")); 1837c478bd9Sstevel@tonic-gate } 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate CLIENT * 18661961e0fSrobinson clntraw_create(rpcprog_t prog, rpcvers_t vers) 1877c478bd9Sstevel@tonic-gate { 18861961e0fSrobinson return (clnt_raw_create(prog, vers)); 1897c478bd9Sstevel@tonic-gate } 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate /* 1927c478bd9Sstevel@tonic-gate * A common server create routine 1937c478bd9Sstevel@tonic-gate */ 1947c478bd9Sstevel@tonic-gate static SVCXPRT * 19561961e0fSrobinson svc_com_create(int fd, uint_t sendsize, uint_t recvsize, char *netid) 1967c478bd9Sstevel@tonic-gate { 1977c478bd9Sstevel@tonic-gate struct netconfig *nconf; 1987c478bd9Sstevel@tonic-gate SVCXPRT *svc; 1997c478bd9Sstevel@tonic-gate int madefd = FALSE; 2007c478bd9Sstevel@tonic-gate int port; 2017c478bd9Sstevel@tonic-gate int res; 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate if ((nconf = __rpc_getconfip(netid)) == NULL) { 2047c478bd9Sstevel@tonic-gate (void) syslog(LOG_ERR, "Could not get %s transport", netid); 20561961e0fSrobinson return (NULL); 2067c478bd9Sstevel@tonic-gate } 2077c478bd9Sstevel@tonic-gate if (fd == RPC_ANYSOCK) { 20861961e0fSrobinson fd = t_open(nconf->nc_device, O_RDWR, NULL); 2097c478bd9Sstevel@tonic-gate if (fd == -1) { 2107c478bd9Sstevel@tonic-gate char errorstr[100]; 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate __tli_sys_strerror(errorstr, sizeof (errorstr), 2137c478bd9Sstevel@tonic-gate t_errno, errno); 2147c478bd9Sstevel@tonic-gate (void) syslog(LOG_ERR, 2157c478bd9Sstevel@tonic-gate "svc%s_create: could not open connection : %s", netid, 2167c478bd9Sstevel@tonic-gate errorstr); 2177c478bd9Sstevel@tonic-gate (void) freenetconfigent(nconf); 21861961e0fSrobinson return (NULL); 2197c478bd9Sstevel@tonic-gate } 2207c478bd9Sstevel@tonic-gate madefd = TRUE; 2217c478bd9Sstevel@tonic-gate } 2227c478bd9Sstevel@tonic-gate 22361961e0fSrobinson res = __rpc_bindresvport(fd, NULL, &port, 8); 22461961e0fSrobinson svc = svc_tli_create(fd, nconf, NULL, 2257c478bd9Sstevel@tonic-gate sendsize, recvsize); 2267c478bd9Sstevel@tonic-gate (void) freenetconfigent(nconf); 22761961e0fSrobinson if (svc == NULL) { 2287c478bd9Sstevel@tonic-gate if (madefd) 2297c478bd9Sstevel@tonic-gate (void) t_close(fd); 23061961e0fSrobinson return (NULL); 2317c478bd9Sstevel@tonic-gate } 23261961e0fSrobinson if (res == -1) 23361961e0fSrobinson /* LINTED pointer cast */ 2347c478bd9Sstevel@tonic-gate port = (((struct sockaddr_in *)svc->xp_ltaddr.buf)->sin_port); 2357c478bd9Sstevel@tonic-gate svc->xp_port = ntohs(port); 2367c478bd9Sstevel@tonic-gate return (svc); 2377c478bd9Sstevel@tonic-gate } 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate SVCXPRT * 24061961e0fSrobinson svctcp_create(int fd, uint_t sendsize, uint_t recvsize) 2417c478bd9Sstevel@tonic-gate { 24261961e0fSrobinson return (svc_com_create(fd, sendsize, recvsize, "tcp")); 2437c478bd9Sstevel@tonic-gate } 2447c478bd9Sstevel@tonic-gate 2457c478bd9Sstevel@tonic-gate SVCXPRT * 24661961e0fSrobinson svcudp_bufcreate(int fd, uint_t sendsz, uint_t recvsz) 2477c478bd9Sstevel@tonic-gate { 24861961e0fSrobinson return (svc_com_create(fd, sendsz, recvsz, "udp")); 2497c478bd9Sstevel@tonic-gate } 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate SVCXPRT * 25261961e0fSrobinson svcfd_create(int fd, uint_t sendsize, uint_t recvsize) 2537c478bd9Sstevel@tonic-gate { 25461961e0fSrobinson return (svc_fd_create(fd, sendsize, recvsize)); 2557c478bd9Sstevel@tonic-gate } 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate SVCXPRT * 25961961e0fSrobinson svcudp_create(int fd) 2607c478bd9Sstevel@tonic-gate { 26161961e0fSrobinson return (svc_com_create(fd, UDPMSGSIZE, UDPMSGSIZE, "udp")); 2627c478bd9Sstevel@tonic-gate } 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate SVCXPRT * 26561961e0fSrobinson svcraw_create(void) 2667c478bd9Sstevel@tonic-gate { 26761961e0fSrobinson return (svc_raw_create()); 2687c478bd9Sstevel@tonic-gate } 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate /* 2717c478bd9Sstevel@tonic-gate * Bind a fd to a privileged IP port. 2727c478bd9Sstevel@tonic-gate * This is slightly different from the code in netdir_options 2737c478bd9Sstevel@tonic-gate * because it has a different interface - main thing is that it 2747c478bd9Sstevel@tonic-gate * needs to know its own address. We also wanted to set the qlen. 2757c478bd9Sstevel@tonic-gate * t_getname() can be used for those purposes and perhaps job can be done. 2767c478bd9Sstevel@tonic-gate */ 2777c478bd9Sstevel@tonic-gate int 2787c478bd9Sstevel@tonic-gate __rpc_bindresvport_ipv6(int fd, struct sockaddr *sin, int *portp, int qlen, 2797c478bd9Sstevel@tonic-gate char *fmly) 2807c478bd9Sstevel@tonic-gate { 2817c478bd9Sstevel@tonic-gate int res; 2827c478bd9Sstevel@tonic-gate static in_port_t port, *sinport; 2837c478bd9Sstevel@tonic-gate struct sockaddr_in6 myaddr; 2847c478bd9Sstevel@tonic-gate int i; 2857c478bd9Sstevel@tonic-gate struct t_bind tbindstr, *tres; 2867c478bd9Sstevel@tonic-gate struct t_info tinfo; 2877c478bd9Sstevel@tonic-gate extern mutex_t portnum_lock; 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate /* VARIABLES PROTECTED BY portnum_lock: port */ 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gate #define STARTPORT 600 2927c478bd9Sstevel@tonic-gate #define ENDPORT (IPPORT_RESERVED - 1) 2937c478bd9Sstevel@tonic-gate #define NPORTS (ENDPORT - STARTPORT + 1) 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate if (sin == 0 && fmly == 0) { 2967c478bd9Sstevel@tonic-gate errno = EINVAL; 2977c478bd9Sstevel@tonic-gate return (-1); 2987c478bd9Sstevel@tonic-gate } 2997c478bd9Sstevel@tonic-gate if (geteuid()) { 3007c478bd9Sstevel@tonic-gate errno = EACCES; 3017c478bd9Sstevel@tonic-gate return (-1); 3027c478bd9Sstevel@tonic-gate } 3037c478bd9Sstevel@tonic-gate if ((i = t_getstate(fd)) != T_UNBND) { 3047c478bd9Sstevel@tonic-gate if (t_errno == TBADF) 3057c478bd9Sstevel@tonic-gate errno = EBADF; 3067c478bd9Sstevel@tonic-gate if (i != -1) 3077c478bd9Sstevel@tonic-gate errno = EISCONN; 3087c478bd9Sstevel@tonic-gate return (-1); 3097c478bd9Sstevel@tonic-gate } 3107c478bd9Sstevel@tonic-gate if (sin == 0) { 3117c478bd9Sstevel@tonic-gate sin = (struct sockaddr *)&myaddr; 3127c478bd9Sstevel@tonic-gate get_myaddress_ipv6(fmly, sin); 3137c478bd9Sstevel@tonic-gate } 3147c478bd9Sstevel@tonic-gate if (sin->sa_family == AF_INET) { 31561961e0fSrobinson /* LINTED pointer cast */ 3167c478bd9Sstevel@tonic-gate sinport = &((struct sockaddr_in *)sin)->sin_port; 3177c478bd9Sstevel@tonic-gate } else if (sin->sa_family == AF_INET6) { 31861961e0fSrobinson /* LINTED pointer cast */ 3197c478bd9Sstevel@tonic-gate sinport = &((struct sockaddr_in6 *)sin)->sin6_port; 3207c478bd9Sstevel@tonic-gate } else { 3217c478bd9Sstevel@tonic-gate errno = EPFNOSUPPORT; 3227c478bd9Sstevel@tonic-gate return (-1); 3237c478bd9Sstevel@tonic-gate } 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate /* Transform sockaddr to netbuf */ 3267c478bd9Sstevel@tonic-gate if (t_getinfo(fd, &tinfo) == -1) { 3277c478bd9Sstevel@tonic-gate return (-1); 3287c478bd9Sstevel@tonic-gate } 32961961e0fSrobinson /* LINTED pointer cast */ 3307c478bd9Sstevel@tonic-gate tres = (struct t_bind *)t_alloc(fd, T_BIND, T_ADDR); 33161961e0fSrobinson if (tres == NULL) 3327c478bd9Sstevel@tonic-gate return (-1); 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate tbindstr.qlen = qlen; 3357c478bd9Sstevel@tonic-gate tbindstr.addr.buf = (char *)sin; 3367c478bd9Sstevel@tonic-gate tbindstr.addr.len = tbindstr.addr.maxlen = __rpc_get_a_size(tinfo.addr); 33761961e0fSrobinson /* LINTED pointer cast */ 3387c478bd9Sstevel@tonic-gate sin = (struct sockaddr *)tbindstr.addr.buf; 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate res = -1; 34161961e0fSrobinson (void) mutex_lock(&portnum_lock); 3427c478bd9Sstevel@tonic-gate if (port == 0) 3437c478bd9Sstevel@tonic-gate port = (getpid() % NPORTS) + STARTPORT; 3447c478bd9Sstevel@tonic-gate for (i = 0; i < NPORTS; i++) { 3457c478bd9Sstevel@tonic-gate *sinport = htons(port++); 3467c478bd9Sstevel@tonic-gate if (port > ENDPORT) 3477c478bd9Sstevel@tonic-gate port = STARTPORT; 3487c478bd9Sstevel@tonic-gate res = t_bind(fd, &tbindstr, tres); 3497c478bd9Sstevel@tonic-gate if (res == 0) { 3507c478bd9Sstevel@tonic-gate if ((tbindstr.addr.len == tres->addr.len) && 3517c478bd9Sstevel@tonic-gate (memcmp(tbindstr.addr.buf, tres->addr.buf, 3527c478bd9Sstevel@tonic-gate (int)tres->addr.len) == 0)) 3537c478bd9Sstevel@tonic-gate break; 3547c478bd9Sstevel@tonic-gate (void) t_unbind(fd); 3557c478bd9Sstevel@tonic-gate res = -1; 3567c478bd9Sstevel@tonic-gate } else if (t_errno != TSYSERR || errno != EADDRINUSE) 3577c478bd9Sstevel@tonic-gate break; 3587c478bd9Sstevel@tonic-gate } 35961961e0fSrobinson (void) mutex_unlock(&portnum_lock); 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate if ((portp != NULL) && (res == 0)) 3627c478bd9Sstevel@tonic-gate *portp = *sinport; 3637c478bd9Sstevel@tonic-gate (void) t_free((char *)tres, T_BIND); 3647c478bd9Sstevel@tonic-gate return (res); 3657c478bd9Sstevel@tonic-gate } 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate int 3687c478bd9Sstevel@tonic-gate __rpc_bindresvport(int fd, struct sockaddr_in *sin, int *portp, int qlen) 3697c478bd9Sstevel@tonic-gate { 3707c478bd9Sstevel@tonic-gate return (__rpc_bindresvport_ipv6(fd, (struct sockaddr *)sin, portp, 3717c478bd9Sstevel@tonic-gate qlen, NC_INET)); 3727c478bd9Sstevel@tonic-gate } 3737c478bd9Sstevel@tonic-gate 3747c478bd9Sstevel@tonic-gate /* 3757c478bd9Sstevel@tonic-gate * Get clients IP address. 3767c478bd9Sstevel@tonic-gate * don't use gethostbyname, which would invoke yellow pages 3777c478bd9Sstevel@tonic-gate * Remains only for backward compatibility reasons. 3787c478bd9Sstevel@tonic-gate * Used mainly by the portmapper so that it can register 3797c478bd9Sstevel@tonic-gate * with itself. Also used by pmap*() routines 3807c478bd9Sstevel@tonic-gate */ 3817c478bd9Sstevel@tonic-gate void 3827c478bd9Sstevel@tonic-gate get_myaddress_ipv6(char *fmly, struct sockaddr *addr) 3837c478bd9Sstevel@tonic-gate { 3847c478bd9Sstevel@tonic-gate if (fmly != 0 && strcmp(fmly, NC_INET6) == 0) { 38561961e0fSrobinson /* LINTED pointer cast */ 3867c478bd9Sstevel@tonic-gate struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr; 38761961e0fSrobinson (void) memset(sin6, 0, sizeof (*sin6)); 3887c478bd9Sstevel@tonic-gate sin6->sin6_family = AF_INET6; 3897c478bd9Sstevel@tonic-gate sin6->sin6_port = htons(PMAPPORT); 3907c478bd9Sstevel@tonic-gate if (__can_use_af(AF_INET6)) { 3917c478bd9Sstevel@tonic-gate /* Local copy of in6addr_any to avoid -lsocket */ 3927c478bd9Sstevel@tonic-gate struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; 3937c478bd9Sstevel@tonic-gate sin6->sin6_addr = in6addr_any; 3947c478bd9Sstevel@tonic-gate } else { 3957c478bd9Sstevel@tonic-gate struct in_addr in4; 3967c478bd9Sstevel@tonic-gate in4.s_addr = INADDR_ANY; 3977c478bd9Sstevel@tonic-gate IN6_INADDR_TO_V4MAPPED(&in4, &sin6->sin6_addr); 3987c478bd9Sstevel@tonic-gate } 3997c478bd9Sstevel@tonic-gate } else { 40061961e0fSrobinson /* LINTED pointer cast */ 4017c478bd9Sstevel@tonic-gate struct sockaddr_in *sin = (struct sockaddr_in *)addr; 40261961e0fSrobinson (void) memset(sin, 0, sizeof (*sin)); 4037c478bd9Sstevel@tonic-gate sin->sin_family = AF_INET; 4047c478bd9Sstevel@tonic-gate sin->sin_port = htons(PMAPPORT); 4057c478bd9Sstevel@tonic-gate sin->sin_addr.s_addr = INADDR_ANY; 4067c478bd9Sstevel@tonic-gate } 4077c478bd9Sstevel@tonic-gate } 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate void 4107c478bd9Sstevel@tonic-gate get_myaddress(struct sockaddr_in *addr) 4117c478bd9Sstevel@tonic-gate { 4127c478bd9Sstevel@tonic-gate get_myaddress_ipv6(0, (struct sockaddr *)addr); 4137c478bd9Sstevel@tonic-gate } 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate /* 4167c478bd9Sstevel@tonic-gate * Get port used by specified service on specified host. 4177c478bd9Sstevel@tonic-gate * Exists for source compatibility only. 4187c478bd9Sstevel@tonic-gate * Obsoleted by rpcb_getaddr(). 4197c478bd9Sstevel@tonic-gate */ 4207c478bd9Sstevel@tonic-gate ushort_t 4217c478bd9Sstevel@tonic-gate getrpcport(char *host, rpcprog_t prognum, rpcvers_t versnum, 4227c478bd9Sstevel@tonic-gate rpcprot_t proto) 4237c478bd9Sstevel@tonic-gate { 4247c478bd9Sstevel@tonic-gate struct sockaddr_in addr; 4257c478bd9Sstevel@tonic-gate struct hostent *hp; 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate if ((hp = gethostbyname(host)) == NULL) 4287c478bd9Sstevel@tonic-gate return (0); 42961961e0fSrobinson (void) memcpy(&addr.sin_addr, hp->h_addr, hp->h_length); 4307c478bd9Sstevel@tonic-gate addr.sin_family = AF_INET; 4317c478bd9Sstevel@tonic-gate addr.sin_port = 0; 4327c478bd9Sstevel@tonic-gate return (pmap_getport(&addr, prognum, versnum, proto)); 4337c478bd9Sstevel@tonic-gate } 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate /* 4367c478bd9Sstevel@tonic-gate * For connectionless "udp" transport. Obsoleted by rpc_call(). 4377c478bd9Sstevel@tonic-gate */ 4387c478bd9Sstevel@tonic-gate int 43961961e0fSrobinson callrpc(char *host, rpcprog_t prognum, rpcvers_t versnum, rpcproc_t procnum, 44061961e0fSrobinson xdrproc_t inproc, char *in, xdrproc_t outproc, char *out) 4417c478bd9Sstevel@tonic-gate { 44261961e0fSrobinson return ((int)rpc_call(host, prognum, versnum, procnum, inproc, 44361961e0fSrobinson in, outproc, out, "udp")); 4447c478bd9Sstevel@tonic-gate } 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate /* 4477c478bd9Sstevel@tonic-gate * For connectionless kind of transport. Obsoleted by rpc_reg() 4487c478bd9Sstevel@tonic-gate */ 4497c478bd9Sstevel@tonic-gate int 45061961e0fSrobinson registerrpc(rpcprog_t prognum, rpcvers_t versnum, rpcproc_t procnum, 45161961e0fSrobinson char *(*progname)(), xdrproc_t inproc, xdrproc_t outproc) 4527c478bd9Sstevel@tonic-gate { 45361961e0fSrobinson return (rpc_reg(prognum, versnum, procnum, progname, inproc, 45461961e0fSrobinson outproc, "udp")); 4557c478bd9Sstevel@tonic-gate } 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate /* 4587c478bd9Sstevel@tonic-gate * All the following clnt_broadcast stuff is convulated; it supports 4597c478bd9Sstevel@tonic-gate * the earlier calling style of the callback function 4607c478bd9Sstevel@tonic-gate */ 461*cb620785Sraf static pthread_key_t clnt_broadcast_key = PTHREAD_ONCE_KEY_NP; 4627c478bd9Sstevel@tonic-gate static resultproc_t clnt_broadcast_result_main; 4637c478bd9Sstevel@tonic-gate 4647c478bd9Sstevel@tonic-gate /* 4657c478bd9Sstevel@tonic-gate * Need to translate the netbuf address into sockaddr_in address. 4667c478bd9Sstevel@tonic-gate * Dont care about netid here. 4677c478bd9Sstevel@tonic-gate */ 46861961e0fSrobinson /* ARGSUSED2 */ 4697c478bd9Sstevel@tonic-gate static bool_t 47061961e0fSrobinson rpc_wrap_bcast(char *resultp, struct netbuf *addr, struct netconfig *nconf) 4717c478bd9Sstevel@tonic-gate { 4727c478bd9Sstevel@tonic-gate resultproc_t clnt_broadcast_result; 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate clnt_broadcast_result = thr_main()? clnt_broadcast_result_main : 4757c478bd9Sstevel@tonic-gate (resultproc_t)pthread_getspecific(clnt_broadcast_key); 47661961e0fSrobinson return ((*clnt_broadcast_result)(resultp, 47761961e0fSrobinson /* LINTED pointer cast */ 47861961e0fSrobinson (struct sockaddr_in *)addr->buf)); 4797c478bd9Sstevel@tonic-gate } 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate /* 4827c478bd9Sstevel@tonic-gate * Broadcasts on UDP transport. Obsoleted by rpc_broadcast(). 4837c478bd9Sstevel@tonic-gate */ 4847c478bd9Sstevel@tonic-gate enum clnt_stat 48561961e0fSrobinson clnt_broadcast(rpcprog_t prog, rpcvers_t vers, rpcproc_t proc, xdrproc_t xargs, 48661961e0fSrobinson caddr_t argsp, xdrproc_t xresults, 48761961e0fSrobinson caddr_t resultsp, resultproc_t eachresult) 4887c478bd9Sstevel@tonic-gate { 48961961e0fSrobinson if (thr_main()) { 4907c478bd9Sstevel@tonic-gate clnt_broadcast_result_main = eachresult; 49161961e0fSrobinson } else { 492*cb620785Sraf (void) pthread_key_create_once_np(&clnt_broadcast_key, NULL); 49361961e0fSrobinson (void) pthread_setspecific(clnt_broadcast_key, 49461961e0fSrobinson (void *)eachresult); 4957c478bd9Sstevel@tonic-gate } 49661961e0fSrobinson return (rpc_broadcast(prog, vers, proc, xargs, argsp, xresults, 49761961e0fSrobinson resultsp, (resultproc_t)rpc_wrap_bcast, "udp")); 4987c478bd9Sstevel@tonic-gate } 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate /* 5017c478bd9Sstevel@tonic-gate * Create the client des authentication object. Obsoleted by 5027c478bd9Sstevel@tonic-gate * authdes_seccreate(). 5037c478bd9Sstevel@tonic-gate */ 5047c478bd9Sstevel@tonic-gate AUTH * 50561961e0fSrobinson authdes_create(char *servername, uint_t window, struct sockaddr_in *syncaddr, 50661961e0fSrobinson des_block *ckey) 5077c478bd9Sstevel@tonic-gate { 5087c478bd9Sstevel@tonic-gate char *hostname = NULL; 5097c478bd9Sstevel@tonic-gate 5107c478bd9Sstevel@tonic-gate if (syncaddr) { 5117c478bd9Sstevel@tonic-gate /* 5127c478bd9Sstevel@tonic-gate * Change addr to hostname, because that is the way 5137c478bd9Sstevel@tonic-gate * new interface takes it. 5147c478bd9Sstevel@tonic-gate */ 5157c478bd9Sstevel@tonic-gate struct netconfig *nconf; 5167c478bd9Sstevel@tonic-gate struct netbuf nb_syncaddr; 5177c478bd9Sstevel@tonic-gate struct nd_hostservlist *hlist; 5187c478bd9Sstevel@tonic-gate AUTH *nauth; 5197c478bd9Sstevel@tonic-gate int fd; 5207c478bd9Sstevel@tonic-gate struct t_info tinfo; 5217c478bd9Sstevel@tonic-gate 5227c478bd9Sstevel@tonic-gate if ((nconf = __rpc_getconfip("udp")) == NULL && 5237c478bd9Sstevel@tonic-gate (nconf = __rpc_getconfip("tcp")) == NULL) 5247c478bd9Sstevel@tonic-gate goto fallback; 5257c478bd9Sstevel@tonic-gate 5267c478bd9Sstevel@tonic-gate /* Transform sockaddr_in to netbuf */ 5277c478bd9Sstevel@tonic-gate if ((fd = t_open(nconf->nc_device, O_RDWR, &tinfo)) == -1) { 5287c478bd9Sstevel@tonic-gate (void) freenetconfigent(nconf); 5297c478bd9Sstevel@tonic-gate goto fallback; 5307c478bd9Sstevel@tonic-gate } 5317c478bd9Sstevel@tonic-gate (void) t_close(fd); 5327c478bd9Sstevel@tonic-gate nb_syncaddr.maxlen = nb_syncaddr.len = 5337c478bd9Sstevel@tonic-gate __rpc_get_a_size(tinfo.addr); 5347c478bd9Sstevel@tonic-gate nb_syncaddr.buf = (char *)syncaddr; 5357c478bd9Sstevel@tonic-gate if (netdir_getbyaddr(nconf, &hlist, &nb_syncaddr)) { 5367c478bd9Sstevel@tonic-gate (void) freenetconfigent(nconf); 5377c478bd9Sstevel@tonic-gate goto fallback; 5387c478bd9Sstevel@tonic-gate } 5397c478bd9Sstevel@tonic-gate if (hlist && hlist->h_cnt > 0 && hlist->h_hostservs) 5407c478bd9Sstevel@tonic-gate hostname = hlist->h_hostservs->h_host; 5417c478bd9Sstevel@tonic-gate nauth = authdes_seccreate(servername, window, hostname, ckey); 5427c478bd9Sstevel@tonic-gate (void) netdir_free((char *)hlist, ND_HOSTSERVLIST); 5437c478bd9Sstevel@tonic-gate (void) freenetconfigent(nconf); 5447c478bd9Sstevel@tonic-gate return (nauth); 5457c478bd9Sstevel@tonic-gate } 5467c478bd9Sstevel@tonic-gate fallback: 54761961e0fSrobinson return (authdes_seccreate(servername, window, hostname, ckey)); 5487c478bd9Sstevel@tonic-gate } 5497c478bd9Sstevel@tonic-gate #endif /* PORTMAP */ 550