diff options
author | Nicolas Dichtel <nicolas.dichtel@6wind.com> | 2008-11-02 00:12:07 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-11-02 00:12:07 -0400 |
commit | 7e3a42a12c4b9d99bfe81cb929cadf0e08a37c49 (patch) | |
tree | 517e493ed8294cec73d6815f37db49c5f092f108 | |
parent | e25cf4a6945e0f859186231be7164ba565412e0a (diff) |
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: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/ipv6/xfrm6_policy.c | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 08e4cbbe3f04..604bc0a96c05 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -144,6 +144,7 @@ static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev) | |||
144 | static inline void | 144 | static inline void |
145 | _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | 145 | _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) |
146 | { | 146 | { |
147 | int onlyproto = 0; | ||
147 | u16 offset = skb_network_header_len(skb); | 148 | u16 offset = skb_network_header_len(skb); |
148 | struct ipv6hdr *hdr = ipv6_hdr(skb); | 149 | struct ipv6hdr *hdr = ipv6_hdr(skb); |
149 | struct ipv6_opt_hdr *exthdr; | 150 | struct ipv6_opt_hdr *exthdr; |
@@ -159,6 +160,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
159 | exthdr = (struct ipv6_opt_hdr *)(nh + offset); | 160 | exthdr = (struct ipv6_opt_hdr *)(nh + offset); |
160 | 161 | ||
161 | switch (nexthdr) { | 162 | switch (nexthdr) { |
163 | case NEXTHDR_FRAGMENT: | ||
164 | onlyproto = 1; | ||
162 | case NEXTHDR_ROUTING: | 165 | case NEXTHDR_ROUTING: |
163 | case NEXTHDR_HOP: | 166 | case NEXTHDR_HOP: |
164 | case NEXTHDR_DEST: | 167 | case NEXTHDR_DEST: |
@@ -172,7 +175,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
172 | case IPPROTO_TCP: | 175 | case IPPROTO_TCP: |
173 | case IPPROTO_SCTP: | 176 | case IPPROTO_SCTP: |
174 | case IPPROTO_DCCP: | 177 | case IPPROTO_DCCP: |
175 | if (pskb_may_pull(skb, nh + offset + 4 - skb->data)) { | 178 | if (!onlyproto && pskb_may_pull(skb, nh + offset + 4 - skb->data)) { |
176 | __be16 *ports = (__be16 *)exthdr; | 179 | __be16 *ports = (__be16 *)exthdr; |
177 | 180 | ||
178 | fl->fl_ip_sport = ports[!!reverse]; | 181 | fl->fl_ip_sport = ports[!!reverse]; |
@@ -182,7 +185,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
182 | return; | 185 | return; |
183 | 186 | ||
184 | case IPPROTO_ICMPV6: | 187 | case IPPROTO_ICMPV6: |
185 | if (pskb_may_pull(skb, nh + offset + 2 - skb->data)) { | 188 | if (!onlyproto && pskb_may_pull(skb, nh + offset + 2 - skb->data)) { |
186 | u8 *icmp = (u8 *)exthdr; | 189 | u8 *icmp = (u8 *)exthdr; |
187 | 190 | ||
188 | fl->fl_icmp_type = icmp[0]; | 191 | fl->fl_icmp_type = icmp[0]; |
@@ -193,7 +196,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
193 | 196 | ||
194 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | 197 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
195 | case IPPROTO_MH: | 198 | case IPPROTO_MH: |
196 | if (pskb_may_pull(skb, nh + offset + 3 - skb->data)) { | 199 | if (!onlyproto && pskb_may_pull(skb, nh + offset + 3 - skb->data)) { |
197 | struct ip6_mh *mh; | 200 | struct ip6_mh *mh; |
198 | mh = (struct ip6_mh *)exthdr; | 201 | mh = (struct ip6_mh *)exthdr; |
199 | 202 | ||