|
|
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.