X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/6d2010ae8f7a6078e10b361c6962983bab233e0f..04b8595b18b1b41ac7a206e4b3d51a635f8413d7:/bsd/net/ether_inet_pr_module.c diff --git a/bsd/net/ether_inet_pr_module.c b/bsd/net/ether_inet_pr_module.c index 12a8ead3c..b47c9dfba 100644 --- a/bsd/net/ether_inet_pr_module.c +++ b/bsd/net/ether_inet_pr_module.c @@ -1,8 +1,8 @@ /* - * Copyright (c) 2000-2011 Apple Inc. All rights reserved. + * Copyright (c) 2000-2013 Apple Inc. All rights reserved. * * @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 @@ -11,10 +11,10 @@ * 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, @@ -22,7 +22,7 @@ * 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@ */ /* @@ -74,15 +74,14 @@ #include #include #include -#include +#include #include #include #include #include #include #include - #include #include #include @@ -109,7 +108,7 @@ extern void kdp_set_ip_and_mac_addresses(struct in_addr *ipaddr, struct ether_addr *macaddr); #define _ip_copy(dst, src) \ - (*(dst) = *(src)) + bcopy(src, dst, sizeof (struct in_addr)) static void ether_inet_arp_input(struct ifnet *ifp, struct mbuf *m) @@ -142,9 +141,9 @@ ether_inet_arp_input(struct ifnet *ifp, struct mbuf *m) bzero(&sender_ip, sizeof (sender_ip)); sender_ip.sin_len = sizeof (sender_ip); sender_ip.sin_family = AF_INET; - _ip_copy(&sender_ip.sin_addr, (const struct in_addr *)ea->arp_spa); + _ip_copy(&sender_ip.sin_addr, ea->arp_spa); target_ip = sender_ip; - _ip_copy(&target_ip.sin_addr, (const struct in_addr *)ea->arp_tpa); + _ip_copy(&target_ip.sin_addr, ea->arp_tpa); bzero(&sender_hw, sizeof (sender_hw)); sender_hw.sdl_len = sizeof (sender_hw); @@ -247,25 +246,28 @@ ether_inet_pre_output(ifnet_t ifp, protocol_family_t protocol_family, struct sockaddr_dl ll_dest; result = arp_lookup_ip(ifp, - (const struct sockaddr_in *)dst_netaddr, &ll_dest, - sizeof (ll_dest), (route_t)route, *m0); + (const struct sockaddr_in *)(uintptr_t)(size_t)dst_netaddr, + &ll_dest, sizeof (ll_dest), (route_t)route, *m0); if (result == 0) { + u_int16_t ethertype_ip = htons(ETHERTYPE_IP); + bcopy(LLADDR(&ll_dest), edst, ETHER_ADDR_LEN); - *(u_int16_t *)type = htons(ETHERTYPE_IP); + bcopy(ðertype_ip, type, sizeof (ethertype_ip)); } - break; + break; } case pseudo_AF_HDRCMPLT: case AF_UNSPEC: m->m_flags &= ~M_LOOP; - eh = (const struct ether_header *)dst_netaddr->sa_data; + eh = (const struct ether_header *)(uintptr_t)(size_t) + dst_netaddr->sa_data; (void) memcpy(edst, eh->ether_dhost, 6); - *(u_short *)type = eh->ether_type; + bcopy(&eh->ether_type, type, sizeof (u_short)); break; default: - printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit, + printf("%s: can't handle af%d\n", if_name(ifp), dst_netaddr->sa_family); result = EAFNOSUPPORT; @@ -281,7 +283,8 @@ ether_inet_resolve_multi(ifnet_t ifp, const struct sockaddr *proto_addr, { static const size_t minsize = offsetof(struct sockaddr_dl, sdl_data[0]) + ETHER_ADDR_LEN; - const struct sockaddr_in *sin = (const struct sockaddr_in *)proto_addr; + const struct sockaddr_in *sin = + (const struct sockaddr_in *)(uintptr_t)(size_t)proto_addr; if (proto_addr->sa_family != AF_INET) return (EAFNOSUPPORT); @@ -310,13 +313,18 @@ ether_inet_prmod_ioctl(ifnet_t ifp, protocol_family_t protocol_family, u_long command, void *data) { #pragma unused(protocol_family) - ifaddr_t ifa = data; - struct ifreq *ifr = data; int error = 0; switch (command) { - case SIOCSIFADDR: - case SIOCAIFADDR: + case SIOCSIFADDR: /* struct ifaddr pointer */ + case SIOCAIFADDR: { /* struct ifaddr pointer */ + /* + * Note: caller of ifnet_ioctl() passes in pointer to + * struct ifaddr as parameter to SIOC{A,S}IFADDR, for + * legacy reasons. + */ + struct ifaddr *ifa = data; + if (!(ifnet_flags(ifp) & IFF_RUNNING)) { ifnet_set_flags(ifp, IFF_UP, IFF_UP); ifnet_ioctl(ifp, 0, SIOCSIFFLAGS, NULL); @@ -326,6 +334,10 @@ ether_inet_prmod_ioctl(ifnet_t ifp, protocol_family_t protocol_family, break; inet_arp_init_ifaddr(ifp, ifa); + + if (command != SIOCSIFADDR) + break; + /* * Register new IP and MAC addresses with the kernel * debugger if the interface is the same as was registered @@ -334,18 +346,20 @@ ether_inet_prmod_ioctl(ifnet_t ifp, protocol_family_t protocol_family, * Do this only for the first address of the interface * and not for aliases. */ - if (command == SIOCSIFADDR && - ((kdp_get_interface() != 0 && + if ((kdp_get_interface() != 0 && kdp_get_interface() == ifp->if_softc) || - (kdp_get_interface() == 0 && ifp->if_unit == 0))) + (kdp_get_interface() == 0 && ifp->if_unit == 0)) kdp_set_ip_and_mac_addresses(&(IA_SIN(ifa)->sin_addr), - ifnet_lladdr(ifp)); + (struct ether_addr *)IF_LLADDR(ifp)); break; + } - case SIOCGIFADDR: - ifnet_lladdr_copy_bytes(ifp, ifr->ifr_addr.sa_data, + case SIOCGIFADDR: { /* struct ifreq */ + struct ifreq *ifr = data; + ifnet_guarded_lladdr_copy_bytes(ifp, ifr->ifr_addr.sa_data, ETHER_ADDR_LEN); break; + } default: error = EOPNOTSUPP; @@ -390,9 +404,9 @@ ether_inet_arp(ifnet_t ifp, u_short arpop, const struct sockaddr_dl *sender_hw, struct ether_header *eh; struct ether_arp *ea; const struct sockaddr_in *sender_ip = - (const struct sockaddr_in *)sender_proto; - const struct sockaddr_in *target_ip = - (const struct sockaddr_in *)target_proto; + (const struct sockaddr_in *)(uintptr_t)(size_t)sender_proto; + const struct sockaddr_inarp *target_ip = + (const struct sockaddr_inarp *)(uintptr_t)(size_t)target_proto; char *datap; if (target_ip == NULL) @@ -459,8 +473,9 @@ ether_inet_arp(ifnet_t ifp, u_short arpop, const struct sockaddr_dl *sender_hw, IFA_LOCK(ifa); if (ifa->ifa_addr != NULL && ifa->ifa_addr->sa_family == AF_INET) { - bcopy(&((struct sockaddr_in *)ifa->ifa_addr)-> - sin_addr, ea->arp_spa, sizeof(ea->arp_spa)); + bcopy(&((struct sockaddr_in *)(void *) + ifa->ifa_addr)->sin_addr, ea->arp_spa, + sizeof (ea->arp_spa)); IFA_UNLOCK(ifa); break; } @@ -479,16 +494,43 @@ ether_inet_arp(ifnet_t ifp, u_short arpop, const struct sockaddr_dl *sender_hw, bzero(ea->arp_tha, sizeof (ea->arp_tha)); bcopy(etherbroadcastaddr, eh->ether_dhost, sizeof (eh->ether_dhost)); + m->m_flags |= M_BCAST; } else { bcopy(CONST_LLADDR(target_hw), ea->arp_tha, sizeof (ea->arp_tha)); bcopy(CONST_LLADDR(target_hw), eh->ether_dhost, sizeof (eh->ether_dhost)); + + if (bcmp(eh->ether_dhost, etherbroadcastaddr, + ETHER_ADDR_LEN) == 0) + m->m_flags |= M_BCAST; } /* Target IP */ bcopy(&target_ip->sin_addr, ea->arp_tpa, sizeof (ea->arp_tpa)); + /* + * PKTF_{INET,INET6}_RESOLVE_RTR are mutually exclusive, so make + * sure only one of them is set (just in case.) + */ + m->m_pkthdr.pkt_flags &= ~(PKTF_INET6_RESOLVE | PKTF_RESOLVE_RTR); + m->m_pkthdr.pkt_flags |= PKTF_INET_RESOLVE; + /* + * If this is an ARP request for a (default) router, mark + * the packet accordingly so that the driver can find out, + * in case it needs to perform driver-specific action(s). + */ + if (arpop == ARPOP_REQUEST && (target_ip->sin_other & SIN_ROUTER)) + m->m_pkthdr.pkt_flags |= PKTF_RESOLVE_RTR; + + if (ifp->if_eflags & IFEF_TXSTART) { + /* + * Use control service class if the interface + * supports transmit-start model + */ + (void) m_set_service_class(m, MBUF_SC_CTL); + } + ifnet_output_raw(ifp, PF_INET, m); return (0); @@ -524,8 +566,8 @@ ether_attach_inet(struct ifnet *ifp, protocol_family_t proto_family) error = ifnet_attach_protocol_v2(ifp, proto_family, &proto); if (error && error != EEXIST) { - printf("WARNING: %s can't attach ip to %s%d\n", __func__, - ifp->if_name, ifp->if_unit); + printf("WARNING: %s can't attach ip to %s\n", __func__, + if_name(ifp)); } return (error); }