[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

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