[PATCH][IPSEC] IPsec policy can be matched by ICMP type and code

STALE8054d

9 messages, 4 authors, 2004-08-18 · open the first message on its own page

[PATCH][IPSEC] IPsec policy can be matched by ICMP type and code

From: Masahide Nakamura <hidden>
Date: 2004-08-09 08:54:04

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,
-- 
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 <redacted>


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:

Re: [PATCH][IPSEC] IPsec policy can be matched by ICMP type and code

From: YOSHIFUJI Hideaki / 吉藤英明 <hidden>
Date: 2004-08-09 09:03:17

In article <20040809175404.301bd60a@localhost> (at Mon, 9 Aug 2004 17:54:04 +0900), Masahide Nakamura [off-list ref] says:
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

Re: [PATCH][IPSEC] IPsec policy can be matched by ICMP type and code

From: David S. Miller <hidden>
Date: 2004-08-10 00:07:05

On Mon, 9 Aug 2004 17:54:04 +0900
Masahide Nakamura [off-list ref] wrote:
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.

Re: [PATCH][IPSEC] IPsec policy can be matched by ICMP type and code

From: YOSHIFUJI Hideaki / 吉藤英明 <hidden>
Date: 2004-08-10 01:32:29

In article [off-list ref] (at Mon, 9 Aug 2004 17:07:05 -0700), "David S. Miller" [off-list ref] says:
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

Re: [PATCH][IPSEC] IPsec policy can be matched by ICMP type and code

From: David S. Miller <hidden>
Date: 2004-08-11 06:01:44

