2  * Copyright (c) 2000-2010 Apple Inc. All rights reserved. 
   4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 
   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. 
  15  * Please obtain a copy of the License at 
  16  * http://www.opensource.apple.com/apsl/ and read it before using this file. 
  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. 
  26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 
  29  * Copyright (c) 1982, 1986, 1993 
  30  *      The Regents of the University of California.  All rights reserved. 
  32  * Redistribution and use in source and binary forms, with or without 
  33  * modification, are permitted provided that the following conditions 
  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. 
  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 
  60  *      @(#)if_loop.c   8.1 (Berkeley) 6/10/93 
  61  * $FreeBSD: src/sys/net/if_loop.c,v 1.47.2.5 2001/07/03 11:01:41 ume Exp $ 
  64  * NOTICE: This file was modified by SPARTA, Inc. in 2006 to introduce 
  65  * support for mandatory and extensible security protections.  This notice 
  66  * is included in support of clause 2.2 (b) of the Apple Public License, 
  71  * Loopback interface driver for protocol testing and timing. 
  76 #include <sys/param.h> 
  77 #include <sys/systm.h> 
  78 #include <sys/kernel.h> 
  80 #include <sys/socket.h> 
  81 #include <sys/sockio.h> 
  82 #include <sys/mcache.h> 
  85 #include <net/if_types.h> 
  86 #include <net/route.h> 
  88 #include <sys/malloc.h> 
  91 #include <netinet/in.h> 
  92 #include <netinet/in_var.h> 
  97 #include <netinet/in.h> 
  99 #include <netinet6/in6_var.h> 
 100 #include <netinet/ip6.h> 
 103 #include <net/dlil.h> 
 104 #include <net/kpi_protocol.h> 
 107 extern struct ifqueue atalkintrq
; 
 111 #include <security/mac_framework.h> 
 114 #define NLOOP_ATTACHMENTS (NLOOP * 12) 
 116 struct lo_statics_str 
{ 
 118         bpf_packet_func bpf_callback
; 
 121 void loopattach(void); 
 123 static struct lo_statics_str lo_statics
[NLOOP
]; 
 124 int loopattach_done 
= 0; /* used to sync ip6_init2 loopback configuration */ 
 127 #define LOMTU   (1024+512) 
 132 ifnet_t lo_ifp 
= NULL
; 
 134 struct  loopback_header 
{ 
 135         protocol_family_t       protocol
; 
 138 static void lo_reg_if_mods(void); 
 140 /* Local forward declerations */ 
 144     __unused ifnet_t    ifp
, 
 147     protocol_family_t   
*protocol_family
) 
 149         struct loopback_header 
*header 
= (struct loopback_header 
*)frame_header
; 
 151         *protocol_family 
= header
->protocol
; 
 159     __unused ifnet_t                            ifp
, 
 161     __unused 
const struct sockaddr      
*dest
, 
 162     __unused 
const char                 *dest_linkaddr
, 
 163     const char                                          *frame_type
) 
 165         struct loopback_header  
*header
; 
 167         M_PREPEND(*m
, sizeof(struct loopback_header
), M_WAITOK
); 
 169                 return EJUSTRETURN
; /* Tell caller not to try to free passed-in mbuf */ 
 170         header 
= mtod(*m
, struct loopback_header
*); 
 171         header
->protocol 
= *(const u_int32_t
*)frame_type
; 
 177     __unused ifnet_t                                            interface
, 
 178         __unused protocol_family_t                              protocol_family
, 
 179         __unused 
const struct ifnet_demux_desc  
*demux_array
, 
 180         __unused u_int32_t                                              demux_count
) 
 188         __unused ifnet_t                        ifp
