Annotation of kernel/bsd/nfs/nfs_boot.c, revision 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, 1997 NeXT Computer, Inc. All Rights Reserved */
        !            26: /*
        !            27:  * Copyright (c) 1994 Adam Glass, Gordon Ross
        !            28:  * All rights reserved.
        !            29:  *
        !            30:  * The NEXTSTEP Software License Agreement specifies the terms
        !            31:  * and conditions for redistribution.
        !            32:  *
        !            33:  *  History:
        !            34:  *
        !            35:  *  14-March-97        Dieter Siegmund ([email protected])
        !            36:  *     Use BOOTP instead of RARP to get the IP address at boot time
        !            37:  *
        !            38:  *  23-May-97  Umesh Vaishampayan  ([email protected])
        !            39:  *     Added the ability to mount "/private" separately.
        !            40:  *
        !            41:  *  30-May-97  Dieter Siegmund ([email protected])
        !            42:  *     - Clear out the ireq structure before using it to prevent
        !            43:  *       our sending using a bogus source IP address, we should use
        !            44:  *       an IP address of all zeroes
        !            45:  *     - Right after BOOTP, get the correct netmask using AUTONETMASK
        !            46:  *  18-Jul-97  Dieter Siegmund ([email protected])
        !            47:  *     - we can't restrict the netmask until we have a default route,
        !            48:  *       removed AUTONETMASK call (ifdef'd out)
        !            49:  *  5-Aug-97   Dieter Siegmund ([email protected])
        !            50:  *     - use the default route from the bpwhoami call, enabled autonetmask
        !            51:  *       again
        !            52:  */
        !            53: 
        !            54: #include <sys/param.h>
        !            55: #include <sys/systm.h>
        !            56: #include <sys/kernel.h>
        !            57: #include <sys/conf.h>
        !            58: #include <sys/ioctl.h>
        !            59: #include <sys/proc.h>
        !            60: #include <sys/mount.h>
        !            61: #include <sys/mbuf.h>
        !            62: #include <sys/socket.h>
        !            63: #include <sys/reboot.h>
        !            64: 
        !            65: #include <net/if.h>
        !            66: #include <net/route.h>
        !            67: 
        !            68: #include <netinet/in.h>
        !            69: #include <netinet/if_ether.h>
        !            70: 
        !            71: #include <nfs/rpcv2.h>
        !            72: #include <nfs/nfsproto.h>
        !            73: #include <nfs/nfs.h>
        !            74: #include <nfs/nfsdiskless.h>
        !            75: #include <nfs/krpc.h>
        !            76: 
        !            77: #include "ether.h"
        !            78: 
        !            79: #if NETHER == 0
        !            80: 
        !            81: int nfs_boot_init(nd, procp)
        !            82:        struct nfs_diskless *nd;
        !            83:        struct proc *procp;
        !            84: {
        !            85:        panic("nfs_boot_init: no ether");
        !            86: }
        !            87: 
        !            88: #else /* NETHER */
        !            89: 
        !            90: /*
        !            91:  * Support for NFS diskless booting, specifically getting information
        !            92:  * about where to boot from, what pathnames, etc.
        !            93:  *
        !            94:  * This implememtation uses RARP and the bootparam RPC.
        !            95:  * We are forced to implement RPC anyway (to get file handles)
        !            96:  * so we might as well take advantage of it for bootparam too.
        !            97:  *
        !            98:  * The diskless boot sequence goes as follows:
        !            99:  * (1) Use RARP to get our interface address
        !           100:  * (2) Use RPC/bootparam/whoami to get our hostname,
        !           101:  *     our IP address, and the server's IP address.
        !           102:  * (3) Use RPC/bootparam/getfile to get the root path
        !           103:  * (4) Use RPC/mountd to get the root file handle
        !           104:  * (5) Use RPC/bootparam/getfile to get the swap path
        !           105:  * (6) Use RPC/mountd to get the swap file handle
        !           106:  *
        !           107:  * (This happens to be the way Sun does it too.)
        !           108:  */
        !           109: 
        !           110: /* bootparam RPC */
        !           111: static int bp_whoami __P((struct sockaddr_in *bpsin,
        !           112:        struct in_addr *my_ip, struct in_addr *gw_ip));
        !           113: static int bp_getfile __P((struct sockaddr_in *bpsin, char *key,
        !           114:        struct sockaddr_in *mdsin, char *servname, char *path));
        !           115: 
        !           116: /* mountd RPC */
        !           117: static int md_mount __P((struct sockaddr_in *mdsin, char *path,
        !           118:        u_char *fh));
        !           119: 
        !           120: /* other helpers */
        !           121: static void get_path_and_handle __P((struct sockaddr_in *bpsin,
        !           122:        char *key, struct nfs_dlmount *ndmntp));
        !           123: 
        !           124: char   *nfsbootdevname;
        !           125: 
        !           126: /*
        !           127:  * Called with an empty nfs_diskless struct to be filled in.
        !           128:  */
        !           129: int
        !           130: nfs_boot_init(nd, procp)
        !           131:        struct nfs_diskless *nd;
        !           132:        struct proc *procp;
        !           133: {
        !           134:        struct ifreq ireq;
        !           135:        struct in_addr my_ip, gw_ip;
        !           136:        struct sockaddr_in bp_sin;
        !           137:        struct sockaddr_in *sin;
        !           138:        struct ifnet *ifp;
        !           139:        struct socket *so;
        !           140:        int error;
        !           141: 
        !           142:        /* clear out the request structure */
        !           143:        bzero(&ireq, sizeof(ireq));
        !           144: 
        !           145:        /*
        !           146:         * Find an interface, rarp for its ip address, stuff it, the
        !           147:         * implied broadcast addr, and netmask into a nfs_diskless struct.
        !           148:         *
        !           149:         * This was moved here from nfs_vfsops.c because this procedure
        !           150:         * would be quite different if someone decides to write (i.e.) a
        !           151:         * BOOTP version of this file (might not use RARP, etc.)
        !           152:         */
        !           153: 
        !           154:        /*
        !           155:         * Find a network interface.
        !           156:         */
        !           157:        if (nfsbootdevname)
        !           158:                ifp = ifunit(nfsbootdevname);
        !           159:        else
        !           160:                for (ifp = ifnet; ifp; ifp = ifp->if_next)
        !           161:                        if ((ifp->if_flags &
        !           162:                             (IFF_LOOPBACK|IFF_POINTOPOINT)) == 0)
        !           163:                                break;
        !           164:        if (ifp == NULL)
        !           165:                panic("nfs_boot: no suitable interface");
        !           166:        sprintf(ireq.ifr_name, "%s%d", ifp->if_name, ifp->if_unit);
        !           167:        printf("nfs_boot: using network interface '%s'\n", ireq.ifr_name);
        !           168: 
        !           169:        /*
        !           170:         * Bring up the interface.
        !           171:         */
        !           172:        if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0)) != 0)
        !           173:                panic("nfs_boot: socreate, error=%d", error);
        !           174:        ireq.ifr_flags = IFF_UP;
        !           175:        error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)&ireq, procp);
        !           176:        if (error)
        !           177:                panic("nfs_boot: SIFFLAGS, error=%d", error);
        !           178: 
        !           179: #if NeXT
        !           180:        /*
        !           181:         * Do BOOTP to get the interface address
        !           182:         */
        !           183:        {
        !           184:            int message = 0;
        !           185:            
        !           186:            ireq.ifr_addr.sa_family = AF_INET;
        !           187:            while ((error = ifioctl(so, SIOCAUTOADDR, (caddr_t)&ireq, procp))) {
        !           188:                if (error == ETIMEDOUT) {
        !           189:                    if (!message) {
        !           190:                        printf("nfs_boot: BOOTP timed out, still trying...\n");
        !           191:                        message++;
        !           192:                    }
        !           193:                } 
        !           194:                else {
        !           195:                    printf("nfs_boot: autoaddr failed, error = %d\n", error);
        !           196:                    panic("nfs_boot: SIOCAUTOADDR failed");
        !           197:                }
        !           198:            }
        !           199: 
        !           200:            sin = (struct sockaddr_in *)&(ireq.ifr_addr);
        !           201:            my_ip = sin->sin_addr;
        !           202:        }
        !           203:        printf("nfs_boot: client_addr=0x%x\n", ntohl(my_ip.s_addr));
        !           204: 
        !           205:        /*
        !           206:         * get the netmask
        !           207:         * XXX - if BOOTP returns a netmask, we should use that instead
        !           208:         *       of icmp (DWS)
        !           209:         */
        !           210:        if ((error = ifioctl(so, SIOCAUTONETMASK, (caddr_t)&ireq, procp))) {
        !           211:            printf("nfs_boot: autonetmask failed, error = %d\n", error);
        !           212:        }
        !           213: 
        !           214: #else NeXT
        !           215:        /*
        !           216:         * Do RARP for the interface address.
        !           217:         */
        !           218:        if ((error = revarpwhoami(&my_ip, ifp)) != 0)
        !           219:                panic("revarp failed, error=%d", error);
        !           220:        printf("nfs_boot: client_addr=0x%x\n", ntohl(my_ip.s_addr));
        !           221: 
        !           222:        /*
        !           223:         * Do enough of ifconfig(8) so that the chosen interface
        !           224:         * can talk to the servers.  (just set the address)
        !           225:         */
        !           226:        sin = (struct sockaddr_in *)&ireq.ifr_addr;
        !           227:        bzero((caddr_t)sin, sizeof(*sin));
        !           228:        sin->sin_len = sizeof(*sin);
        !           229:        sin->sin_family = AF_INET;
        !           230:        sin->sin_addr.s_addr = my_ip.s_addr;
        !           231:        error = ifioctl(so, SIOCSIFADDR, (caddr_t)&ireq, procp);
        !           232:        if (error)
        !           233:                panic("nfs_boot: set if addr, error=%d", error);
        !           234: #endif NeXT
        !           235: 
        !           236:        soclose(so);
        !           237: 
        !           238:        /*
        !           239:         * Get client name and gateway address.
        !           240:         * RPC: bootparam/whoami
        !           241:         * Use the old broadcast address for the WHOAMI
        !           242:         * call because we do not yet know our netmask.
        !           243:         * The server address returned by the WHOAMI call
        !           244:         * is used for all subsequent booptaram RPCs.
        !           245:         */
        !           246:        bzero((caddr_t)&bp_sin, sizeof(bp_sin));
        !           247:        bp_sin.sin_len = sizeof(bp_sin);
        !           248:        bp_sin.sin_family = AF_INET;
        !           249:        bp_sin.sin_addr.s_addr = INADDR_BROADCAST;
        !           250:        hostnamelen = MAXHOSTNAMELEN;
        !           251: 
        !           252:        /* this returns gateway IP address */
        !           253:        error = bp_whoami(&bp_sin, &my_ip, &gw_ip);
        !           254:        if (error) {
        !           255:            printf("nfs_boot: bootparam whoami, error=%d", error);
        !           256:            panic("nfs_boot: bootparam whoami\n");
        !           257:        }
        !           258:        printf("nfs_boot: server_addr=0x%x\n",
        !           259:                   ntohl(bp_sin.sin_addr.s_addr));
        !           260:        printf("nfs_boot: hostname=%s\n", hostname);
        !           261: #define NFS_BOOT_GATEWAY       1
        !           262: #ifdef NFS_BOOT_GATEWAY
        !           263:        /*
        !           264:         * XXX - This code is conditionally compiled only because
        !           265:         * many bootparam servers (in particular, SunOS 4.1.3)
        !           266:         * always set the gateway address to their own address.
        !           267:         * The bootparam server is not necessarily the gateway.
        !           268:         * We could just believe the server, and at worst you would
        !           269:         * need to delete the incorrect default route before adding
        !           270:         * the correct one, but for simplicity, ignore the gateway.
        !           271:         * If your server is OK, you can turn on this option.
        !           272:         *
        !           273:         * If the gateway address is set, add a default route.
        !           274:         * (The mountd RPCs may go across a gateway.)
        !           275:         */
        !           276:        if (gw_ip.s_addr) {
        !           277:                struct sockaddr dst, gw, mask;
        !           278:                /* Destination: (default) */
        !           279:                bzero((caddr_t)&dst, sizeof(dst));
        !           280:                dst.sa_len = sizeof(dst);
        !           281:                dst.sa_family = AF_INET;
        !           282:                /* Gateway: */
        !           283:                bzero((caddr_t)&gw, sizeof(gw));
        !           284:                sin = (struct sockaddr_in *)&gw;
        !           285:                sin->sin_len = sizeof(gw);
        !           286:                sin->sin_family = AF_INET;
        !           287:                sin->sin_addr.s_addr = gw_ip.s_addr;
        !           288:                /* Mask: (zero length) */
        !           289:                bzero(&mask, sizeof(mask));
        !           290: 
        !           291:                printf("nfs_boot: gateway=0x%x\n", ntohl(gw_ip.s_addr));
        !           292:                /* add, dest, gw, mask, flags, 0 */
        !           293:                error = rtrequest(RTM_ADD, &dst, (struct sockaddr *)&gw,
        !           294:                    &mask, (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL);
        !           295:                if (error)
        !           296:                        printf("nfs_boot: add route, error=%d\n", error);
        !           297:        }
        !           298: #endif
        !           299: 
        !           300:        get_path_and_handle(&bp_sin, "root", &nd->nd_root);
        !           301: #if !defined(NO_MOUNT_PRIVATE)
        !           302:        get_path_and_handle(&bp_sin, "private", &nd->nd_private);
        !           303: #endif /* NO_MOUNT_PRIVATE */
        !           304: 
        !           305:        return (0);
        !           306: }
        !           307: 
        !           308: static void
        !           309: get_path_and_handle(bpsin, key, ndmntp)
        !           310:        struct sockaddr_in *bpsin;      /* bootparam server */
        !           311:        char *key;                      /* root or swap */
        !           312:        struct nfs_dlmount *ndmntp;     /* output */
        !           313: {
        !           314:        char pathname[MAXPATHLEN];
        !           315:        char *sp, *dp, *endp;
        !           316:        int error;
        !           317: 
        !           318:        /*
        !           319:         * Get server:pathname for "key" (root or swap)
        !           320:         * using RPC to bootparam/getfile
        !           321:         */
        !           322:        error = bp_getfile(bpsin, key, &ndmntp->ndm_saddr,
        !           323:            ndmntp->ndm_host, pathname);
        !           324:        if (error) {
        !           325:                printf("nfs_boot: bootparam get %s: %d\n", key, error);
        !           326:                panic("nfs_boot: bootparam get %s: %d", key, error);
        !           327:        }
        !           328:        /*
        !           329:         * Get file handle for "key" (root or swap)
        !           330:         * using RPC to mountd/mount
        !           331:         */
        !           332:        error = md_mount(&ndmntp->ndm_saddr, pathname, ndmntp->ndm_fh);
        !           333:        if (error)
        !           334:                panic("nfs_boot: mountd %s, error=%d", key, error);
        !           335: 
        !           336:        /* Construct remote path (for getmntinfo(3)) */
        !           337:        dp = ndmntp->ndm_host;
        !           338:        endp = dp + MNAMELEN - 1;
        !           339:        dp += strlen(dp);
        !           340:        *dp++ = ':';
        !           341:        for (sp = pathname; *sp && dp < endp;)
        !           342:                *dp++ = *sp++;
        !           343:        *dp = '\0';
        !           344: 
        !           345: }
        !           346: 
        !           347: 
        !           348: /*
        !           349:  * Get an mbuf with the given length, and
        !           350:  * initialize the pkthdr length field.
        !           351:  */
        !           352: static struct mbuf *
        !           353: m_get_len(int msg_len)
        !           354: {
        !           355:        struct mbuf *m;
        !           356:        m = m_gethdr(M_WAIT, MT_DATA);
        !           357:        if (m == NULL)
        !           358:                return NULL;
        !           359:        if (msg_len > MHLEN) {
        !           360:                if (msg_len > MCLBYTES)
        !           361:                        panic("nfs_boot: msg_len > MCLBYTES");
        !           362:                MCLGET(m, M_WAIT);
        !           363:                if (m == NULL)
        !           364:                        return NULL;
        !           365:        }
        !           366:        m->m_len = msg_len;
        !           367:        m->m_pkthdr.len = m->m_len;
        !           368:        return (m);
        !           369: }
        !           370: 
        !           371: 
        !           372: /*
        !           373:  * String representation for RPC.
        !           374:  */
        !           375: struct rpc_string {
        !           376:        u_long len;             /* length without null or padding */
        !           377:        u_char data[4]; /* data (longer, of course) */
        !           378:     /* data is padded to a long-word boundary */
        !           379: };
        !           380: /* Compute space used given string length. */
        !           381: #define        RPC_STR_SIZE(slen) (4 + ((slen + 3) & ~3))
        !           382: 
        !           383: /*
        !           384:  * Inet address in RPC messages
        !           385:  * (Note, really four longs, NOT chars.  Blech.)
        !           386:  */
        !           387: struct bp_inaddr {
        !           388:        u_long  atype;
        !           389:        long    addr[4];
        !           390: };
        !           391: 
        !           392: 
        !           393: /*
        !           394:  * RPC: bootparam/whoami
        !           395:  * Given client IP address, get:
        !           396:  *     client name     (hostname)
        !           397:  *     domain name (domainname)
        !           398:  *     gateway address
        !           399:  *
        !           400:  * The hostname and domainname are set here for convenience.
        !           401:  *
        !           402:  * Note - bpsin is initialized to the broadcast address,
        !           403:  * and will be replaced with the bootparam server address
        !           404:  * after this call is complete.  Have to use PMAP_PROC_CALL
        !           405:  * to make sure we get responses only from a servers that
        !           406:  * know about us (don't want to broadcast a getport call).
        !           407:  */
        !           408: static int
        !           409: bp_whoami(bpsin, my_ip, gw_ip)
        !           410:        struct sockaddr_in *bpsin;
        !           411:        struct in_addr *my_ip;
        !           412:        struct in_addr *gw_ip;
        !           413: {
        !           414:        /* RPC structures for PMAPPROC_CALLIT */
        !           415:        struct whoami_call {
        !           416:                u_long call_prog;
        !           417:                u_long call_vers;
        !           418:                u_long call_proc;
        !           419:                u_long call_arglen;
        !           420:                struct bp_inaddr call_ia;
        !           421:        } *call;
        !           422: 
        !           423:        struct rpc_string *str;
        !           424:        struct bp_inaddr *bia;
        !           425:        struct mbuf *m, *from;
        !           426:        struct sockaddr_in *sin;
        !           427:        int error, msg_len;
        !           428:        int cn_len, dn_len;
        !           429:        u_char *p;
        !           430:        long *lp;
        !           431: 
        !           432:        /*
        !           433:         * Get message buffer of sufficient size.
        !           434:         */
        !           435:        msg_len = sizeof(*call);
        !           436:        m = m_get_len(msg_len);
        !           437:        if (m == NULL)
        !           438:                return ENOBUFS;
        !           439: 
        !           440:        /*
        !           441:         * Build request message for PMAPPROC_CALLIT.
        !           442:         */
        !           443:        call = mtod(m, struct whoami_call *);
        !           444:        call->call_prog = htonl(BOOTPARAM_PROG);
        !           445:        call->call_vers = htonl(BOOTPARAM_VERS);
        !           446:        call->call_proc = htonl(BOOTPARAM_WHOAMI);
        !           447:        call->call_arglen = htonl(sizeof(struct bp_inaddr));
        !           448: 
        !           449:        /* client IP address */
        !           450:        call->call_ia.atype = htonl(1);
        !           451:        p = (u_char*)my_ip;
        !           452:        lp = call->call_ia.addr;
        !           453:        *lp++ = htonl(*p);      p++;
        !           454:        *lp++ = htonl(*p);      p++;
        !           455:        *lp++ = htonl(*p);      p++;
        !           456:        *lp++ = htonl(*p);      p++;
        !           457: 
        !           458:        /* RPC: portmap/callit */
        !           459:        bpsin->sin_port = htons(PMAPPORT);
        !           460:        from = NULL;
        !           461:        error = krpc_call(bpsin, PMAPPROG, PMAPVERS,
        !           462:                        PMAPPROC_CALLIT, &m, &from);
        !           463:        if (error)
        !           464:                return error;
        !           465: 
        !           466:        /*
        !           467:         * Parse result message.
        !           468:         */
        !           469:        msg_len = m->m_len;
        !           470:        lp = mtod(m, long *);
        !           471: 
        !           472:        /* bootparam server port (also grab from address). */
        !           473:        if (msg_len < sizeof(*lp))
        !           474:                goto bad;
        !           475:        msg_len -= sizeof(*lp);
        !           476:        bpsin->sin_port = htons((short)ntohl(*lp++));
        !           477:        sin = mtod(from, struct sockaddr_in *);
        !           478:        bpsin->sin_addr.s_addr = sin->sin_addr.s_addr;
        !           479: 
        !           480:        /* length of encapsulated results */
        !           481:        if (msg_len < (ntohl(*lp) + sizeof(*lp)))
        !           482:                goto bad;
        !           483:        msg_len = ntohl(*lp++);
        !           484:        p = (char*)lp;
        !           485: 
        !           486:        /* client name */
        !           487:        if (msg_len < sizeof(*str))
        !           488:                goto bad;
        !           489:        str = (struct rpc_string *)p;
        !           490:        cn_len = ntohl(str->len);
        !           491:        if (msg_len < cn_len)
        !           492:                goto bad;
        !           493:        if (cn_len >= MAXHOSTNAMELEN)
        !           494:                goto bad;
        !           495:        bcopy(str->data, hostname, cn_len);
        !           496:        hostname[cn_len] = '\0';
        !           497:        hostnamelen = cn_len;
        !           498:        p += RPC_STR_SIZE(cn_len);
        !           499:        msg_len -= RPC_STR_SIZE(cn_len);
        !           500: 
        !           501:        /* domain name */
        !           502:        if (msg_len < sizeof(*str))
        !           503:                goto bad;
        !           504:        str = (struct rpc_string *)p;
        !           505:        dn_len = ntohl(str->len);
        !           506:        if (msg_len < dn_len)
        !           507:                goto bad;
        !           508:        if (dn_len >= MAXHOSTNAMELEN)
        !           509:                goto bad;
        !           510:        bcopy(str->data, domainname, dn_len);
        !           511:        domainname[dn_len] = '\0';
        !           512:        domainnamelen = dn_len;
        !           513:        p += RPC_STR_SIZE(dn_len);
        !           514:        msg_len -= RPC_STR_SIZE(dn_len);
        !           515: 
        !           516:        /* gateway address */
        !           517:        if (msg_len < sizeof(*bia))
        !           518:                goto bad;
        !           519:        bia = (struct bp_inaddr *)p;
        !           520:        if (bia->atype != htonl(1))
        !           521:                goto bad;
        !           522:        p = (u_char*)gw_ip;
        !           523:        *p++ = ntohl(bia->addr[0]);
        !           524:        *p++ = ntohl(bia->addr[1]);
        !           525:        *p++ = ntohl(bia->addr[2]);
        !           526:        *p++ = ntohl(bia->addr[3]);
        !           527:        goto out;
        !           528: 
        !           529: bad:
        !           530:        printf("nfs_boot: bootparam_whoami: bad reply\n");
        !           531:        error = EBADRPC;
        !           532: 
        !           533: out:
        !           534:        if (from)
        !           535:                m_freem(from);
        !           536:        m_freem(m);
        !           537:        return(error);
        !           538: }
        !           539: 
        !           540: 
        !           541: /*
        !           542:  * RPC: bootparam/getfile
        !           543:  * Given client name and file "key", get:
        !           544:  *     server name
        !           545:  *     server IP address
        !           546:  *     server pathname
        !           547:  */
        !           548: static int
        !           549: bp_getfile(bpsin, key, md_sin, serv_name, pathname)
        !           550:        struct sockaddr_in *bpsin;
        !           551:        char *key;
        !           552:        struct sockaddr_in *md_sin;
        !           553:        char *serv_name;
        !           554:        char *pathname;
        !           555: {
        !           556:        struct rpc_string *str;
        !           557:        struct mbuf *m;
        !           558:        struct bp_inaddr *bia;
        !           559:        struct sockaddr_in *sin;
        !           560:        u_char *p, *q;
        !           561:        int error, msg_len;
        !           562:        int cn_len, key_len, sn_len, path_len;
        !           563: 
        !           564:        /*
        !           565:         * Get message buffer of sufficient size.
        !           566:         */
        !           567:        cn_len = hostnamelen;
        !           568:        key_len = strlen(key);
        !           569:        msg_len = 0;
        !           570:        msg_len += RPC_STR_SIZE(cn_len);
        !           571:        msg_len += RPC_STR_SIZE(key_len);
        !           572:        m = m_get_len(msg_len);
        !           573:        if (m == NULL)
        !           574:                return ENOBUFS;
        !           575: 
        !           576:        /*
        !           577:         * Build request message.
        !           578:         */
        !           579:        p = mtod(m, u_char *);
        !           580:        bzero(p, msg_len);
        !           581:        /* client name (hostname) */
        !           582:        str = (struct rpc_string *)p;
        !           583:        str->len = htonl(cn_len);
        !           584:        bcopy(hostname, str->data, cn_len);
        !           585:        p += RPC_STR_SIZE(cn_len);
        !           586:        /* key name (root or swap) */
        !           587:        str = (struct rpc_string *)p;
        !           588:        str->len = htonl(key_len);
        !           589:        bcopy(key, str->data, key_len);
        !           590: 
        !           591:        /* RPC: bootparam/getfile */
        !           592:        error = krpc_call(bpsin, BOOTPARAM_PROG, BOOTPARAM_VERS,
        !           593:                        BOOTPARAM_GETFILE, &m, NULL);
        !           594:        if (error)
        !           595:                return error;
        !           596: 
        !           597:        /*
        !           598:         * Parse result message.
        !           599:         */
        !           600:        p = mtod(m, u_char *);
        !           601:        msg_len = m->m_len;
        !           602: 
        !           603:        /* server name */
        !           604:        if (msg_len < sizeof(*str))
        !           605:                goto bad;
        !           606:        str = (struct rpc_string *)p;
        !           607:        sn_len = ntohl(str->len);
        !           608:        if (msg_len < sn_len)
        !           609:                goto bad;
        !           610:        if (sn_len >= MNAMELEN)
        !           611:                goto bad;
        !           612:        bcopy(str->data, serv_name, sn_len);
        !           613:        serv_name[sn_len] = '\0';
        !           614:        p += RPC_STR_SIZE(sn_len);
        !           615:        msg_len -= RPC_STR_SIZE(sn_len);
        !           616: 
        !           617:        /* server IP address (mountd) */
        !           618:        if (msg_len < sizeof(*bia))
        !           619:                goto bad;
        !           620:        bia = (struct bp_inaddr *)p;
        !           621:        if (bia->atype != htonl(1))
        !           622:                goto bad;
        !           623:        sin = md_sin;
        !           624:        bzero((caddr_t)sin, sizeof(*sin));
        !           625:        sin->sin_len = sizeof(*sin);
        !           626:        sin->sin_family = AF_INET;
        !           627:        q = (u_char*) &sin->sin_addr;
        !           628:        *q++ = ntohl(bia->addr[0]);
        !           629:        *q++ = ntohl(bia->addr[1]);
        !           630:        *q++ = ntohl(bia->addr[2]);
        !           631:        *q++ = ntohl(bia->addr[3]);
        !           632:        p += sizeof(*bia);
        !           633:        msg_len -= sizeof(*bia);
        !           634: 
        !           635:        /* server pathname */
        !           636:        if (msg_len < sizeof(*str))
        !           637:                goto bad;
        !           638:        str = (struct rpc_string *)p;
        !           639:        path_len = ntohl(str->len);
        !           640:        if (msg_len < path_len)
        !           641:                goto bad;
        !           642:        if (path_len >= MAXPATHLEN)
        !           643:                goto bad;
        !           644:        bcopy(str->data, pathname, path_len);
        !           645:        pathname[path_len] = '\0';
        !           646:        goto out;
        !           647: 
        !           648: bad:
        !           649:        printf("nfs_boot: bootparam_getfile: bad reply\n");
        !           650:        error = EBADRPC;
        !           651: 
        !           652: out:
        !           653:        m_freem(m);
        !           654:        return(0);
        !           655: }
        !           656: 
        !           657: 
        !           658: /*
        !           659:  * RPC: mountd/mount
        !           660:  * Given a server pathname, get an NFS file handle.
        !           661:  * Also, sets sin->sin_port to the NFS service port.
        !           662:  */
        !           663: static int
        !           664: md_mount(mdsin, path, fhp)
        !           665:        struct sockaddr_in *mdsin;              /* mountd server address */
        !           666:        char *path;
        !           667:        u_char *fhp;
        !           668: {
        !           669:        /* The RPC structures */
        !           670:        struct rpc_string *str;
        !           671:        struct rdata {
        !           672:                u_long  errno;
        !           673:                u_char  fh[NFSX_V2FH];
        !           674:        } *rdata;
        !           675:        struct mbuf *m;
        !           676:        int error, mlen, slen;
        !           677: 
        !           678:        /* Get port number for MOUNTD. */
        !           679:        error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER1,
        !           680:                                                 &mdsin->sin_port);
        !           681:        if (error) return error;
        !           682: 
        !           683:        slen = strlen(path);
        !           684:        mlen = RPC_STR_SIZE(slen);
        !           685: 
        !           686:        m = m_get_len(mlen);
        !           687:        if (m == NULL)
        !           688:                return ENOBUFS;
        !           689:        str = mtod(m, struct rpc_string *);
        !           690:        str->len = htonl(slen);
        !           691:        bcopy(path, str->data, slen);
        !           692: 
        !           693:        /* Do RPC to mountd. */
        !           694:        error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER1,
        !           695:                        RPCMNT_MOUNT, &m, NULL);
        !           696:        if (error)
        !           697:                return error;   /* message already freed */
        !           698: 
        !           699:        mlen = m->m_len;
        !           700:        if (mlen < sizeof(*rdata))
        !           701:                goto bad;
        !           702:        rdata = mtod(m, struct rdata *);
        !           703:        error = ntohl(rdata->errno);
        !           704:        if (error)
        !           705:                goto bad;
        !           706:        bcopy(rdata->fh, fhp, NFSX_V2FH);
        !           707: 
        !           708:        /* Set port number for NFS use. */
        !           709:        error = krpc_portmap(mdsin, NFS_PROG, NFS_VER2,
        !           710:                                                 &mdsin->sin_port);
        !           711:        goto out;
        !           712: 
        !           713: bad:
        !           714:        error = EBADRPC;
        !           715: 
        !           716: out:
        !           717:        m_freem(m);
        !           718:        return error;
        !           719: }
        !           720: 
        !           721: #endif /* NETHER */

unix.superglobalmegacorp.com

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