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