Skip to contentSkip to conversation

IPsec policy can be matched by ICMP type and code

PATCH In review Masahide Nakamura 4 participants 9 messages Aug 9, 2004 – Aug 18, 2004

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 IPsec policy can be matched by ICMP type and code

Hello,

This patch makes that IPsec policy can be matched by ICMP type and code. Actually setkey(ipsec-tools) already has their interface so it follows setkey's manner where type/code are stored in selector. I added shortcuts for them as a trial. Please read the patch and its log below first.

Thinking of raw socket (in outbound case), the patch supports only ICMP; it is out of scope such packet as user-land builds non-ICMP data (e.g. TCP/UDP) and sends through raw socket. IMO this behavior is enough, however does anybody have comments?

The patch is against 2.6.8-rc3. Can you check it?

Regards,

Signature · 298 lines
Masahide NAKAMURA


Log:
IPsec ICMP type and code support.

* inbound:
 - add entry of ICMP[46] to decode_session[46]() to update flowi.
 - add xfrm_selector_icmp_match().
* outbound:
 - store type/code to flowi when it seems to be ICMP[46] data in raw
socket.


Signed-off-by: Masahide NAKAMURA <[email protected]>


Index: include/linux/xfrm.h
===================================================================
RCS file: /cvsroot/usagi/usagi/kernel/linux26/include/linux/xfrm.h,v
retrieving revision 1.1.1.14
diff -u -r1.1.1.14 xfrm.h
--- include/linux/xfrm.h	19 Jul 2004 16:53:28 -0000	1.1.1.14
+++ include/linux/xfrm.h	9 Aug 2004 08:31:12 -0000
@@ -43,6 +43,15 @@
 	__u8	proto;
 	int	ifindex;
 	uid_t	user;
+	/*
+	 * XXX: ICMP values defined like a manner which setkey does:
+	 * XXX: ICMP-type is "sport" area and ICMP-code is stored "dport" area.
+	 * XXX: Should it be formed union like struct flowi? --nakam
+	 */
+#define xfrmsel_icmp_type	sport
+#define xfrmsel_icmp_type_mask	sport_mask
+#define xfrmsel_icmp_code	dport
+#define xfrmsel_icmp_code_mask	dport_mask
 };
 
 #define XFRM_INF (~(__u64)0)
Index: include/net/xfrm.h
===================================================================
RCS file: /cvsroot/usagi/usagi/kernel/linux26/include/net/xfrm.h,v
retrieving revision 1.1.1.28
diff -u -r1.1.1.28 xfrm.h
--- include/net/xfrm.h	3 Aug 2004 23:00:04 -0000	1.1.1.28
+++ include/net/xfrm.h	9 Aug 2004 08:31:13 -0000
@@ -463,25 +463,54 @@
 }
 
 static inline int
