*/
#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;
#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)
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;
-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;
return EINVAL;
}
- restart:
ed = ether_desc_blk[proto->ifp->family_cookie].block_ptr;
/* Find a free entry */
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 */
{
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;
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
}
return ENOENT;
-}
+}
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);
}
-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)
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))
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;
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;
}
+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);
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);
}