1/* 2 * Copyright (c) 2000-2013 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 78#include <net/dlil.h> 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#include <netinet/in.h> 86#include <netinet/in_var.h> 87#include <netinet/if_ether.h> 88#include <netinet/in_systm.h> 89#include <netinet/ip.h> 90#include <netinet/in_arp.h> 91 92#include <sys/socketvar.h> 93 94#include <net/dlil.h> 95 96/* #include "vlan.h" */ 97#if NVLAN > 0 98#include <net/if_vlan_var.h> 99#endif /* NVLAN > 0 */ 100#include <net/ether_if_module.h> 101#if CONFIG_MACF 102#include <security/mac_framework.h> 103#endif 104 105/* Local function declarations */ 106extern void *kdp_get_interface(void); 107extern void kdp_set_ip_and_mac_addresses(struct in_addr *ipaddr, 108 struct ether_addr *macaddr); 109 110#define _ip_copy(dst, src) \ 111 bcopy(src, dst, sizeof (struct in_addr)) 112 113static void 114ether_inet_arp_input(struct ifnet *ifp, struct mbuf *m) 115{ 116 struct ether_arp *ea; 117 struct sockaddr_dl sender_hw; 118 struct sockaddr_in sender_ip; 119 struct sockaddr_in target_ip; 120 121 if (mbuf_len(m) < sizeof (*ea) && mbuf_pullup(&m, sizeof (*ea)) != 0) 122 return; 123 124 ea = mbuf_data(m); 125 126 /* Verify this is an ethernet/ip arp and address lengths are correct */ 127 if (ntohs(ea->arp_hrd) != ARPHRD_ETHER || 128 ntohs(ea->arp_pro) != ETHERTYPE_IP || 129 ea->arp_pln != sizeof (struct in_addr) || 130 ea->arp_hln != ETHER_ADDR_LEN) { 131 mbuf_freem(m); 132 return; 133 } 134 135 /* Verify the sender is not broadcast */ 136 if (bcmp(ea->arp_sha, etherbroadcastaddr, ETHER_ADDR_LEN) == 0) { 137 mbuf_freem(m); 138 return; 139 } 140 141 bzero(&sender_ip, sizeof (sender_ip)); 142 sender_ip.sin_len = sizeof (sender_ip); 143 sender_ip.sin_family = AF_INET; 144 _ip_copy(&sender_ip.sin_addr, ea->arp_spa); 145 target_ip = sender_ip; 146 _ip_copy(&target_ip.sin_addr, ea->arp_tpa); 147 148 bzero(&sender_hw, sizeof (sender_hw)); 149 sender_hw.sdl_len = sizeof (sender_hw); 150 sender_hw.sdl_family = AF_LINK; 151 sender_hw.sdl_type = IFT_ETHER; 152 sender_hw.sdl_alen = ETHER_ADDR_LEN; 153 bcopy(ea->arp_sha, LLADDR(&sender_hw), ETHER_ADDR_LEN); 154 155 /* update L2 reachability record, if present */ 156 arp_llreach_set_reachable(ifp, LLADDR(&sender_hw), ETHER_ADDR_LEN); 157 158 arp_ip_handle_input(ifp, ntohs(ea->arp_op), &sender_hw, &sender_ip, 159 &target_ip); 160 mbuf_freem(m); 161} 162 163/* 164 * Process a received Ethernet packet; 165 * the packet is in the mbuf chain m without 166 * the ether header, which is provided separately. 167 */ 168static errno_t 169ether_inet_input(ifnet_t ifp, protocol_family_t protocol_family, 170 mbuf_t m_list) 171{ 172#pragma unused(ifp, protocol_family) 173 mbuf_t m; 174 mbuf_t *tailptr = &m_list; 175 mbuf_t nextpkt; 176 177 /* Strip ARP and non-IP packets out of the list */ 178 for (m = m_list; m; m = nextpkt) { 179 struct ether_header *eh = mbuf_pkthdr_header(m); 180 struct ifnet *mifp; 181 182 /* 183 * Trust the ifp in the mbuf, rather than ifproto's 184 * since the packet could have been injected via 185 * a dlil_input_packet_list() using an ifp that is 186 * different than the one where the packet really 187 * came from. 188 */ 189 mifp = mbuf_pkthdr_rcvif(m); 190 191 nextpkt = m->m_nextpkt; 192 193 if (eh->ether_type == htons(ETHERTYPE_IP)) { 194 /* 195 * Update L2 reachability record, if present 196 * (and if not a broadcast sender). 197 */ 198 if (bcmp(eh->ether_shost, etherbroadcastaddr, 199 ETHER_ADDR_LEN) != 0) { 200 arp_llreach_set_reachable(mifp, eh->ether_shost, 201 ETHER_ADDR_LEN); 202 } 203 /* put this packet in the list */ 204 *tailptr = m; 205 tailptr = &m->m_nextpkt; 206 } else { 207 /* Pass ARP packets to arp input */ 208 m->m_nextpkt = NULL; 209 if (eh->ether_type == htons(ETHERTYPE_ARP)) 210 ether_inet_arp_input(mifp, m); 211 else 212 mbuf_freem(m); 213 } 214 } 215 216 *tailptr = NULL; 217 218 /* Pass IP list to ip input */ 219 if (m_list != NULL && proto_input(PF_INET, m_list) != 0) { 220 mbuf_freem_list(m_list); 221 } 222 223 return (EJUSTRETURN); 224} 225 226static errno_t 227ether_inet_pre_output(ifnet_t ifp, protocol_family_t protocol_family, 228 mbuf_t *m0, const struct sockaddr *dst_netaddr, 229 void *route, char *type, char *edst) 230{ 231#pragma unused(protocol_family) 232 struct mbuf *m = *m0; 233 const struct ether_header *eh; 234 errno_t result = 0; 235 236 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) 237 return (ENETDOWN); 238 239 /* 240 * Tell ether_frameout it's ok to loop packet unless negated below. 241 */ 242 m->m_flags |= M_LOOP; 243 244 switch (dst_netaddr->sa_family) { 245 case AF_INET: { 246 struct sockaddr_dl ll_dest; 247 248 result = arp_lookup_ip(ifp, 249 (const struct sockaddr_in *)(uintptr_t)(size_t)dst_netaddr, 250 &ll_dest, sizeof (ll_dest), (route_t)route, *m0); 251 if (result == 0) { 252 u_int16_t ethertype_ip = htons(ETHERTYPE_IP); 253 254 bcopy(LLADDR(&ll_dest), edst, ETHER_ADDR_LEN); 255 bcopy(ðertype_ip, type, sizeof (ethertype_ip)); 256 } 257 break; 258 } 259 260 case pseudo_AF_HDRCMPLT: 261 case AF_UNSPEC: 262 m->m_flags &= ~M_LOOP; 263 eh = (const struct ether_header *)(uintptr_t)(size_t) 264 dst_netaddr->sa_data; 265 (void) memcpy(edst, eh->ether_dhost, 6); 266 bcopy(&eh->ether_type, type, sizeof (u_short)); 267 break; 268 269 default: 270 printf("%s: can't handle af%d\n", if_name(ifp), 271 dst_netaddr->sa_family); 272 273 result = EAFNOSUPPORT; 274 break; 275 } 276 277 return (result); 278} 279 280static errno_t 281ether_inet_resolve_multi(ifnet_t ifp, const struct sockaddr *proto_addr, 282 struct sockaddr_dl *out_ll, size_t ll_len) 283{ 284 static const size_t minsize = 285 offsetof(struct sockaddr_dl, sdl_data[0]) + ETHER_ADDR_LEN; 286 const struct sockaddr_in *sin = 287 (const struct sockaddr_in *)(uintptr_t)(size_t)proto_addr; 288 289 if (proto_addr->sa_family != AF_INET) 290 return (EAFNOSUPPORT); 291 292 if (proto_addr->sa_len < sizeof (struct sockaddr_in)) 293 return (EINVAL); 294 295 if (ll_len < minsize) 296 return (EMSGSIZE); 297 298 bzero(out_ll, minsize); 299 out_ll->sdl_len = minsize; 300 out_ll->sdl_family = AF_LINK; 301 out_ll->sdl_index = ifp->if_index; 302 out_ll->sdl_type = IFT_ETHER; 303 out_ll->sdl_nlen = 0; 304 out_ll->sdl_alen = ETHER_ADDR_LEN; 305 out_ll->sdl_slen = 0; 306 ETHER_MAP_IP_MULTICAST(&sin->sin_addr, LLADDR(out_ll)); 307 308 return (0); 309} 310 311static errno_t 312ether_inet_prmod_ioctl(ifnet_t ifp, protocol_family_t protocol_family, 313 u_long command, void *data) 314{ 315#pragma unused(protocol_family) 316 int error = 0; 317 318 switch (command) { 319 case SIOCSIFADDR: /* struct ifaddr pointer */ 320 case SIOCAIFADDR: { /* struct ifaddr pointer */ 321 /* 322 * Note: caller of ifnet_ioctl() passes in pointer to 323 * struct ifaddr as parameter to SIOC{A,S}IFADDR, for 324 * legacy reasons. 325 */ 326 struct ifaddr *ifa = data; 327 328 if (!(ifnet_flags(ifp) & IFF_RUNNING)) { 329 ifnet_set_flags(ifp, IFF_UP, IFF_UP); 330 ifnet_ioctl(ifp, 0, SIOCSIFFLAGS, NULL); 331 } 332 333 if (ifaddr_address_family(ifa) != AF_INET) 334 break; 335 336 inet_arp_init_ifaddr(ifp, ifa); 337 338 if (command != SIOCSIFADDR) 339 break; 340 341 /* 342 * Register new IP and MAC addresses with the kernel 343 * debugger if the interface is the same as was registered 344 * by IOKernelDebugger. If no interface was registered, 345 * fall back and just match against en0 interface. 346 * Do this only for the first address of the interface 347 * and not for aliases. 348 */ 349 if ((kdp_get_interface() != 0 && 350 kdp_get_interface() == ifp->if_softc) || 351 (kdp_get_interface() == 0 && ifp->if_unit == 0)) 352 kdp_set_ip_and_mac_addresses(&(IA_SIN(ifa)->sin_addr), 353 (struct ether_addr *)IF_LLADDR(ifp)); 354 break; 355 } 356 357 case SIOCGIFADDR: { /* struct ifreq */ 358 struct ifreq *ifr = data; 359 ifnet_guarded_lladdr_copy_bytes(ifp, ifr->ifr_addr.sa_data, 360 ETHER_ADDR_LEN); 361 break; 362 } 363 364 default: 365 error = EOPNOTSUPP; 366 break; 367 } 368 369 return (error); 370} 371 372static void 373ether_inet_event(ifnet_t ifp, protocol_family_t protocol, 374 const struct kev_msg *event) 375{ 376#pragma unused(protocol) 377 ifaddr_t *addresses; 378 379 if (event->vendor_code != KEV_VENDOR_APPLE || 380 event->kev_class != KEV_NETWORK_CLASS || 381 event->kev_subclass != KEV_DL_SUBCLASS || 382 event->event_code != KEV_DL_LINK_ADDRESS_CHANGED) { 383 return; 384 } 385 386 if (ifnet_get_address_list_family(ifp, &addresses, AF_INET) == 0) { 387 int i; 388 389 for (i = 0; addresses[i] != NULL; i++) { 390 inet_arp_init_ifaddr(ifp, addresses[i]); 391 } 392 393 ifnet_free_address_list(addresses); 394 } 395} 396 397static errno_t 398ether_inet_arp(ifnet_t ifp, u_short arpop, const struct sockaddr_dl *sender_hw, 399 const struct sockaddr *sender_proto, const struct sockaddr_dl *target_hw, 400 const struct sockaddr *target_proto) 401{ 402 mbuf_t m; 403 errno_t result; 404 struct ether_header *eh; 405 struct ether_arp *ea; 406 const struct sockaddr_in *sender_ip = 407 (const struct sockaddr_in *)(uintptr_t)(size_t)sender_proto; 408 const struct sockaddr_inarp *target_ip = 409 (const struct sockaddr_inarp *)(uintptr_t)(size_t)target_proto; 410 char *datap; 411 412 if (target_ip == NULL) 413 return (EINVAL); 414 415 if ((sender_ip && sender_ip->sin_family != AF_INET) || 416 target_ip->sin_family != AF_INET) 417 return (EAFNOSUPPORT); 418 419 result = mbuf_gethdr(MBUF_DONTWAIT, MBUF_TYPE_DATA, &m); 420 if (result != 0) 421 return (result); 422 423 mbuf_setlen(m, sizeof (*ea)); 424 mbuf_pkthdr_setlen(m, sizeof (*ea)); 425 426 /* Move the data pointer in the mbuf to the end, aligned to 4 bytes */ 427 datap = mbuf_datastart(m); 428 datap += mbuf_trailingspace(m); 429 datap -= (((uintptr_t)datap) & 0x3); 430 mbuf_setdata(m, datap, sizeof (*ea)); 431 ea = mbuf_data(m); 432 433 /* 434 * Prepend the ethernet header, we will send the raw frame; 435 * callee frees the original mbuf when allocation fails. 436 */ 437 result = mbuf_prepend(&m, sizeof (*eh), MBUF_DONTWAIT); 438 if (result != 0) 439 return (result); 440 441 eh = mbuf_data(m); 442 eh->ether_type = htons(ETHERTYPE_ARP); 443 444#if CONFIG_MACF_NET 445 mac_mbuf_label_associate_linklayer(ifp, m); 446#endif 447 448 /* Fill out the arp header */ 449 ea->arp_pro = htons(ETHERTYPE_IP); 450 ea->arp_hln = sizeof (ea->arp_sha); 451 ea->arp_pln = sizeof (ea->arp_spa); 452 ea->arp_hrd = htons(ARPHRD_ETHER); 453 ea->arp_op = htons(arpop); 454 455 /* Sender Hardware */ 456 if (sender_hw != NULL) { 457 bcopy(CONST_LLADDR(sender_hw), ea->arp_sha, 458 sizeof (ea->arp_sha)); 459 } else { 460 ifnet_lladdr_copy_bytes(ifp, ea->arp_sha, ETHER_ADDR_LEN); 461 } 462 ifnet_lladdr_copy_bytes(ifp, eh->ether_shost, sizeof (eh->ether_shost)); 463 464 /* Sender IP */ 465 if (sender_ip != NULL) { 466 bcopy(&sender_ip->sin_addr, ea->arp_spa, sizeof (ea->arp_spa)); 467 } else { 468 struct ifaddr *ifa; 469 470 /* Look for an IP address to use as our source */ 471 ifnet_lock_shared(ifp); 472 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 473 IFA_LOCK(ifa); 474 if (ifa->ifa_addr != NULL && 475 ifa->ifa_addr->sa_family == AF_INET) { 476 bcopy(&((struct sockaddr_in *)(void *) 477 ifa->ifa_addr)->sin_addr, ea->arp_spa, 478 sizeof (ea->arp_spa)); 479 IFA_UNLOCK(ifa); 480 break; 481 } 482 IFA_UNLOCK(ifa); 483 } 484 ifnet_lock_done(ifp); 485 486 if (ifa == NULL) { 487 mbuf_freem(m); 488 return (ENXIO); 489 } 490 } 491 492 /* Target Hardware */ 493 if (target_hw == NULL) { 494 bzero(ea->arp_tha, sizeof (ea->arp_tha)); 495 bcopy(etherbroadcastaddr, eh->ether_dhost, 496 sizeof (eh->ether_dhost)); 497 m->m_flags |= M_BCAST; 498 } else { 499 bcopy(CONST_LLADDR(target_hw), ea->arp_tha, 500 sizeof (ea->arp_tha)); 501 bcopy(CONST_LLADDR(target_hw), eh->ether_dhost, 502 sizeof (eh->ether_dhost)); 503 504 if (bcmp(eh->ether_dhost, etherbroadcastaddr, 505 ETHER_ADDR_LEN) == 0) 506 m->m_flags |= M_BCAST; 507 } 508 509 /* Target IP */ 510 bcopy(&target_ip->sin_addr, ea->arp_tpa, sizeof (ea->arp_tpa)); 511 512 /* 513 * PKTF_{INET,INET6}_RESOLVE_RTR are mutually exclusive, so make 514 * sure only one of them is set (just in case.) 515 */ 516 m->m_pkthdr.pkt_flags &= ~(PKTF_INET6_RESOLVE | PKTF_RESOLVE_RTR); 517 m->m_pkthdr.pkt_flags |= PKTF_INET_RESOLVE; 518 /* 519 * If this is an ARP request for a (default) router, mark 520 * the packet accordingly so that the driver can find out, 521 * in case it needs to perform driver-specific action(s). 522 */ 523 if (arpop == ARPOP_REQUEST && (target_ip->sin_other & SIN_ROUTER)) 524 m->m_pkthdr.pkt_flags |= PKTF_RESOLVE_RTR; 525 526 if (ifp->if_eflags & IFEF_TXSTART) { 527 /* 528 * Use control service class if the interface 529 * supports transmit-start model 530 */ 531 (void) m_set_service_class(m, MBUF_SC_CTL); 532 } 533 534 ifnet_output_raw(ifp, PF_INET, m); 535 536 return (0); 537} 538 539errno_t 540ether_attach_inet(struct ifnet *ifp, protocol_family_t proto_family) 541{ 542#pragma unused(proto_family) 543 struct ifnet_attach_proto_param_v2 proto; 544 struct ifnet_demux_desc demux[2]; 545 u_short en_native = htons(ETHERTYPE_IP); 546 u_short arp_native = htons(ETHERTYPE_ARP); 547 errno_t error; 548 549 bzero(&demux[0], sizeof (demux)); 550 demux[0].type = DLIL_DESC_ETYPE2; 551 demux[0].data = &en_native; 552 demux[0].datalen = sizeof (en_native); 553 demux[1].type = DLIL_DESC_ETYPE2; 554 demux[1].data = &arp_native; 555 demux[1].datalen = sizeof (arp_native); 556 557 bzero(&proto, sizeof (proto)); 558 proto.demux_list = demux; 559 proto.demux_count = sizeof (demux) / sizeof (demux[0]); 560 proto.input = ether_inet_input; 561 proto.pre_output = ether_inet_pre_output; 562 proto.ioctl = ether_inet_prmod_ioctl; 563 proto.event = ether_inet_event; 564 proto.resolve = ether_inet_resolve_multi; 565 proto.send_arp = ether_inet_arp; 566 567 error = ifnet_attach_protocol_v2(ifp, proto_family, &proto); 568 if (error && error != EEXIST) { 569 printf("WARNING: %s can't attach ip to %s\n", __func__, 570 if_name(ifp)); 571 } 572 return (error); 573} 574 575void 576ether_detach_inet(struct ifnet *ifp, protocol_family_t proto_family) 577{ 578 (void) ifnet_detach_protocol(ifp, proto_family); 579} 580