[BACK]Return to if.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / net

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/net/if.c between version 1.208 and 1.208.4.2

version 1.208, 2007/12/06 02:23:42 version 1.208.4.2, 2008/01/23 19:27:44
Line 261  struct ifaddr **ifnet_addrs = NULL;
Line 261  struct ifaddr **ifnet_addrs = NULL;
 struct ifnet **ifindex2ifnet = NULL;  struct ifnet **ifindex2ifnet = NULL;
 struct ifnet *lo0ifp;  struct ifnet *lo0ifp;
   
 /*  
  * Allocate the link level name for the specified interface.  This  
  * is an attachment helper.  It must be called after ifp->if_addrlen  
  * is initialized, which may not be the case when if_attach() is  
  * called.  
  */  
 void  void
 if_alloc_sadl(struct ifnet *ifp)  if_set_sadl(struct ifnet *ifp, const void *lla, u_char addrlen)
   {
           struct ifaddr *ifa;
           struct sockaddr_dl *sdl;
   
           ifp->if_addrlen = addrlen;
           if_alloc_sadl(ifp);
           ifa = ifp->if_dl;
           sdl = satosdl(ifa->ifa_addr);
   
           (void)sockaddr_dl_setaddr(sdl, sdl->sdl_len, lla, ifp->if_addrlen);
   }
   
   struct ifaddr *
   if_dl_create(const struct ifnet *ifp, const struct sockaddr_dl **sdlp)
 {  {
         unsigned socksize, ifasize;          unsigned socksize, ifasize;
         int addrlen, namelen;          int addrlen, namelen;
         struct sockaddr_dl *mask, *sdl;          struct sockaddr_dl *mask, *sdl;
         struct ifaddr *ifa;          struct ifaddr *ifa;
   
         /*  
          * If the interface already has a link name, release it  
          * now.  This is useful for interfaces that can change  
          * link types, and thus switch link names often.  
          */  
         if (ifp->if_sadl != NULL)  
                 if_free_sadl(ifp);  
   
         namelen = strlen(ifp->if_xname);          namelen = strlen(ifp->if_xname);
         addrlen = ifp->if_addrlen;          addrlen = ifp->if_addrlen;
         socksize = roundup(sockaddr_dl_measure(namelen, addrlen), sizeof(long));          socksize = roundup(sockaddr_dl_measure(namelen, addrlen), sizeof(long));
Line 296  if_alloc_sadl(struct ifnet *ifp)
Line 296  if_alloc_sadl(struct ifnet *ifp)
             ifp->if_xname, namelen, NULL, addrlen);              ifp->if_xname, namelen, NULL, addrlen);
         mask->sdl_len = sockaddr_dl_measure(namelen, 0);          mask->sdl_len = sockaddr_dl_measure(namelen, 0);
         memset(&mask->sdl_data[0], 0xff, namelen);          memset(&mask->sdl_data[0], 0xff, namelen);
           ifa->ifa_rtrequest = link_rtrequest;
           ifa->ifa_addr = (struct sockaddr *)sdl;
           ifa->ifa_netmask = (struct sockaddr *)mask;
   
           *sdlp = sdl;
   
           return ifa;
   }
   
   /*
    * Allocate the link level name for the specified interface.  This
    * is an attachment helper.  It must be called after ifp->if_addrlen
    * is initialized, which may not be the case when if_attach() is
    * called.
    */
   void
   if_alloc_sadl(struct ifnet *ifp)
   {
           struct ifaddr *ifa;
           const struct sockaddr_dl *sdl;
   
           /*
            * If the interface already has a link name, release it
            * now.  This is useful for interfaces that can change
            * link types, and thus switch link names often.
            */
           if (ifp->if_sadl != NULL)
                   if_free_sadl(ifp);
   
           ifa = if_dl_create(ifp, &sdl);
   
         ifnet_addrs[ifp->if_index] = ifa;          ifnet_addrs[ifp->if_index] = ifa;
         IFAREF(ifa);          IFAREF(ifa);
         ifa_insert(ifp, ifa);          ifa_insert(ifp, ifa);
         ifa->ifa_rtrequest = link_rtrequest;          ifp->if_dl = ifa;
         ifa->ifa_addr = (struct sockaddr *)sdl;          IFAREF(ifa);
         ifp->if_sadl = sdl;          ifp->if_sadl = sdl;
         ifa->ifa_netmask = (struct sockaddr *)mask;  
 }  }
   
 /*  /*
Line 320  if_free_sadl(struct ifnet *ifp)
Line 349  if_free_sadl(struct ifnet *ifp)
         ifa = ifnet_addrs[ifp->if_index];          ifa = ifnet_addrs[ifp->if_index];
         if (ifa == NULL) {          if (ifa == NULL) {
                 KASSERT(ifp->if_sadl == NULL);                  KASSERT(ifp->if_sadl == NULL);
                   KASSERT(ifp->if_dl == NULL);
                 return;                  return;
         }          }
   
         KASSERT(ifp->if_sadl != NULL);          KASSERT(ifp->if_sadl != NULL);
           KASSERT(ifp->if_dl != NULL);
   
         s = splnet();          s = splnet();
         rtinit(ifa, RTM_DELETE, 0);          rtinit(ifa, RTM_DELETE, 0);
Line 333  if_free_sadl(struct ifnet *ifp)
Line 364  if_free_sadl(struct ifnet *ifp)
   
         ifnet_addrs[ifp->if_index] = NULL;          ifnet_addrs[ifp->if_index] = NULL;
         IFAFREE(ifa);          IFAFREE(ifa);
           ifp->if_dl = NULL;
           IFAFREE(ifa);
         splx(s);          splx(s);
 }  }
   
Line 1325  ifunit(const char *name)
Line 1358  ifunit(const char *name)
         return NULL;          return NULL;
 }  }
   
   /* common */
   static int
   ifioctl_common(u_long cmd, struct ifnet *ifp, struct ifreq *ifr,
       struct ifcapreq *ifcr, struct ifdatareq *ifdr)
   {
           int s;
   
           switch (cmd) {
           case SIOCSIFCAP:
                   if ((ifcr->ifcr_capenable & ~ifp->if_capabilities) != 0)
                           return EINVAL;
   
                   if (ifcr->ifcr_capenable == ifp->if_capenable)
                           return 0;
   
                   ifp->if_capenable = ifcr->ifcr_capenable;
   
                   /* Pre-compute the checksum flags mask. */
                   ifp->if_csum_flags_tx = 0;
                   ifp->if_csum_flags_rx = 0;
                   if (ifp->if_capenable & IFCAP_CSUM_IPv4_Tx) {
                           ifp->if_csum_flags_tx |= M_CSUM_IPv4;
                   }
                   if (ifp->if_capenable & IFCAP_CSUM_IPv4_Rx) {
                           ifp->if_csum_flags_rx |= M_CSUM_IPv4;
                   }
   
                   if (ifp->if_capenable & IFCAP_CSUM_TCPv4_Tx) {
                           ifp->if_csum_flags_tx |= M_CSUM_TCPv4;
                   }
                   if (ifp->if_capenable & IFCAP_CSUM_TCPv4_Rx) {
                           ifp->if_csum_flags_rx |= M_CSUM_TCPv4;
                   }
   
                   if (ifp->if_capenable & IFCAP_CSUM_UDPv4_Tx) {
                           ifp->if_csum_flags_tx |= M_CSUM_UDPv4;
                   }
                   if (ifp->if_capenable & IFCAP_CSUM_UDPv4_Rx) {
                           ifp->if_csum_flags_rx |= M_CSUM_UDPv4;
                   }
   
                   if (ifp->if_capenable & IFCAP_CSUM_TCPv6_Tx) {
                           ifp->if_csum_flags_tx |= M_CSUM_TCPv6;
                   }
                   if (ifp->if_capenable & IFCAP_CSUM_TCPv6_Rx) {
                           ifp->if_csum_flags_rx |= M_CSUM_TCPv6;
                   }
   
                   if (ifp->if_capenable & IFCAP_CSUM_UDPv6_Tx) {
                           ifp->if_csum_flags_tx |= M_CSUM_UDPv6;
                   }
                   if (ifp->if_capenable & IFCAP_CSUM_UDPv6_Rx) {
                           ifp->if_csum_flags_rx |= M_CSUM_UDPv6;
                   }
                   return ENETRESET;
           case SIOCSIFFLAGS:
                   if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
                           s = splnet();
                           if_down(ifp);
                           splx(s);
                   }
                   if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) {
                           s = splnet();
                           if_up(ifp);
                           splx(s);
                   }
                   ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
                           (ifr->ifr_flags &~ IFF_CANTCHANGE);
                   break;
           case SIOCGIFFLAGS:
                   ifr->ifr_flags = ifp->if_flags;
                   break;
   
           case SIOCGIFMETRIC:
                   ifr->ifr_metric = ifp->if_metric;
                   break;
   
           case SIOCGIFMTU:
                   ifr->ifr_mtu = ifp->if_mtu;
                   break;
   
           case SIOCGIFDLT:
                   ifr->ifr_dlt = ifp->if_dlt;
                   break;
   
           case SIOCGIFCAP:
                   ifcr->ifcr_capabilities = ifp->if_capabilities;
                   ifcr->ifcr_capenable = ifp->if_capenable;
                   break;
   
           case SIOCSIFMETRIC:
                   ifp->if_metric = ifr->ifr_metric;
                   break;
   
           case SIOCGIFDATA:
                   ifdr->ifdr_data = ifp->if_data;
                   break;
   
           case SIOCZIFDATA:
                   ifdr->ifdr_data = ifp->if_data;
                   /*
                    * Assumes that the volatile counters that can be
                    * zero'ed are at the end of if_data.
                    */
                   memset(&ifp->if_data.ifi_ipackets, 0, sizeof(ifp->if_data) -
                       offsetof(struct if_data, ifi_ipackets));
                   break;
           default:
                   return EOPNOTSUPP;
           }
           return 0;
   }
   
 /*  /*
  * Interface ioctls.   * Interface ioctls.
  */   */
