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
));