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 /* 29 * Copyright (c) 1986-1991 by Sun Microsystems Inc. 30 */ 31 //#include <sys/cdefs.h> 32 33 /* 34 * clnt_bcast.c 35 * Client interface to broadcast service. 36 * 37 * Copyright (C) 1988, Sun Microsystems, Inc. 38 * 39 * The following is kludged-up support for simple rpc broadcasts. 40 * Someday a large, complicated system will replace these routines. 41 */ 42 43 #include <wintirpc.h> 44 //#include <sys/socket.h> 45 #include <sys/types.h> 46 //#include <sys/queue.h> 47 48 /* new queue functions */ 49 //#include <misc/queue.h> 50 51 //#include <net/if.h> 52 //#include <netinet/in.h> 53 //#include <ifaddrs.h> 54 //#include <sys/poll.h> 55 #include <rpc/rpc.h> 56 #ifdef PORTMAP 57 #include <rpc/pmap_prot.h> 58 #include <rpc/pmap_clnt.h> 59 #include <rpc/pmap_rmt.h> 60 #endif /* PORTMAP */ 61 #include <rpc/nettype.h> 62 //#include <arpa/inet.h> 63 #ifdef RPC_DEBUG 64 #include <stdio.h> 65 #endif 66 #include <errno.h> 67 #include <stdlib.h> 68 //#include <unistd.h> 69 //#include <netdb.h> 70 //#include <err.h> 71 #include <string.h> 72 73 #include "rpc_com.h" 74 75 #define MAXBCAST 20 /* Max no of broadcasting transports */ 76 #define INITTIME 4000 /* Time to wait initially */ 77 #define WAITTIME 8000 /* Maximum time to wait */ 78 79 #ifndef POLLRDNORM 80 # define POLLRDNORM 0x040 /* Normal data may be read. */ 81 #endif 82 #ifndef POLLRDBAND 83 # define POLLRDBAND 0x080 /* Priority data may be read. */ 84 #endif 85 86 /* 87 * For now, ASSUME that we do not need this for the Windows port!!!! 88 */ 89 #include <wintirpc.h> 90 #ifdef _WIN32 91 int __rpc_lowvers = 0; 92 93 enum clnt_stat 94 rpc_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, 95 eachresult, nettype) 96 rpcprog_t prog; /* program number */ 97 rpcvers_t vers; /* version number */ 98 rpcproc_t proc; /* procedure number */ 99 xdrproc_t xargs; /* xdr routine for args */ 100 caddr_t argsp; /* pointer to args */ 101 xdrproc_t xresults; /* xdr routine for results */ 102 caddr_t resultsp; /* pointer to results */ 103 resultproc_t eachresult; /* call with each result obtained */ 104 const char *nettype; /* transport type */ 105 { 106 return 0; 107 } 108 #else 109 110 111 /* 112 * If nettype is NULL, it broadcasts on all the available 113 * datagram_n transports. May potentially lead to broadacst storms 114 * and hence should be used with caution, care and courage. 115 * 116 * The current parameter xdr packet size is limited by the max tsdu 117 * size of the transport. If the max tsdu size of any transport is 118 * smaller than the parameter xdr packet, then broadcast is not 119 * sent on that transport. 120 * 121 * Also, the packet size should be less the packet size of 122 * the data link layer (for ethernet it is 1400 bytes). There is 123 * no easy way to find out the max size of the data link layer and 124 * we are assuming that the args would be smaller than that. 125 * 126 * The result size has to be smaller than the transport tsdu size. 127 * 128 * If PORTMAP has been defined, we send two packets for UDP, one for 129 * rpcbind and one for portmap. For those machines which support 130 * both rpcbind and portmap, it will cause them to reply twice, and 131 * also here it will get two responses ... inefficient and clumsy. 132 */ 133 134 #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) 135 136 #define TAILQ_FIRST(head) ((head)->tqh_first) 137 138 139 struct broadif { 140 int index; 141 struct sockaddr_storage broadaddr; 142 TAILQ_ENTRY(broadif) link; 143 }; 144 145 typedef TAILQ_HEAD(, broadif) broadlist_t; 146 147 int __rpc_getbroadifs(int, int, int, broadlist_t *); 148 void __rpc_freebroadifs(broadlist_t *); 149 int __rpc_broadenable(int, int, struct broadif *); 150 151 int __rpc_lowvers = 0; 152 153 int 154 __rpc_getbroadifs(int af, int proto, int socktype, broadlist_t *list) 155 { 156 int count = 0; 157 struct broadif *bip; 158 struct ifaddrs *ifap, *ifp; 159 #ifdef INET6 160 struct sockaddr_in6 *sin6; 161 #endif 162 struct sockaddr_in *sin; 163 struct addrinfo hints, *res; 164 165 #if 0 /* WINDOWS */ 166 if (getifaddrs(&ifp) < 0) 167 return 0; 168 #else 169 /* Use GetAdaptersAddresses() ? */ 170 #endif 171 172 memset(&hints, 0, sizeof hints); 173 174 hints.ai_family = af; 175 hints.ai_protocol = proto; 176 hints.ai_socktype = socktype; 177 178 if (getaddrinfo(NULL, "sunrpc", &hints, &res) != 0) 179 return 0; 180 181 for (ifap = ifp; ifap != NULL; ifap = ifap->ifa_next) { 182 if (ifap->ifa_addr->sa_family != af || 183 !(ifap->ifa_flags & IFF_UP)) 184 continue; 185 bip = (struct broadif *)malloc(sizeof *bip); 186 if (bip == NULL) 187 break; 188 bip->index = if_nametoindex(ifap->ifa_name); 189 if ( 190 #ifdef INET6 191 af != AF_INET6 && 192 #endif 193 (ifap->ifa_flags & IFF_BROADCAST) && 194 ifap->ifa_broadaddr) { 195 /* memcpy(&bip->broadaddr, ifap->ifa_broadaddr, 196 (size_t)ifap->ifa_broadaddr->sa_len);*/ 197 memcpy(&bip->broadaddr, ifap->ifa_broadaddr, 198 sizeof(bip->broadaddr)); 199 sin = (struct sockaddr_in *)(void *)&bip->broadaddr; 200 sin->sin_port = 201 ((struct sockaddr_in *) 202 (void *)res->ai_addr)->sin_port; 203 } else 204 #ifdef INET6 205 if (af == AF_INET6 && (ifap->ifa_flags & IFF_MULTICAST)) { 206 sin6 = (struct sockaddr_in6 *)(void *)&bip->broadaddr; 207 inet_pton(af, RPCB_MULTICAST_ADDR, &sin6->sin6_addr); 208 sin6->sin6_family = af; 209 sin6->sin6_port = 210 ((struct sockaddr_in6 *) 211 (void *)res->ai_addr)->sin6_port; 212 sin6->sin6_scope_id = bip->index; 213 } else 214 #endif 215 { 216 free(bip); 217 continue; 218 } 219 TAILQ_INSERT_TAIL(list, bip, link); 220 count++; 221 } 222 freeifaddrs(ifp); 223 freeaddrinfo(res); 224 225 return count; 226 } 227 228 void 229 __rpc_freebroadifs(broadlist_t *list) 230 { 231 struct broadif *bip, *next; 232 233 bip = TAILQ_FIRST(list); 234 235 while (bip != NULL) { 236 next = TAILQ_NEXT(bip, link); 237 free(bip); 238 bip = next; 239 } 240 } 241 242 int 243 /*ARGSUSED*/ 244 __rpc_broadenable(int af, int s, struct broadif *bip) 245 { 246 int o = 1; 247 248 #if 0 249 if (af == AF_INET6) { 250 fprintf(stderr, "set v6 multicast if to %d\n", bip->index); 251 if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, &bip->index, 252 sizeof bip->index) < 0) 253 return -1; 254 } else 255 #endif 256 if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &o, sizeof o) == SOCKET_ERROR) 257 return -1; 258 259 return 0; 260 } 261 262 263 enum clnt_stat 264 rpc_broadcast_exp(prog, vers, proc, xargs, argsp, xresults, resultsp, 265 eachresult, inittime, waittime, nettype) 266 rpcprog_t prog; /* program number */ 267 rpcvers_t vers; /* version number */ 268 rpcproc_t proc; /* procedure number */ 269 xdrproc_t xargs; /* xdr routine for args */ 270 caddr_t argsp; /* pointer to args */ 271 xdrproc_t xresults; /* xdr routine for results */ 272 caddr_t resultsp; /* pointer to results */ 273 resultproc_t eachresult; /* call with each result obtained */ 274 int inittime; /* how long to wait initially */ 275 int waittime; /* maximum time to wait */ 276 const char *nettype; /* transport type */ 277 { 278 enum clnt_stat stat = RPC_SUCCESS; /* Return status */ 279 XDR xdr_stream; /* XDR stream */ 280 XDR *xdrs = &xdr_stream; 281 struct rpc_msg msg; /* RPC message */ 282 struct timeval t; 283 char *outbuf = NULL; /* Broadcast msg buffer */ 284 char *inbuf = NULL; /* Reply buf */ 285 int inlen; 286 u_int maxbufsize = 0; 287 AUTH *sys_auth = authunix_create_default(); 288 int i; 289 void *handle; 290 char uaddress[1024]; /* A self imposed limit */ 291 char *uaddrp = uaddress; 292 int pmap_reply_flag; /* reply recvd from PORTMAP */ 293 /* An array of all the suitable broadcast transports */ 294 struct { 295 int fd; /* File descriptor */ 296 int af; 297 int proto; 298 struct netconfig *nconf; /* Netconfig structure */ 299 u_int asize; /* Size of the addr buf */ 300 u_int dsize; /* Size of the data buf */ 301 struct sockaddr_storage raddr; /* Remote address */ 302 broadlist_t nal; 303 } fdlist[MAXBCAST]; 304 struct pollfd pfd[MAXBCAST]; 305 size_t fdlistno = 0; 306 struct r_rpcb_rmtcallargs barg; /* Remote arguments */ 307 struct r_rpcb_rmtcallres bres; /* Remote results */ 308 size_t outlen; 309 struct netconfig *nconf; 310 int msec; 311 int pollretval; 312 int fds_found; 313 314 #ifdef PORTMAP 315 size_t outlen_pmap = 0; 316 u_long port; /* Remote port number */ 317 int pmap_flag = 0; /* UDP exists ? */ 318 char *outbuf_pmap = NULL; 319 struct rmtcallargs barg_pmap; /* Remote arguments */ 320 struct rmtcallres bres_pmap; /* Remote results */ 321 u_int udpbufsz = 0; 322 #endif /* PORTMAP */ 323 324 if (sys_auth == NULL) { 325 return (RPC_SYSTEMERROR); 326 } 327 /* 328 * initialization: create a fd, a broadcast address, and send the 329 * request on the broadcast transport. 330 * Listen on all of them and on replies, call the user supplied 331 * function. 332 */ 333 334 if (nettype == NULL) 335 nettype = "datagram_n"; 336 if ((handle = __rpc_setconf(nettype)) == NULL) { 337 return (RPC_UNKNOWNPROTO); 338 } 339 while ((nconf = __rpc_getconf(handle)) != NULL) { 340 int fd; 341 struct __rpc_sockinfo si; 342 343 if (nconf->nc_semantics != NC_TPI_CLTS) 344 continue; 345 if (fdlistno >= MAXBCAST) 346 break; /* No more slots available */ 347 if (!__rpc_nconf2sockinfo(nconf, &si)) 348 continue; 349 350 TAILQ_INIT(&fdlist[fdlistno].nal); 351 if (__rpc_getbroadifs(si.si_af, si.si_proto, si.si_socktype, 352 &fdlist[fdlistno].nal) == 0) 353 continue; 354 355 fd = socket(si.si_af, si.si_socktype, si.si_proto); 356 if (fd == INVALID_SOCKET) { 357 stat = RPC_CANTSEND; 358 continue; 359 } 360 fdlist[fdlistno].af = si.si_af; 361 fdlist[fdlistno].proto = si.si_proto; 362 fdlist[fdlistno].fd = fd; 363 fdlist[fdlistno].nconf = nconf; 364 fdlist[fdlistno].asize = __rpc_get_a_size(si.si_af); 365 pfd[fdlistno].events = POLLIN | POLLPRI | 366 POLLRDNORM | POLLRDBAND; 367 pfd[fdlistno].fd = fdlist[fdlistno].fd = fd; 368 fdlist[fdlistno].dsize = __rpc_get_t_size(si.si_af, si.si_proto, 369 0); 370 371 if (maxbufsize <= fdlist[fdlistno].dsize) 372 maxbufsize = fdlist[fdlistno].dsize; 373 374 #ifdef PORTMAP 375 if (si.si_af == AF_INET && si.si_proto == IPPROTO_UDP) { 376 udpbufsz = fdlist[fdlistno].dsize; 377 if ((outbuf_pmap = malloc(udpbufsz)) == NULL) { 378 closesocket(fd); 379 stat = RPC_SYSTEMERROR; 380 goto done_broad; 381 } 382 pmap_flag = 1; 383 } 384 #endif /* PORTMAP */ 385 fdlistno++; 386 } 387 388 if (fdlistno == 0) { 389 if (stat == RPC_SUCCESS) 390 stat = RPC_UNKNOWNPROTO; 391 goto done_broad; 392 } 393 if (maxbufsize == 0) { 394 if (stat == RPC_SUCCESS) 395 stat = RPC_CANTSEND; 396 goto done_broad; 397 } 398 inbuf = malloc(maxbufsize); 399 outbuf = malloc(maxbufsize); 400 if ((inbuf == NULL) || (outbuf == NULL)) { 401 stat = RPC_SYSTEMERROR; 402 goto done_broad; 403 } 404 405 /* Serialize all the arguments which have to be sent */ 406 (void) gettimeofday(&t, NULL); 407 msg.rm_xid = __RPC_GETXID(&t); 408 msg.rm_direction = CALL; 409 msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; 410 msg.rm_call.cb_prog = RPCBPROG; 411 msg.rm_call.cb_vers = RPCBVERS; 412 msg.rm_call.cb_proc = RPCBPROC_CALLIT; 413 barg.prog = prog; 414 barg.vers = vers; 415 barg.proc = proc; 416 barg.args.args_val = argsp; 417 barg.xdr_args = xargs; 418 bres.addr = uaddrp; 419 bres.results.results_val = resultsp; 420 bres.xdr_res = xresults; 421 msg.rm_call.cb_cred = sys_auth->ah_cred; 422 msg.rm_call.cb_verf = sys_auth->ah_verf; 423 xdrmem_create(xdrs, outbuf, maxbufsize, XDR_ENCODE); 424 if ((!xdr_callmsg(xdrs, &msg)) || 425 (!xdr_rpcb_rmtcallargs(xdrs, 426 (struct rpcb_rmtcallargs *)(void *)&barg))) { 427 stat = RPC_CANTENCODEARGS; 428 goto done_broad; 429 } 430 outlen = xdr_getpos(xdrs); 431 xdr_destroy(xdrs); 432 433 #ifdef PORTMAP 434 /* Prepare the packet for version 2 PORTMAP */ 435 if (pmap_flag) { 436 msg.rm_xid++; /* One way to distinguish */ 437 msg.rm_call.cb_prog = PMAPPROG; 438 msg.rm_call.cb_vers = PMAPVERS; 439 msg.rm_call.cb_proc = PMAPPROC_CALLIT; 440 barg_pmap.prog = prog; 441 barg_pmap.vers = vers; 442 barg_pmap.proc = proc; 443 barg_pmap.args_ptr = argsp; 444 barg_pmap.xdr_args = xargs; 445 bres_pmap.port_ptr = &port; 446 bres_pmap.xdr_results = xresults; 447 bres_pmap.results_ptr = resultsp; 448 xdrmem_create(xdrs, outbuf_pmap, udpbufsz, XDR_ENCODE); 449 if ((! xdr_callmsg(xdrs, &msg)) || 450 (! xdr_rmtcall_args(xdrs, &barg_pmap))) { 451 stat = RPC_CANTENCODEARGS; 452 goto done_broad; 453 } 454 outlen_pmap = xdr_getpos(xdrs); 455 xdr_destroy(xdrs); 456 } 457 #endif /* PORTMAP */ 458 459 /* 460 * Basic loop: broadcast the packets to transports which 461 * support data packets of size such that one can encode 462 * all the arguments. 463 * Wait a while for response(s). 464 * The response timeout grows larger per iteration. 465 */ 466 for (msec = inittime; msec <= waittime; msec += msec) { 467 struct broadif *bip; 468 469 /* Broadcast all the packets now */ 470 for (i = 0; i < fdlistno; i++) { 471 if (fdlist[i].dsize < outlen) { 472 stat = RPC_CANTSEND; 473 continue; 474 } 475 for (bip = TAILQ_FIRST(&fdlist[i].nal); bip != NULL; 476 bip = TAILQ_NEXT(bip, link)) { 477 void *addr; 478 479 addr = &bip->broadaddr; 480 481 __rpc_broadenable(fdlist[i].af, fdlist[i].fd, 482 bip); 483 484 /* 485 * Only use version 3 if lowvers is not set 486 */ 487 488 if (!__rpc_lowvers) 489 if (sendto(fdlist[i].fd, outbuf, 490 outlen, 0, (struct sockaddr*)addr, 491 (size_t)fdlist[i].asize) != 492 outlen) { 493 #ifdef RPC_DEBUG 494 perror("sendto"); 495 #endif 496 warnx("clnt_bcast: cannot send" 497 "broadcast packet"); 498 stat = RPC_CANTSEND; 499 continue; 500 }; 501 #ifdef RPC_DEBUG 502 if (!__rpc_lowvers) 503 fprintf(stderr, "Broadcast packet sent " 504 "for %s\n", 505 fdlist[i].nconf->nc_netid); 506 #endif 507 #ifdef PORTMAP 508 /* 509 * Send the version 2 packet also 510 * for UDP/IP 511 */ 512 if (pmap_flag && 513 fdlist[i].proto == IPPROTO_UDP) { 514 if (sendto(fdlist[i].fd, outbuf_pmap, 515 outlen_pmap, 0, addr, 516 (size_t)fdlist[i].asize) != 517 outlen_pmap) { 518 warnx("clnt_bcast: " 519 "Cannot send broadcast packet"); 520 stat = RPC_CANTSEND; 521 continue; 522 } 523 } 524 #ifdef RPC_DEBUG 525 fprintf(stderr, "PMAP Broadcast packet " 526 "sent for %s\n", 527 fdlist[i].nconf->nc_netid); 528 #endif 529 #endif /* PORTMAP */ 530 } 531 /* End for sending all packets on this transport */ 532 } /* End for sending on all transports */ 533 534 if (eachresult == NULL) { 535 stat = RPC_SUCCESS; 536 goto done_broad; 537 } 538 539 /* 540 * Get all the replies from these broadcast requests 541 */ 542 recv_again: 543 544 switch (pollretval = poll(pfd, fdlistno, msec)) { 545 case 0: /* timed out */ 546 stat = RPC_TIMEDOUT; 547 continue; 548 case -1: /* some kind of error - we ignore it */ 549 goto recv_again; 550 } /* end of poll results switch */ 551 552 for (i = fds_found = 0; 553 i < fdlistno && fds_found < pollretval; i++) { 554 bool_t done = FALSE; 555 556 if (pfd[i].revents == 0) 557 continue; 558 else if (pfd[i].revents & POLLNVAL) { 559 /* 560 * Something bad has happened to this descri- 561 * ptor. We can cause _poll() to ignore 562 * it simply by using a negative fd. We do that 563 * rather than compacting the pfd[] and fdlist[] 564 * arrays. 565 */ 566 pfd[i].fd = -1; 567 fds_found++; 568 continue; 569 } else 570 fds_found++; 571 #ifdef RPC_DEBUG 572 fprintf(stderr, "response for %s\n", 573 fdlist[i].nconf->nc_netid); 574 #endif 575 try_again: 576 inlen = recvfrom(fdlist[i].fd, inbuf, fdlist[i].dsize, 577 0, (struct sockaddr *)(void *)&fdlist[i].raddr, 578 &fdlist[i].asize); 579 if (inlen < 0) { 580 if (errno == EINTR) 581 goto try_again; 582 warnx("clnt_bcast: Cannot receive reply to " 583 "broadcast"); 584 stat = RPC_CANTRECV; 585 continue; 586 } 587 if (inlen < sizeof (u_int32_t)) 588 continue; /* Drop that and go ahead */ 589 /* 590 * see if reply transaction id matches sent id. 591 * If so, decode the results. If return id is xid + 1 592 * it was a PORTMAP reply 593 */ 594 if (*((u_int32_t *)(void *)(inbuf)) == 595 *((u_int32_t *)(void *)(outbuf))) { 596 pmap_reply_flag = 0; 597 msg.acpted_rply.ar_verf = _null_auth; 598 msg.acpted_rply.ar_results.where = 599 (caddr_t)(void *)&bres; 600 msg.acpted_rply.ar_results.proc = 601 (xdrproc_t)xdr_rpcb_rmtcallres; 602 #ifdef PORTMAP 603 } else if (pmap_flag && 604 *((u_int32_t *)(void *)(inbuf)) == 605 *((u_int32_t *)(void *)(outbuf_pmap))) { 606 pmap_reply_flag = 1; 607 msg.acpted_rply.ar_verf = _null_auth; 608 msg.acpted_rply.ar_results.where = 609 (caddr_t)(void *)&bres_pmap; 610 msg.acpted_rply.ar_results.proc = 611 (xdrproc_t)xdr_rmtcallres; 612 #endif /* PORTMAP */ 613 } else 614 continue; 615 xdrmem_create(xdrs, inbuf, (u_int)inlen, XDR_DECODE); 616 if (xdr_replymsg(xdrs, &msg)) { 617 if ((msg.rm_reply.rp_stat == MSG_ACCEPTED) && 618 (msg.acpted_rply.ar_stat == SUCCESS)) { 619 struct netbuf *np; 620 #ifdef PORTMAP 621 struct netbuf taddr; 622 struct sockaddr_in sin; 623 624 if (pmap_flag && pmap_reply_flag) { 625 memcpy(&sin, &fdlist[i].raddr, sizeof(sin)); 626 sin.sin_port = htons((u_short)port); 627 memcpy(&fdlist[i].raddr, &sin, sizeof(sin)); 628 taddr.len = taddr.maxlen = 629 sizeof(fdlist[i].raddr); 630 taddr.buf = &fdlist[i].raddr; 631 done = (*eachresult)(resultsp, 632 &taddr, fdlist[i].nconf); 633 } else { 634 #endif /* PORTMAP */ 635 #ifdef RPC_DEBUG 636 fprintf(stderr, "uaddr %s\n", 637 uaddrp); 638 #endif 639 np = uaddr2taddr( 640 fdlist[i].nconf, uaddrp); 641 done = (*eachresult)(resultsp, 642 np, fdlist[i].nconf); 643 free(np); 644 #ifdef PORTMAP 645 } 646 #endif /* PORTMAP */ 647 } 648 /* otherwise, we just ignore the errors ... */ 649 } 650 /* else some kind of deserialization problem ... */ 651 652 xdrs->x_op = XDR_FREE; 653 msg.acpted_rply.ar_results.proc = (xdrproc_t) xdr_void; 654 (void) xdr_replymsg(xdrs, &msg); 655 (void) (*xresults)(xdrs, resultsp); 656 XDR_DESTROY(xdrs); 657 if (done) { 658 stat = RPC_SUCCESS; 659 goto done_broad; 660 } else { 661 goto recv_again; 662 } 663 } /* The recv for loop */ 664 } /* The giant for loop */ 665 666 done_broad: 667 if (inbuf) 668 (void) free(inbuf); 669 if (outbuf) 670 (void) free(outbuf); 671 #ifdef PORTMAP 672 if (outbuf_pmap) 673 (void) free(outbuf_pmap); 674 #endif /* PORTMAP */ 675 for (i = 0; i < fdlistno; i++) { 676 (void)closesocket(fdlist[i].fd); 677 __rpc_freebroadifs(&fdlist[i].nal); 678 } 679 AUTH_DESTROY(sys_auth); 680 (void) __rpc_endconf(handle); 681 682 return (stat); 683 } 684 685 686 enum clnt_stat 687 rpc_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, 688 eachresult, nettype) 689 rpcprog_t prog; /* program number */ 690 rpcvers_t vers; /* version number */ 691 rpcproc_t proc; /* procedure number */ 692 xdrproc_t xargs; /* xdr routine for args */ 693 caddr_t argsp; /* pointer to args */ 694 xdrproc_t xresults; /* xdr routine for results */ 695 caddr_t resultsp; /* pointer to results */ 696 resultproc_t eachresult; /* call with each result obtained */ 697 const char *nettype; /* transport type */ 698 { 699 enum clnt_stat dummy; 700 701 dummy = rpc_broadcast_exp(prog, vers, proc, xargs, argsp, 702 xresults, resultsp, eachresult, 703 INITTIME, WAITTIME, nettype); 704 return (dummy); 705 } 706 707 #endif 708