aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/cls_flow.c
diff options
context:
space:
mode:
authorMichal Marek <mmarek@suse.cz>2010-10-27 18:15:57 -0400
committerMichal Marek <mmarek@suse.cz>2010-10-27 18:15:57 -0400
commitb74b953b998bcc2db91b694446f3a2619ec32de6 (patch)
tree6ce24caabd730f6ae9287ed0676ec32e6ff31e9d /net/sched/cls_flow.c
parentabb438526201c6a79949ad45375c051b6681c253 (diff)
parentf6f94e2ab1b33f0082ac22d71f66385a60d8157f (diff)
Merge commit 'v2.6.36' into kbuild/misc
Update to be able to fix a recent change to scripts/basic/docproc.c (commit eda603f).
Diffstat (limited to 'net/sched/cls_flow.c')
-rw-r--r--net/sched/cls_flow.c98
1 files changed, 57 insertions, 41 deletions
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c
index e054c62857e1..e17096e3913c 100644
--- a/net/sched/cls_flow.c
+++ b/net/sched/cls_flow.c
@@ -20,6 +20,7 @@
20#include <linux/ip.h> 20#include <linux/ip.h>
21#include <linux/ipv6.h> 21#include <linux/ipv6.h>
22#include <linux/if_vlan.h> 22#include <linux/if_vlan.h>
23#include <linux/slab.h>
23 24
24#include <net/pkt_cls.h> 25#include <net/pkt_cls.h>
25#include <net/ip.h> 26#include <net/ip.h>
@@ -64,37 +65,47 @@ static inline u32 addr_fold(void *addr)
64 return (a & 0xFFFFFFFF) ^ (BITS_PER_LONG > 32 ? a >> 32 : 0); 65 return (a & 0xFFFFFFFF) ^ (BITS_PER_LONG > 32 ? a >> 32 : 0);
65} 66}
66 67
67static u32 flow_get_src(const struct sk_buff *skb) 68static u32 flow_get_src(struct sk_buff *skb)
68{ 69{
69 switch (skb->protocol) { 70 switch (skb->protocol) {
70 case htons(ETH_P_IP): 71 case htons(ETH_P_IP):
71 return ntohl(ip_hdr(skb)->saddr); 72 if (pskb_network_may_pull(skb, sizeof(struct iphdr)))
73 return ntohl(ip_hdr(skb)->saddr);
74 break;
72 case htons(ETH_P_IPV6): 75 case htons(ETH_P_IPV6):
73 return ntohl(ipv6_hdr(skb)->saddr.s6_addr32[3]); 76 if (pskb_network_may_pull(skb, sizeof(struct ipv6hdr)))
74 default: 77 return ntohl(ipv6_hdr(skb)->saddr.s6_addr32[3]);
75 return addr_fold(skb->sk); 78 break;
76 } 79 }
80
81 return addr_fold(skb->sk);
77} 82}
78 83
79static u32 flow_get_dst(const struct sk_buff *skb) 84static u32 flow_get_dst(struct sk_buff *skb)
80{ 85{
81 switch (skb->protocol) { 86 switch (skb->protocol) {
82 case htons(ETH_P_IP): 87 case htons(ETH_P_IP):
83 return ntohl(ip_hdr(skb)->daddr); 88 if (pskb_network_may_pull(skb, sizeof(struct iphdr)))
89 return ntohl(ip_hdr(skb)->daddr);
90 break;
84 case htons(ETH_P_IPV6): 91 case htons(ETH_P_IPV6):
85 return ntohl(ipv6_hdr(skb)->daddr.s6_addr32[3]); 92 if (pskb_network_may_pull(skb, sizeof(struct ipv6hdr)))
86 default: 93 return ntohl(ipv6_hdr(skb)->daddr.s6_addr32[3]);
87 return addr_fold(skb_dst(skb)) ^ (__force u16)skb->protocol; 94 break;
88 } 95 }
96
97 return addr_fold(skb_dst(skb)) ^ (__force u16)skb->protocol;
89} 98}
90 99
91static u32 flow_get_proto(const struct sk_buff *skb) 100static u32 flow_get_proto(struct sk_buff *skb)
92{ 101{
93 switch (skb->protocol) { 102 switch (skb->protocol) {
94 case htons(ETH_P_IP): 103 case htons(ETH_P_IP):
95 return ip_hdr(skb)->protocol; 104 return pskb_network_may_pull(skb, sizeof(struct iphdr)) ?
105 ip_hdr(skb)->protocol : 0;
96 case htons(ETH_P_IPV6): 106 case htons(ETH_P_IPV6):
97 return ipv6_hdr(skb)->nexthdr; 107 return pskb_network_may_pull(skb, sizeof(struct ipv6hdr)) ?
108 ipv6_hdr(skb)->nexthdr : 0;
98 default: 109 default:
99 return 0; 110 return 0;
100 } 111 }
@@ -115,58 +126,64 @@ static int has_ports(u8 protocol)
115 } 126 }
116} 127}
117 128
118static u32 flow_get_proto_src(const struct sk_buff *skb) 129static u32 flow_get_proto_src(struct sk_buff *skb)
119{ 130{
120 u32 res = 0;
121
122 switch (skb->protocol) { 131 switch (skb->protocol) {
123 case htons(ETH_P_IP): { 132 case htons(ETH_P_IP): {
124 struct iphdr *iph = ip_hdr(skb); 133 struct iphdr *iph;
125 134
135 if (!pskb_network_may_pull(skb, sizeof(*iph)))
136 break;
137 iph = ip_hdr(skb);
126 if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) && 138 if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) &&
127 has_ports(iph->protocol)) 139 has_ports(iph->protocol) &&
128 res = ntohs(*(__be16 *)((void *)iph + iph->ihl * 4)); 140 pskb_network_may_pull(skb, iph->ihl * 4 + 2))
141 return ntohs(*(__be16 *)((void *)iph + iph->ihl * 4));
129 break; 142 break;
130 } 143 }
131 case htons(ETH_P_IPV6): { 144 case htons(ETH_P_IPV6): {
132 struct ipv6hdr *iph = ipv6_hdr(skb); 145 struct ipv6hdr *iph;
133 146
147 if (!pskb_network_may_pull(skb, sizeof(*iph) + 2))
148 break;
149 iph = ipv6_hdr(skb);
134 if (has_ports(iph->nexthdr)) 150 if (has_ports(iph->nexthdr))
135 res = ntohs(*(__be16 *)&iph[1]); 151 return ntohs(*(__be16 *)&iph[1]);
136 break; 152 break;
137 } 153 }
138 default:
139 res = addr_fold(skb->sk);
140 } 154 }
141 155
142 return res; 156 return addr_fold(skb->sk);
143} 157}
144 158
145static u32 flow_get_proto_dst(const struct sk_buff *skb) 159static u32 flow_get_proto_dst(struct sk_buff *skb)
146{ 160{
147 u32 res = 0;
148
149 switch (skb->protocol) { 161 switch (skb->protocol) {
150 case htons(ETH_P_IP): { 162 case htons(ETH_P_IP): {
151 struct iphdr *iph = ip_hdr(skb); 163 struct iphdr *iph;
152 164
165 if (!pskb_network_may_pull(skb, sizeof(*iph)))
166 break;
167 iph = ip_hdr(skb);
153 if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) && 168 if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) &&
154 has_ports(iph->protocol)) 169 has_ports(iph->protocol) &&
155 res = ntohs(*(__be16 *)((void *)iph + iph->ihl * 4 + 2)); 170 pskb_network_may_pull(skb, iph->ihl * 4 + 4))
171 return ntohs(*(__be16 *)((void *)iph + iph->ihl * 4 + 2));
156 break; 172 break;
157 } 173 }
158 case htons(ETH_P_IPV6): { 174 case htons(ETH_P_IPV6): {
159 struct ipv6hdr *iph = ipv6_hdr(skb); 175 struct ipv6hdr *iph;
160 176
177 if (!pskb_network_may_pull(skb, sizeof(*iph) + 4))
178 break;
179 iph = ipv6_hdr(skb);
161 if (has_ports(iph->nexthdr)) 180 if (has_ports(iph->nexthdr))
162 res = ntohs(*(__be16 *)((void *)&iph[1] + 2)); 181 return ntohs(*(__be16 *)((void *)&iph[1] + 2));
163 break; 182 break;
164 } 183 }
165 default:
166 res = addr_fold(skb_dst(skb)) ^ (__force u16)skb->protocol;
167 } 184 }
168 185
169 return res; 186 return addr_fold(skb_dst(skb)) ^ (__force u16)skb->protocol;
170} 187}
171 188
172static u32 flow_get_iif(const struct sk_buff *skb) 189static u32 flow_get_iif(const struct sk_buff *skb)
@@ -210,7 +227,7 @@ static u32 flow_get_nfct(const struct sk_buff *skb)
210}) 227})
211#endif 228#endif
212 229
213static u32 flow_get_nfct_src(const struct sk_buff *skb) 230static u32 flow_get_nfct_src(struct sk_buff *skb)
214{ 231{
215 switch (skb->protocol) { 232 switch (skb->protocol) {
216 case htons(ETH_P_IP): 233 case htons(ETH_P_IP):
@@ -222,7 +239,7 @@ fallback:
222 return flow_get_src(skb); 239 return flow_get_src(skb);
223} 240}
224 241
225static u32 flow_get_nfct_dst(const struct sk_buff *skb) 242static u32 flow_get_nfct_dst(struct sk_buff *skb)
226{ 243{
227 switch (skb->protocol) { 244 switch (skb->protocol) {
228 case htons(ETH_P_IP): 245 case htons(ETH_P_IP):
@@ -234,14 +251,14 @@ fallback:
234 return flow_get_dst(skb); 251 return flow_get_dst(skb);
235} 252}
236 253
237static u32 flow_get_nfct_proto_src(const struct sk_buff *skb) 254static u32 flow_get_nfct_proto_src(struct sk_buff *skb)
238{ 255{
239 return ntohs(CTTUPLE(skb, src.u.all)); 256 return ntohs(CTTUPLE(skb, src.u.all));
240fallback: 257fallback:
241 return flow_get_proto_src(skb); 258 return flow_get_proto_src(skb);
242} 259}
243 260
244static u32 flow_get_nfct_proto_dst(const struct sk_buff *skb) 261static u32 flow_get_nfct_proto_dst(struct sk_buff *skb)
245{ 262{
246 return ntohs(CTTUPLE(skb, dst.u.all)); 263 return ntohs(CTTUPLE(skb, dst.u.all));
247fallback: 264fallback:
@@ -280,7 +297,7 @@ static u32 flow_get_vlan_tag(const struct sk_buff *skb)
280 return tag & VLAN_VID_MASK; 297 return tag & VLAN_VID_MASK;
281} 298}
282 299
283static u32 flow_key_get(const struct sk_buff *skb, int key) 300static u32 flow_key_get(struct sk_buff *skb, int key)
284{ 301{
285 switch (key) { 302 switch (key) {
286 case FLOW_KEY_SRC: 303 case FLOW_KEY_SRC:
@@ -601,7 +618,6 @@ static unsigned long flow_get(struct tcf_proto *tp, u32 handle)
601 618
602static void flow_put(struct tcf_proto *tp, unsigned long f) 619static void flow_put(struct tcf_proto *tp, unsigned long f)
603{ 620{
604 return;
605} 621}
606 622
607static int flow_dump(struct tcf_proto *tp, unsigned long fh, 623static int flow_dump(struct tcf_proto *tp, unsigned long fh,