|
|
1.1 ! root 1: /* ! 2: * Sun RPC is a product of Sun Microsystems, Inc. and is provided for ! 3: * unrestricted use provided that this legend is included on all tape ! 4: * media and as a part of the software program in whole or part. Users ! 5: * may copy or modify Sun RPC without charge, but are not authorized ! 6: * to license or distribute it to anyone else except as part of a product or ! 7: * program developed by the user. ! 8: * ! 9: * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE ! 10: * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR ! 11: * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. ! 12: * ! 13: * Sun RPC is provided with no support and without any obligation on the ! 14: * part of Sun Microsystems, Inc. to assist in its use, correction, ! 15: * modification or enhancement. ! 16: * ! 17: * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE ! 18: * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC ! 19: * OR ANY PART THEREOF. ! 20: * ! 21: * In no event will Sun Microsystems, Inc. be liable for any lost revenue ! 22: * or profits or other special, indirect and consequential damages, even if ! 23: * Sun has been advised of the possibility of such damages. ! 24: * ! 25: * Sun Microsystems, Inc. ! 26: * 2550 Garcia Avenue ! 27: * Mountain View, California 94043 ! 28: */ ! 29: #ifndef lint ! 30: static char sccsid[] = "@(#)pmap_rmt.c 1.5 85/04/08 Copyr 1984 Sun Micro"; ! 31: #endif ! 32: ! 33: /* ! 34: * pmap_rmt.c ! 35: * Client interface to pmap rpc service. ! 36: * remote call and broadcast service ! 37: * ! 38: * Copyright (C) 1984, Sun Microsystems, Inc. ! 39: */ ! 40: ! 41: #include "types.h" ! 42: #include <netinet/in.h> ! 43: #include "xdr.h" ! 44: #include "auth.h" ! 45: #include "clnt.h" ! 46: #include "rpc_msg.h" ! 47: #include "pmap_prot.h" ! 48: #include "pmap_clnt.h" ! 49: #include <sys/socket.h> ! 50: #include <sys/time.h> ! 51: #include <stdio.h> ! 52: #include <errno.h> ! 53: #include <net/if.h> ! 54: #include <sys/ioctl.h> ! 55: #include <arpa/inet.h> ! 56: #define MAX_BROADCAST_SIZE 1400 ! 57: ! 58: extern int errno; ! 59: static struct timeval timeout = { 3, 0 }; ! 60: ! 61: /* ! 62: * Structures and XDR routines for parameters to and replys from ! 63: * the pmapper remote-call-service. ! 64: */ ! 65: ! 66: struct rmtcallargs { ! 67: u_long prog, vers, proc, arglen; ! 68: caddr_t args_ptr; ! 69: xdrproc_t xdr_args; ! 70: }; ! 71: static bool_t xdr_rmtcall_args(); ! 72: ! 73: struct rmtcallres { ! 74: u_long *port_ptr; ! 75: u_long resultslen; ! 76: caddr_t results_ptr; ! 77: xdrproc_t xdr_results; ! 78: }; ! 79: static bool_t xdr_rmtcallres(); ! 80: ! 81: /* ! 82: * pmapper remote-call-service interface. ! 83: * This routine is used to call the pmapper remote call service ! 84: * which will look up a service program in the port maps, and then ! 85: * remotely call that routine with the given parameters. This allows ! 86: * programs to do a lookup and call in one step. ! 87: */ ! 88: enum clnt_stat ! 89: pmap_rmtcall(addr, prog, vers, proc, xdrargs, argsp, xdrres, resp, tout, port_ptr) ! 90: struct sockaddr_in *addr; ! 91: u_long prog, vers, proc; ! 92: xdrproc_t xdrargs, xdrres; ! 93: caddr_t argsp, resp; ! 94: struct timeval tout; ! 95: u_long *port_ptr; ! 96: { ! 97: int socket = -1; ! 98: register CLIENT *client; ! 99: struct rmtcallargs a; ! 100: struct rmtcallres r; ! 101: enum clnt_stat stat; ! 102: ! 103: addr->sin_port = htons(PMAPPORT); ! 104: client = clntudp_create(addr, PMAPPROG, PMAPVERS, timeout, &socket); ! 105: if (client != (CLIENT *)NULL) { ! 106: a.prog = prog; ! 107: a.vers = vers; ! 108: a.proc = proc; ! 109: a.args_ptr = argsp; ! 110: a.xdr_args = xdrargs; ! 111: r.port_ptr = port_ptr; ! 112: r.results_ptr = resp; ! 113: r.xdr_results = xdrres; ! 114: stat = CLNT_CALL(client, PMAPPROC_CALLIT, xdr_rmtcall_args, &a, ! 115: xdr_rmtcallres, &r, tout); ! 116: CLNT_DESTROY(client); ! 117: } else { ! 118: stat = RPC_FAILED; ! 119: } ! 120: (void)close(socket); ! 121: addr->sin_port = 0; ! 122: return (stat); ! 123: } ! 124: ! 125: /* ! 126: * XDR remote call arguments ! 127: * written for XDR_ENCODE direction only ! 128: */ ! 129: static bool_t ! 130: xdr_rmtcall_args(xdrs, cap) ! 131: register XDR *xdrs; ! 132: register struct rmtcallargs *cap; ! 133: { ! 134: u_int lenposition, argposition, position; ! 135: ! 136: if (xdr_u_long(xdrs, &(cap->prog)) && ! 137: xdr_u_long(xdrs, &(cap->vers)) && ! 138: xdr_u_long(xdrs, &(cap->proc))) { ! 139: lenposition = XDR_GETPOS(xdrs); ! 140: if (! xdr_u_long(xdrs, &(cap->arglen))) ! 141: return (FALSE); ! 142: argposition = XDR_GETPOS(xdrs); ! 143: if (! (*(cap->xdr_args))(xdrs, cap->args_ptr)) ! 144: return (FALSE); ! 145: position = XDR_GETPOS(xdrs); ! 146: cap->arglen = (u_long)position - (u_long)argposition; ! 147: XDR_SETPOS(xdrs, lenposition); ! 148: if (! xdr_u_long(xdrs, &(cap->arglen))) ! 149: return (FALSE); ! 150: XDR_SETPOS(xdrs, position); ! 151: return (TRUE); ! 152: } ! 153: return (FALSE); ! 154: } ! 155: ! 156: /* ! 157: * XDR remote call results ! 158: * written for XDR_DECODE direction only ! 159: */ ! 160: static bool_t ! 161: xdr_rmtcallres(xdrs, crp) ! 162: register XDR *xdrs; ! 163: register struct rmtcallres *crp; ! 164: { ! 165: ! 166: if (xdr_reference(xdrs, &crp->port_ptr, sizeof (u_long), xdr_u_long) && ! 167: xdr_u_long(xdrs, &crp->resultslen)) ! 168: return ((*(crp->xdr_results))(xdrs, crp->results_ptr)); ! 169: return (FALSE); ! 170: } ! 171: ! 172: /* ! 173: * The following is kludged-up support for simple rpc broadcasts. ! 174: * Someday a large, complicated system will replace these trivial ! 175: * routines which only support udp/ip . ! 176: */ ! 177: ! 178: static int ! 179: getbroadcastnets(addrs, sock, buf) ! 180: struct in_addr *addrs; ! 181: int sock; /* any valid socket will do */ ! 182: char *buf; /* why allocxate more when we can use existing... */ ! 183: { ! 184: struct ifconf ifc; ! 185: struct ifreq ifreq, *ifr; ! 186: struct sockaddr_in *sin; ! 187: int n, i; ! 188: ! 189: ifc.ifc_len = MAX_BROADCAST_SIZE; ! 190: ifc.ifc_buf = buf; ! 191: if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) { ! 192: perror("broadcast: ioctl (get interface configuration)"); ! 193: return (0); ! 194: } ! 195: ifr = ifc.ifc_req; ! 196: for (i = 0, n = ifc.ifc_len/sizeof (struct ifreq); n > 0; n--, ifr++) { ! 197: ifreq = *ifr; ! 198: if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifreq) < 0) { ! 199: perror("broadcast: ioctl (get interface flags)"); ! 200: continue; ! 201: } ! 202: if ((ifreq.ifr_flags & IFF_BROADCAST) && ! 203: (ifreq.ifr_flags & IFF_UP) && ! 204: ifr->ifr_addr.sa_family == AF_INET) { ! 205: sin = (struct sockaddr_in *)&ifr->ifr_addr; ! 206: addrs[i++] = inet_makeaddr(inet_netof ! 207: (sin->sin_addr.s_addr), INADDR_ANY); ! 208: } ! 209: } ! 210: return (i); ! 211: } ! 212: ! 213: typedef bool_t (*resultproc_t)(); ! 214: ! 215: enum clnt_stat ! 216: clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult) ! 217: u_long prog; /* program number */ ! 218: u_long vers; /* version number */ ! 219: u_long proc; /* procedure number */ ! 220: xdrproc_t xargs; /* xdr routine for args */ ! 221: caddr_t argsp; /* pointer to args */ ! 222: xdrproc_t xresults; /* xdr routine for results */ ! 223: caddr_t resultsp; /* pointer to results */ ! 224: resultproc_t eachresult; /* call with each result obtained */ ! 225: { ! 226: enum clnt_stat stat; ! 227: AUTH *unix_auth = authunix_create_default(); ! 228: XDR xdr_stream; ! 229: register XDR *xdrs = &xdr_stream; ! 230: int outlen, inlen, fromlen, readfds, nets; ! 231: register int sock, mask, i; ! 232: bool_t done = FALSE; ! 233: register u_long xid; ! 234: u_long port; ! 235: struct in_addr addrs[20]; ! 236: struct sockaddr_in baddr, raddr; /* broadcast and response addresses */ ! 237: struct rmtcallargs a; ! 238: struct rmtcallres r; ! 239: struct rpc_msg msg; ! 240: struct timeval t; ! 241: char outbuf[MAX_BROADCAST_SIZE], inbuf[MAX_BROADCAST_SIZE]; ! 242: ! 243: /* ! 244: * initialization: create a socket, a broadcast address, and ! 245: * preserialize the arguments into a send buffer. ! 246: */ ! 247: if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { ! 248: perror("Cannot create socket for broadcast rpc"); ! 249: stat = RPC_CANTSEND; ! 250: goto done_broad; ! 251: } ! 252: mask = (1 << sock); ! 253: nets = getbroadcastnets(addrs, sock, inbuf); ! 254: bzero(&baddr, sizeof (baddr)); ! 255: baddr.sin_family = AF_INET; ! 256: baddr.sin_port = htons(PMAPPORT); ! 257: baddr.sin_addr.s_addr = htonl(INADDR_ANY); ! 258: (void)gettimeofday(&t, (struct timezone *)0); ! 259: msg.rm_xid = xid = getpid() ^ t.tv_sec ^ t.tv_usec; ! 260: t.tv_usec = 0; ! 261: msg.rm_direction = CALL; ! 262: msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; ! 263: msg.rm_call.cb_prog = PMAPPROG; ! 264: msg.rm_call.cb_vers = PMAPVERS; ! 265: msg.rm_call.cb_proc = PMAPPROC_CALLIT; ! 266: msg.rm_call.cb_cred = unix_auth->ah_cred; ! 267: msg.rm_call.cb_verf = unix_auth->ah_verf; ! 268: a.prog = prog; ! 269: a.vers = vers; ! 270: a.proc = proc; ! 271: a.xdr_args = xargs; ! 272: a.args_ptr = argsp; ! 273: r.port_ptr = &port; ! 274: r.xdr_results = xresults; ! 275: r.results_ptr = resultsp; ! 276: xdrmem_create(xdrs, outbuf, MAX_BROADCAST_SIZE, XDR_ENCODE); ! 277: if ((! xdr_callmsg(xdrs, &msg)) || (! xdr_rmtcall_args(xdrs, &a))) { ! 278: stat = RPC_CANTENCODEARGS; ! 279: goto done_broad; ! 280: } ! 281: outlen = (int)xdr_getpos(xdrs); ! 282: xdr_destroy(xdrs); ! 283: /* ! 284: * Basic loop: broadcast a packet and wait a while for response(s). ! 285: * The response timeout grows larger per iteration. ! 286: */ ! 287: for (t.tv_sec = 2; t.tv_sec <= 6; t.tv_sec += 2) { ! 288: for (i = 0; i < nets; i++) { ! 289: baddr.sin_addr = addrs[i]; ! 290: if (sendto(sock, outbuf, outlen, 0, ! 291: (struct socketaddr *)&baddr, ! 292: sizeof (struct sockaddr)) != outlen) { ! 293: perror("Cannot send broadcast packet"); ! 294: stat = RPC_CANTSEND; ! 295: goto done_broad; ! 296: } ! 297: } ! 298: recv_again: ! 299: msg.acpted_rply.ar_verf = _null_auth; ! 300: msg.acpted_rply.ar_results.where = (caddr_t)&r; ! 301: msg.acpted_rply.ar_results.proc = xdr_rmtcallres; ! 302: readfds = mask; ! 303: switch (select(32, &readfds, (int *)NULL, (int *)NULL, &t)) { ! 304: ! 305: case 0: /* timed out */ ! 306: stat = RPC_TIMEDOUT; ! 307: continue; ! 308: ! 309: case -1: /* some kind of error */ ! 310: if (errno == EINTR) ! 311: goto recv_again; ! 312: perror("Broadcast select problem"); ! 313: stat = RPC_CANTRECV; ! 314: goto done_broad; ! 315: ! 316: } /* end of select results switch */ ! 317: if ((readfds & mask) == 0) ! 318: goto recv_again; ! 319: try_again: ! 320: fromlen = sizeof(struct sockaddr); ! 321: inlen = recvfrom(sock, inbuf, MAX_BROADCAST_SIZE, 0, ! 322: (struct sockaddr *)&raddr, &fromlen); ! 323: if (inlen < 0) { ! 324: if (errno == EINTR) ! 325: goto try_again; ! 326: perror("Cannot receive reply to broadcast"); ! 327: stat = RPC_CANTRECV; ! 328: goto done_broad; ! 329: } ! 330: if (inlen < sizeof(u_long)) ! 331: goto recv_again; ! 332: /* ! 333: * see if reply transaction id matches sent id. ! 334: * If so, decode the results. ! 335: */ ! 336: xdrmem_create(xdrs, inbuf, inlen, XDR_DECODE); ! 337: if (xdr_replymsg(xdrs, &msg)) { ! 338: if ((msg.rm_xid == xid) && ! 339: (msg.rm_reply.rp_stat == MSG_ACCEPTED) && ! 340: (msg.acpted_rply.ar_stat == SUCCESS)) { ! 341: raddr.sin_port = htons((u_short)port); ! 342: done = (*eachresult)(resultsp, &raddr); ! 343: } ! 344: /* otherwise, we just ignore the errors ... */ ! 345: } else { ! 346: /* some kind of deserialization problem ... */ ! 347: if (msg.rm_xid == xid) ! 348: fprintf(stderr, "Broadcast deserialization problem"); ! 349: /* otherwise, just random garbage */ ! 350: } ! 351: xdrs->x_op = XDR_FREE; ! 352: msg.acpted_rply.ar_results.proc = xdr_void; ! 353: (void)xdr_replymsg(xdrs, &msg); ! 354: (void)(*xresults)(xdrs, resultsp); ! 355: xdr_destroy(xdrs); ! 356: if (done) { ! 357: stat = RPC_SUCCESS; ! 358: goto done_broad; ! 359: } else { ! 360: goto recv_again; ! 361: } ! 362: } ! 363: done_broad: ! 364: (void)close(sock); ! 365: AUTH_DESTROY(unix_auth); ! 366: return (stat); ! 367: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.