BSD 4_3_Net_2 release
[unix-history] / usr / src / sys / tests / nfs / unix-tests / tools / pmapbrd.c
CommitLineData
1c15e888
C
1/* @(#)pmapbrd.c 1.2 90/01/03 NFS Rev 2 Testsuite
2 * 1.4 Lachman ONC Test Suite source
3 *
4 * Test portmap broadcast rpc facility
5 */
6
7#include <rpc/rpc.h>
8#include <rpc/pmap_prot.h>
9#include <rpc/pmap_clnt.h>
10#include <sys/socket.h>
11#ifdef SVR3
12#include <sys/fs/nfs/time.h>
13#else
14#include <sys/time.h>
15#endif
16#include <stdio.h>
17#include <errno.h>
18#include <net/if.h>
19#include <sys/ioctl.h>
20#include <arpa/inet.h>
21
22#define MAX_BROADCAST_SIZE 1400
23
24XDR xdr_stream;
25extern int errno;
26static struct timeval timeout = { 3, 0 };
27struct sockaddr_in baddr; /* broadcast addresses */
28typedef bool_t (*resultproc_t)();
29char outbuf[MAX_BROADCAST_SIZE], inbuf[MAX_BROADCAST_SIZE];
30
31
32/*
33 * Structures and XDR routines for parameters to and replys from
34 * the pmapper remote-call-service.
35 */
36
37struct rmtcallargs {
38#ifdef SVR3
39 ulong prog, vers, proc, arglen;
40#else
41 u_long prog, vers, proc, arglen;
42#endif
43 caddr_t args_ptr;
44 xdrproc_t xdr_args;
45};
46static bool_t xdr_rmtcall_args();
47
48struct rmtcallres {
49#ifdef SVR3
50 ulong *port_ptr;
51 ulong resultslen;
52#else
53 u_long *port_ptr;
54 u_long resultslen;
55#endif
56 caddr_t results_ptr;
57 xdrproc_t xdr_results;
58};
59static bool_t xdr_rmtcallres();
60
61#ifdef SVR3
62#define RPROG (ulong)40000010
63#define RVERS (ulong)1
64#define RPROC_NUM (ulong)1
65#else
66#define RPROG (u_long)40000010
67#define RVERS (u_long)1
68#define RPROC_NUM (u_long)1
69#endif
70
71
72int i;
73main(argc, argv)
74int argc;
75char **argv;
76{
77 SVCXPRT *transp;
78 struct sockaddr_in sin;
79 int pktspersec, count;
80 int sock, readfds;
81 enum clnt_stat clnt_stat;
82#ifdef SVR3
83 ulong result;
84#else
85 u_long result;
86#endif
87 bool_t eachresult();
88 struct timeval t;
89 int a, b;
90
91 if (argc != 3) {
92 fprintf(stderr, "usage: %s pktspersec count\n", argv[0]);
93 exit(1);
94 }
95
96 pktspersec = atoi(argv[1]);
97 if (pktspersec < 1) {
98 fprintf(stderr,
99 "%s: packet rate must greater than or equal to 1\n",
100 argv[0]);
101 exit(1);
102 }
103 count = atoi(argv[2]);
104
105 sock = socket(AF_INET,SOCK_DGRAM,0);
106 sin.sin_family = AF_INET;
107 sin.sin_addr.s_addr = INADDR_ANY;
108 sin.sin_port = htons(3300);
109
110 if(bind(sock, (char *)&sin, sizeof (sin)) == -1) {
111 perror("brd: bind");
112 exit(1);
113 }
114#ifdef SO_BROADCAST
115 i = 1;
116 if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &i, sizeof(i)) == -1) {
117 perror("brd: setsockopt");
118 exit(1);
119 }
120#endif
121 getbroadcastnets(sock, inbuf);
122 baddr.sin_family = AF_INET;
123 baddr.sin_port = htons(PMAPPORT);
124 printf("broadcast addr %x\n", ntohl(baddr.sin_addr.s_addr));
125
126 if (pktspersec == 1) {
127 t.tv_sec = 1;
128 t.tv_usec = 0;
129 } else {
130 t.tv_sec = 0;
131 t.tv_usec = 1000000 / pktspersec;
132 }
133 printf("%d/sec for %d\n", pktspersec, count);
134
135 for (i=0; i<count; i++) {
136 /*
137 * modified verison of clnt_broadcast is called
138 */
139 clnt_stat =
140 clnt_broadcast(sock, RPROG, RVERS, RPROC_NUM, xdr_void, &a,
141 xdr_void, &b, eachresult, &t);
142 if(clnt_stat != RPC_TIMEDOUT) {
143 printf("error: clnt_stat = %d\n", clnt_stat);
144 clnt_perrno(clnt_stat);
145 exit(-1);
146 }
147 }
148}
149
150bool_t
151eachresult()
152{
153 return(1);
154}
155
156/*
157 * XDR remote call arguments
158 * written for XDR_ENCODE direction only
159 */
160static bool_t
161xdr_rmtcall_args(xdrs, cap)
162 register XDR *xdrs;
163 register struct rmtcallargs *cap;
164{
165#ifdef SVR3
166 uint lenposition, argposition, position;
167#else
168 u_int lenposition, argposition, position;
169#endif
170
171 if (xdr_u_long(xdrs, &(cap->prog)) &&
172 xdr_u_long(xdrs, &(cap->vers)) &&
173 xdr_u_long(xdrs, &(cap->proc))) {
174 lenposition = XDR_GETPOS(xdrs);
175 if (! xdr_u_long(xdrs, &(cap->arglen)))
176 return (FALSE);
177 argposition = XDR_GETPOS(xdrs);
178 if (! (*(cap->xdr_args))(xdrs, cap->args_ptr))
179 return (FALSE);
180 position = XDR_GETPOS(xdrs);
181#ifdef SVR3
182 cap->arglen = (ulong)position - (ulong)argposition;
183#else
184 cap->arglen = (u_long)position - (u_long)argposition;
185#endif
186 XDR_SETPOS(xdrs, lenposition);
187 if (! xdr_u_long(xdrs, &(cap->arglen)))
188 return (FALSE);
189 XDR_SETPOS(xdrs, position);
190 return (TRUE);
191 }
192 return (FALSE);
193}
194
195/*
196 * XDR remote call results
197 * written for XDR_DECODE direction only
198 */
199static bool_t
200xdr_rmtcallres(xdrs, crp)
201 register XDR *xdrs;
202 register struct rmtcallres *crp;
203{
204
205#ifdef SVR3
206 if (xdr_reference(xdrs, &crp->port_ptr, sizeof (ulong), xdr_u_long) &&
207#else
208 if (xdr_reference(xdrs, &crp->port_ptr, sizeof (u_long), xdr_u_long) &&
209#endif
210 xdr_u_long(xdrs, &crp->resultslen))
211 return ((*(crp->xdr_results))(xdrs, crp->results_ptr));
212 return (FALSE);
213}
214
215/*
216 * The following is kludged-up support for simple rpc broadcasts.
217 * Someday a large, complicated system will replace these trivial
218 * routines which only support udp/ip .
219 */
220
221static int
222getbroadcastnets(sock, buf)
223 int sock; /* any valid socket will do */
224 char *buf; /* why allocxate more when we can use existing... */
225{
226 struct ifconf ifc;
227 struct ifreq ifreq, *ifr;
228 struct sockaddr_in *sin;
229 int n, i;
230
231 ifc.ifc_len = MAX_BROADCAST_SIZE;
232 ifc.ifc_buf = buf;
233 if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
234 perror("broadcast: ioctl (get interface configuration)");
235 return (0);
236 }
237 ifr = ifc.ifc_req;
238 for (i = 0, n = ifc.ifc_len/sizeof (struct ifreq); n > 0; n--, ifr++) {
239 ifreq = *ifr;
240 if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
241 perror("broadcast: ioctl (get interface flags)");
242 continue;
243 }
244 if ((ifreq.ifr_flags & IFF_BROADCAST) &&
245 (ifreq.ifr_flags & IFF_UP) &&
246 ifr->ifr_addr.sa_family == AF_INET) {
247 sin = (struct sockaddr_in *)&ifr->ifr_addr;
248#ifdef SIOCGIFBRDADDR
249 if (ioctl(sock, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
250 baddr.sin_addr = inet_makeaddr(inet_netof(sin->sin_addr),
251 INADDR_ANY);
252 } else {
253 baddr.sin_addr = ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr;
254 }
255
256#else
257 baddr.sin_addr = inet_makeaddr(inet_netof
258 (sin->sin_addr.s_addr), INADDR_ANY);
259#endif
260 break;
261 }
262 }
263}
264
265enum clnt_stat
266clnt_broadcast(sock, prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult, t)
267 int sock;
268#ifdef SVR3
269 ulong prog; /* program number */
270 ulong vers; /* version number */
271 ulong proc; /* procedure number */
272#else
273 u_long prog; /* program number */
274 u_long vers; /* version number */
275 u_long proc; /* procedure number */
276#endif
277 xdrproc_t xargs; /* xdr routine for args */
278 caddr_t argsp; /* pointer to args */
279 xdrproc_t xresults; /* xdr routine for results */
280 caddr_t resultsp; /* pointer to results */
281 resultproc_t eachresult; /* call with each result obtained */
282 struct timeval *t;
283{
284 XDR *xdrs = &xdr_stream;
285 enum clnt_stat stat;
286 AUTH *unix_auth = authunix_create_default();
287 int outlen, inlen, fromlen, readfds;
288 register int mask, i;
289 bool_t done = FALSE;
290#ifdef SVR3
291 register ulong xid;
292 ulong port;
293#else
294 register u_long xid;
295 u_long port;
296#endif
297 struct sockaddr_in raddr; /* broadcast and response addresses */
298 struct rmtcallargs a;
299 struct rmtcallres r;
300 struct rpc_msg msg;
301
302 mask = (1 << sock);
303 msg.rm_xid = xid;
304 msg.rm_direction = CALL;
305 msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
306 msg.rm_call.cb_prog = PMAPPROG;
307 msg.rm_call.cb_vers = PMAPVERS;
308 msg.rm_call.cb_proc = PMAPPROC_CALLIT;
309 msg.rm_call.cb_cred = unix_auth->ah_cred;
310 msg.rm_call.cb_verf = unix_auth->ah_verf;
311 a.prog = prog;
312 a.vers = vers;
313 a.proc = proc;
314 a.xdr_args = xargs;
315 a.args_ptr = argsp;
316 r.port_ptr = &port;
317 r.xdr_results = xresults;
318 r.results_ptr = resultsp;
319 xdrmem_create(xdrs, outbuf, MAX_BROADCAST_SIZE, XDR_ENCODE);
320 if ((! xdr_callmsg(xdrs, &msg)) || (! xdr_rmtcall_args(xdrs, &a))) {
321 stat = RPC_CANTENCODEARGS;
322 goto done_broad;
323 }
324 outlen = (int)xdr_getpos(xdrs);
325 xdr_destroy(xdrs);
326 /*
327 * Basic loop: broadcast a packet and wait a while for response(s).
328 * The response timeout grows larger per iteration.
329 */
330
331 if (sendto(sock, outbuf, outlen, 0,
332 (struct socketaddr *)&baddr,
333 sizeof (struct sockaddr)) != outlen) {
334 perror("Cannot send broadcast packet");
335 stat = RPC_CANTSEND;
336 goto done_broad;
337 }
338recv_again:
339 msg.acpted_rply.ar_verf = _null_auth;
340 msg.acpted_rply.ar_results.where = (caddr_t)&r;
341 msg.acpted_rply.ar_results.proc = xdr_rmtcallres;
342 readfds = mask;
343 switch (select(32, &readfds, (int *)NULL, (int *)NULL, t)) {
344
345 case 0: /* timed out */
346 stat = RPC_TIMEDOUT;
347 goto done_broad;
348
349 case -1: /* some kind of error */
350 if (errno == EINTR)
351 goto recv_again;
352 perror("Broadcast select problem");
353 stat = RPC_CANTRECV;
354 goto done_broad;
355
356 } /* end of select results switch */
357 if ((readfds & mask) == 0)
358 goto recv_again;
359try_again:
360 fromlen = sizeof(struct sockaddr);
361 inlen = recvfrom(sock, inbuf, MAX_BROADCAST_SIZE, 0,
362 (struct sockaddr *)&raddr, &fromlen);
363 if (inlen < 0) {
364 if (errno == EINTR)
365 goto try_again;
366 perror("Cannot receive reply to broadcast");
367 stat = RPC_CANTRECV;
368 goto done_broad;
369 }
370#ifdef SVR3
371 if (inlen < sizeof(ulong))
372#else
373 if (inlen < sizeof(u_long))
374#endif
375 goto recv_again;
376 /*
377 * see if reply transaction id matches sent id.
378 * If so, decode the results.
379 */
380 xdrmem_create(xdrs, inbuf, inlen, XDR_DECODE);
381 if (xdr_replymsg(xdrs, &msg)) {
382 if ((msg.rm_xid == xid) &&
383 (msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
384 (msg.acpted_rply.ar_stat == SUCCESS)) {
385#ifdef SVR3
386 raddr.sin_port = htons((ushort)port);
387#else
388 raddr.sin_port = htons((u_short)port);
389#endif
390 done = (*eachresult)(resultsp, &raddr);
391 }
392 /* otherwise, we just ignore the errors ... */
393 } else {
394 /* some kind of deserialization problem ... */
395 if (msg.rm_xid == xid)
396 fprintf(stderr, "Broadcast deserialization problem");
397 /* otherwise, just random garbage */
398 }
399 xdrs->x_op = XDR_FREE;
400 msg.acpted_rply.ar_results.proc = xdr_void;
401 (void)xdr_replymsg(xdrs, &msg);
402 (void)(*xresults)(xdrs, resultsp);
403 xdr_destroy(xdrs);
404 if (done) {
405 stat = RPC_SUCCESS;
406 } else {
407 goto recv_again;
408 }
409
410done_broad:
411 AUTH_DESTROY(unix_auth);
412 return (stat);
413}