/* * Copyright (c) 2000-2012 Apple, Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * * 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. * * 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, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* * Copyright 1994 Apple Computer, Inc. * All Rights Reserved. * * Tuyen A. Nguyen. (December 5, 1994) * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define DSAP_SNAP 0xaa extern int adspInited; static llc_header_t snap_hdr_at = SNAP_HDR_AT; static llc_header_t snap_hdr_aarp = SNAP_HDR_AARP; static unsigned char snap_proto_ddp[5] = SNAP_PROTO_AT; static unsigned char snap_proto_aarp[5] = SNAP_PROTO_AARP; static void at_input_packet(protocol_family_t protocol, mbuf_t m); struct ifqueue atalkintrq; /* appletalk and aarp packet input queue */ short appletalk_inited = 0; void atalk_load(void); void atalk_unload(void); extern int pktsIn, pktsOut; void atalk_load() { atp_init(); atp_link(); adspInited = 0; /* adsp_init(); for 2225395 this happens in adsp_open and is undone on ADSP_UNLINK */ domain_proto_mtx_unlock(TRUE); proto_register_input(PF_APPLETALK, at_input_packet, NULL, 0); domain_proto_mtx_lock(); } /* atalk_load */ /* Undo everything atalk_load() did. */ void atalk_unload() /* not currently used */ { atp_unlink(); #ifdef NOT_YET { extern gbuf_t *scb_resource_m; extern gbuf_t *atp_resource_m; if (scb_resource_m) { gbuf_freem(scb_resource_m); scb_resource_m = 0; scb_free_list = 0; } /* allocated in atp_trans_alloc() */ if (atp_resource_m) { gbuf_freem(atp_resource_m); atp_resource_m = 0; atp_trans_free_list = 0; } } #endif appletalk_inited = 0; } /* atalk_unload */ void appletalk_hack_start(void) { if (!appletalk_inited) { atalk_load(); atalkintrq.ifq_maxlen = IFQ_MAXLEN; appletalk_inited = 1; } } /* appletalk_hack_start */ int pat_output(patp, mlist, dst_addr, type) at_ifaddr_t *patp; struct mbuf *mlist; /* packet chain */ unsigned char *dst_addr; /* for atalk addr - net # must be in network byte order */ int type; { struct mbuf *m, *m1; llc_header_t *llc_header; struct sockaddr dst; if (! patp->aa_ifp) { for (m = mlist; m; m = mlist) { mlist = m->m_nextpkt; m->m_nextpkt = 0; m_freem(m); } return ENOTREADY; } /* this is for ether_output */ dst.sa_family = AF_APPLETALK; dst.sa_len = 2 + sizeof(struct etalk_addr); bcopy (dst_addr, &dst.sa_data[0], sizeof(struct etalk_addr)); /* packet chains are used on output and can be tested using aufs */ for (m = mlist; m; m = mlist) { mlist = m->m_nextpkt; m->m_nextpkt = 0; M_PREPEND(m, sizeof(llc_header_t), M_DONTWAIT); if (m == 0) { continue; } llc_header = mtod(m, llc_header_t *); *llc_header = (type == AARP_AT_TYPE) ? snap_hdr_aarp : snap_hdr_at; for (m->m_pkthdr.len = 0, m1 = m; m1; m1 = m1->m_next) m->m_pkthdr.len += m1->m_len; m->m_pkthdr.rcvif = 0; /* *** Note: AT is sending out mbufs of type MSG_DATA, not MT_DATA. *** */ #ifdef APPLETALK_DEBUG if (m->m_next && !((m->m_next)->m_flags & M_EXT)) kprintf("po: mlen= %d, m2len= %d\n", m->m_len, (m->m_next)->m_len); #endif atalk_unlock(); dlil_output(patp->aa_ifp, PF_APPLETALK, m, NULL, &dst, 0, NULL); atalk_lock(); pktsOut++; } return 0; } /* pat_output */ static void at_input_packet( __unused protocol_family_t protocol, mbuf_t m) { struct mbuf *m1; struct ifnet *ifp; llc_header_t *llc_header; at_ifaddr_t *ifID; char src[6]; enet_header_t *enet_header; if (!appletalk_inited) { m_freem(m); return; } if ((m->m_flags & M_PKTHDR) == 0) { #ifdef APPLETALK_DEBUG kprintf("atalkintr: no HDR on packet received"); #endif m_freem(m); return; } /* make sure the interface this packet was received on is configured for AppleTalk */ ifp = m->m_pkthdr.rcvif; TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) { if (ifID->aa_ifp && (ifID->aa_ifp == ifp)) break; } /* if we didn't find a matching interface */ if (!ifID) { m_freem(m); return; /* was EAFNOSUPPORT */ } /* make sure the entire packet header is in the current mbuf */ if (m->m_len < ENET_LLC_SIZE && (m = m_pullup(m, ENET_LLC_SIZE)) == 0) { #ifdef APPLETALK_DEBUG kprintf("atalkintr: packet too small\n"); #endif m_freem(m); return; } enet_header = mtod(m, enet_header_t *); /* Ignore multicast packets from local station */ /* *** Note: code for IFTYPE_TOKENTALK may be needed here. *** */ if (ifID->aa_ifp->if_type == IFT_ETHER || ifID->aa_ifp->if_type == IFT_L2VLAN || ifID->aa_ifp->if_type == IFT_IEEE8023ADLAG) { bcopy((char *)enet_header->src, src, sizeof(src)); #ifdef COMMENT /* In order to receive packets from the Blue Box, we cannot reject packets whose source address matches our local address. */ if ((enet_header->dst[0] & 1) && (bcmp(src, ifID->xaddr, sizeof(src)) == 0)) { /* Packet rejected: think it's a local mcast. */ m_freem(m); return; /* was EAFNOSUPPORT */ } #endif /* COMMENT */ llc_header = (llc_header_t *)(enet_header+1); /* advance the mbuf pointers past the ethernet header */ m->m_data += ENET_LLC_SIZE; m->m_len -= ENET_LLC_SIZE; pktsIn++; if (LLC_PROTO_EQUAL(llc_header->protocol,snap_proto_aarp)) { (void)aarp_rcv_pkt(mtod(m, aarp_pkt_t *), ifID); m_freem(m); } else if (LLC_PROTO_EQUAL(llc_header->protocol, snap_proto_ddp)) { /* if we're a router take all pkts */ if (!ROUTING_MODE) { if (aarp_chk_addr(mtod(m, at_ddp_t *), ifID) == AARP_ERR_NOT_OURS) { #ifdef APPLETALK_DEBUG kprintf("pat_input: Packet Rejected: not for us? dest=%x.%x.%x.%x.%x.%x LLC_PROTO= %02x%02x\n", enet_header->dst[0], enet_header->dst[1], enet_header->dst[2], enet_header->dst[3], enet_header->dst[4], enet_header->dst[5], llc_header->protocol[3], llc_header->protocol[4]); #endif m_freem(m); return; /* was EAFNOSUPPORT */ } } MCHTYPE(m, MSG_DATA); /* set the mbuf type */ ifID->stats.rcv_packets++; for (m1 = m; m1; m1 = m1->m_next) ifID->stats.rcv_bytes += m1->m_len; if (!MULTIPORT_MODE) ddp_glean(m, ifID, (struct etalk_addr *)src); ddp_input(m, ifID); } else { #ifdef APPLETALK_DEBUG kprintf("pat_input: Packet Rejected: wrong LLC_PROTO = %02x%02x\n", llc_header->protocol[3], llc_header->protocol[4]); #endif m_freem(m); } } }