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 57 #include <net/vnet.h> 58 59 #include <rpc/rpc.h> 60 #include <rpc/nettype.h> 61 #include <rpc/rpcsec_gss.h> 62 #include <rpc/rpcsec_tls.h> 63 64 #include <rpc/rpc_com.h> 65 #include <rpc/krpc.h> 66 67 #include <vm/vm.h> 68 #include <vm/pmap.h> 69 #include <vm/vm_param.h> 70 71 extern u_long sb_max_adj; /* not defined in socketvar.h */ 72 73 /* Provide an entry point hook for the rpcsec_gss module. */ 74 struct rpc_gss_entries rpc_gss_entries; 75 76 struct handle { 77 NCONF_HANDLE *nhandle; 78 int nflag; /* Whether NETPATH or NETCONFIG */ 79 int nettype; 80 }; 81 82 static const struct _rpcnettype { 83 const char *name; 84 const int type; 85 } _rpctypelist[] = { 86 { "netpath", _RPC_NETPATH }, 87 { "visible", _RPC_VISIBLE }, 88 { "circuit_v", _RPC_CIRCUIT_V }, 89 { "datagram_v", _RPC_DATAGRAM_V }, 90 { "circuit_n", _RPC_CIRCUIT_N }, 91 { "datagram_n", _RPC_DATAGRAM_N }, 92 { "tcp", _RPC_TCP }, 93 { "udp", _RPC_UDP }, 94 { 0, _RPC_NONE } 95 }; 96 97 struct netid_af { 98 const char *netid; 99 int af; 100 int protocol; 101 }; 102 103 static const struct netid_af na_cvt[] = { 104 { "udp", AF_INET, IPPROTO_UDP }, 105 { "tcp", AF_INET, IPPROTO_TCP }, 106 #ifdef INET6 107 { "udp6", AF_INET6, IPPROTO_UDP }, 108 { "tcp6", AF_INET6, IPPROTO_TCP }, 109 #endif 110 { "local", AF_LOCAL, 0 } 111 }; 112 113 struct rpc_createerr rpc_createerr; 114 115 /* 116 * Find the appropriate buffer size 117 */ 118 u_int 119 /*ARGSUSED*/ 120 __rpc_get_t_size(int af, int proto, int size) 121 { 122 int defsize; 123 124 switch (proto) { 125 case IPPROTO_TCP: 126 defsize = 64 * 1024; /* XXX */ 127 break; 128 case IPPROTO_UDP: 129 defsize = UDPMSGSIZE; 130 break; 131 default: 132 defsize = RPC_MAXDATASIZE; 133 break; 134 } 135 if (size == 0) 136 return defsize; 137 138 /* Check whether the value is within the upper max limit */ 139 return (size > sb_max_adj ? (u_int)sb_max_adj : (u_int)size); 140 } 141 142 /* 143 * Find the appropriate address buffer size 144 */ 145 u_int 146 __rpc_get_a_size(int af) 147 { 148 switch (af) { 149 case AF_INET: 150 return sizeof (struct sockaddr_in); 151 #ifdef INET6 152 case AF_INET6: 153 return sizeof (struct sockaddr_in6); 154 #endif 155 case AF_LOCAL: 156 return sizeof (struct sockaddr_un); 157 default: 158 break; 159 } 160 return ((u_int)RPC_MAXADDRSIZE); 161 } 162 163 #if 0 164 165 /* 166 * Used to ping the NULL procedure for clnt handle. 167 * Returns NULL if fails, else a non-NULL pointer. 168 */ 169 void * 170 rpc_nullproc(clnt) 171 CLIENT *clnt; 172 { 173 struct timeval TIMEOUT = {25, 0}; 174 175 if (clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void, NULL, 176 (xdrproc_t) xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) { 177 return (NULL); 178 } 179 return ((void *) clnt); 180 } 181 182 #endif 183 184 int 185 __rpc_socket2sockinfo(struct socket *so, struct __rpc_sockinfo *sip) 186 { 187 int type, proto; 188 struct sockaddr_storage ss = { .ss_len = sizeof(ss) }; 189 sa_family_t family; 190 struct sockopt opt; 191 int error; 192 193 error = sosockaddr(so, (struct sockaddr *)&ss); 194 if (error) 195 return 0; 196 197 sip->si_alen = ss.ss_len; 198 family = ss.ss_family; 199 200 opt.sopt_dir = SOPT_GET; 201 opt.sopt_level = SOL_SOCKET; 202 opt.sopt_name = SO_TYPE; 203 opt.sopt_val = &type; 204 opt.sopt_valsize = sizeof type; 205 opt.sopt_td = NULL; 206 error = sogetopt(so, &opt); 207 if (error) 208 return 0; 209 210 /* XXX */ 211 if (family != AF_LOCAL) { 212 if (type == SOCK_STREAM) 213 proto = IPPROTO_TCP; 214 else if (type == SOCK_DGRAM) 215 proto = IPPROTO_UDP; 216 else 217 return 0; 218 } else 219 proto = 0; 220 221 sip->si_af = family; 222 sip->si_proto = proto; 223 sip->si_socktype = type; 224 225 return 1; 226 } 227 228 /* 229 * Linear search, but the number of entries is small. 230 */ 231 int 232 __rpc_nconf2sockinfo(const struct netconfig *nconf, struct __rpc_sockinfo *sip) 233 { 234 int i; 235 236 for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++) 237 if (strcmp(na_cvt[i].netid, nconf->nc_netid) == 0 || ( 238 strcmp(nconf->nc_netid, "unix") == 0 && 239 strcmp(na_cvt[i].netid, "local") == 0)) { 240 sip->si_af = na_cvt[i].af; 241 sip->si_proto = na_cvt[i].protocol; 242 sip->si_socktype = 243 __rpc_seman2socktype((int)nconf->nc_semantics); 244 if (sip->si_socktype == -1) 245 return 0; 246 sip->si_alen = __rpc_get_a_size(sip->si_af); 247 return 1; 248 } 249 250 return 0; 251 } 252 253 struct socket * 254 __rpc_nconf2socket(const struct netconfig *nconf) 255 { 256 struct __rpc_sockinfo si; 257 struct socket *so; 258 int error; 259 260 if (!__rpc_nconf2sockinfo(nconf, &si)) 261 return 0; 262 263 so = NULL; 264 error = socreate(si.si_af, &so, si.si_socktype, si.si_proto, 265 curthread->td_ucred, curthread); 266 267 if (error) 268 return NULL; 269 else 270 return so; 271 } 272 273 char * 274 taddr2uaddr(const struct netconfig *nconf, const struct netbuf *nbuf) 275 { 276 struct __rpc_sockinfo si; 277 278 if (!__rpc_nconf2sockinfo(nconf, &si)) 279 return NULL; 280 return __rpc_taddr2uaddr_af(si.si_af, nbuf); 281 } 282 283 struct netbuf * 284 uaddr2taddr(const struct netconfig *nconf, const char *uaddr) 285 { 286 struct __rpc_sockinfo si; 287 288 if (!__rpc_nconf2sockinfo(nconf, &si)) 289 return NULL; 290 return __rpc_uaddr2taddr_af(si.si_af, uaddr); 291 } 292 293 char * 294 __rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf) 295 { 296 char *ret; 297 struct sbuf sb; 298 struct sockaddr_in *sin; 299 struct sockaddr_un *sun; 300 char namebuf[INET_ADDRSTRLEN]; 301 #ifdef INET6 302 struct sockaddr_in6 *sin6; 303 char namebuf6[INET6_ADDRSTRLEN]; 304 #endif 305 uint16_t port; 306 307 sbuf_new(&sb, NULL, 0, SBUF_AUTOEXTEND); 308 309 switch (af) { 310 case AF_INET: 311 if (nbuf->len < sizeof(*sin)) 312 return NULL; 313 sin = nbuf->buf; 314 if (inet_ntop(af, &sin->sin_addr, namebuf, sizeof namebuf) 315 == NULL) 316 return NULL; 317 port = ntohs(sin->sin_port); 318 if (sbuf_printf(&sb, "%s.%u.%u", namebuf, 319 ((uint32_t)port) >> 8, 320 port & 0xff) < 0) 321 return NULL; 322 break; 323 #ifdef INET6 324 case AF_INET6: 325 if (nbuf->len < sizeof(*sin6)) 326 return NULL; 327 sin6 = nbuf->buf; 328 if (inet_ntop(af, &sin6->sin6_addr, namebuf6, sizeof namebuf6) 329 == NULL) 330 return NULL; 331 port = ntohs(sin6->sin6_port); 332 if (sbuf_printf(&sb, "%s.%u.%u", namebuf6, 333 ((uint32_t)port) >> 8, 334 port & 0xff) < 0) 335 return NULL; 336 break; 337 #endif 338 case AF_LOCAL: 339 sun = nbuf->buf; 340 if (sbuf_printf(&sb, "%.*s", (int)(sun->sun_len - 341 offsetof(struct sockaddr_un, sun_path)), 342 sun->sun_path) < 0) 343 return (NULL); 344 break; 345 default: 346 return NULL; 347 } 348 349 sbuf_finish(&sb); 350 ret = strdup(sbuf_data(&sb), M_RPC); 351 sbuf_delete(&sb); 352 353 return ret; 354 } 355 356 struct netbuf * 357 __rpc_uaddr2taddr_af(int af, const char *uaddr) 358 { 359 struct netbuf *ret = NULL; 360 char *addrstr, *p; 361 unsigned port, portlo, porthi; 362 struct sockaddr_in *sin; 363 #ifdef INET6 364 struct sockaddr_in6 *sin6; 365 #endif 366 struct sockaddr_un *sun; 367 368 port = 0; 369 sin = NULL; 370 371 if (uaddr == NULL) 372 return NULL; 373 374 addrstr = strdup(uaddr, M_RPC); 375 if (addrstr == NULL) 376 return NULL; 377 378 /* 379 * AF_LOCAL addresses are expected to be absolute 380 * pathnames, anything else will be AF_INET or AF_INET6. 381 */ 382 if (*addrstr != '/') { 383 p = strrchr(addrstr, '.'); 384 if (p == NULL) 385 goto out; 386 portlo = (unsigned)strtol(p + 1, NULL, 10); 387 *p = '\0'; 388 389 p = strrchr(addrstr, '.'); 390 if (p == NULL) 391 goto out; 392 porthi = (unsigned)strtol(p + 1, NULL, 10); 393 *p = '\0'; 394 port = (porthi << 8) | portlo; 395 } 396 397 ret = (struct netbuf *)malloc(sizeof *ret, M_RPC, M_WAITOK); 398 399 switch (af) { 400 case AF_INET: 401 sin = (struct sockaddr_in *)malloc(sizeof *sin, M_RPC, 402 M_WAITOK); 403 memset(sin, 0, sizeof *sin); 404 sin->sin_family = AF_INET; 405 sin->sin_port = htons(port); 406 if (inet_pton(AF_INET, addrstr, &sin->sin_addr) <= 0) { 407 free(sin, M_RPC); 408 free(ret, M_RPC); 409 ret = NULL; 410 goto out; 411 } 412 sin->sin_len = ret->maxlen = ret->len = sizeof *sin; 413 ret->buf = sin; 414 break; 415 #ifdef INET6 416 case AF_INET6: 417 sin6 = (struct sockaddr_in6 *)malloc(sizeof *sin6, M_RPC, 418 M_WAITOK); 419 memset(sin6, 0, sizeof *sin6); 420 sin6->sin6_family = AF_INET6; 421 sin6->sin6_port = htons(port); 422 if (inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) <= 0) { 423 free(sin6, M_RPC); 424 free(ret, M_RPC); 425 ret = NULL; 426 goto out; 427 } 428 sin6->sin6_len = ret->maxlen = ret->len = sizeof *sin6; 429 ret->buf = sin6; 430 break; 431 #endif 432 case AF_LOCAL: 433 sun = (struct sockaddr_un *)malloc(sizeof *sun, M_RPC, 434 M_WAITOK); 435 memset(sun, 0, sizeof *sun); 436 sun->sun_family = AF_LOCAL; 437 strncpy(sun->sun_path, addrstr, sizeof(sun->sun_path) - 1); 438 ret->len = ret->maxlen = sun->sun_len = SUN_LEN(sun); 439 ret->buf = sun; 440 break; 441 default: 442 break; 443 } 444 out: 445 free(addrstr, M_RPC); 446 return ret; 447 } 448 449 int 450 __rpc_seman2socktype(int semantics) 451 { 452 switch (semantics) { 453 case NC_TPI_CLTS: 454 return SOCK_DGRAM; 455 case NC_TPI_COTS_ORD: 456 return SOCK_STREAM; 457 case NC_TPI_RAW: 458 return SOCK_RAW; 459 default: 460 break; 461 } 462 463 return -1; 464 } 465 466 int 467 __rpc_socktype2seman(int socktype) 468 { 469 switch (socktype) { 470 case SOCK_DGRAM: 471 return NC_TPI_CLTS; 472 case SOCK_STREAM: 473 return NC_TPI_COTS_ORD; 474 case SOCK_RAW: 475 return NC_TPI_RAW; 476 default: 477 break; 478 } 479 480 return -1; 481 } 482 483 /* 484 * Returns the type of the network as defined in <rpc/nettype.h> 485 * If nettype is NULL, it defaults to NETPATH. 486 */ 487 static int 488 getnettype(const char *nettype) 489 { 490 int i; 491 492 if ((nettype == NULL) || (nettype[0] == 0)) { 493 return (_RPC_NETPATH); /* Default */ 494 } 495 496 #if 0 497 nettype = strlocase(nettype); 498 #endif 499 for (i = 0; _rpctypelist[i].name; i++) 500 if (strcasecmp(nettype, _rpctypelist[i].name) == 0) { 501 return (_rpctypelist[i].type); 502 } 503 return (_rpctypelist[i].type); 504 } 505 506 /* 507 * For the given nettype (tcp or udp only), return the first structure found. 508 * This should be freed by calling freenetconfigent() 509 */ 510 struct netconfig * 511 __rpc_getconfip(const char *nettype) 512 { 513 char *netid; 514 static char *netid_tcp = (char *) NULL; 515 static char *netid_udp = (char *) NULL; 516 struct netconfig *dummy; 517 518 if (!netid_udp && !netid_tcp) { 519 struct netconfig *nconf; 520 void *confighandle; 521 522 if (!(confighandle = setnetconfig())) { 523 log(LOG_ERR, "rpc: failed to open " NETCONFIG); 524 return (NULL); 525 } 526 while ((nconf = getnetconfig(confighandle)) != NULL) { 527 if (strcmp(nconf->nc_protofmly, NC_INET) == 0) { 528 if (strcmp(nconf->nc_proto, NC_TCP) == 0) { 529 netid_tcp = strdup(nconf->nc_netid, 530 M_RPC); 531 } else 532 if (strcmp(nconf->nc_proto, NC_UDP) == 0) { 533 netid_udp = strdup(nconf->nc_netid, 534 M_RPC); 535 } 536 } 537 } 538 endnetconfig(confighandle); 539 } 540 if (strcmp(nettype, "udp") == 0) 541 netid = netid_udp; 542 else if (strcmp(nettype, "tcp") == 0) 543 netid = netid_tcp; 544 else { 545 return (NULL); 546 } 547 if ((netid == NULL) || (netid[0] == 0)) { 548 return (NULL); 549 } 550 dummy = getnetconfigent(netid); 551 return (dummy); 552 } 553 554 /* 555 * Returns the type of the nettype, which should then be used with 556 * __rpc_getconf(). 557 * 558 * For simplicity in the kernel, we don't support the NETPATH 559 * environment variable. We behave as userland would then NETPATH is 560 * unset, i.e. iterate over all visible entries in netconfig. 561 */ 562 void * 563 __rpc_setconf(const char *nettype) 564 { 565 struct handle *handle; 566 567 handle = (struct handle *) malloc(sizeof (struct handle), 568 M_RPC, M_WAITOK); 569 switch (handle->nettype = getnettype(nettype)) { 570 case _RPC_NETPATH: 571 case _RPC_CIRCUIT_N: 572 case _RPC_DATAGRAM_N: 573 if (!(handle->nhandle = setnetconfig())) 574 goto failed; 575 handle->nflag = TRUE; 576 break; 577 case _RPC_VISIBLE: 578 case _RPC_CIRCUIT_V: 579 case _RPC_DATAGRAM_V: 580 case _RPC_TCP: 581 case _RPC_UDP: 582 if (!(handle->nhandle = setnetconfig())) { 583 log(LOG_ERR, "rpc: failed to open " NETCONFIG); 584 goto failed; 585 } 586 handle->nflag = FALSE; 587 break; 588 default: 589 goto failed; 590 } 591 592 return (handle); 593 594 failed: 595 free(handle, M_RPC); 596 return (NULL); 597 } 598 599 /* 600 * Returns the next netconfig struct for the given "net" type. 601 * __rpc_setconf() should have been called previously. 602 */ 603 struct netconfig * 604 __rpc_getconf(void *vhandle) 605 { 606 struct handle *handle; 607 struct netconfig *nconf; 608 609 handle = (struct handle *)vhandle; 610 if (handle == NULL) { 611 return (NULL); 612 } 613 for (;;) { 614 if (handle->nflag) { 615 nconf = getnetconfig(handle->nhandle); 616 if (nconf && !(nconf->nc_flag & NC_VISIBLE)) 617 continue; 618 } else { 619 nconf = getnetconfig(handle->nhandle); 620 } 621 if (nconf == NULL) 622 break; 623 if ((nconf->nc_semantics != NC_TPI_CLTS) && 624 (nconf->nc_semantics != NC_TPI_COTS) && 625 (nconf->nc_semantics != NC_TPI_COTS_ORD)) 626 continue; 627 switch (handle->nettype) { 628 case _RPC_VISIBLE: 629 if (!(nconf->nc_flag & NC_VISIBLE)) 630 continue; 631 /* FALLTHROUGH */ 632 case _RPC_NETPATH: /* Be happy */ 633 break; 634 case _RPC_CIRCUIT_V: 635 if (!(nconf->nc_flag & NC_VISIBLE)) 636 continue; 637 /* FALLTHROUGH */ 638 case _RPC_CIRCUIT_N: 639 if ((nconf->nc_semantics != NC_TPI_COTS) && 640 (nconf->nc_semantics != NC_TPI_COTS_ORD)) 641 continue; 642 break; 643 case _RPC_DATAGRAM_V: 644 if (!(nconf->nc_flag & NC_VISIBLE)) 645 continue; 646 /* FALLTHROUGH */ 647 case _RPC_DATAGRAM_N: 648 if (nconf->nc_semantics != NC_TPI_CLTS) 649 continue; 650 break; 651 case _RPC_TCP: 652 if (((nconf->nc_semantics != NC_TPI_COTS) && 653 (nconf->nc_semantics != NC_TPI_COTS_ORD)) || 654 (strcmp(nconf->nc_protofmly, NC_INET) 655 #ifdef INET6 656 && strcmp(nconf->nc_protofmly, NC_INET6)) 657 #else 658 ) 659 #endif 660 || 661 strcmp(nconf->nc_proto, NC_TCP)) 662 continue; 663 break; 664 case _RPC_UDP: 665 if ((nconf->nc_semantics != NC_TPI_CLTS) || 666 (strcmp(nconf->nc_protofmly, NC_INET) 667 #ifdef INET6 668 && strcmp(nconf->nc_protofmly, NC_INET6)) 669 #else 670 ) 671 #endif 672 || 673 strcmp(nconf->nc_proto, NC_UDP)) 674 continue; 675 break; 676 } 677 break; 678 } 679 return (nconf); 680 } 681 682 void 683 __rpc_endconf(void *vhandle) 684 { 685 struct handle *handle; 686 687 handle = (struct handle *) vhandle; 688 if (handle == NULL) { 689 return; 690 } 691 endnetconfig(handle->nhandle); 692 free(handle, M_RPC); 693 } 694 695 int 696 __rpc_sockisbound(struct socket *so) 697 { 698 struct sockaddr_storage ss = { .ss_len = sizeof(ss) }; 699 int error, bound; 700 701 error = sosockaddr(so, (struct sockaddr *)&ss); 702 if (error) 703 return (0); 704 705 switch (ss.ss_family) { 706 case AF_INET: 707 bound = (((struct sockaddr_in *)&ss)->sin_port != 0); 708 break; 709 #ifdef INET6 710 case AF_INET6: 711 bound = (((struct sockaddr_in6 *)&ss)->sin6_port != 0); 712 break; 713 #endif 714 case AF_LOCAL: 715 /* XXX check this */ 716 bound = (((struct sockaddr_un *)&ss)->sun_path[0] != '\0'); 717 break; 718 default: 719 bound = FALSE; 720 break; 721 } 722 723 return bound; 724 } 725 726 /* 727 * Implement XDR-style API for RPC call. 728 */ 729 enum clnt_stat 730 clnt_call_private( 731 CLIENT *cl, /* client handle */ 732 struct rpc_callextra *ext, /* call metadata */ 733 rpcproc_t proc, /* procedure number */ 734 xdrproc_t xargs, /* xdr routine for args */ 735 void *argsp, /* pointer to args */ 736 xdrproc_t xresults, /* xdr routine for results */ 737 void *resultsp, /* pointer to results */ 738 struct timeval utimeout) /* seconds to wait before giving up */ 739 { 740 XDR xdrs; 741 struct mbuf *mreq; 742 struct mbuf *mrep; 743 enum clnt_stat stat; 744 745 mreq = m_getcl(M_WAITOK, MT_DATA, 0); 746 747 xdrmbuf_create(&xdrs, mreq, XDR_ENCODE); 748 if (!xargs(&xdrs, argsp)) { 749 m_freem(mreq); 750 return (RPC_CANTENCODEARGS); 751 } 752 XDR_DESTROY(&xdrs); 753 754 stat = CLNT_CALL_MBUF(cl, ext, proc, mreq, &mrep, utimeout); 755 m_freem(mreq); 756 757 if (stat == RPC_SUCCESS) { 758 xdrmbuf_create(&xdrs, mrep, XDR_DECODE); 759 if (!xresults(&xdrs, resultsp)) { 760 XDR_DESTROY(&xdrs); 761 return (RPC_CANTDECODERES); 762 } 763 XDR_DESTROY(&xdrs); 764 } 765 766 return (stat); 767 } 768 769 /* 770 * Bind a socket to a privileged IP port 771 */ 772 int 773 bindresvport(struct socket *so, struct sockaddr *sa) 774 { 775 struct sockaddr_storage ss = { .ss_len = sizeof(ss) }; 776 int old, error, af; 777 struct sockaddr_in *sin; 778 #ifdef INET6 779 struct sockaddr_in6 *sin6; 780 #endif 781 struct sockopt opt; 782 int proto, portrange, portlow; 783 uint16_t *portp; 784 socklen_t salen; 785 786 if (sa == NULL) { 787 sa = (struct sockaddr *)&ss; 788 error = sosockaddr(so, sa); 789 if (error) 790 return (error); 791 af = sa->sa_family; 792 salen = sa->sa_len; 793 memset(sa, 0, sa->sa_len); 794 } else { 795 af = sa->sa_family; 796 salen = sa->sa_len; 797 } 798 799 switch (af) { 800 case AF_INET: 801 proto = IPPROTO_IP; 802 portrange = IP_PORTRANGE; 803 portlow = IP_PORTRANGE_LOW; 804 sin = (struct sockaddr_in *)sa; 805 portp = &sin->sin_port; 806 break; 807 #ifdef INET6 808 case AF_INET6: 809 proto = IPPROTO_IPV6; 810 portrange = IPV6_PORTRANGE; 811 portlow = IPV6_PORTRANGE_LOW; 812 sin6 = (struct sockaddr_in6 *)sa; 813 portp = &sin6->sin6_port; 814 break; 815 #endif 816 default: 817 return (EPFNOSUPPORT); 818 } 819 820 sa->sa_family = af; 821 sa->sa_len = salen; 822 823 if (*portp == 0) { 824 bzero(&opt, sizeof(opt)); 825 opt.sopt_dir = SOPT_GET; 826 opt.sopt_level = proto; 827 opt.sopt_name = portrange; 828 opt.sopt_val = &old; 829 opt.sopt_valsize = sizeof(old); 830 error = sogetopt(so, &opt); 831 if (error) 832 return (error); 833 834 opt.sopt_dir = SOPT_SET; 835 opt.sopt_val = &portlow; 836 error = sosetopt(so, &opt); 837 if (error) 838 return (error); 839 } 840 841 error = sobind(so, sa, curthread); 842 843 if (*portp == 0) { 844 if (error) { 845 opt.sopt_dir = SOPT_SET; 846 opt.sopt_val = &old; 847 sosetopt(so, &opt); 848 } 849 } 850 851 return (error); 852 } 853 854 /* 855 * Make sure an mbuf list is made up entirely of ext_pgs mbufs. 856 * This is needed for sosend() when KERN_TLS is being used. 857 * (There might also be a performance improvement for certain 858 * network interfaces that handle ext_pgs mbufs efficiently.) 859 * It expects at least one non-ext_pgs mbuf followed by zero 860 * or more ext_pgs mbufs. It does not handle the case where 861 * non-ext_pgs mbuf(s) follow ext_pgs ones. 862 * It also performs sanity checks on the resultant list. 863 * The "mp" argument list is consumed. 864 * The "maxextsiz" argument is the upper bound on the data 865 * size for each mbuf (usually 16K for KERN_TLS). 866 */ 867 struct mbuf * 868 _rpc_copym_into_ext_pgs(struct mbuf *mp, int maxextsiz) 869 { 870 struct mbuf *m, *m2, *m3, *mhead; 871 int tlen; 872 873 KASSERT((mp->m_flags & (M_EXT | M_EXTPG)) != 874 (M_EXT | M_EXTPG), ("_rpc_copym_into_ext_pgs:" 875 " first mbuf is an ext_pgs")); 876 /* 877 * Find the last non-ext_pgs mbuf and the total 878 * length of the non-ext_pgs mbuf(s). 879 * The first mbuf must always be a non-ext_pgs 880 * mbuf. 881 */ 882 tlen = mp->m_len; 883 m2 = mp; 884 for (m = mp->m_next; m != NULL; m = m->m_next) { 885 if ((m->m_flags & M_EXTPG) != 0) 886 break; 887 tlen += m->m_len; 888 m2 = m; 889 } 890 891 /* 892 * Copy the non-ext_pgs mbuf(s) into an ext_pgs 893 * mbuf list. 894 */ 895 m2->m_next = NULL; 896 mhead = mb_mapped_to_unmapped(mp, tlen, maxextsiz, 897 M_WAITOK, &m2); 898 899 /* 900 * Link the ext_pgs list onto the newly copied 901 * list and free up the non-ext_pgs mbuf(s). 902 */ 903 m2->m_next = m; 904 m_freem(mp); 905 906 /* 907 * Sanity check the resultant mbuf list. Check for and 908 * remove any 0 length mbufs in the list, since the 909 * KERN_TLS code does not expect any 0 length mbuf(s) 910 * in the list. 911 */ 912 m3 = NULL; 913 m2 = mhead; 914 tlen = 0; 915 while (m2 != NULL) { 916 KASSERT(m2->m_len >= 0, ("_rpc_copym_into_ext_pgs:" 917 " negative m_len")); 918 KASSERT((m2->m_flags & (M_EXT | M_EXTPG)) == 919 (M_EXT | M_EXTPG), ("_rpc_copym_into_ext_pgs:" 920 " non-nomap mbuf in list")); 921 if (m2->m_len == 0) { 922 if (m3 != NULL) 923 m3->m_next = m2->m_next; 924 else 925 m = m2->m_next; 926 m2->m_next = NULL; 927 m_free(m2); 928 if (m3 != NULL) 929 m2 = m3->m_next; 930 else 931 m2 = m; 932 } else { 933 MBUF_EXT_PGS_ASSERT_SANITY(m2); 934 m3 = m2; 935 tlen += m2->m_len; 936 m2 = m2->m_next; 937 } 938 } 939 return (mhead); 940 } 941 942 /* 943 * Kernel module glue 944 */ 945 static int 946 krpc_modevent(module_t mod, int type, void *data) 947 { 948 int error = 0; 949 950 switch (type) { 951 case MOD_LOAD: 952 error = rpctls_init(); 953 break; 954 case MOD_UNLOAD: 955 /* 956 * Cannot be unloaded, since the rpctlssd or rpctlscd daemons 957 * might be performing a rpctls syscall. 958 */ 959 /* FALLTHROUGH */ 960 default: 961 error = EOPNOTSUPP; 962 } 963 return (error); 964 } 965 static moduledata_t krpc_mod = { 966 "krpc", 967 krpc_modevent, 968 NULL, 969 }; 970 DECLARE_MODULE(krpc, krpc_mod, SI_SUB_VFS, SI_ORDER_ANY); 971 972 /* So that loader and kldload(2) can find us, wherever we are.. */ 973 MODULE_VERSION(krpc, 1); 974 MODULE_DEPEND(krpc, xdr, 1, 1, 1); 975