, 
 189         __unused protocol_family_t      protocol
) 
 201         for (m 
= m_list
; m
; m 
= m
->m_nextpkt
) { 
 202                 if ((m
->m_flags 
& M_PKTHDR
) == 0) 
 203                         panic("lo_output: no HDR"); 
 206                  * Don't overwrite the rcvif field if it is in use. 
 207                  *  This is used to match multicast packets, sent looping 
 208                  *  back, with the appropriate group record on input. 
 210                 if (m
->m_pkthdr
.rcvif 
== NULL
) 
 211                         m
->m_pkthdr
.rcvif 
= ifp
; 
 213                 atomic_add_64(&ifp
->if_ibytes
, m
->m_pkthdr
.len
); 
 214                 atomic_add_64(&ifp
->if_obytes
, m
->m_pkthdr
.len
); 
 216                 atomic_add_64(&ifp
->if_opackets
, 1); 
 217                 atomic_add_64(&ifp
->if_ipackets
, 1); 
 219                 m
->m_pkthdr
.header 
= mtod(m
, char *); 
 220                 if (apple_hwcksum_tx 
!= 0) { 
 221                         /* loopback checksums are always OK */ 
 222                         m
->m_pkthdr
.csum_data 
= 0xffff; 
 223                         m
->m_pkthdr
.csum_flags 
= CSUM_DATA_VALID 
| CSUM_PSEUDO_HDR 
| 
 224                                 CSUM_IP_CHECKED 
| CSUM_IP_VALID
; 
 226                 m_adj(m
, sizeof(struct loopback_header
)); 
 229                         /* We need to prepend the address family as a four byte field. */ 
 230                         u_int32_t protocol_family 
= 
 231                                 ((struct loopback_header
*)m
->m_pkthdr
.header
)->protocol
; 
 233                         bpf_tap_out(ifp
, DLT_NULL
, m
, &protocol_family
, sizeof(protocol_family
)); 
 237         return ifnet_input(ifp
, m_list
, NULL
); 
 242  * This is a common pre-output route used by INET and INET6. This could 
 243  * (should?) be split into separate pre-output routines for each protocol. 
 248         __unused ifnet_t        ifp
, 
 249         protocol_family_t       protocol_family
, 
 251         __unused 
const struct sockaddr  
*dst
, 
 254         __unused 
char           *dst_addr
) 
 257         register struct rtentry 
*rt 
= route
; 
 259         (*m
)->m_flags 
|= M_LOOP
; 
 261         if (((*m
)->m_flags 
& M_PKTHDR
) == 0) 
 262                 panic("looutput no HDR"); 
 265                 u_int32_t rt_flags 
= rt
->rt_flags
; 
 266                 if (rt_flags 
& (RTF_REJECT 
| RTF_BLACKHOLE
)) { 
 267                         if (rt_flags 
& RTF_BLACKHOLE
) { 
 271                                 return ((rt_flags 
& RTF_HOST
) ? 
 272                                     EHOSTUNREACH 
: ENETUNREACH
); 
 277         *(protocol_family_t
*)frame_type 
= protocol_family
; 
 283  *  lo_input - This should work for all attached protocols that use the 
 284  *             ifq/schednetisr input mechanism. 
 288         __unused ifnet_t                        ifp
, 
 289         __unused protocol_family_t      protocol_family
, 
 292         if (proto_input(protocol_family
, m
) != 0) 
 305         __unused 
struct sockaddr 
*sa
) 
 308                 RT_LOCK_ASSERT_HELD(rt
); 
 309                 rt
->rt_rmx
.rmx_mtu 
= rt
->rt_ifp
->if_mtu
; /* for ISO */ 
 311                  * For optimal performance, the send and receive buffers 
 312                  * should be at least twice the MTU plus a little more for 
 315                 rt
->rt_rmx
.rmx_recvpipe 
=  
 316                         rt
->rt_rmx
.rmx_sendpipe 
= 3 * LOMTU
; 
 321  * Process an ioctl request. 
 329         register struct ifaddr 
*ifa
; 
 330         register struct ifreq 
*ifr 
= (struct ifreq 
*)data
; 
 331         register int error 
= 0; 
 336                 ifnet_set_flags(ifp
, IFF_UP 
| IFF_RUNNING
, IFF_UP 
| IFF_RUNNING
); 
 337                 ifa 
= (struct ifaddr 
*)data
; 
 339                 ifa
->ifa_rtrequest 
= lortrequest
; 
 342                  * Everything else is done at a higher level. 
 349                         error 
= EAFNOSUPPORT
;           /* XXX */ 
 352                 switch (ifr
->ifr_addr
.sa_family
) { 
 364                         error 
= EAFNOSUPPORT
; 
 370                 ifp
->if_mtu 
= ifr
->ifr_mtu
; 
 382 #endif /* NLOOP > 0 */ 
 385 static errno_t  
lo_attach_proto(ifnet_t ifp
, protocol_family_t protocol_family
) 
 387         struct ifnet_attach_proto_param_v2      proto
; 
 390         bzero(&proto
, sizeof(proto
)); 
 391         proto
.input 
= lo_input
; 
 392         proto
.pre_output 
= lo_pre_output
; 
 394         result 
= ifnet_attach_protocol_v2(ifp
, protocol_family
, &proto
); 
 396         if (result 
&& result 
!= EEXIST
) { 
 397                 printf("lo_attach_proto: ifnet_attach_protocol for %u returned=%d\n", 
 398                            protocol_family
, result
); 
 404 static void lo_reg_if_mods(void) 
 408         /* Register protocol registration functions */ 
 409         if ((error 
= proto_register_plumber(PF_INET
, APPLE_IF_FAM_LOOPBACK
, lo_attach_proto
, NULL
)) != 0) 
 410                 printf("proto_register_plumber failed for AF_INET error=%d\n", error
); 
 412         if ((error 
= proto_register_plumber(PF_INET6
, APPLE_IF_FAM_LOOPBACK
, lo_attach_proto
, NULL
)) != 0) 
 413                 printf("proto_register_plumber failed for AF_INET6 error=%d\n", error
); 
 420         bpf_packet_func bpf_callback
) 
 424    * NEED MUTEX HERE XXX 
 426         if (mode 
== BPF_TAP_DISABLE
) { 
 427                 lo_statics
[ifp
->if_unit
].bpf_mode 
= mode
; 
 428                 lo_statics
[ifp
->if_unit
].bpf_callback 
= bpf_callback
; 
 431                 lo_statics
[ifp
->if_unit
].bpf_callback 
= bpf_callback
; 
 432                 lo_statics
[ifp
->if_unit
].bpf_mode 
= mode
;                
 443         struct ifnet_init_params        lo_init
; 
 447 More than one loopback interface is 
not supported
. 
 452         lo_statics
[0].bpf_callback 
= 0; 
 453         lo_statics
[0].bpf_mode      
= BPF_TAP_DISABLE
; 
 455         bzero(&lo_init
, sizeof(lo_init
)); 
 458         lo_init
.family 
= IFNET_FAMILY_LOOPBACK
; 
 459         lo_init
.type 
= IFT_LOOP
; 
 460         lo_init
.output 
= lo_output
; 
 461         lo_init
.demux 
= lo_demux
; 
 462         lo_init
.add_proto 
= lo_add_proto
; 
 463         lo_init
.del_proto 
= lo_del_proto
; 
 464         lo_init
.framer 
= lo_framer
; 
 465         lo_init
.softc 
= &lo_statics
[0]; 
 466         lo_init
.ioctl 
= loioctl
; 
 467         lo_init
.set_bpf_tap 
= lo_set_bpf_tap
; 
 468         result 
= ifnet_allocate(&lo_init
, &lo_ifp
); 
 470                 printf("ifnet_allocate for lo0 failed - %d\n", result
); 
 474         ifnet_set_mtu(lo_ifp
, LOMTU
); 
 475         ifnet_set_flags(lo_ifp
, IFF_LOOPBACK 
| IFF_MULTICAST
, IFF_LOOPBACK 
| IFF_MULTICAST
); 
 476         ifnet_set_offload(lo_ifp
, IFNET_CSUM_IP 
| IFNET_CSUM_TCP 
| IFNET_CSUM_UDP 
| 
 477                 IFNET_CSUM_TCPIPV6 
| IFNET_CSUM_UDPIPV6 
| IFNET_IPV6_FRAGMENT 
| 
 478                 IFNET_CSUM_FRAGMENT 
| IFNET_IP_FRAGMENT 
| IFNET_MULTIPAGES
); 
 479         ifnet_set_hdrlen(lo_ifp
, sizeof(struct loopback_header
)); 
 480         ifnet_set_eflags(lo_ifp
, IFEF_SENDLIST
, IFEF_SENDLIST
); 
 483                 mac_ifnet_label_init(ifp
); 
 486         result 
= ifnet_attach(lo_ifp
, NULL
); 
 488                 printf("ifnet_attach lo0 failed - %d\n", result
); 
 491         bpfattach(lo_ifp
, DLT_NULL
, sizeof(u_int
));