[PATCH] ISC DHCP, feature, add support for IPSEC interface, request for comment. [ISC-Bugs #43221]

PiBa-NL piba.nl.dev at gmail.com
Fri Sep 23 18:11:27 UTC 2016


Hi ISC / Developers,

I hope i'm addressing the correct mail-address/list here.. Please do

tell if i should send it elsewhere.

I've added support on FreeBSD to allow for sending an DHCP-ACK message
over a 'enc0' interface in response to a DHCPINFORM request which is
used for ipsec connections.

Windows7/10 requires that subnets to be routed over the vpn connection
will be send by a dhcp option 249 as described here:
https://wiki.strongswan.org/projects/strongswan/wiki/Windows7#Split-routing-on-Windows-10-and-Windows-10-Mobile

I've only tested it between Windows10 and FreeBSD11rc2 sofar. But would
like to hear your opinion about this feature, is it possible to get it
merged in the next ISC-DHCP version? Or are there significant objections
against it?

Also is the implementation as done alright or what should be changed in
my implementation? Any advice / requirements / changes i should do,
please let me know.

Thanks in advance.

Regards,

PiBa-NL


-------------- next part --------------
From 38023b3bebecafb073ac306914a520d6429a95eb Mon Sep 17 00:00:00 2001
From: PiBa-NL <PiBa.NL.dev at gmail.com>
Date: Sat, 17 Sep 2016 17:20:39 +0200
Subject: [PATCH] Add support for enc0 ipsec interface on FreeBSD to allow for
 answering DHCPINFORM requests on a IKEv2 IPSEC connection for mobile users
 (Tested with StrongSwan on FreeBSD11)

---
 common/bpf.c      | 51 ++++++++++++++++++++++++++++++++++++++++++++++-----
 common/discover.c |  5 ++++-
 common/packet.c   |  2 ++
 includes/dhcp.h   |  1 +
 4 files changed, 53 insertions(+), 6 deletions(-)

diff --git a/common/bpf.c b/common/bpf.c
index 1816496..9753339 100644
--- a/common/bpf.c
+++ b/common/bpf.c
@@ -198,11 +198,39 @@ struct bpf_insn dhcp_bpf_filter [] = {
 	BPF_STMT(BPF_RET+BPF_K, 0),
 };
 
+struct bpf_insn dhcp_bpf_efilter[] = {
+	/* Make sure this is an AF_INET packet... */
+	BPF_STMT(BPF_LD + BPF_W + BPF_ABS, 0),
+	BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, AF_INET << 24, 0, 8),
+
+	/* Make sure it's an UDP packet... */
+	BPF_STMT(BPF_LD + BPF_B + BPF_ABS, 21),
+	BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6),
+
+	/* Make sure this isn't a fragment... */
+	BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 18),
+	BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0),
+	
+	/* Get the IP header length... */
+	BPF_STMT (BPF_LDX + BPF_B + BPF_MSH, 12),
+
+	/* Make sure it's to the right port... */
+	BPF_STMT (BPF_LD + BPF_H + BPF_IND, 14),
+	BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1),             /* patch */
+
+	/* If we passed all the tests, ask for the whole packet. */
+	BPF_STMT(BPF_RET+BPF_K, (u_int)-1),
+
+	/* Otherwise, drop it. */
+	BPF_STMT(BPF_RET+BPF_K, 0),
+};
+
 #if defined (DEC_FDDI)
 struct bpf_insn *bpf_fddi_filter = NULL;
 #endif
 
 int dhcp_bpf_filter_len = sizeof dhcp_bpf_filter / sizeof (struct bpf_insn);
+int dhcp_bpf_efilter_len = sizeof(dhcp_bpf_efilter) / sizeof(struct bpf_insn);
 #if defined (HAVE_TR_SUPPORT)
 struct bpf_insn dhcp_bpf_tr_filter [] = {
         /* accept all token ring packets due to variable length header */
@@ -277,7 +305,11 @@ void if_register_receive (info)
 	info -> rbuf_len = 0;
 
 	/* Set up the bpf filter program structure. */
-	p.bf_len = dhcp_bpf_filter_len;
+	if (info->hw_address.hbuf[0] == HTYPE_IPSEC_TUNNEL) {
+		p.bf_len = dhcp_bpf_efilter_len;
+	} else {
+		p.bf_len = dhcp_bpf_filter_len;
+	}	
 
 #ifdef DEC_FDDI
 	/* See if this is an FDDI interface, flag it for later. */
@@ -304,12 +336,17 @@ void if_register_receive (info)
 		p.bf_insns = bpf_fddi_filter;
 	} else
 #endif /* DEC_FDDI */
