4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
30 * Portions of this source code were derived from Berkeley 4.3 BSD
31 * under license from the Regents of the University of California.
34 #include <sys/param.h>
35 #include <sys/types.h>
36 #include <rpc/types.h>
37 #include <netinet/in.h>
40 #include <sys/tiuser.h>
41 #include <sys/t_kuser.h>
47 #include <sys/vnode.h>
48 #include <sys/stream.h>
49 #include <sys/tihdr.h>
50 #include <sys/fcntl.h>
51 #include <sys/socket.h>
52 #include <sys/sysmacros.h>
53 #include <sys/errno.h>
55 #include <sys/systm.h>
56 #include <sys/cmn_err.h>
58 #define NC_INET "inet"
60 #define MAX_PRIV (IPPORT_RESERVED-1)
61 #define MIN_PRIV (IPPORT_RESERVED/2)
63 ushort_t clnt_udp_last_used
= MIN_PRIV
;
64 ushort_t clnt_tcp_last_used
= MIN_PRIV
;
67 * PSARC 2003/523 Contract Private Interface
69 * Changes must be reviewed by Solaris File Sharing
70 * Changes must be communicated to contract-2003-523@sun.com
74 struct knetconfig
*config
,
75 struct netbuf
*svcaddr
, /* Servers address */
76 rpcprog_t prog
, /* Program number */
77 rpcvers_t vers
, /* Version number */
83 CLIENT
*cl
; /* Client handle */
85 int family
= AF_UNSPEC
;
90 RPCLOG(8, "clnt_tli_kcreate: prog %x", prog
);
91 RPCLOG(8, ", vers %d", vers
);
92 RPCLOG(8, ", knc_semantics %d", config
->knc_semantics
);
93 RPCLOG(8, ", knc_protofmly %s", config
->knc_protofmly
);
94 RPCLOG(8, ", knc_proto %s\n", config
->knc_proto
);
96 if (config
== NULL
|| config
->knc_protofmly
== NULL
|| ncl
== NULL
) {
97 RPCLOG0(1, "clnt_tli_kcreate: bad config or handle\n");
101 switch (config
->knc_semantics
) {
103 RPCLOG0(8, "clnt_tli_kcreate: CLTS selected\n");
104 error
= clnt_clts_kcreate(config
, svcaddr
, prog
, vers
,
108 "clnt_tli_kcreate: clnt_clts_kcreate failed error %d\n",
115 case NC_TPI_COTS_ORD
:
116 RPCLOG0(8, "clnt_tli_kcreate: COTS selected\n");
117 if (strcmp(config
->knc_protofmly
, NC_INET
) == 0)
119 else if (strcmp(config
->knc_protofmly
, NC_INET6
) == 0)
121 error
= clnt_cots_kcreate(config
->knc_rdev
, svcaddr
, family
,
122 prog
, vers
, max_msgsize
, cred
, &cl
);
125 "clnt_tli_kcreate: clnt_cots_kcreate failed error %d\n",
131 RPCLOG0(8, "clnt_tli_kcreate: RDMA selected\n");
133 if (strcmp(config
->knc_protofmly
, NC_INET
) == 0)
135 else if (strcmp(config
->knc_protofmly
, NC_INET6
) == 0)
137 error
= clnt_rdma_kcreate(config
->knc_proto
,
138 (void *)config
->knc_rdev
, svcaddr
, family
, prog
, vers
, cred
,
142 "clnt_tli_kcreate: clnt_rdma_kcreate failed error %d\n",
149 RPCLOG(1, "clnt_tli_kcreate: Bad service type %d\n",
150 config
->knc_semantics
);
158 * "Kinit" a client handle by calling the appropriate cots or clts routine.
160 * PSARC 2003/523 Contract Private Interface
162 * Changes must be reviewed by Solaris File Sharing
163 * Changes must be communicated to contract-2003-523@sun.com
168 struct knetconfig
*config
,
175 int family
= AF_UNSPEC
;
177 switch (config
->knc_semantics
) {
179 clnt_clts_kinit(h
, addr
, retries
, cred
);
182 case NC_TPI_COTS_ORD
:
183 RPCLOG0(2, "clnt_tli_kinit: COTS selected\n");
184 if (strcmp(config
->knc_protofmly
, NC_INET
) == 0)
186 else if (strcmp(config
->knc_protofmly
, NC_INET6
) == 0)
188 clnt_cots_kinit(h
, config
->knc_rdev
, family
,
189 addr
, max_msgsize
, cred
);
192 RPCLOG0(2, "clnt_tli_kinit: RDMA selected\n");
193 clnt_rdma_kinit(h
, config
->knc_proto
,
194 (void *)config
->knc_rdev
, addr
, cred
);
205 * try to bind to a reserved port
211 struct netbuf
*bound_addr
,
214 struct sockaddr_in
*sin
;
215 struct sockaddr_in6
*sin6
;
216 bool_t ipv6_flag
= 0;
226 if ((error
= t_kalloc(tiptr
, T_BIND
, T_ADDR
, (char **)&req
)) != 0) {
227 RPCLOG(1, "bindresvport: t_kalloc %d\n", error
);
231 if ((error
= t_kalloc(tiptr
, T_BIND
, T_ADDR
, (char **)&ret
)) != 0) {
232 RPCLOG(1, "bindresvport: t_kalloc %d\n", error
);
233 (void) t_kfree(tiptr
, (char *)req
, T_BIND
);
237 /* now separate IPv4 and IPv6 by looking at len of tiptr.addr */
238 if (tiptr
->tp_info
.addr
== sizeof (struct sockaddr_in6
)) {
241 sin6
= (struct sockaddr_in6
*)req
->addr
.buf
;
242 sin6
->sin6_family
= AF_INET6
;
243 bzero((char *)&sin6
->sin6_addr
, sizeof (struct in6_addr
));
244 req
->addr
.len
= sizeof (struct sockaddr_in6
);
246 /* LINTED pointer alignment */
247 sin
= (struct sockaddr_in
*)req
->addr
.buf
;
248 sin
->sin_family
= AF_INET
;
249 sin
->sin_addr
.s_addr
= INADDR_ANY
;
250 req
->addr
.len
= sizeof (struct sockaddr_in
);
254 * Caller wants to bind to a specific port, so don't bother with the
255 * loop that binds to the next free one.
260 ((struct sockaddr_in6
*)addr
->buf
)->sin6_port
;
263 ((struct sockaddr_in
*)addr
->buf
)->sin_port
;
265 RPCLOG(8, "bindresvport: calling t_kbind tiptr = %p\n",
267 if ((error
= t_kbind(tiptr
, req
, ret
)) != 0) {
268 RPCLOG(1, "bindresvport: t_kbind: %d\n", error
);
270 * The unbind is called in case the bind failed
271 * with an EINTR potentially leaving the
272 * transport in bound state.
275 (void) t_kunbind(tiptr
);
276 } else if (bcmp(req
->addr
.buf
, ret
->addr
.buf
,
277 ret
->addr
.len
) != 0) {
278 RPCLOG0(1, "bindresvport: bcmp error\n");
279 (void) t_kunbind(tiptr
);
284 last_used
= &clnt_tcp_last_used
;
286 last_used
= &clnt_udp_last_used
;
290 start
= (*last_used
== MIN_PRIV
? MAX_PRIV
: *last_used
- 1);
291 loop_twice
= (start
< MAX_PRIV
? TRUE
: FALSE
);
295 (error
== EADDRINUSE
|| error
== EADDRNOTAVAIL
) &&
298 sin6
->sin6_port
= htons(i
);
300 sin
->sin_port
= htons(i
);
301 RPCLOG(8, "bindresvport: calling t_kbind tiptr = 0%p\n",
303 if ((error
= t_kbind(tiptr
, req
, ret
)) != 0) {
304 RPCLOG(1, "bindresvport: t_kbind: %d\n", error
);
306 * The unbind is called in case the bind failed
307 * with an EINTR potentially leaving the
308 * transport in bound state.
311 (void) t_kunbind(tiptr
);
312 } else if (bcmp(req
->addr
.buf
, ret
->addr
.buf
,
313 ret
->addr
.len
) != 0) {
314 RPCLOG0(1, "bindresvport: bcmp error\n");
315 (void) t_kunbind(tiptr
);
322 RPCLOG(8, "bindresvport: port assigned %d\n",
324 *last_used
= ntohs(sin6
->sin6_port
);
326 RPCLOG(8, "bindresvport: port assigned %d\n",
328 *last_used
= ntohs(sin
->sin_port
);
330 } else if (loop_twice
) {
333 stop
= *last_used
+ 1;
334 goto bindresvport_again
;
338 if (!error
&& bound_addr
) {
339 if (bound_addr
->maxlen
< ret
->addr
.len
) {
340 kmem_free(bound_addr
->buf
, bound_addr
->maxlen
);
341 bound_addr
->buf
= kmem_zalloc(ret
->addr
.len
, KM_SLEEP
);
342 bound_addr
->maxlen
= ret
->addr
.len
;
344 bcopy(ret
->addr
.buf
, bound_addr
->buf
, ret
->addr
.len
);
345 bound_addr
->len
= ret
->addr
.len
;
347 (void) t_kfree(tiptr
, (char *)req
, T_BIND
);
348 (void) t_kfree(tiptr
, (char *)ret
, T_BIND
);
367 call_table_init(int size
)
372 ctp
= kmem_alloc(sizeof (call_table_t
) * size
, KM_SLEEP
);
374 for (i
= 0; i
< size
; i
++) {
375 ctp
[i
].ct_call_next
= (calllist_t
*)&ctp
[i
];
376 ctp
[i
].ct_call_prev
= (calllist_t
*)&ctp
[i
];
377 mutex_init(&ctp
[i
].ct_lock
, NULL
, MUTEX_DEFAULT
, NULL
);