/*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000,2009 Apple Inc. All rights reserved.
*
- * @APPLE_LICENSE_HEADER_START@
+ * @APPLE_OSREFERENCE_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.
+ * 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. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
*
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * 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@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/*
* Copyright (c) 1982, 1989, 1993
#include <sys/sysctl.h>
#include <net/if.h>
-#include <net/netisr.h>
#include <net/route.h>
#include <net/if_llc.h>
#include <net/if_dl.h>
#include <net/if_types.h>
#include <netinet/if_ether.h>
+#include <net/kpi_interface.h>
+#include <net/kpi_protocol.h>
#include <sys/socketvar.h>
#endif
-#if BRIDGE
-#include <net/bridge.h>
-#endif
-
/* #include "vlan.h" */
#if NVLAN > 0
#include <net/if_vlan_var.h>
#endif /* NVLAN > 0 */
-static
-u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-
-#define IFP2AC(IFP) ((struct arpcom *)IFP)
-
-
-struct dl_es_at_entry
-{
- struct ifnet *ifp;
- u_long dl_tag;
- int ref_count;
-};
-
-
-/*
- * Temp static for protocol registration XXX
- */
-
-#define MAX_EN_COUNT 30
-
-static struct dl_es_at_entry en_at_array[MAX_EN_COUNT];
+#include <net/ether_if_module.h>
/*
* Process a received Ethernet packet;
* the packet is in the mbuf chain m without
* the ether header, which is provided separately.
*/
-int
-at_ether_input(m, frame_header, ifp, dl_tag, sync_ok)
- struct mbuf *m;
- char *frame_header;
- struct ifnet *ifp;
- u_long dl_tag;
- int sync_ok;
-
+static errno_t
+ether_at_input(
+ __unused ifnet_t ifp,
+ __unused protocol_family_t protocol_family,
+ mbuf_t m,
+ __unused char *frame_header)
{
- register struct ether_header *eh = (struct ether_header *) frame_header;
- register struct ifqueue *inq=0;
- u_short ether_type;
- int s;
- u_int16_t ptype = -1;
- unsigned char buf[18];
-
-#if NETAT
- register struct llc *l;
-#endif
-
- if ((ifp->if_flags & IFF_UP) == 0) {
- m_freem(m);
- return EJUSTRETURN;
- }
-
- ifp->if_lastchange = time;
-
- if (eh->ether_dhost[0] & 1) {
- if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
- sizeof(etherbroadcastaddr)) == 0)
- m->m_flags |= M_BCAST;
- else
- m->m_flags |= M_MCAST;
- }
- if (m->m_flags & (M_BCAST|M_MCAST))
- ifp->if_imcasts++;
-
- ether_type = ntohs(eh->ether_type);
-
-#if NVLAN > 0
- if (ether_type == vlan_proto) {
- if (vlan_input(eh, m) < 0)
- ifp->if_data.ifi_noproto++;
- return EJUSTRETURN;
- }
-#endif /* NVLAN > 0 */
-
- if (ether_type > ETHERMTU)
- return ENOENT;
-
-#if NETAT
- l = mtod(m, struct llc *);
-
- switch (l->llc_dsap) {
- case LLC_SNAP_LSAP:
-
- /* Temporary hack: check for AppleTalk and AARP packets */
- /* WARNING we're checking only on the "ether_type" (the 2 bytes
- * of the SNAP header. This shouldn't be a big deal,
- * AppleTalk pat_input is making sure we have the right packets
- * because it needs to discrimante AARP from EtherTalk packets.
- */
-
- if (l->llc_ssap == LLC_SNAP_LSAP &&
- l->llc_un.type_snap.control == 0x03) {
-
-#ifdef APPLETALK_DEBUG
- printf("new_ether_input: SNAP Cntrol type=0x%x Src=%s\n",
- l->llc_un.type_snap.ether_type,
- ether_sprintf(buf, &eh->ether_shost));
- printf(" Dst=%s\n",
- ether_sprintf(buf, &eh->ether_dhost));
-#endif /* APPLETALK_DEBUG */
-
- if ((l->llc_un.type_snap.ether_type == 0x809B) ||
- (l->llc_un.type_snap.ether_type == 0x80F3)) {
-
-
- /*
- * note: for AppleTalk we need to pass the enet header of the
- * packet up stack. To do so, we made sure in that the FULL packet
- * is copied in the mbuf by the mace driver, and only the m_data and
- * length have been shifted to make IP and the other guys happy.
- */
-
- m->m_data -= sizeof(*eh);
- m->m_len += sizeof(*eh);
- m->m_pkthdr.len += sizeof(*eh);
-#ifdef APPLETALK_DEBUG
- l == (struct llc *)(eh+1);
- if (l->llc_un.type_snap.ether_type == 0x80F3) {
- kprintf("new_ether_input: RCV AppleTalk type=0x%x Src=%s\n",
- l->llc_un.type_snap.ether_type,
- ether_sprintf(buf, &eh->ether_shost));
- kprintf(" Dst=%s\n",
- ether_sprintf(buf, &eh->ether_dhost));
- }
-#endif /* APPLETALK_DEBUG */
- schednetisr(NETISR_APPLETALK);
- inq = &atalkintrq ;
-
- break;
- }
- }
-
- break;
-
-
- default:
- return ENOENT;
- }
-
+ errno_t error;
+ /*
+ * note: for AppleTalk we need to pass the enet header of the
+ * packet up stack. To do so, we made sure in that the FULL packet
+ * is copied in the mbuf by the driver, and only the m_data and
+ * length have been shifted to make IP and the other guys happy.
+ */
- if (inq == 0)
- return ENOENT;
+ m->m_data -= sizeof(struct ether_header);
+ m->m_len += sizeof(struct ether_header);
+ m->m_pkthdr.len += sizeof(struct ether_header);
- s = splimp();
- if (IF_QFULL(inq)) {
- IF_DROP(inq);
+ error = proto_input(PF_APPLETALK, m);
+
+ if (error)
m_freem(m);
- splx(s);
- return EJUSTRETURN;
- } else
- IF_ENQUEUE(inq, m);
- splx(s);
- return 0;
-#else
- return ENOENT;
-#endif /* NETAT */
+
+ return error;
}
-int
-ether_pre_output(ifp, m0, dst_netaddr, route, type, edst, dl_tag )
- struct ifnet *ifp;
- struct mbuf **m0;
- struct sockaddr *dst_netaddr;
- caddr_t route;
- char *type;
- char *edst;
- u_long dl_tag;
+static errno_t
+ether_at_pre_output(
+ ifnet_t ifp,
+ __unused protocol_family_t protocol_family,
+ mbuf_t *m0,
+ const struct sockaddr *dst_netaddr,
+ __unused void *route,
+ char *type,
+ char *edst)
{
- int s;
- register struct mbuf *m = *m0;
- register struct rtentry *rt;
- register struct ether_header *eh;
- int off, len = m->m_pkthdr.len;
- int hlen; /* link layer header lenght */
- struct arpcom *ac = IFP2AC(ifp);
+ struct mbuf *m = *m0;
+ const struct ether_header *eh;
+ int hlen; /* link layer header length */
+ if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
+ return ENETDOWN;
+ hlen = ETHER_HDR_LEN;
- if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
- return ENETDOWN;
-
- hlen = ETHER_HDR_LEN;
-
- /*
- * Tell ether_frameout it's ok to loop packet unless negated below.
- */
- m->m_flags |= M_LOOP;
-
- switch (dst_netaddr->sa_family) {
- case AF_UNSPEC:
- m->m_flags &= ~M_LOOP;
- eh = (struct ether_header *)dst_netaddr->sa_data;
- (void)memcpy(edst, eh->ether_dhost, 6);
- *(u_short *)type = eh->ether_type;
- break;
+ /*
+ * Tell ether_frameout it's ok to loop packet unless negated below.
+ */
+ m->m_flags |= M_LOOP;
+
+ switch (dst_netaddr->sa_family) {
+ case AF_UNSPEC:
+ m->m_flags &= ~M_LOOP;
+ eh = (const struct ether_header *)dst_netaddr->sa_data;
+ (void)memcpy(edst, eh->ether_dhost, 6);
+ *(u_short *)type = eh->ether_type;
+ break;
-
- case AF_APPLETALK:
- {
- eh = (struct ether_header *)dst_netaddr->sa_data;
- bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, 6);
+ case AF_APPLETALK:
+ eh = (const struct ether_header *)dst_netaddr->sa_data;
+ (void)memcpy(edst, eh->ether_dhost, 6);
+ *(u_short *)type = htons(m->m_pkthdr.len);
+ break;
- *(u_short *)type = m->m_pkthdr.len;
- }
- break;
-
-
- default:
- kprintf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
- dst_netaddr->sa_family);
-
- return EAFNOSUPPORT;
- }
-
- return (0);
+ default:
+ printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
+ dst_netaddr->sa_family);
+ return EAFNOSUPPORT;
+ }
+
+ return (0);
}
-
-int
-ether_prmod_ioctl(dl_tag, ifp, command, data)
- u_long dl_tag;
- struct ifnet *ifp;
- int command;
- caddr_t data;
+static errno_t
+ether_at_prmod_ioctl(
+ ifnet_t ifp,
+ __unused protocol_family_t protocol_family,
+ u_int32_t command,
+ void *data)
{
- struct ifaddr *ifa = (struct ifaddr *) data;
- struct ifreq *ifr = (struct ifreq *) data;
+ struct ifreq *ifr = data;
int error = 0;
- boolean_t funnel_state;
- struct arpcom *ac = (struct arpcom *) ifp;
- struct sockaddr_dl *sdl;
- struct sockaddr_in *sin;
- u_char *e_addr;
-
-
- funnel_state = thread_funnel_set(network_flock, TRUE);
switch (command) {
case SIOCSIFADDR:
if ((ifp->if_flags & IFF_RUNNING) == 0) {
- ifp->if_flags |= IFF_UP;
- dlil_ioctl(0, ifp, SIOCSIFFLAGS, (caddr_t) 0);
+ ifnet_set_flags(ifp, IFF_UP, IFF_UP);
+ ifnet_ioctl(ifp, 0, SIOCSIFFLAGS, NULL);
}
break;
case SIOCGIFADDR:
- {
- struct sockaddr *sa;
-
- sa = (struct sockaddr *) & ifr->ifr_data;
- bcopy(IFP2AC(ifp)->ac_enaddr,
- (caddr_t) sa->sa_data, ETHER_ADDR_LEN);
- }
- break;
-
- case SIOCSIFMTU:
- /*
- * Set the interface MTU.
- */
- if (ifr->ifr_mtu > ETHERMTU) {
- error = EINVAL;
- } else {
- ifp->if_mtu = ifr->ifr_mtu;
- }
+ ifnet_lladdr_copy_bytes(ifp, ifr->ifr_addr.sa_data, ETHER_ADDR_LEN);
break;
default:
- return EOPNOTSUPP;
+ error = EOPNOTSUPP;
+ break;
}
-
- (void) thread_funnel_set(network_flock, funnel_state);
-
return (error);
}
-void
-ether_attach_at(struct ifnet *ifp, u_long *at_dl_tag, u_long *aarp_dl_tag)
+__private_extern__ errno_t
+ether_attach_at(
+ ifnet_t ifp,
+ __unused protocol_family_t proto_family)
{
- struct dlil_proto_reg_str reg;
- struct dlil_demux_desc desc;
- struct dlil_demux_desc desc2;
- u_short native = 0; /* 802.2 frames use a length here */
- int stat;
- int first_empty;
- int i;
-
-
- first_empty = MAX_EN_COUNT;
- for (i=0; i < MAX_EN_COUNT; i++) {
- if (en_at_array[i].ifp == 0)
- first_empty = i;
-
- if (en_at_array[i].ifp == ifp) {
- en_at_array[i].ref_count++;
- *at_dl_tag = *aarp_dl_tag = en_at_array[i].dl_tag;
- return;
+ struct ifnet_attach_proto_param proto;
+ struct ifnet_demux_desc demux[2];
+ u_int8_t atalk_snap[5] = {0x08, 0x00, 0x07, 0x80, 0x9b};
+ u_int8_t aarp_snap[5] = {0x00, 0x00, 0x00, 0x80, 0xf3};
+ int error;
+
+ bzero(demux, sizeof(demux));
+ demux[0].type = DLIL_DESC_SNAP;
+ demux[0].data = atalk_snap;
+ demux[0].datalen = sizeof(atalk_snap);
+ demux[1].type = DLIL_DESC_SNAP;
+ demux[1].data = aarp_snap;
+ demux[1].datalen = sizeof(aarp_snap);
+
+ bzero(&proto, sizeof(proto));
+ proto.demux_list = demux;
+ proto.demux_count = sizeof(demux) / sizeof(demux[0]);
+ proto.input = ether_at_input;
+ proto.pre_output = ether_at_pre_output;
+ proto.ioctl = ether_at_prmod_ioctl;
+
+ error = ifnet_attach_protocol(ifp, PF_APPLETALK, &proto);
+ if (error && error != EEXIST) {
+ printf("WARNING: ether_attach_at failed to attach"
+ " AppleTalk to %s%d\n", ifp->if_name, ifp->if_unit);
}
- }
-
- if (first_empty == MAX_EN_COUNT)
- return;
-
- TAILQ_INIT(®.demux_desc_head);
- desc.type = DLIL_DESC_802_2_SNAP;
- desc.variants.desc_802_2_SNAP.dsap = LLC_SNAP_LSAP;
- desc.variants.desc_802_2_SNAP.ssap = LLC_SNAP_LSAP;
- desc.variants.desc_802_2_SNAP.control_code = 0x03;
- desc.variants.desc_802_2_SNAP.org[0] = 0x08;
- desc.variants.desc_802_2_SNAP.org[1] = 0x00;
- desc.variants.desc_802_2_SNAP.org[2] = 0x07;
- desc.variants.desc_802_2_SNAP.protocol_type = 0x809B;
- desc.native_type = NULL;
- TAILQ_INSERT_TAIL(®.demux_desc_head, &desc, next);
- reg.interface_family = ifp->if_family;
- reg.unit_number = ifp->if_unit;
- reg.input = at_ether_input;
- reg.pre_output = ether_pre_output;
- reg.event = 0;
- reg.offer = 0;
- reg.ioctl = ether_prmod_ioctl;
- reg.default_proto = 0;
- reg.protocol_family = PF_APPLETALK;
-
- desc2 = desc;
- desc2.variants.desc_802_2_SNAP.protocol_type = 0x80F3;
- desc2.variants.desc_802_2_SNAP.org[0] = 0;
- desc2.variants.desc_802_2_SNAP.org[1] = 0;
- desc2.variants.desc_802_2_SNAP.org[2] = 0;
-
- TAILQ_INSERT_TAIL(®.demux_desc_head, &desc2, next);
-
- stat = dlil_attach_protocol(®, at_dl_tag);
- if (stat) {
- printf("WARNING: ether_attach_at can't attach at to interface\n");
- return;
- }
-
- *aarp_dl_tag = *at_dl_tag;
-
- en_at_array[first_empty].ifp = ifp;
- en_at_array[first_empty].dl_tag = *at_dl_tag;
- en_at_array[first_empty].ref_count = 1;
-
-} /* ether_attach_at */
-
+ return (error);
+}
-void
-ether_detach_at(struct ifnet *ifp)
+__private_extern__ void
+ether_detach_at(
+ ifnet_t ifp,
+ __unused protocol_family_t proto_family)
{
- int i;
-
- for (i=0; i < MAX_EN_COUNT; i++) {
- if (en_at_array[i].ifp == ifp)
- break;
- }
-
- if (i < MAX_EN_COUNT) {
- if (en_at_array[i].ref_count > 1)
- en_at_array[i].ref_count--;
- else {
- if (en_at_array[i].ref_count == 1) {
- dlil_detach_protocol(en_at_array[i].dl_tag);
- en_at_array[i].ifp = 0;
- }
- }
- }
+ (void)ifnet_detach_protocol(ifp, PF_APPLETALK);
}