aboutsummaryrefslogtreecommitdiffstats
path: root/include/net/ip.h
diff options
context:
space:
mode:
authorAnsis Atteka <aatteka@nicira.com>2013-09-18 18:29:53 -0400
committerDavid S. Miller <davem@davemloft.net>2013-09-19 14:11:15 -0400
commit703133de331a7a7df47f31fb9de51dc6f68a9de8 (patch)
tree0c6c49e15c9461cd3a563d17062a866d2fafd6fa /include/net/ip.h
parent749154aa56b57652a282cbde57a57abc278d1205 (diff)
ip: generate unique IP identificator if local fragmentation is allowed
If local fragmentation is allowed, then ip_select_ident() and ip_select_ident_more() need to generate unique IDs to ensure correct defragmentation on the peer. For example, if IPsec (tunnel mode) has to encrypt large skbs that have local_df bit set, then all IP fragments that belonged to different ESP datagrams would have used the same identificator. If one of these IP fragments would get lost or reordered, then peer could possibly stitch together wrong IP fragments that did not belong to the same datagram. This would lead to a packet loss or data corruption. Signed-off-by: Ansis Atteka <aatteka@nicira.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/net/ip.h')
-rw-r--r--include/net/ip.h12
1 files changed, 8 insertions, 4 deletions
diff --git a/include/net/ip.h b/include/net/ip.h
index 48f55979d842..5e5268807a1c 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -264,9 +264,11 @@ int ip_dont_fragment(struct sock *sk, struct dst_entry *dst)
264 264
265extern void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more); 265extern void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more);
266 266
267static inline void ip_select_ident(struct iphdr *iph, struct dst_entry *dst, struct sock *sk) 267static inline void ip_select_ident(struct sk_buff *skb, struct dst_entry *dst, struct sock *sk)
268{ 268{
269 if (iph->frag_off & htons(IP_DF)) { 269 struct iphdr *iph = ip_hdr(skb);
270
271 if ((iph->frag_off & htons(IP_DF)) && !skb->local_df) {
270 /* This is only to work around buggy Windows95/2000 272 /* This is only to work around buggy Windows95/2000
271 * VJ compression implementations. If the ID field 273 * VJ compression implementations. If the ID field
272 * does not change, they drop every other packet in 274 * does not change, they drop every other packet in
@@ -278,9 +280,11 @@ static inline void ip_select_ident(struct iphdr *iph, struct dst_entry *dst, str
278 __ip_select_ident(iph, dst, 0); 280 __ip_select_ident(iph, dst, 0);
279} 281}
280 282
281static inline void ip_select_ident_more(struct iphdr *iph, struct dst_entry *dst, struct sock *sk, int more) 283static inline void ip_select_ident_more(struct sk_buff *skb, struct dst_entry *dst, struct sock *sk, int more)
282{ 284{
283 if (iph->frag_off & htons(IP_DF)) { 285 struct iphdr *iph = ip_hdr(skb);
286
287 if ((iph->frag_off & htons(IP_DF)) && !skb->local_df) {
284 if (sk && inet_sk(sk)->inet_daddr) { 288 if (sk && inet_sk(sk)->inet_daddr) {
285 iph->id = htons(inet_sk(sk)->inet_id); 289 iph->id = htons(inet_sk(sk)->inet_id);
286 inet_sk(sk)->inet_id += 1 + more; 290 inet_sk(sk)->inet_id += 1 + more;