diff options
-rw-r--r-- | include/net/inet_frag.h | 12 | ||||
-rw-r--r-- | net/ipv4/inet_fragment.c | 22 | ||||
-rw-r--r-- | net/ipv4/ip_fragment.c | 31 |
3 files changed, 35 insertions, 30 deletions
diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h index 0a1dcc2fa2f5..64b4e7d23b8a 100644 --- a/include/net/inet_frag.h +++ b/include/net/inet_frag.h | |||
@@ -153,4 +153,16 @@ static inline void inet_frag_lru_add(struct netns_frags *nf, | |||
153 | list_add_tail(&q->lru_list, &nf->lru_list); | 153 | list_add_tail(&q->lru_list, &nf->lru_list); |
154 | spin_unlock(&nf->lru_lock); | 154 | spin_unlock(&nf->lru_lock); |
155 | } | 155 | } |
156 | |||
157 | /* RFC 3168 support : | ||
158 | * We want to check ECN values of all fragments, do detect invalid combinations. | ||
159 | * In ipq->ecn, we store the OR value of each ip4_frag_ecn() fragment value. | ||
160 | */ | ||
161 | #define IPFRAG_ECN_NOT_ECT 0x01 /* one frag had ECN_NOT_ECT */ | ||
162 | #define IPFRAG_ECN_ECT_1 0x02 /* one frag had ECN_ECT_1 */ | ||
163 | #define IPFRAG_ECN_ECT_0 0x04 /* one frag had ECN_ECT_0 */ | ||
164 | #define IPFRAG_ECN_CE 0x08 /* one frag had ECN_CE */ | ||
165 | |||
166 | extern const u8 ip_frag_ecn_table[16]; | ||
167 | |||
156 | #endif | 168 | #endif |
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c index f4fd23de9b13..2bff045bec60 100644 --- a/net/ipv4/inet_fragment.c +++ b/net/ipv4/inet_fragment.c | |||
@@ -23,6 +23,28 @@ | |||
23 | 23 | ||
24 | #include <net/sock.h> | 24 | #include <net/sock.h> |
25 | #include <net/inet_frag.h> | 25 | #include <net/inet_frag.h> |
26 | #include <net/inet_ecn.h> | ||
27 | |||
28 | /* Given the OR values of all fragments, apply RFC 3168 5.3 requirements | ||
29 | * Value : 0xff if frame should be dropped. | ||
30 | * 0 or INET_ECN_CE value, to be ORed in to final iph->tos field | ||
31 | */ | ||
32 | const u8 ip_frag_ecn_table[16] = { | ||
33 | /* at least one fragment had CE, and others ECT_0 or ECT_1 */ | ||
34 | [IPFRAG_ECN_CE | IPFRAG_ECN_ECT_0] = INET_ECN_CE, | ||
35 | [IPFRAG_ECN_CE | IPFRAG_ECN_ECT_1] = INET_ECN_CE, | ||
36 | [IPFRAG_ECN_CE | IPFRAG_ECN_ECT_0 | IPFRAG_ECN_ECT_1] = INET_ECN_CE, | ||
37 | |||
38 | /* invalid combinations : drop frame */ | ||
39 | [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_CE] = 0xff, | ||
40 | [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_ECT_0] = 0xff, | ||
41 | [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_ECT_1] = 0xff, | ||
42 | [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_ECT_0 | IPFRAG_ECN_ECT_1] = 0xff, | ||
43 | [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_CE | IPFRAG_ECN_ECT_0] = 0xff, | ||
44 | [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_CE | IPFRAG_ECN_ECT_1] = 0xff, | ||
45 | [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_CE | IPFRAG_ECN_ECT_0 | IPFRAG_ECN_ECT_1] = 0xff, | ||
46 | }; | ||
47 | EXPORT_SYMBOL(ip_frag_ecn_table); | ||
26 | 48 | ||
27 | static void inet_frag_secret_rebuild(unsigned long dummy) | 49 | static void inet_frag_secret_rebuild(unsigned long dummy) |
28 | { | 50 | { |
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index a6445b843ef4..938520668b2f 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
@@ -79,40 +79,11 @@ struct ipq { | |||
79 | struct inet_peer *peer; | 79 | struct inet_peer *peer; |
80 | }; | 80 | }; |
81 | 81 | ||
82 | /* RFC 3168 support : | ||
83 | * We want to check ECN values of all fragments, do detect invalid combinations. | ||
84 | * In ipq->ecn, we store the OR value of each ip4_frag_ecn() fragment value. | ||
85 | */ | ||
86 | #define IPFRAG_ECN_NOT_ECT 0x01 /* one frag had ECN_NOT_ECT */ | ||
87 | #define IPFRAG_ECN_ECT_1 0x02 /* one frag had ECN_ECT_1 */ | ||
88 | #define IPFRAG_ECN_ECT_0 0x04 /* one frag had ECN_ECT_0 */ | ||
89 | #define IPFRAG_ECN_CE 0x08 /* one frag had ECN_CE */ | ||
90 | |||
91 | static inline u8 ip4_frag_ecn(u8 tos) | 82 | static inline u8 ip4_frag_ecn(u8 tos) |
92 | { | 83 | { |
93 | return 1 << (tos & INET_ECN_MASK); | 84 | return 1 << (tos & INET_ECN_MASK); |
94 | } | 85 | } |
95 | 86 | ||
96 | /* Given the OR values of all fragments, apply RFC 3168 5.3 requirements | ||
97 | * Value : 0xff if frame should be dropped. | ||
98 | * 0 or INET_ECN_CE value, to be ORed in to final iph->tos field | ||
99 | */ | ||
100 | static const u8 ip4_frag_ecn_table[16] = { | ||
101 | /* at least one fragment had CE, and others ECT_0 or ECT_1 */ | ||
102 | [IPFRAG_ECN_CE | IPFRAG_ECN_ECT_0] = INET_ECN_CE, | ||
103 | [IPFRAG_ECN_CE | IPFRAG_ECN_ECT_1] = INET_ECN_CE, | ||
104 | [IPFRAG_ECN_CE | IPFRAG_ECN_ECT_0 | IPFRAG_ECN_ECT_1] = INET_ECN_CE, | ||
105 | |||
106 | /* invalid combinations : drop frame */ | ||
107 | [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_CE] = 0xff, | ||
108 | [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_ECT_0] = 0xff, | ||
109 | [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_ECT_1] = 0xff, | ||
110 | [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_ECT_0 | IPFRAG_ECN_ECT_1] = 0xff, | ||
111 | [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_CE | IPFRAG_ECN_ECT_0] = 0xff, | ||
112 | [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_CE | IPFRAG_ECN_ECT_1] = 0xff, | ||
113 | [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_CE | IPFRAG_ECN_ECT_0 | IPFRAG_ECN_ECT_1] = 0xff, | ||
114 | }; | ||
115 | |||
116 | static struct inet_frags ip4_frags; | 87 | static struct inet_frags ip4_frags; |
117 | 88 | ||
118 | int ip_frag_nqueues(struct net *net) | 89 | int ip_frag_nqueues(struct net *net) |
@@ -551,7 +522,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, | |||
551 | 522 | ||
552 | ipq_kill(qp); | 523 | ipq_kill(qp); |
553 | 524 | ||
554 | ecn = ip4_frag_ecn_table[qp->ecn]; | 525 | ecn = ip_frag_ecn_table[qp->ecn]; |
555 | if (unlikely(ecn == 0xff)) { | 526 | if (unlikely(ecn == 0xff)) { |
556 | err = -EINVAL; | 527 | err = -EINVAL; |
557 | goto out_fail; | 528 | goto out_fail; |