The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/lib/libsa/bootparam.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: dcacfbdc0c81bac375f892041ff7ada1


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.