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 * Copyright (c) 1982, 1989, 1993 24 * The Regents of the University of California. All rights reserved. 25 * 26 * Redistribution and use in source and binary forms, with or without 27 * modification, are permitted provided that the following conditions 28 * are met: 29 * 1. Redistributions of source code must retain the above copyright 30 * notice, this list of conditions and the following disclaimer. 31 * 2. Redistributions in binary form must reproduce the above copyright 32 * notice, this list of conditions and the following disclaimer in the 33 * documentation and/or other materials provided with the distribution. 34 * 3. All advertising materials mentioning features or use of this software 35 * must display the following acknowledgement: 36 * This product includes software developed by the University of 37 * California, Berkeley and its contributors. 38 * 4. Neither the name of the University nor the names of its contributors 39 * may be used to endorse or promote products derived from this software 40 * without specific prior written permission. 41 * 42 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 43 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 44 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 45 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 46 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 47 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 48 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 50 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 51 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 52 * SUCH DAMAGE. 53 * 54 */ 55#include <sys/param.h> 56#include <sys/systm.h> 57#include <sys/kernel.h> 58#include <sys/malloc.h> 59#include <sys/mbuf.h> 60#include <sys/socket.h> 61#include <sys/sockio.h> 62#include <sys/sysctl.h> 63#include <sys/syslog.h> 64 65#include <net/if.h> 66#include <net/route.h> 67#include <net/if_llc.h> 68#include <net/if_dl.h> 69#include <net/if_types.h> 70#include <net/ndrv.h> 71 72#include <netinet/in.h> 73#include <netinet/in_var.h> 74#include <netinet/in_systm.h> 75#include <netinet/ip.h> 76 77#include <netinet6/in6_var.h> 78#include <netinet6/nd6.h> 79#include <netinet6/in6_ifattach.h> 80 81#include <sys/socketvar.h> 82 83#include <net/dlil.h> 84#include <net/kpi_protocol.h> 85 86#include "firewire.h" 87#include "if_firewire.h" 88 89extern void ip6_input(struct mbuf *); 90 91/* 92 * Process a received firewire packet; 93 * the packet is in the mbuf chain m without 94 * the firewire header, which is provided separately. 95 */ 96int 97inet6_firewire_input( 98 ifnet_t ifp, 99 protocol_family_t protocol_fmaily, 100 mbuf_t m, 101 char *frame_header) 102{ 103 register struct firewire_header *eh = (struct firewire_header *) frame_header; 104 105 if ((ifnet_flags(ifp) & IFF_UP) == 0) 106 { 107 mbuf_freem(m); 108 return EJUSTRETURN; 109 } 110 111 ifnet_touch_lastchange(ifp); 112 113 if (eh->fw_dhost[0] & 1) 114 { 115 int flags = (bcmp((caddr_t)fwbroadcastaddr, (caddr_t)eh->fw_dhost, sizeof(fwbroadcastaddr)) == 0) 116 ? MBUF_BCAST : MBUF_MCAST; 117 118 mbuf_setflags(m, mbuf_flags(m) | flags); 119 } 120 121 errno_t ret = proto_input(PF_INET6, (struct __mbuf*)m); 122 123 if( ret ) 124 mbuf_freem(m); 125 126 return ret; 127} 128 129 130 131 132int 133inet6_firewire_pre_output( 134 ifnet_t ifp, 135 protocol_family_t protocol_family, 136 mbuf_t *m0, 137 const struct sockaddr *dst_netaddr, 138 void *route, 139 char *type, 140 char *edst) 141{ 142 errno_t result; 143 struct sockaddr_dl sdl; 144 145 mbuf_setflags(*m0, mbuf_flags(*m0) | MBUF_LOOP); 146 147 result = nd6_lookup_ipv6(ifp, (const struct sockaddr_in6*)dst_netaddr, 148 &sdl, sizeof(sdl), (route_t)route, *m0); 149 150 if (result == 0) 151 { 152 *(u_int16_t*)type = htons(FWTYPE_IPV6); 153 bcopy(LLADDR(&sdl), edst, sdl.sdl_alen); 154 } 155 156 return result; 157} 158 159static int 160firewire_inet6_resolve_multi( 161 ifnet_t ifp, 162 const struct sockaddr *proto_addr, 163 struct sockaddr_dl *out_ll, 164 size_t ll_len) 165{ 166 static const size_t minsize = offsetof(struct sockaddr_dl, sdl_data[0]) + FIREWIRE_ADDR_LEN; 167 const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6*)proto_addr; 168 169 if (proto_addr->sa_family != AF_INET6) 170 return EAFNOSUPPORT; 171 172 if (proto_addr->sa_len < sizeof(struct sockaddr_in6)) 173 return EINVAL; 174 175 if (ll_len < minsize) 176 return EMSGSIZE; 177 178 bzero(out_ll, minsize); 179 out_ll->sdl_len = minsize; 180 out_ll->sdl_family = AF_LINK; 181 out_ll->sdl_index = ifnet_index(ifp); 182 out_ll->sdl_type = IFT_IEEE1394; 183 out_ll->sdl_nlen = 0; 184 out_ll->sdl_alen = FIREWIRE_ADDR_LEN; 185 out_ll->sdl_slen = 0; 186 187 FIREWIRE_MAP_IPV6_MULTICAST(&sin6->sin6_addr, LLADDR(out_ll)); 188 189 return 0; 190} 191 192errno_t 193firewire_inet6_prmod_ioctl( 194 __unused ifnet_t ifp, 195 __unused protocol_family_t protocol_family, 196 __unused unsigned long command, 197 __unused void *data) 198{ 199 return EOPNOTSUPP; 200} 201 202int 203firewire_attach_inet6( 204 ifnet_t ifp, 205 __unused protocol_family_t protocol_family) 206{ 207 struct ifnet_attach_proto_param proto; 208 struct ifnet_demux_desc demux[1]; 209 u_short en_6native=htons(FWTYPE_IPV6); 210 errno_t error; 211 212 bzero(&proto, sizeof(proto)); 213 demux[0].type = DLIL_DESC_ETYPE2; 214 demux[0].data = &en_6native; 215 demux[0].datalen = sizeof(en_6native); 216 proto.demux_list = demux; 217 proto.demux_count = 1; 218 proto.input = inet6_firewire_input; 219 proto.pre_output = inet6_firewire_pre_output; 220 proto.ioctl = firewire_inet6_prmod_ioctl; 221 proto.resolve = firewire_inet6_resolve_multi; 222 223 error = ifnet_attach_protocol(ifp, protocol_family, &proto); 224 225 if (error && error != EEXIST) 226 { 227 printf("WARNING: firewire_attach_inet6 can't attach ipv6 to %s%d\n", 228 ifnet_name(ifp), ifnet_unit(ifp)); 229 } 230 231 return error; 232}