diff options
Diffstat (limited to 'util.c')
-rw-r--r-- | util.c | 39 |
1 files changed, 39 insertions, 0 deletions
@@ -7,8 +7,11 @@ * */ +#include <stdio.h> #include <stdint.h> #include <stddef.h> +#include <linux/ipv6.h> +#include <arpa/inet.h> /** * csum_fold() - Fold long sum for IP and TCP checksum @@ -46,3 +49,39 @@ uint16_t csum_ip4(void *buf, size_t len) return ~csum_fold(sum); } + +unsigned char *ipv6_l4hdr(struct ipv6hdr *ip6h, uint8_t *proto) +{ + int offset, len, hdrlen; + struct ipv6_opt_hdr *o; + uint8_t nh; + + len = ntohs(ip6h->payload_len); + offset = 0; + + while (offset < len) { + if (!offset) { + nh = ip6h->nexthdr; + hdrlen = sizeof(struct ipv6hdr); + } else { + nh = o->nexthdr; + hdrlen = (o->hdrlen + 1) * 8; + } + + if (nh == 59) + return NULL; + + if (nh == 0 || nh == 43 || nh == 44 || nh == 50 || + nh == 51 || nh == 60 || nh == 135 || nh == 139 || + nh == 140 || nh == 253 || nh == 254) { + offset += hdrlen; + o = (struct ipv6_opt_hdr *)(unsigned char *)ip6h + + offset; + } else { + *proto = nh; + return (unsigned char *)(ip6h + 1) + offset; + } + } + + return NULL; +} |