remove unnecessary uint_t casts of 0
[unleashed.git] / usr / src / lib / libc / port / nsl / rpc_generic.c
blob2fe7f8fd499b9eb1aaa88cbc918bba9590863301
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
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
32 * California.
37 * Miscl routines for RPC.
40 #include "mt.h"
41 #include "rpc_mt.h"
42 #include <stdio.h>
43 #include <sys/types.h>
44 #include <rpc/rpc.h>
45 #include <rpc/nettype.h>
46 #include <sys/param.h>
47 #include <sys/mkdev.h>
48 #include <sys/stat.h>
49 #include <ctype.h>
50 #include <errno.h>
51 #include <sys/resource.h>
52 #include <netconfig.h>
53 #include <malloc.h>
54 #include <syslog.h>
55 #include <string.h>
56 #include <sys/systeminfo.h>
57 #include <netdir.h>
58 #include <netdb.h>
60 struct handle {
61 NCONF_HANDLE *nhandle;
62 int nflag; /* Whether NETPATH or NETCONFIG */
63 int nettype;
66 struct _rpcnettype {
67 const char *name;
68 const int type;
69 } _rpctypelist[] = {
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,
76 "tcp", _RPC_TCP,
77 "udp", _RPC_UDP,
78 "local", _RPC_LOCAL,
79 "door", _RPC_DOOR,
80 "door_local", _RPC_DOOR_LOCAL,
81 "door_netpath", _RPC_DOOR_NETPATH,
82 0, _RPC_NONE
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.
91 int
92 __rpc_dtbsize(void)
94 static int tbsize;
95 struct rlimit rl;
97 if (tbsize)
98 return (tbsize);
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
104 * maximum of 1024.
106 if (tbsize > FD_SETSIZE)
107 tbsize = FD_SETSIZE;
108 return (tbsize);
111 * Something wrong. I'll try to save face by returning a
112 * pessimistic number.
114 return (32);
118 * Find the appropriate buffer size
120 uint_t
121 __rpc_get_t_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 */
126 return (0);
127 if (size == 0) {
128 if ((bufsize == -1) || (bufsize == 0)) {
130 * bufsize == -1 : No limit on the size
131 * bufsize == 0 : Concept of tsdu foreign. Choose
132 * a value.
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
147 uint_t
148 __rpc_get_a_size(
149 t_scalar_t size) /* normally tinfo.addr */
151 if (size >= 0)
152 return ((uint_t)size);
153 if (size <= -2)
154 return (0);
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.
165 static int
166 getnettype(const char *nettype)
168 int i;
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()
183 struct netconfig *
184 __rpc_getconfip(char *nettype)
186 char *netid;
187 char *netid_tcp;
188 char *netid_udp;
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;
193 int main_thread;
195 if ((main_thread = thr_main())) {
196 netid_udp = netid_udp_main;
197 netid_tcp = netid_tcp_main;
198 } else {
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;
206 void *confighandle;
208 if (!(confighandle = setnetconfig()))
209 return (NULL);
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) {
215 syslog(LOG_ERR,
216 "__rpc_getconfip : "
217 "strdup failed");
218 return (NULL);
220 if (main_thread)
221 netid_tcp_main = netid_tcp;
222 else
223 (void) pthread_setspecific(
224 tcp_key,
225 (void *)netid_tcp);
226 } else
227 if (strcmp(nconf->nc_proto, NC_UDP) == 0) {
228 netid_udp = strdup(nconf->nc_netid);
229 if (netid_udp == NULL) {
230 syslog(LOG_ERR,
231 "__rpc_getconfip : "
232 "strdup failed");
233 return (NULL);
235 if (main_thread)
236 netid_udp_main = netid_udp;
237 else
238 (void) pthread_setspecific(
239 udp_key,
240 (void *)netid_udp);
244 (void) endnetconfig(confighandle);
246 if (strcmp(nettype, "udp") == 0)
247 netid = netid_udp;
248 else if (strcmp(nettype, "tcp") == 0)
249 netid = netid_tcp;
250 else
251 return (NULL);
252 if ((netid == NULL) || (netid[0] == '\0'))
253 return (NULL);
254 return (getnetconfigent(netid));
259 * Returns the type of the nettype, which should then be used with
260 * __rpc_getconf().
262 void *
263 __rpc_setconf(char *nettype)
265 struct handle *handle;
267 handle = malloc(sizeof (struct handle));
268 if (handle == NULL)
269 return (NULL);
270 switch (handle->nettype = getnettype(nettype)) {
271 case _RPC_DOOR_NETPATH:
272 case _RPC_NETPATH:
273 case _RPC_CIRCUIT_N:
274 case _RPC_DATAGRAM_N:
275 if (!(handle->nhandle = setnetpath())) {
276 free(handle);
277 return (NULL);
279 handle->nflag = TRUE;
280 break;
281 case _RPC_VISIBLE:
282 case _RPC_CIRCUIT_V:
283 case _RPC_DATAGRAM_V:
284 case _RPC_TCP:
285 case _RPC_UDP:
286 case _RPC_LOCAL:
287 case _RPC_DOOR_LOCAL:
288 if (!(handle->nhandle = setnetconfig())) {
289 free(handle);
290 return (NULL);
292 handle->nflag = FALSE;
293 break;
294 default:
295 free(handle);
296 return (NULL);
299 return (handle);
303 * Returns the next netconfig struct for the given "net" type.
304 * __rpc_setconf() should have been called previously.
306 struct netconfig *
307 __rpc_getconf(void *vhandle)
309 struct handle *handle;
310 struct netconfig *nconf;
312 handle = (struct handle *)vhandle;
313 if (handle == NULL)
314 return (NULL);
315 for (;;) {
316 if (handle->nflag)
317 nconf = getnetpath(handle->nhandle);
318 else
319 nconf = getnetconfig(handle->nhandle);
320 if (nconf == NULL)
321 break;
322 if ((nconf->nc_semantics != NC_TPI_CLTS) &&
323 (nconf->nc_semantics != NC_TPI_COTS) &&
324 (nconf->nc_semantics != NC_TPI_COTS_ORD))
325 continue;
326 switch (handle->nettype) {
327 case _RPC_VISIBLE:
328 if (!(nconf->nc_flag & NC_VISIBLE))
329 continue;
330 /*FALLTHROUGH*/
331 case _RPC_DOOR_NETPATH:
332 /*FALLTHROUGH*/
333 case _RPC_NETPATH: /* Be happy */
334 break;
335 case _RPC_CIRCUIT_V:
336 if (!(nconf->nc_flag & NC_VISIBLE))
337 continue;
338 /*FALLTHROUGH*/
339 case _RPC_CIRCUIT_N:
340 if ((nconf->nc_semantics != NC_TPI_COTS) &&
341 (nconf->nc_semantics != NC_TPI_COTS_ORD))
342 continue;
343 break;
344 case _RPC_DATAGRAM_V:
345 if (!(nconf->nc_flag & NC_VISIBLE))
346 continue;
347 /*FALLTHROUGH*/
348 case _RPC_DATAGRAM_N:
349 if (nconf->nc_semantics != NC_TPI_CLTS)
350 continue;
351 break;
352 case _RPC_TCP:
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))
358 continue;
359 break;
360 case _RPC_UDP:
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))
365 continue;
366 break;
367 case _RPC_LOCAL:
368 case _RPC_DOOR_LOCAL:
369 if (!(nconf->nc_flag & NC_VISIBLE))
370 continue;
371 if (strcmp(nconf->nc_protofmly, NC_LOOPBACK))
372 continue;
373 break;
375 break;
377 return (nconf);
380 void
381 __rpc_endconf(void *vhandle)
383 struct handle *handle;
385 handle = (struct handle *)vhandle;
386 if (handle == NULL)
387 return;
388 if (handle->nflag) {
389 (void) endnetpath(handle->nhandle);
390 } else {
391 (void) endnetconfig(handle->nhandle);
393 free(handle);
397 * Used to ping the NULL procedure for clnt handle.
398 * Returns NULL if fails, else a non-NULL pointer.
400 void *
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)
407 return (NULL);
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.
417 struct netconfig *
418 __rpcfd_to_nconf(int fd, int servtype)
420 struct stat statbuf;
421 void *hndl;
422 struct netconfig *nconf, *newnconf = NULL;
423 major_t fdmajor;
424 struct t_info tinfo;
426 if (fstat(fd, &statbuf) == -1)
427 return (NULL);
429 fdmajor = major(statbuf.st_rdev);
430 if (servtype == 0) {
431 if (t_getinfo(fd, &tinfo) == -1) {
432 char errorstr[100];
434 __tli_sys_strerror(errorstr, sizeof (errorstr),
435 t_errno, errno);
436 (void) syslog(LOG_ERR, "__rpcfd_to_nconf : %s : %s",
437 "could not get transport information",
438 errorstr);
439 return (NULL);
441 servtype = tinfo.servtype;
444 hndl = setnetconfig();
445 if (hndl == NULL)
446 return (NULL);
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! */
469 if (nconf)
470 newnconf = getnetconfigent(nconf->nc_netid);
471 (void) endnetconfig(hndl);
472 return (newnconf);
476 __rpc_matchserv(int servtype, unsigned int nc_semantics)
478 switch (servtype) {
479 case T_COTS:
480 if (nc_semantics == NC_TPI_COTS)
481 return (TRUE);
482 break;
484 case T_COTS_ORD:
485 if (nc_semantics == NC_TPI_COTS_ORD)
486 return (TRUE);
487 break;
489 case T_CLTS:
490 if (nc_semantics == NC_TPI_CLTS)
491 return (TRUE);
492 break;
494 default:
495 /* FALSE! */
496 break;
499 return (FALSE);
503 * Routines for RPC/Doors support.
506 extern bool_t __inet_netdir_is_my_host(const char *);
508 bool_t
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 ||
516 strlen(host) == 0)
517 return (TRUE);
518 if (sysinfo(SI_HOSTNAME, buf, sizeof (buf)) < 0)
519 return (FALSE);
520 if (strcmp(host, buf) == 0)
521 return (TRUE);
522 return (__inet_netdir_is_my_host(host));
525 bool_t
526 __rpc_try_doors(const char *nettype, bool_t *try_others)
528 switch (getnettype(nettype)) {
529 case _RPC_DOOR:
530 *try_others = FALSE;
531 return (TRUE);
532 case _RPC_DOOR_LOCAL:
533 case _RPC_DOOR_NETPATH:
534 *try_others = TRUE;
535 return (TRUE);
536 default:
537 *try_others = TRUE;
538 return (FALSE);