1 /* $NetBSD: rpcb_svc_com.c,v 1.9 2002/11/08 00:16:39 fvdl 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 /* 37 * rpcb_svc_com.c 38 * The commom server procedure for the rpcbind. 39 */ 40 41 #include <sys/types.h> 42 #include <sys/stat.h> 43 #include <sys/param.h> 44 #include <sys/poll.h> 45 #include <sys/socket.h> 46 #include <rpc/rpc.h> 47 #include <rpc/rpcb_prot.h> 48 #include <rpc/svc_dg.h> 49 #include <assert.h> 50 #include <netconfig.h> 51 #include <errno.h> 52 #include <syslog.h> 53 #include <stdio.h> 54 #include <string.h> 55 #include <stdlib.h> 56 #include <unistd.h> 57 #ifdef PORTMAP 58 #include <netinet/in.h> 59 #include <rpc/rpc_com.h> 60 #include <rpc/pmap_prot.h> 61 #endif /* PORTMAP */ 62 63 #include "rpcbind.h" 64 65 #define RPC_BUF_MAX 65536 /* can be raised if required */ 66 67 static char *nullstring = ""; 68 static int rpcb_rmtcalls; 69 70 struct rmtcallfd_list { 71 int fd; 72 SVCXPRT *xprt; 73 char *netid; 74 struct rmtcallfd_list *next; 75 }; 76 77 #define NFORWARD 64 78 #define MAXTIME_OFF 300 /* 5 minutes */ 79 80 struct finfo { 81 int flag; 82 #define FINFO_ACTIVE 0x1 83 u_int32_t caller_xid; 84 struct netbuf *caller_addr; 85 u_int32_t forward_xid; 86 int forward_fd; 87 char *uaddr; 88 rpcproc_t reply_type; 89 rpcvers_t versnum; 90 time_t time; 91 }; 92 static struct finfo FINFO[NFORWARD]; 93 94 95 static bool_t xdr_encap_parms(XDR *, struct encap_parms *); 96 static bool_t xdr_rmtcall_args(XDR *, struct r_rmtcall_args *); 97 static bool_t xdr_rmtcall_result(XDR *, struct r_rmtcall_args *); 98 static bool_t xdr_opaque_parms(XDR *, struct r_rmtcall_args *); 99 static int find_rmtcallfd_by_netid(char *); 100 static SVCXPRT *find_rmtcallxprt_by_fd(int); 101 static int forward_register(u_int32_t, struct netbuf *, int, char *, 102 rpcproc_t, rpcvers_t, u_int32_t *); 103 static struct finfo *forward_find(u_int32_t); 104 static int free_slot_by_xid(u_int32_t); 105 static int free_slot_by_index(int); 106 static int netbufcmp(struct netbuf *, struct netbuf *); 107 static struct netbuf *netbufdup(struct netbuf *); 108 static void netbuffree(struct netbuf *); 109 static int check_rmtcalls(struct pollfd *, int); 110 static void xprt_set_caller(SVCXPRT *, struct finfo *); 111 static void send_svcsyserr(SVCXPRT *, struct finfo *); 112 static void handle_reply(int, SVCXPRT *); 113 static void find_versions(rpcprog_t, const char *, rpcvers_t *, rpcvers_t *); 114 static rpcblist_ptr find_service(rpcprog_t, rpcvers_t, char *); 115 static char *getowner(SVCXPRT *, char *, size_t); 116 static int add_pmaplist(RPCB *); 117 static int del_pmaplist(RPCB *); 118 119 /* 120 * Set a mapping of program, version, netid 121 */ 122 /* ARGSUSED */ 123 void * 124 rpcbproc_set_com(void *arg, struct svc_req *rqstp __unused, SVCXPRT *transp, 125 rpcvers_t rpcbversnum) 126 { 127 RPCB *regp = arg; 128 static bool_t ans; 129 char owner[64]; 130 131 #ifdef RPCBIND_DEBUG 132 if (debugging) 133 fprintf(stderr, "%s: RPCB_SET request for (%lu, %lu, %s, %s): ", 134 __func__, (unsigned long)regp->r_prog, 135 (unsigned long)regp->r_vers, regp->r_netid, regp->r_addr); 136 #endif 137 ans = map_set(regp, getowner(transp, owner, sizeof owner)); 138 #ifdef RPCBIND_DEBUG 139 if (debugging) 140 fprintf(stderr, "%s\n", ans == TRUE ? "succeeded" : "failed"); 141 #endif 142 /* XXX: should have used some defined constant here */ 143 rpcbs_set(rpcbversnum - 2, ans); 144 return (void *)&ans; 145 } 146 147 bool_t 148 map_set(RPCB *regp, const char *owner) 149 { 150 RPCB reg, *a; 151 rpcblist_ptr rbl, fnd; 152 153 reg = *regp; 154 /* 155 * check to see if already used 156 * find_service returns a hit even if 157 * the versions don't match, so check for it 158 */ 159 fnd = find_service(reg.r_prog, reg.r_vers, reg.r_netid); 160 if (fnd && (fnd->rpcb_map.r_vers == reg.r_vers)) { 161 if (!strcmp(fnd->rpcb_map.r_addr, reg.r_addr)) 162 /* 163 * if these match then it is already 164 * registered so just say "OK". 165 */ 166 return (TRUE); 167 else 168 return (FALSE); 169 } 170 /* 171 * add to the end of the list 172 */ 173 rbl = malloc(sizeof(*rbl)); 174 if (rbl == NULL) 175 return (FALSE); 176 a = &(rbl->rpcb_map); 177 a->r_prog = reg.r_prog; 178 a->r_vers = reg.r_vers; 179 a->r_netid = strdup(reg.r_netid); 180 a->r_addr = strdup(reg.r_addr); 181 a->r_owner = strdup(owner); 182 if (!a->r_addr || !a->r_netid || !a->r_owner) { 183 free(a->r_netid); 184 free(a->r_addr); 185 free(a->r_owner); 186 free(rbl); 187 return (FALSE); 188 } 189 rbl->rpcb_next = NULL; 190 if (list_rbl == NULL) { 191 list_rbl = rbl; 192 } else { 193 for (fnd = list_rbl; fnd->rpcb_next; 194 fnd = fnd->rpcb_next) 195 ; 196 fnd->rpcb_next = rbl; 197 } 198 #ifdef PORTMAP 199 (void)add_pmaplist(regp); 200 #endif 201 return (TRUE); 202 } 203 204 /* 205 * Unset a mapping of program, version, netid 206 */ 207 /* ARGSUSED */ 208 void * 209 rpcbproc_unset_com(void *arg, struct svc_req *rqstp __unused, SVCXPRT *transp, 210 rpcvers_t rpcbversnum) 211 { 212 RPCB *regp = arg; 213 static bool_t ans; 214 char owner[64]; 215 216 #ifdef RPCBIND_DEBUG 217 if (debugging) 218 fprintf(stderr, "%s: RPCB_UNSET request for (%lu, %lu, %s): ", 219 __func__, (unsigned long)regp->r_prog, 220 (unsigned long)regp->r_vers, regp->r_netid); 221 #endif 222 ans = map_unset(regp, getowner(transp, owner, sizeof owner)); 223 #ifdef RPCBIND_DEBUG 224 if (debugging) 225 fprintf(stderr, "%s\n", ans == TRUE ? "succeeded" : "failed"); 226 #endif 227 /* XXX: should have used some defined constant here */ 228 rpcbs_unset(rpcbversnum - 2, ans); 229 return (void *)&ans; 230 } 231 232 bool_t 233 map_unset(RPCB *regp, const char *owner) 234 { 235 int ans = 0; 236 rpcblist_ptr rbl, prev, tmp; 237 238 if (owner == NULL) 239 return (0); 240 241 for (prev = NULL, rbl = list_rbl; rbl; /* cstyle */) { 242 if ((rbl->rpcb_map.r_prog != regp->r_prog) || 243 (rbl->rpcb_map.r_vers != regp->r_vers) || 244 (regp->r_netid[0] && strcasecmp(regp->r_netid, 245 rbl->rpcb_map.r_netid))) { 246 /* both rbl & prev move forwards */ 247 prev = rbl; 248 rbl = rbl->rpcb_next; 249 continue; 250 } 251 /* 252 * Check whether appropriate uid. Unset only 253 * if superuser or the owner itself. 254 */ 255 if (strcmp(owner, rpcbind_superuser) && 256 strcmp(rbl->rpcb_map.r_owner, owner)) 257 return (0); 258 /* found it; rbl moves forward, prev stays */ 259 ans = 1; 260 tmp = rbl; 261 rbl = rbl->rpcb_next; 262 if (prev == NULL) 263 list_rbl = rbl; 264 else 265 prev->rpcb_next = rbl; 266 free(tmp->rpcb_map.r_addr); 267 free(tmp->rpcb_map.r_netid); 268 free(tmp->rpcb_map.r_owner); 269 free(tmp); 270 } 271 #ifdef PORTMAP 272 if (ans) 273 (void)del_pmaplist(regp); 274 #endif 275 /* 276 * We return 1 either when the entry was not there or it 277 * was able to unset it. It can come to this point only if 278 * at least one of the conditions is true. 279 */ 280 return (1); 281 } 282 283 void 284 delete_prog(rpcprog_t prog) 285 { 286 RPCB reg; 287 rpcblist_ptr rbl; 288 289 for (rbl = list_rbl; rbl != NULL; rbl = rbl->rpcb_next) { 290 if ((rbl->rpcb_map.r_prog != prog)) 291 continue; 292 if (is_bound(rbl->rpcb_map.r_netid, rbl->rpcb_map.r_addr)) 293 continue; 294 reg.r_prog = rbl->rpcb_map.r_prog; 295 reg.r_vers = rbl->rpcb_map.r_vers; 296 reg.r_netid = strdup(rbl->rpcb_map.r_netid); 297 if (reg.r_netid == NULL) 298 syslog(LOG_ERR, "%s: %m", __func__); 299 else { 300 (void)map_unset(®, rpcbind_superuser); 301 free(reg.r_netid); 302 } 303 } 304 } 305 306 void * 307 rpcbproc_getaddr_com(RPCB *regp, struct svc_req *rqstp __unused, 308 SVCXPRT *transp, rpcvers_t rpcbversnum, rpcvers_t verstype) 309 { 310 static char *uaddr; 311 char *saddr = NULL; 312 rpcblist_ptr fnd; 313 314 if (uaddr != NULL && uaddr != nullstring) { 315 free(uaddr); 316 uaddr = NULL; 317 } 318 fnd = find_service(regp->r_prog, regp->r_vers, transp->xp_netid); 319 if (fnd && ((verstype == RPCB_ALLVERS) || 320 (regp->r_vers == fnd->rpcb_map.r_vers))) { 321 if (*(regp->r_addr) != '\0') { /* may contain a hint about */ 322 saddr = regp->r_addr; /* the interface that we */ 323 } /* should use */ 324 if (!(uaddr = mergeaddr(transp, transp->xp_netid, 325 fnd->rpcb_map.r_addr, saddr))) { 326 /* Try whatever we have */ 327 uaddr = strdup(fnd->rpcb_map.r_addr); 328 } else if (!uaddr[0]) { 329 /* 330 * The server died. Unset all versions of this prog. 331 */ 332 delete_prog(regp->r_prog); 333 uaddr = nullstring; 334 } 335 } else { 336 uaddr = nullstring; 337 } 338 #ifdef RPCBIND_DEBUG 339 if (debugging) 340 fprintf(stderr, "%s: %s\n", __func__, uaddr); 341 #endif 342 /* XXX: should have used some defined constant here */ 343 rpcbs_getaddr(rpcbversnum - 2, regp->r_prog, regp->r_vers, 344 transp->xp_netid, uaddr); 345 return (&uaddr); 346 } 347 348 /* ARGSUSED */ 349 void * 350 rpcbproc_gettime_com(void *arg __unused, struct svc_req *rqstp __unused, 351 SVCXPRT *transp __unused, rpcvers_t rpcbversnum __unused) 352 { 353 static time_t curtime; 354 355 (void)time(&curtime); 356 return (&curtime); 357 } 358 359 /* 360 * Convert uaddr to taddr. Should be used only by 361 * local servers/clients. (kernel level stuff only) 362 */ 363 /* ARGSUSED */ 364 void * 365 rpcbproc_uaddr2taddr_com(void *arg, struct svc_req *rqstp __unused, 366 SVCXPRT *transp, rpcvers_t rpcbversnum __unused) 367 { 368 char **uaddrp = arg; 369 struct netconfig *nconf; 370 static struct netbuf nbuf; 371 static struct netbuf *taddr; 372 373 netbuffree(taddr); 374 taddr = NULL; 375 if (((nconf = rpcbind_get_conf(transp->xp_netid)) == NULL) || 376 ((taddr = uaddr2taddr(nconf, *uaddrp)) == NULL)) { 377 memset(&nbuf, 0, sizeof(nbuf)); 378 return (&nbuf); 379 } 380 return (taddr); 381 } 382 383 /* 384 * Convert taddr to uaddr. Should be used only by 385 * local servers/clients. (kernel level stuff only) 386 */ 387 /* ARGSUSED */ 388 void * 389 rpcbproc_taddr2uaddr_com(void *arg, struct svc_req *rqstp __unused, 390 SVCXPRT *transp, rpcvers_t rpcbversnum __unused) 391 { 392 struct netbuf *taddr = arg; 393 static char *uaddr; 394 struct netconfig *nconf; 395 396 #ifdef CHEW_FDS 397 int fd; 398 399 if ((fd = open("/dev/null", O_RDONLY)) == -1) { 400 uaddr = strerror(errno); 401 return (&uaddr); 402 } 403 #endif /* CHEW_FDS */ 404 if (uaddr != NULL && uaddr != nullstring) { 405 free(uaddr); 406 uaddr = NULL; 407 } 408 if (((nconf = rpcbind_get_conf(transp->xp_netid)) == NULL) || 409 ((uaddr = taddr2uaddr(nconf, taddr)) == NULL)) { 410 uaddr = nullstring; 411 } 412 return (void *)&uaddr; 413 } 414 415 416 static bool_t 417 xdr_encap_parms(XDR *xdrs, struct encap_parms *epp) 418 { 419 return (xdr_bytes(xdrs, &(epp->args), (u_int *) &(epp->arglen), 420 RPC_MAXDATASIZE)); 421 } 422 423 /* 424 * XDR remote call arguments. It ignores the address part. 425 * written for XDR_DECODE direction only 426 */ 427 static bool_t 428 xdr_rmtcall_args(XDR *xdrs, struct r_rmtcall_args *cap) 429 { 430 /* does not get the address or the arguments */ 431 if (xdr_rpcprog(xdrs, &(cap->rmt_prog)) && 432 xdr_rpcvers(xdrs, &(cap->rmt_vers)) && 433 xdr_rpcproc(xdrs, &(cap->rmt_proc))) { 434 return (xdr_encap_parms(xdrs, &(cap->rmt_args))); 435 } 436 return (FALSE); 437 } 438 439 /* 440 * XDR remote call results along with the address. Ignore 441 * program number, version number and proc number. 442 * Written for XDR_ENCODE direction only. 443 */ 444 static bool_t 445 xdr_rmtcall_result(XDR *xdrs, struct r_rmtcall_args *cap) 446 { 447 bool_t result; 448 449 #ifdef PORTMAP 450 if (cap->rmt_localvers == PMAPVERS) { 451 int h1, h2, h3, h4, p1, p2; 452 u_long port; 453 454 /* interpret the universal address for TCP/IP */ 455 if (sscanf(cap->rmt_uaddr, "%d.%d.%d.%d.%d.%d", 456 &h1, &h2, &h3, &h4, &p1, &p2) != 6) 457 return (FALSE); 458 port = ((p1 & 0xff) << 8) + (p2 & 0xff); 459 result = xdr_u_long(xdrs, &port); 460 } else 461 #endif 462 if ((cap->rmt_localvers == RPCBVERS) || 463 (cap->rmt_localvers == RPCBVERS4)) { 464 result = xdr_wrapstring(xdrs, &(cap->rmt_uaddr)); 465 } else { 466 return (FALSE); 467 } 468 if (result == TRUE) 469 return (xdr_encap_parms(xdrs, &(cap->rmt_args))); 470 return (FALSE); 471 } 472 473 /* 474 * only worries about the struct encap_parms part of struct r_rmtcall_args. 475 * The arglen must already be set!! 476 */ 477 static bool_t 478 xdr_opaque_parms(XDR *xdrs, struct r_rmtcall_args *cap) 479 { 480 return (xdr_opaque(xdrs, cap->rmt_args.args, cap->rmt_args.arglen)); 481 } 482 483 static struct rmtcallfd_list *rmthead; 484 static struct rmtcallfd_list *rmttail; 485 486 int 487 create_rmtcall_fd(const struct netconfig *nconf) 488 { 489 int fd; 490 struct rmtcallfd_list *rmt; 491 SVCXPRT *xprt; 492 493 if ((fd = __rpc_nconf2fd(nconf)) == -1) { 494 if (debugging) 495 fprintf(stderr, "%s: couldn't open \"%s\": %m\n", 496 __func__, nconf->nc_device); 497 return (-1); 498 } 499 xprt = svc_tli_create(fd, 0, NULL, 0, 0); 500 if (xprt == NULL) { 501 if (debugging) 502 fprintf(stderr, "%s: svc_tli_create failed\n", 503 __func__); 504 return (-1); 505 } 506 rmt = malloc(sizeof(*rmt)); 507 if (rmt == NULL) { 508 syslog(LOG_ERR, "%s: %m", __func__); 509 return (-1); 510 } 511 rmt->xprt = xprt; 512 rmt->netid = strdup(nconf->nc_netid); 513 xprt->xp_netid = rmt->netid; 514 rmt->fd = fd; 515 rmt->next = NULL; 516 if (rmthead == NULL) { 517 rmthead = rmt; 518 rmttail = rmt; 519 } else { 520 rmttail->next = rmt; 521 rmttail = rmt; 522 } 523 /* XXX not threadsafe */ 524 if (fd > svc_maxfd) 525 svc_maxfd = fd; 526 FD_SET(fd, &svc_fdset); 527 return (fd); 528 } 529 530 static int 531 find_rmtcallfd_by_netid(char *netid) 532 { 533 struct rmtcallfd_list *rmt; 534 535 for (rmt = rmthead; rmt != NULL; rmt = rmt->next) { 536 if (strcmp(netid, rmt->netid) == 0) { 537 return (rmt->fd); 538 } 539 } 540 return (-1); 541 } 542 543 static SVCXPRT * 544 find_rmtcallxprt_by_fd(int fd) 545 { 546 struct rmtcallfd_list *rmt; 547 548 for (rmt = rmthead; rmt != NULL; rmt = rmt->next) { 549 if (fd == rmt->fd) { 550 return (rmt->xprt); 551 } 552 } 553 return (NULL); 554 } 555 556 557 /* 558 * Call a remote procedure service. This procedure is very quiet when things 559 * go wrong. The proc is written to support broadcast rpc. In the broadcast 560 * case, a machine should shut-up instead of complain, lest the requestor be 561 * overrun with complaints at the expense of not hearing a valid reply. 562 * When receiving a request and verifying that the service exists, we 563 * 564 * receive the request 565 * 566 * open a new TLI endpoint on the same transport on which we received 567 * the original request 568 * 569 * remember the original request's XID (which requires knowing the format 570 * of the svc_dg_data structure) 571 * 572 * forward the request, with a new XID, to the requested service, 573 * remembering the XID used to send this request (for later use in 574 * reassociating the answer with the original request), the requestor's 575 * address, the file descriptor on which the forwarded request is 576 * made and the service's address. 577 * 578 * mark the file descriptor on which we anticipate receiving a reply from 579 * the service and one to select for in our private svc_run procedure 580 * 581 * At some time in the future, a reply will be received from the service to 582 * which we forwarded the request. At that time, we detect that the socket 583 * used was for forwarding (by looking through the finfo structures to see 584 * whether the fd corresponds to one of those) and call handle_reply() to 585 * 586 * receive the reply 587 * 588 * bundle the reply, along with the service's universal address 589 * 590 * create a SVCXPRT structure and use a version of svc_sendreply 591 * that allows us to specify the reply XID and destination, send the reply 592 * to the original requestor. 593 */ 594 595 void 596 rpcbproc_callit_com(struct svc_req *rqstp, SVCXPRT *transp, 597 rpcproc_t reply_type, rpcvers_t versnum) 598 { 599 rpcblist_ptr rbl; 600 struct netconfig *nconf; 601 struct netbuf *caller; 602 struct r_rmtcall_args a; 603 char *buf_alloc = NULL, *outbufp; 604 char *outbuf_alloc = NULL; 605 char buf[RPC_BUF_MAX], outbuf[RPC_BUF_MAX]; 606 struct netbuf *na = NULL; 607 struct rpc_msg call_msg; 608 int outlen; 609 u_int sendsz; 610 XDR outxdr; 611 AUTH *auth; 612 int fd = -1; 613 char *uaddr, *m_uaddr = NULL, *local_uaddr = NULL; 614 u_int32_t *xidp; 615 struct __rpc_sockinfo si; 616 struct sockaddr *localsa; 617 struct netbuf tbuf; 618 619 if (!__rpc_fd2sockinfo(transp->xp_fd, &si)) { 620 if (reply_type == RPCBPROC_INDIRECT) 621 svcerr_systemerr(transp); 622 return; 623 } 624 if (si.si_socktype != SOCK_DGRAM) 625 return; /* Only datagram type accepted */ 626 sendsz = __rpc_get_t_size(si.si_af, si.si_proto, UDPMSGSIZE); 627 if (sendsz == 0) { /* data transfer not supported */ 628 if (reply_type == RPCBPROC_INDIRECT) 629 svcerr_systemerr(transp); 630 return; 631 } 632 /* 633 * Should be multiple of 4 for XDR. 634 */ 635 sendsz = roundup(sendsz, 4); 636 if (sendsz > RPC_BUF_MAX) { 637 #ifdef notyet 638 buf_alloc = alloca(sendsz); /* not in IDR2? */ 639 #else 640 buf_alloc = malloc(sendsz); 641 #endif /* notyet */ 642 if (buf_alloc == NULL) { 643 if (debugging) 644 fprintf(stderr, "%s: %m\n", __func__); 645 if (reply_type == RPCBPROC_INDIRECT) 646 svcerr_systemerr(transp); 647 return; 648 } 649 a.rmt_args.args = buf_alloc; 650 } else { 651 a.rmt_args.args = buf; 652 } 653 654 call_msg.rm_xid = 0; /* For error checking purposes */ 655 if (!svc_getargs(transp, (xdrproc_t)xdr_rmtcall_args, (char *) &a)) { 656 if (reply_type == RPCBPROC_INDIRECT) 657 svcerr_decode(transp); 658 if (debugging) 659 fprintf(stderr, "%s: svc_getargs failed\n", __func__); 660 goto error; 661 } 662 663 if (!check_callit(transp, &a, versnum)) { 664 svcerr_weakauth(transp); 665 goto error; 666 } 667 668 caller = svc_getrpccaller(transp); 669 #ifdef RPCBIND_DEBUG 670 if (debugging) { 671 uaddr = taddr2uaddr(rpcbind_get_conf(transp->xp_netid), caller); 672 fprintf(stderr, 673 "%s: %s %s req for (%lu, %lu, %lu, %s) from %s: ", 674 __func__, versnum == PMAPVERS ? "pmap_rmtcall" : 675 versnum == RPCBVERS ? "rpcb_rmtcall" : 676 versnum == RPCBVERS4 ? "rpcb_indirect" : rpcbind_unknown, 677 reply_type == RPCBPROC_INDIRECT ? "indirect" : "callit", 678 (unsigned long)a.rmt_prog, (unsigned long)a.rmt_vers, 679 (unsigned long)a.rmt_proc, transp->xp_netid, 680 uaddr ? uaddr : rpcbind_unknown); 681 free(uaddr); 682 } 683 #endif 684 685 rbl = find_service(a.rmt_prog, a.rmt_vers, transp->xp_netid); 686 687 rpcbs_rmtcall(versnum - 2, reply_type, a.rmt_prog, a.rmt_vers, 688 a.rmt_proc, transp->xp_netid, rbl); 689 690 if (rbl == NULL) { 691 #ifdef RPCBIND_DEBUG 692 if (debugging) 693 fprintf(stderr, "not found\n"); 694 #endif 695 if (reply_type == RPCBPROC_INDIRECT) 696 svcerr_noprog(transp); 697 goto error; 698 } 699 if (rbl->rpcb_map.r_vers != a.rmt_vers) { 700 if (reply_type == RPCBPROC_INDIRECT) { 701 rpcvers_t vers_low, vers_high; 702 703 find_versions(a.rmt_prog, transp->xp_netid, 704 &vers_low, &vers_high); 705 svcerr_progvers(transp, vers_low, vers_high); 706 } 707 goto error; 708 } 709 710 #ifdef RPCBIND_DEBUG 711 if (debugging) 712 fprintf(stderr, "found at uaddr %s\n", rbl->rpcb_map.r_addr); 713 #endif 714 /* 715 * Check whether this entry is valid and a server is present 716 * Mergeaddr() returns NULL if no such entry is present, and 717 * returns "" if the entry was present but the server is not 718 * present (i.e., it crashed). 719 */ 720 if (reply_type == RPCBPROC_INDIRECT) { 721 uaddr = mergeaddr(transp, transp->xp_netid, 722 rbl->rpcb_map.r_addr, NULL); 723 if (uaddr == NULL || uaddr[0] == '\0') { 724 svcerr_noprog(transp); 725 free(uaddr); 726 goto error; 727 } 728 free(uaddr); 729 } 730 nconf = rpcbind_get_conf(transp->xp_netid); 731 if (nconf == NULL) { 732 if (reply_type == RPCBPROC_INDIRECT) 733 svcerr_systemerr(transp); 734 if (debugging) 735 fprintf(stderr, "%s: rpcbind_get_conf failed\n", 736 __func__); 737 goto error; 738 } 739 localsa = local_sa(((struct sockaddr *)caller->buf)->sa_family); 740 if (localsa == NULL) { 741 if (debugging) 742 fprintf(stderr, "%s: no local address\n", __func__); 743 goto error; 744 } 745 tbuf.len = tbuf.maxlen = localsa->sa_len; 746 tbuf.buf = localsa; 747 local_uaddr = 748 addrmerge(&tbuf, rbl->rpcb_map.r_addr, NULL, nconf->nc_netid); 749 m_uaddr = addrmerge(caller, rbl->rpcb_map.r_addr, NULL, 750 nconf->nc_netid); 751 #ifdef RPCBIND_DEBUG 752 if (debugging) 753 fprintf(stderr, "%s: merged uaddr %s\n", __func__, m_uaddr); 754 #endif 755 if ((fd = find_rmtcallfd_by_netid(nconf->nc_netid)) == -1) { 756 if (reply_type == RPCBPROC_INDIRECT) 757 svcerr_systemerr(transp); 758 goto error; 759 } 760 xidp = __rpcb_get_dg_xidp(transp); 761 switch (forward_register(*xidp, caller, fd, m_uaddr, reply_type, 762 versnum, &call_msg.rm_xid)) { 763 case 1: 764 /* Success; forward_register() will free m_uaddr for us. */ 765 m_uaddr = NULL; 766 break; 767 case 0: 768 /* 769 * A duplicate request for the slow server. Let's not 770 * beat on it any more. 771 */ 772 if (debugging) 773 fprintf(stderr, "%s: duplicate request\n", __func__); 774 goto error; 775 case -1: 776 /* forward_register failed. Perhaps no memory. */ 777 if (debugging) 778 fprintf(stderr, "%s: forward_register failed\n", 779 __func__); 780 goto error; 781 } 782 783 #ifdef DEBUG_RMTCALL 784 if (debugging) 785 fprintf(stderr, "%s: original XID %x, new XID %x\n", __func__, 786 *xidp, call_msg.rm_xid); 787 #endif 788 call_msg.rm_direction = CALL; 789 call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; 790 call_msg.rm_call.cb_prog = a.rmt_prog; 791 call_msg.rm_call.cb_vers = a.rmt_vers; 792 if (sendsz > RPC_BUF_MAX) { 793 #ifdef notyet 794 outbuf_alloc = alloca(sendsz); /* not in IDR2? */ 795 #else 796 outbuf_alloc = malloc(sendsz); 797 #endif /* notyet */ 798 if (outbuf_alloc == NULL) { 799 if (debugging) 800 fprintf(stderr, "%s: %m\n", __func__); 801 if (reply_type == RPCBPROC_INDIRECT) 802 svcerr_systemerr(transp); 803 goto error; 804 } 805 xdrmem_create(&outxdr, outbuf_alloc, sendsz, XDR_ENCODE); 806 } else { 807 xdrmem_create(&outxdr, outbuf, sendsz, XDR_ENCODE); 808 } 809 if (!xdr_callhdr(&outxdr, &call_msg)) { 810 if (reply_type == RPCBPROC_INDIRECT) 811 svcerr_systemerr(transp); 812 if (debugging) 813 fprintf(stderr, "%s: xdr_callhdr failed\n", __func__); 814 goto error; 815 } 816 if (!xdr_u_int32_t(&outxdr, &(a.rmt_proc))) { 817 if (reply_type == RPCBPROC_INDIRECT) 818 svcerr_systemerr(transp); 819 if (debugging) 820 fprintf(stderr, "%s: xdr_u_long failed\n", __func__); 821 goto error; 822 } 823 824 if (rqstp->rq_cred.oa_flavor == AUTH_NULL) { 825 auth = authnone_create(); 826 } else if (rqstp->rq_cred.oa_flavor == AUTH_SYS) { 827 struct authunix_parms *au; 828 829 au = (struct authunix_parms *)rqstp->rq_clntcred; 830 auth = authunix_create(au->aup_machname, 831 au->aup_uid, au->aup_gid, 832 au->aup_len, au->aup_gids); 833 if (auth == NULL) /* fall back */ 834 auth = authnone_create(); 835 } else { 836 /* we do not support any other authentication scheme */ 837 if (debugging) 838 fprintf(stderr, "%s: oa_flavor != AUTH_NONE and " 839 "oa_flavor != AUTH_SYS\n", __func__); 840 if (reply_type == RPCBPROC_INDIRECT) 841 svcerr_weakauth(transp); /* XXX too strong.. */ 842 goto error; 843 } 844 if (auth == NULL) { 845 if (reply_type == RPCBPROC_INDIRECT) 846 svcerr_systemerr(transp); 847 if (debugging) 848 fprintf(stderr, 849 "%s: authwhatever_create returned NULL\n", 850 __func__); 851 goto error; 852 } 853 if (!AUTH_MARSHALL(auth, &outxdr)) { 854 if (reply_type == RPCBPROC_INDIRECT) 855 svcerr_systemerr(transp); 856 AUTH_DESTROY(auth); 857 if (debugging) 858 fprintf(stderr, "%s: AUTH_MARSHALL failed\n", 859 __func__); 860 goto error; 861 } 862 AUTH_DESTROY(auth); 863 if (!xdr_opaque_parms(&outxdr, &a)) { 864 if (reply_type == RPCBPROC_INDIRECT) 865 svcerr_systemerr(transp); 866 if (debugging) 867 fprintf(stderr, "%s: xdr_opaque_parms failed\n", 868 __func__); 869 goto error; 870 } 871 outlen = (int) XDR_GETPOS(&outxdr); 872 if (outbuf_alloc) 873 outbufp = outbuf_alloc; 874 else 875 outbufp = outbuf; 876 877 na = uaddr2taddr(nconf, local_uaddr); 878 if (!na) { 879 if (reply_type == RPCBPROC_INDIRECT) 880 svcerr_systemerr(transp); 881 goto error; 882 } 883 884 if (sendto(fd, outbufp, outlen, 0, (struct sockaddr *)na->buf, na->len) 885 != outlen) { 886 if (debugging) 887 fprintf(stderr, "%s: sendto failed: %m\n", __func__); 888 if (reply_type == RPCBPROC_INDIRECT) 889 svcerr_systemerr(transp); 890 goto error; 891 } 892 goto out; 893 894 error: 895 if (call_msg.rm_xid != 0) 896 (void)free_slot_by_xid(call_msg.rm_xid); 897 out: 898 free(local_uaddr); 899 free(buf_alloc); 900 free(outbuf_alloc); 901 netbuffree(na); 902 free(m_uaddr); 903 } 904 905 /* 906 * Makes an entry into the FIFO for the given request. 907 * Returns 1 on success, 0 if this is a duplicate request, or -1 on error. 908 * *callxidp is set to the xid of the call. 909 */ 910 static int 911 forward_register(u_int32_t caller_xid, struct netbuf *caller_addr, 912 int forward_fd, char *uaddr, rpcproc_t reply_type, 913 rpcvers_t versnum, u_int32_t *callxidp) 914 { 915 static u_int32_t lastxid; 916 time_t min_time, time_now; 917 int i, j = 0, entry = -1; 918 919 min_time = FINFO[0].time; 920 time_now = time((time_t *)0); 921 /* initialization */ 922 if (lastxid == 0) 923 lastxid = time_now * NFORWARD; 924 925 /* 926 * Check if it is a duplicate entry. Then, 927 * try to find an empty slot. If not available, then 928 * use the slot with the earliest time. 929 */ 930 for (i = 0; i < NFORWARD; i++) { 931 if (FINFO[i].flag & FINFO_ACTIVE) { 932 if ((FINFO[i].caller_xid == caller_xid) && 933 (FINFO[i].reply_type == reply_type) && 934 (FINFO[i].versnum == versnum) && 935 (!netbufcmp(FINFO[i].caller_addr, 936 caller_addr))) { 937 FINFO[i].time = time((time_t *)0); 938 return (0); /* Duplicate entry */ 939 } else { 940 /* Should we wait any longer */ 941 if ((time_now - FINFO[i].time) > MAXTIME_OFF) 942 (void)free_slot_by_index(i); 943 } 944 } 945 if (entry == -1) { 946 if ((FINFO[i].flag & FINFO_ACTIVE) == 0) { 947 entry = i; 948 } else if (FINFO[i].time < min_time) { 949 j = i; 950 min_time = FINFO[i].time; 951 } 952 } 953 } 954 if (entry != -1) { 955 /* use this empty slot */ 956 j = entry; 957 } else { 958 (void)free_slot_by_index(j); 959 } 960 if ((FINFO[j].caller_addr = netbufdup(caller_addr)) == NULL) { 961 return (-1); 962 } 963 rpcb_rmtcalls++; /* no of pending calls */ 964 FINFO[j].flag = FINFO_ACTIVE; 965 FINFO[j].reply_type = reply_type; 966 FINFO[j].versnum = versnum; 967 FINFO[j].time = time_now; 968 FINFO[j].caller_xid = caller_xid; 969 FINFO[j].forward_fd = forward_fd; 970 /* 971 * Though uaddr is not allocated here, it will still be freed 972 * from free_slot_*(). 973 */ 974 FINFO[j].uaddr = uaddr; 975 lastxid = lastxid + NFORWARD; 976 /* Don't allow a zero xid below. */ 977 if ((u_int32_t)(lastxid + NFORWARD) <= NFORWARD) 978 lastxid = NFORWARD; 979 FINFO[j].forward_xid = lastxid + j; /* encode slot */ 980 *callxidp = FINFO[j].forward_xid; /* forward on this xid */ 981 return (1); 982 } 983 984 static struct finfo * 985 forward_find(u_int32_t reply_xid) 986 { 987 int i; 988 989 i = reply_xid % (u_int32_t)NFORWARD; 990 if ((FINFO[i].flag & FINFO_ACTIVE) && 991 (FINFO[i].forward_xid == reply_xid)) { 992 return (&FINFO[i]); 993 } 994 return (NULL); 995 } 996 997 static int 998 free_slot_by_xid(u_int32_t xid) 999 { 1000 int entry; 1001 1002 entry = xid % (u_int32_t)NFORWARD; 1003 return (free_slot_by_index(entry)); 1004 } 1005 1006 static int 1007 free_slot_by_index(int index) 1008 { 1009 struct finfo *fi; 1010 1011 fi = &FINFO[index]; 1012 if (fi->flag & FINFO_ACTIVE) { 1013 netbuffree(fi->caller_addr); 1014 /* XXX may be too big, but can't access xprt array here */ 1015 if (fi->forward_fd >= svc_maxfd) 1016 svc_maxfd--; 1017 free(fi->uaddr); 1018 fi->flag &= ~FINFO_ACTIVE; 1019 rpcb_rmtcalls--; 1020 return (1); 1021 } 1022 return (0); 1023 } 1024 1025 static int 1026 netbufcmp(struct netbuf *n1, struct netbuf *n2) 1027 { 1028 return ((n1->len != n2->len) || memcmp(n1->buf, n2->buf, n1->len)); 1029 } 1030 1031 static bool_t 1032 netbuf_copybuf(struct netbuf *dst, const struct netbuf *src) 1033 { 1034 assert(src->len <= src->maxlen); 1035 1036 if (dst->maxlen < src->len || dst->buf == NULL) { 1037 free(dst->buf); 1038 if ((dst->buf = calloc(1, src->maxlen)) == NULL) 1039 return (FALSE); 1040 dst->maxlen = src->maxlen; 1041 } 1042 1043 dst->len = src->len; 1044 memcpy(dst->buf, src->buf, src->len); 1045 1046 return (TRUE); 1047 } 1048 1049 static struct netbuf * 1050 netbufdup(struct netbuf *ap) 1051 { 1052 struct netbuf *np; 1053 1054 if ((np = calloc(1, sizeof(struct netbuf))) == NULL) 1055 return (NULL); 1056 if (netbuf_copybuf(np, ap) == FALSE) { 1057 free(np); 1058 return (NULL); 1059 } 1060 return (np); 1061 } 1062 1063 static void 1064 netbuffree(struct netbuf *ap) 1065 { 1066 1067 if (ap == NULL) 1068 return; 1069 free(ap->buf); 1070 ap->buf = NULL; 1071 free(ap); 1072 } 1073 1074 1075 #define MASKVAL (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND) 1076 extern bool_t __svc_clean_idle(fd_set *, int, bool_t); 1077 1078 void 1079 my_svc_run(void) 1080 { 1081 struct pollfd pollfds[FD_SETSIZE + 1]; 1082 fd_set cleanfds; 1083 struct pollfd *p; 1084 size_t nfds; 1085 #ifdef SVC_RUN_DEBUG 1086 size_t i; 1087 #endif 1088 int n, poll_ret, check_ret; 1089 1090 for (;;) { 1091 p = pollfds; 1092 p->fd = terminate_rfd; 1093 p->events = MASKVAL; 1094 p++; 1095 for (n = 0; n <= svc_maxfd; n++) { 1096 if (FD_ISSET(n, &svc_fdset)) { 1097 p->fd = n; 1098 p->events = MASKVAL; 1099 p++; 1100 } 1101 } 1102 nfds = p - pollfds; 1103 poll_ret = 0; 1104 #ifdef SVC_RUN_DEBUG 1105 if (debugging) { 1106 fprintf(stderr, "%s: polling for read on fd < ", 1107 __func__); 1108 for (i = 0, p = pollfds; i < nfds; i++, p++) 1109 if (p->events) 1110 fprintf(stderr, "%d ", p->fd); 1111 fprintf(stderr, ">\n"); 1112 } 1113 #endif 1114 poll_ret = poll(pollfds, nfds, 30 * 1000); 1115 1116 if (doterminate != 0) { 1117 close(rpcbindlockfd); 1118 #ifdef WARMSTART 1119 syslog(LOG_ERR, 1120 "rpcbind terminating on signal %d. Restart with \"rpcbind -w\"", 1121 (int)doterminate); 1122 write_warmstart(); /* Dump yourself */ 1123 #endif 1124 exit(2); 1125 } 1126 1127 switch (poll_ret) { 1128 case -1: 1129 /* 1130 * We ignore all errors, continuing with the assumption 1131 * that it was set by the signal handlers (or any 1132 * other outside event) and not caused by poll(). 1133 */ 1134 #ifdef SVC_RUN_DEBUG 1135 if (debugging) { 1136 fprintf(stderr, "%s: poll returned %d: %m\n", 1137 __func__, poll_ret); 1138 } 1139 #endif 1140 /* FALLTHROUGH */ 1141 case 0: 1142 cleanfds = svc_fdset; 1143 __svc_clean_idle(&cleanfds, 30, FALSE); 1144 continue; 1145 default: 1146 #ifdef SVC_RUN_DEBUG 1147 if (debugging) { 1148 fprintf(stderr, "%s: poll returned read fds < ", 1149 __func__); 1150 for (i = 0, p = pollfds; i < nfds; i++, p++) 1151 if (p->revents) 1152 fprintf(stderr, "%d (%#x)", 1153 p->fd, p->revents); 1154 fprintf(stderr, ">\n"); 1155 } 1156 #endif 1157 /* 1158 * If we found as many replies on callback fds 1159 * as the number of descriptors selectable which 1160 * poll() returned, there can be no more so we 1161 * don't call svc_getreq_poll. Otherwise, there 1162 * must be another so we must call svc_getreq_poll. 1163 */ 1164 if ((check_ret = check_rmtcalls(pollfds, nfds)) == 1165 poll_ret) 1166 continue; 1167 svc_getreq_poll(pollfds, poll_ret-check_ret); 1168 } 1169 #ifdef SVC_RUN_DEBUG 1170 if (debugging) { 1171 fprintf(stderr, "%s: svc_maxfd now %u\n", __func__, 1172 svc_maxfd); 1173 } 1174 #endif 1175 } 1176 } 1177 1178 static int 1179 check_rmtcalls(struct pollfd *pfds, int nfds) 1180 { 1181 int j, ncallbacks_found = 0, rmtcalls_pending; 1182 SVCXPRT *xprt; 1183 1184 if (rpcb_rmtcalls == 0) 1185 return (0); 1186 1187 rmtcalls_pending = rpcb_rmtcalls; 1188 for (j = 0; j < nfds; j++) { 1189 if ((xprt = find_rmtcallxprt_by_fd(pfds[j].fd)) != NULL) { 1190 if (pfds[j].revents) { 1191 ncallbacks_found++; 1192 #ifdef DEBUG_RMTCALL 1193 if (debugging) 1194 fprintf(stderr, "%s: polled on forwarding " 1195 "fd %d, netid %s - calling handle_reply\n", 1196 __func__, pfds[j].fd, xprt->xp_netid); 1197 #endif 1198 handle_reply(pfds[j].fd, xprt); 1199 pfds[j].revents = 0; 1200 if (ncallbacks_found >= rmtcalls_pending) { 1201 break; 1202 } 1203 } 1204 } 1205 } 1206 return (ncallbacks_found); 1207 } 1208 1209 static void 1210 xprt_set_caller(SVCXPRT *xprt, struct finfo *fi) 1211 { 1212 u_int32_t *xidp; 1213 1214 netbuf_copybuf(svc_getrpccaller(xprt), fi->caller_addr); 1215 xidp = __rpcb_get_dg_xidp(xprt); 1216 *xidp = fi->caller_xid; 1217 } 1218 1219 /* 1220 * Call svcerr_systemerr() only if RPCBVERS4 1221 */ 1222 static void 1223 send_svcsyserr(SVCXPRT *xprt, struct finfo *fi) 1224 { 1225 if (fi->reply_type == RPCBPROC_INDIRECT) { 1226 xprt_set_caller(xprt, fi); 1227 svcerr_systemerr(xprt); 1228 } 1229 } 1230 1231 static void 1232 handle_reply(int fd, SVCXPRT *xprt) 1233 { 1234 XDR reply_xdrs; 1235 struct rpc_msg reply_msg; 1236 struct rpc_err reply_error; 1237 char *buffer; 1238 struct finfo *fi; 1239 int inlen, pos, len; 1240 struct r_rmtcall_args a; 1241 struct sockaddr_storage ss; 1242 socklen_t fromlen; 1243 #ifdef SVC_RUN_DEBUG 1244 char *uaddr; 1245 #endif 1246 1247 buffer = malloc(RPC_BUF_MAX); 1248 if (buffer == NULL) 1249 goto done; 1250 1251 do { 1252 fromlen = sizeof(ss); 1253 inlen = recvfrom(fd, buffer, RPC_BUF_MAX, 0, 1254 (struct sockaddr *)&ss, &fromlen); 1255 } while (inlen < 0 && errno == EINTR); 1256 if (inlen < 0) { 1257 if (debugging) 1258 fprintf(stderr, "%s: recvfrom returned %d: %m\n", 1259 __func__, inlen); 1260 goto done; 1261 } 1262 1263 reply_msg.acpted_rply.ar_verf = _null_auth; 1264 reply_msg.acpted_rply.ar_results.where = 0; 1265 reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void; 1266 1267 xdrmem_create(&reply_xdrs, buffer, (u_int)inlen, XDR_DECODE); 1268 if (!xdr_replymsg(&reply_xdrs, &reply_msg)) { 1269 if (debugging) 1270 fprintf(stderr, "%s: xdr_replymsg failed\n", __func__); 1271 goto done; 1272 } 1273 fi = forward_find(reply_msg.rm_xid); 1274 #ifdef SVC_RUN_DEBUG 1275 if (debugging) { 1276 fprintf(stderr, "%s: reply xid: %d fi addr: %p\n", 1277 __func__, reply_msg.rm_xid, fi); 1278 } 1279 #endif 1280 if (fi == NULL) { 1281 goto done; 1282 } 1283 _seterr_reply(&reply_msg, &reply_error); 1284 if (reply_error.re_status != RPC_SUCCESS) { 1285 if (debugging) 1286 fprintf(stderr, "%s: %s\n", __func__, 1287 clnt_sperrno(reply_error.re_status)); 1288 send_svcsyserr(xprt, fi); 1289 goto done; 1290 } 1291 pos = XDR_GETPOS(&reply_xdrs); 1292 len = inlen - pos; 1293 a.rmt_args.args = &buffer[pos]; 1294 a.rmt_args.arglen = len; 1295 a.rmt_uaddr = fi->uaddr; 1296 a.rmt_localvers = fi->versnum; 1297 1298 xprt_set_caller(xprt, fi); 1299 #ifdef SVC_RUN_DEBUG 1300 uaddr = taddr2uaddr(rpcbind_get_conf("udp"), 1301 svc_getrpccaller(xprt)); 1302 if (debugging) { 1303 fprintf(stderr, "%s: forwarding address %s to %s\n", 1304 __func__, a.rmt_uaddr, uaddr ? uaddr : rpcbind_unknown); 1305 } 1306 free(uaddr); 1307 #endif 1308 svc_sendreply(xprt, (xdrproc_t)xdr_rmtcall_result, &a); 1309 done: 1310 free(buffer); 1311 1312 if (reply_msg.rm_xid == 0) { 1313 #ifdef SVC_RUN_DEBUG 1314 if (debugging) { 1315 fprintf(stderr, "%s: NULL xid on exit!\n", __func__); 1316 } 1317 #endif 1318 } else 1319 (void)free_slot_by_xid(reply_msg.rm_xid); 1320 } 1321 1322 static void 1323 find_versions(rpcprog_t prog, const char *netid, rpcvers_t *lowvp, 1324 rpcvers_t *highvp) 1325 { 1326 rpcblist_ptr rbl; 1327 rpcvers_t lowv = 0; 1328 rpcvers_t highv = 0; 1329 1330 for (rbl = list_rbl; rbl != NULL; rbl = rbl->rpcb_next) { 1331 if ((rbl->rpcb_map.r_prog != prog) || 1332 ((rbl->rpcb_map.r_netid != NULL) && 1333 (strcasecmp(rbl->rpcb_map.r_netid, netid) != 0))) 1334 continue; 1335 if (lowv == 0) { 1336 highv = rbl->rpcb_map.r_vers; 1337 lowv = highv; 1338 } else if (rbl->rpcb_map.r_vers < lowv) { 1339 lowv = rbl->rpcb_map.r_vers; 1340 } else if (rbl->rpcb_map.r_vers > highv) { 1341 highv = rbl->rpcb_map.r_vers; 1342 } 1343 } 1344 *lowvp = lowv; 1345 *highvp = highv; 1346 } 1347 1348 /* 1349 * returns the item with the given program, version number and netid. 1350 * If that version number is not found, it returns the item with that 1351 * program number, so that address is now returned to the caller. The 1352 * caller when makes a call to this program, version number, the call 1353 * will fail and it will return with PROGVERS_MISMATCH. The user can 1354 * then determine the highest and the lowest version number for this 1355 * program using clnt_geterr() and use those program version numbers. 1356 * 1357 * Returns the RPCBLIST for the given prog, vers and netid 1358 */ 1359 static rpcblist_ptr 1360 find_service(rpcprog_t prog, rpcvers_t vers, char *netid) 1361 { 1362 rpcblist_ptr hit = NULL; 1363 rpcblist_ptr rbl; 1364 1365 for (rbl = list_rbl; rbl != NULL; rbl = rbl->rpcb_next) { 1366 if ((rbl->rpcb_map.r_prog != prog) || 1367 ((rbl->rpcb_map.r_netid != NULL) && 1368 (strcasecmp(rbl->rpcb_map.r_netid, netid) != 0))) 1369 continue; 1370 hit = rbl; 1371 if (rbl->rpcb_map.r_vers == vers) 1372 break; 1373 } 1374 return (hit); 1375 } 1376 1377 /* 1378 * Copies the name associated with the uid of the caller and returns 1379 * a pointer to it. Similar to getwd(). 1380 */ 1381 static char * 1382 getowner(SVCXPRT *transp, char *owner, size_t ownersize) 1383 { 1384 uid_t uid; 1385 1386 if (__rpc_get_local_uid(transp, &uid) < 0) 1387 strlcpy(owner, rpcbind_unknown, ownersize); 1388 else if (uid == 0) 1389 strlcpy(owner, rpcbind_superuser, ownersize); 1390 else 1391 snprintf(owner, ownersize, "%d", uid); 1392 1393 return owner; 1394 } 1395 1396 #ifdef PORTMAP 1397 /* 1398 * Add this to the pmap list only if it is UDP or TCP. 1399 */ 1400 static int 1401 add_pmaplist(RPCB *arg) 1402 { 1403 struct pmap pmap; 1404 struct pmaplist *pml; 1405 int h1, h2, h3, h4, p1, p2; 1406 1407 if (strcmp(arg->r_netid, udptrans) == 0) { 1408 /* It is UDP! */ 1409 pmap.pm_prot = IPPROTO_UDP; 1410 } else if (strcmp(arg->r_netid, tcptrans) == 0) { 1411 /* It is TCP */ 1412 pmap.pm_prot = IPPROTO_TCP; 1413 } else 1414 /* Not an IP protocol */ 1415 return (0); 1416 1417 /* interpret the universal address for TCP/IP */ 1418 if (sscanf(arg->r_addr, "%d.%d.%d.%d.%d.%d", 1419 &h1, &h2, &h3, &h4, &p1, &p2) != 6) 1420 return (0); 1421 pmap.pm_port = ((p1 & 0xff) << 8) + (p2 & 0xff); 1422 pmap.pm_prog = arg->r_prog; 1423 pmap.pm_vers = arg->r_vers; 1424 /* 1425 * add to END of list 1426 */ 1427 pml = malloc(sizeof(*pml)); 1428 if (pml == NULL) { 1429 syslog(LOG_ERR, "%s: %m", __func__); 1430 return (1); 1431 } 1432 pml->pml_map = pmap; 1433 pml->pml_next = NULL; 1434 if (list_pml == NULL) { 1435 list_pml = pml; 1436 } else { 1437 struct pmaplist *fnd; 1438 1439 /* Attach to the end of the list */ 1440 for (fnd = list_pml; fnd->pml_next; fnd = fnd->pml_next) 1441 continue; 1442 fnd->pml_next = pml; 1443 } 1444 return (0); 1445 } 1446 1447 /* 1448 * Delete this from the pmap list only if it is UDP or TCP. 1449 */ 1450 static int 1451 del_pmaplist(RPCB *arg) 1452 { 1453 struct pmaplist *pml; 1454 struct pmaplist *prevpml, *fnd; 1455 unsigned long prot; 1456 1457 if (strcmp(arg->r_netid, udptrans) == 0) { 1458 /* It is UDP! */ 1459 prot = IPPROTO_UDP; 1460 } else if (strcmp(arg->r_netid, tcptrans) == 0) { 1461 /* It is TCP */ 1462 prot = IPPROTO_TCP; 1463 } else if (arg->r_netid[0] == 0) { 1464 prot = 0; /* Remove all occurrences */ 1465 } else { 1466 /* Not an IP protocol */ 1467 return (0); 1468 } 1469 for (prevpml = NULL, pml = list_pml; pml; /* cstyle */) { 1470 if ((pml->pml_map.pm_prog != arg->r_prog) || 1471 (pml->pml_map.pm_vers != arg->r_vers) || 1472 (prot && (pml->pml_map.pm_prot != prot))) { 1473 /* both pml & prevpml move forwards */ 1474 prevpml = pml; 1475 pml = pml->pml_next; 1476 continue; 1477 } 1478 /* found it; pml moves forward, prevpml stays */ 1479 fnd = pml; 1480 pml = pml->pml_next; 1481 if (prevpml == NULL) 1482 list_pml = pml; 1483 else 1484 prevpml->pml_next = pml; 1485 free(fnd); 1486 } 1487 return (0); 1488 } 1489 #endif /* PORTMAP */ 1490