xref: /freebsd/crypto/krb5/src/lib/rpc/pmap_rmt.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1*7f2fe78bSCy Schubert /* @(#)pmap_rmt.c	2.2 88/08/01 4.0 RPCSRC */
2*7f2fe78bSCy Schubert /*
3*7f2fe78bSCy Schubert  * Copyright (c) 2010, Oracle America, Inc.
4*7f2fe78bSCy Schubert  *
5*7f2fe78bSCy Schubert  * All rights reserved.
6*7f2fe78bSCy Schubert  *
7*7f2fe78bSCy Schubert  * Redistribution and use in source and binary forms, with or without
8*7f2fe78bSCy Schubert  * modification, are permitted provided that the following conditions are met:
9*7f2fe78bSCy Schubert  *
10*7f2fe78bSCy Schubert  *     * Redistributions of source code must retain the above copyright
11*7f2fe78bSCy Schubert  *       notice, this list of conditions and the following disclaimer.
12*7f2fe78bSCy Schubert  *
13*7f2fe78bSCy Schubert  *     * Redistributions in binary form must reproduce the above copyright
14*7f2fe78bSCy Schubert  *       notice, this list of conditions and the following disclaimer in
15*7f2fe78bSCy Schubert  *       the documentation and/or other materials provided with the
16*7f2fe78bSCy Schubert  *       distribution.
17*7f2fe78bSCy Schubert  *
18*7f2fe78bSCy Schubert  *     * Neither the name of the "Oracle America, Inc." nor the names of
19*7f2fe78bSCy Schubert  *       its contributors may be used to endorse or promote products
20*7f2fe78bSCy Schubert  *       derived from this software without specific prior written permission.
21*7f2fe78bSCy Schubert  *
22*7f2fe78bSCy Schubert  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
23*7f2fe78bSCy Schubert  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24*7f2fe78bSCy Schubert  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25*7f2fe78bSCy Schubert  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26*7f2fe78bSCy Schubert  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27*7f2fe78bSCy Schubert  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
28*7f2fe78bSCy Schubert  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29*7f2fe78bSCy Schubert  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30*7f2fe78bSCy Schubert  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31*7f2fe78bSCy Schubert  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32*7f2fe78bSCy Schubert  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33*7f2fe78bSCy Schubert  */
34*7f2fe78bSCy Schubert #if !defined(lint) && defined(SCCSIDS)
35*7f2fe78bSCy Schubert static char sccsid[] = "@(#)pmap_rmt.c 1.21 87/08/27 Copyr 1984 Sun Micro";
36*7f2fe78bSCy Schubert #endif
37*7f2fe78bSCy Schubert 
38*7f2fe78bSCy Schubert /*
39*7f2fe78bSCy Schubert  * pmap_rmt.c
40*7f2fe78bSCy Schubert  * Client interface to pmap rpc service.
41*7f2fe78bSCy Schubert  * remote call and broadcast service
42*7f2fe78bSCy Schubert  */
43*7f2fe78bSCy Schubert 
44*7f2fe78bSCy Schubert #include "k5-platform.h"
45*7f2fe78bSCy Schubert #include <unistd.h>
46*7f2fe78bSCy Schubert #include <gssrpc/rpc.h>
47*7f2fe78bSCy Schubert #include <gssrpc/pmap_prot.h>
48*7f2fe78bSCy Schubert #include <gssrpc/pmap_clnt.h>
49*7f2fe78bSCy Schubert #include <gssrpc/pmap_rmt.h>
50*7f2fe78bSCy Schubert #include <sys/socket.h>
51*7f2fe78bSCy Schubert #ifdef sun
52*7f2fe78bSCy Schubert #include <sys/sockio.h>
53*7f2fe78bSCy Schubert #endif
54*7f2fe78bSCy Schubert #ifdef OSF1
55*7f2fe78bSCy Schubert #include <net/route.h>
56*7f2fe78bSCy Schubert #include <sys/mbuf.h>
57*7f2fe78bSCy Schubert #endif
58*7f2fe78bSCy Schubert #include <net/if.h>
59*7f2fe78bSCy Schubert #include <sys/ioctl.h>
60*7f2fe78bSCy Schubert #include <arpa/inet.h>
61*7f2fe78bSCy Schubert #define MAX_BROADCAST_SIZE 1400
62*7f2fe78bSCy Schubert #include <port-sockets.h>
63*7f2fe78bSCy Schubert #include "socket-utils.h"
64*7f2fe78bSCy Schubert 
65*7f2fe78bSCy Schubert static struct timeval timeout = { 3, 0 };
66*7f2fe78bSCy Schubert 
67*7f2fe78bSCy Schubert #ifndef GETSOCKNAME_ARG3_TYPE
68*7f2fe78bSCy Schubert #define GETSOCKNAME_ARG3_TYPE int
69*7f2fe78bSCy Schubert #endif
70*7f2fe78bSCy Schubert 
71*7f2fe78bSCy Schubert /*
72*7f2fe78bSCy Schubert  * pmapper remote-call-service interface.
73*7f2fe78bSCy Schubert  * This routine is used to call the pmapper remote call service
74*7f2fe78bSCy Schubert  * which will look up a service program in the port maps, and then
75*7f2fe78bSCy Schubert  * remotely call that routine with the given parameters.  This allows
76*7f2fe78bSCy Schubert  * programs to do a lookup and call in one step.
77*7f2fe78bSCy Schubert */
78*7f2fe78bSCy Schubert enum clnt_stat
pmap_rmtcall(struct sockaddr_in * addr,rpcprog_t prog,rpcvers_t vers,rpcproc_t proc,xdrproc_t xdrargs,caddr_t argsp,xdrproc_t xdrres,caddr_t resp,struct timeval tout,rpcport_t * port_ptr)79*7f2fe78bSCy Schubert pmap_rmtcall(
80*7f2fe78bSCy Schubert 	struct sockaddr_in *addr,
81*7f2fe78bSCy Schubert 	rpcprog_t prog,
82*7f2fe78bSCy Schubert 	rpcvers_t vers,
83*7f2fe78bSCy Schubert 	rpcproc_t proc,
84*7f2fe78bSCy Schubert 	xdrproc_t xdrargs,
85*7f2fe78bSCy Schubert 	caddr_t argsp,
86*7f2fe78bSCy Schubert 	xdrproc_t xdrres,
87*7f2fe78bSCy Schubert 	caddr_t resp,
88*7f2fe78bSCy Schubert 	struct timeval tout,
89*7f2fe78bSCy Schubert 	rpcport_t *port_ptr)
90*7f2fe78bSCy Schubert {
91*7f2fe78bSCy Schubert         SOCKET sock = INVALID_SOCKET;
92*7f2fe78bSCy Schubert 	CLIENT *client;
93*7f2fe78bSCy Schubert 	struct rmtcallargs a;
94*7f2fe78bSCy Schubert 	struct rmtcallres r;
95*7f2fe78bSCy Schubert 	enum clnt_stat stat;
96*7f2fe78bSCy Schubert 
97*7f2fe78bSCy Schubert 	addr->sin_port = htons(PMAPPORT);
98*7f2fe78bSCy Schubert 	client = clntudp_create(addr, PMAPPROG, PMAPVERS, timeout, &sock);
99*7f2fe78bSCy Schubert 	if (client != (CLIENT *)NULL) {
100*7f2fe78bSCy Schubert 		a.prog = prog;
101*7f2fe78bSCy Schubert 		a.vers = vers;
102*7f2fe78bSCy Schubert 		a.proc = proc;
103*7f2fe78bSCy Schubert 		a.args_ptr = argsp;
104*7f2fe78bSCy Schubert 		a.xdr_args = xdrargs;
105*7f2fe78bSCy Schubert 		r.port_ptr = port_ptr;
106*7f2fe78bSCy Schubert 		r.results_ptr = resp;
107*7f2fe78bSCy Schubert 		r.xdr_results = xdrres;
108*7f2fe78bSCy Schubert 		stat = CLNT_CALL(client, PMAPPROC_CALLIT, xdr_rmtcall_args, &a,
109*7f2fe78bSCy Schubert 		    xdr_rmtcallres, &r, tout);
110*7f2fe78bSCy Schubert 		CLNT_DESTROY(client);
111*7f2fe78bSCy Schubert 	} else {
112*7f2fe78bSCy Schubert 		stat = RPC_FAILED;
113*7f2fe78bSCy Schubert 	}
114*7f2fe78bSCy Schubert         (void)closesocket(sock);
115*7f2fe78bSCy Schubert 	addr->sin_port = 0;
116*7f2fe78bSCy Schubert 	return (stat);
117*7f2fe78bSCy Schubert }
118*7f2fe78bSCy Schubert 
119*7f2fe78bSCy Schubert 
120*7f2fe78bSCy Schubert /*
121*7f2fe78bSCy Schubert  * XDR remote call arguments
122*7f2fe78bSCy Schubert  * written for XDR_ENCODE direction only
123*7f2fe78bSCy Schubert  */
124*7f2fe78bSCy Schubert bool_t
xdr_rmtcall_args(XDR * xdrs,struct rmtcallargs * cap)125*7f2fe78bSCy Schubert xdr_rmtcall_args(
126*7f2fe78bSCy Schubert 	XDR *xdrs,
127*7f2fe78bSCy Schubert 	struct rmtcallargs *cap)
128*7f2fe78bSCy Schubert {
129*7f2fe78bSCy Schubert 	u_int lenposition, argposition, position;
130*7f2fe78bSCy Schubert 
131*7f2fe78bSCy Schubert 	if (xdr_u_int32(xdrs, &(cap->prog)) &&
132*7f2fe78bSCy Schubert 	    xdr_u_int32(xdrs, &(cap->vers)) &&
133*7f2fe78bSCy Schubert 	    xdr_u_int32(xdrs, &(cap->proc))) {
134*7f2fe78bSCy Schubert 		lenposition = XDR_GETPOS(xdrs);
135*7f2fe78bSCy Schubert 		if (! xdr_u_int32(xdrs, &(cap->arglen)))
136*7f2fe78bSCy Schubert 		    return (FALSE);
137*7f2fe78bSCy Schubert 		argposition = XDR_GETPOS(xdrs);
138*7f2fe78bSCy Schubert 		if (! (*(cap->xdr_args))(xdrs, cap->args_ptr))
139*7f2fe78bSCy Schubert 		    return (FALSE);
140*7f2fe78bSCy Schubert 		position = XDR_GETPOS(xdrs);
141*7f2fe78bSCy Schubert 		cap->arglen = (uint32_t)position - (uint32_t)argposition;
142*7f2fe78bSCy Schubert 		XDR_SETPOS(xdrs, lenposition);
143*7f2fe78bSCy Schubert 		if (! xdr_u_int32(xdrs, &(cap->arglen)))
144*7f2fe78bSCy Schubert 		    return (FALSE);
145*7f2fe78bSCy Schubert 		XDR_SETPOS(xdrs, position);
146*7f2fe78bSCy Schubert 		return (TRUE);
147*7f2fe78bSCy Schubert 	}
148*7f2fe78bSCy Schubert 	return (FALSE);
149*7f2fe78bSCy Schubert }
150*7f2fe78bSCy Schubert 
151*7f2fe78bSCy Schubert /*
152*7f2fe78bSCy Schubert  * XDR remote call results
153*7f2fe78bSCy Schubert  * written for XDR_DECODE direction only
154*7f2fe78bSCy Schubert  */
155*7f2fe78bSCy Schubert bool_t
xdr_rmtcallres(XDR * xdrs,struct rmtcallres * crp)156*7f2fe78bSCy Schubert xdr_rmtcallres(
157*7f2fe78bSCy Schubert 	XDR *xdrs,
158*7f2fe78bSCy Schubert 	struct rmtcallres *crp)
159*7f2fe78bSCy Schubert {
160*7f2fe78bSCy Schubert 	caddr_t port_ptr;
161*7f2fe78bSCy Schubert 
162*7f2fe78bSCy Schubert 	port_ptr = (caddr_t)(void *)crp->port_ptr;
163*7f2fe78bSCy Schubert 	if (xdr_reference(xdrs, &port_ptr, sizeof (uint32_t),
164*7f2fe78bSCy Schubert 	    xdr_u_int32) && xdr_u_int32(xdrs, &crp->resultslen)) {
165*7f2fe78bSCy Schubert 		crp->port_ptr = (uint32_t *)(void *)port_ptr;
166*7f2fe78bSCy Schubert 		return ((*(crp->xdr_results))(xdrs, crp->results_ptr));
167*7f2fe78bSCy Schubert 	}
168*7f2fe78bSCy Schubert 	return (FALSE);
169*7f2fe78bSCy Schubert }
170*7f2fe78bSCy Schubert 
171*7f2fe78bSCy Schubert 
172*7f2fe78bSCy Schubert /*
173*7f2fe78bSCy Schubert  * The following is kludged-up support for simple rpc broadcasts.
174*7f2fe78bSCy Schubert  * Someday a large, complicated system will replace these trivial
175*7f2fe78bSCy Schubert  * routines which only support udp/ip .
176*7f2fe78bSCy Schubert  */
177*7f2fe78bSCy Schubert 
178*7f2fe78bSCy Schubert #define GIFCONF_BUFSIZE (256 * sizeof (struct ifconf))
179*7f2fe78bSCy Schubert 
180*7f2fe78bSCy Schubert static int
getbroadcastnets(struct in_addr * addrs,int sock,char * buf)181*7f2fe78bSCy Schubert getbroadcastnets(
182*7f2fe78bSCy Schubert 	struct in_addr *addrs,
183*7f2fe78bSCy Schubert 	int sock,  /* any valid socket will do */
184*7f2fe78bSCy Schubert 	char *buf  /* why allocxate more when we can use existing... */
185*7f2fe78bSCy Schubert 	)
186*7f2fe78bSCy Schubert {
187*7f2fe78bSCy Schubert 	struct ifconf ifc;
188*7f2fe78bSCy Schubert         struct ifreq ifreq, *ifr;
189*7f2fe78bSCy Schubert         int n, i;
190*7f2fe78bSCy Schubert 
191*7f2fe78bSCy Schubert         ifc.ifc_len = GIFCONF_BUFSIZE;
192*7f2fe78bSCy Schubert         ifc.ifc_buf = buf;
193*7f2fe78bSCy Schubert 	memset (buf, 0, GIFCONF_BUFSIZE);
194*7f2fe78bSCy Schubert         if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
195*7f2fe78bSCy Schubert                 perror("broadcast: ioctl (get interface configuration)");
196*7f2fe78bSCy Schubert                 return (0);
197*7f2fe78bSCy Schubert         }
198*7f2fe78bSCy Schubert         ifr = ifc.ifc_req;
199*7f2fe78bSCy Schubert         for (i = 0, n = ifc.ifc_len/sizeof (struct ifreq); n > 0; n--, ifr++) {
200*7f2fe78bSCy Schubert                 ifreq = *ifr;
201*7f2fe78bSCy Schubert                 if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
202*7f2fe78bSCy Schubert                         perror("broadcast: ioctl (get interface flags)");
203*7f2fe78bSCy Schubert                         continue;
204*7f2fe78bSCy Schubert                 }
205*7f2fe78bSCy Schubert                 if ((ifreq.ifr_flags & IFF_BROADCAST) &&
206*7f2fe78bSCy Schubert 		    (ifreq.ifr_flags & IFF_UP) &&
207*7f2fe78bSCy Schubert 		    ifr->ifr_addr.sa_family == AF_INET) {
208*7f2fe78bSCy Schubert #ifdef SIOCGIFBRDADDR   /* 4.3BSD */
209*7f2fe78bSCy Schubert 			if (ioctl(sock, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
210*7f2fe78bSCy Schubert 				addrs[i++].s_addr = INADDR_ANY;
211*7f2fe78bSCy Schubert 			} else {
212*7f2fe78bSCy Schubert 				addrs[i++] = sa2sin(&ifreq.ifr_addr)->sin_addr;
213*7f2fe78bSCy Schubert 			}
214*7f2fe78bSCy Schubert #else /* 4.2 BSD */
215*7f2fe78bSCy Schubert 			struct sockaddr_in *sockin;
216*7f2fe78bSCy Schubert 			sockin = sa2sin(&ifr->ifr_addr);
217*7f2fe78bSCy Schubert 			addrs[i++] = inet_makeaddr(inet_netof
218*7f2fe78bSCy Schubert 			  (sockin->sin_addr.s_addr), INADDR_ANY);
219*7f2fe78bSCy Schubert #endif
220*7f2fe78bSCy Schubert 		}
221*7f2fe78bSCy Schubert 	}
222*7f2fe78bSCy Schubert 	return (i);
223*7f2fe78bSCy Schubert }
224*7f2fe78bSCy Schubert 
225*7f2fe78bSCy Schubert enum clnt_stat
clnt_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)226*7f2fe78bSCy Schubert clnt_broadcast(
227*7f2fe78bSCy Schubert 	rpcprog_t	prog,		/* program number */
228*7f2fe78bSCy Schubert 	rpcvers_t	vers,		/* version number */
229*7f2fe78bSCy Schubert 	rpcproc_t	proc,		/* procedure number */
230*7f2fe78bSCy Schubert 	xdrproc_t	xargs,		/* xdr routine for args */
231*7f2fe78bSCy Schubert 	caddr_t		argsp,		/* pointer to args */
232*7f2fe78bSCy Schubert 	xdrproc_t	xresults,	/* xdr routine for results */
233*7f2fe78bSCy Schubert 	caddr_t		resultsp,	/* pointer to results */
234*7f2fe78bSCy Schubert 	resultproc_t	eachresult	/* call with each result obtained */
235*7f2fe78bSCy Schubert 	)
236*7f2fe78bSCy Schubert {
237*7f2fe78bSCy Schubert 	enum clnt_stat stat;
238*7f2fe78bSCy Schubert 	AUTH *unix_auth = authunix_create_default();
239*7f2fe78bSCy Schubert 	XDR xdr_stream;
240*7f2fe78bSCy Schubert 	XDR *xdrs = &xdr_stream;
241*7f2fe78bSCy Schubert 	int outlen, nets;
242*7f2fe78bSCy Schubert 	ssize_t inlen;
243*7f2fe78bSCy Schubert 	GETSOCKNAME_ARG3_TYPE fromlen;
244*7f2fe78bSCy Schubert         SOCKET sock;
245*7f2fe78bSCy Schubert 	int on = 1;
246*7f2fe78bSCy Schubert #ifdef FD_SETSIZE
247*7f2fe78bSCy Schubert 	fd_set mask;
248*7f2fe78bSCy Schubert 	fd_set readfds;
249*7f2fe78bSCy Schubert #else
250*7f2fe78bSCy Schubert 	int readfds;
251*7f2fe78bSCy Schubert 	int mask;
252*7f2fe78bSCy Schubert #endif /* def FD_SETSIZE */
253*7f2fe78bSCy Schubert 	int i;
254*7f2fe78bSCy Schubert 	bool_t done = FALSE;
255*7f2fe78bSCy Schubert 	uint32_t xid;
256*7f2fe78bSCy Schubert 	rpcport_t port;
257*7f2fe78bSCy Schubert 	struct in_addr addrs[20];
258*7f2fe78bSCy Schubert 	struct sockaddr_in baddr, raddr; /* broadcast and response addresses */
259*7f2fe78bSCy Schubert 	struct rmtcallargs a;
260*7f2fe78bSCy Schubert 	struct rmtcallres r;
261*7f2fe78bSCy Schubert 	struct rpc_msg msg;
262*7f2fe78bSCy Schubert 	struct timeval t, t2;
263*7f2fe78bSCy Schubert 	char outbuf[MAX_BROADCAST_SIZE];
264*7f2fe78bSCy Schubert #ifndef MAX
265*7f2fe78bSCy Schubert #define MAX(A,B) ((A)<(B)?(B):(A))
266*7f2fe78bSCy Schubert #endif
267*7f2fe78bSCy Schubert 	char inbuf[MAX (UDPMSGSIZE, GIFCONF_BUFSIZE)];
268*7f2fe78bSCy Schubert 
269*7f2fe78bSCy Schubert 	/*
270*7f2fe78bSCy Schubert 	 * initialization: create a socket, a broadcast address, and
271*7f2fe78bSCy Schubert 	 * preserialize the arguments into a send buffer.
272*7f2fe78bSCy Schubert 	 */
273*7f2fe78bSCy Schubert 	if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
274*7f2fe78bSCy Schubert 		perror("Cannot create socket for broadcast rpc");
275*7f2fe78bSCy Schubert 		stat = RPC_CANTSEND;
276*7f2fe78bSCy Schubert 		goto done_broad;
277*7f2fe78bSCy Schubert 	}
278*7f2fe78bSCy Schubert 	set_cloexec_fd(sock);
279*7f2fe78bSCy Schubert #ifdef SO_BROADCAST
280*7f2fe78bSCy Schubert 	if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *) &on,
281*7f2fe78bSCy Schubert 		       sizeof (on)) < 0) {
282*7f2fe78bSCy Schubert 		perror("Cannot set socket option SO_BROADCAST");
283*7f2fe78bSCy Schubert 		stat = RPC_CANTSEND;
284*7f2fe78bSCy Schubert 		goto done_broad;
285*7f2fe78bSCy Schubert 	}
286*7f2fe78bSCy Schubert #endif /* def SO_BROADCAST */
287*7f2fe78bSCy Schubert #ifdef FD_SETSIZE
288*7f2fe78bSCy Schubert 	FD_ZERO(&mask);
289*7f2fe78bSCy Schubert 	FD_SET(sock, &mask);
290*7f2fe78bSCy Schubert #else
291*7f2fe78bSCy Schubert 	mask = (1 << sock);
292*7f2fe78bSCy Schubert #endif /* def FD_SETSIZE */
293*7f2fe78bSCy Schubert 	nets = getbroadcastnets(addrs, sock, inbuf);
294*7f2fe78bSCy Schubert 	memset(&baddr, 0, sizeof (baddr));
295*7f2fe78bSCy Schubert 	baddr.sin_family = AF_INET;
296*7f2fe78bSCy Schubert 	baddr.sin_port = htons(PMAPPORT);
297*7f2fe78bSCy Schubert 	baddr.sin_addr.s_addr = htonl(INADDR_ANY);
298*7f2fe78bSCy Schubert /*	baddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); */
299*7f2fe78bSCy Schubert 	(void)gettimeofday(&t, (struct timezone *)0);
300*7f2fe78bSCy Schubert 	msg.rm_xid = xid = getpid() ^ t.tv_sec ^ t.tv_usec;
301*7f2fe78bSCy Schubert 	t.tv_usec = 0;
302*7f2fe78bSCy Schubert 	msg.rm_direction = CALL;
303*7f2fe78bSCy Schubert 	msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
304*7f2fe78bSCy Schubert 	msg.rm_call.cb_prog = PMAPPROG;
305*7f2fe78bSCy Schubert 	msg.rm_call.cb_vers = PMAPVERS;
306*7f2fe78bSCy Schubert 	msg.rm_call.cb_proc = PMAPPROC_CALLIT;
307*7f2fe78bSCy Schubert 	msg.rm_call.cb_cred = unix_auth->ah_cred;
308*7f2fe78bSCy Schubert 	msg.rm_call.cb_verf = unix_auth->ah_verf;
309*7f2fe78bSCy Schubert 	a.prog = prog;
310*7f2fe78bSCy Schubert 	a.vers = vers;
311*7f2fe78bSCy Schubert 	a.proc = proc;
312*7f2fe78bSCy Schubert 	a.xdr_args = xargs;
313*7f2fe78bSCy Schubert 	a.args_ptr = argsp;
314*7f2fe78bSCy Schubert 	r.port_ptr = &port;
315*7f2fe78bSCy Schubert 	r.xdr_results = xresults;
316*7f2fe78bSCy Schubert 	r.results_ptr = resultsp;
317*7f2fe78bSCy Schubert 	xdrmem_create(xdrs, outbuf, MAX_BROADCAST_SIZE, XDR_ENCODE);
318*7f2fe78bSCy Schubert 	if ((! xdr_callmsg(xdrs, &msg)) || (! xdr_rmtcall_args(xdrs, &a))) {
319*7f2fe78bSCy Schubert 		stat = RPC_CANTENCODEARGS;
320*7f2fe78bSCy Schubert 		goto done_broad;
321*7f2fe78bSCy Schubert 	}
322*7f2fe78bSCy Schubert 	outlen = (int)xdr_getpos(xdrs);
323*7f2fe78bSCy Schubert 	xdr_destroy(xdrs);
324*7f2fe78bSCy Schubert 	/*
325*7f2fe78bSCy Schubert 	 * Basic loop: broadcast a packet and wait a while for response(s).
326*7f2fe78bSCy Schubert 	 * The response timeout grows larger per iteration.
327*7f2fe78bSCy Schubert 	 */
328*7f2fe78bSCy Schubert 	for (t.tv_sec = 4; t.tv_sec <= 14; t.tv_sec += 2) {
329*7f2fe78bSCy Schubert 		for (i = 0; i < nets; i++) {
330*7f2fe78bSCy Schubert 			baddr.sin_addr = addrs[i];
331*7f2fe78bSCy Schubert 			if (sendto(sock, outbuf, outlen, 0,
332*7f2fe78bSCy Schubert 				(struct sockaddr *)&baddr,
333*7f2fe78bSCy Schubert 				sizeof (struct sockaddr)) != outlen) {
334*7f2fe78bSCy Schubert 				perror("Cannot send broadcast packet");
335*7f2fe78bSCy Schubert 				stat = RPC_CANTSEND;
336*7f2fe78bSCy Schubert 				goto done_broad;
337*7f2fe78bSCy Schubert 			}
338*7f2fe78bSCy Schubert 		}
339*7f2fe78bSCy Schubert 		if (eachresult == NULL) {
340*7f2fe78bSCy Schubert 			stat = RPC_SUCCESS;
341*7f2fe78bSCy Schubert 			goto done_broad;
342*7f2fe78bSCy Schubert 		}
343*7f2fe78bSCy Schubert 	recv_again:
344*7f2fe78bSCy Schubert 		msg.acpted_rply.ar_verf = gssrpc__null_auth;
345*7f2fe78bSCy Schubert 		msg.acpted_rply.ar_results.where = (caddr_t)&r;
346*7f2fe78bSCy Schubert                 msg.acpted_rply.ar_results.proc = xdr_rmtcallres;
347*7f2fe78bSCy Schubert 		readfds = mask;
348*7f2fe78bSCy Schubert 		t2 = t;
349*7f2fe78bSCy Schubert 		switch (select(gssrpc__rpc_dtablesize(), &readfds, (fd_set *)NULL,
350*7f2fe78bSCy Schubert 			       (fd_set *)NULL, &t2)) {
351*7f2fe78bSCy Schubert 
352*7f2fe78bSCy Schubert 		case 0:  /* timed out */
353*7f2fe78bSCy Schubert 			stat = RPC_TIMEDOUT;
354*7f2fe78bSCy Schubert 			continue;
355*7f2fe78bSCy Schubert 
356*7f2fe78bSCy Schubert 		case -1:  /* some kind of error */
357*7f2fe78bSCy Schubert 			if (errno == EINTR)
358*7f2fe78bSCy Schubert 				goto recv_again;
359*7f2fe78bSCy Schubert 			perror("Broadcast select problem");
360*7f2fe78bSCy Schubert 			stat = RPC_CANTRECV;
361*7f2fe78bSCy Schubert 			goto done_broad;
362*7f2fe78bSCy Schubert 
363*7f2fe78bSCy Schubert 		}  /* end of select results switch */
364*7f2fe78bSCy Schubert 	try_again:
365*7f2fe78bSCy Schubert 		fromlen = sizeof(struct sockaddr);
366*7f2fe78bSCy Schubert 		inlen = recvfrom(sock, inbuf, UDPMSGSIZE, 0,
367*7f2fe78bSCy Schubert 			(struct sockaddr *)&raddr, &fromlen);
368*7f2fe78bSCy Schubert 		if (inlen < 0) {
369*7f2fe78bSCy Schubert 			if (errno == EINTR)
370*7f2fe78bSCy Schubert 				goto try_again;
371*7f2fe78bSCy Schubert 			perror("Cannot receive reply to broadcast");
372*7f2fe78bSCy Schubert 			stat = RPC_CANTRECV;
373*7f2fe78bSCy Schubert 			goto done_broad;
374*7f2fe78bSCy Schubert 		}
375*7f2fe78bSCy Schubert 		if ((size_t)inlen < sizeof(uint32_t))
376*7f2fe78bSCy Schubert 			goto recv_again;
377*7f2fe78bSCy Schubert 		/*
378*7f2fe78bSCy Schubert 		 * see if reply transaction id matches sent id.
379*7f2fe78bSCy Schubert 		 * If so, decode the results.
380*7f2fe78bSCy Schubert 		 */
381*7f2fe78bSCy Schubert 		xdrmem_create(xdrs, inbuf, (u_int)inlen, XDR_DECODE);
382*7f2fe78bSCy Schubert 		if (xdr_replymsg(xdrs, &msg)) {
383*7f2fe78bSCy Schubert 			if ((msg.rm_xid == xid) &&
384*7f2fe78bSCy Schubert 				(msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
385*7f2fe78bSCy Schubert 				(msg.acpted_rply.ar_stat == SUCCESS)) {
386*7f2fe78bSCy Schubert 				raddr.sin_port = htons((u_short)port);
387*7f2fe78bSCy Schubert 				done = (*eachresult)(resultsp, &raddr);
388*7f2fe78bSCy Schubert 			}
389*7f2fe78bSCy Schubert 			/* otherwise, we just ignore the errors ... */
390*7f2fe78bSCy Schubert 		} else {
391*7f2fe78bSCy Schubert #ifdef notdef
392*7f2fe78bSCy Schubert 			/* some kind of deserialization problem ... */
393*7f2fe78bSCy Schubert 			if (msg.rm_xid == xid)
394*7f2fe78bSCy Schubert 				fprintf(stderr, "Broadcast deserialization problem");
395*7f2fe78bSCy Schubert 			/* otherwise, just random garbage */
396*7f2fe78bSCy Schubert #endif
397*7f2fe78bSCy Schubert 		}
398*7f2fe78bSCy Schubert 		xdrs->x_op = XDR_FREE;
399*7f2fe78bSCy Schubert 		msg.acpted_rply.ar_results.proc = xdr_void;
400*7f2fe78bSCy Schubert 		(void)xdr_replymsg(xdrs, &msg);
401*7f2fe78bSCy Schubert 		(void)(*xresults)(xdrs, resultsp);
402*7f2fe78bSCy Schubert 		xdr_destroy(xdrs);
403*7f2fe78bSCy Schubert 		if (done) {
404*7f2fe78bSCy Schubert 			stat = RPC_SUCCESS;
405*7f2fe78bSCy Schubert 			goto done_broad;
406*7f2fe78bSCy Schubert 		} else {
407*7f2fe78bSCy Schubert 			goto recv_again;
408*7f2fe78bSCy Schubert 		}
409*7f2fe78bSCy Schubert 	}
410*7f2fe78bSCy Schubert done_broad:
411*7f2fe78bSCy Schubert         (void)closesocket(sock);
412*7f2fe78bSCy Schubert 	AUTH_DESTROY(unix_auth);
413*7f2fe78bSCy Schubert 	return (stat);
414*7f2fe78bSCy Schubert }
415