diff options
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/flow_dissector.c | 40 |
1 files changed, 26 insertions, 14 deletions
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 5f362c1d0332..660c6492fb78 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c | |||
@@ -34,29 +34,40 @@ static void iph_to_flow_copy_addrs(struct flow_keys *flow, const struct iphdr *i | |||
34 | * The function will try to retrieve the ports at offset thoff + poff where poff | 34 | * The function will try to retrieve the ports at offset thoff + poff where poff |
35 | * is the protocol port offset returned from proto_ports_offset | 35 | * is the protocol port offset returned from proto_ports_offset |
36 | */ | 36 | */ |
37 | __be32 skb_flow_get_ports(const struct sk_buff *skb, int thoff, u8 ip_proto) | 37 | __be32 __skb_flow_get_ports(const struct sk_buff *skb, int thoff, u8 ip_proto, |
38 | void *data, int hlen) | ||
38 | { | 39 | { |
39 | int poff = proto_ports_offset(ip_proto); | 40 | int poff = proto_ports_offset(ip_proto); |
40 | 41 | ||
42 | if (!data) { | ||
43 | data = skb->data; | ||
44 | hlen = skb_headlen(skb); | ||
45 | } | ||
46 | |||
41 | if (poff >= 0) { | 47 | if (poff >= 0) { |
42 | __be32 *ports, _ports; | 48 | __be32 *ports, _ports; |
43 | 49 | ||
44 | ports = skb_header_pointer(skb, thoff + poff, | 50 | ports = __skb_header_pointer(skb, thoff + poff, |
45 | sizeof(_ports), &_ports); | 51 | sizeof(_ports), data, hlen, &_ports); |
46 | if (ports) | 52 | if (ports) |
47 | return *ports; | 53 | return *ports; |
48 | } | 54 | } |
49 | 55 | ||
50 | return 0; | 56 | return 0; |
51 | } | 57 | } |
52 | EXPORT_SYMBOL(skb_flow_get_ports); | 58 | EXPORT_SYMBOL(__skb_flow_get_ports); |
53 | 59 | ||
54 | bool skb_flow_dissect(const struct sk_buff *skb, struct flow_keys *flow) | 60 | bool __skb_flow_dissect(const struct sk_buff *skb, struct flow_keys *flow, void *data, int hlen) |
55 | { | 61 | { |
56 | int nhoff = skb_network_offset(skb); | 62 | int nhoff = skb_network_offset(skb); |
57 | u8 ip_proto; | 63 | u8 ip_proto; |
58 | __be16 proto = skb->protocol; | 64 | __be16 proto = skb->protocol; |
59 | 65 | ||
66 | if (!data) { | ||
67 | data = skb->data; | ||
68 | hlen = skb_headlen(skb); | ||
69 | } | ||
70 | |||
60 | memset(flow, 0, sizeof(*flow)); | 71 | memset(flow, 0, sizeof(*flow)); |
61 | 72 | ||
62 | again: | 73 | again: |
@@ -65,7 +76,7 @@ again: | |||
65 | const struct iphdr *iph; | 76 | const struct iphdr *iph; |
66 | struct iphdr _iph; | 77 | struct iphdr _iph; |
67 | ip: | 78 | ip: |
68 | iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph); | 79 | iph = __skb_header_pointer(skb, nhoff, sizeof(_iph), data, hlen, &_iph); |
69 | if (!iph || iph->ihl < 5) | 80 | if (!iph || iph->ihl < 5) |
70 | return false; | 81 | return false; |
71 | nhoff += iph->ihl * 4; | 82 | nhoff += iph->ihl * 4; |
@@ -83,7 +94,7 @@ ip: | |||
83 | __be32 flow_label; | 94 | __be32 flow_label; |
84 | 95 | ||
85 | ipv6: | 96 | ipv6: |
86 | iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph); | 97 | iph = __skb_header_pointer(skb, nhoff, sizeof(_iph), data, hlen, &_iph); |
87 | if (!iph) | 98 | if (!iph) |
88 | return false; | 99 | return false; |
89 | 100 | ||
@@ -113,7 +124,7 @@ ipv6: | |||
113 | const struct vlan_hdr *vlan; | 124 | const struct vlan_hdr *vlan; |
114 | struct vlan_hdr _vlan; | 125 | struct vlan_hdr _vlan; |
115 | 126 | ||
116 | vlan = skb_header_pointer(skb, nhoff, sizeof(_vlan), &_vlan); | 127 | vlan = __skb_header_pointer(skb, nhoff, sizeof(_vlan), data, hlen, &_vlan); |
117 | if (!vlan) | 128 | if (!vlan) |
118 | return false; | 129 | return false; |
119 | 130 | ||
@@ -126,7 +137,7 @@ ipv6: | |||
126 | struct pppoe_hdr hdr; | 137 | struct pppoe_hdr hdr; |
127 | __be16 proto; | 138 | __be16 proto; |
128 | } *hdr, _hdr; | 139 | } *hdr, _hdr; |
129 | hdr = skb_header_pointer(skb, nhoff, sizeof(_hdr), &_hdr); | 140 | hdr = __skb_header_pointer(skb, nhoff, sizeof(_hdr), data, hlen, &_hdr); |
130 | if (!hdr) | 141 | if (!hdr) |
131 | return false; | 142 | return false; |
132 | proto = hdr->proto; | 143 | proto = hdr->proto; |
@@ -151,7 +162,7 @@ ipv6: | |||
151 | __be16 proto; | 162 | __be16 proto; |
152 | } *hdr, _hdr; | 163 | } *hdr, _hdr; |
153 | 164 | ||
154 | hdr = skb_header_pointer(skb, nhoff, sizeof(_hdr), &_hdr); | 165 | hdr = __skb_header_pointer(skb, nhoff, sizeof(_hdr), data, hlen, &_hdr); |
155 | if (!hdr) | 166 | if (!hdr) |
156 | return false; | 167 | return false; |
157 | /* | 168 | /* |
@@ -171,8 +182,9 @@ ipv6: | |||
171 | const struct ethhdr *eth; | 182 | const struct ethhdr *eth; |
172 | struct ethhdr _eth; | 183 | struct ethhdr _eth; |
173 | 184 | ||
174 | eth = skb_header_pointer(skb, nhoff, | 185 | eth = __skb_header_pointer(skb, nhoff, |
175 | sizeof(_eth), &_eth); | 186 | sizeof(_eth), |
187 | data, hlen, &_eth); | ||
176 | if (!eth) | 188 | if (!eth) |
177 | return false; | 189 | return false; |
178 | proto = eth->h_proto; | 190 | proto = eth->h_proto; |
@@ -194,12 +206,12 @@ ipv6: | |||
194 | 206 | ||
195 | flow->n_proto = proto; | 207 | flow->n_proto = proto; |
196 | flow->ip_proto = ip_proto; | 208 | flow->ip_proto = ip_proto; |
197 | flow->ports = skb_flow_get_ports(skb, nhoff, ip_proto); | 209 | flow->ports = __skb_flow_get_ports(skb, nhoff, ip_proto, data, hlen); |
198 | flow->thoff = (u16) nhoff; | 210 | flow->thoff = (u16) nhoff; |
199 | 211 | ||
200 | return true; | 212 | return true; |
201 | } | 213 | } |
202 | EXPORT_SYMBOL(skb_flow_dissect); | 214 | EXPORT_SYMBOL(__skb_flow_dissect); |
203 | 215 | ||
204 | static u32 hashrnd __read_mostly; | 216 | static u32 hashrnd __read_mostly; |
205 | static __always_inline void __flow_hash_secret_init(void) | 217 | static __always_inline void __flow_hash_secret_init(void) |