Checks whether IPPROTO_ROUTING exists in the IPv6 extension headers. If it exists, the first address is retrieved.
If NULL is specified for "frag_hdr" and/or "rt_hdr", those addresses in the header are not reported to the caller. Of course, "frag_hdr" and "rt_hdr" are properly parsed inside this function. Signed-off-by: Nobuhiro MIKI <nm...@yahoo-corp.jp> --- lib/conntrack.c | 4 ++-- lib/flow.c | 48 +++++++++++++++++++++++++++++++++++++----------- lib/flow.h | 3 ++- lib/ipf.c | 15 ++++++++------- lib/packets.h | 9 +++++++++ 5 files changed, 58 insertions(+), 21 deletions(-) diff --git a/lib/conntrack.c b/lib/conntrack.c index 8cf7779c6703..f86fa26f466d 100644 --- a/lib/conntrack.c +++ b/lib/conntrack.c @@ -1617,8 +1617,8 @@ extract_l3_ipv6(struct conn_key *key, const void *data, size_t size, uint8_t nw_proto = ip6->ip6_nxt; uint8_t nw_frag = 0; - const struct ovs_16aligned_ip6_frag *frag_hdr; - if (!parse_ipv6_ext_hdrs(&data, &size, &nw_proto, &nw_frag, &frag_hdr)) { + if (!parse_ipv6_ext_hdrs(&data, &size, &nw_proto, &nw_frag, + NULL, NULL)) { return false; } diff --git a/lib/flow.c b/lib/flow.c index c3a3aa3ce45d..9501a259e9d4 100644 --- a/lib/flow.c +++ b/lib/flow.c @@ -479,9 +479,17 @@ invalid: static inline bool parse_ipv6_ext_hdrs__(const void **datap, size_t *sizep, uint8_t *nw_proto, uint8_t *nw_frag, - const struct ovs_16aligned_ip6_frag **frag_hdr) + const struct ovs_16aligned_ip6_frag **frag_hdr, + const struct ip6_rt_hdr **rt_hdr) { - *frag_hdr = NULL; + if (frag_hdr) { + *frag_hdr = NULL; + } + + if (rt_hdr) { + *rt_hdr = NULL; + } + while (1) { if (OVS_LIKELY((*nw_proto != IPPROTO_HOPOPTS) && (*nw_proto != IPPROTO_ROUTING) @@ -504,7 +512,6 @@ parse_ipv6_ext_hdrs__(const void **datap, size_t *sizep, uint8_t *nw_proto, } if ((*nw_proto == IPPROTO_HOPOPTS) - || (*nw_proto == IPPROTO_ROUTING) || (*nw_proto == IPPROTO_DSTOPTS)) { /* These headers, while different, have the fields we care * about in the same location and with the same @@ -515,6 +522,18 @@ parse_ipv6_ext_hdrs__(const void **datap, size_t *sizep, uint8_t *nw_proto, (ext_hdr->ip6e_len + 1) * 8))) { return false; } + } else if (*nw_proto == IPPROTO_ROUTING) { + const struct ip6_rt_hdr *tmp; + if (!rt_hdr) { + rt_hdr = &tmp; + } + + *rt_hdr = *datap; + *nw_proto = (*rt_hdr)->nexthdr; + if (OVS_UNLIKELY(!data_try_pull(datap, sizep, + ((*rt_hdr)->hdrlen + 1) * 8))) { + return false; + } } else if (*nw_proto == IPPROTO_AH) { /* A standard AH definition isn't available, but the fields * we care about are in the same location as the generic @@ -527,6 +546,11 @@ parse_ipv6_ext_hdrs__(const void **datap, size_t *sizep, uint8_t *nw_proto, return false; } } else if (*nw_proto == IPPROTO_FRAGMENT) { + const struct ovs_16aligned_ip6_frag *tmp; + if (!frag_hdr) { + frag_hdr = &tmp; + } + *frag_hdr = *datap; *nw_proto = (*frag_hdr)->ip6f_nxt; @@ -561,15 +585,19 @@ parse_ipv6_ext_hdrs__(const void **datap, size_t *sizep, uint8_t *nw_proto, * has FLOW_NW_FRAG_LATER set. Both first and later fragments have * FLOW_NW_FRAG_ANY set in 'nw_frag'. * + * If a routing header is found, '*rt_hdr' is set to the routing + * header and otherwise set to NULL. + * * A return value of false indicates that there was a problem parsing * the extension headers.*/ bool parse_ipv6_ext_hdrs(const void **datap, size_t *sizep, uint8_t *nw_proto, uint8_t *nw_frag, - const struct ovs_16aligned_ip6_frag **frag_hdr) + const struct ovs_16aligned_ip6_frag **frag_hdr, + const struct ip6_rt_hdr **rt_hdr) { return parse_ipv6_ext_hdrs__(datap, sizep, nw_proto, nw_frag, - frag_hdr); + frag_hdr, rt_hdr); } bool @@ -945,9 +973,8 @@ miniflow_extract(struct dp_packet *packet, struct miniflow *dst) nw_ttl = nh->ip6_hlim; nw_proto = nh->ip6_nxt; - const struct ovs_16aligned_ip6_frag *frag_hdr; - if (!parse_ipv6_ext_hdrs__(&data, &size, &nw_proto, &nw_frag, - &frag_hdr)) { + if (!parse_ipv6_ext_hdrs(&data, &size, &nw_proto, &nw_frag, + NULL, NULL)) { goto out; } @@ -1200,10 +1227,9 @@ parse_tcp_flags(struct dp_packet *packet, plen = ntohs(nh->ip6_plen); /* Never pull padding. */ dp_packet_set_l2_pad_size(packet, size - plen); size = plen; - const struct ovs_16aligned_ip6_frag *frag_hdr; nw_proto = nh->ip6_nxt; - if (!parse_ipv6_ext_hdrs__(&data, &size, &nw_proto, &nw_frag, - &frag_hdr)) { + if (!parse_ipv6_ext_hdrs(&data, &size, &nw_proto, &nw_frag, + NULL, NULL)) { return 0; } } else { diff --git a/lib/flow.h b/lib/flow.h index c647ad83c256..a9d026e1ce3b 100644 --- a/lib/flow.h +++ b/lib/flow.h @@ -132,7 +132,8 @@ void packet_expand(struct dp_packet *, const struct flow *, size_t size); bool parse_ipv6_ext_hdrs(const void **datap, size_t *sizep, uint8_t *nw_proto, uint8_t *nw_frag, - const struct ovs_16aligned_ip6_frag **frag_hdr); + const struct ovs_16aligned_ip6_frag **frag_hdr, + const struct ip6_rt_hdr **rt_hdr); bool parse_nsh(const void **datap, size_t *sizep, struct ovs_key_nsh *key); uint16_t parse_tcp_flags(struct dp_packet *packet, ovs_be16 *dl_type_p, uint8_t *nw_frag_p, ovs_be16 *first_vlan_tci_p); diff --git a/lib/ipf.c b/lib/ipf.c index d452663743c5..affd440f6387 100644 --- a/lib/ipf.c +++ b/lib/ipf.c @@ -485,9 +485,9 @@ ipf_reassemble_v6_frags(struct ipf_list *ipf_list) const void *data = l3 + 1; size_t datasize = pl; - const struct ovs_16aligned_ip6_frag *frag_hdr = NULL; - if (!parse_ipv6_ext_hdrs(&data, &datasize, &nw_proto, &nw_frag, &frag_hdr) - || !nw_frag || !frag_hdr) { + const struct ovs_16aligned_ip6_frag *frag_hdr; + if (!parse_ipv6_ext_hdrs(&data, &datasize, &nw_proto, &nw_frag, &frag_hdr, + NULL) || !nw_frag || !frag_hdr) { ipf_print_reass_packet("Unparsed reassembled v6 packet; v6 hdr:", l3); dp_packet_delete(pkt); @@ -678,9 +678,9 @@ ipf_is_valid_v6_frag(struct ipf *ipf, struct dp_packet *pkt) uint8_t nw_proto = l3->ip6_nxt; const void *data = l3 + 1; size_t datasize = l3_size - l3_hdr_size; - const struct ovs_16aligned_ip6_frag *frag_hdr = NULL; + const struct ovs_16aligned_ip6_frag *frag_hdr; if (!parse_ipv6_ext_hdrs(&data, &datasize, &nw_proto, &nw_frag, - &frag_hdr) || !nw_frag || !frag_hdr) { + &frag_hdr, NULL) || !nw_frag || !frag_hdr) { return false; } @@ -721,9 +721,10 @@ ipf_v6_key_extract(struct dp_packet *pkt, ovs_be16 dl_type, uint16_t zone, uint8_t nw_proto = l3->ip6_nxt; const void *data = l3 + 1; size_t datasize = dp_packet_l3_size(pkt) - sizeof *l3; - const struct ovs_16aligned_ip6_frag *frag_hdr = NULL; + const struct ovs_16aligned_ip6_frag *frag_hdr; - parse_ipv6_ext_hdrs(&data, &datasize, &nw_proto, &nw_frag, &frag_hdr); + parse_ipv6_ext_hdrs(&data, &datasize, &nw_proto, &nw_frag, &frag_hdr, + NULL); ovs_assert(nw_frag && frag_hdr); ovs_be16 ip6f_offlg = frag_hdr->ip6f_offlg; *start_data_byte = ntohs(ip6f_offlg & IP6F_OFF_MASK) + diff --git a/lib/packets.h b/lib/packets.h index 8626aac8d53f..70cd072228ae 100644 --- a/lib/packets.h +++ b/lib/packets.h @@ -988,6 +988,15 @@ struct ovs_16aligned_ip6_frag { ovs_16aligned_be32 ip6f_ident; }; +#define IP6_RT_HDR_LEN 4 +struct ip6_rt_hdr { + uint8_t nexthdr; + uint8_t hdrlen; + uint8_t type; + uint8_t segments_left; +}; +BUILD_ASSERT_DECL(IP6_RT_HDR_LEN == sizeof(struct ip6_rt_hdr)); + #define ICMP6_HEADER_LEN 4 struct icmp6_header { uint8_t icmp6_type; -- 2.31.1 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev