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