Commit 7e3a42a1 authored by Nicolas Dichtel's avatar Nicolas Dichtel Committed by David S. Miller

xfrm6: handling fragment

RFC4301 Section 7.1 says:

"7.1.  Tunnel Mode SAs that Carry Initial and Non-Initial Fragments

     All implementations MUST support tunnel mode SAs that are configured
     to pass traffic without regard to port field (or ICMP type/code or
     Mobility Header type) values.  If the SA will carry traffic for
     specified protocols, the selector set for the SA MUST specify the
     port fields (or ICMP type/code or Mobility Header type) as ANY.  An
     SA defined in this fashion will carry all traffic including initial
     and non-initial fragments for the indicated Local/Remote addresses
     and specified Next Layer protocol(s)."

But for IPv6, fragment is treated as a protocol.  This change catches
protocol transported in fragmented packet.  In IPv4, there is no
problem.
Signed-off-by: default avatarNicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e25cf4a6
...@@ -144,6 +144,7 @@ static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev) ...@@ -144,6 +144,7 @@ static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev)
static inline void static inline void
_decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
{ {
int onlyproto = 0;
u16 offset = skb_network_header_len(skb); u16 offset = skb_network_header_len(skb);
struct ipv6hdr *hdr = ipv6_hdr(skb); struct ipv6hdr *hdr = ipv6_hdr(skb);
struct ipv6_opt_hdr *exthdr; struct ipv6_opt_hdr *exthdr;
...@@ -159,6 +160,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) ...@@ -159,6 +160,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
exthdr = (struct ipv6_opt_hdr *)(nh + offset); exthdr = (struct ipv6_opt_hdr *)(nh + offset);
switch (nexthdr) { switch (nexthdr) {
case NEXTHDR_FRAGMENT:
onlyproto = 1;
case NEXTHDR_ROUTING: case NEXTHDR_ROUTING:
case NEXTHDR_HOP: case NEXTHDR_HOP:
case NEXTHDR_DEST: case NEXTHDR_DEST:
...@@ -172,7 +175,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) ...@@ -172,7 +175,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
case IPPROTO_TCP: case IPPROTO_TCP:
case IPPROTO_SCTP: case IPPROTO_SCTP:
case IPPROTO_DCCP: case IPPROTO_DCCP:
if (pskb_may_pull(skb, nh + offset + 4 - skb->data)) { if (!onlyproto && pskb_may_pull(skb, nh + offset + 4 - skb->data)) {
__be16 *ports = (__be16 *)exthdr; __be16 *ports = (__be16 *)exthdr;
fl->fl_ip_sport = ports[!!reverse]; fl->fl_ip_sport = ports[!!reverse];
...@@ -182,7 +185,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) ...@@ -182,7 +185,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
return; return;
case IPPROTO_ICMPV6: case IPPROTO_ICMPV6:
if (pskb_may_pull(skb, nh + offset + 2 - skb->data)) { if (!onlyproto && pskb_may_pull(skb, nh + offset + 2 - skb->data)) {
u8 *icmp = (u8 *)exthdr; u8 *icmp = (u8 *)exthdr;
fl->fl_icmp_type = icmp[0]; fl->fl_icmp_type = icmp[0];
...@@ -193,7 +196,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) ...@@ -193,7 +196,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
case IPPROTO_MH: case IPPROTO_MH:
if (pskb_may_pull(skb, nh + offset + 3 - skb->data)) { if (!onlyproto && pskb_may_pull(skb, nh + offset + 3 - skb->data)) {
struct ip6_mh *mh; struct ip6_mh *mh;
mh = (struct ip6_mh *)exthdr; mh = (struct ip6_mh *)exthdr;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment