]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/net/ether_if_module.c
xnu-517.7.7.tar.gz
[apple/xnu.git] / bsd / net / ether_if_module.c
index 27e9dd8b8ecb6a058fa415beae407360c117dd80..5d47f82b2f5d7dc80183612073ceee79a097d6bc 100644 (file)
 */
 
 #include <sys/socketvar.h>
+#include <net/if_vlan_var.h>
 
 #include <net/dlil.h>
 
+extern int  vlan_demux(struct ifnet * ifp, struct mbuf *, 
+                      char * frame_header, struct if_proto * * proto);
 
 #if LLC && CCITT
 extern struct ifqueue pkintrq;
@@ -104,11 +107,6 @@ extern struct ifqueue atalkintrq;
 #include <net/bridge.h>
 #endif
 
-/* #include "vlan.h" */
-#if NVLAN > 0
-#include <net/if_vlan_var.h>
-#endif /* NVLAN > 0 */
-
 static u_long lo_dlt = 0;
 
 #define IFP2AC(IFP) ((struct arpcom *)IFP)
@@ -136,13 +134,17 @@ struct ether_desc_blk_str {
 static struct ether_desc_blk_str ether_desc_blk[MAX_INTERFACES];
 
 
+/* from if_ethersubr.c */
+int ether_resolvemulti __P((struct ifnet *, struct sockaddr **,
+                                    struct sockaddr *));
+
 /*
  * Release all descriptor entries owned by this dl_tag (there may be several).
  * Setting the type to 0 releases the entry. Eventually we should compact-out
  * the unused entries.
  */
-static
-int  ether_del_proto(struct if_proto *proto, u_long dl_tag)
+__private_extern__ int
+ether_del_proto(struct if_proto *proto, u_long dl_tag)
 {
     struct en_desc*    ed = ether_desc_blk[proto->ifp->family_cookie].block_ptr;
     u_long     current = 0;
@@ -165,7 +167,8 @@ int  ether_del_proto(struct if_proto *proto, u_long dl_tag)
 
 
 
-static int
+
+__private_extern__ int
 ether_add_proto(struct ddesc_head_str *desc_head, struct if_proto *proto, u_long dl_tag)
 {
    char *current_ptr;
@@ -213,7 +216,6 @@ ether_add_proto(struct ddesc_head_str *desc_head, struct if_proto *proto, u_long
                 return EINVAL;
         }
     
-    restart:
         ed = ether_desc_blk[proto->ifp->family_cookie].block_ptr;
         
         /* Find a free entry */
@@ -241,6 +243,7 @@ ether_add_proto(struct ddesc_head_str *desc_head, struct if_proto *proto, u_long
             FREE(ether_desc_blk[proto->ifp->family_cookie].block_ptr, M_IFADDR);
             ether_desc_blk[proto->ifp->family_cookie].n_count = new_count;
             ether_desc_blk[proto->ifp->family_cookie].block_ptr = (struct en_desc*)tmp;
+           ed = ether_desc_blk[proto->ifp->family_cookie].block_ptr;
         }
         
         /* Bump n_max_used if appropriate */
@@ -317,6 +320,7 @@ int ether_demux(ifp, m, frame_header, proto)
 {
     register struct ether_header *eh = (struct ether_header *)frame_header;
     u_short                    ether_type = eh->ether_type;
+    u_short                    ether_type_host;
     u_int16_t          type;
     u_int8_t           *data;
     u_long                     i = 0;
@@ -332,16 +336,37 @@ int ether_demux(ifp, m, frame_header, proto)
             m->m_flags |= M_BCAST;
         else
             m->m_flags |= M_MCAST;
-    }
+    } else {
+        /*
+         * When the driver is put into promiscuous mode we may receive unicast
+         * frames that are not intended for our interfaces.  They are filtered
+         * here to keep them from traveling further up the stack to code that
+         * is not expecting them or prepared to deal with them.  In the near
+         * future, the filtering done here will be moved even further down the
+         * stack into the IONetworkingFamily, preventing even interface
+         * filter NKE's from receiving promiscuous packets.  Please use BPF.
+         */
+        #define ETHER_CMP(x, y) ( ((u_int16_t *) x)[0] != ((u_int16_t *) y)[0] || \
+                                  ((u_int16_t *) x)[1] != ((u_int16_t *) y)[1] || \
+                                  ((u_int16_t *) x)[2] != ((u_int16_t *) y)[2] )
     
+        if (ETHER_CMP(eh->ether_dhost, ((struct arpcom *) ifp)->ac_enaddr)) {
+            m_freem(m);
+            return EJUSTRETURN;
+        }
+    }
+    ether_type_host = ntohs(ether_type);
+    if ((m->m_pkthdr.csum_flags & CSUM_VLAN_TAG_VALID)
+       || ether_type_host == ETHERTYPE_VLAN) {
+       return (vlan_demux(ifp, m, frame_header, proto));
+    }
     data = mtod(m, u_int8_t*);
-    
+
     /*
      * Determine the packet's protocol type and stuff the protocol into
      * longs for quick compares.
      */
-    
-    if (ntohs(ether_type) <= 1500) {
+    if (ether_type_host <= 1500) {
         extProto1 = *(u_int32_t*)data;
         
         // SAP or SNAP
@@ -393,7 +418,7 @@ int ether_demux(ifp, m, frame_header, proto)
     }
     
     return ENOENT;
-}                      
+}
 
 
 
