source: rtems-libbsd/freebsd/lib/libc/rpc/clnt_bcast.c @ f41a394

55-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since f41a394 was 60b1d40, checked in by Sebastian Huber <sebastian.huber@…>, on 06/09/16 at 08:23:57

RPC(3): Import from FreeBSD

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