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
rpc_broadcast(prog,vers,proc,xargs,argsp,xresults,resultsp,eachresult,nettype)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
__rpc_getbroadifs(int af,int proto,int socktype,broadlist_t * list)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
__rpc_freebroadifs(broadlist_t * list)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*/
__rpc_broadenable(int af,int s,struct broadif * bip)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
rpc_broadcast_exp(prog,vers,proc,xargs,argsp,xresults,resultsp,eachresult,inittime,waittime,nettype)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
rpc_broadcast(prog,vers,proc,xargs,argsp,xresults,resultsp,eachresult,nettype)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