1 /* $NetBSD: if_faith.c,v 1.44 2008/10/24 17:07:33 dyoung Exp $ */
2 /* $KAME: if_faith.c,v 1.21 2001/02/20 07:59:26 itojun Exp $ */
5 * Copyright (c) 1982, 1986, 1993
6 * The Regents of the University of California. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * @(#)if_loop.c 8.1 (Berkeley) 6/10/93
35 * Id: if_loop.c,v 1.22 1996/06/19 16:24:10 wollman Exp
39 * IPv6-to-IPv4 TCP relay capturing interface
42 #include <sys/cdefs.h>
43 __KERNEL_RCSID(0, "$NetBSD: if_faith.c,v 1.44 2008/10/24 17:07:33 dyoung Exp $");
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/kernel.h>
51 #include <sys/socket.h>
52 #include <sys/errno.h>
53 #include <sys/ioctl.h>
55 #include <sys/queue.h>
60 #include <net/if_types.h>
61 #include <net/netisr.h>
62 #include <net/route.h>
64 #include <net/if_faith.h>
67 #include <netinet/in.h>
68 #include <netinet/in_systm.h>
69 #include <netinet/in_var.h>
70 #include <netinet/ip.h>
75 #include <netinet/in.h>
77 #include <netinet6/in6_var.h>
78 #include <netinet/ip6.h>
79 #include <netinet6/ip6_var.h>
84 #include <net/net_osdep.h>
86 static int faithioctl(struct ifnet
*, u_long
, void *);
87 static int faithoutput(struct ifnet
*, struct mbuf
*,
88 const struct sockaddr
*, struct rtentry
*);
89 static void faithrtrequest(int, struct rtentry
*,
90 const struct rt_addrinfo
*);
92 void faithattach(int);
94 static int faith_clone_create(struct if_clone
*, int);
95 static int faith_clone_destroy(struct ifnet
*);
97 static struct if_clone faith_cloner
=
98 IF_CLONE_INITIALIZER("faith", faith_clone_create
, faith_clone_destroy
);
100 #define FAITHMTU 1500
104 faithattach(int count
)
107 if_clone_attach(&faith_cloner
);
111 faith_clone_create(struct if_clone
*ifc
, int unit
)
115 ifp
= if_alloc(IFT_FAITH
);
117 if_initname(ifp
, ifc
->ifc_name
, unit
);
119 ifp
->if_mtu
= FAITHMTU
;
120 /* Change to BROADCAST experimentaly to announce its prefix. */
121 ifp
->if_flags
= /* IFF_LOOPBACK */ IFF_BROADCAST
| IFF_MULTICAST
;
122 ifp
->if_ioctl
= faithioctl
;
123 ifp
->if_output
= faithoutput
;
124 ifp
->if_type
= IFT_FAITH
;
127 ifp
->if_dlt
= DLT_NULL
;
131 bpfattach(ifp
, DLT_NULL
, sizeof(u_int
));
137 faith_clone_destroy(struct ifnet
*ifp
)
150 faithoutput(struct ifnet
*ifp
, struct mbuf
*m
, const struct sockaddr
*dst
,
155 struct ifqueue
*ifq
= 0;
157 if ((m
->m_flags
& M_PKTHDR
) == 0)
158 panic("faithoutput no HDR");
161 /* BPF write needs to be handled specially */
162 if (af
== AF_UNSPEC
) {
163 af
= *(mtod(m
, int *));
164 m_adj(m
, sizeof(int));
168 bpf_mtap_af(ifp
->if_bpf
, af
, m
);
171 if (rt
&& rt
->rt_flags
& (RTF_REJECT
|RTF_BLACKHOLE
)) {
173 return (rt
->rt_flags
& RTF_BLACKHOLE
? 0 :
174 rt
->rt_flags
& RTF_HOST
? EHOSTUNREACH
: ENETUNREACH
);
177 ifp
->if_obytes
+= m
->m_pkthdr
.len
;
196 /* XXX do we need more sanity checks? */
198 m
->m_pkthdr
.rcvif
= ifp
;
209 ifp
->if_ibytes
+= m
->m_pkthdr
.len
;
216 faithrtrequest(int cmd
, struct rtentry
*rt
,
217 const struct rt_addrinfo
*info
)
220 rt
->rt_rmx
.rmx_mtu
= rt
->rt_ifp
->if_mtu
; /* for ISO */
224 * Process an ioctl request.
228 faithioctl(struct ifnet
*ifp
, u_long cmd
, void *data
)
231 struct ifreq
*ifr
= (struct ifreq
*)data
;
237 ifp
->if_flags
|= IFF_UP
| IFF_RUNNING
;
238 ifa
= (struct ifaddr
*)data
;
239 ifa
->ifa_rtrequest
= faithrtrequest
;
241 * Everything else is done at a higher level.
248 error
= EAFNOSUPPORT
; /* XXX */
251 switch (ifr
->ifr_addr
.sa_family
) {
262 error
= EAFNOSUPPORT
;
268 if ((error
= ifioctl_common(ifp
, cmd
, data
)) == ENETRESET
)
278 * XXX could be layer violation to call sys/net from sys/netinet6
281 faithprefix(struct in6_addr
*in6
)
284 struct sockaddr_in6 sin6
;
287 if (ip6_keepfaith
== 0)
290 memset(&sin6
, 0, sizeof(sin6
));
291 sin6
.sin6_family
= AF_INET6
;
292 sin6
.sin6_len
= sizeof(struct sockaddr_in6
);
293 sin6
.sin6_addr
= *in6
;
294 rt
= rtalloc1((struct sockaddr
*)&sin6
, 0);
295 if (rt
&& rt
->rt_ifp
&& rt
->rt_ifp
->if_type
== IFT_FAITH
&&
296 (rt
->rt_ifp
->if_flags
& IFF_UP
) != 0)