+__xfrm_selector_icmp_match(struct xfrm_selector *sel, struct flowi *fl)
+{
+	/* In selector, type/code are stored 16-bit area and
+	 * should be network byte-order.
+	 */
+	__u8 *xtype = (__u8 *)&sel->xfrmsel_icmp_type;
+	__u8 *xcode = (__u8 *)&sel->xfrmsel_icmp_code;
+	__u8 *xtypemask = (__u8 *)&sel->xfrmsel_icmp_type_mask;
+	__u8 *xcodemask = (__u8 *)&sel->xfrmsel_icmp_code_mask;
+
+	return (!(xtype[0]&xtypemask[0]) &&
+		!((fl->fl_icmp_type^xtype[1])&xtypemask[1])) &&
+	       (!(xcode[0]&xcodemask[0]) &&
+		!((fl->fl_icmp_code^xcode[1])&xcodemask[1]));
+}
+
+static inline int
 __xfrm4_selector_match(struct xfrm_selector *sel, struct flowi *fl)
 {
-	return  addr_match(&fl->fl4_dst, &sel->daddr, sel->prefixlen_d) &&
-		addr_match(&fl->fl4_src, &sel->saddr, sel->prefixlen_s) &&
-		!((fl->fl_ip_dport^sel->dport)&sel->dport_mask) &&
-		!((fl->fl_ip_sport^sel->sport)&sel->sport_mask) &&
-		(fl->proto == sel->proto || !sel->proto) &&
-		(fl->oif == sel->ifindex || !sel->ifindex);
+	if (!(addr_match(&fl->fl4_dst, &sel->daddr, sel->prefixlen_d) &&
+	      addr_match(&fl->fl4_src, &sel->saddr, sel->prefixlen_s) &&
+	      (fl->proto == sel->proto || !sel->proto) &&
+	      (fl->oif == sel->ifindex || !sel->ifindex)))
+		return 0;
+	      
+	if (fl->proto == IPPROTO_ICMP)
+		return __xfrm_selector_icmp_match(sel, fl);
+	else {
+		return !((fl->fl_ip_dport^sel->dport)&sel->dport_mask) &&
+		       !((fl->fl_ip_sport^sel->sport)&sel->sport_mask);
+	}
 }
 
 static inline int
 __xfrm6_selector_match(struct xfrm_selector *sel, struct flowi *fl)
 {
-	return  addr_match(&fl->fl6_dst, &sel->daddr, sel->prefixlen_d) &&
-		addr_match(&fl->fl6_src, &sel->saddr, sel->prefixlen_s) &&
-		!((fl->fl_ip_dport^sel->dport)&sel->dport_mask) &&
-		!((fl->fl_ip_sport^sel->sport)&sel->sport_mask) &&
-		(fl->proto == sel->proto || !sel->proto) &&
-		(fl->oif == sel->ifindex || !sel->ifindex);
+	if (!(addr_match(&fl->fl6_dst, &sel->daddr, sel->prefixlen_d) &&
+	      addr_match(&fl->fl6_src, &sel->saddr, sel->prefixlen_s) &&
+	      (fl->oif == sel->ifindex || !sel->ifindex) &&
+	      (fl->proto == sel->proto || !sel->proto)))
+		return 0;
+
+	if (fl->proto == IPPROTO_ICMPV6)
+		return __xfrm_selector_icmp_match(sel, fl);
+	else {
+		return !((fl->fl_ip_dport^sel->dport)&sel->dport_mask) &&
+		       !((fl->fl_ip_sport^sel->sport)&sel->sport_mask);
+	}
 }
 
 static inline int
Index: net/ipv4/raw.c
===================================================================
RCS file: /cvsroot/usagi/usagi/kernel/linux26/net/ipv4/raw.c,v
retrieving revision 1.1.1.29
diff -u -r1.1.1.29 raw.c
--- net/ipv4/raw.c	3 Aug 2004 23:01:54 -0000	1.1.1.29
+++ net/ipv4/raw.c	9 Aug 2004 08:31:15 -0000
@@ -323,6 +323,51 @@
 	return err; 
 }
 
+static void raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
+{
+	struct iovec *iov;
+	u8 *type = NULL;
+	u8 *code = NULL;
+	int probed = 0;
+	int i;
+
+	if (!msg->msg_iov)
+		return;
+
+	for (i = 0; i < msg->msg_iovlen; i++) {
+		iov = &msg->msg_iov[i];
+		if (!iov)
+			continue;
+
+		switch (fl->proto) {
+		case IPPROTO_ICMP:
+			/* check if one-byte field is readable or not. */
+			if (iov->iov_base && iov->iov_len < 1)
+				break;
+
+			if (!type) {
+				type = iov->iov_base;
+				/* check if code field is readable or not. */
+				if (iov->iov_len > 1)
+					code = type + 1;
+			} else if (!code)
+				code = iov->iov_base;
+
+			if (type && code) {
+				fl->fl_icmp_type = *type;
+				fl->fl_icmp_code = *code;
+				probed = 1;
+			}
+			break;
+		default:
+			probed = 1;
+			break;
+		}
+		if (probed)
+			break;
+	}
+}
+
 static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 		       size_t len)
 {
@@ -429,6 +474,8 @@
 				    .proto = inet->hdrincl ? IPPROTO_RAW :
 					    		     sk->sk_protocol,
 				  };
+		raw_probe_proto_opt(&fl, msg);
+
 		err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT));
 	}
 	if (err)
Index: net/ipv4/xfrm4_policy.c
===================================================================
RCS file: /cvsroot/usagi/usagi/kernel/linux26/net/ipv4/xfrm4_policy.c,v
retrieving revision 1.1.1.7
diff -u -r1.1.1.7 xfrm4_policy.c
--- net/ipv4/xfrm4_policy.c	19 Jul 2004 16:55:14 -0000	1.1.1.7
+++ net/ipv4/xfrm4_policy.c	9 Aug 2004 08:31:15 -0000
@@ -183,6 +183,15 @@
 			}
 			break;
 
+		case IPPROTO_ICMP:
+			if (pskb_may_pull(skb, xprth + 2 - skb->data)) {
+				u8 *icmp = xprth;
+
+				fl->fl_icmp_type = icmp[0];
+				fl->fl_icmp_code = icmp[1];
+			}
+			break;
+
 		case IPPROTO_ESP:
 			if (pskb_may_pull(skb, xprth + 4 - skb->data)) {
 				u32 *ehdr = (u32 *)xprth;
Index: net/ipv6/raw.c
===================================================================
RCS file: /cvsroot/usagi/usagi/kernel/linux26/net/ipv6/raw.c,v
retrieving revision 1.1.1.35
diff -u -r1.1.1.35 raw.c
--- net/ipv6/raw.c	3 Aug 2004 23:01:59 -0000	1.1.1.35
+++ net/ipv6/raw.c	9 Aug 2004 08:31:15 -0000
@@ -555,6 +555,52 @@
 	IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS);
 	return err; 
 }
+
+static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
+{
+	struct iovec *iov;
+	u8 *type = NULL;
+	u8 *code = NULL;
+	int probed = 0;
+	int i;
+
+	if (!msg->msg_iov)
+		return;
+
+	for (i = 0; i < msg->msg_iovlen; i++) {
+		iov = &msg->msg_iov[i];
+		if (!iov)
+			continue;
+
+		switch (fl->proto) {
+		case IPPROTO_ICMPV6:
+			/* check if one-byte field is readable or not. */
+			if (iov->iov_base && iov->iov_len < 1)
+				break;
+
+			if (!type) {
+				type = iov->iov_base;
+				/* check if code field is readable or not. */
+				if (iov->iov_len > 1)
+					code = type + 1;
+			} else if (!code)
+				code = iov->iov_base;
+
+			if (type && code) {
+				fl->fl_icmp_type = *type;
+				fl->fl_icmp_code = *code;
+				probed = 1;
+			}
+			break;
+		default:
+			probed = 1;
+			break;
+		}
+		if (probed)
+			break;
+	}
+}
+
 static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
 		   struct msghdr *msg, size_t len)
 {
@@ -674,6 +720,8 @@
 		opt = fl6_merge_options(&opt_space, flowlabel, opt);
 
 	fl.proto = proto;
+	rawv6_probe_proto_opt(&fl, msg);
+ 
 	ipv6_addr_copy(&fl.fl6_dst, daddr);
 	if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr))
 		ipv6_addr_copy(&fl.fl6_src, &np->saddr);
Index: net/ipv6/xfrm6_policy.c
===================================================================
RCS file: /cvsroot/usagi/usagi/kernel/linux26/net/ipv6/xfrm6_policy.c,v
retrieving revision 1.1.1.15
diff -u -r1.1.1.15 xfrm6_policy.c
--- net/ipv6/xfrm6_policy.c	3 Aug 2004 23:01:59 -0000	1.1.1.15
+++ net/ipv6/xfrm6_policy.c	9 Aug 2004 08:31:15 -0000
@@ -213,6 +213,16 @@
 			fl->proto = nexthdr;
 			return;
 
+		case IPPROTO_ICMPV6:
+			if (pskb_may_pull(skb, skb->nh.raw + offset + 2 - skb->data)) {
+				u8 *icmp = (u8 *)exthdr;
+
+				fl->fl_icmp_type = icmp[0];
+				fl->fl_icmp_code = icmp[1];
+			}
+			fl->proto = nexthdr;
+			return;
+
 		/* XXX Why are there these headers? */
 		case IPPROTO_AH:
 		case IPPROTO_ESP:
#1 lore raw

In article <20040809175404.301bd60a@localhost> (at Mon, 9 Aug 2004 17:54:04 +0900), Masahide Nakamura <[email protected]> says:

Quoted 5 lines

This patch makes that IPsec policy can be matched by ICMP type and code. Actually setkey(ipsec-tools) already has their interface so it follows setkey's manner where type/code are stored in selector. I added shortcuts for them as a trial. Please read the patch and its log below first.

Sorry, please do not apply this.
I notice that this does not seem to work on big-endian archs.