@@ -413,7 +438,7 @@ ether_frameout(ifp, m, ndest, edst, ether_type)
        char                    *ether_type;
 {
        register struct ether_header *eh;
-       int hlen;       /* link layer header lenght */
+       int hlen;       /* link layer header length */
        struct arpcom *ac = IFP2AC(ifp);
 
 
@@ -471,14 +496,17 @@ ether_frameout(ifp, m, ndest, edst, ether_type)
 }
 
 
-static
-int  ether_add_if(struct ifnet *ifp)
+
+__private_extern__ int
+ether_add_if(struct ifnet *ifp)
 {
     u_long  i;
 
     ifp->if_framer = ether_frameout;
     ifp->if_demux  = ether_demux;
     ifp->if_event  = 0;
+    ifp->if_resolvemulti = ether_resolvemulti;
+    ifp->if_nvlans = 0;
 
     for (i=0; i < MAX_INTERFACES; i++)
         if (ether_desc_blk[i].n_count == 0)
@@ -500,8 +528,8 @@ int  ether_add_if(struct ifnet *ifp)
     return 0;
 }
 
-static
-int  ether_del_if(struct ifnet *ifp)
+__private_extern__ int
+ether_del_if(struct ifnet *ifp)
 {
     if ((ifp->family_cookie < MAX_INTERFACES) &&
         (ether_desc_blk[ifp->family_cookie].n_count))
@@ -516,8 +544,8 @@ int  ether_del_if(struct ifnet *ifp)
         return ENOENT;
 }
 
-static
-int  ether_init_if(struct ifnet *ifp)
+__private_extern__ int
+ether_init_if(struct ifnet *ifp)
 {
     register struct ifaddr *ifa;
     register struct sockaddr_dl *sdl;
@@ -525,7 +553,7 @@ int  ether_init_if(struct ifnet *ifp)
     ifa = ifnet_addrs[ifp->if_index - 1];
     if (ifa == 0) {
             printf("ether_ifattach: no lladdr!\n");
-            return;
+            return (EINVAL);
     }
     sdl = (struct sockaddr_dl *)ifa->ifa_addr;
     sdl->sdl_type = IFT_ETHER;
@@ -584,10 +612,16 @@ ether_ifmod_ioctl(ifp, command, data)
 }
 
 
+extern int ether_attach_inet(struct ifnet *ifp, u_long *dl_tag);
+extern int ether_detach_inet(struct ifnet *ifp, u_long dl_tag);
+extern int ether_attach_inet6(struct ifnet *ifp, u_long *dl_tag);
+extern int ether_detach_inet6(struct ifnet *ifp, u_long dl_tag);
 int ether_family_init()
 {
-    int  i;
+    int  i, error=0;
     struct dlil_ifmod_reg_str  ifmod_reg;
+    struct dlil_protomod_reg_str enet_protoreg;
+    extern int vlan_family_init(void);
 
     /* ethernet family is built-in, called from bsd_init */
     thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
@@ -603,13 +637,33 @@ int ether_family_init()
 
     if (dlil_reg_if_modules(APPLE_IF_FAM_ETHERNET, &ifmod_reg)) {
         printf("WARNING: ether_family_init -- Can't register if family modules\n");
-        return EIO;
+        error = EIO;
+       goto done;
     }
 
-    for (i=0; i < MAX_INTERFACES; i++)
-        ether_desc_blk[i].n_count = 0;
 
+    /* Register protocol registration functions */
+    
+    bzero(&enet_protoreg, sizeof(enet_protoreg));
+    enet_protoreg.attach_proto = ether_attach_inet;
+    enet_protoreg.detach_proto = ether_detach_inet;
+    
+    if (error = dlil_reg_proto_module(PF_INET, APPLE_IF_FAM_ETHERNET, &enet_protoreg) != 0) {
+       printf("ether_family_init: dlil_reg_proto_module failed for AF_INET error=%d\n", error);
+       goto done;
+    }
+    
+    enet_protoreg.attach_proto = ether_attach_inet6;
+    enet_protoreg.detach_proto = ether_detach_inet6;
+    
+    if (error = dlil_reg_proto_module(PF_INET6, APPLE_IF_FAM_ETHERNET, &enet_protoreg) != 0) {
+       printf("ether_family_init: dlil_reg_proto_module failed for AF_INET6 error=%d\n", error);
+       goto done;
+    }
+    vlan_family_init();
+
+ done:
     thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
 
-    return 0;
+    return (error);
 }