4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
24 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
32 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
33 * Use is subject to license terms.
39 * Miscellaneous support routines for kernel implementation of RPC.
42 #include <sys/param.h>
43 #include <sys/t_lock.h>
45 #include <sys/vnode.h>
46 #include <sys/stream.h>
47 #include <sys/stropts.h>
48 #include <sys/strsubr.h>
49 #include <sys/socket.h>
50 #include <sys/tihdr.h>
51 #include <sys/timod.h>
52 #include <sys/tiuser.h>
53 #include <sys/systm.h>
54 #include <sys/cmn_err.h>
55 #include <sys/debug.h>
57 #include <netinet/in.h>
58 #include <rpc/types.h>
61 #include <rpc/rpcb_prot.h>
62 #include <rpc/pmap_prot.h>
64 static int strtoi(char *, char **);
65 static void grow_netbuf(struct netbuf
*, size_t);
66 static void loopb_u2t(const char *, struct netbuf
*);
68 #define RPC_PMAP_TIMEOUT 15
70 * define for max length of an ip address and port address, the value was
71 * calculated using INET6_ADDRSTRLEN (46) + max port address (12) +
72 * seperator "."'s in port address (2) + null (1) = 61.
73 * Then there is IPV6_TOKEN_LEN which is 64, so the value is 64 to be safe.
75 #define RPC_MAX_IP_LENGTH 64
78 * Kernel level debugging aid. The global variable "rpclog" is a bit
79 * mask which allows various types of debugging messages to be printed
82 * rpclog & 1 will cause actual failures to be printed.
83 * rpclog & 2 will cause informational messages to be
84 * printed on the client side of rpc.
85 * rpclog & 4 will cause informational messages to be
86 * printed on the server side of rpc.
87 * rpclog & 8 will cause informational messages for rare events to be
88 * printed on the client side of rpc.
89 * rpclog & 16 will cause informational messages for rare events to be
90 * printed on the server side of rpc.
91 * rpclog & 32 will cause informational messages for rare events to be
92 * printed on the common client/server code paths of rpc.
93 * rpclog & 64 will cause informational messages for manipulation
94 * client-side COTS dispatch list to be printed.
101 rpc_poptimod(vnode_t
*vp
)
103 int error
, isfound
, ret
;
105 error
= strioctl(vp
, I_FIND
, (intptr_t)"timod", 0, K_TO_K
, kcred
,
108 RPCLOG(1, "rpc_poptimod: I_FIND strioctl error %d\n", error
);
115 error
= strioctl(vp
, I_POP
, 0, 0, K_TO_K
, kcred
, &ret
);
117 RPCLOG(1, "rpc_poptimod: I_POP strioctl error %d\n",
125 * Check the passed in ip address for correctness (limited) and return its
128 * an ipv4 looks like this:
129 * "IP.IP.IP.IP.PORT[top byte].PORT[bottom byte]"
131 * an ipv6 looks like this:
132 * fec0:A02::2:202:4FCD
151 /* search for the different type of characters in the ip address */
152 while ((*cp
!= '\0') && (chcnt
< RPC_MAX_IP_LENGTH
)) {
194 /* check for bad ip strings */
195 if ((chcnt
== RPC_MAX_IP_LENGTH
) || (othercnt
))
198 /* if we have a coloncnt, it can only be an ipv6 address */
200 if ((coloncnt
< 2) || (coloncnt
> 7))
205 /* since there are no colons, make sure it is ipv4 */
206 if ((hexnumcnt
) || (dotcnt
!= 5))
215 * Return a port number from a sockaddr_in expressed in universal address
216 * format. Note that this routine does not work for address families other
217 * than INET. Eventually, we should replace this routine with one that
218 * contacts the rpcbind running locally.
221 rpc_uaddr2port(int af
, char *addr
)
229 * A struct sockaddr_in expressed in universal address
232 * "IP.IP.IP.IP.PORT[top byte].PORT[bottom byte]"
234 * Where each component expresses as a character,
235 * the corresponding part of the IP address
237 * Thus 127.0.0.1, port 2345 looks like:
239 * 49 50 55 46 48 46 48 46 49 46 57 46 52 49
240 * 1 2 7 . 0 . 0 . 1 . 9 . 4 1
242 * 2345 = 929base16 = 9.32+9 = 9.41
244 (void) strtoi(addr
, &next
);
245 (void) strtoi(next
, &next
);
246 (void) strtoi(next
, &next
);
247 (void) strtoi(next
, &next
);
248 p1
= strtoi(next
, &next
);
249 p2
= strtoi(next
, &next
);
251 } else if (af
== AF_INET6
) {
253 * An IPv6 address is expressed in following two formats
254 * fec0:A02::2:202:4FCD or
256 * An universal address will have porthi.portlo appended to
257 * v6 address. So always look for the last two dots when
258 * extracting port number.
261 while (next
= strchr(next
, '.')) {
263 next
= strchr(next
, '.');
268 RPCLOG(1, "rpc_uaddr2port: IPv6 port %d\n", ((p1
<< 8) + p2
));
271 return ((p1
<< 8) + p2
);
275 * Modified strtol(3). Should we be using mi_strtol() instead?
278 strtoi(char *str
, char **ptr
)
283 for (val
= 0, c
= *str
++; c
>= '0' && c
<= '9'; c
= *str
++) {
292 * Utilities for manipulating netbuf's.
294 * Note that loopback addresses are not null-terminated, so these utilities
295 * typically use the strn* string routines.
299 * Utilities to patch a port number (for NC_INET protocols) or a
300 * port name (for NC_LOOPBACK) into a network address.
305 * PSARC 2003/523 Contract Private Interface
307 * Changes must be reviewed by Solaris File Sharing
308 * Changes must be communicated to contract-2003-523@sun.com
311 put_inet_port(struct netbuf
*addr
, ushort_t port
)
314 * Easy - we always patch an unsigned short on top of an
315 * unsigned short. No changes to addr's len or maxlen are
318 ((struct sockaddr_in
*)(addr
->buf
))->sin_port
= port
;
322 put_inet6_port(struct netbuf
*addr
, ushort_t port
)
324 ((struct sockaddr_in6
*)(addr
->buf
))->sin6_port
= port
;
328 put_loopback_port(struct netbuf
*addr
, char *port
)
336 * We must make sure the addr has enough space for us,
337 * patch in `port', and then adjust addr's len and maxlen
338 * to reflect the change.
340 if ((dot
= strnrchr(addr
->buf
, '.', addr
->len
)) == (char *)NULL
)
343 newlen
= (int)((dot
- addr
->buf
+ 1) + strlen(port
));
344 if (newlen
> addr
->maxlen
) {
345 newbuf
= kmem_zalloc(newlen
, KM_SLEEP
);
346 bcopy(addr
->buf
, newbuf
, addr
->len
);
347 kmem_free(addr
->buf
, addr
->maxlen
);
349 addr
->len
= addr
->maxlen
= newlen
;
350 dot
= strnrchr(addr
->buf
, '.', addr
->len
);
355 (void) strncpy(++dot
, port
, strlen(port
));
359 * Convert a loopback universal address to a loopback transport address.
362 loopb_u2t(const char *ua
, struct netbuf
*addr
)
364 size_t stringlen
= strlen(ua
) + 1;
365 const char *univp
; /* ptr into universal addr */
366 char *transp
; /* ptr into transport addr */
368 /* Make sure the netbuf will be big enough. */
369 if (addr
->maxlen
< stringlen
) {
370 grow_netbuf(addr
, stringlen
);
375 while (*univp
!= NULL
) {
376 if (*univp
== '\\' && *(univp
+1) == '\\') {
379 } else if (*univp
== '\\') {
380 /* octal character */
381 *transp
= (((*(univp
+1) - '0') & 3) << 6) +
382 (((*(univp
+2) - '0') & 7) << 3) +
383 ((*(univp
+3) - '0') & 7);
392 addr
->len
= (unsigned int)(transp
- addr
->buf
);
393 ASSERT(addr
->len
<= addr
->maxlen
);
397 * Make sure the given netbuf has a maxlen at least as big as the given
401 grow_netbuf(struct netbuf
*nb
, size_t length
)
405 if (nb
->maxlen
>= length
)
408 newbuf
= kmem_zalloc(length
, KM_SLEEP
);
409 bcopy(nb
->buf
, newbuf
, nb
->len
);
410 kmem_free(nb
->buf
, nb
->maxlen
);
412 nb
->maxlen
= (unsigned int)length
;
416 * XXX: xdr_pmap is here, because it's the only XDR function
417 * of portmap protocol. If there'll be more portmap functions,
418 * it would be better to put them to a separate file.
421 xdr_pmap(XDR
*xdrs
, PMAP
*objp
)
423 if (!xdr_rpcprog(xdrs
, &objp
->pm_prog
))
425 if (!xdr_rpcvers(xdrs
, &objp
->pm_vers
))
427 if (!xdr_rpcprot(xdrs
, &objp
->pm_prot
))
429 if (!xdr_u_int(xdrs
, &objp
->pm_port
))
436 * Get remote port via PORTMAP protocol version 2 (works for IPv4 only)
437 * according to RFC 1833, section 3.
439 static enum clnt_stat
440 portmap_getport(struct knetconfig
*config
, rpcprog_t prog
, rpcvers_t vers
,
441 struct netbuf
*addr
, struct timeval tmo
)
443 enum clnt_stat status
;
444 CLIENT
*client
= NULL
;
450 ASSERT(strcmp(config
->knc_protofmly
, NC_INET
) == 0);
452 bzero(&parms
, sizeof (parms
));
453 parms
.pm_prog
= prog
;
454 parms
.pm_vers
= vers
;
455 if (strcmp(config
->knc_proto
, NC_TCP
) == 0) {
456 parms
.pm_prot
= IPPROTO_TCP
;
457 } else { /* NC_UDP */
458 parms
.pm_prot
= IPPROTO_UDP
;
463 * Mask all signals before doing RPC network operations
464 * in the same way rpcbind_getaddr() does (see comments
467 sigfillset(&newmask
);
468 sigreplace(&newmask
, &oldmask
);
470 if (clnt_tli_kcreate(config
, addr
, PMAPPROG
,
471 PMAPVERS
, 0, 0, CRED(), &client
)) {
472 sigreplace(&oldmask
, (k_sigset_t
*)NULL
);
473 return (RPC_TLIERROR
);
476 client
->cl_nosignal
= 1;
477 status
= CLNT_CALL(client
, PMAPPROC_GETPORT
,
478 xdr_pmap
, (char *)&parms
,
479 xdr_u_short
, (char *)&port
, tmo
);
481 sigreplace(&oldmask
, (k_sigset_t
*)NULL
);
482 if (status
!= RPC_SUCCESS
)
485 status
= RPC_PROGNOTREGISTERED
;
489 put_inet_port(addr
, ntohs(port
));
492 auth_destroy(client
->cl_auth
);
493 clnt_destroy(client
);
499 * Try to get the address for the desired service by using the rpcbind
500 * protocol. Ignores signals. If addr is a loopback address, it is
501 * expected to be initialized to "localhost.".
502 * rpcbind_getaddr() is able to work with RPCBIND protocol version 3 and 4
503 * and PORTMAP protocol version 2.
504 * It tries version 4 at first, then version 3 and finally (if both failed)
505 * it tries portmapper protocol version 2.
508 rpcbind_getaddr(struct knetconfig
*config
, rpcprog_t prog
, rpcvers_t vers
,
512 enum clnt_stat status
;
522 * Call rpcbind (local or remote) to get an address we can use
523 * in an RPC client handle.
525 tmo
.tv_sec
= RPC_PMAP_TIMEOUT
;
529 parms
.r_addr
= parms
.r_owner
= "";
531 if (strcmp(config
->knc_protofmly
, NC_INET
) == 0) {
532 put_inet_port(addr
, htons(PMAPPORT
));
534 if (strcmp(config
->knc_proto
, NC_TCP
) == 0)
535 parms
.r_netid
= "tcp";
537 parms
.r_netid
= "udp";
539 } else if (strcmp(config
->knc_protofmly
, NC_INET6
) == 0) {
540 if (strcmp(config
->knc_proto
, NC_TCP
) == 0)
541 parms
.r_netid
= "tcp6";
543 parms
.r_netid
= "udp6";
544 put_inet6_port(addr
, htons(PMAPPORT
));
545 } else if (strcmp(config
->knc_protofmly
, NC_LOOPBACK
) == 0) {
546 ASSERT(strnrchr(addr
->buf
, '.', addr
->len
) != NULL
);
547 if (config
->knc_semantics
== NC_TPI_COTS_ORD
)
548 parms
.r_netid
= "ticotsord";
549 else if (config
->knc_semantics
== NC_TPI_COTS
)
550 parms
.r_netid
= "ticots";
552 parms
.r_netid
= "ticlts";
554 put_loopback_port(addr
, "rpc");
556 status
= RPC_UNKNOWNPROTO
;
561 * Try RPCBIND versions 4 and 3 (if 4 fails).
563 for (rpcbv
= RPCBVERS4
; rpcbv
>= RPCBVERS
; rpcbv
--) {
564 CLIENT
*client
= NULL
;
567 xdr_free(xdr_wrapstring
, (char *)&ua
);
572 * Mask signals for the duration of the handle creation and
573 * RPC calls. This allows relatively normal operation with a
574 * signal already posted to our thread (e.g., when we are
575 * sending an NLM_CANCEL in response to catching a signal).
577 * Any further exit paths from this routine must restore
578 * the original signal mask.
580 sigfillset(&newmask
);
581 sigreplace(&newmask
, &oldmask
);
583 if (clnt_tli_kcreate(config
, addr
, RPCBPROG
,
584 rpcbv
, 0, 0, CRED(), &client
)) {
585 status
= RPC_TLIERROR
;
586 sigreplace(&oldmask
, (k_sigset_t
*)NULL
);
590 client
->cl_nosignal
= 1;
591 status
= CLNT_CALL(client
, RPCBPROC_GETADDR
,
592 xdr_rpcb
, (char *)&parms
,
593 xdr_wrapstring
, (char *)&ua
, tmo
);
595 sigreplace(&oldmask
, (k_sigset_t
*)NULL
);
596 auth_destroy(client
->cl_auth
);
597 clnt_destroy(client
);
599 if (status
== RPC_SUCCESS
) {
600 if (ua
== NULL
|| *ua
== NULL
) {
601 status
= RPC_PROGNOTREGISTERED
;
608 if (status
!= RPC_SUCCESS
)
612 * Convert the universal address to the transport address.
613 * Theoretically, we should call the local rpcbind to translate
614 * from the universal address to the transport address, but it gets
615 * complicated (e.g., there's no direct way to tell rpcbind that we
616 * want an IP address instead of a loopback address). Note that
617 * the transport address is potentially host-specific, so we can't
618 * just ask the remote rpcbind, because it might give us the wrong
621 if (strcmp(config
->knc_protofmly
, NC_INET
) == 0) {
622 /* make sure that the ip address is the correct type */
623 if (rpc_iptype(ua
, &iptype
) != 0) {
624 status
= RPC_UNKNOWNADDR
;
627 port
= rpc_uaddr2port(iptype
, ua
);
628 put_inet_port(addr
, ntohs(port
));
629 } else if (strcmp(config
->knc_protofmly
, NC_INET6
) == 0) {
630 /* make sure that the ip address is the correct type */
631 if (rpc_iptype(ua
, &iptype
) != 0) {
632 status
= RPC_UNKNOWNADDR
;
635 port
= rpc_uaddr2port(iptype
, ua
);
636 put_inet6_port(addr
, ntohs(port
));
637 } else if (strcmp(config
->knc_protofmly
, NC_LOOPBACK
) == 0) {
640 /* "can't happen" - should have been checked for above */
641 cmn_err(CE_PANIC
, "rpcbind_getaddr: bad protocol family");
645 if (status
!= RPC_SUCCESS
&&
646 strcmp(config
->knc_protofmly
, NC_INET
) == 0) {
648 * For IPv4 try to get remote port via PORTMAP protocol.
649 * NOTE: if we're here, then all attempts to get remote
650 * port via RPCBIND protocol failed.
653 DTRACE_PROBE1(try__portmap
, enum clnt_stat
, status
);
654 status
= portmap_getport(config
, prog
, vers
, addr
, tmo
);
659 xdr_free(xdr_wrapstring
, (char *)&ua
);
663 static const char *tpiprims
[] = {
664 "T_CONN_REQ 0 connection request",
665 "T_CONN_RES 1 connection response",
666 "T_DISCON_REQ 2 disconnect request",
667 "T_DATA_REQ 3 data request",
668 "T_EXDATA_REQ 4 expedited data request",
669 "T_INFO_REQ 5 information request",
670 "T_BIND_REQ 6 bind request",
671 "T_UNBIND_REQ 7 unbind request",
672 "T_UNITDATA_REQ 8 unitdata request",
673 "T_OPTMGMT_REQ 9 manage options req",
674 "T_ORDREL_REQ 10 orderly release req",
675 "T_CONN_IND 11 connection indication",
676 "T_CONN_CON 12 connection confirmation",
677 "T_DISCON_IND 13 disconnect indication",
678 "T_DATA_IND 14 data indication",
679 "T_EXDATA_IND 15 expeditied data indication",
680 "T_INFO_ACK 16 information acknowledgment",
681 "T_BIND_ACK 17 bind acknowledment",
682 "T_ERROR_ACK 18 error acknowledgment",
683 "T_OK_ACK 19 ok acknowledgment",
684 "T_UNITDATA_IND 20 unitdata indication",
685 "T_UDERROR_IND 21 unitdata error indication",
686 "T_OPTMGMT_ACK 22 manage options ack",
687 "T_ORDREL_IND 23 orderly release ind"
692 rpc_tpiprim2name(uint_t prim
)
694 if (prim
> (sizeof (tpiprims
) / sizeof (tpiprims
[0]) - 1))
695 return ("unknown primitive");
697 return (tpiprims
[prim
]);
700 static const char *tpierrs
[] = {
702 "TBADADDR 1 incorrect addr format",
703 "TBADOPT 2 incorrect option format",
704 "TACCES 3 incorrect permissions",
705 "TBADF 4 illegal transport fd",
706 "TNOADDR 5 couldn't allocate addr",
707 "TOUTSTATE 6 out of state",
708 "TBADSEQ 7 bad call sequnce number",
709 "TSYSERR 8 system error",
710 "TLOOK 9 event requires attention",
711 "TBADDATA 10 illegal amount of data",
712 "TBUFOVFLW 11 buffer not large enough",
713 "TFLOW 12 flow control",
714 "TNODATA 13 no data",
715 "TNODIS 14 discon_ind not found on q",
716 "TNOUDERR 15 unitdata error not found",
717 "TBADFLAG 16 bad flags",
718 "TNOREL 17 no ord rel found on q",
719 "TNOTSUPPORT 18 primitive not supported",
720 "TSTATECHNG 19 state is in process of changing"
725 rpc_tpierr2name(uint_t err
)
727 if (err
> (sizeof (tpierrs
) / sizeof (tpierrs
[0]) - 1))
728 return ("unknown error");
730 return (tpierrs
[err
]);
734 * derive the code from user land inet_top6
735 * convert IPv6 binary address into presentation (printable) format
741 kinet_ntop6(src
, dst
, size
)
747 * Note that int32_t and int16_t need only be "at least" large enough
748 * to contain a value of the specified size. On some systems, like
749 * Crays, there is no such thing as an integer variable with 16 bits.
750 * Keep this in mind if you think this function should have been coded
751 * to use pointer overlays. All the world's not a VAX.
753 char tmp
[sizeof ("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
755 struct { int base
, len
; } best
, cur
;
756 uint_t words
[IN6ADDRSZ
/ INT16SZ
];
758 size_t len
; /* this is used to track the sprintf len */
762 * Copy the input (bytewise) array into a wordwise array.
763 * Find the longest run of 0x00's in src[] for :: shorthanding.
766 bzero(words
, sizeof (words
));
767 for (i
= 0; i
< IN6ADDRSZ
; i
++)
768 words
[i
/ 2] |= (src
[i
] << ((1 - (i
% 2)) << 3));
772 for (i
= 0; i
< (IN6ADDRSZ
/ INT16SZ
); i
++) {
775 cur
.base
= i
, cur
.len
= 1;
779 if (cur
.base
!= -1) {
780 if (best
.base
== -1 || cur
.len
> best
.len
)
786 if (cur
.base
!= -1) {
787 if (best
.base
== -1 || cur
.len
> best
.len
)
791 if (best
.base
!= -1 && best
.len
< 2)
798 for (i
= 0; i
< (IN6ADDRSZ
/ INT16SZ
); i
++) {
799 /* Are we inside the best run of 0x00's? */
800 if (best
.base
!= -1 && i
>= best
.base
&&
801 i
< (best
.base
+ best
.len
)) {
806 /* Are we following an initial run of 0x00s or any real hex? */
809 (void) sprintf(tp
, "%x", words
[i
]);
813 /* Was it a trailing run of 0x00's? */
814 if (best
.base
!= -1 && (best
.base
+ best
.len
) == (IN6ADDRSZ
/ INT16SZ
))
819 * Check for overflow, copy, and we're done.
821 if ((int)(tp
- tmp
) > size
) {
824 (void) strcpy(dst
, tmp
);