+#ifdef HAVE_NETINET_IP6_H
+/**
+ * Skip to the actual payload and parse the transport header.
+ */
+static bool parse_transport_header_v6(struct ip6_hdr *ip, chunk_t packet,
+ chunk_t *payload, uint8_t *proto,
+ uint16_t *sport, uint16_t *dport)
+{
+ struct ip6_ext *ext;
+ bool fragment = FALSE;
+
+ *proto = ip->ip6_nxt;
+ *payload = chunk_skip(packet, 40);
+ while (payload->len >= sizeof(struct ip6_ext))
+ {
+ switch (*proto)
+ {
+ case 44: /* Fragment Header */
+ fragment = TRUE;
+ /* skip the header */
+ case 0: /* Hop-by-Hop Options Header */
+ case 43: /* Routing Header */
+ case 60: /* Destination Options Header */
+ case 135: /* Mobility Header */
+ case 139: /* HIP */
+ case 140: /* Shim6 */
+ /* simply skip over these headers for now */
+ ext = (struct ip6_ext*)payload->ptr;
+ *proto = ext->ip6e_nxt;
+ *payload = chunk_skip(*payload, 8 * (ext->ip6e_len + 1));
+ continue;
+ default:
+ /* assume anything else is an upper layer protocol but only
+ * attempt to parse the transport header for non-fragmented
+ * packets as there is no guarantee that initial fragments
+ * contain the transport header, depending on the number and
+ * type of extension headers */
+ if (!fragment &&
+ !parse_transport_header(*payload, *proto, sport, dport))
+ {
+ return FALSE;
+ }
+ break;
+ }
+ break;
+ }
+ return TRUE;
+}
+#endif /* HAVE_NETINET_IP6_H */
+