--yoshfuji

#2 lore raw
In reply to Masahide Nakamura
Quoted 4 lines · On Mon, 9 Aug 2004 17:54:04 +0900 Masahide Nakamura <[email protected]>…

Thinking of raw socket (in outbound case), the patch supports only ICMP; it is out of scope such packet as user-land builds non-ICMP data (e.g. TCP/UDP) and sends through raw socket. IMO this behavior is enough, however does anybody have comments?

Truly %100 RAW sockets should have their packets untouched by the kernel. User wants exactly that packet to be sent onto the wire.

#3 lore raw

In article <[email protected]> (at Mon, 9 Aug 2004 17:07:05 -0700), "David S. Miller" <[email protected]> says:

Quoted 3 lines

Truly %100 RAW sockets should have their packets untouched by the kernel. User wants exactly that packet to be sent onto the wire.

Does it make sense to excude IPPPROTO_RAW sockets and/or hdrincl sockets, which would be 100% truly raw socket?
Or, do we add some socket option for this?

Mip6 is required to exchange ipsec'ed datagrams (!= IPPROTO_RAW). (as I told you at Networking Summit if I remember correctly), so we need some sort of the patch, anyway.

Thanks.

--yoshfuji

#4 lore raw
Quoted 7 lines · On Tue, 10 Aug 2004 10:32:29 +0900 (JST) YOSHIFUJI Hideaki / $B5HF#1QL@(B…

Does it make sense to excude IPPPROTO_RAW sockets and/or hdrincl sockets, which would be 100% truly raw socket?
Or, do we add some socket option for this?

Mip6 is required to exchange ipsec'ed datagrams (!= IPPROTO_RAW). (as I told you at Networking Summit if I remember correctly), so we need some sort of the patch, anyway.

This is what Alexey told me when I last spoke with him about this:

Return-Path: <[email protected]>
Received: from localhost (IDENT:[email protected] [127.0.0.1])

	by pizda.ninka.net (8.9.3/8.9.3) with ESMTP id QAA27793
	for <davem@localhost>; Sat, 17 May 2003 16:28:26 -0700
From: [email protected]
Received: from localhost.localdomain [127.0.0.1]
	by localhost with POP3 (fetchmail-6.2.2)
	for davem@localhost (single-drop); Sat, 17 May 2003 16:28:26 -0700 (PDT)
Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254])
	by devserv.devel.redhat.com (8.11.6/8.11.0) with ESMTP id h4HNSr500334
	for <[email protected]>; Sat, 17 May 2003 19:28:53 -0400
Received: from mx1.redhat.com (mx1.redhat.com [172.16.48.31])
	by int-mx1.corp.redhat.com (8.11.6/8.11.6) with SMTP id h4HNSrI11137
	for <[email protected]>; Sat, 17 May 2003 19:28:53 -0400
Received: from dub.inr.ac.ru (dub.inr.ac.ru [193.233.7.105])
	by mx1.redhat.com (8.11.6/8.11.6) with SMTP id h4HNSqH20272
	for <[email protected]>; Sat, 17 May 2003 19:28:52 -0400

Received: (from kuznet@localhost) by dub.inr.ac.ru (8.6.13/ANK) id DAA10631 for [email protected]; Sun, 18 May 2003 03:28:45 +0400
Message-Id: <[email protected]>
Subject: Re: dst_pmtu() check in ip_output()
To: [email protected] (David S. Miller)
Date: Sun, 18 May 2003 03:28:45 +0400 (MSD)
In-Reply-To: <[email protected]> from "David S. Miller" at May 14, 2003 06:41:39 PM
X-Mailer: ELM [version 2.5 PL6]
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Hello!

Quoted 6 lines

Let's ask the following question: What is difference between adding transformation locally, and adding it at some hop on the way to destination?

I can already hear answers of the form "It is same difference as that between tunnel and transport mode." :-)

Exactly.

Plus one more thing: when you noticed pathology with raw socket you referred to "What does user expect?".

Use of raw socket is pathological itself, f.e. IPv6 does not even have such a concept. It is used by (and invented by VJ for) traceroute. And beyond this it is used by various testing and attacker's software. Shortly, the packet which it generates are _tricky_ by user desire, when user wants to test (or attack) someone.

So, I would expect the packet is not transformed locally at all. Remember f.e. that it can be an _IPsec_ packet already.

