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/malloc.h> 31#include <sys/mbuf.h> 32#include <sys/socket.h> 33#include <sys/sockio.h> 34#include <net/dlil.h> 35#include <sys/sysctl.h> 36#include <sys/systm.h> 37#include <sys/syslog.h> 38 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 <sys/kpi_mbuf.h> /* For MBUF_LOOP */ 45 46#include <sys/socketvar.h> 47 48#include <net/dlil.h> 49 50#include "firewire.h" 51#include <if_firewire.h> 52} 53#include "IOFireWireIP.h" 54 55struct fw_desc { 56 u_int16_t type; /* Type of protocol stored in data */ 57 u_long protocol_family; /* Protocol family */ 58 u_long data[2]; /* Protocol data */ 59}; 60 61#define FIREWIRE_DESC_BLK_SIZE (10) 62 63// 64// Statics for demux module 65// 66struct firewire_desc_blk_str { 67 u_long n_max_used; 68 u_long n_count; 69 u_long n_used; 70 struct fw_desc block_ptr[1]; 71}; 72/* Size of the above struct before the array of struct fw_desc */ 73#define FIREWIRE_DESC_HEADER_SIZE ((size_t)&(((struct firewire_desc_blk_str*)0)->block_ptr[0])) 74 75static ifnet_t loop_ifp; 76 77 78//////////////////////////////////////////////////////////////////////////////// 79// 80// firewire_del_proto 81// 82// IN: ifnet_t ifp, u_long protocol_family 83// 84// Invoked by : 85// dlil_detach_protocol calls this funcion 86// 87// Release all descriptor entries owned by this ifp/protocol_family (there may be several). 88// Setting the type to 0 releases the entry. Eventually we should compact-out 89// the unused entries. 90// 91//////////////////////////////////////////////////////////////////////////////// 92__private_extern__ 93int firewire_del_proto(ifnet_t ifp, protocol_family_t protocol_family) 94{ 95 IOFWInterface *fwIf = (IOFWInterface*)ifnet_softc(ifp); 96 97 if(fwIf == NULL) 98 return EINVAL; 99 100 struct firewire_desc_blk_str *desc_blk = (struct firewire_desc_blk_str *)fwIf->getFamilyCookie(); 101 102 if (desc_blk == NULL) 103 return EINVAL; 104 105 int found = 0; 106 107 for (u_long current = desc_blk->n_max_used; current > 0; current--) 108 { 109 if (desc_blk->block_ptr[current - 1].protocol_family == protocol_family) 110 { 111 found = 1; 112 desc_blk->block_ptr[current - 1].type = 0; 113 desc_blk->n_used--; 114 } 115 } 116 117 if (desc_blk->n_used == 0) 118 { 119 FREE(fwIf->getFamilyCookie(), M_IFADDR); 120 fwIf->setFamilyCookie(NULL); 121 } 122 else 123 { 124 /* Decrement n_max_used */ 125 for (; desc_blk->n_max_used > 0 && desc_blk->block_ptr[desc_blk->n_max_used - 1].type == 0; desc_blk->n_max_used--) 126 ; 127 } 128 129 return found; 130 } 131 132//////////////////////////////////////////////////////////////////////////////// 133// 134// firewire_add_proto 135// 136// IN: ifnet_t ifp, u_long protocol_family, struct ddesc_head_str *desc_head 137// 138// Invoked by : 139// dlil_attach_protocol calls this funcion 140// 141// 142//////////////////////////////////////////////////////////////////////////////// 143__private_extern__ int 144firewire_add_proto_internal(ifnet_t ifp, u_long protocol_family, const struct ifnet_demux_desc *demux) 145{ 146 IOFWInterface *fwIf = (IOFWInterface*)ifnet_softc(ifp); 147 148 if(fwIf == NULL) 149 return EINVAL; 150 151 struct firewire_desc_blk_str *desc_blk = (struct firewire_desc_blk_str *)fwIf->getFamilyCookie(); 152 153 struct fw_desc *ed; 154 u_long i; 155 156 switch (demux->type) 157 { 158 case DLIL_DESC_ETYPE2: 159 if (demux->datalen != 2) 160 return EINVAL; 161 break; 162 163 default: 164 return EOPNOTSUPP; 165 } 166 167 // Check for case where all of the descriptor blocks are in use 168 if (desc_blk == NULL || desc_blk->n_used == desc_blk->n_count) 169 { 170 struct firewire_desc_blk_str *tmp; 171 u_long new_count = FIREWIRE_DESC_BLK_SIZE; 172 u_long new_size; 173 u_long old_size = 0; 174 175 i = 0; 176 if (desc_blk) 177 { 178 new_count += desc_blk->n_count; 179 old_size = desc_blk->n_count * sizeof(struct fw_desc) + FIREWIRE_DESC_HEADER_SIZE; 180 i = desc_blk->n_used; 181 } 182 183 new_size = new_count * sizeof(struct fw_desc) + FIREWIRE_DESC_HEADER_SIZE; 184 185 tmp = (struct firewire_desc_blk_str*)_MALLOC(new_size, M_IFADDR, MBUF_WAITOK); 186 if (tmp == 0) 187 return ENOMEM; 188 189 bzero(tmp + old_size, new_size - old_size); 190 if (desc_blk) 191 { 192 bcopy(desc_blk, tmp, old_size); 193 FREE(desc_blk, M_IFADDR); 194 } 195 desc_blk = tmp; 196 fwIf->setFamilyCookie(desc_blk); 197 desc_blk->n_count = new_count; 198 } 199 else 200 { 201 // Find a free entry 202 for (i = 0; i < desc_blk->n_count; i++) 203 { 204 if (desc_blk->block_ptr[i].type == 0) 205 break; 206 } 207 } 208 209 // Bump n_max_used if appropriate 210 if (i + 1 > desc_blk->n_max_used) { 211 desc_blk->n_max_used = i + 1; 212 } 213 214 ed = &desc_blk->block_ptr[i]; 215 ed->protocol_family = protocol_family; 216 ed->data[0] = 0; 217 ed->data[1] = 0; 218 219 switch (demux->type) { 220 case DLIL_DESC_ETYPE2: 221 /* 2 byte ethernet raw protocol type is at native_type */ 222 /* prtocol must be in network byte order */ 223 ed->type = DLIL_DESC_ETYPE2; 224 ed->data[0] = *(u_int16_t*)demux->data; 225 break; 226 } 227 228 desc_blk->n_used++; 229 230 return 0; 231} 232 233int 234firewire_add_proto(ifnet_t ifp, protocol_family_t protocol, const struct ifnet_demux_desc *demux_list, u_int32_t demux_count) 235{ 236 int error = 0; 237 u_int32_t i; 238 239 for (i = 0; i < demux_count; i++) 240 { 241 error = firewire_add_proto_internal(ifp, protocol, &demux_list[i]); 242 if (error) 243 { 244 firewire_del_proto(ifp, protocol); 245 break; 246 } 247 } 248 249 return error; 250} 251 252//////////////////////////////////////////////////////////////////////////////// 253// 254// firewire_demux 255// 256// IN: ifnet_t ifp,struct mbuf *m,char *frame_header, 257// u_long *protocol_family 258// 259// Invoked by : 260// dlil_input_packet() 261// 262//////////////////////////////////////////////////////////////////////////////// 263__private_extern__ int firewire_demux(ifnet_t ifp, mbuf_t m, char *frame_header, protocol_family_t *protocol_family) 264{ 265 register struct firewire_header *eh = (struct firewire_header *)frame_header; 266 267 IOFWInterface *fwIf = (IOFWInterface*)ifnet_softc(ifp); 268 269 if(fwIf == NULL) 270 return EINVAL; 271 272 struct firewire_desc_blk_str *desc_blk = (struct firewire_desc_blk_str *)fwIf->getFamilyCookie(); 273 274 if (desc_blk == NULL) 275 return EINVAL; 276 277 u_short fw_type = eh->fw_type; 278 u_int16_t type = DLIL_DESC_ETYPE2; 279 u_long maxd = desc_blk->n_max_used; 280 struct fw_desc *ed = desc_blk->block_ptr; 281 282 /* 283 * Search through the connected protocols for a match. 284 */ 285 for (u_long i = 0; i < maxd; i++) 286 { 287 if ((ed[i].type == type) && (ed[i].data[0] == fw_type)) 288 { 289 *protocol_family = ed[i].protocol_family; 290 return 0; 291 } 292 } 293 294 return ENOENT; 295} 296 297//////////////////////////////////////////////////////////////////////////////// 298// 299// firewire_frameout 300// 301// IN: ifnet_t ifp,struct mbuf **m 302// IN: struct sockaddr *ndest - contains the destination IP Address 303// IN: char *edst - filled by firewire_arpresolve function in if_firewire.c 304// IN: char *fw_type 305// 306// Invoked by : 307// dlil.c for dlil_output, Its called after inet_firewire_pre_output 308// 309// Encapsulate a packet of type family for the local net. 310// Use trailer local net encapsulation if enough data in first 311// packet leaves a multiple of 512 bytes of data in remainder. 312// 313//////////////////////////////////////////////////////////////////////////////// 314__private_extern__ int 315firewire_frameout(ifnet_t ifp, mbuf_t *m, 316 const struct sockaddr *ndest, const char *edst, const char *fw_type) 317{ 318 register struct firewire_header *fwh; 319 320 /* 321 * If a simplex interface, and the packet is being sent to our 322 * Ethernet address or a broadcast address, loopback a copy. 323 * XXX To make a simplex device behave exactly like a duplex 324 * device, we should copy in the case of sending to our own 325 * ethernet address (thus letting the original actually appear 326 * on the wire). However, we don't do that here for security 327 * reasons and compatibility with the original behavior. 328 */ 329 330 if ((ifnet_flags(ifp) & IFF_SIMPLEX) && 331 (mbuf_flags(*m) & MBUF_LOOP)) 332 { 333 if (loop_ifp == NULL) { 334 ifnet_find_by_name("lo0", &loop_ifp); 335 336 /* 337 * We make an assumption here that lo0 will never go away. This 338 * means we don't have to worry about releasing the reference 339 * later and we don't have to worry about leaking a reference 340 * every time we are loaded. 341 */ 342 ifnet_release(loop_ifp); 343 } 344 345 if (loop_ifp) 346 { 347 if (mbuf_flags(*m) & MBUF_BCAST) 348 { 349 mbuf_t n; 350 351 if (mbuf_copym(*m, 0, MBUF_COPYALL, MBUF_WAITOK, &n) == 0) 352 ifnet_output(loop_ifp, PF_INET, n, 0, ndest); 353 } 354 else 355 { 356 if (bcmp(edst, ifnet_lladdr(ifp), FIREWIRE_ADDR_LEN) == 0) 357 { 358 ifnet_output(loop_ifp, PF_INET, *m, 0, ndest); 359 return EJUSTRETURN; 360 } 361 } 362 } 363 } 364 365 // 366 // Add local net header. If no space in first mbuf, 367 // allocate another. 368 // 369 if (mbuf_prepend(m, sizeof(struct firewire_header), MBUF_DONTWAIT) != 0) 370 return (EJUSTRETURN); 371 372 // 373 // Lets put this intelligent here into the mbuf 374 // so we can demux on our output path 375 // 376 fwh = (struct firewire_header*)mbuf_data(*m); 377 (void)memcpy(&fwh->fw_type, fw_type,sizeof(fwh->fw_type)); 378 memcpy(fwh->fw_dhost, edst, FIREWIRE_ADDR_LEN); 379 (void)memcpy(fwh->fw_shost, ifnet_lladdr(ifp), sizeof(fwh->fw_shost)); 380 381 return 0; 382} 383 384//////////////////////////////////////////////////////////////////////////////// 385// 386// firewire_add_if 387// 388// IN: ifnet_t ifp 389// 390//////////////////////////////////////////////////////////////////////////////// 391__private_extern__ 392int firewire_add_if(ifnet_t ifp) 393{ 394 return 0; 395} 396 397//////////////////////////////////////////////////////////////////////////////// 398// 399// firewire_del_if 400// 401// IN: ifnet_t ifp 402// 403// Invoked by : 404// firewire_free calls this function 405// 406//////////////////////////////////////////////////////////////////////////////// 407__private_extern__ 408int firewire_del_if(IOFWInterface *fwIf) 409{ 410 if (fwIf->getFamilyCookie()) { 411 FREE(fwIf->getFamilyCookie(), M_IFADDR); 412 return 0; 413 } 414 else 415 return ENOENT; 416} 417 418//////////////////////////////////////////////////////////////////////////////// 419// 420// firewire_ifmod_ioctl 421// 422// IN: ifnet_t ifp 423// 424// Invoked by : 425// dlil_ioctl calls this function, all ioctls are handled at 426// firewire_inet_prmod_ioctl 427// 428//////////////////////////////////////////////////////////////////////////////// 429__private_extern__ int 430firewire_ifmod_ioctl(ifnet_t ifp, unsigned long cmd, void *data) 431{ 432 int err = EOPNOTSUPP; 433 return err; 434} 435 436__private_extern__ int 437firewire_init_if(ifnet_t ifp) 438{ 439 return 0; 440} 441