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/nfs/bootp_subr.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 /* $FreeBSD$    */
    2 
    3 /*
    4  * Copyright (c) 1995 Gordon Ross, Adam Glass
    5  * Copyright (c) 1992 Regents of the University of California.
    6  * All rights reserved.
    7  *
    8  * This software was developed by the Computer Systems Engineering group
    9  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
   10  * contributed to Berkeley.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. All advertising materials mentioning features or use of this software
   21  *    must display the following acknowledgement:
   22  *      This product includes software developed by the University of
   23  *      California, Lawrence Berkeley Laboratory and its contributors.
   24  * 4. Neither the name of the University nor the names of its contributors
   25  *    may be used to endorse or promote products derived from this software
   26  *    without specific prior written permission.
   27  *
   28  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   29  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   31  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   32  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   37  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   38  * SUCH DAMAGE.
   39  *
   40  * based on:
   41  *      nfs/krpc_subr.c
   42  *      $NetBSD: krpc_subr.c,v 1.10 1995/08/08 20:43:43 gwr Exp $
   43  */
   44 
   45 #include "opt_bootp.h"
   46 
   47 #include <sys/param.h>
   48 #include <sys/systm.h>
   49 #include <sys/kernel.h>
   50 #include <sys/sockio.h>
   51 #include <sys/proc.h>
   52 #include <sys/mount.h>
   53 #include <sys/mbuf.h>
   54 #include <sys/socket.h>
   55 #include <sys/socketvar.h>
   56 #include <sys/uio.h>
   57 
   58 #include <net/if.h>
   59 #include <net/route.h>
   60 
   61 #include <netinet/in.h>
   62 #include <net/if_types.h>
   63 #include <net/if_dl.h>
   64 
   65 #include <nfs/rpcv2.h>
   66 #include <nfs/nfsproto.h>
   67 #include <nfs/nfs.h>
   68 #include <nfs/nfsdiskless.h>
   69 #include <nfs/krpc.h>
   70 #include <nfs/xdr_subs.h>
   71 
   72 
   73 #define BOOTP_MIN_LEN           300     /* Minimum size of bootp udp packet */
   74 
   75 /*
   76  * What is the longest we will wait before re-sending a request?
   77  * Note this is also the frequency of "RPC timeout" messages.
   78  * The re-send loop count sup linearly to this maximum, so the
   79  * first complaint will happen after (1+2+3+4+5)=15 seconds.
   80  */
   81 #define MAX_RESEND_DELAY 5      /* seconds */
   82 
   83 /* Definitions from RFC951 */
   84 struct bootp_packet {
   85   u_int8_t op;
   86   u_int8_t htype;
   87   u_int8_t hlen;
   88   u_int8_t hops;
   89   u_int32_t xid;
   90   u_int16_t secs;
   91   u_int16_t flags;
   92   struct in_addr ciaddr;
   93   struct in_addr yiaddr;
   94   struct in_addr siaddr;
   95   struct in_addr giaddr;
   96   unsigned char chaddr[16];
   97   char sname[64];
   98   char file[128];
   99   unsigned char vend[256];
  100 };
  101 
  102 #define IPPORT_BOOTPC 68
  103 #define IPPORT_BOOTPS 67
  104 
  105 extern int nfs_diskless_valid;
  106 extern struct nfsv3_diskless nfsv3_diskless;
  107 
  108 /* mountd RPC */
  109 static int md_mount __P((struct sockaddr_in *mdsin, char *path,
  110         u_char *fhp, int *fhsizep, struct nfs_args *args,struct proc *procp));
  111 static int md_lookup_swap __P((struct sockaddr_in *mdsin,char *path,
  112                                u_char *fhp, int *fhsizep, 
  113                                struct nfs_args *args,
  114                                struct proc *procp));
  115 static int setfs __P((struct sockaddr_in *addr, char *path, char *p));
  116 static int getdec __P((char **ptr));
  117 static char *substr __P((char *a,char *b));
  118 static void mountopts __P((struct nfs_args *args, char *p)); 
  119 static int xdr_opaque_decode __P((struct mbuf **ptr,u_char *buf,
  120                                   int len));
  121 static int xdr_int_decode __P((struct mbuf **ptr,int *iptr));
  122 static void printip __P((char *prefix,struct in_addr addr));
  123 
  124 #ifdef BOOTP_DEBUG
  125 void bootpboot_p_sa(struct sockaddr *sa,struct sockaddr *ma);
  126 void bootpboot_p_ma(struct sockaddr *ma);
  127 void bootpboot_p_rtentry(struct rtentry *rt);
  128 void bootpboot_p_tree(struct radix_node *rn);
  129 void bootpboot_p_rtlist(void);
  130 void bootpboot_p_iflist(void);
  131 #endif
  132 
  133 static int  bootpc_call(struct bootp_packet *call,
  134                         struct bootp_packet *reply,
  135                         struct proc *procp);
  136 
  137 static int bootpc_fakeup_interface(struct ifreq *ireq,
  138                         struct socket *so,
  139                         struct proc *procp);
  140 
  141 static int 
  142 bootpc_adjust_interface(struct ifreq *ireq,struct socket *so,
  143                         struct sockaddr_in *myaddr,
  144                         struct sockaddr_in *netmask,
  145                         struct sockaddr_in *gw,
  146                         struct proc *procp);
  147 
  148 void bootpc_init(void);
  149 
  150 #ifdef BOOTP_DEBUG
  151 void bootpboot_p_sa(sa,ma)
  152      struct sockaddr *sa;
  153      struct sockaddr *ma;
  154 {
  155   if (!sa) {
  156     printf("(sockaddr *) <null>");
  157     return;
  158   }
  159   switch (sa->sa_family) {
  160   case AF_INET:
  161     {
  162       struct sockaddr_in *sin = (struct sockaddr_in *) sa;
  163       printf("inet %x",ntohl(sin->sin_addr.s_addr));
  164       if (ma) {
  165         struct sockaddr_in *sin = (struct sockaddr_in *) ma;
  166         printf(" mask %x",ntohl(sin->sin_addr.s_addr));
  167       }
  168     }
  169   break;
  170   case AF_LINK:
  171     {
  172       struct sockaddr_dl *sli = (struct sockaddr_dl *) sa;
  173       int i;
  174       printf("link %.*s ",sli->sdl_nlen,sli->sdl_data);
  175       for (i=0;i<sli->sdl_alen;i++) {
  176         if (i>0)
  177           printf(":");
  178         printf("%x",(unsigned char) sli->sdl_data[i+sli->sdl_nlen]);
  179       }
  180     }
  181   break;
  182   default:
  183     printf("af%d",sa->sa_family);
  184   }
  185 }
  186 
  187 void bootpboot_p_ma(ma)
  188      struct sockaddr *ma;
  189 {
  190   if (!ma) {
  191     printf("<null>");
  192     return;
  193   }
  194   printf("%x",*(int*)ma);
  195 }
  196 
  197 void bootpboot_p_rtentry(rt)
  198      struct rtentry *rt;
  199 {
  200   bootpboot_p_sa(rt_key(rt),rt_mask(rt));
  201   printf(" ");
  202   bootpboot_p_ma(rt->rt_genmask);
  203   printf(" ");
  204   bootpboot_p_sa(rt->rt_gateway,NULL);
  205   printf(" ");
  206   printf("flags %x",(unsigned short) rt->rt_flags);
  207   printf(" %d",rt->rt_rmx.rmx_expire);
  208   printf(" %s%d\n",rt->rt_ifp->if_name,rt->rt_ifp->if_unit);
  209 }
  210 void  bootpboot_p_tree(rn)
  211      struct radix_node *rn;
  212 {
  213   while (rn) {
  214     if (rn->rn_b < 0) {
  215       if (rn->rn_flags & RNF_ROOT) {
  216       } else {
  217         bootpboot_p_rtentry((struct rtentry *) rn);
  218       }
  219       rn = rn->rn_dupedkey;
  220     } else {
  221       bootpboot_p_tree(rn->rn_l);
  222       bootpboot_p_tree(rn->rn_r);
  223       return;
  224     }
  225     
  226   }
  227 }
  228 
  229 void bootpboot_p_rtlist(void)
  230 {
  231   printf("Routing table:\n");
  232   bootpboot_p_tree(rt_tables[AF_INET]->rnh_treetop);
  233 }
  234 
  235 void bootpboot_p_iflist(void)
  236 {
  237   struct ifnet *ifp;
  238   struct ifaddr *ifa;
  239   printf("Interface list:\n");
  240   for (ifp = TAILQ_FIRST(&ifnet); ifp != 0; ifp = TAILQ_NEXT(ifp,if_link))
  241     {
  242       for (ifa = TAILQ_FIRST(&ifp->if_addrhead) ;ifa; 
  243            ifa=TAILQ_NEXT(ifa,ifa_link))
  244         if (ifa->ifa_addr->sa_family == AF_INET ) {
  245           printf("%s%d flags %x, addr %x, bcast %x, net %x\n",
  246                  ifp->if_name,ifp->if_unit,
  247                  (unsigned short) ifp->if_flags,
  248                  ntohl(((struct sockaddr_in *) ifa->ifa_addr)->sin_addr.s_addr),
  249                  ntohl(((struct sockaddr_in *) ifa->ifa_dstaddr)->sin_addr.s_addr),
  250                  ntohl(((struct sockaddr_in *) ifa->ifa_netmask)->sin_addr.s_addr)
  251                  );
  252         }
  253     }
  254 }
  255 #endif
  256 
  257 static int
  258 bootpc_call(call,reply,procp)
  259      struct bootp_packet *call;
  260      struct bootp_packet *reply;        /* output */
  261      struct proc *procp;
  262 {
  263         struct socket *so;
  264         struct sockaddr_in *sin, sa;
  265         struct uio auio;
  266         struct sockopt sopt;
  267         struct iovec aio;
  268         struct timeval tv;
  269         int error, on, len, rcvflg, secs, timo;
  270 
  271         /*
  272          * Create socket and set its recieve timeout.
  273          */
  274         if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0,procp)))
  275                 goto out;
  276 
  277         tv.tv_sec = 1;
  278         tv.tv_usec = 0;
  279         bzero(&sopt, sizeof sopt);
  280         sopt.sopt_level = SOL_SOCKET;
  281         sopt.sopt_name = SO_RCVTIMEO;
  282         sopt.sopt_val = &tv;
  283         sopt.sopt_valsize = sizeof tv;
  284 
  285         if (error = sosetopt(so, &sopt))
  286                 goto out;
  287 
  288         /*
  289          * Enable broadcast.
  290          */
  291         on = 1;
  292         sopt.sopt_val = &on;
  293         sopt.sopt_valsize = sizeof on;
  294         sopt.sopt_name = SO_BROADCAST;
  295         if (error = sosetopt(so, &sopt))
  296                 goto out;
  297 
  298         /*
  299          * Bind the local endpoint to a bootp client port.
  300          */
  301         sin = &sa;
  302         bzero(sin, sizeof *sin);
  303         sin->sin_len = sizeof(*sin);
  304         sin->sin_family = AF_INET;
  305         sin->sin_addr.s_addr = INADDR_ANY;
  306         sin->sin_port = htons(IPPORT_BOOTPC);
  307         error = sobind(so, (struct sockaddr *)sin, procp);
  308         if (error) {
  309                 printf("bind failed\n");
  310                 goto out;
  311         }
  312 
  313         /*
  314          * Setup socket address for the server.
  315          */
  316         sin = &sa;
  317         bzero(sin, sizeof *sin);
  318         sin->sin_len = sizeof(*sin);
  319         sin->sin_family = AF_INET;
  320         sin->sin_addr.s_addr = INADDR_BROADCAST;
  321         sin->sin_port = htons(IPPORT_BOOTPS);
  322 
  323         /*
  324          * Send it, repeatedly, until a reply is received,
  325          * but delay each re-send by an increasing amount.
  326          * If the delay hits the maximum, start complaining.
  327          */
  328         timo = 0;
  329         for (;;) {
  330                 /* Send BOOTP request (or re-send). */
  331                 
  332                 aio.iov_base = (caddr_t) call;
  333                 aio.iov_len = sizeof(*call);
  334                 
  335                 auio.uio_iov = &aio;
  336                 auio.uio_iovcnt = 1;
  337                 auio.uio_segflg = UIO_SYSSPACE;
  338                 auio.uio_rw = UIO_WRITE;
  339                 auio.uio_offset = 0;
  340                 auio.uio_resid = sizeof(*call);
  341                 auio.uio_procp = procp;
  342 
  343                 error = sosend(so, (struct sockaddr *)sin, &auio, NULL, 
  344                                NULL, 0, procp);
  345                 if (error) {
  346                         printf("bootpc_call: sosend: %d state %08x\n", error, (int)so->so_state);
  347                         goto out;
  348                 }
  349 
  350                 /* Determine new timeout. */
  351                 if (timo < MAX_RESEND_DELAY)
  352                         timo++;
  353                 else
  354                         printf("BOOTP timeout for server 0x%lx\n",
  355                                (u_long)ntohl(sin->sin_addr.s_addr));
  356 
  357                 /*
  358                  * Wait for up to timo seconds for a reply.
  359                  * The socket receive timeout was set to 1 second.
  360                  */
  361                 secs = timo;
  362                 while (secs > 0) {
  363                         aio.iov_base = (caddr_t) reply;
  364                         aio.iov_len = sizeof(*reply);
  365 
  366                         auio.uio_iov = &aio;
  367                         auio.uio_iovcnt = 1;
  368                         auio.uio_segflg = UIO_SYSSPACE;
  369                         auio.uio_rw = UIO_READ;
  370                         auio.uio_offset = 0;
  371                         auio.uio_resid = sizeof(*reply);
  372                         auio.uio_procp = procp;
  373                         
  374                         rcvflg = 0;
  375                         error = soreceive(so, NULL, &auio, NULL, NULL, &rcvflg);
  376                         if (error == EWOULDBLOCK) {
  377                                 secs--;
  378                                 call->secs=htons(ntohs(call->secs)+1);
  379                                 continue;
  380                         }
  381                         if (error)
  382                                 goto out;
  383                         len = sizeof(*reply) - auio.uio_resid;
  384 
  385                         /* Do we have the required number of bytes ? */
  386                         if (len < BOOTP_MIN_LEN)
  387                                 continue;
  388 
  389                         /* Is it the right reply? */
  390                         if (reply->op != 2)
  391                           continue;
  392 
  393                         if (reply->xid != call->xid)
  394                                 continue;
  395 
  396                         if (reply->hlen != call->hlen)
  397                           continue;
  398 
  399                         if (bcmp(reply->chaddr,call->chaddr,call->hlen))
  400                           continue;
  401 
  402                         goto gotreply;  /* break two levels */
  403 
  404                 } /* while secs */
  405         } /* forever send/receive */
  406 
  407         error = ETIMEDOUT;
  408         goto out;
  409 
  410  gotreply:
  411  out:
  412         soclose(so);
  413         return error;
  414 }
  415 
  416 static int 
  417 bootpc_fakeup_interface(struct ifreq *ireq,struct socket *so,
  418                         struct proc *procp)
  419 {
  420   struct sockaddr_in *sin;
  421   int error;
  422   struct sockaddr_in dst;
  423   struct sockaddr_in gw;
  424   struct sockaddr_in mask;
  425 
  426   /*
  427    * Bring up the interface.
  428    *
  429    * Get the old interface flags and or IFF_UP into them; if
  430    * IFF_UP set blindly, interface selection can be clobbered.
  431    */
  432   error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, procp);
  433   if (error)
  434     panic("bootpc_fakeup_interface: GIFFLAGS, error=%d", error);
  435   ireq->ifr_flags |= IFF_UP;
  436   error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, procp);
  437   if (error)
  438     panic("bootpc_fakeup_interface: SIFFLAGS, error=%d", error);
  439 
  440   /*
  441    * Do enough of ifconfig(8) so that the chosen interface
  442    * can talk to the servers.  (just set the address)
  443    */
  444   
  445   /* addr is 0.0.0.0 */
  446   
  447   sin = (struct sockaddr_in *)&ireq->ifr_addr;
  448   bzero((caddr_t)sin, sizeof(*sin));
  449   sin->sin_len = sizeof(*sin);
  450   sin->sin_family = AF_INET;
  451   sin->sin_addr.s_addr = INADDR_ANY;
  452   error = ifioctl(so, SIOCSIFADDR, (caddr_t)ireq, procp);
  453   if (error)
  454     panic("bootpc_fakeup_interface: set if addr, error=%d", error);
  455   
  456   /* netmask is 0.0.0.0 */
  457   
  458   sin = (struct sockaddr_in *)&ireq->ifr_addr;
  459   bzero((caddr_t)sin, sizeof(*sin));
  460   sin->sin_len = sizeof(*sin);
  461   sin->sin_family = AF_INET;
  462   sin->sin_addr.s_addr = INADDR_ANY;
  463   error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, procp);
  464   if (error)
  465     panic("bootpc_fakeup_interface: set if net addr, error=%d", error);
  466   
  467   /* Broadcast is 255.255.255.255 */
  468   
  469   sin = (struct sockaddr_in *)&ireq->ifr_addr;
  470   bzero((caddr_t)sin, sizeof(*sin));
  471   sin->sin_len = sizeof(*sin);
  472   sin->sin_family = AF_INET;
  473   sin->sin_addr.s_addr = INADDR_BROADCAST;
  474   error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, procp);
  475   if (error)
  476     panic("bootpc_fakeup_interface: set if broadcast addr, error=%d", error);
  477   
  478   /* Add default route to 0.0.0.0 so we can send data */
  479   
  480   bzero((caddr_t) &dst, sizeof(dst));
  481   dst.sin_len=sizeof(dst);
  482   dst.sin_family=AF_INET;
  483   dst.sin_addr.s_addr = htonl(0);
  484   
  485   bzero((caddr_t) &gw, sizeof(gw));
  486   gw.sin_len=sizeof(gw);
  487   gw.sin_family=AF_INET;
  488   gw.sin_addr.s_addr = htonl(0x0);
  489   
  490   bzero((caddr_t) &mask, sizeof(mask));
  491   mask.sin_len=sizeof(mask);
  492   mask.sin_family=AF_INET;
  493   mask.sin_addr.s_addr = htonl(0);
  494   
  495   error = rtrequest(RTM_ADD, 
  496                     (struct sockaddr *) &dst, 
  497                     (struct sockaddr *) &gw,
  498                     (struct sockaddr *) &mask, 
  499                     RTF_UP | RTF_STATIC
  500                     , NULL);
  501   if (error)
  502     printf("bootpc_fakeup_interface: add default route, error=%d\n", error);
  503   return error;
  504 }
  505 
  506 static int 
  507 bootpc_adjust_interface(struct ifreq *ireq,struct socket *so,
  508                         struct sockaddr_in *myaddr,
  509                         struct sockaddr_in *netmask,
  510                         struct sockaddr_in *gw,
  511                         struct proc *procp)
  512 {
  513   int error;
  514   struct sockaddr_in oldgw;
  515   struct sockaddr_in olddst;
  516   struct sockaddr_in oldmask;
  517   struct sockaddr_in *sin;
  518 
  519   /* Remove old default route to 0.0.0.0 */
  520   
  521   bzero((caddr_t) &olddst, sizeof(olddst));
  522   olddst.sin_len=sizeof(olddst);
  523   olddst.sin_family=AF_INET;
  524   olddst.sin_addr.s_addr = INADDR_ANY;
  525   
  526   bzero((caddr_t) &oldgw, sizeof(oldgw));
  527   oldgw.sin_len=sizeof(oldgw);
  528   oldgw.sin_family=AF_INET;
  529   oldgw.sin_addr.s_addr = INADDR_ANY;
  530   
  531   bzero((caddr_t) &oldmask, sizeof(oldmask));
  532   oldmask.sin_len=sizeof(oldmask);
  533   oldmask.sin_family=AF_INET;
  534   oldmask.sin_addr.s_addr = INADDR_ANY;
  535   
  536   error = rtrequest(RTM_DELETE, 
  537                     (struct sockaddr *) &olddst,
  538                     (struct sockaddr *) &oldgw,
  539                     (struct sockaddr *) &oldmask, 
  540                     (RTF_UP | RTF_STATIC), NULL);
  541   if (error) {
  542     printf("nfs_boot: del default route, error=%d\n", error);
  543     return error;
  544   }
  545 
  546   /*
  547    * Do enough of ifconfig(8) so that the chosen interface
  548    * can talk to the servers.  (just set the address)
  549    */
  550   bcopy(netmask,&ireq->ifr_addr,sizeof(*netmask));
  551   error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, procp);
  552   if (error)
  553     panic("nfs_boot: set if netmask, error=%d", error);
  554 
  555   /* Broadcast is with host part of IP address all 1's */
  556   
  557   sin = (struct sockaddr_in *)&ireq->ifr_addr;
  558   bzero((caddr_t)sin, sizeof(*sin));
  559   sin->sin_len = sizeof(*sin);
  560   sin->sin_family = AF_INET;
  561   sin->sin_addr.s_addr = myaddr->sin_addr.s_addr | ~ netmask->sin_addr.s_addr;
  562   error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, procp);
  563   if (error)
  564     panic("bootpc_call: set if broadcast addr, error=%d", error);
  565   
  566   bcopy(myaddr,&ireq->ifr_addr,sizeof(*myaddr));
  567   error = ifioctl(so, SIOCSIFADDR, (caddr_t)ireq, procp);
  568   if (error)
  569     panic("nfs_boot: set if addr, error=%d", error);
  570 
  571   /* Add new default route */
  572 
  573   error = rtrequest(RTM_ADD, 
  574                     (struct sockaddr *) &olddst,
  575                     (struct sockaddr *) gw,
  576                     (struct sockaddr *) &oldmask,
  577                     (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL);
  578   if (error) {
  579     printf("nfs_boot: add net route, error=%d\n", error);
  580     return error;
  581   }
  582 
  583   return 0;
  584 }
  585 
  586 static int setfs(addr, path, p)
  587         struct sockaddr_in *addr;
  588         char *path;
  589         char *p;
  590 {
  591         unsigned ip = 0;
  592         int val;
  593 
  594         if (((val = getdec(&p)) < 0) || (val > 255)) return(0);
  595         ip = val << 24;
  596         if (*p != '.') return(0);
  597         p++;
  598         if (((val = getdec(&p)) < 0) || (val > 255)) return(0);
  599         ip |= (val << 16);
  600         if (*p != '.') return(0);
  601         p++;
  602         if (((val = getdec(&p)) < 0) || (val > 255)) return(0);
  603         ip |= (val << 8);
  604         if (*p != '.') return(0);
  605         p++;
  606         if (((val = getdec(&p)) < 0) || (val > 255)) return(0);
  607         ip |= val;
  608         if (*p != ':') return(0);
  609         p++;
  610 
  611         addr->sin_addr.s_addr = htonl(ip);
  612         addr->sin_len = sizeof(struct sockaddr_in);
  613         addr->sin_family = AF_INET;
  614 
  615         strncpy(path,p,MNAMELEN-1);
  616         return(1);
  617 }
  618 
  619 static int getdec(ptr)
  620         char **ptr;
  621 {
  622         char *p = *ptr;
  623         int ret=0;
  624         if ((*p < '') || (*p > '9')) return(-1);
  625         while ((*p >= '') && (*p <= '9')) {
  626                 ret = ret*10 + (*p - '');
  627                 p++;
  628         }
  629         *ptr = p;
  630         return(ret);
  631 }
  632 
  633 static char *substr(a,b)
  634         char *a,*b;
  635 {
  636         char *loc1;
  637         char *loc2;
  638 
  639         while (*a != '\0') {
  640                 loc1 = a;
  641                 loc2 = b;
  642                 while (*loc1 == *loc2++) {
  643                         if (*loc1 == '\0') return (0);
  644                         loc1++;
  645                         if (*loc2 == '\0') return (loc1);
  646                 }
  647         a++;
  648         }
  649         return (0);
  650 }
  651 
  652 static void mountopts(args,p)
  653         struct nfs_args *args;
  654         char *p;
  655 {
  656         char *tmp;
  657   
  658         args->flags = NFSMNT_RSIZE | NFSMNT_WSIZE | NFSMNT_RESVPORT;
  659         args->sotype = SOCK_DGRAM;
  660         if ((tmp = (char *)substr(p,"rsize=")))
  661                 args->rsize=getdec(&tmp);
  662         if ((tmp = (char *)substr(p,"wsize=")))
  663                 args->wsize=getdec(&tmp);
  664         if ((tmp = (char *)substr(p,"intr")))
  665                 args->flags |= NFSMNT_INT;
  666         if ((tmp = (char *)substr(p,"soft")))
  667                 args->flags |= NFSMNT_SOFT;
  668         if ((tmp = (char *)substr(p,"noconn")))
  669                 args->flags |= NFSMNT_NOCONN;
  670         if ((tmp = (char *)substr(p, "tcp")))
  671             args->sotype = SOCK_STREAM;
  672 }
  673 
  674 static int xdr_opaque_decode(mptr,buf,len)
  675      struct mbuf **mptr;
  676      u_char *buf;
  677      int len;   
  678 {
  679   struct mbuf *m;
  680   int alignedlen;
  681 
  682   m = *mptr;
  683   alignedlen = ( len + 3 ) & ~3;
  684 
  685   if (m->m_len < alignedlen) {
  686     m = m_pullup(m,alignedlen);
  687     if (m == NULL) {
  688       *mptr = NULL;
  689       return EBADRPC;
  690     }
  691   }
  692   bcopy(mtod(m,u_char *),buf,len);
  693   m_adj(m,alignedlen);
  694   *mptr = m;
  695   return 0;
  696 }
  697 
  698 static int xdr_int_decode(mptr,iptr)
  699      struct mbuf **mptr;
  700      int *iptr;
  701 {
  702   u_int32_t i;
  703   if (xdr_opaque_decode(mptr,(u_char *) &i,sizeof(u_int32_t)))
  704     return EBADRPC;
  705   *iptr = fxdr_unsigned(u_int32_t,i);
  706   return 0;
  707 }
  708 
  709 static void printip(char *prefix,struct in_addr addr)
  710 {
  711   unsigned int ip;
  712 
  713   ip = ntohl(addr.s_addr);
  714 
  715   printf("%s is %d.%d.%d.%d\n",prefix,
  716          ip >> 24, (ip >> 16) & 255 ,(ip >> 8) & 255 ,ip & 255 );
  717 }
  718 
  719 void
  720 bootpc_init(void)
  721 {
  722   struct bootp_packet call;
  723   struct bootp_packet reply;
  724   static u_int32_t xid = ~0xFF;
  725   
  726   struct ifreq ireq;
  727   struct ifnet *ifp;
  728   struct socket *so;
  729   int error;
  730   int code,ncode,len;
  731   int j;
  732   char *p;
  733   unsigned int ip;
  734 
  735   struct sockaddr_in myaddr;
  736   struct sockaddr_in netmask;
  737   struct sockaddr_in gw;
  738   int gotgw=0;
  739   int gotnetmask=0;
  740   int gotrootpath=0;
  741   int gotswappath=0;
  742   char lookup_path[24];
  743 
  744 #define EALEN 6
  745   struct ifaddr *ifa;
  746   struct sockaddr_dl *sdl = NULL;
  747   char *delim;
  748 
  749   struct nfsv3_diskless *nd = &nfsv3_diskless;
  750   struct proc *procp = curproc;
  751 
  752   /*
  753    * If already filled in, don't touch it here 
  754    */
  755   if (nfs_diskless_valid)
  756     return;
  757 
  758   /*
  759    * Wait until arp entries can be handled.
  760    */
  761   while (time_second == 0)
  762         tsleep(&time_second, PZERO+8, "arpkludge", 10);
  763 
  764   /*
  765    * Find a network interface.
  766    */
  767 #ifdef BOOTP_WIRED_TO
  768   printf("bootpc_init: wired to interface '%s'\n",
  769          __XSTRING(BOOTP_WIRED_TO)); 
  770 #endif
  771   bzero(&ireq, sizeof(ireq));
  772   for (ifp = TAILQ_FIRST(&ifnet); ifp != 0; ifp = TAILQ_NEXT(ifp,if_link))
  773   {
  774     snprintf(ireq.ifr_name, sizeof(ireq.ifr_name),
  775         "%s%d", ifp->if_name, ifp->if_unit);
  776 #ifdef BOOTP_WIRED_TO
  777     if (strcmp(ireq.ifr_name, __XSTRING(BOOTP_WIRED_TO)) == 0)
  778         break;
  779 #else
  780     if ((ifp->if_flags &
  781       (IFF_LOOPBACK|IFF_POINTOPOINT)) == 0)
  782         break;
  783 #endif
  784   }     
  785   if (ifp == NULL)
  786     panic("bootpc_init: no suitable interface");
  787   strcpy(nd->myif.ifra_name,ireq.ifr_name);
  788   printf("bootpc_init: using network interface '%s'\n",
  789          ireq.ifr_name);
  790 
  791   if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0,procp)) != 0)
  792     panic("nfs_boot: socreate, error=%d", error);
  793           
  794   bootpc_fakeup_interface(&ireq,so,procp);
  795 
  796   printf("Bootpc testing starting\n");
  797   
  798   /* Get HW address */
  799 
  800   for (ifa = TAILQ_FIRST(&ifp->if_addrhead) ;ifa; 
  801        ifa=TAILQ_NEXT(ifa,ifa_link))
  802     if (ifa->ifa_addr->sa_family == AF_LINK &&
  803         (sdl = ((struct sockaddr_dl *) ifa->ifa_addr)) &&
  804         sdl->sdl_type == IFT_ETHER)
  805       break;
  806   
  807   if (!sdl)
  808     panic("bootpc: Unable to find HW address");
  809   if (sdl->sdl_alen != EALEN ) 
  810     panic("bootpc: HW address len is %d, expected value is %d",
  811           sdl->sdl_alen,EALEN);
  812 
  813   printf("bootpc hw address is ");
  814   delim="";
  815   for (j=0;j<sdl->sdl_alen;j++) {
  816     printf("%s%x",delim,((unsigned char *)LLADDR(sdl))[j]);
  817     delim=":";
  818   }
  819   printf("\n");
  820 
  821 #if 0
  822   bootpboot_p_iflist();
  823   bootpboot_p_rtlist();
  824 #endif
  825   
  826   bzero((caddr_t) &call, sizeof(call));
  827 
  828   /* bootpc part */
  829   call.op = 1;                  /* BOOTREQUEST */
  830   call.htype= 1;                /* 10mb ethernet */
  831   call.hlen=sdl->sdl_alen;      /* Hardware address length */
  832   call.hops=0;  
  833   xid++;
  834   call.xid = txdr_unsigned(xid);
  835   bcopy(LLADDR(sdl),&call.chaddr,sdl->sdl_alen);
  836   
  837   call.vend[0]=99;
  838   call.vend[1]=130;
  839   call.vend[2]=83;
  840   call.vend[3]=99;
  841   call.vend[4]=255;
  842   
  843   call.secs = 0;
  844   call.flags = htons(0x8000); /* We need an broadcast answer */
  845   
  846   error = bootpc_call(&call,&reply,procp);
  847   
  848   if (error) {
  849 #ifdef BOOTP_NFSROOT
  850     panic("BOOTP call failed");
  851 #endif
  852     return;
  853   }
  854   
  855   bzero(&myaddr,sizeof(myaddr));
  856   bzero(&netmask,sizeof(netmask));
  857   bzero(&gw,sizeof(gw));
  858 
  859   myaddr.sin_len = sizeof(myaddr);
  860   myaddr.sin_family = AF_INET;
  861 
  862   netmask.sin_len = sizeof(netmask);
  863   netmask.sin_family = AF_INET;
  864 
  865   gw.sin_len = sizeof(gw);
  866   gw.sin_family= AF_INET;
  867 
  868   nd->root_args.version = NFS_ARGSVERSION;
  869   nd->root_args.rsize = 8192;
  870   nd->root_args.wsize = 8192;
  871   nd->root_args.sotype = SOCK_DGRAM;
  872   nd->root_args.flags = (NFSMNT_WSIZE | NFSMNT_RSIZE | NFSMNT_RESVPORT);
  873 
  874   nd->swap_saddr.sin_len = sizeof(gw);
  875   nd->swap_saddr.sin_family = AF_INET;
  876 
  877   nd->swap_args.version = NFS_ARGSVERSION;
  878   nd->swap_args.rsize = 8192;
  879   nd->swap_args.wsize = 8192;
  880   nd->swap_args.sotype = SOCK_DGRAM;
  881   nd->swap_args.flags = (NFSMNT_WSIZE | NFSMNT_RSIZE | NFSMNT_RESVPORT);
  882   
  883   myaddr.sin_addr = reply.yiaddr;
  884 
  885   ip = ntohl(myaddr.sin_addr.s_addr);
  886   snprintf(lookup_path, sizeof(lookup_path), "swap.%d.%d.%d.%d",
  887           ip >> 24, (ip >> 16) & 255 ,(ip >> 8) & 255 ,ip & 255 );
  888 
  889   printip("My ip address",myaddr.sin_addr);
  890 
  891   printip("Server ip address",reply.siaddr);
  892 
  893   gw.sin_addr = reply.giaddr;
  894   printip("Gateway ip address",reply.giaddr);
  895 
  896   if (reply.sname[0])
  897     printf("Server name is %s\n",reply.sname);
  898   if (reply.file[0])
  899     printf("boot file is %s\n",reply.file);
  900   if (reply.vend[0]==99 && reply.vend[1]==130 &&
  901       reply.vend[2]==83 && reply.vend[3]==99) {
  902     j=4;
  903     ncode = reply.vend[j];
  904     while (j<sizeof(reply.vend)) {
  905       code = reply.vend[j] = ncode;
  906       if (code==255)
  907         break;
  908       if (code==0) {
  909         j++;
  910         continue;
  911       }
  912       len = reply.vend[j+1];
  913       j+=2;
  914       if (len+j>=sizeof(reply.vend)) {
  915         printf("Truncated field");
  916         break;
  917       }
  918       ncode = reply.vend[j+len];
  919       reply.vend[j+len]='\0';
  920       p = &reply.vend[j];
  921       switch (code) {
  922       case 1:
  923         if (len!=4) 
  924           panic("bootpc: subnet mask len is %d",len);
  925         bcopy(&reply.vend[j],&netmask.sin_addr,4);
  926         gotnetmask=1;
  927         printip("Subnet mask",netmask.sin_addr);
  928         break;
  929       case 6:   /* Domain Name servers. Unused */
  930       case 16:  /* Swap server IP address. unused */
  931       case 2:
  932         /* Time offset */
  933         break;
  934       case 3:
  935         /* Routers */
  936         if (len % 4) 
  937           panic("bootpc: Router Len is %d",len);
  938         if (len > 0) {
  939           bcopy(&reply.vend[j],&gw.sin_addr,4);
  940           printip("Router",gw.sin_addr);
  941           gotgw=1;
  942         }
  943         break;
  944       case 17:
  945         if (setfs(&nd->root_saddr, nd->root_hostnam, p)) {
  946           printf("rootfs is %s\n",p);
  947           gotrootpath=1;
  948         } else 
  949           panic("Failed to set rootfs to %s",p);
  950         break;
  951       case 12:
  952         if (len>=MAXHOSTNAMELEN)
  953           panic("bootpc: hostname  >=%d bytes",MAXHOSTNAMELEN);
  954         strncpy(nd->my_hostnam,&reply.vend[j],len);
  955         nd->my_hostnam[len]=0;
  956         strncpy(hostname,&reply.vend[j],len);
  957         hostname[len]=0;
  958         printf("Hostname is %s\n",hostname);
  959         break;
  960       case 128:
  961         if (setfs(&nd->swap_saddr, nd->swap_hostnam, p)) {
  962           gotswappath=1;
  963           printf("swapfs is %s\n",p);
  964         } else
  965           panic("Failed to set swapfs to %s",p);
  966         break;
  967       case 129:
  968         {
  969           int swaplen;
  970           if (len!=4) 
  971             panic("bootpc: Expected 4 bytes for swaplen, not %d bytes",len);
  972           bcopy(&reply.vend[j],&swaplen,4);
  973           nd->swap_nblks = ntohl(swaplen);
  974           printf("bootpc: Swap size is %d KB\n",nd->swap_nblks);
  975         }
  976         break;
  977       case 130: /* root mount options */
  978         mountopts(&nd->root_args,p);
  979         break;
  980       case 131: /* swap mount options */
  981         mountopts(&nd->swap_args,p);
  982         break;
  983       default:
  984         printf("Ignoring field type %d\n",code);
  985       }
  986       j+=len;
  987     }
  988   }
  989 
  990   if (!gotswappath)
  991     nd->swap_nblks = 0;
  992 #ifdef BOOTP_NFSROOT
  993   if (!gotrootpath)
  994     panic("bootpc: No root path offered");
  995 #endif
  996 
  997   if (!gotnetmask) {
  998     if (IN_CLASSA(ntohl(myaddr.sin_addr.s_addr)))
  999       netmask.sin_addr.s_addr = htonl(IN_CLASSA_NET);
 1000     else if (IN_CLASSB(ntohl(myaddr.sin_addr.s_addr)))
 1001       netmask.sin_addr.s_addr = htonl(IN_CLASSB_NET);
 1002     else 
 1003       netmask.sin_addr.s_addr = htonl(IN_CLASSC_NET);
 1004   }
 1005   if (!gotgw) {
 1006     /* Use proxyarp */
 1007     gw.sin_addr.s_addr = myaddr.sin_addr.s_addr;
 1008   }
 1009   
 1010 #if 0
 1011   bootpboot_p_iflist();
 1012   bootpboot_p_rtlist();
 1013 #endif
 1014   error = bootpc_adjust_interface(&ireq,so,
 1015                                   &myaddr,&netmask,&gw,procp);
 1016   
 1017   soclose(so);
 1018 
 1019 #if 0
 1020   bootpboot_p_iflist();
 1021   bootpboot_p_rtlist();
 1022 #endif
 1023 
 1024   if (gotrootpath) {
 1025 
 1026     error = md_mount(&nd->root_saddr, nd->root_hostnam, 
 1027                      nd->root_fh, &nd->root_fhsize,
 1028                      &nd->root_args,procp);
 1029     if (error)
 1030       panic("nfs_boot: mountd root, error=%d", error);
 1031     
 1032     if (gotswappath) {
 1033 
 1034       error = md_mount(&nd->swap_saddr, 
 1035                        nd->swap_hostnam,
 1036                        nd->swap_fh, &nd->swap_fhsize,&nd->swap_args,procp);
 1037       if (error)
 1038         panic("nfs_boot: mountd swap, error=%d", error);
 1039       
 1040       error = md_lookup_swap(&nd->swap_saddr,lookup_path,nd->swap_fh, 
 1041                              &nd->swap_fhsize, &nd->swap_args,procp);
 1042       if (error)
 1043         panic("nfs_boot: lookup swap, error=%d", error);
 1044     }
 1045     nfs_diskless_valid = 3;
 1046   }
 1047 
 1048 
 1049   bcopy(&myaddr,&nd->myif.ifra_addr,sizeof(myaddr));
 1050   bcopy(&myaddr,&nd->myif.ifra_broadaddr,sizeof(myaddr));
 1051   ((struct sockaddr_in *) &nd->myif.ifra_broadaddr)->sin_addr.s_addr = 
 1052     myaddr.sin_addr.s_addr | ~ netmask.sin_addr.s_addr;
 1053   bcopy(&netmask,&nd->myif.ifra_mask,sizeof(netmask));
 1054 
 1055 #if 0
 1056   bootpboot_p_iflist();
 1057   bootpboot_p_rtlist();
 1058 #endif
 1059   return;
 1060 }
 1061 
 1062 /*
 1063  * RPC: mountd/mount
 1064  * Given a server pathname, get an NFS file handle.
 1065  * Also, sets sin->sin_port to the NFS service port.
 1066  */
 1067 static int
 1068 md_mount(mdsin, path, fhp, fhsizep, args, procp)
 1069         struct sockaddr_in *mdsin;              /* mountd server address */
 1070         char *path;
 1071         u_char *fhp;
 1072         int *fhsizep;
 1073         struct nfs_args *args;
 1074         struct proc *procp;
 1075 {
 1076         struct mbuf *m;
 1077         int error;
 1078         int authunixok;
 1079         int authcount;
 1080         int authver;
 1081 
 1082 #ifdef BOOTP_NFSV3
 1083         /* First try NFS v3 */
 1084         /* Get port number for MOUNTD. */
 1085         error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER3,
 1086                                                  &mdsin->sin_port, procp);
 1087         if (!error) {
 1088           m = xdr_string_encode(path, strlen(path));
 1089           
 1090           /* Do RPC to mountd. */
 1091           error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER3,
 1092                             RPCMNT_MOUNT, &m, NULL, curproc);
 1093         }
 1094         if (!error) {
 1095           args->flags |= NFSMNT_NFSV3;
 1096         } else {
 1097 #endif
 1098           /* Fallback to NFS v2 */
 1099           
 1100           /* Get port number for MOUNTD. */
 1101           error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER1,
 1102                                &mdsin->sin_port, procp);
 1103           if (error) return error;
 1104           
 1105           m = xdr_string_encode(path, strlen(path));
 1106           
 1107           /* Do RPC to mountd. */
 1108           error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER1,
 1109                             RPCMNT_MOUNT, &m, NULL, curproc);
 1110           if (error)
 1111             return error;       /* message already freed */
 1112 
 1113 #ifdef BOOTP_NFSV3
 1114         }
 1115 #endif
 1116 
 1117         if (xdr_int_decode(&m,&error) || error)
 1118           goto bad;
 1119 
 1120         if (args->flags & NFSMNT_NFSV3) {
 1121           if (xdr_int_decode(&m,fhsizep) ||
 1122               *fhsizep > NFSX_V3FHMAX || *fhsizep <= 0 ) 
 1123             goto bad;
 1124         } else 
 1125           *fhsizep = NFSX_V2FH;
 1126 
 1127         if (xdr_opaque_decode(&m,fhp,*fhsizep))
 1128           goto bad;
 1129 
 1130         if (args->flags & NFSMNT_NFSV3) {
 1131           if (xdr_int_decode(&m,&authcount))
 1132             goto bad;
 1133           authunixok = 0;
 1134           if (authcount<0 || authcount>100)
 1135             goto bad;
 1136           while (authcount>0) {
 1137             if (xdr_int_decode(&m,&authver))
 1138               goto bad;
 1139             if (authver == RPCAUTH_UNIX)
 1140               authunixok = 1;
 1141             authcount--;
 1142           }
 1143           if (!authunixok)
 1144             goto bad;
 1145         }
 1146           
 1147         /* Set port number for NFS use. */
 1148         error = krpc_portmap(mdsin, NFS_PROG, 
 1149                              (args->flags & NFSMNT_NFSV3)?NFS_VER3:NFS_VER2,
 1150                              &mdsin->sin_port, procp);
 1151 
 1152         goto out;
 1153 
 1154 bad:
 1155         error = EBADRPC;
 1156 
 1157 out:
 1158         m_freem(m);
 1159         return error;
 1160 }
 1161 
 1162 
 1163 static int md_lookup_swap(mdsin, path, fhp, fhsizep, args, procp)
 1164         struct sockaddr_in *mdsin;              /* mountd server address */
 1165         char *path;
 1166         u_char *fhp;
 1167         int *fhsizep;
 1168         struct nfs_args *args;
 1169         struct proc *procp;
 1170 {
 1171         struct mbuf *m;
 1172         int error;
 1173         int size = -1;
 1174         int attribs_present;
 1175         int status;
 1176         union {
 1177           u_int32_t v2[17];
 1178           u_int32_t v3[21];
 1179         } fattribs;
 1180 
 1181         m = m_get(M_WAIT,MT_DATA);
 1182         if (!m)
 1183                 return ENOBUFS;
 1184 
 1185         if (args->flags & NFSMNT_NFSV3) {
 1186           *mtod(m,u_int32_t *) = txdr_unsigned(*fhsizep);
 1187           bcopy(fhp,mtod(m,u_char *)+sizeof(u_int32_t),*fhsizep);
 1188           m->m_len = *fhsizep + sizeof(u_int32_t);
 1189         } else {
 1190           bcopy(fhp,mtod(m,u_char *),NFSX_V2FH);
 1191           m->m_len = NFSX_V2FH;
 1192         }
 1193         
 1194         m->m_next = xdr_string_encode(path, strlen(path));
 1195         if (!m->m_next) {
 1196           error = ENOBUFS;
 1197           goto out;
 1198         }
 1199 
 1200         /* Do RPC to nfsd. */
 1201         if (args->flags & NFSMNT_NFSV3)
 1202           error = krpc_call(mdsin, NFS_PROG, NFS_VER3,
 1203                             NFSPROC_LOOKUP, &m, NULL, procp);
 1204         else 
 1205           error = krpc_call(mdsin, NFS_PROG, NFS_VER2,
 1206                             NFSV2PROC_LOOKUP, &m, NULL, procp);
 1207         if (error)
 1208           return error; /* message already freed */
 1209 
 1210         if (xdr_int_decode(&m,&status))
 1211           goto bad;
 1212         if (status) {
 1213           error = ENOENT;
 1214           goto out;
 1215         }
 1216         
 1217         if (args->flags & NFSMNT_NFSV3) {
 1218           if (xdr_int_decode(&m,fhsizep) ||
 1219               *fhsizep > NFSX_V3FHMAX || *fhsizep <= 0 ) 
 1220             goto bad;
 1221         } else
 1222           *fhsizep = NFSX_V2FH;
 1223         
 1224         if (xdr_opaque_decode(&m, fhp, *fhsizep))
 1225           goto bad;
 1226 
 1227         if (args->flags & NFSMNT_NFSV3) {
 1228           if (xdr_int_decode(&m,&attribs_present))
 1229             goto bad;
 1230           if (attribs_present) {
 1231             if (xdr_opaque_decode(&m,(u_char *) &fattribs.v3,
 1232                                   sizeof(u_int32_t)*21))
 1233               goto bad;
 1234             size = fxdr_unsigned(u_int32_t, fattribs.v3[6]);
 1235           }
 1236         } else {
 1237           if (xdr_opaque_decode(&m,(u_char *) &fattribs.v2,
 1238                                 sizeof(u_int32_t)*17))
 1239             goto bad;
 1240           size = fxdr_unsigned(u_int32_t, fattribs.v2[5]);
 1241         }
 1242           
 1243         if (!nfsv3_diskless.swap_nblks && size!= -1) {
 1244           nfsv3_diskless.swap_nblks = size/1024;
 1245           printf("md_lookup_swap: Swap size is %d KB\n",
 1246                  nfsv3_diskless.swap_nblks);
 1247         }
 1248         
 1249         goto out;
 1250 
 1251 bad:
 1252         error = EBADRPC;
 1253 
 1254 out:
 1255         m_freem(m);
 1256         return error;
 1257 }

Cache object: 8ee6c8c424b0de7006537f29680dda1e


[ 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.