PageRenderTime 50ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

lib/libc/rpc/clnt_bcast.c

http://www.minix3.org/
C | 686 lines | 519 code | 60 blank | 107 comment | 101 complexity | e8f67ccf5ac1bc561be7ce55ef0666ed MD5 | raw file
Possible License(s): MIT, WTFPL, AGPL-1.0, BSD-3-Clause, GPL-3.0, LGPL-2.0, JSON, 0BSD
  1. /* $NetBSD: clnt_bcast.c,v 1.22 2010/03/07 23:49:14 dholland Exp $ */
  2. /*
  3. * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  4. * unrestricted use provided that this legend is included on all tape
  5. * media and as a part of the software program in whole or part. Users
  6. * may copy or modify Sun RPC without charge, but are not authorized
  7. * to license or distribute it to anyone else except as part of a product or
  8. * program developed by the user.
  9. *
  10. * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  11. * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  12. * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  13. *
  14. * Sun RPC is provided with no support and without any obligation on the
  15. * part of Sun Microsystems, Inc. to assist in its use, correction,
  16. * modification or enhancement.
  17. *
  18. * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  19. * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  20. * OR ANY PART THEREOF.
  21. *
  22. * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  23. * or profits or other special, indirect and consequential damages, even if
  24. * Sun has been advised of the possibility of such damages.
  25. *
  26. * Sun Microsystems, Inc.
  27. * 2550 Garcia Avenue
  28. * Mountain View, California 94043
  29. */
  30. /*
  31. * Copyright (c) 1986-1991 by Sun Microsystems Inc.
  32. */
  33. /* #ident "@(#)clnt_bcast.c 1.18 94/05/03 SMI" */
  34. #include <sys/cdefs.h>
  35. #if defined(LIBC_SCCS) && !defined(lint)
  36. #if 0
  37. static char sccsid[] = "@(#)clnt_bcast.c 1.15 89/04/21 Copyr 1988 Sun Micro";
  38. #else
  39. __RCSID("$NetBSD: clnt_bcast.c,v 1.22 2010/03/07 23:49:14 dholland Exp $");
  40. #endif
  41. #endif
  42. /*
  43. * clnt_bcast.c
  44. * Client interface to broadcast service.
  45. *
  46. * Copyright (C) 1988, Sun Microsystems, Inc.
  47. *
  48. * The following is kludged-up support for simple rpc broadcasts.
  49. * Someday a large, complicated system will replace these routines.
  50. */
  51. #include "namespace.h"
  52. #include <sys/types.h>
  53. #include <sys/socket.h>
  54. #include <sys/queue.h>
  55. #include <net/if.h>
  56. #include <netinet/in.h>
  57. #include <ifaddrs.h>
  58. #include <sys/poll.h>
  59. #include <rpc/rpc.h>
  60. #ifdef PORTMAP
  61. #include <rpc/pmap_prot.h>
  62. #include <rpc/pmap_clnt.h>
  63. #include <rpc/pmap_rmt.h>
  64. #endif
  65. #include <rpc/nettype.h>
  66. #include <arpa/inet.h>
  67. #ifdef RPC_DEBUG
  68. #include <stdio.h>
  69. #endif
  70. #include <assert.h>
  71. #include <errno.h>
  72. #include <stdlib.h>
  73. #include <unistd.h>
  74. #include <netdb.h>
  75. #include <err.h>
  76. #include <string.h>
  77. #include "rpc_internal.h"
  78. #define MAXBCAST 20 /* Max no of broadcasting transports */
  79. #define INITTIME 4000 /* Time to wait initially */
  80. #define WAITTIME 8000 /* Maximum time to wait */
  81. /*
  82. * If nettype is NULL, it broadcasts on all the available
  83. * datagram_n transports. May potentially lead to broadacst storms
  84. * and hence should be used with caution, care and courage.
  85. *
  86. * The current parameter xdr packet size is limited by the max tsdu
  87. * size of the transport. If the max tsdu size of any transport is
  88. * smaller than the parameter xdr packet, then broadcast is not
  89. * sent on that transport.
  90. *
  91. * Also, the packet size should be less the packet size of
  92. * the data link layer (for ethernet it is 1400 bytes). There is
  93. * no easy way to find out the max size of the data link layer and
  94. * we are assuming that the args would be smaller than that.
  95. *
  96. * The result size has to be smaller than the transport tsdu size.
  97. *
  98. * If PORTMAP has been defined, we send two packets for UDP, one for
  99. * rpcbind and one for portmap. For those machines which support
  100. * both rpcbind and portmap, it will cause them to reply twice, and
  101. * also here it will get two responses ... inefficient and clumsy.
  102. */
  103. #ifdef __weak_alias
  104. __weak_alias(rpc_broadcast_exp,_rpc_broadcast_exp)
  105. __weak_alias(rpc_broadcast,_rpc_broadcast)
  106. #endif
  107. struct broadif {
  108. int index;
  109. struct sockaddr_storage broadaddr;
  110. TAILQ_ENTRY(broadif) link;
  111. };
  112. typedef TAILQ_HEAD(, broadif) broadlist_t;
  113. int __rpc_getbroadifs __P((int, int, int, broadlist_t *));
  114. void __rpc_freebroadifs __P((broadlist_t *));
  115. int __rpc_broadenable __P((int, int, struct broadif *));
  116. int __rpc_lowvers = 0;
  117. int
  118. __rpc_getbroadifs(int af, int proto, int socktype, broadlist_t *list)
  119. {
  120. int count = 0;
  121. struct broadif *bip;
  122. struct ifaddrs *ifap, *ifp;
  123. #ifdef INET6
  124. struct sockaddr_in6 *sin6;
  125. #endif
  126. struct sockaddr_in *gbsin;
  127. struct addrinfo hints, *res;
  128. _DIAGASSERT(list != NULL);
  129. if (getifaddrs(&ifp) < 0)
  130. return 0;
  131. memset(&hints, 0, sizeof hints);
  132. hints.ai_family = af;
  133. hints.ai_protocol = proto;
  134. hints.ai_socktype = socktype;
  135. if (getaddrinfo(NULL, "sunrpc", &hints, &res) != 0) {
  136. freeifaddrs(ifp);
  137. return 0;
  138. }
  139. for (ifap = ifp; ifap != NULL; ifap = ifap->ifa_next) {
  140. if (ifap->ifa_addr->sa_family != af ||
  141. !(ifap->ifa_flags & IFF_UP))
  142. continue;
  143. bip = malloc(sizeof(*bip));
  144. if (bip == NULL)
  145. break;
  146. bip->index = if_nametoindex(ifap->ifa_name);
  147. if (
  148. #ifdef INET6
  149. af != AF_INET6 &&
  150. #endif
  151. (ifap->ifa_flags & IFF_BROADCAST) &&
  152. ifap->ifa_broadaddr) {
  153. memcpy(&bip->broadaddr, ifap->ifa_broadaddr,
  154. (size_t)ifap->ifa_broadaddr->sa_len);
  155. gbsin = (struct sockaddr_in *)(void *)&bip->broadaddr;
  156. gbsin->sin_port =
  157. ((struct sockaddr_in *)
  158. (void *)res->ai_addr)->sin_port;
  159. } else
  160. #ifdef INET6
  161. if (af == AF_INET6 && (ifap->ifa_flags & IFF_MULTICAST)) {
  162. sin6 = (struct sockaddr_in6 *)(void *)&bip->broadaddr;
  163. inet_pton(af, RPCB_MULTICAST_ADDR, &sin6->sin6_addr);
  164. sin6->sin6_family = af;
  165. sin6->sin6_len = sizeof *sin6;
  166. sin6->sin6_port =
  167. ((struct sockaddr_in6 *)
  168. (void *)res->ai_addr)->sin6_port;
  169. sin6->sin6_scope_id = bip->index;
  170. } else
  171. #endif
  172. {
  173. free(bip);
  174. continue;
  175. }
  176. TAILQ_INSERT_TAIL(list, bip, link);
  177. count++;
  178. }
  179. freeifaddrs(ifp);
  180. freeaddrinfo(res);
  181. return count;
  182. }
  183. void
  184. __rpc_freebroadifs(broadlist_t *list)
  185. {
  186. struct broadif *bip, *next;
  187. _DIAGASSERT(list != NULL);
  188. bip = TAILQ_FIRST(list);
  189. while (bip != NULL) {
  190. next = TAILQ_NEXT(bip, link);
  191. free(bip);
  192. bip = next;
  193. }
  194. }
  195. int
  196. /*ARGSUSED*/
  197. __rpc_broadenable(int af, int s, struct broadif *bip)
  198. {
  199. int o = 1;
  200. #if 0
  201. _DIAGASSERT(bip != NULL);
  202. if (af == AF_INET6) {
  203. fprintf(stderr, "set v6 multicast if to %d\n", bip->index);
  204. if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, &bip->index,
  205. sizeof bip->index) < 0)
  206. return -1;
  207. } else
  208. #endif
  209. if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &o, sizeof o) < 0)
  210. return -1;
  211. return 0;
  212. }
  213. enum clnt_stat
  214. rpc_broadcast_exp(prog, vers, proc, xargs, argsp, xresults, resultsp,
  215. eachresult, inittime, waittime, nettype)
  216. rpcprog_t prog; /* program number */
  217. rpcvers_t vers; /* version number */
  218. rpcproc_t proc; /* procedure number */
  219. xdrproc_t xargs; /* xdr routine for args */
  220. const char * argsp; /* pointer to args */
  221. xdrproc_t xresults; /* xdr routine for results */
  222. caddr_t resultsp; /* pointer to results */
  223. resultproc_t eachresult; /* call with each result obtained */
  224. int inittime; /* how long to wait initially */
  225. int waittime; /* maximum time to wait */
  226. const char *nettype; /* transport type */
  227. {
  228. enum clnt_stat stat = RPC_SUCCESS; /* Return status */
  229. XDR xdr_stream; /* XDR stream */
  230. XDR *xdrs = &xdr_stream;
  231. struct rpc_msg msg; /* RPC message */
  232. char *outbuf = NULL; /* Broadcast msg buffer */
  233. char *inbuf = NULL; /* Reply buf */
  234. ssize_t inlen;
  235. u_int maxbufsize = 0;
  236. AUTH *sys_auth = authunix_create_default();
  237. size_t i;
  238. void *handle;
  239. char uaddress[1024]; /* A self imposed limit */
  240. char *uaddrp = uaddress;
  241. int pmap_reply_flag; /* reply recvd from PORTMAP */
  242. /* An array of all the suitable broadcast transports */
  243. struct {
  244. int fd; /* File descriptor */
  245. int af;
  246. int proto;
  247. struct netconfig *nconf; /* Netconfig structure */
  248. u_int asize; /* Size of the addr buf */
  249. u_int dsize; /* Size of the data buf */
  250. struct sockaddr_storage raddr; /* Remote address */
  251. broadlist_t nal;
  252. } fdlist[MAXBCAST];
  253. struct pollfd pfd[MAXBCAST];
  254. size_t fdlistno = 0;
  255. struct r_rpcb_rmtcallargs barg; /* Remote arguments */
  256. struct r_rpcb_rmtcallres bres; /* Remote results */
  257. size_t outlen;
  258. struct netconfig *nconf;
  259. int msec;
  260. int pollretval;
  261. int fds_found;
  262. struct timespec ts;
  263. #ifdef PORTMAP
  264. size_t outlen_pmap = 0;
  265. u_long port; /* Remote port number */
  266. int pmap_flag = 0; /* UDP exists ? */
  267. char *outbuf_pmap = NULL;
  268. struct rmtcallargs barg_pmap; /* Remote arguments */
  269. struct rmtcallres bres_pmap; /* Remote results */
  270. u_int udpbufsz = 0;
  271. #endif /* PORTMAP */
  272. if (sys_auth == NULL) {
  273. return (RPC_SYSTEMERROR);
  274. }
  275. /*
  276. * initialization: create a fd, a broadcast address, and send the
  277. * request on the broadcast transport.
  278. * Listen on all of them and on replies, call the user supplied
  279. * function.
  280. */
  281. if (nettype == NULL)
  282. nettype = "datagram_n";
  283. if ((handle = __rpc_setconf(nettype)) == NULL) {
  284. AUTH_DESTROY(sys_auth);
  285. return (RPC_UNKNOWNPROTO);
  286. }
  287. while ((nconf = __rpc_getconf(handle)) != NULL) {
  288. int fd;
  289. struct __rpc_sockinfo si;
  290. if (nconf->nc_semantics != NC_TPI_CLTS)
  291. continue;
  292. if (fdlistno >= MAXBCAST)
  293. break; /* No more slots available */
  294. if (!__rpc_nconf2sockinfo(nconf, &si))
  295. continue;
  296. TAILQ_INIT(&fdlist[fdlistno].nal);
  297. if (__rpc_getbroadifs(si.si_af, si.si_proto, si.si_socktype,
  298. &fdlist[fdlistno].nal) == 0)
  299. continue;
  300. fd = socket(si.si_af, si.si_socktype, si.si_proto);
  301. if (fd < 0) {
  302. stat = RPC_CANTSEND;
  303. continue;
  304. }
  305. fdlist[fdlistno].af = si.si_af;
  306. fdlist[fdlistno].proto = si.si_proto;
  307. fdlist[fdlistno].fd = fd;
  308. fdlist[fdlistno].nconf = nconf;
  309. fdlist[fdlistno].asize = __rpc_get_a_size(si.si_af);
  310. pfd[fdlistno].events = POLLIN | POLLPRI |
  311. POLLRDNORM | POLLRDBAND;
  312. pfd[fdlistno].fd = fdlist[fdlistno].fd = fd;
  313. fdlist[fdlistno].dsize = __rpc_get_t_size(si.si_af, si.si_proto,
  314. 0);
  315. if (maxbufsize <= fdlist[fdlistno].dsize)
  316. maxbufsize = fdlist[fdlistno].dsize;
  317. #ifdef PORTMAP
  318. if (si.si_af == AF_INET && si.si_proto == IPPROTO_UDP) {
  319. udpbufsz = fdlist[fdlistno].dsize;
  320. if ((outbuf_pmap = malloc(udpbufsz)) == NULL) {
  321. close(fd);
  322. stat = RPC_SYSTEMERROR;
  323. goto done_broad;
  324. }
  325. pmap_flag = 1;
  326. }
  327. #endif
  328. fdlistno++;
  329. }
  330. if (fdlistno == 0) {
  331. if (stat == RPC_SUCCESS)
  332. stat = RPC_UNKNOWNPROTO;
  333. goto done_broad;
  334. }
  335. if (maxbufsize == 0) {
  336. if (stat == RPC_SUCCESS)
  337. stat = RPC_CANTSEND;
  338. goto done_broad;
  339. }
  340. inbuf = malloc(maxbufsize);
  341. outbuf = malloc(maxbufsize);
  342. if ((inbuf == NULL) || (outbuf == NULL)) {
  343. stat = RPC_SYSTEMERROR;
  344. goto done_broad;
  345. }
  346. /* Serialize all the arguments which have to be sent */
  347. msg.rm_xid = __RPC_GETXID();
  348. msg.rm_direction = CALL;
  349. msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
  350. msg.rm_call.cb_prog = RPCBPROG;
  351. msg.rm_call.cb_vers = RPCBVERS;
  352. msg.rm_call.cb_proc = RPCBPROC_CALLIT;
  353. barg.prog = prog;
  354. barg.vers = vers;
  355. barg.proc = proc;
  356. barg.args.args_val = argsp;
  357. barg.xdr_args = xargs;
  358. bres.addr = uaddrp;
  359. bres.results.results_val = resultsp;
  360. bres.xdr_res = xresults;
  361. msg.rm_call.cb_cred = sys_auth->ah_cred;
  362. msg.rm_call.cb_verf = sys_auth->ah_verf;
  363. xdrmem_create(xdrs, outbuf, maxbufsize, XDR_ENCODE);
  364. if ((!xdr_callmsg(xdrs, &msg)) ||
  365. (!xdr_rpcb_rmtcallargs(xdrs,
  366. (struct rpcb_rmtcallargs *)(void *)&barg))) {
  367. stat = RPC_CANTENCODEARGS;
  368. goto done_broad;
  369. }
  370. outlen = xdr_getpos(xdrs);
  371. xdr_destroy(xdrs);
  372. #ifdef PORTMAP
  373. /* Prepare the packet for version 2 PORTMAP */
  374. if (pmap_flag) {
  375. msg.rm_xid++; /* One way to distinguish */
  376. msg.rm_call.cb_prog = PMAPPROG;
  377. msg.rm_call.cb_vers = PMAPVERS;
  378. msg.rm_call.cb_proc = PMAPPROC_CALLIT;
  379. barg_pmap.prog = prog;
  380. barg_pmap.vers = vers;
  381. barg_pmap.proc = proc;
  382. barg_pmap.args_ptr = argsp;
  383. barg_pmap.xdr_args = xargs;
  384. bres_pmap.port_ptr = &port;
  385. bres_pmap.xdr_results = xresults;
  386. bres_pmap.results_ptr = resultsp;
  387. xdrmem_create(xdrs, outbuf_pmap, udpbufsz, XDR_ENCODE);
  388. if ((! xdr_callmsg(xdrs, &msg)) ||
  389. (! xdr_rmtcall_args(xdrs, &barg_pmap))) {
  390. stat = RPC_CANTENCODEARGS;
  391. goto done_broad;
  392. }
  393. outlen_pmap = xdr_getpos(xdrs);
  394. xdr_destroy(xdrs);
  395. }
  396. #endif /* PORTMAP */
  397. /*
  398. * Basic loop: broadcast the packets to transports which
  399. * support data packets of size such that one can encode
  400. * all the arguments.
  401. * Wait a while for response(s).
  402. * The response timeout grows larger per iteration.
  403. */
  404. for (msec = inittime; msec <= waittime; msec += msec) {
  405. struct broadif *bip;
  406. /* Broadcast all the packets now */
  407. for (i = 0; i < fdlistno; i++) {
  408. if (fdlist[i].dsize < outlen) {
  409. stat = RPC_CANTSEND;
  410. continue;
  411. }
  412. for (bip = TAILQ_FIRST(&fdlist[i].nal); bip != NULL;
  413. bip = TAILQ_NEXT(bip, link)) {
  414. void *addr;
  415. addr = &bip->broadaddr;
  416. __rpc_broadenable(fdlist[i].af, fdlist[i].fd,
  417. bip);
  418. /*
  419. * Only use version 3 if lowvers is not set
  420. */
  421. if (!__rpc_lowvers)
  422. if ((size_t)sendto(fdlist[i].fd, outbuf,
  423. outlen, 0, (struct sockaddr*)addr,
  424. (size_t)fdlist[i].asize) !=
  425. outlen) {
  426. warn("clnt_bcast: cannot send"
  427. " broadcast packet");
  428. stat = RPC_CANTSEND;
  429. continue;
  430. }
  431. #ifdef RPC_DEBUG
  432. if (!__rpc_lowvers)
  433. fprintf(stderr, "Broadcast packet sent "
  434. "for %s\n",
  435. fdlist[i].nconf->nc_netid);
  436. #endif
  437. #ifdef PORTMAP
  438. /*
  439. * Send the version 2 packet also
  440. * for UDP/IP
  441. */
  442. if (pmap_flag &&
  443. fdlist[i].proto == IPPROTO_UDP) {
  444. if ((size_t)sendto(fdlist[i].fd,
  445. outbuf_pmap, outlen_pmap, 0, addr,
  446. (size_t)fdlist[i].asize) !=
  447. outlen_pmap) {
  448. warnx("clnt_bcast: "
  449. "Cannot send "
  450. "broadcast packet");
  451. stat = RPC_CANTSEND;
  452. continue;
  453. }
  454. }
  455. #ifdef RPC_DEBUG
  456. fprintf(stderr, "PMAP Broadcast packet "
  457. "sent for %s\n",
  458. fdlist[i].nconf->nc_netid);
  459. #endif
  460. #endif /* PORTMAP */
  461. }
  462. /* End for sending all packets on this transport */
  463. } /* End for sending on all transports */
  464. if (eachresult == NULL) {
  465. stat = RPC_SUCCESS;
  466. goto done_broad;
  467. }
  468. /*
  469. * Get all the replies from these broadcast requests
  470. */
  471. recv_again:
  472. ts.tv_sec = msec / 1000;
  473. ts.tv_nsec = (msec % 1000) * 1000000;
  474. switch (pollretval = pollts(pfd, fdlistno, &ts, NULL)) {
  475. case 0: /* timed out */
  476. stat = RPC_TIMEDOUT;
  477. continue;
  478. case -1: /* some kind of error - we ignore it */
  479. goto recv_again;
  480. } /* end of poll results switch */
  481. for (i = fds_found = 0;
  482. i < fdlistno && fds_found < pollretval; i++) {
  483. bool_t done = FALSE;
  484. if (pfd[i].revents == 0)
  485. continue;
  486. else if (pfd[i].revents & POLLNVAL) {
  487. /*
  488. * Something bad has happened to this descri-
  489. * ptor. We can cause pollts() to ignore
  490. * it simply by using a negative fd. We do that
  491. * rather than compacting the pfd[] and fdlist[]
  492. * arrays.
  493. */
  494. pfd[i].fd = -1;
  495. fds_found++;
  496. continue;
  497. } else
  498. fds_found++;
  499. #ifdef RPC_DEBUG
  500. fprintf(stderr, "response for %s\n",
  501. fdlist[i].nconf->nc_netid);
  502. #endif
  503. try_again:
  504. inlen = recvfrom(fdlist[i].fd, inbuf, fdlist[i].dsize,
  505. 0, (struct sockaddr *)(void *)&fdlist[i].raddr,
  506. &fdlist[i].asize);
  507. if (inlen < 0) {
  508. if (errno == EINTR)
  509. goto try_again;
  510. warnx("clnt_bcast: Cannot receive reply to "
  511. "broadcast");
  512. stat = RPC_CANTRECV;
  513. continue;
  514. }
  515. if (inlen < (ssize_t)sizeof(u_int32_t))
  516. continue; /* Drop that and go ahead */
  517. /*
  518. * see if reply transaction id matches sent id.
  519. * If so, decode the results. If return id is xid + 1
  520. * it was a PORTMAP reply
  521. */
  522. if (*((u_int32_t *)(void *)(inbuf)) ==
  523. *((u_int32_t *)(void *)(outbuf))) {
  524. pmap_reply_flag = 0;
  525. msg.acpted_rply.ar_verf = _null_auth;
  526. msg.acpted_rply.ar_results.where =
  527. (caddr_t)(void *)&bres;
  528. msg.acpted_rply.ar_results.proc =
  529. (xdrproc_t)xdr_rpcb_rmtcallres;
  530. #ifdef PORTMAP
  531. } else if (pmap_flag &&
  532. *((u_int32_t *)(void *)(inbuf)) ==
  533. *((u_int32_t *)(void *)(outbuf_pmap))) {
  534. pmap_reply_flag = 1;
  535. msg.acpted_rply.ar_verf = _null_auth;
  536. msg.acpted_rply.ar_results.where =
  537. (caddr_t)(void *)&bres_pmap;
  538. msg.acpted_rply.ar_results.proc =
  539. (xdrproc_t)xdr_rmtcallres;
  540. #endif /* PORTMAP */
  541. } else
  542. continue;
  543. xdrmem_create(xdrs, inbuf, (u_int)inlen, XDR_DECODE);
  544. if (xdr_replymsg(xdrs, &msg)) {
  545. if ((msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
  546. (msg.acpted_rply.ar_stat == SUCCESS)) {
  547. struct netbuf taddr, *np;
  548. struct sockaddr_in *bsin;
  549. #ifdef PORTMAP
  550. if (pmap_flag && pmap_reply_flag) {
  551. bsin = (struct sockaddr_in *)
  552. (void *)&fdlist[i].raddr;
  553. bsin->sin_port =
  554. htons((u_short)port);
  555. taddr.len = taddr.maxlen =
  556. fdlist[i].raddr.ss_len;
  557. taddr.buf = &fdlist[i].raddr;
  558. done = (*eachresult)(resultsp,
  559. &taddr, fdlist[i].nconf);
  560. } else {
  561. #endif
  562. #ifdef RPC_DEBUG
  563. fprintf(stderr, "uaddr %s\n",
  564. uaddrp);
  565. #endif
  566. np = uaddr2taddr(
  567. fdlist[i].nconf, uaddrp);
  568. done = (*eachresult)(resultsp,
  569. np, fdlist[i].nconf);
  570. free(np);
  571. #ifdef PORTMAP
  572. }
  573. #endif
  574. }
  575. /* otherwise, we just ignore the errors ... */
  576. }
  577. /* else some kind of deserialization problem ... */
  578. xdrs->x_op = XDR_FREE;
  579. msg.acpted_rply.ar_results.proc = (xdrproc_t) xdr_void;
  580. (void) xdr_replymsg(xdrs, &msg);
  581. (void) (*xresults)(xdrs, resultsp);
  582. XDR_DESTROY(xdrs);
  583. if (done) {
  584. stat = RPC_SUCCESS;
  585. goto done_broad;
  586. } else {
  587. goto recv_again;
  588. }
  589. } /* The recv for loop */
  590. } /* The giant for loop */
  591. done_broad:
  592. if (inbuf)
  593. (void) free(inbuf);
  594. if (outbuf)
  595. (void) free(outbuf);
  596. #ifdef PORTMAP
  597. if (outbuf_pmap)
  598. (void) free(outbuf_pmap);
  599. #endif
  600. for (i = 0; i < fdlistno; i++) {
  601. (void) close(fdlist[i].fd);
  602. __rpc_freebroadifs(&fdlist[i].nal);
  603. }
  604. AUTH_DESTROY(sys_auth);
  605. (void) __rpc_endconf(handle);
  606. return (stat);
  607. }
  608. enum clnt_stat
  609. rpc_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp,
  610. eachresult, nettype)
  611. rpcprog_t prog; /* program number */
  612. rpcvers_t vers; /* version number */
  613. rpcproc_t proc; /* procedure number */
  614. xdrproc_t xargs; /* xdr routine for args */
  615. const char * argsp; /* pointer to args */
  616. xdrproc_t xresults; /* xdr routine for results */
  617. caddr_t resultsp; /* pointer to results */
  618. resultproc_t eachresult; /* call with each result obtained */
  619. const char *nettype; /* transport type */
  620. {
  621. enum clnt_stat dummy;
  622. dummy = rpc_broadcast_exp(prog, vers, proc, xargs, argsp,
  623. xresults, resultsp, eachresult,
  624. INITTIME, WAITTIME, nettype);
  625. return (dummy);
  626. }