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

Cache object: 4a3fa5f23f6485059fbe1d9663c576bb


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