X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/6601e61aa18bf4f09af135ff61fc7f4771d23b06..a991bd8d3e7fe02dbca0644054bab73c5b75324a:/bsd/net/ether_inet6_pr_module.c?ds=sidebyside diff --git a/bsd/net/ether_inet6_pr_module.c b/bsd/net/ether_inet6_pr_module.c index 1c2175efe..c332fd523 100644 --- a/bsd/net/ether_inet6_pr_module.c +++ b/bsd/net/ether_inet6_pr_module.c @@ -1,23 +1,29 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2013 Apple 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 + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The 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@ + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* * Copyright (c) 1982, 1989, 1993 @@ -53,8 +59,6 @@ * */ - - #include #include #include @@ -63,8 +67,9 @@ #include #include #include -#include +#include +#include #include #include #include @@ -72,6 +77,7 @@ #include #include #include +#include #include #include @@ -79,35 +85,19 @@ #include #include -#if INET6 #include #include -#endif - - - -#include - -#include - - -#if LLC && CCITT -extern struct ifqueue pkintrq; -#endif - - -#if BRIDGE -#include -#endif +#include /* #include "vlan.h" */ #if NVLAN > 0 #include #endif /* NVLAN > 0 */ -/* Local function declerations */ -int ether_attach_inet6(struct ifnet *ifp, u_long protocol_family); -int ether_detach_inet6(struct ifnet *ifp, u_long protocol_family); +#include + +static const u_char etherip6allnodes[ETHER_ADDR_LEN] = +{ 0x33, 0x33, 0, 0, 0, 1 }; /* * Process a received Ethernet packet; @@ -115,67 +105,104 @@ int ether_detach_inet6(struct ifnet *ifp, u_long protocol_family); * the ether header, which is provided separately. */ static errno_t -inet6_ether_input( - __unused ifnet_t ifp, - protocol_family_t protocol, - mbuf_t packet, - __unused char *header) +ether_inet6_input(ifnet_t ifp, protocol_family_t protocol, + mbuf_t packet, char *header) { - proto_input(protocol, packet); - return 0; +#pragma unused(ifp, protocol) + struct ether_header *eh = (struct ether_header *)(void *)header; + u_int16_t ether_type; + + bcopy(&eh->ether_type, ðer_type, sizeof(ether_type)); + + if (ether_type == htons(ETHERTYPE_IPV6)) { + struct ifnet *mifp; + /* + * Trust the ifp in the mbuf, rather than ifproto's + * since the packet could have been injected via + * a dlil_input_packet_list() using an ifp that is + * different than the one where the packet really + * came from. + */ + mifp = mbuf_pkthdr_rcvif(packet); + + /* Update L2 reachability record, if present (and not bcast) */ + if (bcmp(eh->ether_shost, etherbroadcastaddr, + ETHER_ADDR_LEN) != 0) { + nd6_llreach_set_reachable(mifp, eh->ether_shost, + ETHER_ADDR_LEN); + } + + /* Save the Ethernet source address for all-nodes multicasts */ + if (!bcmp(eh->ether_dhost, etherip6allnodes, ETHER_ADDR_LEN)) { + struct ip6aux *ip6a; + + ip6a = ip6_addaux(packet); + if (ip6a) { + ip6a->ip6a_flags |= IP6A_HASEEN; + bcopy(eh->ether_shost, ip6a->ip6a_ehsrc, + ETHER_ADDR_LEN); + } + } + + if (proto_input(protocol, packet) != 0) { + m_freem(packet); + } + } else { + m_freem(packet); + } + + return EJUSTRETURN; } static errno_t -inet6_ether_pre_output( - ifnet_t ifp, - __unused protocol_family_t protocol_family, - mbuf_t *m0, - const struct sockaddr *dst_netaddr, - void *route, - char *type, - char *edst) +ether_inet6_pre_output(ifnet_t ifp, protocol_family_t protocol_family, + mbuf_t *m0, const struct sockaddr *dst_netaddr, void *route, + char *type, char *edst) { - errno_t result; - struct sockaddr_dl sdl; - register struct mbuf *m = *m0; +#pragma unused(protocol_family) + errno_t result; + struct sockaddr_dl sdl = {}; + struct mbuf *m = *m0; /* * Tell ether_frameout it's ok to loop packet if necessary */ m->m_flags |= M_LOOP; - - result = nd6_lookup_ipv6(ifp, (const struct sockaddr_in6*)dst_netaddr, - &sdl, sizeof(sdl), route, *m0); - + + result = nd6_lookup_ipv6(ifp, (const struct sockaddr_in6 *) + (uintptr_t)(size_t)dst_netaddr, &sdl, sizeof(sdl), route, *m0); + if (result == 0) { - *(u_int16_t*)type = htons(ETHERTYPE_IPV6); + u_int16_t ethertype_ipv6 = htons(ETHERTYPE_IPV6); + + bcopy(ðertype_ipv6, type, sizeof(ethertype_ipv6)); bcopy(LLADDR(&sdl), edst, sdl.sdl_alen); } - - - return result; + return result; } static int -ether_inet6_resolve_multi( - ifnet_t ifp, - const struct sockaddr *proto_addr, - struct sockaddr_dl *out_ll, - size_t ll_len) +ether_inet6_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]) + ETHER_ADDR_LEN; - const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6*)proto_addr; - - if (proto_addr->sa_family != AF_INET6) + static const size_t minsize = + offsetof(struct sockaddr_dl, sdl_data[0]) + ETHER_ADDR_LEN; + const struct sockaddr_in6 *sin6 = + (const struct sockaddr_in6 *)(uintptr_t)(size_t)proto_addr; + + if (proto_addr->sa_family != AF_INET6) { return EAFNOSUPPORT; - - if (proto_addr->sa_len < sizeof(struct sockaddr_in6)) + } + + if (proto_addr->sa_len < sizeof(struct sockaddr_in6)) { return EINVAL; - - if (ll_len < minsize) + } + + if (ll_len < minsize) { return EMSGSIZE; - + } + bzero(out_ll, minsize); out_ll->sdl_len = minsize; out_ll->sdl_family = AF_LINK; @@ -185,90 +212,74 @@ ether_inet6_resolve_multi( out_ll->sdl_alen = ETHER_ADDR_LEN; out_ll->sdl_slen = 0; ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, LLADDR(out_ll)); - + return 0; } - static errno_t -ether_inet6_prmod_ioctl( - ifnet_t ifp, - __unused protocol_family_t protocol_family, - u_int32_t command, - void* data) +ether_inet6_prmod_ioctl(ifnet_t ifp, protocol_family_t protocol_family, + u_long command, void *data) { - struct ifreq *ifr = (struct ifreq *) data; - int error = 0; - - switch (command) { - case SIOCSIFADDR: - if ((ifp->if_flags & IFF_RUNNING) == 0) { - ifnet_set_flags(ifp, IFF_UP, IFF_UP); - dlil_ioctl(0, ifp, SIOCSIFFLAGS, (caddr_t) 0); - } - - break; - - case SIOCGIFADDR: - ifnet_lladdr_copy_bytes(ifp, ifr->ifr_addr.sa_data, ETHER_ADDR_LEN); - break; - - case SIOCSIFMTU: - /* - * IOKit IONetworkFamily will set the right MTU according to the driver - */ - - return (0); - - default: - return EOPNOTSUPP; - } +#pragma unused(protocol_family) + int error = 0; + + switch (command) { + case SIOCSIFADDR: /* struct ifaddr pointer */ + /* + * Note: caller of ifnet_ioctl() passes in pointer to + * struct ifaddr as parameter to SIOCSIFADDR, for legacy + * reasons. + */ + if ((ifp->if_flags & IFF_RUNNING) == 0) { + ifnet_set_flags(ifp, IFF_UP, IFF_UP); + ifnet_ioctl(ifp, 0, SIOCSIFFLAGS, NULL); + } + break; + + case SIOCGIFADDR: { /* struct ifreq */ + struct ifreq *ifr = (struct ifreq *)(void *)data; + (void) ifnet_guarded_lladdr_copy_bytes(ifp, + ifr->ifr_addr.sa_data, ETHER_ADDR_LEN); + break; + } - return (error); + default: + error = EOPNOTSUPP; + break; + } + return error; } -int -ether_attach_inet6( - struct ifnet *ifp, - __unused u_long protocol_family) +errno_t +ether_attach_inet6(struct ifnet *ifp, protocol_family_t protocol_family) { - struct ifnet_attach_proto_param proto; +#pragma unused(protocol_family) + struct ifnet_attach_proto_param proto; struct ifnet_demux_desc demux[1]; - u_short en_6native=htons(ETHERTYPE_IPV6); - errno_t error; - + u_short en_6native = htons(ETHERTYPE_IPV6); + errno_t error; + bzero(&proto, sizeof(proto)); demux[0].type = DLIL_DESC_ETYPE2; demux[0].data = &en_6native; demux[0].datalen = sizeof(en_6native); proto.demux_list = demux; proto.demux_count = 1; - proto.input = inet6_ether_input; - proto.pre_output = inet6_ether_pre_output; + proto.input = ether_inet6_input; + proto.pre_output = ether_inet6_pre_output; proto.ioctl = ether_inet6_prmod_ioctl; proto.resolve = ether_inet6_resolve_multi; error = ifnet_attach_protocol(ifp, protocol_family, &proto); if (error && error != EEXIST) { - printf("WARNING: ether_attach_inet6 can't attach ipv6 to %s%d\n", - ifp->if_name, ifp->if_unit); + printf("WARNING: %s can't attach ipv6 to %s\n", __func__, + if_name(ifp)); } - + return error; } -int -ether_detach_inet6( - struct ifnet *ifp, - u_long protocol_family) +void +ether_detach_inet6(struct ifnet *ifp, protocol_family_t protocol_family) { - errno_t error; - - error = ifnet_detach_protocol(ifp, protocol_family); - if (error && error != ENOENT) { - printf("WARNING: ether_detach_inet6 can't detach ipv6 from %s%d\n", - ifp->if_name, ifp->if_unit); - } - - return error; + (void) ifnet_detach_protocol(ifp, protocol_family); } -