[BACK]Return to bootparam.c CVS log [TXT][DIR] Up to [local] / sys / lib / libsa

Annotation of sys/lib/libsa/bootparam.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: bootparam.c,v 1.11 2003/08/11 06:23:09 deraadt Exp $  */
        !             2: /*     $NetBSD: bootparam.c,v 1.10 1996/10/14 21:16:55 thorpej Exp $   */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1995 Gordon W. Ross
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  * 1. Redistributions of source code must retain the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer.
        !            13:  * 2. Redistributions in binary form must reproduce the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer in the
        !            15:  *    documentation and/or other materials provided with the distribution.
        !            16:  * 3. The name of the author may not be used to endorse or promote products
        !            17:  *    derived from this software without specific prior written permission.
        !            18:  * 4. All advertising materials mentioning features or use of this software
        !            19:  *    must display the following acknowledgement:
        !            20:  *      This product includes software developed by Gordon W. Ross
        !            21:  *
        !            22:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            23:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            24:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            25:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            26:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            27:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            28:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            29:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            30:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            31:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            32:  */
        !            33:
        !            34: /*
        !            35:  * RPC/bootparams
        !            36:  */
        !            37:
        !            38: #include <sys/param.h>
        !            39: #include <sys/socket.h>
        !            40:
        !            41: #include <net/if.h>
        !            42:
        !            43: #include <netinet/in.h>
        !            44: #include <netinet/in_systm.h>
        !            45:
        !            46: #include <nfs/rpcv2.h>
        !            47:
        !            48: #include "stand.h"
        !            49: #include "net.h"
        !            50: #include "netif.h"
        !            51: #include "rpc.h"
        !            52: #include "bootparam.h"
        !            53:
        !            54: #ifdef DEBUG_RPC
        !            55: #define RPC_PRINTF(a)  printf a
        !            56: #else
        !            57: #define RPC_PRINTF(a)  /* printf a */
        !            58: #endif
        !            59:
        !            60: struct in_addr bp_server_addr; /* net order */
        !            61: n_short                bp_server_port; /* net order */
        !            62:
        !            63: /*
        !            64:  * RPC definitions for bootparamd
        !            65:  */
        !            66: #define        BOOTPARAM_PROG          100026
        !            67: #define        BOOTPARAM_VERS          1
        !            68: #define BOOTPARAM_WHOAMI       1
        !            69: #define BOOTPARAM_GETFILE      2
        !            70:
        !            71: /*
        !            72:  * Inet address in RPC messages
        !            73:  * (Note, really four ints, NOT chars.  Blech.)
        !            74:  */
        !            75: struct xdr_inaddr {
        !            76:        u_int32_t  atype;
        !            77:        int32_t addr[4];
        !            78: };
        !            79:
        !            80: int xdr_inaddr_encode(char **p, struct in_addr ia);
        !            81: int xdr_inaddr_decode(char **p, struct in_addr *ia);
        !            82:
        !            83: int xdr_string_encode(char **p, char *str, int len);
        !            84: int xdr_string_decode(char **p, char *str, int *len_p);
        !            85:
        !            86:
        !            87: /*
        !            88:  * RPC: bootparam/whoami
        !            89:  * Given client IP address, get:
        !            90:  *     client name     (hostname)
        !            91:  *     domain name (domainname)
        !            92:  *     gateway address
        !            93:  *
        !            94:  * The hostname and domainname are set here for convenience.
        !            95:  *
        !            96:  * Note - bpsin is initialized to the broadcast address,
        !            97:  * and will be replaced with the bootparam server address
        !            98:  * after this call is complete.  Have to use PMAP_PROC_CALL
        !            99:  * to make sure we get responses only from a servers that
        !           100:  * know about us (don't want to broadcast a getport call).
        !           101:  */
        !           102: int
        !           103: bp_whoami(int sockfd)
        !           104: {
        !           105:        /* RPC structures for PMAPPROC_CALLIT */
        !           106:        struct args {
        !           107:                u_int32_t prog;
        !           108:                u_int32_t vers;
        !           109:                u_int32_t proc;
        !           110:                u_int32_t arglen;
        !           111:                struct xdr_inaddr xina;
        !           112:        } *args;
        !           113:        struct repl {
        !           114:                u_int16_t _pad;
        !           115:                u_int16_t port;
        !           116:                u_int32_t encap_len;
        !           117:                /* encapsulated data here */
        !           118:                n_long  capsule[64];
        !           119:        } *repl;
        !           120:        struct {
        !           121:                n_long  h[RPC_HEADER_WORDS];
        !           122:                struct args d;
        !           123:        } sdata;
        !           124:        struct {
        !           125:                n_long  h[RPC_HEADER_WORDS];
        !           126:                struct repl d;
        !           127:        } rdata;
        !           128:        char *send_tail, *recv_head;
        !           129:        struct iodesc *d;
        !           130:        int len, x;
        !           131:
        !           132:        RPC_PRINTF(("bp_whoami: myip=%s\n", inet_ntoa(myip)));
        !           133:
        !           134:        if (!(d = socktodesc(sockfd))) {
        !           135:                RPC_PRINTF(("bp_whoami: bad socket. %d\n", sockfd));
        !           136:                return (-1);
        !           137:        }
        !           138:        args = &sdata.d;
        !           139:        repl = &rdata.d;
        !           140:
        !           141:        /*
        !           142:         * Build request args for PMAPPROC_CALLIT.
        !           143:         */
        !           144:        args->prog = htonl(BOOTPARAM_PROG);
        !           145:        args->vers = htonl(BOOTPARAM_VERS);
        !           146:        args->proc = htonl(BOOTPARAM_WHOAMI);
        !           147:        args->arglen = htonl(sizeof(struct xdr_inaddr));
        !           148:        send_tail = (char *)&args->xina;
        !           149:
        !           150:        /*
        !           151:         * append encapsulated data (client IP address)
        !           152:         */
        !           153:        if (xdr_inaddr_encode(&send_tail, myip))
        !           154:                return (-1);
        !           155:
        !           156:        /* RPC: portmap/callit */
        !           157:        d->myport = htons(--rpc_port);
        !           158:        d->destip.s_addr = INADDR_BROADCAST;    /* XXX: subnet bcast? */
        !           159:        /* rpc_call will set d->destport */
        !           160:
        !           161:        len = rpc_call(d, PMAPPROG, PMAPVERS, PMAPPROC_CALLIT,
        !           162:            args, send_tail - (char *)args,
        !           163:            repl, sizeof(*repl));
        !           164:        if (len < 8) {
        !           165:                printf("bootparamd: 'whoami' call failed\n");
        !           166:                return (-1);
        !           167:        }
        !           168:
        !           169:        /* Save bootparam server address (from IP header). */
        !           170:        rpc_fromaddr(repl, &bp_server_addr, &bp_server_port);
        !           171:
        !           172:        /*
        !           173:         * Note that bp_server_port is now 111 due to the
        !           174:         * indirect call (using PMAPPROC_CALLIT), so get the
        !           175:         * actual port number from the reply data.
        !           176:         */
        !           177:        bp_server_port = repl->port;
        !           178:
        !           179:        RPC_PRINTF(("bp_whoami: server at %s:%d\n",
        !           180:            inet_ntoa(bp_server_addr), ntohs(bp_server_port)));
        !           181:
        !           182:        /* We have just done a portmap call, so cache the portnum. */
        !           183:        rpc_pmap_putcache(bp_server_addr, BOOTPARAM_PROG, BOOTPARAM_VERS,
        !           184:            (int)ntohs(bp_server_port));
        !           185:
        !           186:        /*
        !           187:         * Parse the encapsulated results from bootparam/whoami
        !           188:         */
        !           189:        x = ntohl(repl->encap_len);
        !           190:        if (len < x) {
        !           191:                printf("bp_whoami: short reply, %d < %d\n", len, x);
        !           192:                return (-1);
        !           193:        }
        !           194:        recv_head = (char *)repl->capsule;
        !           195:
        !           196:        /* client name */
        !           197:        hostnamelen = MAXHOSTNAMELEN-1;
        !           198:        if (xdr_string_decode(&recv_head, hostname, &hostnamelen)) {
        !           199:                RPC_PRINTF(("bp_whoami: bad hostname\n"));
        !           200:                return (-1);
        !           201:        }
        !           202:
        !           203:        /* domain name */
        !           204:        domainnamelen = MAXHOSTNAMELEN-1;
        !           205:        if (xdr_string_decode(&recv_head, domainname, &domainnamelen)) {
        !           206:                RPC_PRINTF(("bp_whoami: bad domainname\n"));
        !           207:                return (-1);
        !           208:        }
        !           209:
        !           210:        /* gateway address */
        !           211:        if (xdr_inaddr_decode(&recv_head, &gateip)) {
        !           212:                RPC_PRINTF(("bp_whoami: bad gateway\n"));
        !           213:                return (-1);
        !           214:        }
        !           215:
        !           216:        /* success */
        !           217:        return(0);
        !           218: }
        !           219:
        !           220:
        !           221: /*
        !           222:  * RPC: bootparam/getfile
        !           223:  * Given client name and file "key", get:
        !           224:  *     server name
        !           225:  *     server IP address
        !           226:  *     server pathname
        !           227:  */
        !           228: int
        !           229: bp_getfile(int sockfd, char *key, struct in_addr *serv_addr, char *pathname)
        !           230: {
        !           231:        struct {
        !           232:                n_long  h[RPC_HEADER_WORDS];
        !           233:                n_long  d[64];
        !           234:        } sdata;
        !           235:        struct {
        !           236:                n_long  h[RPC_HEADER_WORDS];
        !           237:                n_long  d[128];
        !           238:        } rdata;
        !           239:        char serv_name[FNAME_SIZE];
        !           240:        char *send_tail, *recv_head;
        !           241:        /* misc... */
        !           242:        struct iodesc *d;
        !           243:        int sn_len, path_len, rlen;
        !           244:
        !           245:        if (!(d = socktodesc(sockfd))) {
        !           246:                RPC_PRINTF(("bp_getfile: bad socket. %d\n", sockfd));
        !           247:                return (-1);
        !           248:        }
        !           249:
        !           250:        send_tail = (char *)sdata.d;
        !           251:        recv_head = (char *)rdata.d;
        !           252:
        !           253:        /*
        !           254:         * Build request message.
        !           255:         */
        !           256:
        !           257:        /* client name (hostname) */
        !           258:        if (xdr_string_encode(&send_tail, hostname, hostnamelen)) {
        !           259:                RPC_PRINTF(("bp_getfile: bad client\n"));
        !           260:                return (-1);
        !           261:        }
        !           262:
        !           263:        /* key name (root or swap) */
        !           264:        if (xdr_string_encode(&send_tail, key, strlen(key))) {
        !           265:                RPC_PRINTF(("bp_getfile: bad key\n"));
        !           266:                return (-1);
        !           267:        }
        !           268:
        !           269:        /* RPC: bootparam/getfile */
        !           270:        d->myport = htons(--rpc_port);
        !           271:        d->destip   = bp_server_addr;
        !           272:        /* rpc_call will set d->destport */
        !           273:
        !           274:        rlen = rpc_call(d,
        !           275:                BOOTPARAM_PROG, BOOTPARAM_VERS, BOOTPARAM_GETFILE,
        !           276:                sdata.d, send_tail - (char *)sdata.d,
        !           277:                rdata.d, sizeof(rdata.d));
        !           278:        if (rlen < 4) {
        !           279:                RPC_PRINTF(("bp_getfile: short reply\n"));
        !           280:                errno = EBADRPC;
        !           281:                return (-1);
        !           282:        }
        !           283:        recv_head = (char *)rdata.d;
        !           284:
        !           285:        /*
        !           286:         * Parse result message.
        !           287:         */
        !           288:
        !           289:        /* server name */
        !           290:        sn_len = FNAME_SIZE-1;
        !           291:        if (xdr_string_decode(&recv_head, serv_name, &sn_len)) {
        !           292:                RPC_PRINTF(("bp_getfile: bad server name\n"));
        !           293:                return (-1);
        !           294:        }
        !           295:
        !           296:        /* server IP address (mountd/NFS) */
        !           297:        if (xdr_inaddr_decode(&recv_head, serv_addr)) {
        !           298:                RPC_PRINTF(("bp_getfile: bad server addr\n"));
        !           299:                return (-1);
        !           300:        }
        !           301:
        !           302:        /* server pathname */
        !           303:        path_len = MAXPATHLEN-1;
        !           304:        if (xdr_string_decode(&recv_head, pathname, &path_len)) {
        !           305:                RPC_PRINTF(("bp_getfile: bad server path\n"));
        !           306:                return (-1);
        !           307:        }
        !           308:
        !           309:        /* success */
        !           310:        return(0);
        !           311: }
        !           312:
        !           313:
        !           314: /*
        !           315:  * eXternal Data Representation routines.
        !           316:  * (but with non-standard args...)
        !           317:  */
        !           318:
        !           319: int
        !           320: xdr_string_encode(char **pkt, char *str, int len)
        !           321: {
        !           322:        u_int32_t *lenp;
        !           323:        char *datap;
        !           324:        int padlen = (len + 3) & ~3;    /* padded length */
        !           325:
        !           326:        /* The data will be int aligned. */
        !           327:        lenp = (u_int32_t*) *pkt;
        !           328:        *pkt += sizeof(*lenp);
        !           329:        *lenp = htonl(len);
        !           330:
        !           331:        datap = *pkt;
        !           332:        *pkt += padlen;
        !           333:        bcopy(str, datap, len);
        !           334:
        !           335:        return (0);
        !           336: }
        !           337:
        !           338: int
        !           339: xdr_string_decode(char **pkt, char *str, int *len_p)
        !           340: {
        !           341:        u_int32_t *lenp;
        !           342:        char *datap;
        !           343:        int slen;       /* string length */
        !           344:        int plen;       /* padded length */
        !           345:
        !           346:        /* The data will be int aligned. */
        !           347:        lenp = (u_int32_t*) *pkt;
        !           348:        *pkt += sizeof(*lenp);
        !           349:        slen = ntohl(*lenp);
        !           350:        plen = (slen + 3) & ~3;
        !           351:
        !           352:        if (slen > *len_p)
        !           353:                slen = *len_p;
        !           354:        datap = *pkt;
        !           355:        *pkt += plen;
        !           356:        bcopy(datap, str, slen);
        !           357:
        !           358:        str[slen] = '\0';
        !           359:        *len_p = slen;
        !           360:
        !           361:        return (0);
        !           362: }
        !           363:
        !           364: int
        !           365: xdr_inaddr_encode(char **pkt, struct in_addr ia)
        !           366: {
        !           367:        struct xdr_inaddr *xi;
        !           368:        u_char *cp;
        !           369:        int32_t *ip;
        !           370:        union {
        !           371:                n_long l;       /* network order */
        !           372:                u_char c[4];
        !           373:        } uia;
        !           374:
        !           375:        /* The data will be int aligned. */
        !           376:        xi = (struct xdr_inaddr *) *pkt;
        !           377:        *pkt += sizeof(*xi);
        !           378:        xi->atype = htonl(1);
        !           379:        uia.l = ia.s_addr;
        !           380:        cp = uia.c;
        !           381:        ip = xi->addr;
        !           382:        /*
        !           383:         * Note: the htonl() calls below DO NOT
        !           384:         * imply that uia.l is in host order.
        !           385:         * In fact this needs it in net order.
        !           386:         */
        !           387:        *ip++ = htonl((unsigned int)*cp++);
        !           388:        *ip++ = htonl((unsigned int)*cp++);
        !           389:        *ip++ = htonl((unsigned int)*cp++);
        !           390:        *ip++ = htonl((unsigned int)*cp++);
        !           391:
        !           392:        return (0);
        !           393: }
        !           394:
        !           395: int
        !           396: xdr_inaddr_decode(char **pkt, struct in_addr *ia)
        !           397: {
        !           398:        struct xdr_inaddr *xi;
        !           399:        u_char *cp;
        !           400:        int32_t *ip;
        !           401:        union {
        !           402:                n_long l;       /* network order */
        !           403:                u_char c[4];
        !           404:        } uia;
        !           405:
        !           406:        /* The data will be int aligned. */
        !           407:        xi = (struct xdr_inaddr *) *pkt;
        !           408:        *pkt += sizeof(*xi);
        !           409:        if (xi->atype != htonl(1)) {
        !           410:                RPC_PRINTF(("xdr_inaddr_decode: bad addrtype=%d\n",
        !           411:                    ntohl(xi->atype)));
        !           412:                return(-1);
        !           413:        }
        !           414:
        !           415:        cp = uia.c;
        !           416:        ip = xi->addr;
        !           417:        /*
        !           418:         * Note: the ntohl() calls below DO NOT
        !           419:         * imply that uia.l is in host order.
        !           420:         * In fact this needs it in net order.
        !           421:         */
        !           422:        *cp++ = ntohl(*ip++);
        !           423:        *cp++ = ntohl(*ip++);
        !           424:        *cp++ = ntohl(*ip++);
        !           425:        *cp++ = ntohl(*ip++);
        !           426:        ia->s_addr = uia.l;
        !           427:
        !           428:        return (0);
        !           429: }

CVSweb