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#include <kern/lock.h> 78 79#include <net/dlil.h> 80#include <net/if.h> 81#include <net/route.h> 82#include <net/if_llc.h> 83#include <net/if_dl.h> 84#include <net/if_types.h> 85#include <net/kpi_protocol.h> 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: can't handle af%d\n", if_name(ifp), 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 (struct ether_addr *)IF_LLADDR(ifp)); 355 break; 356 } 357 358 case SIOCGIFADDR: { /* struct ifreq */ 359 struct ifreq *ifr = data; 360 ifnet_guarded_lladdr_copy_bytes(ifp, ifr->ifr_addr.sa_data, 361 ETHER_ADDR_LEN); 362 break; 363 } 364 365 default: 366 error = EOPNOTSUPP; 367 break; 368 } 369 370 return (error); 371} 372 373static void 374ether_inet_event(ifnet_t ifp, protocol_family_t protocol, 375 const struct kev_msg *event) 376{ 377#pragma unused(protocol) 378 ifaddr_t *addresses; 379 380 if (event->vendor_code != KEV_VENDOR_APPLE || 381 event->kev_class != KEV_NETWORK_CLASS || 382 event->kev_subclass != KEV_DL_SUBCLASS || 383 event->event_code != KEV_DL_LINK_ADDRESS_CHANGED) { 384 return; 385 } 386 387 if (ifnet_get_address_list_family(ifp, &addresses, AF_INET) == 0) { 388 int i; 389 390 for (i = 0; addresses[i] != NULL; i++) { 391 inet_arp_init_ifaddr(ifp, addresses[i]); 392 } 393 394 ifnet_free_address_list(addresses); 395 } 396} 397 398static errno_t 399ether_inet_arp(ifnet_t ifp, u_short arpop, const struct sockaddr_dl *sender_hw, 400 const struct sockaddr *sender_proto, const struct sockaddr_dl *target_hw, 401 const struct sockaddr *target_proto) 402{ 403 mbuf_t m; 404 errno_t result; 405 struct ether_header *eh; 406 struct ether_arp *ea; 407 const struct sockaddr_in *sender_ip = 408 (const struct sockaddr_in *)(uintptr_t)(size_t)sender_proto; 409 const struct sockaddr_inarp *target_ip = 410 (const struct sockaddr_inarp *)(uintptr_t)(size_t)target_proto; 411 char *datap; 412 413 if (target_ip == NULL) 414 return (EINVAL); 415 416 if ((sender_ip && sender_ip->sin_family != AF_INET) || 417 target_ip->sin_family != AF_INET) 418 return (EAFNOSUPPORT); 419 420 result = mbuf_gethdr(MBUF_DONTWAIT, MBUF_TYPE_DATA, &m); 421 if (result != 0) 422 return (result); 423 424 mbuf_setlen(m, sizeof (*ea)); 425 mbuf_pkthdr_setlen(m, sizeof (*ea)); 426 427 /* Move the data pointer in the mbuf to the end, aligned to 4 bytes */ 428 datap = mbuf_datastart(m); 429 datap += mbuf_trailingspace(m); 430 datap -= (((uintptr_t)datap) & 0x3); 431 mbuf_setdata(m, datap, sizeof (*ea)); 432 ea = mbuf_data(m); 433 434 /* 435 * Prepend the ethernet header, we will send the raw frame; 436 * callee frees the original mbuf when allocation fails. 437 */ 438 result = mbuf_prepend(&m, sizeof (*eh), MBUF_DONTWAIT); 439 if (result != 0) 440 return (result); 441 442 eh = mbuf_data(m); 443 eh->ether_type = htons(ETHERTYPE_ARP); 444 445#if CONFIG_MACF_NET 446 mac_mbuf_label_associate_linklayer(ifp, m); 447#endif 448 449 /* Fill out the arp header */ 450 ea->arp_pro = htons(ETHERTYPE_IP); 451 ea->arp_hln = sizeof (ea->arp_sha); 452 ea->arp_pln = sizeof (ea->arp_spa); 453 ea->arp_hrd = htons(ARPHRD_ETHER); 454 ea->arp_op = htons(arpop); 455 456 /* Sender Hardware */ 457 if (sender_hw != NULL) { 458 bcopy(CONST_LLADDR(sender_hw), ea->arp_sha, 459 sizeof (ea->arp_sha)); 460 } else { 461 ifnet_lladdr_copy_bytes(ifp, ea->arp_sha, ETHER_ADDR_LEN); 462 } 463 ifnet_lladdr_copy_bytes(ifp, eh->ether_shost, sizeof (eh->ether_shost)); 464 465 /* Sender IP */ 466 if (sender_ip != NULL) { 467 bcopy(&sender_ip->sin_addr, ea->arp_spa, sizeof (ea->arp_spa)); 468 } else { 469 struct ifaddr *ifa; 470 471 /* Look for an IP address to use as our source */ 472 ifnet_lock_shared(ifp); 473 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 474 IFA_LOCK(ifa); 475 if (ifa->ifa_addr != NULL && 476 ifa->ifa_addr->sa_family == AF_INET) { 477 bcopy(&((struct sockaddr_in *)(void *) 478 ifa->ifa_addr)->sin_addr, ea->arp_spa, 479 sizeof (ea->arp_spa)); 480 IFA_UNLOCK(ifa); 481 break; 482 } 483 IFA_UNLOCK(ifa); 484 } 485 ifnet_lock_done(ifp); 486 487 if (ifa == NULL) { 488 mbuf_freem(m); 489 return (ENXIO); 490 } 491 } 492 493 /* Target Hardware */ 494 if (target_hw == NULL) { 495 bzero(ea->arp_tha, sizeof (ea->arp_tha)); 496 bcopy(etherbroadcastaddr, eh->ether_dhost, 497 sizeof (eh->ether_dhost)); 498 m->m_flags |= M_BCAST; 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 if (bcmp(eh->ether_dhost, etherbroadcastaddr, 506 ETHER_ADDR_LEN) == 0) 507 m->m_flags |= M_BCAST; 508 } 509 510 /* Target IP */ 511 bcopy(&target_ip->sin_addr, ea->arp_tpa, sizeof (ea->arp_tpa)); 512 513 /* 514 * PKTF_{INET,INET6}_RESOLVE_RTR are mutually exclusive, so make 515 * sure only one of them is set (just in case.) 516 */ 517 m->m_pkthdr.pkt_flags &= ~(PKTF_INET6_RESOLVE | PKTF_RESOLVE_RTR); 518 m->m_pkthdr.pkt_flags |= PKTF_INET_RESOLVE; 519 /* 520 * If this is an ARP request for a (default) router, mark 521 * the packet accordingly so that the driver can find out, 522 * in case it needs to perform driver-specific action(s). 523 */ 524 if (arpop == ARPOP_REQUEST && (target_ip->sin_other & SIN_ROUTER)) 525 m->m_pkthdr.pkt_flags |= PKTF_RESOLVE_RTR; 526 527 if (ifp->if_eflags & IFEF_TXSTART) { 528 /* 529 * Use control service class if the interface 530 * supports transmit-start model 531 */ 532 (void) m_set_service_class(m, MBUF_SC_CTL); 533 } 534 535 ifnet_output_raw(ifp, PF_INET, m); 536 537 return (0); 538} 539 540errno_t 541ether_attach_inet(struct ifnet *ifp, protocol_family_t proto_family) 542{ 543#pragma unused(proto_family) 544 struct ifnet_attach_proto_param_v2 proto; 545 struct ifnet_demux_desc demux[2]; 546 u_short en_native = htons(ETHERTYPE_IP); 547 u_short arp_native = htons(ETHERTYPE_ARP); 548 errno_t error; 549 550 bzero(&demux[0], sizeof (demux)); 551 demux[0].type = DLIL_DESC_ETYPE2; 552 demux[0].data = &en_native; 553 demux[0].datalen = sizeof (en_native); 554 demux[1].type = DLIL_DESC_ETYPE2; 555 demux[1].data = &arp_native; 556 demux[1].datalen = sizeof (arp_native); 557 558 bzero(&proto, sizeof (proto)); 559 proto.demux_list = demux; 560 proto.demux_count = sizeof (demux) / sizeof (demux[0]); 561 proto.input = ether_inet_input; 562 proto.pre_output = ether_inet_pre_output; 563 proto.ioctl = ether_inet_prmod_ioctl; 564 proto.event = ether_inet_event; 565 proto.resolve = ether_inet_resolve_multi; 566 proto.send_arp = ether_inet_arp; 567 568 error = ifnet_attach_protocol_v2(ifp, proto_family, &proto); 569 if (error && error != EEXIST) { 570 printf("WARNING: %s can't attach ip to %s\n", __func__, 571 if_name(ifp)); 572 } 573 return (error); 574} 575 576void 577ether_detach_inet(struct ifnet *ifp, protocol_family_t proto_family) 578{ 579 (void) ifnet_detach_protocol(ifp, proto_family); 580} 581