diff options
| author | Michal Marek <mmarek@suse.cz> | 2010-10-27 18:15:57 -0400 |
|---|---|---|
| committer | Michal Marek <mmarek@suse.cz> | 2010-10-27 18:15:57 -0400 |
| commit | b74b953b998bcc2db91b694446f3a2619ec32de6 (patch) | |
| tree | 6ce24caabd730f6ae9287ed0676ec32e6ff31e9d /net/sched/cls_flow.c | |
| parent | abb438526201c6a79949ad45375c051b6681c253 (diff) | |
| parent | f6f94e2ab1b33f0082ac22d71f66385a60d8157f (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.c | 98 |
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 | ||
| 67 | static u32 flow_get_src(const struct sk_buff *skb) | 68 | static 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 | ||
| 79 | static u32 flow_get_dst(const struct sk_buff *skb) | 84 | static 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 | ||
| 91 | static u32 flow_get_proto(const struct sk_buff *skb) | 100 | static 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 | ||
| 118 | static u32 flow_get_proto_src(const struct sk_buff *skb) | 129 | static 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 | ||
| 145 | static u32 flow_get_proto_dst(const struct sk_buff *skb) | 159 | static 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 | ||
| 172 | static u32 flow_get_iif(const struct sk_buff *skb) | 189 | static 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 | ||
| 213 | static u32 flow_get_nfct_src(const struct sk_buff *skb) | 230 | static 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 | ||
| 225 | static u32 flow_get_nfct_dst(const struct sk_buff *skb) | 242 | static 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 | ||
| 237 | static u32 flow_get_nfct_proto_src(const struct sk_buff *skb) | 254 | static 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)); |
| 240 | fallback: | 257 | fallback: |
| 241 | return flow_get_proto_src(skb); | 258 | return flow_get_proto_src(skb); |
| 242 | } | 259 | } |
| 243 | 260 | ||
| 244 | static u32 flow_get_nfct_proto_dst(const struct sk_buff *skb) | 261 | static 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)); |
| 247 | fallback: | 264 | fallback: |
| @@ -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 | ||
| 283 | static u32 flow_key_get(const struct sk_buff *skb, int key) | 300 | static 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 | ||
| 602 | static void flow_put(struct tcf_proto *tp, unsigned long f) | 619 | static void flow_put(struct tcf_proto *tp, unsigned long f) |
| 603 | { | 620 | { |
| 604 | return; | ||
| 605 | } | 621 | } |
| 606 | 622 | ||
| 607 | static int flow_dump(struct tcf_proto *tp, unsigned long fh, | 623 | static int flow_dump(struct tcf_proto *tp, unsigned long fh, |
