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