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 5dc3879f9Sjarrett * Common Development and Distribution License (the "License"). 6dc3879f9Sjarrett * 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 */ 217c478bd9Sstevel@tonic-gate /* 22dc3879f9Sjarrett * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 277c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate /* 307c478bd9Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 4.3 BSD 317c478bd9Sstevel@tonic-gate * under license from the Regents of the University of California. 327c478bd9Sstevel@tonic-gate */ 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate #include <sys/param.h> 377c478bd9Sstevel@tonic-gate #include <sys/types.h> 387c478bd9Sstevel@tonic-gate #include <rpc/types.h> 397c478bd9Sstevel@tonic-gate #include <netinet/in.h> 407c478bd9Sstevel@tonic-gate #include <rpc/auth.h> 417c478bd9Sstevel@tonic-gate #include <rpc/clnt.h> 427c478bd9Sstevel@tonic-gate #include <sys/tiuser.h> 437c478bd9Sstevel@tonic-gate #include <sys/t_kuser.h> 447c478bd9Sstevel@tonic-gate #include <rpc/svc.h> 457c478bd9Sstevel@tonic-gate #include <rpc/xdr.h> 467c478bd9Sstevel@tonic-gate #include <sys/file.h> 477c478bd9Sstevel@tonic-gate #include <sys/user.h> 487c478bd9Sstevel@tonic-gate #include <sys/proc.h> 497c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 507c478bd9Sstevel@tonic-gate #include <sys/stream.h> 517c478bd9Sstevel@tonic-gate #include <sys/tihdr.h> 527c478bd9Sstevel@tonic-gate #include <sys/fcntl.h> 537c478bd9Sstevel@tonic-gate #include <sys/socket.h> 547c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 557c478bd9Sstevel@tonic-gate #include <sys/errno.h> 567c478bd9Sstevel@tonic-gate #include <sys/cred.h> 577c478bd9Sstevel@tonic-gate #include <sys/systm.h> 587c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate #define NC_INET "inet" 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate #define MAX_PRIV (IPPORT_RESERVED-1) 637c478bd9Sstevel@tonic-gate #define MIN_PRIV (IPPORT_RESERVED/2) 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate ushort_t clnt_udp_last_used = MIN_PRIV; 667c478bd9Sstevel@tonic-gate ushort_t clnt_tcp_last_used = MIN_PRIV; 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate /* 697c478bd9Sstevel@tonic-gate * PSARC 2003/523 Contract Private Interface 707c478bd9Sstevel@tonic-gate * clnt_tli_kcreate 717c478bd9Sstevel@tonic-gate * Changes must be reviewed by Solaris File Sharing 727c478bd9Sstevel@tonic-gate * Changes must be communicated to contract-2003-523@sun.com 737c478bd9Sstevel@tonic-gate */ 747c478bd9Sstevel@tonic-gate int 757c478bd9Sstevel@tonic-gate clnt_tli_kcreate( 767c478bd9Sstevel@tonic-gate struct knetconfig *config, 777c478bd9Sstevel@tonic-gate struct netbuf *svcaddr, /* Servers address */ 787c478bd9Sstevel@tonic-gate rpcprog_t prog, /* Program number */ 797c478bd9Sstevel@tonic-gate rpcvers_t vers, /* Version number */ 807c478bd9Sstevel@tonic-gate uint_t max_msgsize, 817c478bd9Sstevel@tonic-gate int retries, 827c478bd9Sstevel@tonic-gate struct cred *cred, 837c478bd9Sstevel@tonic-gate CLIENT **ncl) 847c478bd9Sstevel@tonic-gate { 857c478bd9Sstevel@tonic-gate CLIENT *cl; /* Client handle */ 867c478bd9Sstevel@tonic-gate int error; 877c478bd9Sstevel@tonic-gate int family = AF_UNSPEC; 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate error = 0; 907c478bd9Sstevel@tonic-gate cl = NULL; 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate RPCLOG(8, "clnt_tli_kcreate: prog %x", prog); 937c478bd9Sstevel@tonic-gate RPCLOG(8, ", vers %d", vers); 947c478bd9Sstevel@tonic-gate RPCLOG(8, ", knc_semantics %d", config->knc_semantics); 957c478bd9Sstevel@tonic-gate RPCLOG(8, ", knc_protofmly %s", config->knc_protofmly); 967c478bd9Sstevel@tonic-gate RPCLOG(8, ", knc_proto %s\n", config->knc_proto); 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate if (config == NULL || config->knc_protofmly == NULL || ncl == NULL) { 997c478bd9Sstevel@tonic-gate RPCLOG0(1, "clnt_tli_kcreate: bad config or handle\n"); 1007c478bd9Sstevel@tonic-gate return (EINVAL); 1017c478bd9Sstevel@tonic-gate } 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate switch (config->knc_semantics) { 1047c478bd9Sstevel@tonic-gate case NC_TPI_CLTS: 1057c478bd9Sstevel@tonic-gate RPCLOG0(8, "clnt_tli_kcreate: CLTS selected\n"); 1067c478bd9Sstevel@tonic-gate error = clnt_clts_kcreate(config, svcaddr, prog, vers, 1077c478bd9Sstevel@tonic-gate retries, cred, &cl); 1087c478bd9Sstevel@tonic-gate if (error != 0) { 1097c478bd9Sstevel@tonic-gate RPCLOG(1, 1107c478bd9Sstevel@tonic-gate "clnt_tli_kcreate: clnt_clts_kcreate failed error %d\n", 1117c478bd9Sstevel@tonic-gate error); 1127c478bd9Sstevel@tonic-gate return (error); 1137c478bd9Sstevel@tonic-gate } 1147c478bd9Sstevel@tonic-gate break; 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate case NC_TPI_COTS: 1177c478bd9Sstevel@tonic-gate case NC_TPI_COTS_ORD: 1187c478bd9Sstevel@tonic-gate RPCLOG0(8, "clnt_tli_kcreate: COTS selected\n"); 1197c478bd9Sstevel@tonic-gate if (strcmp(config->knc_protofmly, NC_INET) == 0) 1207c478bd9Sstevel@tonic-gate family = AF_INET; 1217c478bd9Sstevel@tonic-gate else if (strcmp(config->knc_protofmly, NC_INET6) == 0) 1227c478bd9Sstevel@tonic-gate family = AF_INET6; 1237c478bd9Sstevel@tonic-gate error = clnt_cots_kcreate(config->knc_rdev, svcaddr, family, 1247c478bd9Sstevel@tonic-gate prog, vers, max_msgsize, cred, &cl); 1257c478bd9Sstevel@tonic-gate if (error != 0) { 1267c478bd9Sstevel@tonic-gate RPCLOG(1, 1277c478bd9Sstevel@tonic-gate "clnt_tli_kcreate: clnt_cots_kcreate failed error %d\n", 1287c478bd9Sstevel@tonic-gate error); 1297c478bd9Sstevel@tonic-gate return (error); 1307c478bd9Sstevel@tonic-gate } 1317c478bd9Sstevel@tonic-gate break; 1327c478bd9Sstevel@tonic-gate case NC_TPI_RDMA: 1337c478bd9Sstevel@tonic-gate RPCLOG0(8, "clnt_tli_kcreate: RDMA selected\n"); 134dc3879f9Sjarrett /* 135dc3879f9Sjarrett * RDMA doesn't support TSOL. It's better to 136dc3879f9Sjarrett * disallow it here. 137dc3879f9Sjarrett */ 138dc3879f9Sjarrett if (is_system_labeled()) { 139dc3879f9Sjarrett RPCLOG0(1, "clnt_tli_kcreate: tsol not supported\n"); 140dc3879f9Sjarrett return (EPROTONOSUPPORT); 141dc3879f9Sjarrett } 142dc3879f9Sjarrett 1437c478bd9Sstevel@tonic-gate if (strcmp(config->knc_protofmly, NC_INET) == 0) 1447c478bd9Sstevel@tonic-gate family = AF_INET; 1457c478bd9Sstevel@tonic-gate else if (strcmp(config->knc_protofmly, NC_INET6) == 0) 1467c478bd9Sstevel@tonic-gate family = AF_INET6; 1477c478bd9Sstevel@tonic-gate error = clnt_rdma_kcreate(config->knc_proto, 1487c478bd9Sstevel@tonic-gate (void *)config->knc_rdev, svcaddr, family, prog, vers, cred, 1497c478bd9Sstevel@tonic-gate &cl); 1507c478bd9Sstevel@tonic-gate if (error != 0) { 1517c478bd9Sstevel@tonic-gate RPCLOG(1, 1527c478bd9Sstevel@tonic-gate "clnt_tli_kcreate: clnt_rdma_kcreate failed error %d\n", 1537c478bd9Sstevel@tonic-gate error); 1547c478bd9Sstevel@tonic-gate return (error); 1557c478bd9Sstevel@tonic-gate } 1567c478bd9Sstevel@tonic-gate break; 1577c478bd9Sstevel@tonic-gate default: 1587c478bd9Sstevel@tonic-gate error = EINVAL; 1597c478bd9Sstevel@tonic-gate RPCLOG(1, "clnt_tli_kcreate: Bad service type %d\n", 1607c478bd9Sstevel@tonic-gate config->knc_semantics); 1617c478bd9Sstevel@tonic-gate return (error); 1627c478bd9Sstevel@tonic-gate } 1637c478bd9Sstevel@tonic-gate *ncl = cl; 1647c478bd9Sstevel@tonic-gate return (0); 1657c478bd9Sstevel@tonic-gate } 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate /* 1687c478bd9Sstevel@tonic-gate * "Kinit" a client handle by calling the appropriate cots or clts routine. 1697c478bd9Sstevel@tonic-gate * 1707c478bd9Sstevel@tonic-gate * PSARC 2003/523 Contract Private Interface 1717c478bd9Sstevel@tonic-gate * clnt_tli_kinit 1727c478bd9Sstevel@tonic-gate * Changes must be reviewed by Solaris File Sharing 1737c478bd9Sstevel@tonic-gate * Changes must be communicated to contract-2003-523@sun.com 1747c478bd9Sstevel@tonic-gate */ 1757c478bd9Sstevel@tonic-gate int 1767c478bd9Sstevel@tonic-gate clnt_tli_kinit( 1777c478bd9Sstevel@tonic-gate CLIENT *h, 1787c478bd9Sstevel@tonic-gate struct knetconfig *config, 1797c478bd9Sstevel@tonic-gate struct netbuf *addr, 1807c478bd9Sstevel@tonic-gate uint_t max_msgsize, 1817c478bd9Sstevel@tonic-gate int retries, 1827c478bd9Sstevel@tonic-gate struct cred *cred) 1837c478bd9Sstevel@tonic-gate { 1847c478bd9Sstevel@tonic-gate int error = 0; 1857c478bd9Sstevel@tonic-gate int family = AF_UNSPEC; 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate switch (config->knc_semantics) { 1887c478bd9Sstevel@tonic-gate case NC_TPI_CLTS: 1897c478bd9Sstevel@tonic-gate clnt_clts_kinit(h, addr, retries, cred); 1907c478bd9Sstevel@tonic-gate break; 1917c478bd9Sstevel@tonic-gate case NC_TPI_COTS: 1927c478bd9Sstevel@tonic-gate case NC_TPI_COTS_ORD: 1937c478bd9Sstevel@tonic-gate RPCLOG0(2, "clnt_tli_kinit: COTS selected\n"); 1947c478bd9Sstevel@tonic-gate if (strcmp(config->knc_protofmly, NC_INET) == 0) 1957c478bd9Sstevel@tonic-gate family = AF_INET; 1967c478bd9Sstevel@tonic-gate else if (strcmp(config->knc_protofmly, NC_INET6) == 0) 1977c478bd9Sstevel@tonic-gate family = AF_INET6; 1987c478bd9Sstevel@tonic-gate clnt_cots_kinit(h, config->knc_rdev, family, 1997c478bd9Sstevel@tonic-gate addr, max_msgsize, cred); 2007c478bd9Sstevel@tonic-gate break; 2017c478bd9Sstevel@tonic-gate case NC_TPI_RDMA: 2027c478bd9Sstevel@tonic-gate RPCLOG0(2, "clnt_tli_kinit: RDMA selected\n"); 2037c478bd9Sstevel@tonic-gate clnt_rdma_kinit(h, config->knc_proto, 2047c478bd9Sstevel@tonic-gate (void *)config->knc_rdev, addr, cred); 2057c478bd9Sstevel@tonic-gate break; 2067c478bd9Sstevel@tonic-gate default: 2077c478bd9Sstevel@tonic-gate error = EINVAL; 2087c478bd9Sstevel@tonic-gate } 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate return (error); 2117c478bd9Sstevel@tonic-gate } 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate /* 2157c478bd9Sstevel@tonic-gate * try to bind to a reserved port 2167c478bd9Sstevel@tonic-gate */ 2177c478bd9Sstevel@tonic-gate int 2187c478bd9Sstevel@tonic-gate bindresvport( 2197c478bd9Sstevel@tonic-gate TIUSER *tiptr, 2207c478bd9Sstevel@tonic-gate struct netbuf *addr, 2217c478bd9Sstevel@tonic-gate struct netbuf *bound_addr, 2227c478bd9Sstevel@tonic-gate bool_t tcp) 2237c478bd9Sstevel@tonic-gate { 2247c478bd9Sstevel@tonic-gate struct sockaddr_in *sin; 2257c478bd9Sstevel@tonic-gate struct sockaddr_in6 *sin6; 2267c478bd9Sstevel@tonic-gate bool_t ipv6_flag = 0; 2277c478bd9Sstevel@tonic-gate int i; 2287c478bd9Sstevel@tonic-gate struct t_bind *req; 2297c478bd9Sstevel@tonic-gate struct t_bind *ret; 2307c478bd9Sstevel@tonic-gate int error; 2317c478bd9Sstevel@tonic-gate bool_t loop_twice; 2327c478bd9Sstevel@tonic-gate int start; 2337c478bd9Sstevel@tonic-gate int stop; 2347c478bd9Sstevel@tonic-gate ushort_t *last_used; 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate if ((error = t_kalloc(tiptr, T_BIND, T_ADDR, (char **)&req)) != 0) { 2377c478bd9Sstevel@tonic-gate RPCLOG(1, "bindresvport: t_kalloc %d\n", error); 2387c478bd9Sstevel@tonic-gate return (error); 2397c478bd9Sstevel@tonic-gate } 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate if ((error = t_kalloc(tiptr, T_BIND, T_ADDR, (char **)&ret)) != 0) { 2427c478bd9Sstevel@tonic-gate RPCLOG(1, "bindresvport: t_kalloc %d\n", error); 2437c478bd9Sstevel@tonic-gate (void) t_kfree(tiptr, (char *)req, T_BIND); 2447c478bd9Sstevel@tonic-gate return (error); 2457c478bd9Sstevel@tonic-gate } 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate /* now separate IPv4 and IPv6 by looking at len of tiptr.addr */ 2487c478bd9Sstevel@tonic-gate if (tiptr->tp_info.addr == sizeof (struct sockaddr_in6)) { 2497c478bd9Sstevel@tonic-gate /* it's IPv6 */ 2507c478bd9Sstevel@tonic-gate ipv6_flag = 1; 2517c478bd9Sstevel@tonic-gate sin6 = (struct sockaddr_in6 *)req->addr.buf; 2527c478bd9Sstevel@tonic-gate sin6->sin6_family = AF_INET6; 2537c478bd9Sstevel@tonic-gate bzero((char *)&sin6->sin6_addr, sizeof (struct in6_addr)); 2547c478bd9Sstevel@tonic-gate req->addr.len = sizeof (struct sockaddr_in6); 2557c478bd9Sstevel@tonic-gate } else { 2567c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */ 2577c478bd9Sstevel@tonic-gate sin = (struct sockaddr_in *)req->addr.buf; 2587c478bd9Sstevel@tonic-gate sin->sin_family = AF_INET; 2597c478bd9Sstevel@tonic-gate sin->sin_addr.s_addr = INADDR_ANY; 2607c478bd9Sstevel@tonic-gate req->addr.len = sizeof (struct sockaddr_in); 2617c478bd9Sstevel@tonic-gate } 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate /* 2647c478bd9Sstevel@tonic-gate * Caller wants to bind to a specific port, so don't bother with the 2657c478bd9Sstevel@tonic-gate * loop that binds to the next free one. 2667c478bd9Sstevel@tonic-gate */ 2677c478bd9Sstevel@tonic-gate if (addr) { 2687c478bd9Sstevel@tonic-gate if (ipv6_flag) { 2697c478bd9Sstevel@tonic-gate sin6->sin6_port = 2707c478bd9Sstevel@tonic-gate ((struct sockaddr_in6 *)addr->buf)->sin6_port; 2717c478bd9Sstevel@tonic-gate } else { 2727c478bd9Sstevel@tonic-gate sin->sin_port = 2737c478bd9Sstevel@tonic-gate ((struct sockaddr_in *)addr->buf)->sin_port; 2747c478bd9Sstevel@tonic-gate } 2757c478bd9Sstevel@tonic-gate RPCLOG(8, "bindresvport: calling t_kbind tiptr = %p\n", 2767c478bd9Sstevel@tonic-gate (void *)tiptr); 2777c478bd9Sstevel@tonic-gate if ((error = t_kbind(tiptr, req, ret)) != 0) { 2787c478bd9Sstevel@tonic-gate RPCLOG(1, "bindresvport: t_kbind: %d\n", error); 2797c478bd9Sstevel@tonic-gate /* 2807c478bd9Sstevel@tonic-gate * The unbind is called in case the bind failed 2817c478bd9Sstevel@tonic-gate * with an EINTR potentially leaving the 2827c478bd9Sstevel@tonic-gate * transport in bound state. 2837c478bd9Sstevel@tonic-gate */ 2847c478bd9Sstevel@tonic-gate if (error == EINTR) 2857c478bd9Sstevel@tonic-gate (void) t_kunbind(tiptr); 2867c478bd9Sstevel@tonic-gate } else if (bcmp(req->addr.buf, ret->addr.buf, 2877c478bd9Sstevel@tonic-gate ret->addr.len) != 0) { 2887c478bd9Sstevel@tonic-gate RPCLOG0(1, "bindresvport: bcmp error\n"); 2897c478bd9Sstevel@tonic-gate (void) t_kunbind(tiptr); 2907c478bd9Sstevel@tonic-gate error = EADDRINUSE; 2917c478bd9Sstevel@tonic-gate } 2927c478bd9Sstevel@tonic-gate } else { 2937c478bd9Sstevel@tonic-gate if (tcp) 2947c478bd9Sstevel@tonic-gate last_used = &clnt_tcp_last_used; 2957c478bd9Sstevel@tonic-gate else 2967c478bd9Sstevel@tonic-gate last_used = &clnt_udp_last_used; 2977c478bd9Sstevel@tonic-gate error = EADDRINUSE; 2987c478bd9Sstevel@tonic-gate stop = MIN_PRIV; 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate start = (*last_used == MIN_PRIV ? MAX_PRIV : *last_used - 1); 3017c478bd9Sstevel@tonic-gate loop_twice = (start < MAX_PRIV ? TRUE : FALSE); 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate bindresvport_again: 3047c478bd9Sstevel@tonic-gate for (i = start; 3057c478bd9Sstevel@tonic-gate (error == EADDRINUSE || error == EADDRNOTAVAIL) && 3067c478bd9Sstevel@tonic-gate i >= stop; i--) { 3077c478bd9Sstevel@tonic-gate if (ipv6_flag) 3087c478bd9Sstevel@tonic-gate sin6->sin6_port = htons(i); 3097c478bd9Sstevel@tonic-gate else 3107c478bd9Sstevel@tonic-gate sin->sin_port = htons(i); 3117c478bd9Sstevel@tonic-gate RPCLOG(8, "bindresvport: calling t_kbind tiptr = 0%p\n", 3127c478bd9Sstevel@tonic-gate (void *)tiptr); 3137c478bd9Sstevel@tonic-gate if ((error = t_kbind(tiptr, req, ret)) != 0) { 3147c478bd9Sstevel@tonic-gate RPCLOG(1, "bindresvport: t_kbind: %d\n", error); 3157c478bd9Sstevel@tonic-gate /* 3167c478bd9Sstevel@tonic-gate * The unbind is called in case the bind failed 3177c478bd9Sstevel@tonic-gate * with an EINTR potentially leaving the 3187c478bd9Sstevel@tonic-gate * transport in bound state. 3197c478bd9Sstevel@tonic-gate */ 3207c478bd9Sstevel@tonic-gate if (error == EINTR) 3217c478bd9Sstevel@tonic-gate (void) t_kunbind(tiptr); 3227c478bd9Sstevel@tonic-gate } else if (bcmp(req->addr.buf, ret->addr.buf, 3237c478bd9Sstevel@tonic-gate ret->addr.len) != 0) { 3247c478bd9Sstevel@tonic-gate RPCLOG0(1, "bindresvport: bcmp error\n"); 3257c478bd9Sstevel@tonic-gate (void) t_kunbind(tiptr); 3267c478bd9Sstevel@tonic-gate error = EADDRINUSE; 3277c478bd9Sstevel@tonic-gate } else 3287c478bd9Sstevel@tonic-gate error = 0; 3297c478bd9Sstevel@tonic-gate } 3307c478bd9Sstevel@tonic-gate if (!error) { 3317c478bd9Sstevel@tonic-gate if (ipv6_flag) { 3327c478bd9Sstevel@tonic-gate RPCLOG(8, "bindresvport: port assigned %d\n", 3337c478bd9Sstevel@tonic-gate sin6->sin6_port); 3347c478bd9Sstevel@tonic-gate *last_used = ntohs(sin6->sin6_port); 3357c478bd9Sstevel@tonic-gate } else { 3367c478bd9Sstevel@tonic-gate RPCLOG(8, "bindresvport: port assigned %d\n", 3377c478bd9Sstevel@tonic-gate sin->sin_port); 3387c478bd9Sstevel@tonic-gate *last_used = ntohs(sin->sin_port); 3397c478bd9Sstevel@tonic-gate } 3407c478bd9Sstevel@tonic-gate } else if (loop_twice) { 3417c478bd9Sstevel@tonic-gate loop_twice = FALSE; 3427c478bd9Sstevel@tonic-gate start = MAX_PRIV; 3437c478bd9Sstevel@tonic-gate stop = *last_used + 1; 3447c478bd9Sstevel@tonic-gate goto bindresvport_again; 3457c478bd9Sstevel@tonic-gate } 3467c478bd9Sstevel@tonic-gate } 3477c478bd9Sstevel@tonic-gate 3487c478bd9Sstevel@tonic-gate if (!error && bound_addr) { 349*9acbbeafSnn35248 if (bound_addr->maxlen < ret->addr.len) { 350*9acbbeafSnn35248 kmem_free(bound_addr->buf, bound_addr->maxlen); 351*9acbbeafSnn35248 bound_addr->buf = kmem_zalloc(ret->addr.len, KM_SLEEP); 352*9acbbeafSnn35248 bound_addr->maxlen = ret->addr.len; 353*9acbbeafSnn35248 } 3547c478bd9Sstevel@tonic-gate bcopy(ret->addr.buf, bound_addr->buf, ret->addr.len); 3557c478bd9Sstevel@tonic-gate bound_addr->len = ret->addr.len; 3567c478bd9Sstevel@tonic-gate } 3577c478bd9Sstevel@tonic-gate (void) t_kfree(tiptr, (char *)req, T_BIND); 3587c478bd9Sstevel@tonic-gate (void) t_kfree(tiptr, (char *)ret, T_BIND); 3597c478bd9Sstevel@tonic-gate return (error); 3607c478bd9Sstevel@tonic-gate } 3617c478bd9Sstevel@tonic-gate 3627c478bd9Sstevel@tonic-gate void 3637c478bd9Sstevel@tonic-gate clnt_init(void) 3647c478bd9Sstevel@tonic-gate { 3657c478bd9Sstevel@tonic-gate clnt_cots_init(); 3667c478bd9Sstevel@tonic-gate clnt_clts_init(); 3677c478bd9Sstevel@tonic-gate } 3687c478bd9Sstevel@tonic-gate 3697c478bd9Sstevel@tonic-gate void 3707c478bd9Sstevel@tonic-gate clnt_fini(void) 3717c478bd9Sstevel@tonic-gate { 3727c478bd9Sstevel@tonic-gate clnt_clts_fini(); 3737c478bd9Sstevel@tonic-gate clnt_cots_fini(); 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate 3767c478bd9Sstevel@tonic-gate call_table_t * 3777c478bd9Sstevel@tonic-gate call_table_init(int size) 3787c478bd9Sstevel@tonic-gate { 3797c478bd9Sstevel@tonic-gate call_table_t *ctp; 3807c478bd9Sstevel@tonic-gate int i; 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate ctp = kmem_alloc(sizeof (call_table_t) * size, KM_SLEEP); 3837c478bd9Sstevel@tonic-gate 3847c478bd9Sstevel@tonic-gate for (i = 0; i < size; i++) { 3857c478bd9Sstevel@tonic-gate ctp[i].ct_call_next = (calllist_t *)&ctp[i]; 3867c478bd9Sstevel@tonic-gate ctp[i].ct_call_prev = (calllist_t *)&ctp[i]; 3877c478bd9Sstevel@tonic-gate mutex_init(&ctp[i].ct_lock, NULL, MUTEX_DEFAULT, NULL); 3887c478bd9Sstevel@tonic-gate ctp[i].ct_len = 0; 3897c478bd9Sstevel@tonic-gate } 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate return (ctp); 3927c478bd9Sstevel@tonic-gate } 393