Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 22 Mar 2006 14:18:35 +0100 (CET)
From:      VANHULLEBUS Yvan <vanhu@netasq.com>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   kern/94829: OpenBSD's enc0 support for FreeBSD
Message-ID:  <20060322131835.F2BABF7430@darkstar.netasq.com>
Resent-Message-ID: <200603221320.k2MDKI5x095808@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         94829
>Category:       kern
>Synopsis:       OpenBSD's enc0 support for FreeBSD
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          update
>Submitter-Id:   current-users
>Arrival-Date:   Wed Mar 22 13:20:18 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator:     VANHULLEBUS Yvan, THOMAS Fabien
>Release:        FreeBSD 6.1-PRERELEASE i386
>Organization:
NETASQ
>Environment:
System: FreeBSD darkstar.netasq.com 6.1-PRERELEASE FreeBSD 6.1-PRERELEASE #1: Tue Mar 21 17:44:54 CET 2006 root@darkstar.netasq.com:/usr/src/sys/i386/compile/Darkstar i386


	
>Description:
Actually, there is no possibility to do a tcpdump on incoming/outgoing
encrypted traffic, and there is no way to ensure at filtering level
that some specific traffic was encrypted.

This patch adds an optionnal enc0 support "a la OpenBSD", with tcpdump
support for both incoming/outgoing traffic, and sets incoming packet's
interface as enc0.

Note: authentication mark on incoming packets doesn't seems to work
for FAST_IPSEC, I'll try to fix it.


>How-To-Repeat:
	
>Fix:

--- ./conf/options.orig	Thu Mar 16 15:27:31 2006
+++ ./conf/options	Thu Mar 16 15:27:31 2006
@@ -338,6 +338,7 @@ DEVICE_POLLING
 DEV_PF			opt_pf.h
 DEV_PFLOG		opt_pf.h
 DEV_PFSYNC		opt_pf.h
+DEV_ENC			opt_enc.h
 ETHER_II		opt_ef.h
 ETHER_8023		opt_ef.h
 ETHER_8022		opt_ef.h
--- ./conf/files.orig	Thu Mar 16 15:27:31 2006
+++ ./conf/files	Thu Mar 16 15:27:31 2006
@@ -1450,6 +1450,7 @@ net/if_stf.c			optional stf
 net/if_tun.c			optional tun
 net/if_tap.c			optional tap
 net/if_vlan.c			optional vlan
+net/if_enc.c			optional enc
 net/netisr.c			standard
 net/ppp_deflate.c		optional ppp_deflate
 net/ppp_tty.c			optional ppp
--- ./net/if_types.h.orig	Thu Mar 16 15:27:31 2006
+++ ./net/if_types.h	Thu Mar 16 15:27:31 2006
@@ -246,6 +246,7 @@
 #define	IFT_GIF		0xf0
 #define	IFT_PVC		0xf1
 #define	IFT_FAITH	0xf2
+#define IFT_ENC		0xf4
 #define	IFT_PFLOG	0xf6
 #define	IFT_PFSYNC	0xf7
 #define	IFT_CARP	0xf8	/* Common Address Redundancy Protocol */
