1/* 2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * The contents of this file constitute Original Code as defined in and 7 * are subject to the Apple Public Source License Version 1.1 (the 8 * "License"). You may not use this file except in compliance with the 9 * License. Please obtain a copy of the License at 10 * http://www.apple.com/publicsource and read it before using this file. 11 * 12 * This Original Code and all software distributed under the License are 13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 * License for the specific language governing rights and limitations 18 * under the License. 19 * 20 * @APPLE_LICENSE_HEADER_END@ 21 */ 22 23#ifndef INET 24#define INET 1 25#endif 26 27extern "C"{ 28#include <sys/param.h> 29#include <sys/kernel.h> 30#include <sys/queue.h> 31#include <sys/sysctl.h> 32#include <sys/systm.h> 33#include <sys/mbuf.h> 34#include <sys/malloc.h> 35#include <sys/socket.h> 36#include <sys/syslog.h> 37 38#include <net/if.h> 39#include <net/if_dl.h> 40#include <net/if_types.h> 41#include <net/route.h> 42#include <net/dlil.h> 43#include <net/if_llc.h> 44#if BRIDGE 45#include <net/ethernet.h> 46#include <net/bridge.h> 47#endif 48 49#include <netinet/in.h> 50#include <netinet/in_var.h> 51#include <netinet/in_arp.h> 52} 53 54extern "C" 55{ 56#include "firewire.h" 57#include "if_firewire.h" 58} 59#include "IOFireWireIP.h" 60 61void firewire_arpintr __P((mbuf_t m)); 62u_char *firewire_sprintf __P((register u_char *p, register u_char *ap)); 63static void inet_firewire_arp_input __P((mbuf_t m)); 64 65//////////////////////////////////////////////////////////////////////////////// 66// 67// firewire_arpintr 68// 69// IN: register mbuf_t m 70// 71// Invoked by : 72// inet_firewire_input in firewire_inet_pr_module.c and it will be called from 73// the context of dlil_input_thread queue 74// 75// Common length and type checks are done here, then the protocol-specific 76// routine is called. 77// 78//////////////////////////////////////////////////////////////////////////////// 79void 80firewire_arpintr(register mbuf_t m) 81{ 82 if (m == 0 || (mbuf_flags(m) & MBUF_PKTHDR) == 0) 83 panic("arpintr"); 84 85 inet_firewire_arp_input(m); 86} 87 88#if INET 89errno_t 90firewire_inet_arp( 91 ifnet_t ifp, 92 u_short arpop, 93 const struct sockaddr_dl* sender_hw, 94 const struct sockaddr* sender_proto, 95 const struct sockaddr_dl* target_hw, 96 const struct sockaddr* target_proto) 97{ 98 mbuf_t m; 99 errno_t result; 100 register struct firewire_header *fwh; 101 register IP1394_ARP *fwa; 102 const struct sockaddr_in* sender_ip = (const struct sockaddr_in*)sender_proto; 103 const struct sockaddr_in* target_ip = (const struct sockaddr_in*)target_proto; 104 char *datap; 105 106 IOFWInterface *fwIf = (IOFWInterface*)ifnet_softc(ifp); 107 108 if(fwIf == NULL) 109 return EINVAL; 110 111 IOFireWireIP *fwIpObj = (IOFireWireIP*)fwIf->getController(); 112 113 if(fwIpObj == NULL) 114 return EINVAL; 115 116 LCB *lcb = fwIpObj->getLcb(); 117 118 if (target_ip == NULL) 119 return EINVAL; 120 121 if ((sender_ip && sender_ip->sin_family != AF_INET) || 122 (target_ip && target_ip->sin_family != AF_INET)) 123 return EAFNOSUPPORT; 124 125 result = mbuf_gethdr(MBUF_DONTWAIT, MBUF_TYPE_DATA, &m); 126 if (result != 0) 127 return result; 128 129 mbuf_setlen(m, sizeof(*fwa)); 130 mbuf_pkthdr_setlen(m, sizeof(*fwa)); 131 132 /* Move the data pointer in the mbuf to the end, aligned to 4 bytes */ 133 datap = (char*)mbuf_datastart(m); 134 datap += mbuf_trailingspace(m); 135 datap -= (((u_long)datap) & 0x3); 136 mbuf_setdata(m, datap, sizeof(*fwa)); 137 fwa = (IP1394_ARP*)mbuf_data(m); 138 bzero((caddr_t)fwa, sizeof(*fwa)); 139 140 /* Prepend the ethernet header, we will send the raw frame */ 141 result = mbuf_prepend(&m, sizeof(*fwh), MBUF_DONTWAIT); 142 if(result != 0) 143 return result; 144 145 fwh = (struct firewire_header*)mbuf_data(m); 146 fwh->fw_type = htons(FWTYPE_ARP); 147 148 /* Fill out the arp packet */ 149 fwa->hardwareType = htons(ARP_HDW_TYPE); 150 fwa->protocolType = htons(FWTYPE_IP); 151 fwa->hwAddrLen = sizeof(IP1394_HDW_ADDR); 152 fwa->ipAddrLen = IPV4_ADDR_SIZE; 153 fwa->opcode = htons(arpop); 154 fwa->senderMaxRec = lcb->ownHardwareAddress.maxRec; 155 fwa->sspd = lcb->ownHardwareAddress.spd; 156 fwa->senderUnicastFifoHi = htons(lcb->ownHardwareAddress.unicastFifoHi); 157 fwa->senderUnicastFifoLo = htonl(lcb->ownHardwareAddress.unicastFifoLo); 158 159 /* Sender Hardware */ 160 if (sender_hw != NULL) 161 bcopy(CONST_LLADDR(sender_hw), &fwa->senderUniqueID, sizeof(fwa->senderUniqueID)); 162 else 163 ifnet_lladdr_copy_bytes(ifp, &fwa->senderUniqueID, FIREWIRE_ADDR_LEN); 164 165 ifnet_lladdr_copy_bytes(ifp, fwh->fw_shost, sizeof(fwh->fw_shost)); 166 167 /* Sender IP */ 168 if (sender_ip != NULL) 169 fwa->senderIpAddress = sender_ip->sin_addr.s_addr; 170 else 171 { 172 ifaddr_t *addresses; 173 struct sockaddr sa; 174 175 if (ifnet_get_address_list_family(ifp, &addresses, AF_INET) == 0) 176 { 177 ifaddr_address( addresses[0], &sa, 16 ); 178 fwa->senderIpAddress = ((UInt32)(sa.sa_data[5] & 0xFF)) << 24; 179 fwa->senderIpAddress |= ((UInt32)(sa.sa_data[4] & 0xFF)) << 16; 180 fwa->senderIpAddress |= ((UInt32)(sa.sa_data[3] & 0xFF)) << 8; 181 fwa->senderIpAddress |= ((UInt32)(sa.sa_data[2] & 0xFF)); 182 183 ifnet_free_address_list(addresses); 184 } 185 else 186 { 187 mbuf_free(m); 188 return ENXIO; 189 } 190 } 191 192 /* Target Hardware */ 193 if (target_hw == 0) 194 bcopy(fwbroadcastaddr, fwh->fw_dhost, sizeof(fwh->fw_dhost)); 195 else 196 bcopy(CONST_LLADDR(target_hw), fwh->fw_dhost, sizeof(fwh->fw_dhost)); 197 198 /* Target IP */ 199 fwa->targetIpAddress = target_ip->sin_addr.s_addr; 200 201 ifnet_output_raw(ifp, PF_INET, m); 202 203 return 0; 204} 205 206//////////////////////////////////////////////////////////////////////////////// 207// 208// in_firewire_arp_input 209// 210// IN: register struct mbuf *m 211// 212// Invoked by : 213// firewire_arpintr calls it from the context of dlil_input_thread queue 214// 215// ARP for Internet protocols on 10 Mb/s Ethernet. 216// Algorithm is that given in RFC 826. 217// In addition, a sanity check is performed on the sender 218// protocol address, to catch impersonators. 219// We no longer handle negotiations for use of trailer protocol: 220// Formerly, ARP replied for protocol type ETHERTYPE_TRAIL sent 221// along with IP replies if we wanted trailers sent to us, 222// and also sent them in response to IP replies. 223// This allowed either end to announce the desire to receive trailer packets. 224// We no longer reply to requests for ETHERTYPE_TRAIL protocol either, 225// but formerly didn't normally send requests. 226// 227//////////////////////////////////////////////////////////////////////////////// 228static void 229inet_firewire_arp_input( 230 mbuf_t m) 231{ 232 IP1394_ARP *fwa; 233 struct sockaddr_dl sender_hw; 234 struct sockaddr_in sender_ip; 235 struct sockaddr_in target_ip; 236 237 ifnet_t ifp = mbuf_pkthdr_rcvif((mbuf_t)m); 238 239 IOFWInterface *fwIf = (IOFWInterface*)ifnet_softc(ifp); 240 241 if(fwIf == NULL) 242 return; 243 244 IOFireWireIP *fwIpObj = (IOFireWireIP*)fwIf->getController(); 245 246 if(fwIpObj == NULL) 247 return; 248 249 if (mbuf_len(m) < (int)sizeof(IP1394_ARP) && 250 mbuf_pullup(&m, sizeof(IP1394_ARP)) != 0) 251 return; 252 253 fwa = (IP1394_ARP*)mbuf_data(m); 254 255 // Verify this is an firewire/ip arp and address lengths are correct 256 if (fwa->hardwareType != htons(ARP_HDW_TYPE) || fwa->protocolType != htons(FWTYPE_IP) 257 || fwa->hwAddrLen != sizeof(IP1394_HDW_ADDR) || fwa->ipAddrLen != IPV4_ADDR_SIZE) 258 { 259 mbuf_free(m); 260 return; 261 } 262 263 bzero(&sender_ip, sizeof(sender_ip)); 264 sender_ip.sin_len = sizeof(sender_ip); 265 sender_ip.sin_family = AF_INET; 266 sender_ip.sin_addr.s_addr = fwa->senderIpAddress; 267 target_ip = sender_ip; 268 target_ip.sin_addr.s_addr = fwa->targetIpAddress; 269 270 bzero(&sender_hw, sizeof(sender_hw)); 271 sender_hw.sdl_len = sizeof(sender_hw); 272 sender_hw.sdl_family = AF_LINK; 273 sender_hw.sdl_type = IFT_IEEE1394; 274 sender_hw.sdl_alen = FIREWIRE_ADDR_LEN; 275 bcopy(&fwa->senderUniqueID, LLADDR(&sender_hw), FIREWIRE_ADDR_LEN); 276 277 if(fwIpObj->arpCacheHandler(fwa)) 278 inet_arp_handle_input(ifp, ntohs(fwa->opcode), &sender_hw, &sender_ip, &target_ip); 279 280 mbuf_free((mbuf_t)m); 281} 282 283void 284firewire_inet_event( 285 ifnet_t ifp, 286 __unused protocol_family_t protocol, 287 const struct kev_msg *event) 288{ 289 ifaddr_t *addresses; 290 291 if (event->vendor_code != KEV_VENDOR_APPLE || 292 event->kev_class != KEV_NETWORK_CLASS || 293 event->kev_subclass != KEV_DL_SUBCLASS || 294 event->event_code != KEV_DL_LINK_ADDRESS_CHANGED) 295 return; 296 297 if (ifnet_get_address_list_family(ifp, &addresses, AF_INET) == 0) 298 { 299 int i; 300 301 for (i = 0; addresses[i] != NULL; i++) 302 inet_arp_init_ifaddr(ifp, addresses[i]); 303 304 ifnet_free_address_list(addresses); 305 } 306} 307#endif 308 309/* 310 * Convert Ethernet address to printable (loggable) representation. 311 */ 312static u_char digits[] = "0123456789abcdef"; 313u_char * 314firewire_sprintf(register u_char *p, register u_char *ap) 315{ 316 register u_char *cp; 317 register int i; 318 319 for (cp = p, i = 0; i < 8; i++) { 320 *cp++ = digits[*ap >> 4]; 321 *cp++ = digits[*ap++ & 0xf]; 322 *cp++ = ':'; 323 } 324 *--cp = 0; 325 return (p); 326} 327