1/* 2 * Copyright (c) 2000-2012 Apple, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* 29 * Copyright 1994 Apple Computer, Inc. 30 * All Rights Reserved. 31 * 32 * Tuyen A. Nguyen. (December 5, 1994) 33 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX. 34 */ 35 36#include <sys/errno.h> 37#include <sys/types.h> 38#include <sys/param.h> 39#include <machine/spl.h> 40#include <sys/systm.h> 41#include <sys/kernel.h> 42#include <sys/proc.h> 43#include <sys/filedesc.h> 44#include <sys/fcntl.h> 45#include <sys/mbuf.h> 46#include <sys/ioctl.h> 47#include <sys/malloc.h> 48#include <sys/socket.h> 49#include <sys/socketvar.h> 50#include <sys/sockio.h> 51 52#include <net/if.h> 53#include <net/if_types.h> 54#include <net/if_dl.h> 55#include <net/dlil.h> 56#include <net/ethernet.h> 57#include <net/kpi_protocol.h> 58 59#include <netat/sysglue.h> 60#include <netat/appletalk.h> 61#include <netat/at_pcb.h> 62#include <netat/at_var.h> 63#include <netat/ddp.h> 64#include <netat/at_aarp.h> 65#include <netat/at_pat.h> 66#include <netat/atp.h> 67#include <netat/debug.h> 68 69#define DSAP_SNAP 0xaa 70 71extern int adspInited; 72 73static llc_header_t snap_hdr_at = SNAP_HDR_AT; 74static llc_header_t snap_hdr_aarp = SNAP_HDR_AARP; 75static unsigned char snap_proto_ddp[5] = SNAP_PROTO_AT; 76static unsigned char snap_proto_aarp[5] = SNAP_PROTO_AARP; 77 78static void at_input_packet(protocol_family_t protocol, mbuf_t m); 79 80struct ifqueue atalkintrq; /* appletalk and aarp packet input queue */ 81 82short appletalk_inited = 0; 83 84void atalk_load(void); 85void atalk_unload(void); 86 87extern int pktsIn, pktsOut; 88 89 90void atalk_load() 91{ 92 atp_init(); 93 atp_link(); 94 adspInited = 0; 95 96/* adsp_init(); 97 for 2225395 98 this happens in adsp_open and is undone on ADSP_UNLINK 99*/ 100 domain_proto_mtx_unlock(TRUE); 101 proto_register_input(PF_APPLETALK, at_input_packet, NULL, 0); 102 domain_proto_mtx_lock(); 103} /* atalk_load */ 104 105/* Undo everything atalk_load() did. */ 106void atalk_unload() /* not currently used */ 107{ 108 atp_unlink(); 109 110#ifdef NOT_YET 111 { 112 extern gbuf_t *scb_resource_m; 113 extern gbuf_t *atp_resource_m; 114 if (scb_resource_m) { 115 gbuf_freem(scb_resource_m); 116 scb_resource_m = 0; 117 scb_free_list = 0; 118 } 119 /* allocated in atp_trans_alloc() */ 120 if (atp_resource_m) { 121 gbuf_freem(atp_resource_m); 122 atp_resource_m = 0; 123 atp_trans_free_list = 0; 124 } 125 } 126#endif 127 128 appletalk_inited = 0; 129} /* atalk_unload */ 130 131void appletalk_hack_start(void) 132{ 133 if (!appletalk_inited) { 134 atalk_load(); 135 atalkintrq.ifq_maxlen = IFQ_MAXLEN; 136 appletalk_inited = 1; 137 } 138} /* appletalk_hack_start */ 139 140int pat_output(patp, mlist, dst_addr, type) 141 at_ifaddr_t *patp; 142 struct mbuf *mlist; /* packet chain */ 143 unsigned char *dst_addr; /* for atalk addr - net # must be in network byte order */ 144 int type; 145{ 146 struct mbuf *m, *m1; 147 llc_header_t *llc_header; 148 struct sockaddr dst; 149 150 if (! patp->aa_ifp) { 151 for (m = mlist; m; m = mlist) { 152 mlist = m->m_nextpkt; 153 m->m_nextpkt = 0; 154 m_freem(m); 155 } 156 return ENOTREADY; 157 } 158 159 /* this is for ether_output */ 160 dst.sa_family = AF_APPLETALK; 161 dst.sa_len = 2 + sizeof(struct etalk_addr); 162 bcopy (dst_addr, &dst.sa_data[0], sizeof(struct etalk_addr)); 163 164 /* packet chains are used on output and can be tested using aufs */ 165 for (m = mlist; m; m = mlist) { 166 mlist = m->m_nextpkt; 167 m->m_nextpkt = 0; 168 169 M_PREPEND(m, sizeof(llc_header_t), M_DONTWAIT); 170 if (m == 0) { 171 continue; 172 } 173 174 llc_header = mtod(m, llc_header_t *); 175 *llc_header = 176 (type == AARP_AT_TYPE) ? snap_hdr_aarp : snap_hdr_at; 177 178 for (m->m_pkthdr.len = 0, m1 = m; m1; m1 = m1->m_next) 179 m->m_pkthdr.len += m1->m_len; 180 m->m_pkthdr.rcvif = 0; 181 182 /* *** Note: AT is sending out mbufs of type MSG_DATA, 183 not MT_DATA. *** */ 184#ifdef APPLETALK_DEBUG 185 if (m->m_next && 186 !((m->m_next)->m_flags & M_EXT)) 187 kprintf("po: mlen= %d, m2len= %d\n", m->m_len, 188 (m->m_next)->m_len); 189#endif 190 atalk_unlock(); 191 dlil_output(patp->aa_ifp, PF_APPLETALK, m, NULL, &dst, 0, NULL); 192 atalk_lock(); 193 194 pktsOut++; 195 } 196 197 return 0; 198} /* pat_output */ 199 200static void 201at_input_packet( 202 __unused protocol_family_t protocol, 203 mbuf_t m) 204{ 205 struct mbuf *m1; 206 struct ifnet *ifp; 207 llc_header_t *llc_header; 208 at_ifaddr_t *ifID; 209 char src[6]; 210 enet_header_t *enet_header; 211 212 if (!appletalk_inited) { 213 m_freem(m); 214 return; 215 } 216 217 if ((m->m_flags & M_PKTHDR) == 0) { 218#ifdef APPLETALK_DEBUG 219 kprintf("atalkintr: no HDR on packet received"); 220#endif 221 m_freem(m); 222 return; 223 } 224 225 /* make sure the interface this packet was received on is configured 226 for AppleTalk */ 227 ifp = m->m_pkthdr.rcvif; 228 TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) { 229 if (ifID->aa_ifp && (ifID->aa_ifp == ifp)) 230 break; 231 } 232 /* if we didn't find a matching interface */ 233 if (!ifID) { 234 m_freem(m); 235 return; /* was EAFNOSUPPORT */ 236 } 237 238 /* make sure the entire packet header is in the current mbuf */ 239 if (m->m_len < ENET_LLC_SIZE && 240 (m = m_pullup(m, ENET_LLC_SIZE)) == 0) { 241#ifdef APPLETALK_DEBUG 242 kprintf("atalkintr: packet too small\n"); 243#endif 244 m_freem(m); 245 return; 246 } 247 enet_header = mtod(m, enet_header_t *); 248 249 /* Ignore multicast packets from local station */ 250 /* *** Note: code for IFTYPE_TOKENTALK may be needed here. *** */ 251 if (ifID->aa_ifp->if_type == IFT_ETHER || 252 ifID->aa_ifp->if_type == IFT_L2VLAN || 253 ifID->aa_ifp->if_type == IFT_IEEE8023ADLAG) { 254 bcopy((char *)enet_header->src, src, sizeof(src)); 255 256#ifdef COMMENT /* In order to receive packets from the Blue Box, we cannot 257 reject packets whose source address matches our local address. 258 */ 259 if ((enet_header->dst[0] & 1) && 260 (bcmp(src, ifID->xaddr, sizeof(src)) == 0)) { 261 /* Packet rejected: think it's a local mcast. */ 262 m_freem(m); 263 return; /* was EAFNOSUPPORT */ 264 } 265#endif /* COMMENT */ 266 267 llc_header = (llc_header_t *)(enet_header+1); 268 269 /* advance the mbuf pointers past the ethernet header */ 270 m->m_data += ENET_LLC_SIZE; 271 m->m_len -= ENET_LLC_SIZE; 272 273 pktsIn++; 274 275 if (LLC_PROTO_EQUAL(llc_header->protocol,snap_proto_aarp)) { 276 (void)aarp_rcv_pkt(mtod(m, aarp_pkt_t *), ifID); 277 m_freem(m); 278 } 279 else if (LLC_PROTO_EQUAL(llc_header->protocol, snap_proto_ddp)) { 280 /* if we're a router take all pkts */ 281 if (!ROUTING_MODE) { 282 if (aarp_chk_addr(mtod(m, at_ddp_t *), ifID) 283 == AARP_ERR_NOT_OURS) { 284#ifdef APPLETALK_DEBUG 285 kprintf("pat_input: Packet Rejected: not for us? dest=%x.%x.%x.%x.%x.%x LLC_PROTO= %02x%02x\n", 286 enet_header->dst[0], enet_header->dst[1], 287 enet_header->dst[2], enet_header->dst[3], 288 enet_header->dst[4], enet_header->dst[5], 289 llc_header->protocol[3], 290 llc_header->protocol[4]); 291#endif 292 m_freem(m); 293 return; /* was EAFNOSUPPORT */ 294 } 295 } 296 MCHTYPE(m, MSG_DATA); /* set the mbuf type */ 297 298 ifID->stats.rcv_packets++; 299 for (m1 = m; m1; m1 = m1->m_next) 300 ifID->stats.rcv_bytes += m1->m_len; 301 302 if (!MULTIPORT_MODE) 303 ddp_glean(m, ifID, (struct etalk_addr *)src); 304 305 ddp_input(m, ifID); 306 } else { 307#ifdef APPLETALK_DEBUG 308 kprintf("pat_input: Packet Rejected: wrong LLC_PROTO = %02x%02x\n", 309 llc_header->protocol[3], 310 llc_header->protocol[4]); 311#endif 312 m_freem(m); 313 } 314 } 315} 316