Annotation of 43BSDTahoe/new/sunrpc/pmap_rmt.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.