-	p.bf_insns = dhcp_bpf_filter;
-
-        /* Patch the server port into the BPF  program...
+	/* Patch the server port into the BPF  program...
 	   XXX changes to filter program may require changes
 	   to the insn number(s) used below! XXX */
-	dhcp_bpf_filter [8].k = ntohs (local_port);
+	if (info->hw_address.hbuf[0] == HTYPE_IPSEC_TUNNEL) {
+		p.bf_insns = dhcp_bpf_efilter;
+		dhcp_bpf_efilter[8].k = ntohs (local_port);
+	} else {
+		p.bf_insns = dhcp_bpf_filter;
+		dhcp_bpf_filter[8].k = ntohs (local_port);
+	}
+
 
 	if (ioctl (info -> rfdesc, BIOCSETF, &p) < 0)
 		log_fatal ("Can't install packet filter program: %m");
@@ -599,6 +636,10 @@ get_hw_addr(const char *name, struct hardware *hw) {
                         memcpy(&hw->hbuf[1], LLADDR(sa), sa->sdl_alen);
                         break;
 #endif /* IFT_FDDI */
+		case IFT_ENC:
+			hw->hlen = 1;
+			hw->hbuf[0] = HTYPE_IPSEC_TUNNEL;
+			break;
                 default:
                         log_fatal("Unsupported device type %d for \"%s\"",
                                   sa->sdl_type, name);
diff --git a/common/discover.c b/common/discover.c
index 8e7f632..1db358b 100644
--- a/common/discover.c
+++ b/common/discover.c
@@ -1149,7 +1149,10 @@ discover_interfaces(int state) {
 		last = tmp;
 
 		/* We must have a subnet declaration for each interface. */
-		if (!tmp->shared_network && (state == DISCOVER_SERVER)) {
+		get_hw_addr(tmp->name, &tmp->hw_address);
+		if (tmp->hw_address.hbuf[0] == HTYPE_IPSEC_TUNNEL) {
+			log_info("IPSEC interface %s does not need a subnet to answer Windows DHCPINFORM requests.", tmp->name);
+		} else if (!tmp->shared_network && (state == DISCOVER_SERVER)) {
 			log_error("%s", "");
 			if (local_family == AF_INET) {
 				log_error("No subnet declaration for %s (%s).",
diff --git a/common/packet.c b/common/packet.c
index e600e37..3b5f9bd 100644
--- a/common/packet.c
+++ b/common/packet.c
@@ -214,6 +214,8 @@ ssize_t decode_hw_header (interface, buf, bufix, from)
 	case HTYPE_INFINIBAND:
 		log_error("Attempt to decode hw header for infiniband");
 		return (0);
+	case HTYPE_IPSEC_TUNNEL:
+		return 12; // Enc SPI packet: DWORD AddressFamily,DWORD SPI,DWORD Flags 
 	case HTYPE_ETHER:
 	default:
 		return (decode_ethernet_header(interface, buf, bufix, from));
diff --git a/includes/dhcp.h b/includes/dhcp.h
index f916468..b604e51 100644
--- a/includes/dhcp.h
+++ b/includes/dhcp.h
@@ -76,6 +76,7 @@ struct dhcp_packet {
 #define HTYPE_ETHER	1               /* Ethernet 10Mbps              */
 #define HTYPE_IEEE802	6               /* IEEE 802.2 Token Ring...	*/
 #define HTYPE_FDDI	8		/* FDDI...			*/
+#define HTYPE_IPSEC_TUNNEL  31  /* IPsec Tunnel (RFC3456)   */
 #define HTYPE_INFINIBAND  32		/* IP over Infiniband		*/
 #define HTYPE_IPMP       255            /* IPMP - random hw address - there
 					 * is no standard for this so we
-- 
2.7.0.windows.1



More information about the dhcp-workers mailing list