2 * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved.
4 * @APPLE_LICENSE_OSREFERENCE_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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
31 * Copyright (c) 1982, 1986, 1993
32 * The Regents of the University of California. All rights reserved.
34 * Redistribution and use in source and binary forms, with or without
35 * modification, are permitted provided that the following conditions
37 * 1. Redistributions of source code must retain the above copyright
38 * notice, this list of conditions and the following disclaimer.
39 * 2. Redistributions in binary form must reproduce the above copyright
40 * notice, this list of conditions and the following disclaimer in the
41 * documentation and/or other materials provided with the distribution.
42 * 3. All advertising materials mentioning features or use of this software
43 * must display the following acknowledgement:
44 * This product includes software developed by the University of
45 * California, Berkeley and its contributors.
46 * 4. Neither the name of the University nor the names of its contributors
47 * may be used to endorse or promote products derived from this software
48 * without specific prior written permission.
50 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
51 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
54 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * @(#)if_loop.c 8.1 (Berkeley) 6/10/93
63 * $FreeBSD: src/sys/net/if_loop.c,v 1.47.2.5 2001/07/03 11:01:41 ume Exp $
67 * Loopback interface driver for protocol testing and timing.
72 #include <sys/param.h>
73 #include <sys/systm.h>
74 #include <sys/kernel.h>
76 #include <sys/socket.h>
77 #include <sys/sockio.h>
80 #include <net/if_types.h>
81 #include <net/route.h>
83 #include <sys/malloc.h>
86 #include <netinet/in.h>
87 #include <netinet/in_var.h>
91 #include <netipx/ipx.h>
92 #include <netipx/ipx_if.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
;
110 #include "bpfilter.h"
112 #include <net/bpfdesc.h>
115 #define NLOOP_ATTACHMENTS (NLOOP * 12)
117 struct lo_statics_str
{
119 bpf_packet_func bpf_callback
;
122 void loopattach(void *dummy
);
124 static struct lo_statics_str lo_statics
[NLOOP
];
125 int loopattach_done
= 0; /* used to sync ip6_init2 loopback configuration */
128 #define LOMTU (1024+512)
133 struct ifnet loif
[NLOOP
];
134 struct ifnet
*lo_ifp
= &loif
[0];
136 struct loopback_header
{
140 void lo_reg_if_mods(void);
142 /* Local forward declerations */
146 __unused ifnet_t ifp
,
149 protocol_family_t
*protocol_family
)
151 struct loopback_header
*header
= (struct loopback_header
*)frame_header
;
153 *protocol_family
= header
->protocol
;
161 __unused ifnet_t ifp
,
163 __unused
const struct sockaddr
*dest
,
164 __unused
const char *dest_linkaddr
,
165 const char *frame_type
)
167 struct loopback_header
*header
;
169 M_PREPEND(*m
, sizeof(struct loopback_header
), M_WAITOK
);
170 header
= mtod(*m
, struct loopback_header
*);
171 header
->protocol
= *(const u_long
*)frame_type
;
177 __unused
struct ifnet
*ifp
,
178 __unused u_long protocol_family
,
179 __unused
struct ddesc_head_str
*demux_desc_head
)
187 __unused ifnet_t ifp
,
188 __unused protocol_family_t protocol
)
199 if ((m
->m_flags
& M_PKTHDR
) == 0)
200 panic("lo_output: no HDR");
203 * Don't overwrite the rcvif field if it is in use.
204 * This is used to match multicast packets, sent looping
205 * back, with the appropriate group record on input.
207 if (m
->m_pkthdr
.rcvif
== NULL
)
208 m
->m_pkthdr
.rcvif
= ifp
;
210 ifp
->if_ibytes
+= m
->m_pkthdr
.len
;
211 ifp
->if_obytes
+= m
->m_pkthdr
.len
;
216 m
->m_pkthdr
.header
= mtod(m
, char *);
217 m
->m_pkthdr
.csum_data
= 0xffff; /* loopback checksums are always OK */
218 m
->m_pkthdr
.csum_flags
= CSUM_DATA_VALID
| CSUM_PSEUDO_HDR
|
219 CSUM_IP_CHECKED
| CSUM_IP_VALID
;
220 m_adj(m
, sizeof(struct loopback_header
));
223 if (lo_statics
[ifp
->if_unit
].bpf_mode
!= BPF_TAP_DISABLE
) {
227 if (ifp
->if_bpf
->bif_dlt
== DLT_NULL
) {
228 struct loopback_header
*header
;
230 * We need to prepend the address family as
231 * a four byte field. Cons up a dummy header
232 * to pacify bpf. This is safe because bpf
233 * will only read from the mbuf (i.e., it won't
234 * try to free it or keep a pointer a to it).
236 header
= (struct loopback_header
*)m
->m_pkthdr
.header
;
239 m0
.m_data
= (char *)&header
->protocol
;
243 lo_statics
[ifp
->if_unit
].bpf_callback(ifp
, n
);
247 return dlil_input(ifp
, m
, m
);
252 * This is a common pre-output route used by INET and INET6. This could
253 * (should?) be split into separate pre-output routines for each protocol.
258 __unused
struct ifnet
*ifp
,
259 u_long protocol_family
,
261 __unused
const struct sockaddr
*dst
,
264 __unused
char *dst_addr
)
267 register struct rtentry
*rt
= (struct rtentry
*) route
;
269 if (((*m
)->m_flags
& M_PKTHDR
) == 0)
270 panic("looutput no HDR");
272 if (rt
&& rt
->rt_flags
& (RTF_REJECT
|RTF_BLACKHOLE
)) {
273 if (rt
->rt_flags
& RTF_BLACKHOLE
) {
278 return ((rt
->rt_flags
& RTF_HOST
) ? EHOSTUNREACH
: ENETUNREACH
);
281 *(u_long
*)frame_type
= protocol_family
;
287 * lo_input - This should work for all attached protocols that use the
288 * ifq/schednetisr input mechanism.
294 __unused
struct ifnet
*ifp
,
295 __unused u_long protocol_family
,
296 __unused
int sync_ok
)
298 if (proto_input(protocol_family
, m
) != 0)
311 __unused
struct sockaddr
*sa
)
314 rt
->rt_rmx
.rmx_mtu
= rt
->rt_ifp
->if_mtu
; /* for ISO */
316 * For optimal performance, the send and receive buffers
317 * should be at least twice the MTU plus a little more for
320 rt
->rt_rmx
.rmx_recvpipe
=
321 rt
->rt_rmx
.rmx_sendpipe
= 3 * LOMTU
;
326 * Process an ioctl request.
334 register struct ifaddr
*ifa
;
335 register struct ifreq
*ifr
= (struct ifreq
*)data
;
336 register int error
= 0;
341 ifnet_set_flags(ifp
, IFF_UP
| IFF_RUNNING
, IFF_UP
| IFF_RUNNING
);
342 ifa
= (struct ifaddr
*)data
;
343 ifa
->ifa_rtrequest
= lortrequest
;
345 * Everything else is done at a higher level.
352 error
= EAFNOSUPPORT
; /* XXX */
355 switch (ifr
->ifr_addr
.sa_family
) {
367 error
= EAFNOSUPPORT
;
373 ifp
->if_mtu
= ifr
->ifr_mtu
;
385 #endif /* NLOOP > 0 */
388 static int lo_attach_proto(struct ifnet
*ifp
, u_long protocol_family
)
390 struct dlil_proto_reg_str reg
;
393 bzero(®
, sizeof(reg
));
394 TAILQ_INIT(®
.demux_desc_head
);
395 reg
.interface_family
= ifp
->if_family
;
396 reg
.unit_number
= ifp
->if_unit
;
397 reg
.input
= lo_input
;
398 reg
.pre_output
= lo_pre_output
;
399 reg
.protocol_family
= protocol_family
;
401 stat
= dlil_attach_protocol(®
);
403 if (stat
&& stat
!= EEXIST
) {
404 printf("lo_attach_proto: dlil_attach_protocol for %d returned=%d\n",
405 protocol_family
, stat
);
411 void lo_reg_if_mods()
415 /* Register protocol registration functions */
416 if ((error
= dlil_reg_proto_module(PF_INET
, APPLE_IF_FAM_LOOPBACK
, lo_attach_proto
, NULL
)) != 0)
417 printf("dlil_reg_proto_module failed for AF_INET error=%d\n", error
);
419 if ((error
= dlil_reg_proto_module(PF_INET6
, APPLE_IF_FAM_LOOPBACK
, lo_attach_proto
, NULL
)) != 0)
420 printf("dlil_reg_proto_module failed for AF_INET6 error=%d\n", error
);
427 bpf_packet_func bpf_callback
)
431 * NEED MUTEX HERE XXX
433 if (mode
== BPF_TAP_DISABLE
) {
434 lo_statics
[ifp
->if_unit
].bpf_mode
= mode
;
435 lo_statics
[ifp
->if_unit
].bpf_callback
= bpf_callback
;
438 lo_statics
[ifp
->if_unit
].bpf_callback
= bpf_callback
;
439 lo_statics
[ifp
->if_unit
].bpf_mode
= mode
;
449 __unused
void *dummy
)
456 for (ifp
= loif
; i
< NLOOP
; ifp
++) {
457 lo_statics
[i
].bpf_callback
= 0;
458 lo_statics
[i
].bpf_mode
= BPF_TAP_DISABLE
;
459 bzero(ifp
, sizeof(struct ifnet
));
461 ifp
->if_family
= APPLE_IF_FAM_LOOPBACK
;
464 ifp
->if_flags
= IFF_LOOPBACK
| IFF_MULTICAST
;
465 ifp
->if_ioctl
= loioctl
;
466 ifp
->if_demux
= lo_demux
;
467 ifp
->if_framer
= lo_framer
;
468 ifp
->if_add_proto
= lo_add_proto
;
469 ifp
->if_del_proto
= lo_del_proto
;
470 ifp
->if_set_bpf_tap
= lo_set_bpf_tap
;
471 ifp
->if_output
= lo_output
;
472 ifp
->if_type
= IFT_LOOP
;
473 ifp
->if_hwassist
= IF_HWASSIST_CSUM_IP
| IF_HWASSIST_CSUM_TCP
| IF_HWASSIST_CSUM_UDP
;
474 ifp
->if_hdrlen
= sizeof(struct loopback_header
);
478 bpfattach(ifp
, DLT_NULL
, sizeof(u_int
));