Alexey

PS. This is the first mail which I send from new account. Please, tell me if it looks unusual.

#5 lore raw

I may be catching this out of context, but...

raw sockets predate VJ contributions by many years and are typically used by protocols not in the kernel. The original "ping" used raw sockets, as well as routing protocols like BGP and RIP which are directly encapsulated in IP, without a separate transport protocol. The original traceroute I believe used UDP and just set the TTL-- I don't believe it used raw sockets at all. Don't know what the current versions do; haven't looked in a while.

And IPv6 does support raw sockets; it just doesn't let you generate bad checksums and some header fields, I expect to make it harder to write attack software.

                                        +-DLS

"David S. Miller" <[email protected]>
Sent by: [email protected]
08/10/2004 11:01 PM

To
[email protected]
cc
[email protected], [email protected], [email protected] Subject
Re: [PATCH][IPSEC] IPsec policy can be matched by ICMP type and code

Quoted 1 line · On Tue, 10 Aug 2004 10:32:29 +0900 (JST) YOSHIFUJI Hideaki / $B5HF#1QL@(B…

Does it make sense to excude IPPPROTO_RAW sockets and/or hdrincl

sockets,

Quoted 6 lines

which would be 100% truly raw socket?
Or, do we add some socket option for this?

Mip6 is required to exchange ipsec'ed datagrams (!= IPPROTO_RAW). (as I told you at Networking Summit if I remember correctly), so we need some sort of the patch, anyway.

This is what Alexey told me when I last spoke with him about this:

Return-Path: <[email protected]>
Received: from localhost (IDENT:[email protected] [127.0.0.1]) by pizda.ninka.net (8.9.3/8.9.3) with ESMTP id QAA27793
for <davem@localhost>; Sat, 17 May 2003 16:28:26 -0700
From: [email protected]
Received: from localhost.localdomain [127.0.0.1]
by localhost with POP3 (fetchmail-6.2.2)
for davem@localhost (single-drop); Sat, 17 May 2003 16:28:26 -0700 (PDT)
Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254])
by devserv.devel.redhat.com (8.11.6/8.11.0) with ESMTP id h4HNSr500334 for <[email protected]>; Sat, 17 May 2003 19:28:53 -0400
Received: from mx1.redhat.com (mx1.redhat.com [172.16.48.31]) by int-mx1.corp.redhat.com (8.11.6/8.11.6) with SMTP id h4HNSrI11137 for <[email protected]>; Sat, 17 May 2003 19:28:53 -0400
Received: from dub.inr.ac.ru (dub.inr.ac.ru [193.233.7.105]) by mx1.redhat.com (8.11.6/8.11.6) with SMTP id h4HNSqH20272 for <[email protected]>; Sat, 17 May 2003 19:28:52 -0400
Received: (from kuznet@localhost) by dub.inr.ac.ru (8.6.13/ANK) id DAA10631 for [email protected]; Sun, 18 May 2003 03:28:45 +0400
Message-Id: <[email protected]>
Subject: Re: dst_pmtu() check in ip_output()
To: [email protected] (David S. Miller)
Date: Sun, 18 May 2003 03:28:45 +0400 (MSD)
In-Reply-To: <[email protected]> from "David S. Miller" at May 14, 2003 06:41:39 PM
X-Mailer: ELM [version 2.5 PL6]
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Hello!

Quoted 6 lines

Let's ask the following question: What is difference between adding transformation locally, and adding it at some hop on the way to destination?

I can already hear answers of the form "It is same difference as that between tunnel and transport mode." :-)

Exactly.

Plus one more thing: when you noticed pathology with raw socket you referred to "What does user expect?".

Use of raw socket is pathological itself, f.e. IPv6 does not even have such a concept. It is used by (and invented by VJ for) traceroute. And beyond this it is used by various testing and attacker's software. Shortly, the packet which it generates are _tricky_ by user desire, when user wants to test (or attack) someone.

So, I would expect the packet is not transformed locally at all. Remember f.e. that it can be an _IPsec_ packet already.

Alexey

PS. This is the first mail which I send from new account. Please, tell me if it looks unusual.

#6 lore raw
Quoted 7 lines · On Wed, 11 Aug 2004 13:14:19 -0600 David Stevens <[email protected]> wrote:

