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/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 @@}staticinlineint+__xfrm_selector_icmp_match(structxfrm_selector*sel,structflowi*fl)+{+/* In selector, type/code are stored 16-bit area and+*shouldbenetworkbyte-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]));+}++staticinlineint__xfrm4_selector_match(structxfrm_selector*sel,structflowi*fl){-returnaddr_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)))+return0;++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);+}}staticinlineint__xfrm6_selector_match(structxfrm_selector*sel,structflowi*fl){-returnaddr_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)))+return0;++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);+}}staticinlineint
--- 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 @@returnerr;}+staticvoidraw_probe_proto_opt(structflowi*fl,structmsghdr*msg)+{+structiovec*iov;+u8*type=NULL;+u8*code=NULL;+intprobed=0;+inti;++if(!msg->msg_iov)+return;++for(i=0;i<msg->msg_iovlen;i++){+iov=&msg->msg_iov[i];+if(!iov)+continue;++switch(fl->proto){+caseIPPROTO_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;+}elseif(!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;+}+}+staticintraw_sendmsg(structkiocb*iocb,structsock*sk,structmsghdr*msg,size_tlen){
--- 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);returnerr;}++staticvoidrawv6_probe_proto_opt(structflowi*fl,structmsghdr*msg)+{+structiovec*iov;+u8*type=NULL;+u8*code=NULL;+intprobed=0;+inti;++if(!msg->msg_iov)+return;++for(i=0;i<msg->msg_iovlen;i++){+iov=&msg->msg_iov[i];+if(!iov)+continue;++switch(fl->proto){+caseIPPROTO_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;+}elseif(!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;+}+}+staticintrawv6_sendmsg(structkiocb*iocb,structsock*sk,structmsghdr*msg,size_tlen){
--- 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;+caseIPPROTO_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? */caseIPPROTO_AH:caseIPPROTO_ESP:
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
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.
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
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.
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.
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.
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
@@ -213,6 +213,16 @@fl->proto=nexthdr;return;+caseIPPROTO_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? */caseIPPROTO_AH:caseIPPROTO_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
@@ -555,6 +555,52 @@IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS);returnerr;}++staticvoidrawv6_probe_proto_opt(structflowi*fl,structmsghdr*msg)+{+structiovec*iov;+u8*type=NULL;+u8*code=NULL;+intprobed=0;+inti;++if(!msg->msg_iov)+return;++for(i=0;i<msg->msg_iovlen;i++){+iov=&msg->msg_iov[i];+if(!iov)+continue;++switch(fl->proto){+caseIPPROTO_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;+}elseif(!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;+}+}+staticintrawv6_sendmsg(structkiocb*iocb,structsock*sk,structmsghdr*msg,size_tlen){
@@ -323,6 +323,51 @@returnerr;}+staticvoidraw_probe_proto_opt(structflowi*fl,structmsghdr*msg)+{+structiovec*iov;+u8*type=NULL;+u8*code=NULL;+intprobed=0;+inti;++if(!msg->msg_iov)+return;++for(i=0;i<msg->msg_iovlen;i++){+iov=&msg->msg_iov[i];+if(!iov)+continue;++switch(fl->proto){+caseIPPROTO_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;+}elseif(!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;+}+}+staticintraw_sendmsg(structkiocb*iocb,structsock*sk,structmsghdr*msg,size_tlen){