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
*);
103 static int faithprefix (struct in6_addr
*);
106 static int faithmodevent (module_t
, int, void *);
108 static MALLOC_DEFINE(M_FAITH
, FAITHNAME
, "Firewall Assisted Tunnel Interface");
109 LIST_HEAD(, faith_softc
) faith_softc_list
;
111 int faith_clone_create (struct if_clone
*, int);
112 void faith_clone_destroy (struct ifnet
*);
114 struct if_clone faith_cloner
= IF_CLONE_INITIALIZER(FAITHNAME
,
115 faith_clone_create
, faith_clone_destroy
, NFAITH
, IF_MAXUNIT
);
117 #define FAITHMTU 1500
120 faithmodevent(module_t mod
, int type
, void *data
)
125 LIST_INIT(&faith_softc_list
);
126 if_clone_attach(&faith_cloner
);
129 faithprefix_p
= faithprefix
;
135 faithprefix_p
= NULL
;
138 if_clone_detach(&faith_cloner
);
140 while (!LIST_EMPTY(&faith_softc_list
))
142 &LIST_FIRST(&faith_softc_list
)->sc_if
);
149 static moduledata_t faith_mod
= {
155 DECLARE_MODULE(if_faith
, faith_mod
, SI_SUB_PSEUDO
, SI_ORDER_ANY
);
156 MODULE_VERSION(if_faith
, 1);
159 faith_clone_create(struct if_clone
*ifc
, int unit
)
161 struct faith_softc
*sc
;
163 sc
= kmalloc(sizeof(struct faith_softc
), M_FAITH
, M_WAITOK
| M_ZERO
);
165 sc
->sc_if
.if_softc
= sc
;
166 if_initname(&(sc
->sc_if
), FAITHNAME
, unit
);
168 sc
->sc_if
.if_mtu
= FAITHMTU
;
169 /* Change to BROADCAST experimentaly to announce its prefix. */
170 sc
->sc_if
.if_flags
= /* IFF_LOOPBACK */ IFF_BROADCAST
| IFF_MULTICAST
;
171 sc
->sc_if
.if_ioctl
= faithioctl
;
172 sc
->sc_if
.if_output
= faithoutput
;
173 sc
->sc_if
.if_type
= IFT_FAITH
;
174 sc
->sc_if
.if_hdrlen
= 0;
175 sc
->sc_if
.if_addrlen
= 0;
176 sc
->sc_if
.if_snd
.ifq_maxlen
= ifqmaxlen
;
177 if_attach(&sc
->sc_if
, NULL
);
178 bpfattach(&sc
->sc_if
, DLT_NULL
, sizeof(u_int
));
179 LIST_INSERT_HEAD(&faith_softc_list
, sc
, sc_list
);
184 faith_clone_destroy(struct ifnet
*ifp
)
186 struct faith_softc
*sc
= (struct faith_softc
*) ifp
;
188 LIST_REMOVE(sc
, sc_list
);
196 faithoutput(struct ifnet
*ifp
, struct mbuf
*m
, struct sockaddr
*dst
,
201 if ((m
->m_flags
& M_PKTHDR
) == 0)
202 panic("faithoutput no HDR");
204 /* BPF write needs to be handled specially */
205 if (dst
->sa_family
== AF_UNSPEC
) {
206 dst
->sa_family
= *(mtod(m
, int *));
207 m
->m_len
-= sizeof(int);
208 m
->m_pkthdr
.len
-= sizeof(int);
209 m
->m_data
+= sizeof(int);
212 if (ifp
->if_bpf
!= NULL
) {
214 * We need to prepend the address family as
217 uint32_t af
= dst
->sa_family
;
219 bpf_ptap(ifp
->if_bpf
, m
, &af
, sizeof(af
));
222 if (rt
&& rt
->rt_flags
& (RTF_REJECT
|RTF_BLACKHOLE
)) {
224 return (rt
->rt_flags
& RTF_BLACKHOLE
? 0 :
225 rt
->rt_flags
& RTF_HOST
? EHOSTUNREACH
: ENETUNREACH
);
228 ifp
->if_obytes
+= m
->m_pkthdr
.len
;
229 switch (dst
->sa_family
) {
245 /* XXX do we need more sanity checks? */
247 m
->m_pkthdr
.rcvif
= ifp
;
249 ifp
->if_ibytes
+= m
->m_pkthdr
.len
;
250 netisr_dispatch(isr
, m
);
256 faithrtrequest(int cmd
, struct rtentry
*rt
, struct rt_addrinfo
*info
)
259 rt
->rt_rmx
.rmx_mtu
= rt
->rt_ifp
->if_mtu
; /* for ISO */
261 * For optimal performance, the send and receive buffers
262 * should be at least twice the MTU plus a little more for
265 rt
->rt_rmx
.rmx_recvpipe
=
266 rt
->rt_rmx
.rmx_sendpipe
= 3 * FAITHMTU
;
271 * Process an ioctl request.
275 faithioctl(struct ifnet
*ifp
, u_long cmd
, caddr_t data
, struct ucred
*cr
)
278 struct ifreq
*ifr
= (struct ifreq
*)data
;
284 ifp
->if_flags
|= IFF_UP
| IFF_RUNNING
;
285 ifa
= (struct ifaddr
*)data
;
286 ifa
->ifa_rtrequest
= faithrtrequest
;
288 * Everything else is done at a higher level.
295 error
= EAFNOSUPPORT
; /* XXX */
298 switch (ifr
->ifr_addr
.sa_family
) {
309 error
= EAFNOSUPPORT
;
316 ifp
->if_mtu
= ifr
->ifr_mtu
;
332 * XXX could be layer violation to call sys/net from sys/netinet6
335 faithprefix(struct in6_addr
*in6
)
338 struct sockaddr_in6 sin6
;
341 if (ip6_keepfaith
== 0)
344 bzero(&sin6
, sizeof sin6
);
345 sin6
.sin6_family
= AF_INET6
;
346 sin6
.sin6_len
= sizeof(struct sockaddr_in6
);
347 sin6
.sin6_addr
= *in6
;
348 rt
= rtpurelookup((struct sockaddr
*)&sin6
);
349 if (rt
!= NULL
&& rt
->rt_ifp
&& rt
->rt_ifp
->if_type
== IFT_FAITH
&&
350 (rt
->rt_ifp
->if_flags
& IFF_UP
))