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