1/* 2 * Copyright (c) 2000-2012 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* 29 * Copyright (c) 1982, 1989, 1993 30 * The Regents of the University of California. All rights reserved. 31 * 32 * Redistribution and use in source and binary forms, with or without 33 * modification, are permitted provided that the following conditions 34 * are met: 35 * 1. Redistributions of source code must retain the above copyright 36 * notice, this list of conditions and the following disclaimer. 37 * 2. Redistributions in binary form must reproduce the above copyright 38 * notice, this list of conditions and the following disclaimer in the 39 * documentation and/or other materials provided with the distribution. 40 * 3. All advertising materials mentioning features or use of this software 41 * must display the following acknowledgement: 42 * This product includes software developed by the University of 43 * California, Berkeley and its contributors. 44 * 4. Neither the name of the University nor the names of its contributors 45 * may be used to endorse or promote products derived from this software 46 * without specific prior written permission. 47 * 48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * SUCH DAMAGE. 59 * 60 */ 61/* 62 * NOTICE: This file was modified by SPARTA, Inc. in 2006 to introduce 63 * support for mandatory and extensible security protections. This notice 64 * is included in support of clause 2.2 (b) of the Apple Public License, 65 * Version 2.0. 66 */ 67 68 69#include <sys/param.h> 70#include <sys/systm.h> 71#include <sys/kernel.h> 72#include <sys/malloc.h> 73#include <sys/mbuf.h> 74#include <sys/socket.h> 75#include <sys/sockio.h> 76#include <sys/sysctl.h> 77#include <kern/lock.h> 78 79#include <net/if.h> 80#include <net/route.h> 81#include <net/if_llc.h> 82#include <net/if_dl.h> 83#include <net/if_types.h> 84#include <net/kpi_protocol.h> 85 86#include <netinet/in.h> 87#include <netinet/in_var.h> 88#include <netinet/if_ether.h> 89#include <netinet/in_systm.h> 90#include <netinet/ip.h> 91#include <netinet/in_arp.h> 92 93#include <sys/socketvar.h> 94 95#include <net/dlil.h> 96 97/* #include "vlan.h" */ 98#if NVLAN > 0 99#include <net/if_vlan_var.h> 100#endif /* NVLAN > 0 */ 101#include <net/ether_if_module.h> 102#if CONFIG_MACF 103#include <security/mac_framework.h> 104#endif 105 106/* Local function declarations */ 107extern void *kdp_get_interface(void); 108extern void kdp_set_ip_and_mac_addresses(struct in_addr *ipaddr, 109 struct ether_addr *macaddr); 110 111#define _ip_copy(dst, src) \ 112 bcopy(src, dst, sizeof (struct in_addr)) 113 114static void 115ether_inet_arp_input(struct ifnet *ifp, struct mbuf *m) 116{ 117 struct ether_arp *ea; 118 struct sockaddr_dl sender_hw; 119 struct sockaddr_in sender_ip; 120 struct sockaddr_in target_ip; 121 122 if (mbuf_len(m) < sizeof (*ea) && mbuf_pullup(&m, sizeof (*ea)) != 0) 123 return; 124 125 ea = mbuf_data(m); 126 127 /* Verify this is an ethernet/ip arp and address lengths are correct */ 128 if (ntohs(ea->arp_hrd) != ARPHRD_ETHER || 129 ntohs(ea->arp_pro) != ETHERTYPE_IP || 130 ea->arp_pln != sizeof (struct in_addr) || 131 ea->arp_hln != ETHER_ADDR_LEN) { 132 mbuf_freem(m); 133 return; 134 } 135 136 /* Verify the sender is not broadcast */ 137 if (bcmp(ea->arp_sha, etherbroadcastaddr, ETHER_ADDR_LEN) == 0) { 138 mbuf_freem(m); 139 return; 140 } 141 142 bzero(&sender_ip, sizeof (sender_ip)); 143 sender_ip.sin_len = sizeof (sender_ip); 144 sender_ip.sin_family = AF_INET; 145 _ip_copy(&sender_ip.sin_addr, ea->arp_spa); 146 target_ip = sender_ip; 147 _ip_copy(&target_ip.sin_addr, ea->arp_tpa); 148 149 bzero(&sender_hw, sizeof (sender_hw)); 150 sender_hw.sdl_len = sizeof (sender_hw); 151 sender_hw.sdl_family = AF_LINK; 152 sender_hw.sdl_type = IFT_ETHER; 153 sender_hw.sdl_alen = ETHER_ADDR_LEN; 154 bcopy(ea->arp_sha, LLADDR(&sender_hw), ETHER_ADDR_LEN); 155 156 /* update L2 reachability record, if present */ 157 arp_llreach_set_reachable(ifp, LLADDR(&sender_hw), ETHER_ADDR_LEN); 158 159 arp_ip_handle_input(ifp, ntohs(ea->arp_op), &sender_hw, &sender_ip, 160 &target_ip); 161 mbuf_freem(m); 162} 163 164/* 165 * Process a received Ethernet packet; 166 * the packet is in the mbuf chain m without 167 * the ether header, which is provided separately. 168 */ 169static errno_t 170ether_inet_input(ifnet_t ifp, protocol_family_t protocol_family, 171 mbuf_t m_list) 172{ 173#pragma unused(ifp, protocol_family) 174 mbuf_t m; 175 mbuf_t *tailptr = &m_list; 176 mbuf_t nextpkt; 177 178 /* Strip ARP and non-IP packets out of the list */ 179 for (m = m_list; m; m = nextpkt) { 180 struct ether_header *eh = mbuf_pkthdr_header(m); 181 struct ifnet *mifp; 182 183 /* 184 * Trust the ifp in the mbuf, rather than ifproto's 185 * since the packet could have been injected via 186 * a dlil_input_packet_list() using an ifp that is 187 * different than the one where the packet really 188 * came from. 189 */ 190 mifp = mbuf_pkthdr_rcvif(m); 191 192 nextpkt = m->m_nextpkt; 193 194 if (eh->ether_type == htons(ETHERTYPE_IP)) { 195 /* 196 * Update L2 reachability record, if present 197 * (and if not a broadcast sender). 198 */ 199 if (bcmp(eh->ether_shost, etherbroadcastaddr, 200 ETHER_ADDR_LEN) != 0) { 201 arp_llreach_set_reachable(mifp, eh->ether_shost, 202 ETHER_ADDR_LEN); 203 } 204 /* put this packet in the list */ 205 *tailptr = m; 206 tailptr = &m->m_nextpkt; 207 } else { 208 /* Pass ARP packets to arp input */ 209 m->m_nextpkt = NULL; 210 if (eh->ether_type == htons(ETHERTYPE_ARP)) 211 ether_inet_arp_input(mifp, m); 212 else 213 mbuf_freem(m); 214 } 215 } 216 217 *tailptr = NULL; 218 219 /* Pass IP list to ip input */ 220 if (m_list != NULL && proto_input(PF_INET, m_list) != 0) { 221 mbuf_freem_list(m_list); 222 } 223 224 return (EJUSTRETURN); 225} 226 227static errno_t 228ether_inet_pre_output(ifnet_t ifp, protocol_family_t protocol_family, 229 mbuf_t *m0, const struct sockaddr *dst_netaddr, 230 void *route, char *type, char *edst) 231{ 232#pragma unused(protocol_family) 233 struct mbuf *m = *m0; 234 const struct ether_header *eh; 235 errno_t result = 0; 236 237 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) 238 return (ENETDOWN); 239 240 /* 241 * Tell ether_frameout it's ok to loop packet unless negated below. 242 */ 243 m->m_flags |= M_LOOP; 244 245 switch (dst_netaddr->sa_family) { 246 case AF_INET: { 247 struct sockaddr_dl ll_dest; 248 249 result = arp_lookup_ip(ifp, 250 (const struct sockaddr_in *)(uintptr_t)(size_t)dst_netaddr, 251 &ll_dest, sizeof (ll_dest), (route_t)route, *m0); 252 if (result == 0) { 253 u_int16_t ethertype_ip = htons(ETHERTYPE_IP); 254 255 bcopy(LLADDR(&ll_dest), edst, ETHER_ADDR_LEN); 256 bcopy(ðertype_ip, type, sizeof (ethertype_ip)); 257 } 258 break; 259 } 260 261 case pseudo_AF_HDRCMPLT: 262 case AF_UNSPEC: 263 m->m_flags &= ~M_LOOP; 264 eh = (const struct ether_header *)(uintptr_t)(size_t) 265 dst_netaddr->sa_data; 266 (void) memcpy(edst, eh->ether_dhost, 6); 267 bcopy(&eh->ether_type, type, sizeof (u_short)); 268 break; 269 270 default: 271 printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit, 272 dst_netaddr->sa_family); 273 274 result = EAFNOSUPPORT; 275 break; 276 } 277 278 return (result); 279} 280 281static errno_t 282ether_inet_resolve_multi(ifnet_t ifp, const struct sockaddr *proto_addr, 283 struct sockaddr_dl *out_ll, size_t ll_len) 284{ 285 static const size_t minsize = 286 offsetof(struct sockaddr_dl, sdl_data[0]) + ETHER_ADDR_LEN; 287 const struct sockaddr_in *sin = 288 (const struct sockaddr_in *)(uintptr_t)(size_t)proto_addr; 289 290 if (proto_addr->sa_family != AF_INET) 291 return (EAFNOSUPPORT); 292 293 if (proto_addr->sa_len < sizeof (struct sockaddr_in)) 294 return (EINVAL); 295 296 if (ll_len < minsize) 297 return (EMSGSIZE); 298 299 bzero(out_ll, minsize); 300 out_ll->sdl_len = minsize; 301 out_ll->sdl_family = AF_LINK; 302 out_ll->sdl_index = ifp->if_index; 303 out_ll->sdl_type = IFT_ETHER; 304 out_ll->sdl_nlen = 0; 305 out_ll->sdl_alen = ETHER_ADDR_LEN; 306 out_ll->sdl_slen = 0; 307 ETHER_MAP_IP_MULTICAST(&sin->sin_addr, LLADDR(out_ll)); 308 309 return (0); 310} 311 312static errno_t 313ether_inet_prmod_ioctl(ifnet_t ifp, protocol_family_t protocol_family, 314 u_long command, void *data) 315{ 316#pragma unused(protocol_family) 317 int error = 0; 318 319 switch (command) { 320 case SIOCSIFADDR: /* struct ifaddr pointer */ 321 case SIOCAIFADDR: { /* struct ifaddr pointer */ 322 /* 323 * Note: caller of ifnet_ioctl() passes in pointer to 324 * struct ifaddr as parameter to SIOC{A,S}IFADDR, for 325 * legacy reasons. 326 */ 327 struct ifaddr *ifa = data; 328 329 if (!(ifnet_flags(ifp) & IFF_RUNNING)) { 330 ifnet_set_flags(ifp, IFF_UP, IFF_UP); 331 ifnet_ioctl(ifp, 0, SIOCSIFFLAGS, NULL); 332 } 333 334 if (ifaddr_address_family(ifa) != AF_INET) 335 break; 336 337 inet_arp_init_ifaddr(ifp, ifa); 338 339 if (command != SIOCSIFADDR) 340 break; 341 342 /* 343 * Register new IP and MAC addresses with the kernel 344 * debugger if the interface is the same as was registered 345 * by IOKernelDebugger. If no interface was registered, 346 * fall back and just match against en0 interface. 347 * Do this only for the first address of the interface 348 * and not for aliases. 349 */ 350 if ((kdp_get_interface() != 0 && 351 kdp_get_interface() == ifp->if_softc) || 352 (kdp_get_interface() == 0 && ifp->if_unit == 0)) 353 kdp_set_ip_and_mac_addresses(&(IA_SIN(ifa)->sin_addr), 354 ifnet_lladdr(ifp)); 355 break; 356 } 357 358 case SIOCGIFADDR: { /* struct ifreq */ 359 struct ifreq *ifr = data; 360 361 ifnet_lladdr_copy_bytes(ifp, ifr->ifr_addr.sa_data, 362 ETHER_ADDR_LEN); 363 break; 364 } 365 366 default: 367 error = EOPNOTSUPP; 368 break; 369 } 370 371 return (error); 372} 373 374static void 375ether_inet_event(ifnet_t ifp, protocol_family_t protocol, 376 const struct kev_msg *event) 377{ 378#pragma unused(protocol) 379 ifaddr_t *addresses; 380 381 if (event->vendor_code != KEV_VENDOR_APPLE || 382 event->kev_class != KEV_NETWORK_CLASS || 383 event->kev_subclass != KEV_DL_SUBCLASS || 384 event->event_code != KEV_DL_LINK_ADDRESS_CHANGED) { 385 return; 386 } 387 388 if (ifnet_get_address_list_family(ifp, &addresses, AF_INET) == 0) { 389 int i; 390 391 for (i = 0; addresses[i] != NULL; i++) { 392 inet_arp_init_ifaddr(ifp, addresses[i]); 393 } 394 395 ifnet_free_address_list(addresses); 396 } 397} 398 399static errno_t 400ether_inet_arp(ifnet_t ifp, u_short arpop, const struct sockaddr_dl *sender_hw, 401 const struct sockaddr *sender_proto, const struct sockaddr_dl *target_hw, 402 const struct sockaddr *target_proto) 403{ 404 mbuf_t m; 405 errno_t result; 406 struct ether_header *eh; 407 struct ether_arp *ea; 408 const struct sockaddr_in *sender_ip = 409 (const struct sockaddr_in *)(uintptr_t)(size_t)sender_proto; 410 const struct sockaddr_inarp *target_ip = 411 (const struct sockaddr_inarp *)(uintptr_t)(size_t)target_proto; 412 char *datap; 413 414 if (target_ip == NULL) 415 return (EINVAL); 416 417 if ((sender_ip && sender_ip->sin_family != AF_INET) || 418 target_ip->sin_family != AF_INET) 419 return (EAFNOSUPPORT); 420 421 result = mbuf_gethdr(MBUF_DONTWAIT, MBUF_TYPE_DATA, &m); 422 if (result != 0) 423 return (result); 424 425 mbuf_setlen(m, sizeof (*ea)); 426 mbuf_pkthdr_setlen(m, sizeof (*ea)); 427 428 /* Move the data pointer in the mbuf to the end, aligned to 4 bytes */ 429 datap = mbuf_datastart(m); 430 datap += mbuf_trailingspace(m); 431 datap -= (((uintptr_t)datap) & 0x3); 432 mbuf_setdata(m, datap, sizeof (*ea)); 433 ea = mbuf_data(m); 434 435 /* 436 * Prepend the ethernet header, we will send the raw frame; 437 * callee frees the original mbuf when allocation fails. 438 */ 439 result = mbuf_prepend(&m, sizeof (*eh), MBUF_DONTWAIT); 440 if (result != 0) 441 return (result); 442 443 eh = mbuf_data(m); 444 eh->ether_type = htons(ETHERTYPE_ARP); 445 446#if CONFIG_MACF_NET 447 mac_mbuf_label_associate_linklayer(ifp, m); 448#endif 449 450 /* Fill out the arp header */ 451 ea->arp_pro = htons(ETHERTYPE_IP); 452 ea->arp_hln = sizeof (ea->arp_sha); 453 ea->arp_pln = sizeof (ea->arp_spa); 454 ea->arp_hrd = htons(ARPHRD_ETHER); 455 ea->arp_op = htons(arpop); 456 457 /* Sender Hardware */ 458 if (sender_hw != NULL) { 459 bcopy(CONST_LLADDR(sender_hw), ea->arp_sha, 460 sizeof (ea->arp_sha)); 461 } else { 462 ifnet_lladdr_copy_bytes(ifp, ea->arp_sha, ETHER_ADDR_LEN); 463 } 464 ifnet_lladdr_copy_bytes(ifp, eh->ether_shost, sizeof (eh->ether_shost)); 465 466 /* Sender IP */ 467 if (sender_ip != NULL) { 468 bcopy(&sender_ip->sin_addr, ea->arp_spa, sizeof (ea->arp_spa)); 469 } else { 470 struct ifaddr *ifa; 471 472 /* Look for an IP address to use as our source */ 473 ifnet_lock_shared(ifp); 474 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 475 IFA_LOCK(ifa); 476 if (ifa->ifa_addr != NULL && 477 ifa->ifa_addr->sa_family == AF_INET) { 478 bcopy(&((struct sockaddr_in *)(void *) 479 ifa->ifa_addr)->sin_addr, ea->arp_spa, 480 sizeof (ea->arp_spa)); 481 IFA_UNLOCK(ifa); 482 break; 483 } 484 IFA_UNLOCK(ifa); 485 } 486 ifnet_lock_done(ifp); 487 488 if (ifa == NULL) { 489 mbuf_freem(m); 490 return (ENXIO); 491 } 492 } 493 494 /* Target Hardware */ 495 if (target_hw == NULL) { 496 bzero(ea->arp_tha, sizeof (ea->arp_tha)); 497 bcopy(etherbroadcastaddr, eh->ether_dhost, 498 sizeof (eh->ether_dhost)); 499 } else { 500 bcopy(CONST_LLADDR(target_hw), ea->arp_tha, 501 sizeof (ea->arp_tha)); 502 bcopy(CONST_LLADDR(target_hw), eh->ether_dhost, 503 sizeof (eh->ether_dhost)); 504 } 505 506 /* Target IP */ 507 bcopy(&target_ip->sin_addr, ea->arp_tpa, sizeof (ea->arp_tpa)); 508 509 /* 510 * If this is an ARP request for a (default) router, mark 511 * the packet accordingly so that the driver can find out, 512 * in case it needs to perform driver-specific action(s). 513 */ 514 if (arpop == ARPOP_REQUEST && (target_ip->sin_other & SIN_ROUTER)) { 515 m->m_pkthdr.aux_flags |= MAUXF_INET_RESOLVE_RTR; 516 VERIFY(!(m->m_pkthdr.aux_flags & MAUXF_INET6_RESOLVE_RTR)); 517 } 518 519 if (ifp->if_eflags & IFEF_TXSTART) { 520 /* Use control service class if the interface 521 * supports transmit-start model 522 */ 523 (void) m_set_service_class(m, MBUF_SC_CTL); 524 } 525 526 ifnet_output_raw(ifp, PF_INET, m); 527 528 return (0); 529} 530 531errno_t 532ether_attach_inet(struct ifnet *ifp, protocol_family_t proto_family) 533{ 534#pragma unused(proto_family) 535 struct ifnet_attach_proto_param_v2 proto; 536 struct ifnet_demux_desc demux[2]; 537 u_short en_native = htons(ETHERTYPE_IP); 538 u_short arp_native = htons(ETHERTYPE_ARP); 539 errno_t error; 540 541 bzero(&demux[0], sizeof (demux)); 542 demux[0].type = DLIL_DESC_ETYPE2; 543 demux[0].data = &en_native; 544 demux[0].datalen = sizeof (en_native); 545 demux[1].type = DLIL_DESC_ETYPE2; 546 demux[1].data = &arp_native; 547 demux[1].datalen = sizeof (arp_native); 548 549 bzero(&proto, sizeof (proto)); 550 proto.demux_list = demux; 551 proto.demux_count = sizeof (demux) / sizeof (demux[0]); 552 proto.input = ether_inet_input; 553 proto.pre_output = ether_inet_pre_output; 554 proto.ioctl = ether_inet_prmod_ioctl; 555 proto.event = ether_inet_event; 556 proto.resolve = ether_inet_resolve_multi; 557 proto.send_arp = ether_inet_arp; 558 559 error = ifnet_attach_protocol_v2(ifp, proto_family, &proto); 560 if (error && error != EEXIST) { 561 printf("WARNING: %s can't attach ip to %s%d\n", __func__, 562 ifp->if_name, ifp->if_unit); 563 } 564 return (error); 565} 566 567void 568ether_detach_inet(struct ifnet *ifp, protocol_family_t proto_family) 569{ 570 (void) ifnet_detach_protocol(ifp, proto_family); 571} 572