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: }

Defined functions

bool_t defined in line 213; used 7 times
clnt_broadcast defined in line 215; used 1 times
getbroadcastnets defined in line 178; used 1 times
pmap_rmtcall defined in line 88; used 1 times
xdr_rmtcall_args defined in line 129; used 3 times
xdr_rmtcallres defined in line 160; used 3 times

Defined variables

sccsid defined in line 30; never used
timeout defined in line 59; used 1 times

Defined struct's

rmtcallargs defined in line 66; used 6 times
rmtcallres defined in line 73; used 6 times

Defined macros

MAX_BROADCAST_SIZE defined in line 56; used 5 times
Last modified: 1985-08-28
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1843
Valid CSS Valid XHTML 1.0 Strict