rpc_generic.c revision 1.6 1 /* $NetBSD: rpc_generic.c,v 1.6 2001/01/25 22:50:57 jdolecek Exp $ */
2
3 /*
4 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
5 * unrestricted use provided that this legend is included on all tape
6 * media and as a part of the software program in whole or part. Users
7 * may copy or modify Sun RPC without charge, but are not authorized
8 * to license or distribute it to anyone else except as part of a product or
9 * program developed by the user.
10 *
11 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
12 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
13 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
14 *
15 * Sun RPC is provided with no support and without any obligation on the
16 * part of Sun Microsystems, Inc. to assist in its use, correction,
17 * modification or enhancement.
18 *
19 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
20 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
21 * OR ANY PART THEREOF.
22 *
23 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
24 * or profits or other special, indirect and consequential damages, even if
25 * Sun has been advised of the possibility of such damages.
26 *
27 * Sun Microsystems, Inc.
28 * 2550 Garcia Avenue
29 * Mountain View, California 94043
30 */
31 /*
32 * Copyright (c) 1986-1991 by Sun Microsystems Inc.
33 */
34
35 /* #pragma ident "@(#)rpc_generic.c 1.17 94/04/24 SMI" */
36
37 /*
38 * rpc_generic.c, Miscl routines for RPC.
39 *
40 */
41
42 #include "namespace.h"
43 #include <sys/types.h>
44 #include <sys/param.h>
45 #include <sys/socket.h>
46 #include <sys/un.h>
47 #include <sys/resource.h>
48 #include <netinet/in.h>
49 #include <arpa/inet.h>
50 #include <rpc/rpc.h>
51 #include <assert.h>
52 #include <ctype.h>
53 #include <stdio.h>
54 #include <netdb.h>
55 #include <netconfig.h>
56 #include <malloc.h>
57 #include <string.h>
58 #include <syslog.h>
59 #include <rpc/nettype.h>
60 #include "rpc_com.h"
61
62 struct handle {
63 NCONF_HANDLE *nhandle;
64 int nflag; /* Whether NETPATH or NETCONFIG */
65 int nettype;
66 };
67
68 static const struct _rpcnettype {
69 const char *name;
70 const int type;
71 } _rpctypelist[] = {
72 { "netpath", _RPC_NETPATH },
73 { "visible", _RPC_VISIBLE },
74 { "circuit_v", _RPC_CIRCUIT_V },
75 { "datagram_v", _RPC_DATAGRAM_V },
76 { "circuit_n", _RPC_CIRCUIT_N },
77 { "datagram_n", _RPC_DATAGRAM_N },
78 { "tcp", _RPC_TCP },
79 { "udp", _RPC_UDP },
80 { 0, _RPC_NONE }
81 };
82
83 struct netid_af {
84 const char *netid;
85 int af;
86 int protocol;
87 };
88
89 static const struct netid_af na_cvt[] = {
90 { "udp", AF_INET, IPPROTO_UDP },
91 { "tcp", AF_INET, IPPROTO_TCP },
92 #ifdef INET6
93 { "udp6", AF_INET6, IPPROTO_UDP },
94 { "tcp6", AF_INET6, IPPROTO_TCP },
95 #endif
96 { "local", AF_LOCAL, 0 }
97 };
98
99 #if 0
100 static char *strlocase __P((char *));
101 #endif
102 static int getnettype __P((const char *));
103
104 /*
105 * Cache the result of getrlimit(), so we don't have to do an
106 * expensive call every time.
107 */
108 int
109 __rpc_dtbsize()
110 {
111 static int tbsize;
112 struct rlimit rl;
113
114 if (tbsize) {
115 return (tbsize);
116 }
117 if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
118 return (tbsize = (int)rl.rlim_max);
119 }
120 /*
121 * Something wrong. I'll try to save face by returning a
122 * pessimistic number.
123 */
124 return (32);
125 }
126
127
128 /*
129 * Find the appropriate buffer size
130 */
131 u_int
132 /*ARGSUSED*/
133 __rpc_get_t_size(af, proto, size)
134 int af, proto;
135 int size; /* Size requested */
136 {
137 int maxsize;
138
139 switch (proto) {
140 case IPPROTO_TCP:
141 maxsize = 65536; /* XXX */
142 break;
143 case IPPROTO_UDP:
144 maxsize = 8192; /* XXX */
145 break;
146 default:
147 maxsize = RPC_MAXDATASIZE;
148 break;
149 }
150 if (size == 0)
151 return maxsize;
152
153 /* Check whether the value is within the upper max limit */
154 return (size > maxsize ? (u_int)maxsize : (u_int)size);
155 }
156
157 /*
158 * Find the appropriate address buffer size
159 */
160 u_int
161 __rpc_get_a_size(af)
162 int af;
163 {
164 switch (af) {
165 case AF_INET:
166 return sizeof (struct sockaddr_in);
167 #ifdef INET6
168 case AF_INET6:
169 return sizeof (struct sockaddr_in6);
170 #endif
171 case AF_LOCAL:
172 return sizeof (struct sockaddr_un);
173 default:
174 break;
175 }
176 return ((u_int)RPC_MAXADDRSIZE);
177 }
178
179 #if 0
180 static char *
181 strlocase(p)
182 char *p;
183 {
184 char *t = p;
185
186 _DIAGASSERT(p != NULL);
187
188 for (; *p; p++)
189 if (isupper(*p))
190 *p = tolower(*p);
191 return (t);
192 }
193 #endif
194
195 /*
196 * Returns the type of the network as defined in <rpc/nettype.h>
197 * If nettype is NULL, it defaults to NETPATH.
198 */
199 static int
200 getnettype(nettype)
201 const char *nettype;
202 {
203 int i;
204
205 if ((nettype == NULL) || (nettype[0] == NULL)) {
206 return (_RPC_NETPATH); /* Default */
207 }
208
209 #if 0
210 nettype = strlocase(nettype);
211 #endif
212 for (i = 0; _rpctypelist[i].name; i++)
213 if (strcasecmp(nettype, _rpctypelist[i].name) == 0) {
214 return (_rpctypelist[i].type);
215 }
216 return (_rpctypelist[i].type);
217 }
218
219 /*
220 * For the given nettype (tcp or udp only), return the first structure found.
221 * This should be freed by calling freenetconfigent()
222 */
223 struct netconfig *
224 __rpc_getconfip(nettype)
225 const char *nettype;
226 {
227 char *netid;
228 char *netid_tcp = (char *) NULL;
229 char *netid_udp = (char *) NULL;
230 static char *netid_tcp_main;
231 static char *netid_udp_main;
232 struct netconfig *dummy;
233 #ifdef __REENT
234 int main_thread;
235 static thread_key_t tcp_key, udp_key;
236 extern mutex_t tsd_lock;
237
238 if ((main_thread = _thr_main())) {
239 netid_udp = netid_udp_main;
240 netid_tcp = netid_tcp_main;
241 } else {
242 if (tcp_key == 0) {
243 mutex_lock(&tsd_lock);
244 if (tcp_key == 0)
245 thr_keycreate(&tcp_key, free);
246 mutex_unlock(&tsd_lock);
247 }
248 thr_getspecific(tcp_key, (void **) &netid_tcp);
249 if (udp_key == 0) {
250 mutex_lock(&tsd_lock);
251 if (udp_key == 0)
252 thr_keycreate(&udp_key, free);
253 mutex_unlock(&tsd_lock);
254 }
255 thr_getspecific(udp_key, (void **) &netid_udp);
256 }
257 #else
258 netid_udp = netid_udp_main;
259 netid_tcp = netid_tcp_main;
260 #endif
261
262 _DIAGASSERT(nettype != NULL);
263
264 if (!netid_udp && !netid_tcp) {
265 struct netconfig *nconf;
266 void *confighandle;
267
268 if (!(confighandle = setnetconfig())) {
269 syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
270 return (NULL);
271 }
272 while ((nconf = getnetconfig(confighandle)) != NULL) {
273 if (strcmp(nconf->nc_protofmly, NC_INET) == 0) {
274 if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
275 netid_tcp = strdup(nconf->nc_netid);
276 #ifdef __REENT
277 if (main_thread)
278 netid_tcp_main = netid_tcp;
279 else
280 thr_setspecific(tcp_key,
281 (void *) netid_tcp);
282 #else
283 netid_tcp_main = netid_tcp;
284 #endif
285 } else
286 if (strcmp(nconf->nc_proto, NC_UDP) == 0) {
287 netid_udp = strdup(nconf->nc_netid);
288 #ifdef __REENT
289 if (main_thread)
290 netid_udp_main = netid_udp;
291 else
292 thr_setspecific(udp_key,
293 (void *) netid_udp);
294 #else
295 netid_udp_main = netid_udp;
296 #endif
297 }
298 }
299 }
300 endnetconfig(confighandle);
301 }
302 if (strcmp(nettype, "udp") == 0)
303 netid = netid_udp;
304 else if (strcmp(nettype, "tcp") == 0)
305 netid = netid_tcp;
306 else {
307 return (NULL);
308 }
309 if ((netid == NULL) || (netid[0] == NULL)) {
310 return (NULL);
311 }
312 dummy = getnetconfigent(netid);
313 return (dummy);
314 }
315
316 /*
317 * Returns the type of the nettype, which should then be used with
318 * __rpc_getconf().
319 */
320 void *
321 __rpc_setconf(nettype)
322 const char *nettype;
323 {
324 struct handle *handle;
325
326 /* nettype may be NULL; getnettype() supports that */
327
328 handle = (struct handle *) malloc(sizeof (struct handle));
329 if (handle == NULL) {
330 return (NULL);
331 }
332 switch (handle->nettype = getnettype(nettype)) {
333 case _RPC_NETPATH:
334 case _RPC_CIRCUIT_N:
335 case _RPC_DATAGRAM_N:
336 if (!(handle->nhandle = setnetpath())) {
337 free(handle);
338 return (NULL);
339 }
340 handle->nflag = TRUE;
341 break;
342 case _RPC_VISIBLE:
343 case _RPC_CIRCUIT_V:
344 case _RPC_DATAGRAM_V:
345 case _RPC_TCP:
346 case _RPC_UDP:
347 if (!(handle->nhandle = setnetconfig())) {
348 syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
349 free(handle);
350 return (NULL);
351 }
352 handle->nflag = FALSE;
353 break;
354 default:
355 return (NULL);
356 }
357
358 return (handle);
359 }
360
361 /*
362 * Returns the next netconfig struct for the given "net" type.
363 * __rpc_setconf() should have been called previously.
364 */
365 struct netconfig *
366 __rpc_getconf(vhandle)
367 void *vhandle;
368 {
369 struct handle *handle;
370 struct netconfig *nconf;
371
372 handle = (struct handle *)vhandle;
373 if (handle == NULL) {
374 return (NULL);
375 }
376 for (;;) {
377 if (handle->nflag)
378 nconf = getnetpath(handle->nhandle);
379 else
380 nconf = getnetconfig(handle->nhandle);
381 if (nconf == NULL)
382 break;
383 if ((nconf->nc_semantics != NC_TPI_CLTS) &&
384 (nconf->nc_semantics != NC_TPI_COTS) &&
385 (nconf->nc_semantics != NC_TPI_COTS_ORD))
386 continue;
387 switch (handle->nettype) {
388 case _RPC_VISIBLE:
389 if (!(nconf->nc_flag & NC_VISIBLE))
390 continue;
391 /* FALLTHROUGH */
392 case _RPC_NETPATH: /* Be happy */
393 break;
394 case _RPC_CIRCUIT_V:
395 if (!(nconf->nc_flag & NC_VISIBLE))
396 continue;
397 /* FALLTHROUGH */
398 case _RPC_CIRCUIT_N:
399 if ((nconf->nc_semantics != NC_TPI_COTS) &&
400 (nconf->nc_semantics != NC_TPI_COTS_ORD))
401 continue;
402 break;
403 case _RPC_DATAGRAM_V:
404 if (!(nconf->nc_flag & NC_VISIBLE))
405 continue;
406 /* FALLTHROUGH */
407 case _RPC_DATAGRAM_N:
408 if (nconf->nc_semantics != NC_TPI_CLTS)
409 continue;
410 break;
411 case _RPC_TCP:
412 if (((nconf->nc_semantics != NC_TPI_COTS) &&
413 (nconf->nc_semantics != NC_TPI_COTS_ORD)) ||
414 (strcmp(nconf->nc_protofmly, NC_INET)
415 #ifdef INET6
416 && strcmp(nconf->nc_protofmly, NC_INET6))
417 #else
418 )
419 #endif
420 ||
421 strcmp(nconf->nc_proto, NC_TCP))
422 continue;
423 break;
424 case _RPC_UDP:
425 if ((nconf->nc_semantics != NC_TPI_CLTS) ||
426 (strcmp(nconf->nc_protofmly, NC_INET)
427 #ifdef INET6
428 && strcmp(nconf->nc_protofmly, NC_INET6))
429 #else
430 )
431 #endif
432 ||
433 strcmp(nconf->nc_proto, NC_UDP))
434 continue;
435 break;
436 }
437 break;
438 }
439 return (nconf);
440 }
441
442 void
443 __rpc_endconf(vhandle)
444 void * vhandle;
445 {
446 struct handle *handle;
447
448 handle = (struct handle *) vhandle;
449 if (handle == NULL) {
450 return;
451 }
452 if (handle->nflag) {
453 endnetpath(handle->nhandle);
454 } else {
455 endnetconfig(handle->nhandle);
456 }
457 free(handle);
458 }
459
460 /*
461 * Used to ping the NULL procedure for clnt handle.
462 * Returns NULL if fails, else a non-NULL pointer.
463 */
464 void *
465 rpc_nullproc(clnt)
466 CLIENT *clnt;
467 {
468 struct timeval TIMEOUT = {25, 0};
469
470 if (clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void, NULL,
471 (xdrproc_t) xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) {
472 return (NULL);
473 }
474 return ((void *) clnt);
475 }
476
477 /*
478 * Try all possible transports until
479 * one succeeds in finding the netconf for the given fd.
480 */
481 struct netconfig *
482 __rpcgettp(fd)
483 int fd;
484 {
485 const char *netid;
486 struct __rpc_sockinfo si;
487
488 if (!__rpc_fd2sockinfo(fd, &si))
489 return NULL;
490
491 if (!__rpc_sockinfo2netid(&si, &netid))
492 return NULL;
493
494 /*LINTED const castaway*/
495 return getnetconfigent((char *)netid);
496 }
497
498 int
499 __rpc_fd2sockinfo(int fd, struct __rpc_sockinfo *sip)
500 {
501 socklen_t len;
502 int type, proto;
503 struct sockaddr_storage ss;
504
505 _DIAGASSERT(sip != NULL);
506
507 len = sizeof ss;
508 if (getsockname(fd, (struct sockaddr *)(void *)&ss, &len) < 0)
509 return 0;
510 sip->si_alen = len;
511
512 len = sizeof type;
513 if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &len) < 0)
514 return 0;
515
516 /* XXX */
517 if (ss.ss_family != AF_LOCAL) {
518 if (type == SOCK_STREAM)
519 proto = IPPROTO_TCP;
520 else if (type == SOCK_DGRAM)
521 proto = IPPROTO_UDP;
522 else
523 return 0;
524 } else
525 proto = 0;
526
527 sip->si_af = ss.ss_family;
528 sip->si_proto = proto;
529 sip->si_socktype = type;
530
531 return 1;
532 }
533
534 /*
535 * Linear search, but the number of entries is small.
536 */
537 int
538 __rpc_nconf2sockinfo(const struct netconfig *nconf, struct __rpc_sockinfo *sip)
539 {
540 int i;
541
542 _DIAGASSERT(nconf != NULL);
543 _DIAGASSERT(sip != NULL);
544
545 for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++)
546 if (!strcmp(na_cvt[i].netid, nconf->nc_netid)) {
547 sip->si_af = na_cvt[i].af;
548 sip->si_proto = na_cvt[i].protocol;
549 sip->si_socktype =
550 __rpc_seman2socktype((int)nconf->nc_semantics);
551 if (sip->si_socktype == -1)
552 return 0;
553 sip->si_alen = __rpc_get_a_size(sip->si_af);
554 return 1;
555 }
556
557 return 0;
558 }
559
560 int
561 __rpc_nconf2fd(const struct netconfig *nconf)
562 {
563 struct __rpc_sockinfo si;
564
565 _DIAGASSERT(nconf != NULL);
566
567 if (!__rpc_nconf2sockinfo(nconf, &si))
568 return 0;
569
570 return socket(si.si_af, si.si_socktype, si.si_proto);
571 }
572
573 int
574 __rpc_sockinfo2netid(struct __rpc_sockinfo *sip, const char **netid)
575 {
576 int i;
577
578 _DIAGASSERT(sip != NULL);
579 /* netid may be NULL */
580
581 for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++)
582 if (na_cvt[i].af == sip->si_af &&
583 na_cvt[i].protocol == sip->si_proto) {
584 if (netid)
585 *netid = na_cvt[i].netid;
586 return 1;
587 }
588
589 return 0;
590 }
591
592 char *
593 taddr2uaddr(const struct netconfig *nconf, const struct netbuf *nbuf)
594 {
595 struct __rpc_sockinfo si;
596
597 _DIAGASSERT(nconf != NULL);
598 _DIAGASSERT(nbuf != NULL);
599
600 if (!__rpc_nconf2sockinfo(nconf, &si))
601 return NULL;
602 return __rpc_taddr2uaddr_af(si.si_af, nbuf);
603 }
604
605 struct netbuf *
606 uaddr2taddr(const struct netconfig *nconf, const char *uaddr)
607 {
608 struct __rpc_sockinfo si;
609
610 _DIAGASSERT(nconf != NULL);
611 _DIAGASSERT(uaddr != NULL);
612
613 if (!__rpc_nconf2sockinfo(nconf, &si))
614 return NULL;
615 return __rpc_uaddr2taddr_af(si.si_af, uaddr);
616 }
617
618 char *
619 __rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf)
620 {
621 char *ret;
622 struct sockaddr_in *sin;
623 struct sockaddr_un *sun;
624 char namebuf[INET_ADDRSTRLEN];
625 #ifdef INET6
626 struct sockaddr_in6 *sin6;
627 char namebuf6[INET6_ADDRSTRLEN];
628 #endif
629 u_int16_t port;
630
631 _DIAGASSERT(nbuf != NULL);
632
633 switch (af) {
634 case AF_INET:
635 sin = nbuf->buf;
636 if (inet_ntop(af, &sin->sin_addr, namebuf, sizeof namebuf)
637 == NULL)
638 return NULL;
639 port = ntohs(sin->sin_port);
640 if (asprintf(&ret, "%s.%u.%u", namebuf, ((u_int32_t)port) >> 8,
641 port & 0xff) < 0)
642 return NULL;
643 break;
644 #ifdef INET6
645 case AF_INET6:
646 sin6 = nbuf->buf;
647 if (inet_ntop(af, &sin6->sin6_addr, namebuf6, sizeof namebuf6)
648 == NULL)
649 return NULL;
650 port = ntohs(sin6->sin6_port);
651 if (asprintf(&ret, "%s.%u.%u", namebuf6, ((u_int32_t)port) >> 8,
652 port & 0xff) < 0)
653 return NULL;
654 break;
655 #endif
656 case AF_LOCAL:
657 sun = nbuf->buf;
658 sun->sun_path[sizeof(sun->sun_path) - 1] = '\0'; /* safety */
659 ret = strdup(sun->sun_path);
660 break;
661 default:
662 return NULL;
663 }
664
665 return ret;
666 }
667
668 struct netbuf *
669 __rpc_uaddr2taddr_af(int af, const char *uaddr)
670 {
671 struct netbuf *ret = NULL;
672 char *addrstr, *p;
673 unsigned port, portlo, porthi;
674 struct sockaddr_in *sin;
675 #ifdef INET6
676 struct sockaddr_in6 *sin6;
677 #endif
678 struct sockaddr_un *sun;
679
680 _DIAGASSERT(uaddr != NULL);
681
682 addrstr = strdup(uaddr);
683 if (addrstr == NULL)
684 return NULL;
685
686 /*
687 * AF_LOCAL addresses are expected to be absolute
688 * pathnames, anything else will be AF_INET or AF_INET6.
689 */
690 if (*addrstr != '/') {
691 p = strrchr(addrstr, '.');
692 if (p == NULL)
693 goto out;
694 portlo = (unsigned)atoi(p + 1);
695 *p = '\0';
696
697 p = strrchr(addrstr, '.');
698 if (p == NULL)
699 goto out;
700 porthi = (unsigned)atoi(p + 1);
701 *p = '\0';
702 port = (porthi << 8) | portlo;
703 }
704
705 ret = (struct netbuf *)malloc(sizeof *ret);
706
707 switch (af) {
708 case AF_INET:
709 sin = (struct sockaddr_in *)malloc(sizeof *sin);
710 if (sin == NULL)
711 goto out;
712 memset(sin, 0, sizeof *sin);
713 sin->sin_family = AF_INET;
714 sin->sin_port = htons(port);
715 if (inet_pton(AF_INET, addrstr, &sin->sin_addr) <= 0) {
716 free(sin);
717 free(ret);
718 ret = NULL;
719 goto out;
720 }
721 sin->sin_len = ret->maxlen = ret->len = sizeof *sin;
722 ret->buf = sin;
723 break;
724 #ifdef INET6
725 case AF_INET6:
726 sin6 = (struct sockaddr_in6 *)malloc(sizeof *sin6);
727 if (sin6 == NULL)
728 goto out;
729 memset(sin6, 0, sizeof *sin6);
730 sin6->sin6_family = AF_INET6;
731 sin6->sin6_port = htons(port);
732 if (inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) <= 0) {
733 free(sin);
734 free(ret);
735 ret = NULL;
736 goto out;
737 }
738 sin6->sin6_len = ret->maxlen = ret->len = sizeof *sin6;
739 ret->buf = sin6;
740 break;
741 #endif
742 case AF_LOCAL:
743 sun = (struct sockaddr_un *)malloc(sizeof *sun);
744 if (sun == NULL)
745 goto out;
746 memset(sun, 0, sizeof *sun);
747 sun->sun_family = AF_LOCAL;
748 strncpy(sun->sun_path, addrstr, sizeof(sun->sun_path) - 1);
749 break;
750 default:
751 break;
752 }
753 out:
754 free(addrstr);
755 return ret;
756 }
757
758 int
759 __rpc_seman2socktype(int semantics)
760 {
761 switch (semantics) {
762 case NC_TPI_CLTS:
763 return SOCK_DGRAM;
764 case NC_TPI_COTS_ORD:
765 return SOCK_STREAM;
766 case NC_TPI_RAW:
767 return SOCK_RAW;
768 default:
769 break;
770 }
771
772 return -1;
773 }
774
775 int
776 __rpc_socktype2seman(int socktype)
777 {
778 switch (socktype) {
779 case SOCK_DGRAM:
780 return NC_TPI_CLTS;
781 case SOCK_STREAM:
782 return NC_TPI_COTS_ORD;
783 case SOCK_RAW:
784 return NC_TPI_RAW;
785 default:
786 break;
787 }
788
789 return -1;
790 }
791
792 /*
793 * XXXX - IPv6 scope IDs can't be handled in universal addresses.
794 * Here, we compare the original server address to that of the RPC
795 * service we just received back from a call to rpcbind on the remote
796 * machine. If they are both "link local" or "site local", copy
797 * the scope id of the server address over to the service address.
798 */
799 int
800 __rpc_fixup_addr(struct netbuf *new, const struct netbuf *svc)
801 {
802 #ifdef INET6
803 struct sockaddr *sa_new, *sa_svc;
804 struct sockaddr_in6 *sin6_new, *sin6_svc;
805
806 _DIAGASSERT(new != NULL);
807 _DIAGASSERT(svc != NULL);
808
809 sa_svc = (struct sockaddr *)svc->buf;
810 sa_new = (struct sockaddr *)new->buf;
811
812 if (sa_new->sa_family == sa_svc->sa_family &&
813 sa_new->sa_family == AF_INET6) {
814 sin6_new = (struct sockaddr_in6 *)new->buf;
815 sin6_svc = (struct sockaddr_in6 *)svc->buf;
816
817 if ((IN6_IS_ADDR_LINKLOCAL(&sin6_new->sin6_addr) &&
818 IN6_IS_ADDR_LINKLOCAL(&sin6_svc->sin6_addr)) ||
819 (IN6_IS_ADDR_SITELOCAL(&sin6_new->sin6_addr) &&
820 IN6_IS_ADDR_SITELOCAL(&sin6_svc->sin6_addr))) {
821 sin6_new->sin6_scope_id = sin6_svc->sin6_scope_id;
822 }
823 }
824 #endif
825 return 1;
826 }
827
828 int
829 __rpc_sockisbound(int fd)
830 {
831 struct sockaddr_storage ss;
832 socklen_t slen;
833
834 slen = sizeof (struct sockaddr_storage);
835 if (getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0)
836 return 0;
837
838 switch (ss.ss_family) {
839 case AF_INET:
840 return (((struct sockaddr_in *)
841 (void *)&ss)->sin_port != 0);
842 #ifdef INET6
843 case AF_INET6:
844 return (((struct sockaddr_in6 *)
845 (void *)&ss)->sin6_port != 0);
846 #endif
847 case AF_LOCAL:
848 /* XXX check this */
849 return (((struct sockaddr_un *)
850 (void *)&ss)->sun_path[0] != '\0');
851 default:
852 break;
853 }
854
855 return 0;
856 }
857