--- ./net/if_enc.c.orig	Tue Mar 21 17:33:49 2006
+++ ./net/if_enc.c	Tue Mar 21 17:32:45 2006
@@ -0,0 +1,227 @@
+#include "opt_atalk.h"
+#include "opt_inet.h"
+#include "opt_inet6.h"
+#include "opt_ipx.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/module.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/if_clone.h>
+#include <net/if_types.h>
+#include <net/netisr.h>
+#include <net/route.h>
+#include <net/bpf.h>
+#include <net/bpfdesc.h>
+
+#ifdef	INET
+#include <netinet/in.h>
+#include <netinet/in_var.h>
+#endif
+
+#ifdef IPX
+#include <netipx/ipx.h>
+#include <netipx/ipx_if.h>
+#endif
+
+#ifdef INET6
+#ifndef INET
+#include <netinet/in.h>
+#endif
+#include <netinet6/in6_var.h>
+#include <netinet/ip6.h>
+#endif
+
+#ifdef NETATALK
+#include <netatalk/at.h>
+#include <netatalk/at_var.h>
+#endif
+
+#include <net/if_enc.h>
+
+#define ENCNAME	"enc"
+
+struct enc_softc {
+	struct	ifnet *sc_ifp;
+	LIST_ENTRY(enc_softc) sc_next;
+};
+
+int		encioctl(struct ifnet *, u_long, caddr_t);
+static void	encrtrequest(int, struct rtentry *, struct rt_addrinfo *);
+int		encoutput(struct ifnet *ifp, struct mbuf *m,
+		    struct sockaddr *dst, struct rtentry *rt);
+static int	enc_clone_create(struct if_clone *, int);
+static void	enc_clone_destroy(struct ifnet *);
+
+struct ifnet *encif = NULL;			/* Used externally */
+
+static MALLOC_DEFINE(M_ENC, ENCNAME, "IPsec Enc Interface");
+
+static struct mtx enc_mtx;
+static LIST_HEAD(enc_list, enc_softc) enc_list;
+
+IFC_SIMPLE_DECLARE(enc, 1);
+
+static void
+enc_clone_destroy(ifp)
+	struct ifnet *ifp;
+{
+	struct enc_softc *sc;
+	
+	sc = ifp->if_softc;
+
+	/* XXX: destroying enc0 will lead to panics. */
+	KASSERT(encif != ifp, ("%s: destroying enc0", __func__));
+}
+
+static int
+enc_clone_create(ifc, unit)
+	struct if_clone *ifc;
+	int unit;
+{
+	struct ifnet *ifp;
+	struct enc_softc *sc;
+
+	MALLOC(sc, struct enc_softc *, sizeof(*sc), M_ENC, M_WAITOK | M_ZERO);
+	ifp = sc->sc_ifp = if_alloc(IFT_ENC);
+	if (ifp == NULL) {
+		free(sc, M_ENC);
+		return (ENOSPC);
+	}
+
+	if_initname(ifp, ifc->ifc_name, unit);
+	ifp->if_mtu = ENCMTU;
+	ifp->if_flags = IFF_MULTICAST;
+	ifp->if_ioctl = encioctl;
+	ifp->if_output = encoutput;
+	ifp->if_snd.ifq_maxlen = ifqmaxlen;
+	ifp->if_softc = sc;
+	if_attach(ifp);
+	bpfattach(ifp, DLT_ENC, ENC_HDRLEN);
+	mtx_lock(&enc_mtx);
+	LIST_INSERT_HEAD(&enc_list, sc, sc_next);
+	mtx_unlock(&enc_mtx);
+	if (encif == NULL)
+		encif = ifp;
+
+	return (0);
+}
+
+static int
+enc_modevent(module_t mod, int type, void *data) 
+{ 
+	switch (type) { 
+	case MOD_LOAD: 
+		mtx_init(&enc_mtx, "enc_mtx", NULL, MTX_DEF);
+		LIST_INIT(&enc_list);
+		if_clone_attach(&enc_cloner);
+		break; 
+	case MOD_UNLOAD: 
+		printf("enc module unload - not possible for this module type\n"); 
+		return EINVAL; 
+	default:
+		return EOPNOTSUPP;
+	} 
+	return 0; 
+} 
+
+static moduledata_t enc_mod = { 
+	"enc", 
+	enc_modevent, 
+	0
+}; 
+
+DECLARE_MODULE(enc, enc_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY);
+
+int
+encoutput(ifp, m, dst, rt)
+	struct ifnet *ifp;
+	register struct mbuf *m;
+	struct sockaddr *dst;
+	register struct rtentry *rt;
+{
+    m_freem(m);
+    return (0);
+}
+
+/* ARGSUSED */
+static void
+encrtrequest(cmd, rt, info)
+	int cmd;
+	struct rtentry *rt;
+	struct rt_addrinfo *info;
+{
+	RT_LOCK_ASSERT(rt);
+	rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu;
+}
+
+/*
+ * Process an ioctl request.
+ */
+/* ARGSUSED */
+int
+encioctl(ifp, cmd, data)
+	register struct ifnet *ifp;
+	u_long cmd;
+	caddr_t data;
+{
+	register struct ifaddr *ifa;
+	register struct ifreq *ifr = (struct ifreq *)data;
+	register int error = 0;
+
+	switch (cmd) {
+
+	case SIOCSIFADDR:
+		ifp->if_flags |= IFF_UP;
+		ifp->if_drv_flags |= IFF_DRV_RUNNING;
+		ifa = (struct ifaddr *)data;
+		ifa->ifa_rtrequest = encrtrequest;
+		/*
+		 * 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;
+
+	case SIOCSIFMTU:
+		ifp->if_mtu = ifr->ifr_mtu;
+		break;
+
+	case SIOCSIFFLAGS:
+		break;
+
+	default:
+		error = EINVAL;
+	}
+	return (error);
+}
--- ./net/if_enc.h.orig	Tue Mar 21 17:33:51 2006
+++ ./net/if_enc.h	Tue Mar 21 17:32:45 2006
@@ -0,0 +1,21 @@
+#ifndef _NET_IF_ENC_H_
+#define _NET_IF_ENC_H_
+
+#define ENCMTU		(1024+512)
+#define ENC_HDRLEN	12
+
+/* XXX this define must have the same value as in OpenBSD
+ */
+#define M_CONF			0x0400	/* payload was encrypted (ESP-transport) */
+#define M_AUTH			0x0800	/* payload was authenticated (AH or ESP auth) */
+#define M_AUTH_AH		0x2000	/* header was authenticated (AH) */
+
+struct enchdr {
+	u_int32_t af;
+	u_int32_t spi;
+	u_int32_t flags;
+};
+
+extern struct ifnet *encif;
+
+#endif /* _NET_IF_ENC_H_ */
--- ./netinet6/esp_input.c.orig	Thu Mar 16 15:27:31 2006
+++ ./netinet6/esp_input.c	Thu Mar 16 15:27:31 2006
@@ -36,6 +36,7 @@
 
 #include "opt_inet.h"
 #include "opt_inet6.h"
+#include "opt_enc.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -48,6 +49,8 @@
 #include <sys/syslog.h>
 
 #include <net/if.h>
+#include <net/if_enc.h>
+#include <net/bpf.h>
 #include <net/route.h>
 #include <net/netisr.h>
 #include <machine/cpu.h>
@@ -388,6 +391,34 @@ noreplaycheck:
 			ipsecstat.in_nomem++;
 			goto bad;
 		}
+#ifdef DEV_ENC
+		m->m_pkthdr.rcvif = encif;
+
+		if (encif->if_bpf != NULL) {
+			/*
+			 * We need to prepend the address family as
+			 * a four byte field.  Cons up a dummy 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 m1;
+			struct enchdr hdr;
+
+			hdr.af = AF_INET;
+			hdr.spi = spi;
+			hdr.flags = M_CONF;
+			if ((m->m_flags & M_AUTHIPDGM) != 0)
+				hdr.flags |= M_AUTH;
+
+			m1.m_flags = 0;
+			m1.m_next = m;
+			m1.m_len = ENC_HDRLEN;
+			m1.m_data = (char *) &hdr;
+
+			bpf_mtap(encif->if_bpf, &m1);
+		}
+#endif
 
 		if (netisr_queue(NETISR_IP, m)) {	/* (0) on success. */
 			ipsecstat.in_inval++;
@@ -744,6 +775,35 @@ noreplaycheck:
 			ipsec6stat.in_nomem++;
 			goto bad;
 		}
+
+#ifdef DEV_ENC
+		m->m_pkthdr.rcvif = encif;
+
+		if (encif->if_bpf) {
+			/*
+			 * We need to prepend the address family as
+			 * a four byte field.  Cons up a dummy 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 m1;
+			struct enchdr hdr;
+
+			hdr.af = AF_INET6;
+			hdr.spi = spi;
+			hdr.flags = M_CONF;
+			if ((m->m_flags & M_AUTHIPDGM) != 0)
+				hdr.flags |= M_AUTH;
+
+			m1.m_flags = 0;
+			m1.m_next = m;
+			m1.m_len = ENC_HDRLEN;
+			m1.m_data = (char *) &hdr;
+
+			bpf_mtap(encif->if_bpf, &m1);
+		}
+#endif
 
 		if (netisr_queue(NETISR_IPV6, m)) {	/* (0) on success. */
 			ipsec6stat.in_inval++;
--- ./netinet6/esp_output.c.orig	Thu Mar 16 15:27:31 2006
+++ ./netinet6/esp_output.c	Thu Mar 16 15:27:31 2006
@@ -32,6 +32,7 @@
 
 #include "opt_inet.h"
 #include "opt_inet6.h"
+#include "opt_enc.h"
 
 /*
  * RFC1827/2406 Encapsulated Security Payload.
@@ -49,6 +50,8 @@
 #include <sys/syslog.h>
 
 #include <net/if.h>
+#include <net/if_enc.h>
+#include <net/bpf.h>
 #include <net/route.h>
 
 #include <netinet/in.h>
@@ -196,6 +199,33 @@ esp_output(m, nexthdrp, md, isr, af)
 	size_t extendsiz;
 	int error = 0;
 	struct ipsecstat *stat;
+
+#ifdef DEV_ENC
+	if (encif->if_bpf) {
+		/*
+		 * We need to prepend the address family as
+		 * a four byte field.  Cons up a dummy 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 m1;
+		struct enchdr hdr;
+
+		hdr.af = af;
+		hdr.spi = sav->spi;
+		hdr.flags = M_CONF;
+		if (sav->alg_auth != SADB_AALG_NONE)
+			hdr.flags |= M_AUTH;
+
+		m1.m_flags = 0;
+		m1.m_next = m;
+		m1.m_len = ENC_HDRLEN;
+		m1.m_data = (char *) &hdr;
+
+		bpf_mtap(encif->if_bpf, &m1);
+	}
+#endif
 
 	switch (af) {
 #ifdef INET
--- ./netipsec/ipsec_input.c.orig	Thu Mar 16 15:27:31 2006
+++ ./netipsec/ipsec_input.c	Thu Mar 16 15:27:31 2006
@@ -43,6 +43,7 @@
 #include "opt_inet.h"
 #include "opt_inet6.h"
 #include "opt_ipsec.h"
+#include "opt_enc.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -57,6 +58,8 @@
 #include <net/if.h>
 #include <net/route.h>
 #include <net/netisr.h>
+#include <net/if_enc.h>
+#include <net/bpf.h>
 
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
@@ -443,6 +446,34 @@ ipsec4_common_input_cb(struct mbuf *m, s
 	}
 
 	key_sa_recordxfer(sav, m);		/* record data transfer */
+
+#ifdef DEV_ENC
+	m->m_pkthdr.rcvif = encif;
+
+	if (encif->if_bpf != NULL) {
+		/*
+		 * We need to prepend the address family as
+		 * a four byte field.  Cons up a dummy 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 m1;
+		struct enchdr hdr;
+
+		hdr.af = af;
+		hdr.spi = sav->spi;
+		hdr.flags = M_CONF;
+		if ((m->m_flags & M_AUTHIPDGM) != 0)
+			hdr.flags |= M_AUTH;
+
+		m1.m_flags = 0;
+		m1.m_next = m;
+		m1.m_len = ENC_HDRLEN;
+		m1.m_data = (char *) &hdr;
+		bpf_mtap(encif->if_bpf, &m1);
+	}
+#endif
 
 	/*
 	 * Re-dispatch via software interrupt.
--- ./netipsec/ipsec_output.c.orig	Thu Mar 16 15:27:32 2006
+++ ./netipsec/ipsec_output.c	Thu Mar 16 15:27:31 2006
@@ -32,6 +32,7 @@
 #include "opt_inet.h"
 #include "opt_inet6.h"
 #include "opt_ipsec.h"
+#include "opt_enc.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -44,6 +45,8 @@
 
 #include <net/if.h>
 #include <net/route.h>
+#include <net/if_enc.h>
+#include <net/bpf.h>
 
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
@@ -353,6 +356,32 @@ ipsec4_process_packet(
 
 	IPSECREQUEST_LOCK(isr);		/* insure SA contents don't change */
 
+#ifdef DEV_ENC
+	if (encif->if_bpf) {
+		/*
+		 * We need to prepend the address family as
+		 * a four byte field.  Cons up a dummy 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 m1;
+		struct enchdr hdr;
+
+		hdr.af = AF_INET;
+		hdr.spi = sav->spi;
+		hdr.flags = M_CONF;
+		if (sav->alg_auth != SADB_AALG_NONE)
+			hdr.flags |= M_AUTH;
+
+		m1.m_flags = 0;
+		m1.m_next = m;
+		m1.m_len = ENC_HDRLEN;
+		m1.m_data = (char *) &hdr;
+		bpf_mtap(encif->if_bpf, &m1);
+	}
+#endif
+
 	isr = ipsec_nextisr(m, isr, AF_INET, &saidx, &error);
 	if (isr == NULL)
 		goto bad;
@@ -558,6 +587,32 @@ ipsec6_output_trans(
 
 	*tun = 0;
 	m = state->m;
+
+#ifdef DEV_ENC
+	if (encif->if_bpf) {
+		/*
+		 * We need to prepend the address family as
+		 * a four byte field.  Cons up a dummy 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 m1;
+		struct enchdr hdr;
+
+		hdr.af = AF_INET6;
+		hdr.spi = sav->spi;
+		hdr.flags = M_CONF;
+		if (sav->alg_auth != SADB_AALG_NONE)
+			hdr.flags |= M_AUTH;
+
+		m1.m_flags = 0;
+		m1.m_next = m;
+		m1.m_len = ENC_HDRLEN;
+		m1.m_data = (char *) &hdr;
+		bpf_mtap(encif->if_bpf, &m1);
+	}
+#endif
 
 	isr = ipsec_nextisr(m, isr, AF_INET6, &saidx, &error);
 	if (isr == NULL) {
>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20060322131835.F2BABF7430>