Skip to content

Commit c30da49

Browse files
shorman-netronomedavem330
authored andcommitted
openvswitch: retain parsed IPv6 header fields in flow on error skipping extension headers
When an error occurs skipping IPv6 extension headers retain the already parsed IP protocol and IPv6 addresses in the flow. Also assume that the packet is not a fragment in the absence of information to the contrary; that is always use the frag_off value set by ipv6_skip_exthdr(). This allows matching on the IP protocol and IPv6 addresses of packets with malformed extension headers. Signed-off-by: Simon Horman <simon.horman@netronome.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent f5004a1 commit c30da49

File tree

1 file changed

+15
-6
lines changed

1 file changed

+15
-6
lines changed

net/openvswitch/flow.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -272,8 +272,6 @@ static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key)
272272
key->ipv6.addr.dst = nh->daddr;
273273

274274
payload_ofs = ipv6_skip_exthdr(skb, payload_ofs, &nexthdr, &frag_off);
275-
if (unlikely(payload_ofs < 0))
276-
return -EINVAL;
277275

278276
if (frag_off) {
279277
if (frag_off & htons(~0x7))
@@ -284,6 +282,13 @@ static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key)
284282
key->ip.frag = OVS_FRAG_TYPE_NONE;
285283
}
286284

285+
/* Delayed handling of error in ipv6_skip_exthdr() as it
286+
* always sets frag_off to a valid value which may be
287+
* used to set key->ip.frag above.
288+
*/
289+
if (unlikely(payload_ofs < 0))
290+
return -EPROTO;
291+
287292
nh_len = payload_ofs - nh_ofs;
288293
skb_set_transport_header(skb, nh_ofs + nh_len);
289294
key->ip.proto = nexthdr;
@@ -623,12 +628,16 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
623628

624629
nh_len = parse_ipv6hdr(skb, key);
625630
if (unlikely(nh_len < 0)) {
626-
memset(&key->ip, 0, sizeof(key->ip));
627-
memset(&key->ipv6.addr, 0, sizeof(key->ipv6.addr));
628-
if (nh_len == -EINVAL) {
631+
switch (nh_len) {
632+
case -EINVAL:
633+
memset(&key->ip, 0, sizeof(key->ip));
634+
memset(&key->ipv6.addr, 0, sizeof(key->ipv6.addr));
635+
/* fall-through */
636+
case -EPROTO:
629637
skb->transport_header = skb->network_header;
630638
error = 0;
631-
} else {
639+
break;
640+
default:
632641
error = nh_len;
633642
}
634643
return error;

0 commit comments

Comments
 (0)