On Tue, 10 Aug 2004 10:32:29 +0900 (JST)
YOSHIFUJI Hideaki / $B5HF#1QL@(B [off-list ref] wrote:
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: [off-list ref]
Received: from localhost (IDENT:davem@localhost.localdomain [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: kuznet@ms2.inr.ac.ru
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 [off-list ref]; 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 [off-list ref]; 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 [off-list ref]; Sat, 17 May 2003 19:28:52 -0400
Received: (from kuznet@localhost) by dub.inr.ac.ru (8.6.13/ANK) id DAA10631 for davem@redhat.com; Sun, 18 May 2003 03:28:45 +0400
Message-Id: [off-list ref]
Subject: Re: dst_pmtu() check in ip_output()
To: davem@redhat.com (David S. Miller)
Date: Sun, 18 May 2003 03:28:45 +0400 (MSD)
In-Reply-To: [off-list ref] 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!
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.

Re: [PATCH][IPSEC] IPsec policy can be matched by ICMP type and code

From: David Stevens <hidden>
Date: 2004-08-11 19:14:19

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" [off-list ref] 
Sent by: netdev-bounce@oss.sgi.com
08/10/2004 11:01 PM

To
yoshfuji@linux-ipv6.org
cc
nakam@linux-ipv6.org, netdev@oss.sgi.com, usagi-core@linux-ipv6.org
Subject
Re: [PATCH][IPSEC] IPsec policy can be matched by ICMP type and code






On Tue, 10 Aug 2004 10:32:29 +0900 (JST)
YOSHIFUJI Hideaki / $B5HF#1QL@(B [off-list ref] wrote:
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: [off-list ref]
Received: from localhost (IDENT:davem@localhost.localdomain [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: kuznet@ms2.inr.ac.ru
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 [off-list ref]; 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 [off-list ref]; 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 [off-list ref]; Sat, 17 May 2003 19:28:52 -0400
Received: (from kuznet@localhost) by dub.inr.ac.ru (8.6.13/ANK) id 
DAA10631 for davem@redhat.com; Sun, 18 May 2003 03:28:45 +0400
Message-Id: [off-list ref]
Subject: Re: dst_pmtu() check in ip_output()
To: davem@redhat.com (David S. Miller)
Date: Sun, 18 May 2003 03:28:45 +0400 (MSD)
In-Reply-To: [off-list ref] 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!
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.

Re: [PATCH][IPSEC] IPsec policy can be matched by ICMP type and code

From: David S. Miller <hidden>
Date: 2004-08-11 20:30:43

On Wed, 11 Aug 2004 13:14:19 -0600
David Stevens [off-list ref] 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.
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.

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

From: YOSHIFUJI Hideaki / 吉藤英明 <hidden>
Date: 2004-08-18 14:09:36

Hello.

In article [off-list ref] (at Mon, 9 Aug 2004 17:07:05 -0700), "David S. Miller" [off-list ref] says:
On Mon, 9 Aug 2004 17:54:04 +0900
Masahide Nakamura [off-list ref] wrote:
quoted
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
---------
ChangeSet@1.1838, 2004-08-18 22:39:42+09:00, yoshfuji@linux-ipv6.org
  [XFRM] Fix selector comparison against icmp{,v6} flows.
  
  Signed-off-by: Hideaki YOSHIFUJI [off-list ref]

diff -Nru a/include/net/xfrm.h b/include/net/xfrm.h
--- a/include/net/xfrm.h	2004-08-18 22:58:51 +09:00
+++ b/include/net/xfrm.h	2004-08-18 22:58:51 +09:00
@@ -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);
 }

ChangeSet@1.1839, 2004-08-18 22:42:00+09:00, nakam@linux-ipv6.org
  [IPV6] XFRM: decode icmpv6 session.
  
  Signed-off-by: Masahide Nakamura [off-list ref]
  Signed-off-by: Hideaki YOSHIFUJI [off-list ref]

diff -Nru a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
--- a/net/ipv6/xfrm6_policy.c	2004-08-18 22:58:54 +09:00
+++ b/net/ipv6/xfrm6_policy.c	2004-08-18 22:58:54 +09:00
@@ -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:

ChangeSet@1.1840, 2004-08-18 22:43:52+09:00, nakam@linux-ipv6.org
  [IPV6] XFRM: probe icmpv6 type/code when sending packets via raw socket.
  
  Signed-off-by: Masahide Nakamura [off-list ref]
  Signed-off-by: Hideaki YOSHIFUJI [off-list ref]

diff -Nru a/net/ipv6/raw.c b/net/ipv6/raw.c
--- a/net/ipv6/raw.c	2004-08-18 22:58:57 +09:00
+++ b/net/ipv6/raw.c	2004-08-18 22:58:57 +09:00
@@ -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);

ChangeSet@1.1841, 2004-08-18 22:45:29+09:00, nakam@linux-ipv6.org
  [IPV4] XFRM: decode icmp session.
  
  Signed-off-by: Masahide Nakamura [off-list ref]
  Signed-off-by: Hideaki YOSHIFUJI [off-list ref]

diff -Nru a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
--- a/net/ipv4/xfrm4_policy.c	2004-08-18 22:59:00 +09:00
+++ b/net/ipv4/xfrm4_policy.c	2004-08-18 22:59:00 +09:00
@@ -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;

ChangeSet@1.1842, 2004-08-18 22:51:21+09:00, nakam@linux-ipv6.org
  [IPV4] XFRM: probe icmp type/code when sending packets via raw socket.
  
  Signed-off-by: Masahide Nakamura [off-list ref]
  Signed-off-by: Hideaki YOSHIFUJI [off-list ref]

diff -Nru a/net/ipv4/raw.c b/net/ipv4/raw.c
--- a/net/ipv4/raw.c	2004-08-18 22:59:03 +09:00
+++ b/net/ipv4/raw.c	2004-08-18 22:59:03 +09:00
@@ -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)

ChangeSet@1.1843, 2004-08-18 22:56:49+09:00, yoshfuji@linux-ipv6.org
  [IPV4] XFRM: don't probe icmp type/code for hdrincl sockets.
  
  Signed-off-by: Hideaki YOSHIFUJI [off-list ref]

diff -Nru a/net/ipv4/raw.c b/net/ipv4/raw.c
--- a/net/ipv4/raw.c	2004-08-18 22:59:06 +09:00
+++ b/net/ipv4/raw.c	2004-08-18 22:59:06 +09:00
@@ -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));
 	}


-- 
Hideaki YOSHIFUJI @ USAGI Project <yoshfuji@linux-ipv6.org>
GPG FP: 9022 65EB 1ECF 3AD1 0BDF  80D8 4807 F894 E062 0EEA

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

From: David S. Miller <hidden>
Date: 2004-08-18 22:24:42

On Wed, 18 Aug 2004 23:09:36 +0900 (JST)
YOSHIFUJI Hideaki / $B5HF#1QL@(B [off-list ref] wrote:
quoted
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.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help