*
* @APPLE_LICENSE_HEADER_START@
*
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License"). You may not use this file except in compliance with the
- * License. Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
+ * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
*
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
#include <net/if_dl.h>
#include <net/if_types.h>
#include <netinet/if_ether.h>
+#include <netinet/in.h> /* For M_LOOP */
/*
#if INET
*/
#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;
-static ivedonethis = 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 */
}
ed[i].proto = proto;
- ed[i].data[0] = 0;
+ ed[i].data[0] = 0;
ed[i].data[1] = 0;
switch (desc->type) {
case DLIL_DESC_SNAP: {
u_int8_t* pDest = ((u_int8_t*)&ed[i].data[0]) + 3;
ed[i].type = DLIL_DESC_SNAP;
- bcopy(&desc->native_type, pDest, 5);
+ bcopy(desc->native_type, pDest, 5);
}
break;
}
{
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;
}
+__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 (EINVAL);
+ }
+ sdl = (struct sockaddr_dl *)ifa->ifa_addr;
+ sdl->sdl_type = IFT_ETHER;
+ sdl->sdl_alen = ifp->if_addrlen;
+ bcopy((IFP2AC(ifp))->ac_enaddr, LLADDR(sdl), ifp->if_addrlen);
+
+ return 0;
+}
int
}
+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);
- if (ivedonethis)
- return 0;
-
- ivedonethis = 1;
+ /* ethernet family is built-in, called from bsd_init */
+ thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
+ bzero(&ifmod_reg, sizeof(ifmod_reg));
ifmod_reg.add_if = ether_add_if;
ifmod_reg.del_if = ether_del_if;
+ ifmod_reg.init_if = ether_init_if;
ifmod_reg.add_proto = ether_add_proto;
ifmod_reg.del_proto = ether_del_proto;
ifmod_reg.ifmod_ioctl = ether_ifmod_ioctl;
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;
- return 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 (error);
}