Annotation of kernel/bsd/nfs/krpc_subr.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
                     26: /*
                     27:  * Copyright (c) 1994 Gordon Ross, Adam Glass 
                     28:  * Copyright (c) 1992 Regents of the University of California.
                     29:  * All rights reserved.
                     30:  *
                     31:  * The NEXTSTEP Software License Agreement specifies the terms
                     32:  * and conditions for redistribution.
                     33:  *
                     34:  * This software was developed by the Computer Systems Engineering group
                     35:  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
                     36:  * contributed to Berkeley.
                     37:  *
                     38:  * Redistribution and use in source and binary forms, with or without
                     39:  * modification, are permitted provided that the following conditions
                     40:  * are met:
                     41:  * 1. Redistributions of source code must retain the above copyright
                     42:  *    notice, this list of conditions and the following disclaimer.
                     43:  * 2. Redistributions in binary form must reproduce the above copyright
                     44:  *    notice, this list of conditions and the following disclaimer in the
                     45:  *    documentation and/or other materials provided with the distribution.
                     46:  * 3. All advertising materials mentioning features or use of this software
                     47:  *    must display the following acknowledgement:
                     48:  *     This product includes software developed by the University of
                     49:  *     California, Lawrence Berkeley Laboratory and its contributors.
                     50:  * 4. Neither the name of the University nor the names of its contributors
                     51:  *    may be used to endorse or promote products derived from this software
                     52:  *    without specific prior written permission.
                     53:  *
                     54:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     55:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     56:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     57:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     58:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     59:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     60:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     61:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     62:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     63:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     64:  * SUCH DAMAGE.
                     65:  *
                     66:  */
                     67: 
                     68: #include <sys/param.h>
                     69: #include <sys/conf.h>
                     70: #include <sys/ioctl.h>
                     71: #include <sys/proc.h>
                     72: #include <sys/mount.h>
                     73: #include <sys/mbuf.h>
                     74: #include <sys/socket.h>
                     75: #include <sys/systm.h>
                     76: #include <sys/reboot.h>
                     77: 
                     78: #include <net/if.h>
                     79: #include <netinet/in.h>
                     80: 
                     81: #include <nfs/rpcv2.h>
                     82: #include <nfs/krpc.h>
                     83: 
                     84: /*
                     85:  * Kernel support for Sun RPC
                     86:  *
                     87:  * Used currently for bootstrapping in nfs diskless configurations.
                     88:  * 
                     89:  * Note: will not work on variable-sized rpc args/results.
                     90:  *       implicit size-limit of an mbuf.
                     91:  */
                     92: 
                     93: /*
                     94:  * Generic RPC headers
                     95:  */
                     96: 
                     97: struct auth_info {
                     98:        u_int32_t       rp_atype;       /* auth type */
                     99:        u_int32_t       rp_alen;        /* auth length */
                    100: };
                    101: 
                    102: struct rpc_call {
                    103:        u_int32_t       rp_xid;         /* request transaction id */
                    104:        int32_t         rp_direction;   /* call direction (0) */
                    105:        u_int32_t       rp_rpcvers;     /* rpc version (2) */
                    106:        u_int32_t       rp_prog;        /* program */
                    107:        u_int32_t       rp_vers;        /* version */
                    108:        u_int32_t       rp_proc;        /* procedure */
                    109:        struct  auth_info rp_auth;
                    110:        struct  auth_info rp_verf;
                    111: };
                    112: 
                    113: struct rpc_reply {
                    114:        u_int32_t rp_xid;               /* request transaction id */
                    115:        int32_t  rp_direction;          /* call direction (1) */
                    116:        int32_t  rp_astatus;            /* accept status (0: accepted) */
                    117:        union {
                    118:                u_int32_t rpu_errno;
                    119:                struct {
                    120:                        struct auth_info rp_auth;
                    121:                        u_int32_t       rp_rstatus;
                    122:                } rpu_ok;
                    123:        } rp_u;
                    124: };
                    125: 
                    126: #define MIN_REPLY_HDR 16       /* xid, dir, astat, errno */
                    127: 
                    128: /*
                    129:  * What is the longest we will wait before re-sending a request?
                    130:  * Note this is also the frequency of "RPC timeout" messages.
                    131:  * The re-send loop count sup linearly to this maximum, so the
                    132:  * first complaint will happen after (1+2+3+4+5)=15 seconds.
                    133:  */
                    134: #define        MAX_RESEND_DELAY 5      /* seconds */
                    135: 
                    136: /*
                    137:  * Call portmap to lookup a port number for a particular rpc program
                    138:  * Returns non-zero error on failure.
                    139:  */
                    140: int
                    141: krpc_portmap(sin,  prog, vers, portp)
                    142:        struct sockaddr_in *sin;                /* server address */
                    143:        u_int prog, vers;       /* host order */
                    144:        u_int16_t *portp;       /* network order */
                    145: {
                    146:        struct sdata {
                    147:                u_int32_t prog;         /* call program */
                    148:                u_int32_t vers;         /* call version */
                    149:                u_int32_t proto;        /* call protocol */
                    150:                u_int32_t port;         /* call port (unused) */
                    151:        } *sdata;
                    152:        struct rdata {
                    153:                u_int16_t pad;
                    154:                u_int16_t port;
                    155:        } *rdata;
                    156:        struct mbuf *m;
                    157:        int error;
                    158: 
                    159:        /* The portmapper port is fixed. */
                    160:        if (prog == PMAPPROG) {
                    161:                *portp = htons(PMAPPORT);
                    162:                return 0;
                    163:        }
                    164: 
                    165:        m = m_gethdr(M_WAIT, MT_DATA);
                    166:        if (m == NULL)
                    167:                return ENOBUFS;
                    168:        m->m_len = sizeof(*sdata);
                    169:        m->m_pkthdr.len = m->m_len;
                    170:        sdata = mtod(m, struct sdata *);
                    171: 
                    172:        /* Do the RPC to get it. */
                    173:        sdata->prog = htonl(prog);
                    174:        sdata->vers = htonl(vers);
                    175:        sdata->proto = htonl(IPPROTO_UDP);
                    176:        sdata->port = 0;
                    177: 
                    178:        sin->sin_port = htons(PMAPPORT);
                    179:        error = krpc_call(sin, PMAPPROG, PMAPVERS,
                    180:                                          PMAPPROC_GETPORT, &m, NULL);
                    181:        if (error) 
                    182:                return error;
                    183: 
                    184:        rdata = mtod(m, struct rdata *);
                    185:        *portp = rdata->port;
                    186: 
                    187:        m_freem(m);
                    188:        return 0;
                    189: }
                    190: 
                    191: /*
                    192:  * Do a remote procedure call (RPC) and wait for its reply.
                    193:  * If from_p is non-null, then we are doing broadcast, and
                    194:  * the address from whence the response came is saved there.
                    195:  */
                    196: int
                    197: krpc_call(sa, prog, vers, func, data, from_p)
                    198:        struct sockaddr_in *sa;
                    199:        u_int prog, vers, func;
                    200:        struct mbuf **data;     /* input/output */
                    201:        struct mbuf **from_p;   /* output */
                    202: {
                    203:        struct socket *so;
                    204:        struct sockaddr_in *sin;
                    205:        struct mbuf *m, *nam, *mhead, *from;
                    206:        struct rpc_call *call;
                    207:        struct rpc_reply *reply;
                    208:        struct uio auio;
                    209:        int error, rcvflg, timo, secs, len;
                    210:        static u_int32_t xid = ~0xFF;
                    211:        u_int16_t tport;
                    212: 
                    213:        /*
                    214:         * Validate address family.
                    215:         * Sorry, this is INET specific...
                    216:         */
                    217:        if (sa->sin_family != AF_INET)
                    218:                return (EAFNOSUPPORT);
                    219: 
                    220:        /* Free at end if not null. */
                    221:        nam = mhead = NULL;
                    222:        from = NULL;
                    223: 
                    224:        /*
                    225:         * Create socket and set its recieve timeout.
                    226:         */
                    227:        if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0)))
                    228:                goto out;
                    229: 
                    230:        m = m_get(M_WAIT, MT_SOOPTS);
                    231:        if (m == NULL) {
                    232:                error = ENOBUFS;
                    233:                goto out;
                    234:        } else {
                    235:                struct timeval *tv;
                    236:                tv = mtod(m, struct timeval *);
                    237:                m->m_len = sizeof(*tv);
                    238:                tv->tv_sec = 1;
                    239:                tv->tv_usec = 0;
                    240:                if ((error = sosetopt(so, SOL_SOCKET, SO_RCVTIMEO, m)))
                    241:                        goto out;
                    242:        }
                    243: 
                    244:        /*
                    245:         * Enable broadcast if necessary.
                    246:         */
                    247:        if (from_p) {
                    248:                int32_t *on;
                    249:                m = m_get(M_WAIT, MT_SOOPTS);
                    250:                if (m == NULL) {
                    251:                        error = ENOBUFS;
                    252:                        goto out;
                    253:                }
                    254:                on = mtod(m, int32_t *);
                    255:                m->m_len = sizeof(*on);
                    256:                *on = 1;
                    257:                if ((error = sosetopt(so, SOL_SOCKET, SO_BROADCAST, m)))
                    258:                        goto out;
                    259:        }
                    260: 
                    261:        /*
                    262:         * Bind the local endpoint to a reserved port,
                    263:         * because some NFS servers refuse requests from
                    264:         * non-reserved (non-privileged) ports.
                    265:         */
                    266:        m = m_getclr(M_WAIT, MT_SONAME);
                    267:        sin = mtod(m, struct sockaddr_in *);
                    268:        sin->sin_len = m->m_len = sizeof(*sin);
                    269:        sin->sin_family = AF_INET;
                    270:        sin->sin_addr.s_addr = INADDR_ANY;
                    271:        tport = IPPORT_RESERVED;
                    272:        do {
                    273:                tport--;
                    274:                sin->sin_port = htons(tport);
                    275:                error = sobind(so, m);
                    276:        } while (error == EADDRINUSE &&
                    277:                         tport > IPPORT_RESERVED / 2);
                    278:        m_freem(m);
                    279:        if (error) {
                    280:                printf("bind failed\n");
                    281:                goto out;
                    282:        }
                    283: 
                    284:        /*
                    285:         * Setup socket address for the server.
                    286:         */
                    287:        nam = m_get(M_WAIT, MT_SONAME);
                    288:        if (nam == NULL) {
                    289:                error = ENOBUFS;
                    290:                goto out;
                    291:        }
                    292:        sin = mtod(nam, struct sockaddr_in *);
                    293:        bcopy((caddr_t)sa, (caddr_t)sin, (nam->m_len = sa->sin_len));
                    294: 
                    295:        /*
                    296:         * Prepend RPC message header.
                    297:         */
                    298:        m = *data;
                    299:        *data = NULL;
                    300: #if    DIAGNOSTIC
                    301:        if ((m->m_flags & M_PKTHDR) == 0)
                    302:                panic("krpc_call: send data w/o pkthdr");
                    303:        if (m->m_pkthdr.len < m->m_len)
                    304:                panic("krpc_call: pkthdr.len not set");
                    305: #endif
                    306:        mhead = m_prepend(m, sizeof(*call), M_WAIT);
                    307:        if (mhead == NULL) {
                    308:                error = ENOBUFS;
                    309:                goto out;
                    310:        }
                    311:        mhead->m_pkthdr.len += sizeof(*call);
                    312:        mhead->m_pkthdr.rcvif = NULL;
                    313: 
                    314:        /*
                    315:         * Fill in the RPC header
                    316:         */
                    317:        call = mtod(mhead, struct rpc_call *);
                    318:        bzero((caddr_t)call, sizeof(*call));
                    319:        xid++;
                    320:        call->rp_xid = htonl(xid);
                    321:        /* call->rp_direction = 0; */
                    322:        call->rp_rpcvers = htonl(2);
                    323:        call->rp_prog = htonl(prog);
                    324:        call->rp_vers = htonl(vers);
                    325:        call->rp_proc = htonl(func);
                    326:        /* call->rp_auth = 0; */
                    327:        /* call->rp_verf = 0; */
                    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:        timo = 0;
                    335:        for (;;) {
                    336:                /* Send RPC request (or re-send). */
                    337:                m = m_copym(mhead, 0, M_COPYALL, M_WAIT);
                    338:                if (m == NULL) {
                    339:                        error = ENOBUFS;
                    340:                        goto out;
                    341:                }
                    342:                error = sosend(so, nam, NULL, m, NULL, 0);
                    343:                if (error) {
                    344:                        printf("krpc_call: sosend: %d\n", error);
                    345:                        goto out;
                    346:                }
                    347:                m = NULL;
                    348: 
                    349:                /* Determine new timeout. */
                    350:                if (timo < MAX_RESEND_DELAY)
                    351:                        timo++;
                    352:                else
                    353:                        printf("RPC timeout for server 0x%x\n",
                    354:                               ntohl(sin->sin_addr.s_addr));
                    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:                        rcvflg = 0;
                    372:                        error = soreceive(so, &from, &auio, &m, NULL, &rcvflg);
                    373:                        if (error == EWOULDBLOCK) {
                    374:                                secs--;
                    375:                                continue;
                    376:                        }
                    377:                        if (error)
                    378:                                goto out;
                    379:                        len -= auio.uio_resid;
                    380: 
                    381:                        /* Does the reply contain at least a header? */
                    382:                        if (len < MIN_REPLY_HDR)
                    383:                                continue;
                    384:                        if (m->m_len < MIN_REPLY_HDR)
                    385:                                continue;
                    386:                        reply = mtod(m, struct rpc_reply *);
                    387: 
                    388:                        /* Is it the right reply? */
                    389:                        if (reply->rp_direction != htonl(RPC_REPLY))
                    390:                                continue;
                    391: 
                    392:                        if (reply->rp_xid != htonl(xid))
                    393:                                continue;
                    394: 
                    395:                        /* Was RPC accepted? (authorization OK) */
                    396:                        if (reply->rp_astatus != 0) {
                    397:                                error = ntohl(reply->rp_u.rpu_errno);
                    398:                                printf("rpc denied, error=%d\n", error);
                    399:                                continue;
                    400:                        }
                    401: 
                    402:                        /* Did the call succeed? */
                    403:                        if ((error = ntohl(reply->rp_u.rpu_ok.rp_rstatus)) != 0) {
                    404:                                printf("rpc status=%d\n", error);
                    405:                                continue;
                    406:                        }
                    407: 
                    408:                        goto gotreply;  /* break two levels */
                    409: 
                    410:                } /* while secs */
                    411:        } /* forever send/receive */
                    412: 
                    413:        error = ETIMEDOUT;
                    414:        goto out;
                    415: 
                    416:  gotreply:
                    417: 
                    418:        /*
                    419:         * Pull as much as we can into first mbuf, to make
                    420:         * result buffer contiguous.  Note that if the entire
                    421:         * result won't fit into one mbuf, you're out of luck.
                    422:         * XXX - Should not rely on making the entire reply
                    423:         * contiguous (fix callers instead). -gwr
                    424:         */
                    425: #if    DIAGNOSTIC
                    426:        if ((m->m_flags & M_PKTHDR) == 0)
                    427:                panic("krpc_call: received pkt w/o header?");
                    428: #endif
                    429:        len = m->m_pkthdr.len;
                    430:        if (m->m_len < len) {
                    431:                m = m_pullup(m, len);
                    432:                if (m == NULL) {
                    433:                        error = ENOBUFS;
                    434:                        goto out;
                    435:                }
                    436:                reply = mtod(m, struct rpc_reply *);
                    437:        }
                    438: 
                    439:        /*
                    440:         * Strip RPC header
                    441:         */
                    442:        len = sizeof(*reply);
                    443:        if (reply->rp_u.rpu_ok.rp_auth.rp_atype != 0) {
                    444:                len += ntohl(reply->rp_u.rpu_ok.rp_auth.rp_alen);
                    445:                len = (len + 3) & ~3; /* XXX? */
                    446:        }
                    447:        m_adj(m, len);
                    448: 
                    449:        /* result */
                    450:        *data = m;
                    451:        if (from_p) {
                    452:                *from_p = from;
                    453:                from = NULL;
                    454:        }
                    455: 
                    456:  out:
                    457:        if (nam) m_freem(nam);
                    458:        if (mhead) m_freem(mhead);
                    459:        if (from) m_freem(from);
                    460:        soclose(so);
                    461:        return error;
                    462: }

unix.superglobalmegacorp.com

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