Line 1427  ifioctl(struct socket *so, u_long cmd, v
Line 1573  ifioctl(struct socket *so, u_long cmd, v
         oif_flags = ifp->if_flags;          oif_flags = ifp->if_flags;
         switch (cmd) {          switch (cmd) {
   
         case SIOCGIFFLAGS:  
                 ifr->ifr_flags = ifp->if_flags;  
                 break;  
   
         case SIOCGIFMETRIC:  
                 ifr->ifr_metric = ifp->if_metric;  
                 break;  
   
         case SIOCGIFMTU:  
                 ifr->ifr_mtu = ifp->if_mtu;  
                 break;  
   
         case SIOCGIFDLT:  
                 ifr->ifr_dlt = ifp->if_dlt;  
                 break;  
   
         case SIOCSIFFLAGS:          case SIOCSIFFLAGS:
                 if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {                  ifioctl_common(cmd, ifp, ifr, NULL, NULL);
                         s = splnet();  
                         if_down(ifp);  
                         splx(s);  
                 }  
                 if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) {  
                         s = splnet();  
                         if_up(ifp);  
                         splx(s);  
                 }  
                 ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |  
                         (ifr->ifr_flags &~ IFF_CANTCHANGE);  
                 if (ifp->if_ioctl)                  if (ifp->if_ioctl)
                         (void)(*ifp->if_ioctl)(ifp, cmd, data);                          (void)(*ifp->if_ioctl)(ifp, cmd, data);
                 break;                  break;
   
         case SIOCGIFCAP:  
                 ifcr->ifcr_capabilities = ifp->if_capabilities;  
                 ifcr->ifcr_capenable = ifp->if_capenable;  
                 break;  
   
         case SIOCSIFCAP:          case SIOCSIFCAP:
                 if ((ifcr->ifcr_capenable & ~ifp->if_capabilities) != 0)  
                         return EINVAL;  
                 if (ifp->if_ioctl == NULL)                  if (ifp->if_ioctl == NULL)
                         return EOPNOTSUPP;                          return EOPNOTSUPP;
   
                 /* Must prevent race with packet reception here. */                  /* Must prevent race with packet reception here. */
                 s = splnet();                  s = splnet();
                 if (ifcr->ifcr_capenable != ifp->if_capenable) {                  error = ifioctl_common(cmd, ifp, NULL, ifcr, NULL);
                   if (error != ENETRESET)
                           ;
                   else if (ifp->if_flags & IFF_UP) {
                         struct ifreq ifrq;                          struct ifreq ifrq;
   
                         ifrq.ifr_flags = ifp->if_flags;                          ifrq.ifr_flags = ifp->if_flags;
                         ifp->if_capenable = ifcr->ifcr_capenable;  
   
                         /* Pre-compute the checksum flags mask. */  
                         ifp->if_csum_flags_tx = 0;  
                         ifp->if_csum_flags_rx = 0;  
                         if (ifp->if_capenable & IFCAP_CSUM_IPv4_Tx) {  
                                 ifp->if_csum_flags_tx |= M_CSUM_IPv4;  
                         }  
                         if (ifp->if_capenable & IFCAP_CSUM_IPv4_Rx) {  
                                 ifp->if_csum_flags_rx |= M_CSUM_IPv4;  
                         }  
   
                         if (ifp->if_capenable & IFCAP_CSUM_TCPv4_Tx) {  
                                 ifp->if_csum_flags_tx |= M_CSUM_TCPv4;  
                         }  
                         if (ifp->if_capenable & IFCAP_CSUM_TCPv4_Rx) {  
                                 ifp->if_csum_flags_rx |= M_CSUM_TCPv4;  
                         }  
   
                         if (ifp->if_capenable & IFCAP_CSUM_UDPv4_Tx) {  
                                 ifp->if_csum_flags_tx |= M_CSUM_UDPv4;  
                         }  
                         if (ifp->if_capenable & IFCAP_CSUM_UDPv4_Rx) {  
                                 ifp->if_csum_flags_rx |= M_CSUM_UDPv4;  
                         }  
   
                         if (ifp->if_capenable & IFCAP_CSUM_TCPv6_Tx) {  
                                 ifp->if_csum_flags_tx |= M_CSUM_TCPv6;  
                         }  
                         if (ifp->if_capenable & IFCAP_CSUM_TCPv6_Rx) {  
                                 ifp->if_csum_flags_rx |= M_CSUM_TCPv6;  
                         }  
   
                         if (ifp->if_capenable & IFCAP_CSUM_UDPv6_Tx) {  
                                 ifp->if_csum_flags_tx |= M_CSUM_UDPv6;  
                         }  
                         if (ifp->if_capenable & IFCAP_CSUM_UDPv6_Rx) {  
                                 ifp->if_csum_flags_rx |= M_CSUM_UDPv6;  
                         }  
   
                         /*                          /*
                          * Only kick the interface if it's up.  If it's                           * Only kick the interface if it's up.  If it's
                          * not up now, it will notice the cap enables                           * not up now, it will notice the cap enables
                          * when it is brought up later.                           * when it is brought up later.
                          */                           */
                         if (ifp->if_flags & IFF_UP)                          (void)(*ifp->if_ioctl)(ifp, SIOCSIFFLAGS,
                                 (void)(*ifp->if_ioctl)(ifp, SIOCSIFFLAGS,                              (void *)&ifrq);
                                     (void *)&ifrq);                          error = 0;
                 }                  }
                 splx(s);                  splx(s);
                 break;  
   
         case SIOCSIFMETRIC:  
                 ifp->if_metric = ifr->ifr_metric;  
                 break;  
   
         case SIOCGIFDATA:  
                 ifdr->ifdr_data = ifp->if_data;  
                 break;  
   
         case SIOCZIFDATA:  
                 ifdr->ifdr_data = ifp->if_data;  
                 /*  
                  * Assumes that the volatile counters that can be  
                  * zero'ed are at the end of if_data.  
                  */  
                 memset(&ifp->if_data.ifi_ipackets, 0, sizeof(ifp->if_data) -  
                     offsetof(struct if_data, ifi_ipackets));  
                 break;                  break;
   
         case SIOCSIFMTU:          case SIOCSIFMTU:
Line 1590  ifioctl(struct socket *so, u_long cmd, v
Line 1648  ifioctl(struct socket *so, u_long cmd, v
                 error = (*ifp->if_ioctl)(ifp, cmd, data);                  error = (*ifp->if_ioctl)(ifp, cmd, data);
                 break;                  break;
   
         case SIOCSDRVSPEC:  
         default:          default:
                   error = ifioctl_common(cmd, ifp, ifr, ifcr, ifdr);
                   if (error != EOPNOTSUPP)
                           break;
                 if (so->so_proto == NULL)                  if (so->so_proto == NULL)
                         return EOPNOTSUPP;                          return EOPNOTSUPP;
 #ifdef COMPAT_OSOCK  #ifdef COMPAT_OSOCK

Legend:
Removed from v.1.208  
changed lines
  Added in v.1.208.4.2

CVSweb <webmaster@jp.NetBSD.org>