[BACK]Return to krpc_subr.c CVS log [TXT][DIR] Up to [local] / sys / nfs

Annotation of sys/nfs/krpc_subr.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: krpc_subr.c,v 1.14 2007/02/27 19:09:56 deraadt Exp $  */
        !             2: /*     $NetBSD: krpc_subr.c,v 1.12.4.1 1996/06/07 00:52:26 cgd Exp $   */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1995 Gordon Ross, Adam Glass
        !             6:  * Copyright (c) 1992 Regents of the University of California.
        !             7:  * All rights reserved.
        !             8:  *
        !             9:  * This software was developed by the Computer Systems Engineering group
        !            10:  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
        !            11:  * contributed to Berkeley.
        !            12:  *
        !            13:  * Redistribution and use in source and binary forms, with or without
        !            14:  * modification, are permitted provided that the following conditions
        !            15:  * are met:
        !            16:  * 1. Redistributions of source code must retain the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer.
        !            18:  * 2. Redistributions in binary form must reproduce the above copyright
        !            19:  *    notice, this list of conditions and the following disclaimer in the
        !            20:  *    documentation and/or other materials provided with the distribution.
        !            21:  * 3. All advertising materials mentioning features or use of this software
        !            22:  *    must display the following acknowledgement:
        !            23:  *     This product includes software developed by the University of
        !            24:  *     California, Lawrence Berkeley Laboratory and its contributors.
        !            25:  * 4. Neither the name of the University nor the names of its contributors
        !            26:  *    may be used to endorse or promote products derived from this software
        !            27:  *    without specific prior written permission.
        !            28:  *
        !            29:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            30:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            31:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            32:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            33:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            34:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            35:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            36:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            37:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            38:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            39:  * SUCH DAMAGE.
        !            40:  *
        !            41:  * partially based on:
        !            42:  *      libnetboot/rpc.c
        !            43:  *               @(#) Header: rpc.c,v 1.12 93/09/28 08:31:56 leres Exp  (LBL)
        !            44:  */
        !            45:
        !            46: #include <sys/param.h>
        !            47: #include <sys/systm.h>
        !            48: #include <sys/conf.h>
        !            49: #include <sys/ioctl.h>
        !            50: #include <sys/proc.h>
        !            51: #include <sys/mount.h>
        !            52: #include <sys/mbuf.h>
        !            53: #include <sys/reboot.h>
        !            54: #include <sys/socket.h>
        !            55: #include <sys/socketvar.h>
        !            56:
        !            57: #include <net/if.h>
        !            58: #include <netinet/in.h>
        !            59:
        !            60: #include <nfs/rpcv2.h>
        !            61: #include <nfs/krpc.h>
        !            62: #include <nfs/xdr_subs.h>
        !            63: #include <dev/rndvar.h>
        !            64:
        !            65: /*
        !            66:  * Kernel support for Sun RPC
        !            67:  *
        !            68:  * Used currently for bootstrapping in nfs diskless configurations.
        !            69:  */
        !            70:
        !            71: /*
        !            72:  * Generic RPC headers
        !            73:  */
        !            74:
        !            75: struct auth_info {
        !            76:        u_int32_t       authtype;       /* auth type */
        !            77:        u_int32_t       authlen;        /* auth length */
        !            78: };
        !            79:
        !            80: struct auth_unix {
        !            81:        int32_t   ua_time;
        !            82:        int32_t   ua_hostname;  /* null */
        !            83:        int32_t   ua_uid;
        !            84:        int32_t   ua_gid;
        !            85:        int32_t   ua_gidlist;   /* null */
        !            86: };
        !            87:
        !            88: struct rpc_call {
        !            89:        u_int32_t       rp_xid;         /* request transaction id */
        !            90:        int32_t         rp_direction;   /* call direction (0) */
        !            91:        u_int32_t       rp_rpcvers;     /* rpc version (2) */
        !            92:        u_int32_t       rp_prog;        /* program */
        !            93:        u_int32_t       rp_vers;        /* version */
        !            94:        u_int32_t       rp_proc;        /* procedure */
        !            95:        struct  auth_info rpc_auth;
        !            96:        struct  auth_unix rpc_unix;
        !            97:        struct  auth_info rpc_verf;
        !            98: };
        !            99:
        !           100: struct rpc_reply {
        !           101:        u_int32_t rp_xid;               /* request transaction id */
        !           102:        int32_t   rp_direction;         /* call direction (1) */
        !           103:        int32_t   rp_astatus;           /* accept status (0: accepted) */
        !           104:        union {
        !           105:                u_int32_t rpu_errno;
        !           106:                struct {
        !           107:                        struct auth_info rok_auth;
        !           108:                        u_int32_t       rok_status;
        !           109:                } rpu_rok;
        !           110:        } rp_u;
        !           111: };
        !           112: #define rp_errno  rp_u.rpu_errno
        !           113: #define rp_auth   rp_u.rpu_rok.rok_auth
        !           114: #define rp_status rp_u.rpu_rok.rok_status
        !           115:
        !           116: #define MIN_REPLY_HDR 16       /* xid, dir, astat, errno */
        !           117:
        !           118: /*
        !           119:  * What is the longest we will wait before re-sending a request?
        !           120:  * Note this is also the frequency of "RPC timeout" messages.
        !           121:  * The re-send loop count sup linearly to this maximum, so the
        !           122:  * first complaint will happen after (1+2+3+4+5)=15 seconds.
        !           123:  */
        !           124: #define        MAX_RESEND_DELAY 5      /* seconds */
        !           125:
        !           126: /*
        !           127:  * Call portmap to lookup a port number for a particular rpc program
        !           128:  * Returns non-zero error on failure.
        !           129:  */
        !           130: int
        !           131: krpc_portmap(sin,  prog, vers, portp)
        !           132:        struct sockaddr_in *sin;                /* server address */
        !           133:        u_int prog, vers;       /* host order */
        !           134:        u_int16_t *portp;       /* network order */
        !           135: {
        !           136:        struct sdata {
        !           137:                u_int32_t prog;         /* call program */
        !           138:                u_int32_t vers;         /* call version */
        !           139:                u_int32_t proto;        /* call protocol */
        !           140:                u_int32_t port;         /* call port (unused) */
        !           141:        } *sdata;
        !           142:        struct rdata {
        !           143:                u_int16_t pad;
        !           144:                u_int16_t port;
        !           145:        } *rdata;
        !           146:        struct mbuf *m;
        !           147:        int error;
        !           148:
        !           149:        /* The portmapper port is fixed. */
        !           150:        if (prog == PMAPPROG) {
        !           151:                *portp = htons(PMAPPORT);
        !           152:                return 0;
        !           153:        }
        !           154:
        !           155:        m = m_get(M_WAIT, MT_DATA);
        !           156:        sdata = mtod(m, struct sdata *);
        !           157:        m->m_len = sizeof(*sdata);
        !           158:
        !           159:        /* Do the RPC to get it. */
        !           160:        sdata->prog = txdr_unsigned(prog);
        !           161:        sdata->vers = txdr_unsigned(vers);
        !           162:        sdata->proto = txdr_unsigned(IPPROTO_UDP);
        !           163:        sdata->port = 0;
        !           164:
        !           165:        sin->sin_port = htons(PMAPPORT);
        !           166:        error = krpc_call(sin, PMAPPROG, PMAPVERS,
        !           167:            PMAPPROC_GETPORT, &m, NULL, -1);
        !           168:        if (error)
        !           169:                return error;
        !           170:
        !           171:        if (m->m_len < sizeof(*rdata)) {
        !           172:                m = m_pullup(m, sizeof(*rdata));
        !           173:                if (m == NULL)
        !           174:                        return ENOBUFS;
        !           175:        }
        !           176:        rdata = mtod(m, struct rdata *);
        !           177:        *portp = rdata->port;
        !           178:
        !           179:        m_freem(m);
        !           180:        return 0;
        !           181: }
        !           182:
        !           183: /*
        !           184:  * Do a remote procedure call (RPC) and wait for its reply.
        !           185:  * If from_p is non-null, then we are doing broadcast, and
        !           186:  * the address from whence the response came is saved there.
        !           187:  */
        !           188: int
        !           189: krpc_call(sa, prog, vers, func, data, from_p, retries)
        !           190:        struct sockaddr_in *sa;
        !           191:        u_int prog, vers, func;
        !           192:        struct mbuf **data;     /* input/output */
        !           193:        struct mbuf **from_p;   /* output */
        !           194:        int retries;
        !           195: {
        !           196:        struct socket *so;
        !           197:        struct sockaddr_in *sin;
        !           198:        struct mbuf *m, *nam, *mhead, *from, *mopt;
        !           199:        struct rpc_call *call;
        !           200:        struct rpc_reply *reply;
        !           201:        struct uio auio;
        !           202:        int error, rcvflg, timo, secs, len;
        !           203:        static u_int32_t xid = 0;
        !           204:        u_int32_t newxid;
        !           205:        int *ip;
        !           206:        struct timeval *tv;
        !           207:
        !           208:        /*
        !           209:         * Validate address family.
        !           210:         * Sorry, this is INET specific...
        !           211:         */
        !           212:        if (sa->sin_family != AF_INET)
        !           213:                return (EAFNOSUPPORT);
        !           214:
        !           215:        /* Free at end if not null. */
        !           216:        nam = mhead = NULL;
        !           217:        from = NULL;
        !           218:
        !           219:        /*
        !           220:         * Create socket and set its receive timeout.
        !           221:         */
        !           222:        if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0)))
        !           223:                goto out;
        !           224:
        !           225:        m = m_get(M_WAIT, MT_SOOPTS);
        !           226:        tv = mtod(m, struct timeval *);
        !           227:        m->m_len = sizeof(*tv);
        !           228:        tv->tv_sec = 1;
        !           229:        tv->tv_usec = 0;
        !           230:        if ((error = sosetopt(so, SOL_SOCKET, SO_RCVTIMEO, m)))
        !           231:                goto out;
        !           232:
        !           233:        /*
        !           234:         * Enable broadcast if necessary.
        !           235:         */
        !           236:        if (from_p) {
        !           237:                int32_t *on;
        !           238:                m = m_get(M_WAIT, MT_SOOPTS);
        !           239:                on = mtod(m, int32_t *);
        !           240:                m->m_len = sizeof(*on);
        !           241:                *on = 1;
        !           242:                if ((error = sosetopt(so, SOL_SOCKET, SO_BROADCAST, m)))
        !           243:                        goto out;
        !           244:        }
        !           245:
        !           246:        /*
        !           247:         * Bind the local endpoint to a reserved port,
        !           248:         * because some NFS servers refuse requests from
        !           249:         * non-reserved (non-privileged) ports.
        !           250:         */
        !           251:        m = m_getclr(M_WAIT, MT_SONAME);
        !           252:        sin = mtod(m, struct sockaddr_in *);
        !           253:        sin->sin_len = m->m_len = sizeof(*sin);
        !           254:        sin->sin_family = AF_INET;
        !           255:        sin->sin_addr.s_addr = INADDR_ANY;
        !           256:
        !           257:        MGET(mopt, M_WAIT, MT_SOOPTS);
        !           258:        mopt->m_len = sizeof(int);
        !           259:        ip = mtod(mopt, int *);
        !           260:        *ip = IP_PORTRANGE_LOW;
        !           261:        error = sosetopt(so, IPPROTO_IP, IP_PORTRANGE, mopt);
        !           262:        if (error)
        !           263:                goto out;
        !           264:
        !           265:        MGET(m, M_WAIT, MT_SONAME);
        !           266:        sin = mtod(m, struct sockaddr_in *);
        !           267:        sin->sin_len = m->m_len = sizeof (struct sockaddr_in);
        !           268:        sin->sin_family = AF_INET;
        !           269:        sin->sin_addr.s_addr = INADDR_ANY;
        !           270:        sin->sin_port = htons(0);
        !           271:        error = sobind(so, m);
        !           272:        m_freem(m);
        !           273:        if (error) {
        !           274:                printf("bind failed\n");
        !           275:                goto out;
        !           276:        }
        !           277:
        !           278:        MGET(mopt, M_WAIT, MT_SOOPTS);
        !           279:        mopt->m_len = sizeof(int);
        !           280:        ip = mtod(mopt, int *);
        !           281:        *ip = IP_PORTRANGE_DEFAULT;
        !           282:        error = sosetopt(so, IPPROTO_IP, IP_PORTRANGE, mopt);
        !           283:        if (error)
        !           284:                goto out;
        !           285:
        !           286:        /*
        !           287:         * Setup socket address for the server.
        !           288:         */
        !           289:        nam = m_get(M_WAIT, MT_SONAME);
        !           290:        sin = mtod(nam, struct sockaddr_in *);
        !           291:        bcopy((caddr_t)sa, (caddr_t)sin, (nam->m_len = sa->sin_len));
        !           292:
        !           293:        /*
        !           294:         * Prepend RPC message header.
        !           295:         */
        !           296:        mhead = m_gethdr(M_WAIT, MT_DATA);
        !           297:        mhead->m_next = *data;
        !           298:        call = mtod(mhead, struct rpc_call *);
        !           299:        mhead->m_len = sizeof(*call);
        !           300:        bzero((caddr_t)call, sizeof(*call));
        !           301:        /* rpc_call part */
        !           302:        while ((newxid = arc4random()) == xid);
        !           303:        xid = newxid;
        !           304:        call->rp_xid = txdr_unsigned(xid);
        !           305:        /* call->rp_direction = 0; */
        !           306:        call->rp_rpcvers = txdr_unsigned(2);
        !           307:        call->rp_prog = txdr_unsigned(prog);
        !           308:        call->rp_vers = txdr_unsigned(vers);
        !           309:        call->rp_proc = txdr_unsigned(func);
        !           310:        /* rpc_auth part (auth_unix as root) */
        !           311:        call->rpc_auth.authtype = txdr_unsigned(RPCAUTH_UNIX);
        !           312:        call->rpc_auth.authlen  = txdr_unsigned(sizeof(struct auth_unix));
        !           313:        /* rpc_verf part (auth_null) */
        !           314:        call->rpc_verf.authtype = 0;
        !           315:        call->rpc_verf.authlen  = 0;
        !           316:
        !           317:        /*
        !           318:         * Setup packet header
        !           319:         */
        !           320:        len = 0;
        !           321:        m = mhead;
        !           322:        while (m) {
        !           323:                len += m->m_len;
        !           324:                m = m->m_next;
        !           325:        }
        !           326:        mhead->m_pkthdr.len = len;
        !           327:        mhead->m_pkthdr.rcvif = NULL;
        !           328:
        !           329:        /*
        !           330:         * Send it, repeatedly, until a reply is received,
        !           331:         * but delay each re-send by an increasing amount.
        !           332:         * If the delay hits the maximum, start complaining.
        !           333:         */
        !           334:        for (timo = 0; retries; retries--) {
        !           335:                /* Send RPC request (or re-send). */
        !           336:                m = m_copym(mhead, 0, M_COPYALL, M_WAIT);
        !           337:                if (m == NULL) {
        !           338:                        error = ENOBUFS;
        !           339:                        goto out;
        !           340:                }
        !           341:                error = sosend(so, nam, NULL, m, NULL, 0);
        !           342:                if (error) {
        !           343:                        printf("krpc_call: sosend: %d\n", error);
        !           344:                        goto out;
        !           345:                }
        !           346:                m = NULL;
        !           347:
        !           348:                /* Determine new timeout. */
        !           349:                if (timo < MAX_RESEND_DELAY)
        !           350:                        timo++;
        !           351:                else
        !           352:                        printf("RPC timeout for server %s (0x%x) prog %u\n",
        !           353:                            inet_ntoa(sin->sin_addr),
        !           354:                            ntohl(sin->sin_addr.s_addr), prog);
        !           355:
        !           356:                /*
        !           357:                 * Wait for up to timo seconds for a reply.
        !           358:                 * The socket receive timeout was set to 1 second.
        !           359:                 */
        !           360:                secs = timo;
        !           361:                while (secs > 0) {
        !           362:                        if (from) {
        !           363:                                m_freem(from);
        !           364:                                from = NULL;
        !           365:                        }
        !           366:                        if (m) {
        !           367:                                m_freem(m);
        !           368:                                m = NULL;
        !           369:                        }
        !           370:                        auio.uio_resid = len = 1<<16;
        !           371:                        auio.uio_procp = NULL;
        !           372:                        rcvflg = 0;
        !           373:                        error = soreceive(so, &from, &auio, &m, NULL, &rcvflg);
        !           374:                        if (error == EWOULDBLOCK) {
        !           375:                                secs--;
        !           376:                                continue;
        !           377:                        }
        !           378:                        if (error)
        !           379:                                goto out;
        !           380:                        len -= auio.uio_resid;
        !           381:
        !           382:                        /* Does the reply contain at least a header? */
        !           383:                        if (len < MIN_REPLY_HDR)
        !           384:                                continue;
        !           385:                        if (m->m_len < MIN_REPLY_HDR)
        !           386:                                continue;
        !           387:                        reply = mtod(m, struct rpc_reply *);
        !           388:
        !           389:                        /* Is it the right reply? */
        !           390:                        if (reply->rp_direction != txdr_unsigned(RPC_REPLY))
        !           391:                                continue;
        !           392:
        !           393:                        if (reply->rp_xid != txdr_unsigned(xid))
        !           394:                                continue;
        !           395:
        !           396:                        /* Was RPC accepted? (authorization OK) */
        !           397:                        if (reply->rp_astatus != 0) {
        !           398:                                error = fxdr_unsigned(u_int32_t, reply->rp_errno);
        !           399:                                printf("rpc denied, error=%d\n", error);
        !           400:                                continue;
        !           401:                        }
        !           402:
        !           403:                        /* Did the call succeed? */
        !           404:                        if (reply->rp_status != 0) {
        !           405:                                error = fxdr_unsigned(u_int32_t, reply->rp_status);
        !           406:                                printf("rpc denied, status=%d\n", error);
        !           407:                                continue;
        !           408:                        }
        !           409:
        !           410:                        goto gotreply;  /* break two levels */
        !           411:
        !           412:                } /* while secs */
        !           413:        } /* forever send/receive */
        !           414:
        !           415:        error = ETIMEDOUT;
        !           416:        goto out;
        !           417:
        !           418:  gotreply:
        !           419:
        !           420:        /*
        !           421:         * Get RPC reply header into first mbuf,
        !           422:         * get its length, then strip it off.
        !           423:         */
        !           424:        len = sizeof(*reply);
        !           425:        if (m->m_len < len) {
        !           426:                m = m_pullup(m, len);
        !           427:                if (m == NULL) {
        !           428:                        error = ENOBUFS;
        !           429:                        goto out;
        !           430:                }
        !           431:        }
        !           432:        reply = mtod(m, struct rpc_reply *);
        !           433:        if (reply->rp_auth.authtype != 0) {
        !           434:                len += fxdr_unsigned(u_int32_t, reply->rp_auth.authlen);
        !           435:                len = (len + 3) & ~3; /* XXX? */
        !           436:        }
        !           437:        m_adj(m, len);
        !           438:
        !           439:        /* result */
        !           440:        *data = m;
        !           441:        if (from_p) {
        !           442:                *from_p = from;
        !           443:                from = NULL;
        !           444:        }
        !           445:
        !           446:  out:
        !           447:        if (nam) m_freem(nam);
        !           448:        if (mhead) m_freem(mhead);
        !           449:        if (from) m_freem(from);
        !           450:        soclose(so);
        !           451:        return error;
        !           452: }
        !           453:
        !           454: /*
        !           455:  * eXternal Data Representation routines.
        !           456:  * (but with non-standard args...)
        !           457:  */
        !           458:
        !           459: /*
        !           460:  * String representation for RPC.
        !           461:  */
        !           462: struct xdr_string {
        !           463:        u_int32_t len;          /* length without null or padding */
        !           464:        char data[4];   /* data (longer, of course) */
        !           465:     /* data is padded to a long-word boundary */
        !           466: };
        !           467:
        !           468: struct mbuf *
        !           469: xdr_string_encode(str, len)
        !           470:        char *str;
        !           471:        int len;
        !           472: {
        !           473:        struct mbuf *m;
        !           474:        struct xdr_string *xs;
        !           475:        int dlen;       /* padded string length */
        !           476:        int mlen;       /* message length */
        !           477:
        !           478:        dlen = (len + 3) & ~3;
        !           479:        mlen = dlen + 4;
        !           480:
        !           481:        if (mlen > MCLBYTES)            /* If too big, we just can't do it. */
        !           482:                return (NULL);
        !           483:
        !           484:        m = m_get(M_WAIT, MT_DATA);
        !           485:        if (mlen > MLEN) {
        !           486:                MCLGET(m, M_WAIT);
        !           487:                if ((m->m_flags & M_EXT) == 0) {
        !           488:                        (void) m_free(m);       /* There can be only one. */
        !           489:                        return (NULL);
        !           490:                }
        !           491:        }
        !           492:        xs = mtod(m, struct xdr_string *);
        !           493:        m->m_len = mlen;
        !           494:        xs->len = txdr_unsigned(len);
        !           495:        bcopy(str, xs->data, len);
        !           496:        return (m);
        !           497: }
        !           498:
        !           499: struct mbuf *
        !           500: xdr_string_decode(m, str, len_p)
        !           501:        struct mbuf *m;
        !           502:        char *str;
        !           503:        int *len_p;             /* bufsize - 1 */
        !           504: {
        !           505:        struct xdr_string *xs;
        !           506:        int mlen;       /* message length */
        !           507:        int slen;       /* string length */
        !           508:
        !           509:        if (m->m_len < 4) {
        !           510:                m = m_pullup(m, 4);
        !           511:                if (m == NULL)
        !           512:                        return (NULL);
        !           513:        }
        !           514:        xs = mtod(m, struct xdr_string *);
        !           515:        slen = fxdr_unsigned(u_int32_t, xs->len);
        !           516:        mlen = 4 + ((slen + 3) & ~3);
        !           517:
        !           518:        if (slen > *len_p)
        !           519:                slen = *len_p;
        !           520:        if (slen > m->m_pkthdr.len) {
        !           521:                m_freem(m);
        !           522:                return (NULL);
        !           523:        }
        !           524:        m_copydata(m, 4, slen, str);
        !           525:        m_adj(m, mlen);
        !           526:
        !           527:        str[slen] = '\0';
        !           528:        *len_p = slen;
        !           529:
        !           530:        return (m);
        !           531: }
        !           532:
        !           533:
        !           534: /*
        !           535:  * Inet address in RPC messages
        !           536:  * (Note, really four ints, NOT chars.  Blech.)
        !           537:  */
        !           538: struct xdr_inaddr {
        !           539:        u_int32_t atype;
        !           540:        u_int32_t addr[4];
        !           541: };
        !           542:
        !           543: struct mbuf *
        !           544: xdr_inaddr_encode(ia)
        !           545:        struct in_addr *ia;             /* already in network order */
        !           546: {
        !           547:        struct mbuf *m;
        !           548:        struct xdr_inaddr *xi;
        !           549:        u_int8_t *cp;
        !           550:        u_int32_t *ip;
        !           551:
        !           552:        m = m_get(M_WAIT, MT_DATA);
        !           553:        xi = mtod(m, struct xdr_inaddr *);
        !           554:        m->m_len = sizeof(*xi);
        !           555:        xi->atype = txdr_unsigned(1);
        !           556:        ip = xi->addr;
        !           557:        cp = (u_int8_t *)&ia->s_addr;
        !           558:        *ip++ = txdr_unsigned(*cp++);
        !           559:        *ip++ = txdr_unsigned(*cp++);
        !           560:        *ip++ = txdr_unsigned(*cp++);
        !           561:        *ip++ = txdr_unsigned(*cp++);
        !           562:
        !           563:        return (m);
        !           564: }
        !           565:
        !           566: struct mbuf *
        !           567: xdr_inaddr_decode(m, ia)
        !           568:        struct mbuf *m;
        !           569:        struct in_addr *ia;             /* already in network order */
        !           570: {
        !           571:        struct xdr_inaddr *xi;
        !           572:        u_int8_t *cp;
        !           573:        u_int32_t *ip;
        !           574:
        !           575:        if (m->m_len < sizeof(*xi)) {
        !           576:                m = m_pullup(m, sizeof(*xi));
        !           577:                if (m == NULL)
        !           578:                        return (NULL);
        !           579:        }
        !           580:        xi = mtod(m, struct xdr_inaddr *);
        !           581:        if (xi->atype != txdr_unsigned(1)) {
        !           582:                ia->s_addr = INADDR_ANY;
        !           583:                goto out;
        !           584:        }
        !           585:        ip = xi->addr;
        !           586:        cp = (u_int8_t *)&ia->s_addr;
        !           587:        *cp++ = fxdr_unsigned(u_int8_t, *ip++);
        !           588:        *cp++ = fxdr_unsigned(u_int8_t, *ip++);
        !           589:        *cp++ = fxdr_unsigned(u_int8_t, *ip++);
        !           590:        *cp++ = fxdr_unsigned(u_int8_t, *ip++);
        !           591:
        !           592: out:
        !           593:        m_adj(m, sizeof(*xi));
        !           594:        return (m);
        !           595: }

CVSweb