raw sockets predate VJ contributions by many years and are typically used by protocols not in the kernel. The original "ping" used raw sockets, as well as routing protocols like BGP and RIP which are directly encapsulated in IP, without a separate transport protocol. The original traceroute I believe used UDP and just set the TTL-- I don't believe it used raw sockets at all. Don't know what the current versions do; haven't looked in a while.

"ping" does not use the hdrinclude feature.

Quoted 3 lines

And IPv6 does support raw sockets; it just doesn't let you generate bad checksums and some header fields, I expect to make it harder to write attack software.

So like I said, raw without the hdrinclude feature.

#7 lore raw

PATCH 1/1 XFRM: ICMP{,v6} type/code support (Take 2) (was Re: [PATCH][IPSEC] IPsec policy can be matched by ICMP type and code)

In reply to David S. Miller

Hello.

In article <[email protected]> (at Mon, 9 Aug 2004 17:07:05 -0700), "David S. Miller" <[email protected]> says:

Quoted 11 lines
Quoted 4 lines · On Mon, 9 Aug 2004 17:54:04 +0900 Masahide Nakamura <[email protected]>…

Thinking of raw socket (in outbound case), the patch supports only ICMP; it is out of scope such packet as user-land builds non-ICMP data (e.g. TCP/UDP) and sends through raw socket. IMO this behavior is enough, however does anybody have comments?

Truly %100 RAW sockets should have their packets untouched by the kernel. User wants exactly that packet to be sent onto the wire.

Here's the updated version of the patch.
Changesets are available at:

	<bk://bk.skbuff.net:20609/linux-2.6-xfrm-icmp/>.

Thanks.

DIFFSTAT
--------

 include/net/xfrm.h      |   46 ++++++++++++++++++++++++++++++++++++++++----
 net/ipv4/raw.c          |   50 +++++++++++++++++++++++++++++++++++++++++++++++-
 net/ipv4/xfrm4_policy.c |    9 ++++++++
 net/ipv6/raw.c          |   48 ++++++++++++++++++++++++++++++++++++++++++++++
 net/ipv6/xfrm6_policy.c |   10 +++++++++
 5 files changed, 158 insertions(+), 5 deletions(-)

CHANGESET
---------
[email protected], 2004-08-18 22:39:42+09:00, [email protected]
[XFRM] Fix selector comparison against icmp{,v6} flows.

include/net/xfrm.h +42 -4
diff -Nru a/include/net/xfrm.h b/include/net/xfrm.h
@@ -462,13 +462,51 @@
 	return 1;
 }
 
+static __inline__
+u16 xfrm_flowi_sport(struct flowi *fl)
+{
+	u16 port;
+	switch(fl->proto) {
+	case IPPROTO_TCP:
+	case IPPROTO_UDP:
+		port = fl->fl_ip_sport;
+		break;
+	case IPPROTO_ICMP:
+	case IPPROTO_ICMPV6:
+		port = htons(fl->fl_icmp_type);
+		break;
+	default:
+		port = 0;	/*XXX*/
+	}
+	return port;
+}
+
+static __inline__
+u16 xfrm_flowi_dport(struct flowi *fl)
+{
+	u16 port;
+	switch(fl->proto) {
+	case IPPROTO_TCP:
+	case IPPROTO_UDP:
+		port = fl->fl_ip_dport;
+		break;
+	case IPPROTO_ICMP:
+	case IPPROTO_ICMPV6:
+		port = htons(fl->fl_icmp_code);
+		break;
+	default:
+		port = 0;	/*XXX*/
+	}
+	return port;
+}
+
 static inline int
 __xfrm4_selector_match(struct xfrm_selector *sel, struct flowi *fl)
 {
 	return  addr_match(&fl->fl4_dst, &sel->daddr, sel->prefixlen_d) &&
 		addr_match(&fl->fl4_src, &sel->saddr, sel->prefixlen_s) &&
-		!((fl->fl_ip_dport^sel->dport)&sel->dport_mask) &&
-		!((fl->fl_ip_sport^sel->sport)&sel->sport_mask) &&
+		!((xfrm_flowi_dport(fl) ^ sel->dport) & sel->dport_mask) &&
+		!((xfrm_flowi_sport(fl) ^ sel->sport) & sel->sport_mask) &&
 		(fl->proto == sel->proto || !sel->proto) &&
 		(fl->oif == sel->ifindex || !sel->ifindex);
 }
