+static int
+print_nexthdr(struct log_entry *le, char *hdr, int payload_len, u_int8_t proto)
+{
+ while (1) {
+ if (print_ipproto(le, hdr, payload_len, proto) == 0)
+ return 0;
+
+ struct ip6_ext *exthdr = (struct ip6_ext*)hdr;
+
+ switch (proto) {
+ /* protocols (these return) */
+ case IPPROTO_ICMPV6:
+ LEPRINTF("PROTO=ICMPV6 ");
+ if (check_ip6ext(le, exthdr, payload_len) < 0)
+ return -1;
+ if (print_icmp6(le, (struct icmp6_hdr*)(hdr + exthdr->ip6e_len),
+ payload_len - exthdr->ip6e_len) < 0)
+ {
+ return -1;
+ }
+ return 0;
+
+ /* extension headers (these break to keep iterating) */
+ case IPPROTO_ROUTING:
+ if (check_ip6ext(le, exthdr, payload_len) < 0)
+ return -1;
+ if (print_routing(le, (struct ip6_rthdr*)hdr, payload_len) < 0)
+ return -1;
+ break;
+ case IPPROTO_FRAGMENT:
+ if (check_ip6ext(le, exthdr, payload_len) < 0)
+ return -1;
+ if (print_fragment(le, (struct ip6_frag*)hdr, payload_len) < 0)
+ return -1;
+ break;
+ case IPPROTO_HOPOPTS:
+ LEPRINTF("NEXTHDR=HOPOPTS ");
+ if (check_ip6ext(le, exthdr, payload_len) < 0)
+ return -1;
+ /* do we want to print these? */
+ break;
+ case IPPROTO_DSTOPTS:
+ LEPRINTF("NEXTHDR=DSTOPTS ");
+ if (check_ip6ext(le, exthdr, payload_len) < 0)
+ return -1;
+ /* do we want to print these? */
+ break;
+ case IPPROTO_MH:
+ LEPRINTF("NEXTHDR=MH ");
+ if (check_ip6ext(le, exthdr, payload_len) < 0)
+ return -1;
+ break;
+
+ /* unknown protocol */
+ default:
+ LEPRINTF("PROTO=%u ", proto);
+ return 0; /* bail */
+ }
+ /* next header: */
+ if (check_ip6ext(le, exthdr, payload_len) < 0)
+ return -1;
+ hdr += exthdr->ip6e_len;
+ payload_len -= exthdr->ip6e_len;
+ }
+}
+
+static int
+print_ip6hdr(struct log_entry *le, char * payload, int payload_len)
+{
+ if (payload_len < sizeof(struct ip6_hdr)) {
+ LEPRINTF("LEN=%d ", payload_len);
+ LEPRINTF("INVALID=LEN ");
+ return -1;
+ }
+
+ struct ip6_hdr *h = (struct ip6_hdr*)payload;
+
+ char tmp[INET6_ADDRSTRLEN];
+ inet_ntop(AF_INET6, &h->ip6_src, tmp, sizeof(tmp));
+ LEPRINTF("SRC=%s ", tmp);
+ inet_ntop(AF_INET6, &h->ip6_dst, tmp, sizeof(tmp));
+ LEPRINTF("DST=%s ", tmp);
+
+ LEPRINTF("LEN=%u ", ntohs(h->ip6_plen));
+
+ u_int32_t flow = ntohl(h->ip6_flow);
+ LEPRINTF("TC=%d FLOWLBL=%d ", (flow>>20)&0xFF, flow&0xFFFFF);
+
+ LEPRINTF("HOPLIMIT=%d ", h->ip6_hlim);
+
+ return print_nexthdr(le, (char *)(h+1), payload_len - sizeof(*h), h->ip6_nxt);
+}
+