summaryrefslogtreecommitdiffstats
path: root/sys/net/if_faith.c
diff options
context:
space:
mode:
authorume <ume@FreeBSD.org>2001-06-11 12:39:29 +0000
committerume <ume@FreeBSD.org>2001-06-11 12:39:29 +0000
commit832f8d224926758a9ae0b23a6b45353e44fbc87a (patch)
treea79fc7ad2b97862c4a404f352f0211ad93a7b5f1 /sys/net/if_faith.c
parent2693854b01a52b0395a91322aa3edf926bddff38 (diff)
downloadFreeBSD-src-832f8d224926758a9ae0b23a6b45353e44fbc87a.zip
FreeBSD-src-832f8d224926758a9ae0b23a6b45353e44fbc87a.tar.gz
Sync with recent KAME.
This work was based on kame-20010528-freebsd43-snap.tgz and some critical problem after the snap was out were fixed. There are many many changes since last KAME merge. TODO: - The definitions of SADB_* in sys/net/pfkeyv2.h are still different from RFC2407/IANA assignment because of binary compatibility issue. It should be fixed under 5-CURRENT. - ip6po_m member of struct ip6_pktopts is no longer used. But, it is still there because of binary compatibility issue. It should be removed under 5-CURRENT. Reviewed by: itojun Obtained from: KAME MFC after: 3 weeks
Diffstat (limited to 'sys/net/if_faith.c')
-rw-r--r--sys/net/if_faith.c241
1 files changed, 234 insertions, 7 deletions
diff --git a/sys/net/if_faith.c b/sys/net/if_faith.c
index b28fecd..840b77b 100644
--- a/sys/net/if_faith.c
+++ b/sys/net/if_faith.c
@@ -1,3 +1,5 @@
+/* $KAME: if_faith.c,v 1.21 2001/02/20 07:59:26 itojun Exp $ */
+
/*
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
@@ -41,30 +43,58 @@
/*
* Loopback interface driver for protocol testing and timing.
*/
+#include "opt_inet.h"
+#include "opt_inet6.h"
#include "faith.h"
+#if NFAITH > 0
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
+#include <sys/errno.h>
#include <sys/sockio.h>
+#include <sys/time.h>
+#include <sys/queue.h>
#include <net/if.h>
#include <net/if_types.h>
#include <net/netisr.h>
#include <net/route.h>
#include <net/bpf.h>
+#include <net/if_faith.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#endif
+
+#ifdef INET6
+#ifndef INET
+#include <netinet/in.h>
+#endif
+#include <netinet6/in6_var.h>
+#include <netinet/ip6.h>
+#include <netinet6/ip6_var.h>
+#endif
+
+#include "bpf.h"
+#define NBPFILTER NBPF
#include <net/net_osdep.h>
-extern int loioctl __P((struct ifnet *, u_long, caddr_t));
-extern int looutput __P((struct ifnet *ifp,
- struct mbuf *m, struct sockaddr *dst, struct rtentry *rt));
+static int faithioctl __P((struct ifnet *, u_long, caddr_t));
+int faithoutput __P((struct ifnet *, struct mbuf *, struct sockaddr *,
+ struct rtentry *));
+static void faithrtrequest __P((int, struct rtentry *, struct sockaddr *));
void faithattach __P((void *));
PSEUDO_SET(faithattach, if_faith);
+
static struct ifnet faithif[NFAITH];
#define FAITHMTU 1500
@@ -74,8 +104,8 @@ void
faithattach(faith)
void *faith;
{
- register struct ifnet *ifp;
- register int i;
+ struct ifnet *ifp;
+ int i;
for (i = 0; i < NFAITH; i++) {
ifp = &faithif[i];
@@ -85,13 +115,210 @@ faithattach(faith)
ifp->if_mtu = FAITHMTU;
/* LOOPBACK commented out to announce IPv6 routes to faith */
ifp->if_flags = /* IFF_LOOPBACK | */ IFF_MULTICAST;
- ifp->if_ioctl = loioctl;
- ifp->if_output = looutput;
+ ifp->if_ioctl = faithioctl;
+ ifp->if_output = faithoutput;
ifp->if_type = IFT_FAITH;
ifp->if_snd.ifq_maxlen = ifqmaxlen;
ifp->if_hdrlen = 0;
ifp->if_addrlen = 0;
if_attach(ifp);
+#if NBPFILTER > 0
+#ifdef HAVE_OLD_BPF
bpfattach(ifp, DLT_NULL, sizeof(u_int));
+#else
+ bpfattach(&ifp->if_bpf, ifp, DLT_NULL, sizeof(u_int));
+#endif
+#endif
+ }
+}
+
+int
+faithoutput(ifp, m, dst, rt)
+ struct ifnet *ifp;
+ struct mbuf *m;
+ struct sockaddr *dst;
+ struct rtentry *rt;
+{
+ int isr;
+ struct ifqueue *ifq = 0;
+
+ if ((m->m_flags & M_PKTHDR) == 0)
+ panic("faithoutput no HDR");
+#if NBPFILTER > 0
+ /* BPF write needs to be handled specially */
+ if (dst->sa_family == AF_UNSPEC) {
+ dst->sa_family = *(mtod(m, int *));
+ m->m_len -= sizeof(int);
+ m->m_pkthdr.len -= sizeof(int);
+ m->m_data += sizeof(int);
}
+
+ if (ifp->if_bpf) {
+ /*
+ * We need to prepend the address family as
+ * a four byte field. Cons up a faith header
+ * to pacify bpf. This is safe because bpf
+ * will only read from the mbuf (i.e., it won't
+ * try to free it or keep a pointer a to it).
+ */
+ struct mbuf m0;
+ u_int32_t af = dst->sa_family;
+
+ m0.m_next = m;
+ m0.m_len = 4;
+ m0.m_data = (char *)&af;
+
+#ifdef HAVE_OLD_BPF
+ bpf_mtap(ifp, &m0);
+#else
+ bpf_mtap(ifp->if_bpf, &m0);
+#endif
+ }
+#endif
+
+ if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
+ m_freem(m);
+ return (rt->rt_flags & RTF_BLACKHOLE ? 0 :
+ rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
+ }
+ ifp->if_opackets++;
+ ifp->if_obytes += m->m_pkthdr.len;
+ switch (dst->sa_family) {
+#ifdef INET
+ case AF_INET:
+ ifq = &ipintrq;
+ isr = NETISR_IP;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ ifq = &ip6intrq;
+ isr = NETISR_IPV6;
+ break;
+#endif
+ default:
+ m_freem(m);
+ return EAFNOSUPPORT;
+ }
+
+ /* XXX do we need more sanity checks? */
+
+ m->m_pkthdr.rcvif = ifp;
+ ifp->if_ipackets++;
+ ifp->if_ibytes += m->m_pkthdr.len;
+ (void) IF_HANDOFF(ifq, m, NULL);
+ schednetisr(isr);
+ return (0);
+}
+
+/* ARGSUSED */
+static void
+faithrtrequest(cmd, rt, sa)
+ int cmd;
+ struct rtentry *rt;
+ struct sockaddr *sa;
+{
+ if (rt) {
+ rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; /* for ISO */
+ /*
+ * For optimal performance, the send and receive buffers
+ * should be at least twice the MTU plus a little more for
+ * overhead.
+ */
+ rt->rt_rmx.rmx_recvpipe =
+ rt->rt_rmx.rmx_sendpipe = 3 * FAITHMTU;
+ }
+}
+
+/*
+ * Process an ioctl request.
+ */
+/* ARGSUSED */
+static int
+faithioctl(ifp, cmd, data)
+ struct ifnet *ifp;
+ u_long cmd;
+ caddr_t data;
+{
+ struct ifaddr *ifa;
+ struct ifreq *ifr = (struct ifreq *)data;
+ int error = 0;
+
+ switch (cmd) {
+
+ case SIOCSIFADDR:
+ ifp->if_flags |= IFF_UP | IFF_RUNNING;
+ ifa = (struct ifaddr *)data;
+ ifa->ifa_rtrequest = faithrtrequest;
+ /*
+ * Everything else is done at a higher level.
+ */
+ break;
+
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ if (ifr == 0) {
+ error = EAFNOSUPPORT; /* XXX */
+ break;
+ }
+ switch (ifr->ifr_addr.sa_family) {
+#ifdef INET
+ case AF_INET:
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ break;
+#endif
+
+ default:
+ error = EAFNOSUPPORT;
+ break;
+ }
+ break;
+
+#ifdef SIOCSIFMTU
+ case SIOCSIFMTU:
+ ifp->if_mtu = ifr->ifr_mtu;
+ break;
+#endif
+
+ case SIOCSIFFLAGS:
+ break;
+
+ default:
+ error = EINVAL;
+ }
+ return (error);
+}
+
+/*
+ * XXX could be slow
+ * XXX could be layer violation to call sys/net from sys/netinet6
+ */
+int
+faithprefix(in6)
+ struct in6_addr *in6;
+{
+ struct rtentry *rt;
+ struct sockaddr_in6 sin6;
+ int ret;
+
+ if (ip6_keepfaith == 0)
+ return 0;
+
+ bzero(&sin6, sizeof(sin6));
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_len = sizeof(struct sockaddr_in6);
+ sin6.sin6_addr = *in6;
+ rt = rtalloc1((struct sockaddr *)&sin6, 0, 0UL);
+ if (rt && rt->rt_ifp && rt->rt_ifp->if_type == IFT_FAITH &&
+ (rt->rt_ifp->if_flags & IFF_UP) != 0)
+ ret = 1;
+ else
+ ret = 0;
+ if (rt)
+ RTFREE(rt);
+ return ret;
}
+#endif /* NFAITH > 0 */
OpenPOWER on IntegriCloud