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]
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
30 * Portions of this source code were derived from Berkeley
31 * 4.3 BSD under license from the Regents of the University of
37 * Miscl routines for RPC.
43 #include <sys/types.h>
45 #include <rpc/nettype.h>
46 #include <sys/param.h>
47 #include <sys/mkdev.h>
51 #include <sys/resource.h>
52 #include <netconfig.h>
56 #include <sys/systeminfo.h>
61 NCONF_HANDLE
*nhandle
;
62 int nflag
; /* Whether NETPATH or NETCONFIG */
70 "netpath", _RPC_NETPATH
,
71 "visible", _RPC_VISIBLE
,
72 "circuit_v", _RPC_CIRCUIT_V
,
73 "datagram_v", _RPC_DATAGRAM_V
,
74 "circuit_n", _RPC_CIRCUIT_N
,
75 "datagram_n", _RPC_DATAGRAM_N
,
80 "door_local", _RPC_DOOR_LOCAL
,
81 "door_netpath", _RPC_DOOR_NETPATH
,
86 * Cache the result of getrlimit(), so we don't have to do an
87 * expensive call every time. Since many old programs assume
88 * it will not return more than 1024 and use svc_fdset, return
89 * maximum of FD_SETSIZE.
99 if (getrlimit(RLIMIT_NOFILE
, &rl
) == 0) {
100 tbsize
= rl
.rlim_max
;
102 * backward compatibility; too many places
103 * this function is called assuming it returns
106 if (tbsize
> FD_SETSIZE
)
111 * Something wrong. I'll try to save face by returning a
112 * pessimistic number.
118 * Find the appropriate buffer size
122 t_scalar_t size
, /* Size requested */
123 t_scalar_t bufsize
) /* Supported by the transport */
125 if (bufsize
== -2) /* transfer of data unsupported */
128 if ((bufsize
== -1) || (bufsize
== 0)) {
130 * bufsize == -1 : No limit on the size
131 * bufsize == 0 : Concept of tsdu foreign. Choose
134 return ((uint_t
)RPC_MAXDATASIZE
);
136 return ((uint_t
)bufsize
);
138 if ((bufsize
== -1) || (bufsize
== 0))
139 return ((uint_t
)size
);
140 /* Check whether the value is within the upper max limit */
141 return (size
> bufsize
? (uint_t
)bufsize
: (uint_t
)size
);
145 * Find the appropriate address buffer size
149 t_scalar_t size
) /* normally tinfo.addr */
152 return ((uint_t
)size
);
156 * (size == -1) No limit on the size. we impose a limit here.
158 return ((uint_t
)RPC_MAXADDRSIZE
);
162 * Returns the type of the network as defined in <rpc/nettype.h>
163 * If nettype is NULL, it defaults to NETPATH.
166 getnettype(const char *nettype
)
170 if ((nettype
== NULL
) || (nettype
[0] == '\0'))
171 return (_RPC_NETPATH
); /* Default */
173 for (i
= 0; _rpctypelist
[i
].name
; i
++)
174 if (strcasecmp(nettype
, _rpctypelist
[i
].name
) == 0)
175 return (_rpctypelist
[i
].type
);
176 return (_rpctypelist
[i
].type
);
180 * For the given nettype (tcp or udp only), return the first structure found.
181 * This should be freed by calling freenetconfigent()
184 __rpc_getconfip(char *nettype
)
189 static char *netid_tcp_main
= NULL
;
190 static char *netid_udp_main
= NULL
;
191 static pthread_key_t tcp_key
= PTHREAD_ONCE_KEY_NP
;
192 static pthread_key_t udp_key
= PTHREAD_ONCE_KEY_NP
;
195 if ((main_thread
= thr_main())) {
196 netid_udp
= netid_udp_main
;
197 netid_tcp
= netid_tcp_main
;
199 (void) pthread_key_create_once_np(&tcp_key
, free
);
200 netid_tcp
= pthread_getspecific(tcp_key
);
201 (void) pthread_key_create_once_np(&udp_key
, free
);
202 netid_udp
= pthread_getspecific(udp_key
);
204 if (!netid_udp
&& !netid_tcp
) {
205 struct netconfig
*nconf
;
208 if (!(confighandle
= setnetconfig()))
210 while (nconf
= getnetconfig(confighandle
)) {
211 if (strcmp(nconf
->nc_protofmly
, NC_INET
) == 0) {
212 if (strcmp(nconf
->nc_proto
, NC_TCP
) == 0) {
213 netid_tcp
= strdup(nconf
->nc_netid
);
214 if (netid_tcp
== NULL
) {
221 netid_tcp_main
= netid_tcp
;
223 (void) pthread_setspecific(
227 if (strcmp(nconf
->nc_proto
, NC_UDP
) == 0) {
228 netid_udp
= strdup(nconf
->nc_netid
);
229 if (netid_udp
== NULL
) {
236 netid_udp_main
= netid_udp
;
238 (void) pthread_setspecific(
244 (void) endnetconfig(confighandle
);
246 if (strcmp(nettype
, "udp") == 0)
248 else if (strcmp(nettype
, "tcp") == 0)
252 if ((netid
== NULL
) || (netid
[0] == '\0'))
254 return (getnetconfigent(netid
));
259 * Returns the type of the nettype, which should then be used with
263 __rpc_setconf(char *nettype
)
265 struct handle
*handle
;
267 handle
= malloc(sizeof (struct handle
));
270 switch (handle
->nettype
= getnettype(nettype
)) {
271 case _RPC_DOOR_NETPATH
:
274 case _RPC_DATAGRAM_N
:
275 if (!(handle
->nhandle
= setnetpath())) {
279 handle
->nflag
= TRUE
;
283 case _RPC_DATAGRAM_V
:
287 case _RPC_DOOR_LOCAL
:
288 if (!(handle
->nhandle
= setnetconfig())) {
292 handle
->nflag
= FALSE
;
303 * Returns the next netconfig struct for the given "net" type.
304 * __rpc_setconf() should have been called previously.
307 __rpc_getconf(void *vhandle
)
309 struct handle
*handle
;
310 struct netconfig
*nconf
;
312 handle
= (struct handle
*)vhandle
;
317 nconf
= getnetpath(handle
->nhandle
);
319 nconf
= getnetconfig(handle
->nhandle
);
322 if ((nconf
->nc_semantics
!= NC_TPI_CLTS
) &&
323 (nconf
->nc_semantics
!= NC_TPI_COTS
) &&
324 (nconf
->nc_semantics
!= NC_TPI_COTS_ORD
))
326 switch (handle
->nettype
) {
328 if (!(nconf
->nc_flag
& NC_VISIBLE
))
331 case _RPC_DOOR_NETPATH
:
333 case _RPC_NETPATH
: /* Be happy */
336 if (!(nconf
->nc_flag
& NC_VISIBLE
))
340 if ((nconf
->nc_semantics
!= NC_TPI_COTS
) &&
341 (nconf
->nc_semantics
!= NC_TPI_COTS_ORD
))
344 case _RPC_DATAGRAM_V
:
345 if (!(nconf
->nc_flag
& NC_VISIBLE
))
348 case _RPC_DATAGRAM_N
:
349 if (nconf
->nc_semantics
!= NC_TPI_CLTS
)
353 if (((nconf
->nc_semantics
!= NC_TPI_COTS
) &&
354 (nconf
->nc_semantics
!= NC_TPI_COTS_ORD
)) ||
355 (strcmp(nconf
->nc_protofmly
, NC_INET
) &&
356 strcmp(nconf
->nc_protofmly
, NC_INET6
)) ||
357 strcmp(nconf
->nc_proto
, NC_TCP
))
361 if ((nconf
->nc_semantics
!= NC_TPI_CLTS
) ||
362 (strcmp(nconf
->nc_protofmly
, NC_INET
) &&
363 strcmp(nconf
->nc_protofmly
, NC_INET6
)) ||
364 strcmp(nconf
->nc_proto
, NC_UDP
))
368 case _RPC_DOOR_LOCAL
:
369 if (!(nconf
->nc_flag
& NC_VISIBLE
))
371 if (strcmp(nconf
->nc_protofmly
, NC_LOOPBACK
))
381 __rpc_endconf(void *vhandle
)
383 struct handle
*handle
;
385 handle
= (struct handle
*)vhandle
;
389 (void) endnetpath(handle
->nhandle
);
391 (void) endnetconfig(handle
->nhandle
);
397 * Used to ping the NULL procedure for clnt handle.
398 * Returns NULL if fails, else a non-NULL pointer.
401 rpc_nullproc(CLIENT
*clnt
)
403 struct timeval TIMEOUT
= {25, 0};
405 if (clnt_call(clnt
, NULLPROC
, (xdrproc_t
)xdr_void
, NULL
,
406 (xdrproc_t
)xdr_void
, NULL
, TIMEOUT
) != RPC_SUCCESS
)
408 return ((void *)clnt
);
412 * Given a fd, find the transport device it is using and return the
413 * netconf entry corresponding to it.
414 * Note: It assumes servtpe parameter is 0 when uninitialized.
415 * That is true for xprt->xp_type field.
418 __rpcfd_to_nconf(int fd
, int servtype
)
422 struct netconfig
*nconf
, *newnconf
= NULL
;
426 if (fstat(fd
, &statbuf
) == -1)
429 fdmajor
= major(statbuf
.st_rdev
);
431 if (t_getinfo(fd
, &tinfo
) == -1) {
434 __tli_sys_strerror(errorstr
, sizeof (errorstr
),
436 (void) syslog(LOG_ERR
, "__rpcfd_to_nconf : %s : %s",
437 "could not get transport information",
441 servtype
= tinfo
.servtype
;
444 hndl
= setnetconfig();
448 * Go through all transports listed in /etc/netconfig looking for
449 * transport device in use on fd.
450 * - Match on service type first
451 * - if that succeeds, match on major numbers (used for new local
452 * transport code that is self cloning)
453 * - if that fails, assume transport device uses clone driver
454 * and try match the fdmajor with minor number of device path
455 * which will be the major number of transport device since it
456 * uses the clone driver.
459 while (nconf
= getnetconfig(hndl
)) {
460 if (__rpc_matchserv(servtype
, nconf
->nc_semantics
) == TRUE
) {
461 if (!stat(nconf
->nc_device
, &statbuf
)) {
462 if (fdmajor
== major(statbuf
.st_rdev
))
463 break; /* self cloning driver ? */
464 if (fdmajor
== minor(statbuf
.st_rdev
))
465 break; /* clone driver! */
470 newnconf
= getnetconfigent(nconf
->nc_netid
);
471 (void) endnetconfig(hndl
);
476 __rpc_matchserv(int servtype
, unsigned int nc_semantics
)
480 if (nc_semantics
== NC_TPI_COTS
)
485 if (nc_semantics
== NC_TPI_COTS_ORD
)
490 if (nc_semantics
== NC_TPI_CLTS
)
503 * Routines for RPC/Doors support.
506 extern bool_t
__inet_netdir_is_my_host(const char *);
509 __rpc_is_local_host(const char *host
)
511 char buf
[MAXHOSTNAMELEN
+ 1];
513 if (host
== NULL
|| strcmp(host
, "localhost") == 0 ||
514 strcmp(host
, HOST_SELF
) == 0 ||
515 strcmp(host
, HOST_SELF_CONNECT
) == 0 ||
518 if (sysinfo(SI_HOSTNAME
, buf
, sizeof (buf
)) < 0)
520 if (strcmp(host
, buf
) == 0)
522 return (__inet_netdir_is_my_host(host
));
526 __rpc_try_doors(const char *nettype
, bool_t
*try_others
)
528 switch (getnettype(nettype
)) {
532 case _RPC_DOOR_LOCAL
:
533 case _RPC_DOOR_NETPATH
: