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