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 24#ifndef INET 25#define INET 1 26#endif 27 28extern "C"{ 29#include <sys/param.h> 30#include <sys/systm.h> 31#include <sys/kernel.h> 32#include <sys/malloc.h> 33#include <sys/mbuf.h> 34#include <sys/socket.h> 35#include <sys/sockio.h> 36#include <sys/sysctl.h> 37 38#include <net/dlil.h> 39#include <net/if.h> 40#include <net/route.h> 41#include <net/if_llc.h> 42#include <net/if_dl.h> 43#include <net/if_types.h> 44#include <net/kpi_protocol.h> 45 46#include <netinet/in.h> 47#include <netinet/in_var.h> 48#include <netinet/in_systm.h> 49#include <netinet/ip.h> 50#include <netinet/in_arp.h> 51#include <sys/socketvar.h> 52 53#include "firewire.h" 54#include "if_firewire.h" 55} 56#include "IOFireWireIP.h" 57 58extern void firewire_arpintr __P((mbuf_t m)); 59 60extern errno_t firewire_inet_arp __P((ifnet_t ifp, 61 u_short arpop, 62 const struct sockaddr_dl *sender_hw, 63 const struct sockaddr *sender_proto, 64 const struct sockaddr_dl *target_hw, 65 const struct sockaddr *target_proto)); 66 67extern void firewire_inet_event __P((ifnet_t ifp, 68 __unused protocol_family_t protocol, 69 const struct kev_msg *event)); 70 71//////////////////////////////////////////////////////////////////////////////// 72// 73// inet_firewire_input 74// 75// IN: struct mbuf *m, char *frame_header, ifnet_t ifp, 76// IN: u_long dl_tag, int sync_ok 77// 78// Invoked by : 79// It will be called from the context of dlil_input_thread queue from 80// dlil_input_packet 81// 82// Process a received firewire ARP/IP packet, the packet is in the mbuf 83// chain m 84// 85//////////////////////////////////////////////////////////////////////////////// 86static errno_t 87inet_firewire_input( 88 __unused ifnet_t ifp, 89 __unused protocol_family_t protocol_family, 90 mbuf_t m, 91 char *frame_header) 92{ 93 struct firewire_header *eh = (struct firewire_header *)frame_header; 94 u_short fw_type; 95 96 ifnet_touch_lastchange(ifp); 97 98 fw_type = ntohs(eh->fw_type); 99 100 switch (fw_type) 101 { 102 case FWTYPE_IP: 103 { 104 mbuf_pullup(&m, sizeof(struct ip)); 105 if (m == NULL) 106 return EJUSTRETURN; 107 108 errno_t ret = proto_input(PF_INET, m); 109 110 if( ret ) 111 mbuf_freem(m); 112 113 return ret; 114 } 115 116 case FWTYPE_ARP: 117 firewire_arpintr(m); 118 break; 119 120 default: 121 return ENOENT; 122 } 123 124 return 0; 125} 126 127//////////////////////////////////////////////////////////////////////////////// 128// 129// inet_firewire_pre_output 130// 131// IN: ifnet_t ifp 132// IN: struct mbuf **m0 133// IN: struct sockaddr dst_netaddr 134// IN: caddr_t route 135// OUT: char *type 136// OUT: char *edst 137// IN: u_long dl_tag 138// 139// Invoked by : 140// Invoked by dlil.c for dlil_output=>(*proto)->dl_pre_output=> 141// inet_firewire_pre_output=> 142// 143// Process a received firewire ARP/IP packet, the packet is in the mbuf 144// chain m 145// 146//////////////////////////////////////////////////////////////////////////////// 147int 148inet_firewire_pre_output( 149 ifnet_t interface, 150 __unused protocol_family_t protocol_family, 151 mbuf_t *m0, 152 const struct sockaddr *dst_netaddr, 153 void* route, 154 char *type, 155 char *edst) 156{ 157 mbuf_t m = *m0; 158 errno_t result = 0; 159 160 if ((ifnet_flags(interface) & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) 161 return ENETDOWN; 162 163 // Tell firewire_frameout it's ok to loop packet unless negated below. 164 mbuf_setflags(m, mbuf_flags(m) | MBUF_LOOP); 165 166 switch (dst_netaddr->sa_family) 167 { 168 case AF_INET: 169 { 170 struct sockaddr_dl ll_dest; 171 result = inet_arp_lookup(interface, (const struct sockaddr_in*)dst_netaddr, 172 &ll_dest, sizeof(ll_dest), (route_t)route, *m0); 173 if (result == 0) 174 { 175 bcopy(LLADDR(&ll_dest), edst, FIREWIRE_ADDR_LEN); 176 *(u_int16_t*)type = htons(FWTYPE_IP); 177 } 178 } 179 break; 180 181 case AF_UNSPEC: 182 { 183 mbuf_setflags(m, mbuf_flags(m) & ~MBUF_LOOP); 184 register struct firewire_header *fwh = (struct firewire_header *)dst_netaddr->sa_data; 185 (void)memcpy(edst, fwh->fw_dhost, FIREWIRE_ADDR_LEN); 186 *(u_short *)type = fwh->fw_type; 187 } 188 break; 189 190 default: 191 return EAFNOSUPPORT; 192 } 193 194 return result; 195} 196 197//////////////////////////////////////////////////////////////////////////////// 198// 199// firewire_inet_prmod_ioctl 200// 201// IN: ifnet_t ifp 202// IN: unsigned long command 203// IN: caddr_t data 204// 205// Invoked by : 206// Invoked by dlil.c for dlil_output=>(*proto)->dl_pre_output=> 207// inet_firewire_pre_output=> 208// 209// Process an ioctl from dlil_ioctl in the context of ip, i guess !! 210// 211//////////////////////////////////////////////////////////////////////////////// 212static errno_t 213firewire_inet_prmod_ioctl( 214 __unused ifnet_t ifp, 215 __unused protocol_family_t protocol_family, 216 __unused unsigned long command, 217 __unused void* data) 218{ 219 return EOPNOTSUPP; 220} 221 222static errno_t 223firewire_inet_resolve_multi( 224 ifnet_t ifp, 225 const struct sockaddr *proto_addr, 226 struct sockaddr_dl *out_ll, 227 size_t ll_len) 228{ 229 static const size_t minsize = offsetof(struct sockaddr_dl, sdl_data[0]) + FIREWIRE_ADDR_LEN; 230 const struct sockaddr_in *sin = (const struct sockaddr_in*)proto_addr; 231 232 if (proto_addr->sa_family != AF_INET) 233 return EAFNOSUPPORT; 234 235 if (proto_addr->sa_len < sizeof(struct sockaddr_in)) 236 return EINVAL; 237 238 if (ll_len < minsize) 239 return EMSGSIZE; 240 241 bzero(out_ll, minsize); 242 out_ll->sdl_len = minsize; 243 out_ll->sdl_family = AF_LINK; 244 out_ll->sdl_index = ifnet_index(ifp); 245 out_ll->sdl_type = IFT_IEEE1394; 246 out_ll->sdl_nlen = 0; 247 out_ll->sdl_alen = FIREWIRE_ADDR_LEN; 248 out_ll->sdl_slen = 0; 249 FIREWIRE_MAP_IP_MULTICAST(&sin->sin_addr, LLADDR(out_ll)); 250 251 return 0; 252} 253 254//////////////////////////////////////////////////////////////////////////////// 255// 256// firewire_attach_inet 257// 258// IN: ifnet_t ifp 259// 260// Invoked by: 261// firewire_attach_inet will be invoked from IOFWInterface::attachToDataLinkLayer 262// 263//////////////////////////////////////////////////////////////////////////////// 264int 265firewire_attach_inet(ifnet_t ifp, protocol_family_t protocol_family) 266{ 267 struct ifnet_attach_proto_param proto; 268 struct ifnet_demux_desc demux[2]; 269 u_short en_native=htons(FWTYPE_IP); 270 u_short arp_native=htons(FWTYPE_ARP); 271 errno_t error; 272 273 bzero(&demux[0], sizeof(demux)); 274 demux[0].type = DLIL_DESC_ETYPE2; 275 demux[0].data = &en_native; 276 demux[0].datalen = sizeof(en_native); 277 demux[1].type = DLIL_DESC_ETYPE2; 278 demux[1].data = &arp_native; 279 demux[1].datalen = sizeof(arp_native); 280 281 bzero(&proto, sizeof(proto)); 282 proto.demux_list = demux; 283 proto.demux_count = sizeof(demux) / sizeof(demux[0]); 284 proto.input = inet_firewire_input; 285 proto.pre_output = inet_firewire_pre_output; 286 proto.ioctl = firewire_inet_prmod_ioctl; 287 proto.event = firewire_inet_event; 288 proto.resolve = firewire_inet_resolve_multi; 289 proto.send_arp = firewire_inet_arp; 290 291 error = ifnet_attach_protocol(ifp, protocol_family, &proto); 292 if (error && error != EEXIST) 293 { 294 printf("WARNING: firewire_attach_inet can't attach ip to %s%d\n", 295 ifnet_name(ifp), ifnet_unit(ifp)); 296 } 297 298 return error; 299}