1 /* $KAME: if_faith.c,v 1.23 2001/12/17 13:55:29 sumikawa Exp $ */
4 * Copyright (c) 1982, 1986, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * $FreeBSD: src/sys/net/if_faith.c,v 1.3.2.6 2002/04/28 05:40:25 suz Exp $
36 * $DragonFly: src/sys/net/faith/if_faith.c,v 1.18 2008/01/11 11:59:40 sephe Exp $
40 * @(#)if_loop.c 8.1 (Berkeley) 6/10/93
41 * Id: if_loop.c,v 1.22 1996/06/19 16:24:10 wollman Exp
45 * Loopback interface driver for protocol testing and timing.
48 #include "use_faith.h"
51 #include "opt_inet6.h"
53 #include <sys/param.h>
54 #include <sys/systm.h>
55 #include <sys/kernel.h>
58 #include <sys/socket.h>
59 #include <sys/errno.h>
60 #include <sys/sockio.h>
62 #include <sys/queue.h>
63 #include <sys/types.h>
64 #include <sys/malloc.h>
67 #include <net/if_types.h>
68 #include <net/netisr.h>
69 #include <net/route.h>
71 #include <net/if_clone.h>
74 #include <netinet/in.h>
75 #include <netinet/in_systm.h>
76 #include <netinet/in_var.h>
77 #include <netinet/ip.h>
82 #include <netinet/in.h>
84 #include <netinet6/in6_var.h>
85 #include <netinet/ip6.h>
86 #include <netinet6/ip6_var.h>
89 #include <net/net_osdep.h>
91 #define FAITHNAME "faith"
94 struct ifnet sc_if
; /* must be first */
95 LIST_ENTRY(faith_softc
) sc_list
;
98 static int faithioctl (struct ifnet
*, u_long
, caddr_t
, struct ucred
*);
99 int faithoutput (struct ifnet
*, struct mbuf
*, struct sockaddr
*,
101 static void faithrtrequest (int, struct rtentry
*, struct rt_addrinfo
*);
102 static int faithprefix (struct in6_addr
*);
104 static int faithmodevent (module_t
, int, void *);
106 static MALLOC_DEFINE(M_FAITH
, FAITHNAME
, "Firewall Assisted Tunnel Interface");
107 LIST_HEAD(, faith_softc
) faith_softc_list
;
109 int faith_clone_create (struct if_clone
*, int);
110 void faith_clone_destroy (struct ifnet
*);
112 struct if_clone faith_cloner
= IF_CLONE_INITIALIZER(FAITHNAME
,
113 faith_clone_create
, faith_clone_destroy
, NFAITH
, IF_MAXUNIT
);
115 #define FAITHMTU 1500
118 faithmodevent(module_t mod
, int type
, void *data
)
123 LIST_INIT(&faith_softc_list
);
124 if_clone_attach(&faith_cloner
);
127 faithprefix_p
= faithprefix
;
133 faithprefix_p
= NULL
;
136 if_clone_detach(&faith_cloner
);
138 while (!LIST_EMPTY(&faith_softc_list
))
140 &LIST_FIRST(&faith_softc_list
)->sc_if
);
147 static moduledata_t faith_mod
= {
153 DECLARE_MODULE(if_faith
, faith_mod
, SI_SUB_PSEUDO
, SI_ORDER_ANY
);
154 MODULE_VERSION(if_faith
, 1);
157 faith_clone_create(struct if_clone
*ifc
, int unit
)
159 struct faith_softc
*sc
;
161 sc
= kmalloc(sizeof(struct faith_softc
), M_FAITH
, M_WAITOK
| M_ZERO
);
163 sc
->sc_if
.if_softc
= sc
;
164 if_initname(&(sc
->sc_if
), FAITHNAME
, unit
);
166 sc
->sc_if
.if_mtu
= FAITHMTU
;
167 /* Change to BROADCAST experimentaly to announce its prefix. */
168 sc
->sc_if
.if_flags
= /* IFF_LOOPBACK */ IFF_BROADCAST
| IFF_MULTICAST
;
169 sc
->sc_if
.if_ioctl
= faithioctl
;
170 sc
->sc_if
.if_output
= faithoutput
;
171 sc
->sc_if
.if_type
= IFT_FAITH
;
172 sc
->sc_if
.if_hdrlen
= 0;
173 sc
->sc_if
.if_addrlen
= 0;
174 sc
->sc_if
.if_snd
.ifq_maxlen
= ifqmaxlen
;
175 if_attach(&sc
->sc_if
, NULL
);
176 bpfattach(&sc
->sc_if
, DLT_NULL
, sizeof(u_int
));
177 LIST_INSERT_HEAD(&faith_softc_list
, sc
, sc_list
);
182 faith_clone_destroy(struct ifnet
*ifp
)
184 struct faith_softc
*sc
= (struct faith_softc
*) ifp
;
186 LIST_REMOVE(sc
, sc_list
);
194 faithoutput(struct ifnet
*ifp
, struct mbuf
*m
, struct sockaddr
*dst
,
199 if ((m
->m_flags
& M_PKTHDR
) == 0)
200 panic("faithoutput no HDR");
202 /* BPF write needs to be handled specially */
203 if (dst
->sa_family
== AF_UNSPEC
) {
204 dst
->sa_family
= *(mtod(m
, int *));
205 m
->m_len
-= sizeof(int);
206 m
->m_pkthdr
.len
-= sizeof(int);
207 m
->m_data
+= sizeof(int);
210 if (ifp
->if_bpf
!= NULL
) {
212 * We need to prepend the address family as
215 uint32_t af
= dst
->sa_family
;
217 bpf_ptap(ifp
->if_bpf
, m
, &af
, sizeof(af
));
220 if (rt
&& rt
->rt_flags
& (RTF_REJECT
|RTF_BLACKHOLE
)) {
222 return (rt
->rt_flags
& RTF_BLACKHOLE
? 0 :
223 rt
->rt_flags
& RTF_HOST
? EHOSTUNREACH
: ENETUNREACH
);
226 ifp
->if_obytes
+= m
->m_pkthdr
.len
;
227 switch (dst
->sa_family
) {
243 /* XXX do we need more sanity checks? */
245 m
->m_pkthdr
.rcvif
= ifp
;
247 ifp
->if_ibytes
+= m
->m_pkthdr
.len
;
248 netisr_dispatch(isr
, m
);
254 faithrtrequest(int cmd
, struct rtentry
*rt
, struct rt_addrinfo
*info
)
257 rt
->rt_rmx
.rmx_mtu
= rt
->rt_ifp
->if_mtu
; /* for ISO */
259 * For optimal performance, the send and receive buffers
260 * should be at least twice the MTU plus a little more for
263 rt
->rt_rmx
.rmx_recvpipe
=
264 rt
->rt_rmx
.rmx_sendpipe
= 3 * FAITHMTU
;
269 * Process an ioctl request.
273 faithioctl(struct ifnet
*ifp
, u_long cmd
, caddr_t data
, struct ucred
*cr
)
276 struct ifreq
*ifr
= (struct ifreq
*)data
;
282 ifp
->if_flags
|= IFF_UP
| IFF_RUNNING
;
283 ifa
= (struct ifaddr
*)data
;
284 ifa
->ifa_rtrequest
= faithrtrequest
;
286 * Everything else is done at a higher level.
293 error
= EAFNOSUPPORT
; /* XXX */
296 switch (ifr
->ifr_addr
.sa_family
) {
307 error
= EAFNOSUPPORT
;
314 ifp
->if_mtu
= ifr
->ifr_mtu
;
330 * XXX could be layer violation to call sys/net from sys/netinet6
333 faithprefix(struct in6_addr
*in6
)
336 struct sockaddr_in6 sin6
;
339 if (ip6_keepfaith
== 0)
342 bzero(&sin6
, sizeof sin6
);
343 sin6
.sin6_family
= AF_INET6
;
344 sin6
.sin6_len
= sizeof(struct sockaddr_in6
);
345 sin6
.sin6_addr
= *in6
;
346 rt
= rtpurelookup((struct sockaddr
*)&sin6
);
347 if (rt
!= NULL
&& rt
->rt_ifp
&& rt
->rt_ifp
->if_type
== IFT_FAITH
&&
348 (rt
->rt_ifp
->if_flags
& IFF_UP
))