@@ -478,8 +516,8 @@
 {
 	return  addr_match(&fl->fl6_dst, &sel->daddr, sel->prefixlen_d) &&
 		addr_match(&fl->fl6_src, &sel->saddr, sel->prefixlen_s) &&
-		!((fl->fl_ip_dport^sel->dport)&sel->dport_mask) &&
-		!((fl->fl_ip_sport^sel->sport)&sel->sport_mask) &&
+		!((xfrm_flowi_dport(fl) ^ sel->dport) & sel->dport_mask) &&
+		!((xfrm_flowi_sport(fl) ^ sel->sport) & sel->sport_mask) &&
 		(fl->proto == sel->proto || !sel->proto) &&
 		(fl->oif == sel->ifindex || !sel->ifindex);
 }

[email protected], 2004-08-18 22:42:00+09:00, [email protected]
[IPV6] XFRM: decode icmpv6 session.

net/ipv6/xfrm6_policy.c +10 -0
diff -Nru a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
@@ -213,6 +213,16 @@
 			fl->proto = nexthdr;
 			return;
 
+		case IPPROTO_ICMPV6:
+			if (pskb_may_pull(skb, skb->nh.raw + offset + 2 - skb->data)) {
+				u8 *icmp = (u8 *)exthdr;
+
+				fl->fl_icmp_type = icmp[0];
+				fl->fl_icmp_code = icmp[1];
+			}
+			fl->proto = nexthdr;
+			return;
+
 		/* XXX Why are there these headers? */
 		case IPPROTO_AH:
 		case IPPROTO_ESP:

[email protected], 2004-08-18 22:43:52+09:00, [email protected]
[IPV6] XFRM: probe icmpv6 type/code when sending packets via raw socket.

net/ipv6/raw.c +48 -0

60 lines not on this page · raw message

[email protected], 2004-08-18 22:45:29+09:00, [email protected]
[IPV4] XFRM: decode icmp session.

net/ipv4/xfrm4_policy.c +9 -0
diff -Nru a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
@@ -183,6 +183,15 @@
 			}
 			break;
 
+		case IPPROTO_ICMP:
+			if (pskb_may_pull(skb, xprth + 2 - skb->data)) {
+				u8 *icmp = xprth;
+
+				fl->fl_icmp_type = icmp[0];
+				fl->fl_icmp_code = icmp[1];
+			}
+			break;
+
 		case IPPROTO_ESP:
 			if (pskb_may_pull(skb, xprth + 4 - skb->data)) {
 				u32 *ehdr = (u32 *)xprth;

[email protected], 2004-08-18 22:51:21+09:00, [email protected]
[IPV4] XFRM: probe icmp type/code when sending packets via raw socket.

net/ipv4/raw.c +47 -0

59 lines not on this page · raw message

[email protected], 2004-08-18 22:56:49+09:00, [email protected]
[IPV4] XFRM: don't probe icmp type/code for hdrincl sockets.

net/ipv4/raw.c +2 -1
diff -Nru a/net/ipv4/raw.c b/net/ipv4/raw.c
@@ -474,7 +474,8 @@
 				    .proto = inet->hdrincl ? IPPROTO_RAW :
 					    		     sk->sk_protocol,
 				  };
-		raw_probe_proto_opt(&fl, msg);
+		if (!inet->hdrincl)
+			raw_probe_proto_opt(&fl, msg);
 
 		err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT));
 	}
Signature · 2 lines
Hideaki YOSHIFUJI @ USAGI Project <[email protected]>
GPG FP: 9022 65EB 1ECF 3AD1 0BDF  80D8 4807 F894 E062 0EEA
#8 lore raw

Re: [PATCH] XFRM: ICMP{,v6} type/code support (Take 2) (was Re: [PATCH][IPSEC] IPsec policy can be matched by ICMP type and code)

Quoted 7 lines · On Wed, 18 Aug 2004 23:09:36 +0900 (JST) YOSHIFUJI Hideaki / $B5HF#1QL@(B…
Quoted 3 lines

Truly %100 RAW sockets should have their packets untouched by the kernel. User wants exactly that packet to be sent onto the wire.

Here's the updated version of the patch.
Changesets are available at:

	<bk://bk.skbuff.net:20609/linux-2.6-xfrm-icmp/>.

Pulled, thanks Yoshifuji.