1/* $NetBSD: rpcb_svc_com.c,v 1.9 2002/11/08 00:16:39 fvdl Exp $ */ 2/* $FreeBSD: stable/10/usr.sbin/rpcbind/rpcb_svc_com.c 319615 2017-06-06 07:22:26Z delphij $ */ 3 4/* 5 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 6 * unrestricted use provided that this legend is included on all tape 7 * media and as a part of the software program in whole or part. Users 8 * may copy or modify Sun RPC without charge, but are not authorized 9 * to license or distribute it to anyone else except as part of a product or 10 * program developed by the user. 11 * 12 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 13 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 14 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 15 * 16 * Sun RPC is provided with no support and without any obligation on the 17 * part of Sun Microsystems, Inc. to assist in its use, correction, 18 * modification or enhancement. 19 * 20 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 21 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 22 * OR ANY PART THEREOF. 23 * 24 * In no event will Sun Microsystems, Inc. be liable for any lost revenue 25 * or profits or other special, indirect and consequential damages, even if 26 * Sun has been advised of the possibility of such damages. 27 * 28 * Sun Microsystems, Inc. 29 * 2550 Garcia Avenue 30 * Mountain View, California 94043 31 */ 32/* 33 * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc. 34 */ 35 36/* #ident "@(#)rpcb_svc_com.c 1.18 94/05/02 SMI" */ 37 38/* 39 * rpcb_svc_com.c 40 * The commom server procedure for the rpcbind. 41 */ 42 43#include <sys/types.h> 44#include <sys/stat.h> 45#include <sys/param.h> 46#include <sys/poll.h> 47#include <sys/socket.h> 48#include <rpc/rpc.h> 49#include <rpc/rpcb_prot.h> 50#include <rpc/svc_dg.h> 51#include <assert.h> 52#include <netconfig.h> 53#include <errno.h> 54#include <syslog.h> 55#include <unistd.h> 56#include <stdio.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#include <string.h> 63#include <stdlib.h> 64 65#include "rpcbind.h" 66 67#define RPC_BUF_MAX 65536 /* can be raised if required */ 68 69static char *nullstring = ""; 70static int rpcb_rmtcalls; 71 72struct rmtcallfd_list { 73 int fd; 74 SVCXPRT *xprt; 75 char *netid; 76 struct rmtcallfd_list *next; 77}; 78 79#define NFORWARD 64 80#define MAXTIME_OFF 300 /* 5 minutes */ 81 82struct finfo { 83 int flag; 84#define FINFO_ACTIVE 0x1 85 u_int32_t caller_xid; 86 struct netbuf *caller_addr; 87 u_int32_t forward_xid; 88 int forward_fd; 89 char *uaddr; 90 rpcproc_t reply_type; 91 rpcvers_t versnum; 92 time_t time; 93}; 94static struct finfo FINFO[NFORWARD]; 95 96 97static bool_t xdr_encap_parms(XDR *, struct encap_parms *); 98static bool_t xdr_rmtcall_args(XDR *, struct r_rmtcall_args *); 99static bool_t xdr_rmtcall_result(XDR *, struct r_rmtcall_args *); 100static bool_t xdr_opaque_parms(XDR *, struct r_rmtcall_args *); 101static int find_rmtcallfd_by_netid(char *); 102static SVCXPRT *find_rmtcallxprt_by_fd(int); 103static int forward_register(u_int32_t, struct netbuf *, int, char *, 104 rpcproc_t, rpcvers_t, u_int32_t *); 105static struct finfo *forward_find(u_int32_t); 106static int free_slot_by_xid(u_int32_t); 107static int free_slot_by_index(int); 108static int netbufcmp(struct netbuf *, struct netbuf *); 109static struct netbuf *netbufdup(struct netbuf *); 110static void netbuffree(struct netbuf *); 111static int check_rmtcalls(struct pollfd *, int); 112static void xprt_set_caller(SVCXPRT *, struct finfo *); 113static void send_svcsyserr(SVCXPRT *, struct finfo *); 114static void handle_reply(int, SVCXPRT *); 115static void find_versions(rpcprog_t, char *, rpcvers_t *, rpcvers_t *); 116static rpcblist_ptr find_service(rpcprog_t, rpcvers_t, char *); 117static char *getowner(SVCXPRT *, char *, size_t); 118static int add_pmaplist(RPCB *); 119static int del_pmaplist(RPCB *); 120 121/* 122 * Set a mapping of program, version, netid 123 */ 124/* ARGSUSED */ 125void * 126rpcbproc_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 149bool_t 150map_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 = (rpcblist_ptr)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 (void) add_pmaplist(regp); 205#endif 206 return (TRUE); 207} 208 209/* 210 * Unset a mapping of program, version, netid 211 */ 212/* ARGSUSED */ 213void * 214rpcbproc_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 237bool_t 238map_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 (void) 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 288void 289delete_prog(unsigned int prog) 290{ 291 RPCB reg; 292 register 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 (void) map_unset(®, "superuser"); 303 free(reg.r_netid); 304 } 305} 306 307void * 308rpcbproc_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 */ 350void * 351rpcbproc_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 (void) 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 */ 365void * 366rpcbproc_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 (void) 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 */ 392void * 393rpcbproc_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 420static bool_t 421xdr_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 */ 431static bool_t 432xdr_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 */ 448static bool_t 449xdr_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 */ 481static bool_t 482xdr_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 487static struct rmtcallfd_list *rmthead; 488static struct rmtcallfd_list *rmttail; 489 490int 491create_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, (struct t_bind *) 0, 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 535static int 536find_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 548static SVCXPRT * 549find_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 600void 601rpcbproc_callit_com(struct svc_req *rqstp, SVCXPRT *transp, 602 rpcproc_t reply_type, rpcvers_t versnum) 603{ 604 register 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 = (struct netbuf *) 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 = ((sendsz + 3) / 4) * 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 == (rpcblist_ptr)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 == (struct netconfig *)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 908error: 909 if (call_msg.rm_xid != 0) 910 (void) free_slot_by_xid(call_msg.rm_xid); 911out: 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 */ 931static int 932forward_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((time_t *)0); 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((time_t *)0); 961 return (0); /* Duplicate entry */ 962 } else { 963 /* Should we wait any longer */ 964 if ((time_now - FINFO[i].time) > MAXTIME_OFF) 965 (void) 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 (void) 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 1007static struct finfo * 1008forward_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 1020static int 1021free_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 1029static int 1030free_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 1048static int 1049netbufcmp(struct netbuf *n1, struct netbuf *n2) 1050{ 1051 return ((n1->len != n2->len) || memcmp(n1->buf, n2->buf, n1->len)); 1052} 1053 1054static bool_t 1055netbuf_copybuf(struct netbuf *dst, const struct netbuf *src) 1056{ 1057 1058 if (dst->len != src->len || dst->buf == NULL) { 1059 if (dst->buf != NULL) 1060 free(dst->buf); 1061 if ((dst->buf = malloc(src->len)) == NULL) 1062 return (FALSE); 1063 1064 dst->maxlen = dst->len = src->len; 1065 } 1066 1067 memcpy(dst->buf, src->buf, src->len); 1068 return (TRUE); 1069} 1070 1071static struct netbuf * 1072netbufdup(struct netbuf *ap) 1073{ 1074 struct netbuf *np; 1075 1076 if ((np = calloc(1, sizeof(struct netbuf))) == NULL) 1077 return (NULL); 1078 if (netbuf_copybuf(np, ap) == FALSE) { 1079 free(np); 1080 return (NULL); 1081 } 1082 return (np); 1083} 1084 1085static void 1086netbuffree(struct netbuf *ap) 1087{ 1088 free(ap->buf); 1089 ap->buf = NULL; 1090 free(ap); 1091} 1092 1093 1094#define MASKVAL (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND) 1095extern bool_t __svc_clean_idle(fd_set *, int, bool_t); 1096 1097void 1098my_svc_run(void) 1099{ 1100 size_t nfds; 1101 struct pollfd pollfds[FD_SETSIZE]; 1102 int poll_ret, check_ret; 1103 int n; 1104#ifdef SVC_RUN_DEBUG 1105 int i; 1106#endif 1107 register struct pollfd *p; 1108 fd_set cleanfds; 1109 1110 for (;;) { 1111 p = pollfds; 1112 for (n = 0; n <= svc_maxfd; n++) { 1113 if (FD_ISSET(n, &svc_fdset)) { 1114 p->fd = n; 1115 p->events = MASKVAL; 1116 p++; 1117 } 1118 } 1119 nfds = p - pollfds; 1120 poll_ret = 0; 1121#ifdef SVC_RUN_DEBUG 1122 if (debugging) { 1123 fprintf(stderr, "polling for read on fd < "); 1124 for (i = 0, p = pollfds; i < nfds; i++, p++) 1125 if (p->events) 1126 fprintf(stderr, "%d ", p->fd); 1127 fprintf(stderr, ">\n"); 1128 } 1129#endif 1130 switch (poll_ret = poll(pollfds, nfds, 30 * 1000)) { 1131 case -1: 1132 /* 1133 * We ignore all errors, continuing with the assumption 1134 * that it was set by the signal handlers (or any 1135 * other outside event) and not caused by poll(). 1136 */ 1137 case 0: 1138 cleanfds = svc_fdset; 1139 __svc_clean_idle(&cleanfds, 30, FALSE); 1140 continue; 1141 default: 1142#ifdef SVC_RUN_DEBUG 1143 if (debugging) { 1144 fprintf(stderr, "poll returned read fds < "); 1145 for (i = 0, p = pollfds; i < nfds; i++, p++) 1146 if (p->revents) 1147 fprintf(stderr, "%d ", p->fd); 1148 fprintf(stderr, ">\n"); 1149 } 1150#endif 1151 /* 1152 * If we found as many replies on callback fds 1153 * as the number of descriptors selectable which 1154 * poll() returned, there can be no more so we 1155 * don't call svc_getreq_poll. Otherwise, there 1156 * must be another so we must call svc_getreq_poll. 1157 */ 1158 if ((check_ret = check_rmtcalls(pollfds, nfds)) == 1159 poll_ret) 1160 continue; 1161 svc_getreq_poll(pollfds, poll_ret-check_ret); 1162 } 1163#ifdef SVC_RUN_DEBUG 1164 if (debugging) { 1165 fprintf(stderr, "svc_maxfd now %u\n", svc_maxfd); 1166 } 1167#endif 1168 } 1169} 1170 1171static int 1172check_rmtcalls(struct pollfd *pfds, int nfds) 1173{ 1174 int j, ncallbacks_found = 0, rmtcalls_pending; 1175 SVCXPRT *xprt; 1176 1177 if (rpcb_rmtcalls == 0) 1178 return (0); 1179 1180 rmtcalls_pending = rpcb_rmtcalls; 1181 for (j = 0; j < nfds; j++) { 1182 if ((xprt = find_rmtcallxprt_by_fd(pfds[j].fd)) != NULL) { 1183 if (pfds[j].revents) { 1184 ncallbacks_found++; 1185#ifdef DEBUG_RMTCALL 1186 if (debugging) 1187 fprintf(stderr, 1188"my_svc_run: polled on forwarding fd %d, netid %s - calling handle_reply\n", 1189 pfds[j].fd, xprt->xp_netid); 1190#endif 1191 handle_reply(pfds[j].fd, xprt); 1192 pfds[j].revents = 0; 1193 if (ncallbacks_found >= rmtcalls_pending) { 1194 break; 1195 } 1196 } 1197 } 1198 } 1199 return (ncallbacks_found); 1200} 1201 1202static void 1203xprt_set_caller(SVCXPRT *xprt, struct finfo *fi) 1204{ 1205 u_int32_t *xidp; 1206 1207 netbuf_copybuf(svc_getrpccaller(xprt), fi->caller_addr); 1208 xidp = __rpcb_get_dg_xidp(xprt); 1209 *xidp = fi->caller_xid; 1210} 1211 1212/* 1213 * Call svcerr_systemerr() only if RPCBVERS4 1214 */ 1215static void 1216send_svcsyserr(SVCXPRT *xprt, struct finfo *fi) 1217{ 1218 if (fi->reply_type == RPCBPROC_INDIRECT) { 1219 xprt_set_caller(xprt, fi); 1220 svcerr_systemerr(xprt); 1221 } 1222 return; 1223} 1224 1225static void 1226handle_reply(int fd, SVCXPRT *xprt) 1227{ 1228 XDR reply_xdrs; 1229 struct rpc_msg reply_msg; 1230 struct rpc_err reply_error; 1231 char *buffer; 1232 struct finfo *fi; 1233 int inlen, pos, len; 1234 struct r_rmtcall_args a; 1235 struct sockaddr_storage ss; 1236 socklen_t fromlen; 1237#ifdef SVC_RUN_DEBUG 1238 char *uaddr; 1239#endif 1240 1241 buffer = malloc(RPC_BUF_MAX); 1242 if (buffer == NULL) 1243 goto done; 1244 1245 do { 1246 fromlen = sizeof(ss); 1247 inlen = recvfrom(fd, buffer, RPC_BUF_MAX, 0, 1248 (struct sockaddr *)&ss, &fromlen); 1249 } while (inlen < 0 && errno == EINTR); 1250 if (inlen < 0) { 1251 if (debugging) 1252 fprintf(stderr, 1253 "handle_reply: recvfrom returned %d, errno %d\n", inlen, errno); 1254 goto done; 1255 } 1256 1257 reply_msg.acpted_rply.ar_verf = _null_auth; 1258 reply_msg.acpted_rply.ar_results.where = 0; 1259 reply_msg.acpted_rply.ar_results.proc = (xdrproc_t) xdr_void; 1260 1261 xdrmem_create(&reply_xdrs, buffer, (u_int)inlen, XDR_DECODE); 1262 if (!xdr_replymsg(&reply_xdrs, &reply_msg)) { 1263 if (debugging) 1264 (void) fprintf(stderr, 1265 "handle_reply: xdr_replymsg failed\n"); 1266 goto done; 1267 } 1268 fi = forward_find(reply_msg.rm_xid); 1269#ifdef SVC_RUN_DEBUG 1270 if (debugging) { 1271 fprintf(stderr, "handle_reply: reply xid: %d fi addr: %p\n", 1272 reply_msg.rm_xid, fi); 1273 } 1274#endif 1275 if (fi == NULL) { 1276 goto done; 1277 } 1278 _seterr_reply(&reply_msg, &reply_error); 1279 if (reply_error.re_status != RPC_SUCCESS) { 1280 if (debugging) 1281 (void) fprintf(stderr, "handle_reply: %s\n", 1282 clnt_sperrno(reply_error.re_status)); 1283 send_svcsyserr(xprt, fi); 1284 goto done; 1285 } 1286 pos = XDR_GETPOS(&reply_xdrs); 1287 len = inlen - pos; 1288 a.rmt_args.args = &buffer[pos]; 1289 a.rmt_args.arglen = len; 1290 a.rmt_uaddr = fi->uaddr; 1291 a.rmt_localvers = fi->versnum; 1292 1293 xprt_set_caller(xprt, fi); 1294#ifdef SVC_RUN_DEBUG 1295 uaddr = taddr2uaddr(rpcbind_get_conf("udp"), 1296 svc_getrpccaller(xprt)); 1297 if (debugging) { 1298 fprintf(stderr, "handle_reply: forwarding address %s to %s\n", 1299 a.rmt_uaddr, uaddr ? uaddr : "unknown"); 1300 } 1301 if (uaddr) 1302 free(uaddr); 1303#endif 1304 svc_sendreply(xprt, (xdrproc_t) xdr_rmtcall_result, (char *) &a); 1305done: 1306 if (buffer) 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 return; 1318} 1319 1320static void 1321find_versions(rpcprog_t prog, char *netid, rpcvers_t *lowvp, rpcvers_t *highvp) 1322{ 1323 register rpcblist_ptr rbl; 1324 unsigned int lowv = 0; 1325 unsigned int highv = 0; 1326 1327 for (rbl = list_rbl; rbl != NULL; rbl = rbl->rpcb_next) { 1328 if ((rbl->rpcb_map.r_prog != prog) || 1329 ((rbl->rpcb_map.r_netid != NULL) && 1330 (strcasecmp(rbl->rpcb_map.r_netid, netid) != 0))) 1331 continue; 1332 if (lowv == 0) { 1333 highv = rbl->rpcb_map.r_vers; 1334 lowv = highv; 1335 } else if (rbl->rpcb_map.r_vers < lowv) { 1336 lowv = rbl->rpcb_map.r_vers; 1337 } else if (rbl->rpcb_map.r_vers > highv) { 1338 highv = rbl->rpcb_map.r_vers; 1339 } 1340 } 1341 *lowvp = lowv; 1342 *highvp = highv; 1343 return; 1344} 1345 1346/* 1347 * returns the item with the given program, version number and netid. 1348 * If that version number is not found, it returns the item with that 1349 * program number, so that address is now returned to the caller. The 1350 * caller when makes a call to this program, version number, the call 1351 * will fail and it will return with PROGVERS_MISMATCH. The user can 1352 * then determine the highest and the lowest version number for this 1353 * program using clnt_geterr() and use those program version numbers. 1354 * 1355 * Returns the RPCBLIST for the given prog, vers and netid 1356 */ 1357static rpcblist_ptr 1358find_service(rpcprog_t prog, rpcvers_t vers, char *netid) 1359{ 1360 register rpcblist_ptr hit = NULL; 1361 register rpcblist_ptr rbl; 1362 1363 for (rbl = list_rbl; rbl != NULL; rbl = rbl->rpcb_next) { 1364 if ((rbl->rpcb_map.r_prog != prog) || 1365 ((rbl->rpcb_map.r_netid != NULL) && 1366 (strcasecmp(rbl->rpcb_map.r_netid, netid) != 0))) 1367 continue; 1368 hit = rbl; 1369 if (rbl->rpcb_map.r_vers == vers) 1370 break; 1371 } 1372 return (hit); 1373} 1374 1375/* 1376 * Copies the name associated with the uid of the caller and returns 1377 * a pointer to it. Similar to getwd(). 1378 */ 1379static char * 1380getowner(SVCXPRT *transp, char *owner, size_t ownersize) 1381{ 1382 uid_t uid; 1383 1384 if (__rpc_get_local_uid(transp, &uid) < 0) 1385 strlcpy(owner, "unknown", ownersize); 1386 else if (uid == 0) 1387 strlcpy(owner, "superuser", ownersize); 1388 else 1389 snprintf(owner, ownersize, "%d", uid); 1390 1391 return owner; 1392} 1393 1394#ifdef PORTMAP 1395/* 1396 * Add this to the pmap list only if it is UDP or TCP. 1397 */ 1398static int 1399add_pmaplist(RPCB *arg) 1400{ 1401 struct pmap pmap; 1402 struct pmaplist *pml; 1403 int h1, h2, h3, h4, p1, p2; 1404 1405 if (strcmp(arg->r_netid, udptrans) == 0) { 1406 /* It is UDP! */ 1407 pmap.pm_prot = IPPROTO_UDP; 1408 } else if (strcmp(arg->r_netid, tcptrans) == 0) { 1409 /* It is TCP */ 1410 pmap.pm_prot = IPPROTO_TCP; 1411 } else 1412 /* Not an IP protocol */ 1413 return (0); 1414 1415 /* interpret the universal address for TCP/IP */ 1416 if (sscanf(arg->r_addr, "%d.%d.%d.%d.%d.%d", 1417 &h1, &h2, &h3, &h4, &p1, &p2) != 6) 1418 return (0); 1419 pmap.pm_port = ((p1 & 0xff) << 8) + (p2 & 0xff); 1420 pmap.pm_prog = arg->r_prog; 1421 pmap.pm_vers = arg->r_vers; 1422 /* 1423 * add to END of list 1424 */ 1425 pml = malloc(sizeof (struct pmaplist)); 1426 if (pml == NULL) { 1427 (void) syslog(LOG_ERR, "rpcbind: no memory!\n"); 1428 return (1); 1429 } 1430 pml->pml_map = pmap; 1431 pml->pml_next = NULL; 1432 if (list_pml == NULL) { 1433 list_pml = pml; 1434 } else { 1435 struct pmaplist *fnd; 1436 1437 /* Attach to the end of the list */ 1438 for (fnd = list_pml; fnd->pml_next; fnd = fnd->pml_next) 1439 ; 1440 fnd->pml_next = pml; 1441 } 1442 return (0); 1443} 1444 1445/* 1446 * Delete this from the pmap list only if it is UDP or TCP. 1447 */ 1448static int 1449del_pmaplist(RPCB *arg) 1450{ 1451 struct pmaplist *pml; 1452 struct pmaplist *prevpml, *fnd; 1453 unsigned long prot; 1454 1455 if (strcmp(arg->r_netid, udptrans) == 0) { 1456 /* It is UDP! */ 1457 prot = IPPROTO_UDP; 1458 } else if (strcmp(arg->r_netid, tcptrans) == 0) { 1459 /* It is TCP */ 1460 prot = IPPROTO_TCP; 1461 } else if (arg->r_netid[0] == 0) { 1462 prot = 0; /* Remove all occurrences */ 1463 } else { 1464 /* Not an IP protocol */ 1465 return (0); 1466 } 1467 for (prevpml = NULL, pml = list_pml; pml; /* cstyle */) { 1468 if ((pml->pml_map.pm_prog != arg->r_prog) || 1469 (pml->pml_map.pm_vers != arg->r_vers) || 1470 (prot && (pml->pml_map.pm_prot != prot))) { 1471 /* both pml & prevpml move forwards */ 1472 prevpml = pml; 1473 pml = pml->pml_next; 1474 continue; 1475 } 1476 /* found it; pml moves forward, prevpml stays */ 1477 fnd = pml; 1478 pml = pml->pml_next; 1479 if (prevpml == NULL) 1480 list_pml = pml; 1481 else 1482 prevpml->pml_next = pml; 1483 free(fnd); 1484 } 1485 return (0); 1486} 1487#endif /* PORTMAP */ 1488