1 /* $NetBSD: rpc_generic.c,v 1.4 2000/09/28 09:07:04 kleink Exp $ */ 2 3 /*- 4 * SPDX-License-Identifier: BSD-3-Clause 5 * 6 * Copyright (c) 2009, Sun Microsystems, Inc. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions are met: 11 * - Redistributions of source code must retain the above copyright notice, 12 * this list of conditions and the following disclaimer. 13 * - Redistributions in binary form must reproduce the above copyright notice, 14 * this list of conditions and the following disclaimer in the documentation 15 * and/or other materials provided with the distribution. 16 * - Neither the name of Sun Microsystems, Inc. nor the names of its 17 * contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 /* 33 * Copyright (c) 1986-1991 by Sun Microsystems Inc. 34 */ 35 36 #include <sys/cdefs.h> 37 /* 38 * rpc_generic.c, Miscl routines for RPC. 39 * 40 */ 41 42 #include "opt_inet6.h" 43 44 #include <sys/param.h> 45 #include <sys/kernel.h> 46 #include <sys/malloc.h> 47 #include <sys/mbuf.h> 48 #include <sys/module.h> 49 #include <sys/proc.h> 50 #include <sys/protosw.h> 51 #include <sys/sbuf.h> 52 #include <sys/systm.h> 53 #include <sys/socket.h> 54 #include <sys/socketvar.h> 55 #include <sys/syslog.h> 56 #include <sys/uio.h> 57 58 #include <net/vnet.h> 59 60 #include <rpc/rpc.h> 61 #include <rpc/nettype.h> 62 #include <rpc/rpcsec_gss.h> 63 #include <rpc/rpcsec_tls.h> 64 #include <rpc/clntrdma.h> 65 66 #include <rpc/rpc_com.h> 67 #include <rpc/krpc.h> 68 69 #include <vm/vm.h> 70 #include <vm/pmap.h> 71 #include <vm/vm_param.h> 72 #include <vm/vm_page.h> 73 74 extern u_long sb_max_adj; /* not defined in socketvar.h */ 75 76 /* Provide an entry point hook for the rpcsec_gss module. */ 77 struct rpc_gss_entries rpc_gss_entries; 78 79 struct handle { 80 NCONF_HANDLE *nhandle; 81 int nflag; /* Whether NETPATH or NETCONFIG */ 82 int nettype; 83 }; 84 85 static const struct _rpcnettype { 86 const char *name; 87 const int type; 88 } _rpctypelist[] = { 89 { "netpath", _RPC_NETPATH }, 90 { "visible", _RPC_VISIBLE }, 91 { "circuit_v", _RPC_CIRCUIT_V }, 92 { "datagram_v", _RPC_DATAGRAM_V }, 93 { "circuit_n", _RPC_CIRCUIT_N }, 94 { "datagram_n", _RPC_DATAGRAM_N }, 95 { "tcp", _RPC_TCP }, 96 { "udp", _RPC_UDP }, 97 { 0, _RPC_NONE } 98 }; 99 100 struct netid_af { 101 const char *netid; 102 int af; 103 int protocol; 104 }; 105 106 static const struct netid_af na_cvt[] = { 107 { "udp", AF_INET, IPPROTO_UDP }, 108 { "tcp", AF_INET, IPPROTO_TCP }, 109 #ifdef INET6 110 { "udp6", AF_INET6, IPPROTO_UDP }, 111 { "tcp6", AF_INET6, IPPROTO_TCP }, 112 #endif 113 { "local", AF_LOCAL, 0 } 114 }; 115 116 struct rpc_createerr rpc_createerr; 117 118 /* 119 * Find the appropriate buffer size 120 */ 121 u_int 122 /*ARGSUSED*/ 123 __rpc_get_t_size(int af, int proto, int size) 124 { 125 int defsize; 126 127 switch (proto) { 128 case IPPROTO_TCP: 129 defsize = 64 * 1024; /* XXX */ 130 break; 131 case IPPROTO_UDP: 132 defsize = UDPMSGSIZE; 133 break; 134 default: 135 defsize = RPC_MAXDATASIZE; 136 break; 137 } 138 if (size == 0) 139 return defsize; 140 141 /* Check whether the value is within the upper max limit */ 142 return (size > sb_max_adj ? (u_int)sb_max_adj : (u_int)size); 143 } 144 145 /* 146 * Find the appropriate address buffer size 147 */ 148 u_int 149 __rpc_get_a_size(int af) 150 { 151 switch (af) { 152 case AF_INET: 153 return sizeof (struct sockaddr_in); 154 #ifdef INET6 155 case AF_INET6: 156 return sizeof (struct sockaddr_in6); 157 #endif 158 case AF_LOCAL: 159 return sizeof (struct sockaddr_un); 160 default: 161 break; 162 } 163 return ((u_int)RPC_MAXADDRSIZE); 164 } 165 166 #if 0 167 168 /* 169 * Used to ping the NULL procedure for clnt handle. 170 * Returns NULL if fails, else a non-NULL pointer. 171 */ 172 void * 173 rpc_nullproc(clnt) 174 CLIENT *clnt; 175 { 176 struct timeval TIMEOUT = {25, 0}; 177 178 if (clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void, NULL, 179 (xdrproc_t) xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) { 180 return (NULL); 181 } 182 return ((void *) clnt); 183 } 184 185 #endif 186 187 int 188 __rpc_socket2sockinfo(struct socket *so, struct __rpc_sockinfo *sip) 189 { 190 int type, proto; 191 struct sockaddr_storage ss = { .ss_len = sizeof(ss) }; 192 sa_family_t family; 193 struct sockopt opt; 194 int error; 195 196 error = sosockaddr(so, (struct sockaddr *)&ss); 197 if (error) 198 return 0; 199 200 sip->si_alen = ss.ss_len; 201 family = ss.ss_family; 202 203 opt.sopt_dir = SOPT_GET; 204 opt.sopt_level = SOL_SOCKET; 205 opt.sopt_name = SO_TYPE; 206 opt.sopt_val = &type; 207 opt.sopt_valsize = sizeof type; 208 opt.sopt_td = NULL; 209 error = sogetopt(so, &opt); 210 if (error) 211 return 0; 212 213 /* XXX */ 214 if (family != AF_LOCAL) { 215 if (type == SOCK_STREAM) 216 proto = IPPROTO_TCP; 217 else if (type == SOCK_DGRAM) 218 proto = IPPROTO_UDP; 219 else 220 return 0; 221 } else 222 proto = 0; 223 224 sip->si_af = family; 225 sip->si_proto = proto; 226 sip->si_socktype = type; 227 228 return 1; 229 } 230 231 /* 232 * Linear search, but the number of entries is small. 233 */ 234 int 235 __rpc_nconf2sockinfo(const struct netconfig *nconf, struct __rpc_sockinfo *sip) 236 { 237 int i; 238 239 for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++) 240 if (strcmp(na_cvt[i].netid, nconf->nc_netid) == 0 || ( 241 strcmp(nconf->nc_netid, "unix") == 0 && 242 strcmp(na_cvt[i].netid, "local") == 0)) { 243 sip->si_af = na_cvt[i].af; 244 sip->si_proto = na_cvt[i].protocol; 245 sip->si_socktype = 246 __rpc_seman2socktype((int)nconf->nc_semantics); 247 if (sip->si_socktype == -1) 248 return 0; 249 sip->si_alen = __rpc_get_a_size(sip->si_af); 250 return 1; 251 } 252 253 return 0; 254 } 255 256 struct socket * 257 __rpc_nconf2socket(const struct netconfig *nconf) 258 { 259 struct __rpc_sockinfo si; 260 struct socket *so; 261 int error; 262 263 if (!__rpc_nconf2sockinfo(nconf, &si)) 264 return 0; 265 266 so = NULL; 267 error = socreate(si.si_af, &so, si.si_socktype, si.si_proto, 268 curthread->td_ucred, curthread); 269 270 if (error) 271 return NULL; 272 else 273 return so; 274 } 275 276 char * 277 taddr2uaddr(const struct netconfig *nconf, const struct netbuf *nbuf) 278 { 279 struct __rpc_sockinfo si; 280 281 if (!__rpc_nconf2sockinfo(nconf, &si)) 282 return NULL; 283 return __rpc_taddr2uaddr_af(si.si_af, nbuf); 284 } 285 286 struct netbuf * 287 uaddr2taddr(const struct netconfig *nconf, const char *uaddr) 288 { 289 struct __rpc_sockinfo si; 290 291 if (!__rpc_nconf2sockinfo(nconf, &si)) 292 return NULL; 293 return __rpc_uaddr2taddr_af(si.si_af, uaddr); 294 } 295 296 char * 297 __rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf) 298 { 299 char *ret; 300 struct sbuf sb; 301 struct sockaddr_in *sin; 302 struct sockaddr_un *sun; 303 char namebuf[INET_ADDRSTRLEN]; 304 #ifdef INET6 305 struct sockaddr_in6 *sin6; 306 char namebuf6[INET6_ADDRSTRLEN]; 307 #endif 308 uint16_t port; 309 310 sbuf_new(&sb, NULL, 0, SBUF_AUTOEXTEND); 311 312 switch (af) { 313 case AF_INET: 314 if (nbuf->len < sizeof(*sin)) 315 return NULL; 316 sin = nbuf->buf; 317 if (inet_ntop(af, &sin->sin_addr, namebuf, sizeof namebuf) 318 == NULL) 319 return NULL; 320 port = ntohs(sin->sin_port); 321 if (sbuf_printf(&sb, "%s.%u.%u", namebuf, 322 ((uint32_t)port) >> 8, 323 port & 0xff) < 0) 324 return NULL; 325 break; 326 #ifdef INET6 327 case AF_INET6: 328 if (nbuf->len < sizeof(*sin6)) 329 return NULL; 330 sin6 = nbuf->buf; 331 if (inet_ntop(af, &sin6->sin6_addr, namebuf6, sizeof namebuf6) 332 == NULL) 333 return NULL; 334 port = ntohs(sin6->sin6_port); 335 if (sbuf_printf(&sb, "%s.%u.%u", namebuf6, 336 ((uint32_t)port) >> 8, 337 port & 0xff) < 0) 338 return NULL; 339 break; 340 #endif 341 case AF_LOCAL: 342 sun = nbuf->buf; 343 if (sbuf_printf(&sb, "%.*s", (int)(sun->sun_len - 344 offsetof(struct sockaddr_un, sun_path)), 345 sun->sun_path) < 0) 346 return (NULL); 347 break; 348 default: 349 return NULL; 350 } 351 352 sbuf_finish(&sb); 353 ret = strdup(sbuf_data(&sb), M_RPC); 354 sbuf_delete(&sb); 355 356 return ret; 357 } 358 359 struct netbuf * 360 __rpc_uaddr2taddr_af(int af, const char *uaddr) 361 { 362 struct netbuf *ret = NULL; 363 char *addrstr, *p; 364 unsigned port, portlo, porthi; 365 struct sockaddr_in *sin; 366 #ifdef INET6 367 struct sockaddr_in6 *sin6; 368 #endif 369 struct sockaddr_un *sun; 370 371 port = 0; 372 sin = NULL; 373 374 if (uaddr == NULL) 375 return NULL; 376 377 addrstr = strdup(uaddr, M_RPC); 378 if (addrstr == NULL) 379 return NULL; 380 381 /* 382 * AF_LOCAL addresses are expected to be absolute 383 * pathnames, anything else will be AF_INET or AF_INET6. 384 */ 385 if (*addrstr != '/') { 386 p = strrchr(addrstr, '.'); 387 if (p == NULL) 388 goto out; 389 portlo = (unsigned)strtol(p + 1, NULL, 10); 390 *p = '\0'; 391 392 p = strrchr(addrstr, '.'); 393 if (p == NULL) 394 goto out; 395 porthi = (unsigned)strtol(p + 1, NULL, 10); 396 *p = '\0'; 397 port = (porthi << 8) | portlo; 398 } 399 400 ret = (struct netbuf *)malloc(sizeof *ret, M_RPC, M_WAITOK); 401 402 switch (af) { 403 case AF_INET: 404 sin = (struct sockaddr_in *)malloc(sizeof *sin, M_RPC, 405 M_WAITOK); 406 memset(sin, 0, sizeof *sin); 407 sin->sin_family = AF_INET; 408 sin->sin_port = htons(port); 409 if (inet_pton(AF_INET, addrstr, &sin->sin_addr) <= 0) { 410 free(sin, M_RPC); 411 free(ret, M_RPC); 412 ret = NULL; 413 goto out; 414 } 415 sin->sin_len = ret->maxlen = ret->len = sizeof *sin; 416 ret->buf = sin; 417 break; 418 #ifdef INET6 419 case AF_INET6: 420 sin6 = (struct sockaddr_in6 *)malloc(sizeof *sin6, M_RPC, 421 M_WAITOK); 422 memset(sin6, 0, sizeof *sin6); 423 sin6->sin6_family = AF_INET6; 424 sin6->sin6_port = htons(port); 425 if (inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) <= 0) { 426 free(sin6, M_RPC); 427 free(ret, M_RPC); 428 ret = NULL; 429 goto out; 430 } 431 sin6->sin6_len = ret->maxlen = ret->len = sizeof *sin6; 432 ret->buf = sin6; 433 break; 434 #endif 435 case AF_LOCAL: 436 sun = (struct sockaddr_un *)malloc(sizeof *sun, M_RPC, 437 M_WAITOK); 438 memset(sun, 0, sizeof *sun); 439 sun->sun_family = AF_LOCAL; 440 strncpy(sun->sun_path, addrstr, sizeof(sun->sun_path) - 1); 441 ret->len = ret->maxlen = sun->sun_len = SUN_LEN(sun); 442 ret->buf = sun; 443 break; 444 default: 445 break; 446 } 447 out: 448 free(addrstr, M_RPC); 449 return ret; 450 } 451 452 int 453 __rpc_seman2socktype(int semantics) 454 { 455 switch (semantics) { 456 case NC_TPI_CLTS: 457 return SOCK_DGRAM; 458 case NC_TPI_COTS_ORD: 459 return SOCK_STREAM; 460 case NC_TPI_RAW: 461 return SOCK_RAW; 462 default: 463 break; 464 } 465 466 return -1; 467 } 468 469 int 470 __rpc_socktype2seman(int socktype) 471 { 472 switch (socktype) { 473 case SOCK_DGRAM: 474 return NC_TPI_CLTS; 475 case SOCK_STREAM: 476 return NC_TPI_COTS_ORD; 477 case SOCK_RAW: 478 return NC_TPI_RAW; 479 default: 480 break; 481 } 482 483 return -1; 484 } 485 486 /* 487 * Returns the type of the network as defined in <rpc/nettype.h> 488 * If nettype is NULL, it defaults to NETPATH. 489 */ 490 static int 491 getnettype(const char *nettype) 492 { 493 int i; 494 495 if ((nettype == NULL) || (nettype[0] == 0)) { 496 return (_RPC_NETPATH); /* Default */ 497 } 498 499 #if 0 500 nettype = strlocase(nettype); 501 #endif 502 for (i = 0; _rpctypelist[i].name; i++) 503 if (strcasecmp(nettype, _rpctypelist[i].name) == 0) { 504 return (_rpctypelist[i].type); 505 } 506 return (_rpctypelist[i].type); 507 } 508 509 /* 510 * For the given nettype (tcp or udp only), return the first structure found. 511 * This should be freed by calling freenetconfigent() 512 */ 513 struct netconfig * 514 __rpc_getconfip(const char *nettype) 515 { 516 char *netid; 517 static char *netid_tcp = (char *) NULL; 518 static char *netid_udp = (char *) NULL; 519 struct netconfig *dummy; 520 521 if (!netid_udp && !netid_tcp) { 522 struct netconfig *nconf; 523 void *confighandle; 524 525 if (!(confighandle = setnetconfig())) { 526 log(LOG_ERR, "rpc: failed to open " NETCONFIG); 527 return (NULL); 528 } 529 while ((nconf = getnetconfig(confighandle)) != NULL) { 530 if (strcmp(nconf->nc_protofmly, NC_INET) == 0) { 531 if (strcmp(nconf->nc_proto, NC_TCP) == 0) { 532 netid_tcp = strdup(nconf->nc_netid, 533 M_RPC); 534 } else 535 if (strcmp(nconf->nc_proto, NC_UDP) == 0) { 536 netid_udp = strdup(nconf->nc_netid, 537 M_RPC); 538 } 539 } 540 } 541 endnetconfig(confighandle); 542 } 543 if (strcmp(nettype, "udp") == 0) 544 netid = netid_udp; 545 else if (strcmp(nettype, "tcp") == 0) 546 netid = netid_tcp; 547 else { 548 return (NULL); 549 } 550 if ((netid == NULL) || (netid[0] == 0)) { 551 return (NULL); 552 } 553 dummy = getnetconfigent(netid); 554 return (dummy); 555 } 556 557 /* 558 * Returns the type of the nettype, which should then be used with 559 * __rpc_getconf(). 560 * 561 * For simplicity in the kernel, we don't support the NETPATH 562 * environment variable. We behave as userland would then NETPATH is 563 * unset, i.e. iterate over all visible entries in netconfig. 564 */ 565 void * 566 __rpc_setconf(const char *nettype) 567 { 568 struct handle *handle; 569 570 handle = (struct handle *) malloc(sizeof (struct handle), 571 M_RPC, M_WAITOK); 572 switch (handle->nettype = getnettype(nettype)) { 573 case _RPC_NETPATH: 574 case _RPC_CIRCUIT_N: 575 case _RPC_DATAGRAM_N: 576 if (!(handle->nhandle = setnetconfig())) 577 goto failed; 578 handle->nflag = TRUE; 579 break; 580 case _RPC_VISIBLE: 581 case _RPC_CIRCUIT_V: 582 case _RPC_DATAGRAM_V: 583 case _RPC_TCP: 584 case _RPC_UDP: 585 if (!(handle->nhandle = setnetconfig())) { 586 log(LOG_ERR, "rpc: failed to open " NETCONFIG); 587 goto failed; 588 } 589 handle->nflag = FALSE; 590 break; 591 default: 592 goto failed; 593 } 594 595 return (handle); 596 597 failed: 598 free(handle, M_RPC); 599 return (NULL); 600 } 601 602 /* 603 * Returns the next netconfig struct for the given "net" type. 604 * __rpc_setconf() should have been called previously. 605 */ 606 struct netconfig * 607 __rpc_getconf(void *vhandle) 608 { 609 struct handle *handle; 610 struct netconfig *nconf; 611 612 handle = (struct handle *)vhandle; 613 if (handle == NULL) { 614 return (NULL); 615 } 616 for (;;) { 617 if (handle->nflag) { 618 nconf = getnetconfig(handle->nhandle); 619 if (nconf && !(nconf->nc_flag & NC_VISIBLE)) 620 continue; 621 } else { 622 nconf = getnetconfig(handle->nhandle); 623 } 624 if (nconf == NULL) 625 break; 626 if ((nconf->nc_semantics != NC_TPI_CLTS) && 627 (nconf->nc_semantics != NC_TPI_COTS) && 628 (nconf->nc_semantics != NC_TPI_COTS_ORD)) 629 continue; 630 switch (handle->nettype) { 631 case _RPC_VISIBLE: 632 if (!(nconf->nc_flag & NC_VISIBLE)) 633 continue; 634 /* FALLTHROUGH */ 635 case _RPC_NETPATH: /* Be happy */ 636 break; 637 case _RPC_CIRCUIT_V: 638 if (!(nconf->nc_flag & NC_VISIBLE)) 639 continue; 640 /* FALLTHROUGH */ 641 case _RPC_CIRCUIT_N: 642 if ((nconf->nc_semantics != NC_TPI_COTS) && 643 (nconf->nc_semantics != NC_TPI_COTS_ORD)) 644 continue; 645 break; 646 case _RPC_DATAGRAM_V: 647 if (!(nconf->nc_flag & NC_VISIBLE)) 648 continue; 649 /* FALLTHROUGH */ 650 case _RPC_DATAGRAM_N: 651 if (nconf->nc_semantics != NC_TPI_CLTS) 652 continue; 653 break; 654 case _RPC_TCP: 655 if (((nconf->nc_semantics != NC_TPI_COTS) && 656 (nconf->nc_semantics != NC_TPI_COTS_ORD)) || 657 (strcmp(nconf->nc_protofmly, NC_INET) 658 #ifdef INET6 659 && strcmp(nconf->nc_protofmly, NC_INET6)) 660 #else 661 ) 662 #endif 663 || 664 strcmp(nconf->nc_proto, NC_TCP)) 665 continue; 666 break; 667 case _RPC_UDP: 668 if ((nconf->nc_semantics != NC_TPI_CLTS) || 669 (strcmp(nconf->nc_protofmly, NC_INET) 670 #ifdef INET6 671 && strcmp(nconf->nc_protofmly, NC_INET6)) 672 #else 673 ) 674 #endif 675 || 676 strcmp(nconf->nc_proto, NC_UDP)) 677 continue; 678 break; 679 } 680 break; 681 } 682 return (nconf); 683 } 684 685 void 686 __rpc_endconf(void *vhandle) 687 { 688 struct handle *handle; 689 690 handle = (struct handle *) vhandle; 691 if (handle == NULL) { 692 return; 693 } 694 endnetconfig(handle->nhandle); 695 free(handle, M_RPC); 696 } 697 698 int 699 __rpc_sockisbound(struct socket *so) 700 { 701 struct sockaddr_storage ss = { .ss_len = sizeof(ss) }; 702 int error, bound; 703 704 error = sosockaddr(so, (struct sockaddr *)&ss); 705 if (error) 706 return (0); 707 708 switch (ss.ss_family) { 709 case AF_INET: 710 bound = (((struct sockaddr_in *)&ss)->sin_port != 0); 711 break; 712 #ifdef INET6 713 case AF_INET6: 714 bound = (((struct sockaddr_in6 *)&ss)->sin6_port != 0); 715 break; 716 #endif 717 case AF_LOCAL: 718 /* XXX check this */ 719 bound = (((struct sockaddr_un *)&ss)->sun_path[0] != '\0'); 720 break; 721 default: 722 bound = FALSE; 723 break; 724 } 725 726 return bound; 727 } 728 729 /* 730 * Implement XDR-style API for RPC call. 731 */ 732 enum clnt_stat 733 clnt_call_private( 734 CLIENT *cl, /* client handle */ 735 struct rpc_callextra *ext, /* call metadata */ 736 rpcproc_t proc, /* procedure number */ 737 xdrproc_t xargs, /* xdr routine for args */ 738 void *argsp, /* pointer to args */ 739 xdrproc_t xresults, /* xdr routine for results */ 740 void *resultsp, /* pointer to results */ 741 struct timeval utimeout) /* seconds to wait before giving up */ 742 { 743 XDR xdrs; 744 struct mbuf *mreq; 745 struct mbuf *mrep; 746 enum clnt_stat stat; 747 748 mreq = m_getcl(M_WAITOK, MT_DATA, 0); 749 750 xdrmbuf_create(&xdrs, mreq, XDR_ENCODE); 751 if (!xargs(&xdrs, argsp)) { 752 m_freem(mreq); 753 return (RPC_CANTENCODEARGS); 754 } 755 XDR_DESTROY(&xdrs); 756 757 stat = CLNT_CALL_MBUF(cl, ext, proc, mreq, &mrep, utimeout); 758 m_freem(mreq); 759 760 if (stat == RPC_SUCCESS) { 761 xdrmbuf_create(&xdrs, mrep, XDR_DECODE); 762 if (!xresults(&xdrs, resultsp)) { 763 XDR_DESTROY(&xdrs); 764 return (RPC_CANTDECODERES); 765 } 766 XDR_DESTROY(&xdrs); 767 } 768 769 return (stat); 770 } 771 772 /* 773 * Bind a socket to a privileged IP port 774 */ 775 int 776 bindresvport(struct socket *so, struct sockaddr *sa) 777 { 778 struct sockaddr_storage ss = { .ss_len = sizeof(ss) }; 779 int old, error, af; 780 struct sockaddr_in *sin; 781 #ifdef INET6 782 struct sockaddr_in6 *sin6; 783 #endif 784 struct sockopt opt; 785 int proto, portrange, portlow; 786 uint16_t *portp; 787 socklen_t salen; 788 789 if (sa == NULL) { 790 sa = (struct sockaddr *)&ss; 791 error = sosockaddr(so, sa); 792 if (error) 793 return (error); 794 af = sa->sa_family; 795 salen = sa->sa_len; 796 memset(sa, 0, sa->sa_len); 797 } else { 798 af = sa->sa_family; 799 salen = sa->sa_len; 800 } 801 802 switch (af) { 803 case AF_INET: 804 proto = IPPROTO_IP; 805 portrange = IP_PORTRANGE; 806 portlow = IP_PORTRANGE_LOW; 807 sin = (struct sockaddr_in *)sa; 808 portp = &sin->sin_port; 809 break; 810 #ifdef INET6 811 case AF_INET6: 812 proto = IPPROTO_IPV6; 813 portrange = IPV6_PORTRANGE; 814 portlow = IPV6_PORTRANGE_LOW; 815 sin6 = (struct sockaddr_in6 *)sa; 816 portp = &sin6->sin6_port; 817 break; 818 #endif 819 default: 820 return (EPFNOSUPPORT); 821 } 822 823 sa->sa_family = af; 824 sa->sa_len = salen; 825 826 if (*portp == 0) { 827 bzero(&opt, sizeof(opt)); 828 opt.sopt_dir = SOPT_GET; 829 opt.sopt_level = proto; 830 opt.sopt_name = portrange; 831 opt.sopt_val = &old; 832 opt.sopt_valsize = sizeof(old); 833 error = sogetopt(so, &opt); 834 if (error) 835 return (error); 836 837 opt.sopt_dir = SOPT_SET; 838 opt.sopt_val = &portlow; 839 error = sosetopt(so, &opt); 840 if (error) 841 return (error); 842 } 843 844 error = sobind(so, sa, curthread); 845 846 if (*portp == 0) { 847 if (error) { 848 opt.sopt_dir = SOPT_SET; 849 opt.sopt_val = &old; 850 sosetopt(so, &opt); 851 } 852 } 853 854 return (error); 855 } 856 857 /* 858 * Make sure an mbuf list is made up entirely of ext_pgs mbufs. 859 * This is needed for sosend() when KERN_TLS is being used. 860 * (There might also be a performance improvement for certain 861 * network interfaces that handle ext_pgs mbufs efficiently.) 862 * It expects at least one non-ext_pgs mbuf followed by zero 863 * or more ext_pgs mbufs. It does not handle the case where 864 * non-ext_pgs mbuf(s) follow ext_pgs ones. 865 * It also performs sanity checks on the resultant list. 866 * The "mp" argument list is consumed. 867 * The "maxextsiz" argument is the upper bound on the data 868 * size for each mbuf (usually 16K for KERN_TLS). 869 */ 870 struct mbuf * 871 _rpc_copym_into_ext_pgs(struct mbuf *mp, int maxextsiz) 872 { 873 struct mbuf *m, *m2, *m3, *mhead; 874 int tlen; 875 876 KASSERT((mp->m_flags & (M_EXT | M_EXTPG)) != 877 (M_EXT | M_EXTPG), ("_rpc_copym_into_ext_pgs:" 878 " first mbuf is an ext_pgs")); 879 /* 880 * Find the last non-ext_pgs mbuf and the total 881 * length of the non-ext_pgs mbuf(s). 882 * The first mbuf must always be a non-ext_pgs 883 * mbuf. 884 */ 885 tlen = mp->m_len; 886 m2 = mp; 887 for (m = mp->m_next; m != NULL; m = m->m_next) { 888 if ((m->m_flags & M_EXTPG) != 0) 889 break; 890 tlen += m->m_len; 891 m2 = m; 892 } 893 894 /* 895 * Copy the non-ext_pgs mbuf(s) into an ext_pgs 896 * mbuf list. 897 */ 898 m2->m_next = NULL; 899 mhead = mb_mapped_to_unmapped(mp, tlen, maxextsiz, 900 M_WAITOK, &m2); 901 902 /* 903 * Link the ext_pgs list onto the newly copied 904 * list and free up the non-ext_pgs mbuf(s). 905 */ 906 m2->m_next = m; 907 m_freem(mp); 908 909 /* 910 * Sanity check the resultant mbuf list. Check for and 911 * remove any 0 length mbufs in the list, since the 912 * KERN_TLS code does not expect any 0 length mbuf(s) 913 * in the list. 914 */ 915 m3 = NULL; 916 m2 = mhead; 917 tlen = 0; 918 while (m2 != NULL) { 919 KASSERT(m2->m_len >= 0, ("_rpc_copym_into_ext_pgs:" 920 " negative m_len")); 921 KASSERT((m2->m_flags & (M_EXT | M_EXTPG)) == 922 (M_EXT | M_EXTPG), ("_rpc_copym_into_ext_pgs:" 923 " non-nomap mbuf in list")); 924 if (m2->m_len == 0) { 925 if (m3 != NULL) 926 m3->m_next = m2->m_next; 927 else 928 m = m2->m_next; 929 m2->m_next = NULL; 930 m_free(m2); 931 if (m3 != NULL) 932 m2 = m3->m_next; 933 else 934 m2 = m; 935 } else { 936 MBUF_EXT_PGS_ASSERT_SANITY(m2); 937 m3 = m2; 938 tlen += m2->m_len; 939 m2 = m2->m_next; 940 } 941 } 942 return (mhead); 943 } 944 945 /* 946 * Create an mr mbuf and associated pages. 947 */ 948 struct mbuf * 949 rpc_reduce_pg(int len, int pos, bool to_mem) 950 { 951 struct mbuf *mr; 952 struct rpcrdma_reduce_pg *rb; 953 int i; 954 955 i = howmany(len, PAGE_SIZE); 956 mr = m_get2(sizeof(*rb) + sizeof(vm_page_t) * i, M_WAITOK, MT_DATA, 0); 957 mr->m_flags |= M_PROTO10; 958 mr->m_len = sizeof(*rb) + sizeof(vm_page_t) * i; 959 rb = mtod(mr, struct rpcrdma_reduce_pg *); 960 rb->len = len; 961 rb->npg = i; 962 rb->pos = pos; 963 for (i = 0; i < rb->npg; i++) 964 rb->pg[i] = vm_page_alloc_noobj(VM_ALLOC_WAITOK | 965 VM_ALLOC_NODUMP | VM_ALLOC_WIRED); 966 rb->into_mem = (to_mem) ? 1 : 0; 967 return (mr); 968 } 969 970 void 971 rpc_free_rdma_reduction(struct mbuf *mr) 972 { 973 struct rpcrdma_reduce_pg *rb; 974 int i; 975 976 rb = mtod(mr, struct rpcrdma_reduce_pg *); 977 for (i = 0; i < rb->npg; i++) { 978 vm_page_unwire_noq(rb->pg[i]); 979 vm_page_free(rb->pg[i]); 980 } 981 m_free(mr); 982 } 983 984 /* 985 * Copy data between anonymous pages and uiop. 986 */ 987 int 988 rpc_copy_uio_pages(struct mbuf *mr, struct uio *uiop, int siz, bool from_pages) 989 { 990 struct rpcrdma_reduce_pg *rb; 991 char *cp, *uiocp; 992 int error, left, len, i, uiosiz, xfer; 993 994 rb = mtod(mr, struct rpcrdma_reduce_pg *); 995 if (siz > rb->len) 996 return (EBADRPC); 997 i = 0; 998 cp = PHYS_TO_DMAP(VM_PAGE_TO_PHYS(rb->pg[i])); 999 len = PAGE_SIZE; 1000 if (i == rb->npg - 1 && siz < PAGE_SIZE) 1001 len = siz; 1002 while (siz > 0) { 1003 if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL) 1004 return (EBADRPC); 1005 left = uiop->uio_iov->iov_len; 1006 uiocp = uiop->uio_iov->iov_base; 1007 if (left > siz) 1008 left = siz; 1009 uiosiz = left; 1010 while (left > 0) { 1011 if (len == 0) { 1012 if (i == rb->npg - 1) 1013 return (EBADRPC); 1014 i++; 1015 cp = PHYS_TO_DMAP( 1016 VM_PAGE_TO_PHYS(rb->pg[i])); 1017 len = PAGE_SIZE; 1018 if (i == rb->npg - 1 && siz < PAGE_SIZE) 1019 len = siz; 1020 } 1021 xfer = (left > len) ? len : left; 1022 if (from_pages) { 1023 if (uiop->uio_segflg == UIO_SYSSPACE) { 1024 memcpy(uiocp, cp, xfer); 1025 } else { 1026 error = copyout(cp, uiocp, xfer); 1027 if (error != 0) 1028 return (EBADRPC); 1029 } 1030 } else { 1031 if (uiop->uio_segflg == UIO_SYSSPACE) { 1032 memcpy(cp, uiocp, xfer); 1033 } else { 1034 error = copyout(uiocp, cp, xfer); 1035 if (error != 0) 1036 return (EBADRPC); 1037 } 1038 } 1039 left -= xfer; 1040 len -= xfer; 1041 cp += xfer; 1042 uiocp += xfer; 1043 uiop->uio_offset += xfer; 1044 uiop->uio_resid -= xfer; 1045 } 1046 if (uiop->uio_iov->iov_len <= siz) { 1047 uiop->uio_iovcnt--; 1048 uiop->uio_iov++; 1049 } else { 1050 uiop->uio_iov->iov_base = (void *) 1051 ((char *)uiop->uio_iov->iov_base + uiosiz); 1052 uiop->uio_iov->iov_len -= uiosiz; 1053 } 1054 siz -= uiosiz; 1055 } 1056 return (0); 1057 } 1058 1059 /* 1060 * Copy data from an mbuf list into a list of pages in an rb. 1061 */ 1062 void 1063 rpc_copy_mbuf_to_rb(struct mbuf *m, struct rpcrdma_reduce_pg *rb) 1064 { 1065 int i, j, k, plen; 1066 char *cp, *pgp; 1067 1068 j = m->m_len; 1069 cp = mtod(m, char *); 1070 for (i = 0; i < rb->npg && m != NULL; i++) { 1071 pgp = PHYS_TO_DMAP(VM_PAGE_TO_PHYS(rb->pg[i])); 1072 for (plen = PAGE_SIZE; plen > 0; ) { 1073 k = MIN(j, plen); 1074 memcpy(pgp, cp, k); 1075 j -= k; 1076 plen -= k; 1077 pgp += k; 1078 cp += k; 1079 if (j == 0) { 1080 m = m->m_next; 1081 while (m != NULL && m->m_len == 0) 1082 m = m->m_next; 1083 if (m == NULL) 1084 break; 1085 cp = mtod(m, char *); 1086 j = m->m_len; 1087 } 1088 } 1089 } 1090 } 1091 1092 /* 1093 * Kernel module glue 1094 */ 1095 static int 1096 krpc_modevent(module_t mod, int type, void *data) 1097 { 1098 int error = 0; 1099 1100 switch (type) { 1101 case MOD_LOAD: 1102 rpcnl_init(); 1103 error = rpctls_init(); 1104 break; 1105 case MOD_UNLOAD: 1106 /* 1107 * Cannot be unloaded, since the rpctlssd or rpctlscd daemons 1108 * might be performing a rpctls syscall. 1109 */ 1110 /* FALLTHROUGH */ 1111 default: 1112 error = EOPNOTSUPP; 1113 } 1114 return (error); 1115 } 1116 static moduledata_t krpc_mod = { 1117 "krpc", 1118 krpc_modevent, 1119 NULL, 1120 }; 1121 DECLARE_MODULE(krpc, krpc_mod, SI_SUB_VFS, SI_ORDER_FIRST); 1122 1123 /* So that loader and kldload(2) can find us, wherever we are.. */ 1124 MODULE_VERSION(krpc, 1); 1125 MODULE_DEPEND(krpc, xdr, 1, 1, 1); 1126