root/lib/libsa/bootparam.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. bp_whoami
  2. bp_getfile
  3. xdr_string_encode
  4. xdr_string_decode
  5. xdr_inaddr_encode
  6. xdr_inaddr_decode

    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 }

/* [<][>][^][v][top][bottom][index][help] */