/* * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.1 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This 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 OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ #ifndef INET #define INET 1 #endif extern "C"{ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "firewire.h" #include "if_firewire.h" } #include "IOFireWireIP.h" extern void firewire_arpintr __P((mbuf_t m)); extern errno_t firewire_inet_arp __P((ifnet_t ifp, u_short arpop, const struct sockaddr_dl *sender_hw, const struct sockaddr *sender_proto, const struct sockaddr_dl *target_hw, const struct sockaddr *target_proto)); extern void firewire_inet_event __P((ifnet_t ifp, __unused protocol_family_t protocol, const struct kev_msg *event)); //////////////////////////////////////////////////////////////////////////////// // // inet_firewire_input // // IN: struct mbuf *m, char *frame_header, ifnet_t ifp, // IN: u_long dl_tag, int sync_ok // // Invoked by : // It will be called from the context of dlil_input_thread queue from // dlil_input_packet // // Process a received firewire ARP/IP packet, the packet is in the mbuf // chain m // //////////////////////////////////////////////////////////////////////////////// static errno_t inet_firewire_input( __unused ifnet_t ifp, __unused protocol_family_t protocol_family, mbuf_t m, char *frame_header) { struct firewire_header *eh = (struct firewire_header *)frame_header; u_short fw_type; ifnet_touch_lastchange(ifp); fw_type = ntohs(eh->fw_type); switch (fw_type) { case FWTYPE_IP: mbuf_pullup(&m, sizeof(struct ip)); if (m == NULL) return EJUSTRETURN; return proto_input(PF_INET, m); case FWTYPE_ARP: firewire_arpintr(m); break; default: return ENOENT; } return 0; } //////////////////////////////////////////////////////////////////////////////// // // inet_firewire_pre_output // // IN: ifnet_t ifp // IN: struct mbuf **m0 // IN: struct sockaddr dst_netaddr // IN: caddr_t route // OUT: char *type // OUT: char *edst // IN: u_long dl_tag // // Invoked by : // Invoked by dlil.c for dlil_output=>(*proto)->dl_pre_output=> // inet_firewire_pre_output=> // // Process a received firewire ARP/IP packet, the packet is in the mbuf // chain m // //////////////////////////////////////////////////////////////////////////////// int inet_firewire_pre_output( ifnet_t interface, __unused protocol_family_t protocol_family, mbuf_t *m0, const struct sockaddr *dst_netaddr, void* route, char *type, char *edst) { struct mbuf* m = (struct mbuf*)*m0; errno_t result = 0; if ((ifnet_flags(interface) & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) return ENETDOWN; // Tell firewire_frameout it's ok to loop packet unless negated below. m->m_flags |= M_LOOP; switch (dst_netaddr->sa_family) { case AF_INET: { struct sockaddr_dl ll_dest; result = inet_arp_lookup(interface, (const struct sockaddr_in*)dst_netaddr, &ll_dest, sizeof(ll_dest), (route_t)route, *m0); if (result == 0) { bcopy(LLADDR(&ll_dest), edst, FIREWIRE_ADDR_LEN); *(u_int16_t*)type = htons(FWTYPE_IP); } } break; case AF_UNSPEC: { m->m_flags &= ~M_LOOP; register struct firewire_header *fwh = (struct firewire_header *)dst_netaddr->sa_data; (void)memcpy(edst, fwh->fw_dhost, FIREWIRE_ADDR_LEN); *(u_short *)type = fwh->fw_type; } break; default: log(LOG_DEBUG,"%s%d: can't handle af%d\n", ifnet_name(interface), ifnet_unit(interface), dst_netaddr->sa_family); return EAFNOSUPPORT; } return result; } //////////////////////////////////////////////////////////////////////////////// // // firewire_inet_prmod_ioctl // // IN: u_long dl_tag // IN: ifnet_t ifp // IN: int command // IN: caddr_t data // // Invoked by : // Invoked by dlil.c for dlil_output=>(*proto)->dl_pre_output=> // inet_firewire_pre_output=> // // Process an ioctl from dlil_ioctl in the context of ip, i guess !! // //////////////////////////////////////////////////////////////////////////////// static errno_t firewire_inet_prmod_ioctl( ifnet_t ifp, __unused protocol_family_t protocol_family, u_int32_t command, void* data) { return EOPNOTSUPP; } static errno_t firewire_inet_resolve_multi( ifnet_t ifp, const struct sockaddr *proto_addr, struct sockaddr_dl *out_ll, size_t ll_len) { static const size_t minsize = offsetof(struct sockaddr_dl, sdl_data[0]) + FIREWIRE_ADDR_LEN; const struct sockaddr_in *sin = (const struct sockaddr_in*)proto_addr; if (proto_addr->sa_family != AF_INET) return EAFNOSUPPORT; if (proto_addr->sa_len < sizeof(struct sockaddr_in)) return EINVAL; if (ll_len < minsize) return EMSGSIZE; bzero(out_ll, minsize); out_ll->sdl_len = minsize; out_ll->sdl_family = AF_LINK; out_ll->sdl_index = ifnet_index(ifp); out_ll->sdl_type = IFT_IEEE1394; out_ll->sdl_nlen = 0; out_ll->sdl_alen = FIREWIRE_ADDR_LEN; out_ll->sdl_slen = 0; FIREWIRE_MAP_IP_MULTICAST(&sin->sin_addr, LLADDR(out_ll)); return 0; } //////////////////////////////////////////////////////////////////////////////// // // firewire_attach_inet // // IN: ifnet_t ifp // // Invoked by: // firewire_attach_inet will be invoked from IOFWInterface::attachToDataLinkLayer // //////////////////////////////////////////////////////////////////////////////// int firewire_attach_inet(ifnet_t ifp, u_long protocol_family) { struct ifnet_attach_proto_param proto; struct ifnet_demux_desc demux[2]; u_short en_native=htons(FWTYPE_IP); u_short arp_native=htons(FWTYPE_ARP); errno_t error; bzero(&demux[0], sizeof(demux)); demux[0].type = DLIL_DESC_ETYPE2; demux[0].data = &en_native; demux[0].datalen = sizeof(en_native); demux[1].type = DLIL_DESC_ETYPE2; demux[1].data = &arp_native; demux[1].datalen = sizeof(arp_native); bzero(&proto, sizeof(proto)); proto.demux_list = demux; proto.demux_count = sizeof(demux) / sizeof(demux[0]); proto.input = inet_firewire_input; proto.pre_output = inet_firewire_pre_output; proto.ioctl = firewire_inet_prmod_ioctl; proto.event = firewire_inet_event; proto.resolve = firewire_inet_resolve_multi; proto.send_arp = firewire_inet_arp; error = ifnet_attach_protocol(ifp, protocol_family, &proto); if (error && error != EEXIST) { printf("WARNING: firewire_attach_inet can't attach ip to %s%d\n", ifnet_name(ifp), ifnet_unit(ifp)); } return error; } int firewire_detach_inet( struct ifnet *ifp, u_long proto_family) { int stat; stat = dlil_detach_protocol(ifp, proto_family); return stat; }