|
|
1.1 root 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:
24: XDR xdr_stream;
25: extern int errno;
26: static struct timeval timeout = { 3, 0 };
27: struct sockaddr_in baddr; /* broadcast addresses */
28: typedef bool_t (*resultproc_t)();
29: char 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:
37: struct 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: };
46: static bool_t xdr_rmtcall_args();
47:
48: struct 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: };
59: static 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:
72: int i;
73: main(argc, argv)
74: int argc;
75: char **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:
150: bool_t
151: eachresult()
152: {
153: return(1);
154: }
155:
156: /*
157: * XDR remote call arguments
158: * written for XDR_ENCODE direction only
159: */
160: static bool_t
161: xdr_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: */
199: static bool_t
200: xdr_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:
221: static int
222: getbroadcastnets(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:
265: enum clnt_stat
266: clnt_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: }
338: recv_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;
359: try_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:
410: done_broad:
411: AUTH_DESTROY(unix_auth);
412: return (stat);
413: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.