- if (ip6->nexthdr == IP_PROTO_TCP) {
- if (l4hdr + sizeof(struct tcphdr) > data_end)
- return XDP_DROP;
- tcp = (struct tcphdr*) l4hdr;
- } else if (ip6->nexthdr == IP_PROTO_UDP) {
- if (l4hdr + sizeof(struct udphdr) > data_end)
- return XDP_DROP;
- udp = (struct udphdr*) l4hdr;
- } else if (ip6->nexthdr == IP_PROTO_ICMPV6) {
- if (l4hdr + sizeof(struct icmp6hdr) > data_end)
- return XDP_DROP;
- icmpv6 = (struct icmp6hdr*) l4hdr;
+
+ uint8_t v6nexthdr = ip6->nexthdr;
+#ifdef PARSE_V6_FRAG
+#if PARSE_V6_FRAG == PARSE
+ if (ip6->nexthdr == IP6_PROTO_FRAG) {
+ CHECK_LEN(l4hdr, ip6_fraghdr);
+ frag6 = (struct ip6_fraghdr*) l4hdr;
+ l4hdr = l4hdr + sizeof(struct ip6_fraghdr);
+ v6nexthdr = frag6->nexthdr;
+#else
+ if (unlikely(ip6->nexthdr == IP6_PROTO_FRAG)) {
+ DO_RETURN(V6FRAG_DROP, PARSE_V6_FRAG);
+#endif
+ }
+#endif
+ // TODO: Handle more options?
+
+ if (frag6 == NULL || (frag6->frag_off & BE16(IP6_FRAGOFF)) == 0) {
+ if (v6nexthdr == IP_PROTO_TCP) {
+ CHECK_LEN(l4hdr, tcphdr);
+ tcp = (struct tcphdr*) l4hdr;
+ } else if (v6nexthdr == IP_PROTO_UDP) {
+ CHECK_LEN(l4hdr, udphdr);
+ udp = (struct udphdr*) l4hdr;
+ } else if (v6nexthdr == IP6_PROTO_ICMPV6) {
+ CHECK_LEN(l4hdr, icmp6hdr);
+ icmpv6 = (struct icmp6hdr*) l4hdr;
+ }