From: Victor Julien Date: Sun, 15 May 2016 11:35:10 +0000 (+0200) Subject: ipv6: simplify ext hdr parsing and storage X-Git-Tag: suricata-3.1RC1~135 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=68c7fae79fdcf70e817a76022c989f77b176b3fe;p=thirdparty%2Fsuricata.git ipv6: simplify ext hdr parsing and storage This reduces size of the IPV6ExtHdr structure part of every packet significantly. Clean up macro's in the ipv6 header. --- diff --git a/src/decode-ipv6.c b/src/decode-ipv6.c index e636242199..c13b8806c9 100644 --- a/src/decode-ipv6.c +++ b/src/decode-ipv6.c @@ -113,6 +113,14 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt char dstopts = 0; char exthdr_fh_done = 0; + uint8_t ip6_exthdrs_cnt = 0; + IPV6GenOptHdr ip6_exthdrs[IPV6_MAX_OPT]; + + int hh = 0; + int rh = 0; + int eh = 0; + int ah = 0; + nh = IPV6_GET_NH(p); plen = len; @@ -161,16 +169,16 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt SCReturn; } - if (p->IPV6_EH_CNT < IPV6_MAX_OPT) + if (ip6_exthdrs_cnt < IPV6_MAX_OPT) { - p->IPV6_EXTHDRS[p->IPV6_EH_CNT].type = nh; - p->IPV6_EXTHDRS[p->IPV6_EH_CNT].next = *pkt; - p->IPV6_EXTHDRS[p->IPV6_EH_CNT].len = hdrextlen; - p->IPV6_EXTHDRS[p->IPV6_EH_CNT].data = pkt+2; - p->IPV6_EH_CNT++; + ip6_exthdrs[ip6_exthdrs_cnt].type = nh; + ip6_exthdrs[ip6_exthdrs_cnt].next = *pkt; + ip6_exthdrs[ip6_exthdrs_cnt].len = hdrextlen; + ip6_exthdrs[ip6_exthdrs_cnt].data = pkt+2; + ip6_exthdrs_cnt++; } - if (IPV6_EXTHDR_ISSET_RH(p)) { + if (rh) { ENGINE_SET_EVENT(p, IPV6_EXTHDR_DUPL_RH); /* skip past this extension so we can continue parsing the rest * of the packet */ @@ -180,26 +188,14 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt break; } - IPV6_EXTHDR_SET_RH(p, pkt); - - /** \todo move into own function and load on demand */ - if (IPV6_EXTHDR_RH(p)->ip6rh_type == 0) { -#if 0 // XXX usused and broken, original packet is modified in the memcpy - uint8_t i; - - uint8_t n = hdrextlen / 2; - /* because we devide the header len by 2 (as rfc 2460 tells us to) - * we devide the result by 8 and not 16 as the header fields are - * sized */ - for (i = 0; i < (n/8) && i < sizeof(IPV6_EXTHDR_RH(p)->ip6rh0_addr)/sizeof(struct in6_addr); ++i) { - /* the address header fields are 16 bytes in size */ - /** \todo do this without memcpy since it's expensive */ - memcpy(&IPV6_EXTHDR_RH(p)->ip6rh0_addr[i], pkt+(i*16)+8, sizeof(IPV6_EXTHDR_RH(p)->ip6rh0_addr[i])); - } - IPV6_EXTHDR_RH(p)->ip6rh0_num_addrs = i; -#endif + rh = 1; + IPV6_EXTHDR_SET_RH(p); + + uint8_t ip6rh_type = *(pkt + 2); + if (ip6rh_type == 0) { ENGINE_SET_EVENT(p, IPV6_EXTHDR_RH_TYPE_0); } + p->ip6eh.rh_type = ip6rh_type; nh = *pkt; pkt += hdrextlen; @@ -209,9 +205,9 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt case IPPROTO_HOPOPTS: case IPPROTO_DSTOPTS: { - IPV6OptHAO *hao = NULL; - IPV6OptRA *ra = NULL; - IPV6OptJumbo *jumbo = NULL; + IPV6OptHAO hao_s, *hao = &hao_s; + IPV6OptRA ra_s, *ra = &ra_s; + IPV6OptJumbo jumbo_s, *jumbo = &jumbo_s; uint16_t optslen = 0; IPV6_SET_L4PROTO(p,nh); @@ -221,13 +217,13 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt SCReturn; } - if (p->IPV6_EH_CNT < IPV6_MAX_OPT) + if (ip6_exthdrs_cnt < IPV6_MAX_OPT) { - p->IPV6_EXTHDRS[p->IPV6_EH_CNT].type = nh; - p->IPV6_EXTHDRS[p->IPV6_EH_CNT].next = *pkt; - p->IPV6_EXTHDRS[p->IPV6_EH_CNT].len = hdrextlen; - p->IPV6_EXTHDRS[p->IPV6_EH_CNT].data = pkt+2; - p->IPV6_EH_CNT++; + ip6_exthdrs[ip6_exthdrs_cnt].type = nh; + ip6_exthdrs[ip6_exthdrs_cnt].next = *pkt; + ip6_exthdrs[ip6_exthdrs_cnt].len = hdrextlen; + ip6_exthdrs[ip6_exthdrs_cnt].data = pkt+2; + ip6_exthdrs_cnt++; } uint8_t *ptr = pkt + 2; /* +2 to go past nxthdr and len */ @@ -235,7 +231,7 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt /* point the pointers to right structures * in Packet. */ if (nh == IPPROTO_HOPOPTS) { - if (IPV6_EXTHDR_ISSET_HH(p)) { + if (hh) { ENGINE_SET_EVENT(p, IPV6_EXTHDR_DUPL_HH); /* skip past this extension so we can continue parsing the rest * of the packet */ @@ -245,28 +241,17 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt break; } - IPV6_EXTHDR_SET_HH(p, pkt); - hao = &IPV6_EXTHDR_HH_HAO(p); - ra = &IPV6_EXTHDR_HH_RA(p); - jumbo = &IPV6_EXTHDR_HH_JUMBO(p); + hh = 1; - optslen = ((IPV6_EXTHDR_HH(p)->ip6hh_len+1)<<3)-2; + optslen = ((*(pkt + 1) + 1 ) << 3) - 2; } else if (nh == IPPROTO_DSTOPTS) { if (dstopts == 0) { - IPV6_EXTHDR_SET_DH1(p, pkt); - hao = &IPV6_EXTHDR_DH1_HAO(p); - ra = &IPV6_EXTHDR_DH1_RA(p); - jumbo = &IPV6_EXTHDR_DH2_JUMBO(p); - optslen = ((IPV6_EXTHDR_DH1(p)->ip6dh_len+1)<<3)-2; + optslen = ((*(pkt + 1) + 1 ) << 3) - 2; dstopts = 1; } else if (dstopts == 1) { - IPV6_EXTHDR_SET_DH2(p, pkt); - hao = &IPV6_EXTHDR_DH2_HAO(p); - ra = &IPV6_EXTHDR_DH2_RA(p); - jumbo = &IPV6_EXTHDR_DH2_JUMBO(p); - optslen = ((IPV6_EXTHDR_DH2(p)->ip6dh_len+1)<<3)-2; + optslen = ((*(pkt + 1) + 1 ) << 3) - 2; dstopts = 2; } else { ENGINE_SET_EVENT(p, IPV6_EXTHDR_DUPL_DH); @@ -424,13 +409,13 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt /* non fatal, lets try to continue */ } - if(p->IPV6_EH_CNTIPV6_EXTHDRS[p->IPV6_EH_CNT].type = nh; - p->IPV6_EXTHDRS[p->IPV6_EH_CNT].next = *pkt; - p->IPV6_EXTHDRS[p->IPV6_EH_CNT].len = hdrextlen; - p->IPV6_EXTHDRS[p->IPV6_EH_CNT].data = pkt+2; - p->IPV6_EH_CNT++; + ip6_exthdrs[ip6_exthdrs_cnt].type = nh; + ip6_exthdrs[ip6_exthdrs_cnt].next = *pkt; + ip6_exthdrs[ip6_exthdrs_cnt].len = hdrextlen; + ip6_exthdrs[ip6_exthdrs_cnt].data = pkt+2; + ip6_exthdrs_cnt++; } if (IPV6_EXTHDR_ISSET_FH(p)) { @@ -441,14 +426,49 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt break; } - /* set the header ptr first */ - IPV6_EXTHDR_SET_FH(p, pkt); + /* set the header flag first */ + IPV6_EXTHDR_SET_FH(p); + + uint16_t frag_offset = (*(pkt + 2) << 8 | *(pkt + 3)) & 0xFFF8; + int frag_morefrags = (*(pkt + 2) << 8 | *(pkt + 3)) & 0x0001; + + p->ip6eh.fh_offset = frag_offset; + p->ip6eh.fh_more_frags_set = frag_morefrags ? TRUE : FALSE; + p->ip6eh.fh_nh = *pkt; + + uint32_t fh_id; + memcpy(&fh_id, pkt+4, 4); + p->ip6eh.fh_id = ntohl(fh_id); + + SCLogDebug("IPV6 FH: offset %u, mf %s, nh %u, id %u/%x", + p->ip6eh.fh_offset, + p->ip6eh.fh_more_frags_set ? "true" : "false", + p->ip6eh.fh_nh, + p->ip6eh.fh_id, p->ip6eh.fh_id); + + // store header offset, data offset + uint16_t frag_hdr_offset = (uint16_t)(pkt - GET_PKT_DATA(p)); + uint16_t data_offset = (uint16_t)(frag_hdr_offset + hdrextlen); + uint16_t data_len = plen - hdrextlen; + + p->ip6eh.fh_header_offset = frag_hdr_offset; + p->ip6eh.fh_data_offset = data_offset; + p->ip6eh.fh_data_len = data_len; + + /* if we have a prev hdr, store the type and offset of it */ + if (ip6_exthdrs_cnt > 1) { + p->ip6eh.fh_prev_hdr_offset = frag_hdr_offset - ip6_exthdrs[ip6_exthdrs_cnt - 1].len; + } + + SCLogDebug("IPV6 FH: frag_hdr_offset %u, data_offset %u, data_len %u", + p->ip6eh.fh_header_offset, p->ip6eh.fh_data_offset, + p->ip6eh.fh_data_len); /* if FH has offset 0 and no more fragments are coming, we * parse this packet further right away, no defrag will be * needed. It is a useless FH then though, so we do set an * decoder event. */ - if (IPV6_EXTHDR_GET_FH_FLAG(p) == 0 && IPV6_EXTHDR_GET_FH_OFFSET(p) == 0) { + if (frag_morefrags == 0 && frag_offset == 0) { ENGINE_SET_EVENT(p, IPV6_EXTHDR_USELESS_FH); nh = *pkt; @@ -470,21 +490,21 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt SCReturn; } - if(p->IPV6_EH_CNTIPV6_EXTHDRS[p->IPV6_EH_CNT].type = nh; - p->IPV6_EXTHDRS[p->IPV6_EH_CNT].next = IPPROTO_NONE; - p->IPV6_EXTHDRS[p->IPV6_EH_CNT].len = hdrextlen; - p->IPV6_EXTHDRS[p->IPV6_EH_CNT].data = pkt+2; - p->IPV6_EH_CNT++; + ip6_exthdrs[ip6_exthdrs_cnt].type = nh; + ip6_exthdrs[ip6_exthdrs_cnt].next = IPPROTO_NONE; + ip6_exthdrs[ip6_exthdrs_cnt].len = hdrextlen; + ip6_exthdrs[ip6_exthdrs_cnt].data = pkt+2; + ip6_exthdrs_cnt++; } - if (IPV6_EXTHDR_ISSET_EH(p)) { + if (eh) { ENGINE_SET_EVENT(p, IPV6_EXTHDR_DUPL_EH); SCReturn; } - IPV6_EXTHDR_SET_EH(p, pkt); + eh = 1; nh = IPPROTO_NONE; pkt += hdrextlen; @@ -513,16 +533,16 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt ENGINE_SET_EVENT(p, IPV6_EXTHDR_AH_RES_NOT_NULL); } - if(p->IPV6_EH_CNT < IPV6_MAX_OPT) + if(ip6_exthdrs_cnt < IPV6_MAX_OPT) { - p->IPV6_EXTHDRS[p->IPV6_EH_CNT].type = nh; - p->IPV6_EXTHDRS[p->IPV6_EH_CNT].next = *pkt; - p->IPV6_EXTHDRS[p->IPV6_EH_CNT].len = hdrextlen; - p->IPV6_EXTHDRS[p->IPV6_EH_CNT].data = pkt+2; - p->IPV6_EH_CNT++; + ip6_exthdrs[ip6_exthdrs_cnt].type = nh; + ip6_exthdrs[ip6_exthdrs_cnt].next = *pkt; + ip6_exthdrs[ip6_exthdrs_cnt].len = hdrextlen; + ip6_exthdrs[ip6_exthdrs_cnt].data = pkt+2; + ip6_exthdrs_cnt++; } - if (IPV6_EXTHDR_ISSET_AH(p)) { + if (ah) { ENGINE_SET_EVENT(p, IPV6_EXTHDR_DUPL_AH); nh = *pkt; pkt += hdrextlen; @@ -530,7 +550,7 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt break; } - IPV6_EXTHDR_SET_AH(p, pkt); + ah = 1; nh = *pkt; pkt += hdrextlen; @@ -677,30 +697,6 @@ int DecodeIPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, u } } -#ifdef DEBUG - if (IPV6_EXTHDR_ISSET_FH(p)) { - SCLogDebug("IPV6 FRAG - HDRLEN: %" PRIuMAX " NH: %" PRIu32 " OFFSET: %" PRIu32 " ID: %" PRIu32 "", - (uintmax_t)IPV6_EXTHDR_GET_FH_HDRLEN(p), IPV6_EXTHDR_GET_FH_NH(p), - IPV6_EXTHDR_GET_FH_OFFSET(p), IPV6_EXTHDR_GET_FH_ID(p)); - } - if (IPV6_EXTHDR_ISSET_RH(p)) { - SCLogDebug("IPV6 ROUTE - HDRLEN: %" PRIu32 " NH: %" PRIu32 " TYPE: %" PRIu32 "", - IPV6_EXTHDR_GET_RH_HDRLEN(p), IPV6_EXTHDR_GET_RH_NH(p), - IPV6_EXTHDR_GET_RH_TYPE(p)); - } - if (IPV6_EXTHDR_ISSET_HH(p)) { - SCLogDebug("IPV6 HOPOPT - HDRLEN: %" PRIu32 " NH: %" PRIu32 "", - IPV6_EXTHDR_GET_HH_HDRLEN(p), IPV6_EXTHDR_GET_HH_NH(p)); - } - if (IPV6_EXTHDR_ISSET_DH1(p)) { - SCLogDebug("IPV6 DSTOPT1 - HDRLEN: %" PRIu32 " NH: %" PRIu32 "", - IPV6_EXTHDR_GET_DH1_HDRLEN(p), IPV6_EXTHDR_GET_DH1_NH(p)); - } - if (IPV6_EXTHDR_ISSET_DH2(p)) { - SCLogDebug("IPV6 DSTOPT2 - HDRLEN: %" PRIu32 " NH: %" PRIu32 "", - IPV6_EXTHDR_GET_DH2_HDRLEN(p), IPV6_EXTHDR_GET_DH2_NH(p)); - } -#endif return TM_ECODE_OK; } @@ -879,7 +875,6 @@ end: */ static int DecodeIPV6RouteTest01 (void) { - uint8_t raw_pkt1[] = { 0x60, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x2b, 0x40, 0x20, 0x01, 0xaa, 0xaa, 0x00, 0x01, 0x00, 0x00, @@ -893,11 +888,9 @@ static int DecodeIPV6RouteTest01 (void) 0xfa, 0x87, 0x00, 0x00, }; Packet *p1 = PacketGetFromAlloc(); - if (unlikely(p1 == NULL)) - return 0; + FAIL_IF(unlikely(p1 == NULL)); ThreadVars tv; DecodeThreadVars dtv; - int result = 0; PacketQueue pq; FlowInitConfig(FLOW_QUIET); @@ -910,22 +903,12 @@ static int DecodeIPV6RouteTest01 (void) DecodeIPV6(&tv, &dtv, p1, GET_PKT_DATA(p1), GET_PKT_LEN(p1), &pq); - if (!(IPV6_EXTHDR_ISSET_RH(p1))) { - printf("ipv6 routing header not detected: "); - goto end; - } - - if (p1->ip6eh.ip6_exthdrs[0].len != 8) { - printf("ipv6 routing length incorrect: "); - goto end; - } - - result = 1; -end: + FAIL_IF (!(IPV6_EXTHDR_ISSET_RH(p1))); + FAIL_IF (p1->ip6eh.rh_type != 0); PACKET_RECYCLE(p1); SCFree(p1); FlowShutdown(); - return result; + PASS; } /** @@ -936,16 +919,15 @@ static int DecodeIPV6HopTest01 (void) uint8_t raw_pkt1[] = { 0x60,0x00,0x00,0x00,0x00,0x20,0x00,0x01,0xfe,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 0x02,0x0f,0xfe,0xff,0xfe,0x98,0x3d,0x01,0xff,0x02,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x3a,0x00,0x05,0x02,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x3a,0x00,0xff, /* 0xff is a nonsene opt */ + 0x02,0x00,0x00,0x00,0x00, 0x82,0x00,0x1c,0x6f,0x27,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; Packet *p1 = PacketGetFromAlloc(); - if (unlikely(p1 == NULL)) - return 0; + FAIL_IF(unlikely(p1 == NULL)); ThreadVars tv; DecodeThreadVars dtv; - int result = 0; PacketQueue pq; FlowInitConfig(FLOW_QUIET); @@ -958,27 +940,12 @@ static int DecodeIPV6HopTest01 (void) DecodeIPV6(&tv, &dtv, p1, GET_PKT_DATA(p1), GET_PKT_LEN(p1), &pq); - if (!(IPV6_EXTHDR_ISSET_HH(p1))) { - printf("ipv6 routing header not detected: "); - goto end; - } - - if (p1->ip6eh.ip6_exthdrs[0].len != 8) { - printf("ipv6 routing length incorrect: "); - goto end; - } + FAIL_IF (!(ENGINE_ISSET_EVENT(p1, IPV6_HOPOPTS_UNKNOWN_OPT))); - if (ENGINE_ISSET_EVENT(p1, IPV6_HOPOPTS_UNKNOWN_OPT)) { - printf("engine event IPV6_HOPOPTS_UNKNOWN_OPT set: "); - goto end; - } - - result = 1; -end: PACKET_RECYCLE(p1); SCFree(p1); FlowShutdown(); - return result; + PASS; } #endif /* UNITTESTS */ diff --git a/src/decode-ipv6.h b/src/decode-ipv6.h index da58d9e2b3..c30580cbf4 100644 --- a/src/decode-ipv6.h +++ b/src/decode-ipv6.h @@ -109,14 +109,7 @@ typedef struct IPV6Vars_ (p)->ip6h = NULL; \ (p)->ip6vars.ip_opts_len = 0; \ (p)->ip6vars.l4proto = 0; \ - (p)->ip6eh.ip6fh = NULL; \ - (p)->ip6eh.fh_offset = 0; \ - (p)->ip6eh.ip6rh = NULL; \ - (p)->ip6eh.ip6eh = NULL; \ - (p)->ip6eh.ip6dh1 = NULL; \ - (p)->ip6eh.ip6dh2 = NULL; \ - (p)->ip6eh.ip6hh = NULL; \ - (p)->ip6eh.ip6_exthdrs_cnt = 0; \ + memset(&(p)->ip6eh, 0x00, sizeof((p)->ip6eh)); \ } while (0) /* Fragment header */ @@ -128,17 +121,10 @@ typedef struct IPV6FragHdr_ uint32_t ip6fh_ident; /* identification */ } __attribute__((__packed__)) IPV6FragHdr; -#define IPV6_EXTHDR_GET_RAW_FH_NH(p) ((p)->ip6eh.ip6fh->ip6fh_nxt) -#define IPV6_EXTHDR_GET_RAW_FH_HDRLEN(p) sizeof(IPV6FragHdr) -#define IPV6_EXTHDR_GET_RAW_FH_OFFSET(p) (ntohs((p)->ip6eh.ip6fh->ip6fh_offlg) & 0xFFF8) -#define IPV6_EXTHDR_GET_RAW_FH_FLAG(p) (ntohs((p)->ip6eh.ip6fh->ip6fh_offlg) & 0x0001) -#define IPV6_EXTHDR_GET_RAW_FH_ID(p) (ntohl((p)->ip6eh.ip6fh->ip6fh_ident)) - -#define IPV6_EXTHDR_GET_FH_NH(p) IPV6_EXTHDR_GET_RAW_FH_NH((p)) -#define IPV6_EXTHDR_GET_FH_HDRLEN(p) IPV6_EXTHDR_GET_RAW_FH_HDRLEN((p)) -#define IPV6_EXTHDR_GET_FH_OFFSET(p) IPV6_EXTHDR_GET_RAW_FH_OFFSET((p)) -#define IPV6_EXTHDR_GET_FH_FLAG(p) IPV6_EXTHDR_GET_RAW_FH_FLAG((p)) -#define IPV6_EXTHDR_GET_FH_ID(p) IPV6_EXTHDR_GET_RAW_FH_ID((p)) +#define IPV6_EXTHDR_GET_FH_NH(p) (p)->ip6eh.fh_nh +#define IPV6_EXTHDR_GET_FH_OFFSET(p) (p)->ip6eh.fh_offset +#define IPV6_EXTHDR_GET_FH_FLAG(p) (p)->ip6eh.fh_more_frags_set +#define IPV6_EXTHDR_GET_FH_ID(p) (p)->ip6eh.fh_id /* rfc 1826 */ typedef struct IPV6AuthHdr_ @@ -164,24 +150,8 @@ typedef struct IPV6RouteHdr_ including first 8 bytes. */ uint8_t ip6rh_type; /* routing type */ uint8_t ip6rh_segsleft; /* segments left */ -#if 0 - struct in6_addr ip6rh0_addr[23]; /* type 0 addresses */ - uint8_t ip6rh0_num_addrs; /* number of actual addresses in the - array/packet. The array is guarranteed - to be filled up to this number. */ -#endif } __attribute__((__packed__)) IPV6RouteHdr; -#define IPV6_EXTHDR_GET_RAW_RH_NH(p) ((p)->ip6eh.ip6rh->ip6rh_nxt) -#define IPV6_EXTHDR_GET_RAW_RH_HDRLEN(p) ((p)->ip6eh.ip6rh->ip6rh_len) -#define IPV6_EXTHDR_GET_RAW_RH_TYPE(p) (ntohs((p)->ip6eh.ip6rh->ip6rh_type)) -/* XXX */ - -#define IPV6_EXTHDR_GET_RH_NH(p) IPV6_EXTHDR_GET_RAW_RH_NH((p)) -#define IPV6_EXTHDR_GET_RH_HDRLEN(p) IPV6_EXTHDR_GET_RAW_RH_HDRLEN((p)) -#define IPV6_EXTHDR_GET_RH_TYPE(p) IPV6_EXTHDR_GET_RAW_RH_TYPE((p)) -/* XXX */ - /* Hop-by-Hop header and Destination Options header use options that are * defined here. */ @@ -223,14 +193,6 @@ typedef struct IPV6HopOptsHdr_ including first 8 bytes. */ } __attribute__((__packed__)) IPV6HopOptsHdr; -#define IPV6_EXTHDR_GET_RAW_HH_NH(p) ((p)->ip6eh.ip6hh->ip6hh_nxt) -#define IPV6_EXTHDR_GET_RAW_HH_HDRLEN(p) ((p)->ip6eh.ip6hh->ip6hh_len) -/* XXX */ - -#define IPV6_EXTHDR_GET_HH_NH(p) IPV6_EXTHDR_GET_RAW_HH_NH((p)) -#define IPV6_EXTHDR_GET_HH_HDRLEN(p) IPV6_EXTHDR_GET_RAW_HH_HDRLEN((p)) -/* XXX */ - typedef struct IPV6DstOptsHdr_ { uint8_t ip6dh_nxt; /* next header */ @@ -238,22 +200,6 @@ typedef struct IPV6DstOptsHdr_ including first 8 bytes. */ } __attribute__((__packed__)) IPV6DstOptsHdr; -#define IPV6_EXTHDR_GET_RAW_DH1_NH(p) ((p)->ip6eh.ip6dh1->ip6dh_nxt) -#define IPV6_EXTHDR_GET_RAW_DH1_HDRLEN(p) ((p)->ip6eh.ip6dh1->ip6dh_len) -/* XXX */ - -#define IPV6_EXTHDR_GET_DH1_NH(p) IPV6_EXTHDR_GET_RAW_DH1_NH((p)) -#define IPV6_EXTHDR_GET_DH1_HDRLEN(p) IPV6_EXTHDR_GET_RAW_DH1_HDRLEN((p)) -/* XXX */ - -#define IPV6_EXTHDR_GET_RAW_DH2_NH(p) ((p)->ip6eh.ip6dh2->ip6dh_nxt) -#define IPV6_EXTHDR_GET_RAW_DH2_HDRLEN(p) ((p)->ip6eh.ip6dh2->ip6dh_len) -/* XXX */ - -#define IPV6_EXTHDR_GET_DH2_NH(p) IPV6_EXTHDR_GET_RAW_DH2_NH((p)) -#define IPV6_EXTHDR_GET_DH2_HDRLEN(p) IPV6_EXTHDR_GET_RAW_DH2_HDRLEN((p)) -/* XXX */ - typedef struct IPV6GenOptHdr_ { uint8_t type; @@ -264,69 +210,32 @@ typedef struct IPV6GenOptHdr_ typedef struct IPV6ExtHdrs_ { - const IPV6FragHdr *ip6fh; + _Bool rh_set; + uint8_t rh_type; + + _Bool fh_set; + _Bool fh_more_frags_set; + uint8_t fh_nh; + + uint8_t fh_prev_nh; + uint16_t fh_prev_hdr_offset; + + uint16_t fh_header_offset; + uint16_t fh_data_offset; + uint16_t fh_data_len; + /* In fh_offset we store the offset of this extension into the packet past * the ipv6 header. We use it in defrag for creating a defragmented packet * without the frag header */ - uint16_t fh_offset; - - const IPV6RouteHdr *ip6rh; - const IPV6AuthHdr *ip6ah; - const IPV6EspHdr *ip6eh; - const IPV6DstOptsHdr *ip6dh1; - const IPV6DstOptsHdr *ip6dh2; - const IPV6HopOptsHdr *ip6hh; - - /* Hop-By-Hop options */ - IPV6OptHAO ip6hh_opt_hao; - IPV6OptRA ip6hh_opt_ra; - IPV6OptJumbo ip6hh_opt_jumbo; - /* Dest Options 1 */ - IPV6OptHAO ip6dh1_opt_hao; - IPV6OptRA ip6dh1_opt_ra; - IPV6OptJumbo ip6dh1_opt_jumbo; - /* Dest Options 2 */ - IPV6OptHAO ip6dh2_opt_hao; - IPV6OptRA ip6dh2_opt_ra; - IPV6OptJumbo ip6dh2_opt_jumbo; - - IPV6GenOptHdr ip6_exthdrs[IPV6_MAX_OPT]; - uint8_t ip6_exthdrs_cnt; + uint16_t fh_offset; + uint32_t fh_id; } IPV6ExtHdrs; -#define IPV6_EXTHDR_FH(p) (p)->ip6eh.ip6fh -#define IPV6_EXTHDR_RH(p) (p)->ip6eh.ip6rh -#define IPV6_EXTHDR_AH(p) (p)->ip6eh.ip6ah -#define IPV6_EXTHDR_EH(p) (p)->ip6eh.ip6eh -#define IPV6_EXTHDR_DH1(p) (p)->ip6eh.ip6dh1 -#define IPV6_EXTHDR_DH2(p) (p)->ip6eh.ip6dh2 -#define IPV6_EXTHDR_HH(p) (p)->ip6eh.ip6hh - -#define IPV6_EXTHDR_HH_HAO(p) (p)->ip6eh.ip6hh_opt_hao -#define IPV6_EXTHDR_DH1_HAO(p) (p)->ip6eh.ip6dh1_opt_hao -#define IPV6_EXTHDR_DH2_HAO(p) (p)->ip6eh.ip6dh2_opt_hao -#define IPV6_EXTHDR_HH_RA(p) (p)->ip6eh.ip6hh_opt_ra -#define IPV6_EXTHDR_DH1_RA(p) (p)->ip6eh.ip6dh1_opt_ra -#define IPV6_EXTHDR_DH2_RA(p) (p)->ip6eh.ip6dh2_opt_ra -#define IPV6_EXTHDR_HH_JUMBO(p) (p)->ip6eh.ip6hh_opt_jumbo -#define IPV6_EXTHDR_DH1_JUMBO(p) (p)->ip6eh.ip6dh1_opt_jumbo -#define IPV6_EXTHDR_DH2_JUMBO(p) (p)->ip6eh.ip6dh2_opt_jumbo - -#define IPV6_EXTHDR_SET_FH(p,pkt) IPV6_EXTHDR_FH((p)) = (IPV6FragHdr *)pkt -#define IPV6_EXTHDR_ISSET_FH(p) (IPV6_EXTHDR_FH((p)) != NULL) -#define IPV6_EXTHDR_SET_RH(p,pkt) IPV6_EXTHDR_RH((p)) = (IPV6RouteHdr *)pkt -#define IPV6_EXTHDR_ISSET_RH(p) (IPV6_EXTHDR_RH((p)) != NULL) -#define IPV6_EXTHDR_SET_AH(p,pkt) IPV6_EXTHDR_AH((p)) = (IPV6AuthHdr *)pkt -#define IPV6_EXTHDR_ISSET_AH(p) (IPV6_EXTHDR_AH((p)) != NULL) -#define IPV6_EXTHDR_SET_EH(p,pkt) IPV6_EXTHDR_EH((p)) = (IPV6EspHdr *)pkt -#define IPV6_EXTHDR_ISSET_EH(p) (IPV6_EXTHDR_EH((p)) != NULL) -#define IPV6_EXTHDR_SET_DH1(p,pkt) IPV6_EXTHDR_DH1((p)) = (IPV6DstOptsHdr *)pkt -#define IPV6_EXTHDR_ISSET_DH1(p) (IPV6_EXTHDR_DH1((p)) != NULL) -#define IPV6_EXTHDR_SET_DH2(p,pkt) IPV6_EXTHDR_DH2((p)) = (IPV6DstOptsHdr *)pkt -#define IPV6_EXTHDR_ISSET_DH2(p) (IPV6_EXTHDR_DH2((p)) != NULL) -#define IPV6_EXTHDR_SET_HH(p,pkt) IPV6_EXTHDR_HH((p)) = (IPV6HopOptsHdr *)pkt -#define IPV6_EXTHDR_ISSET_HH(p) (IPV6_EXTHDR_HH((p)) != NULL) +#define IPV6_EXTHDR_SET_FH(p) (p)->ip6eh.fh_set = TRUE +#define IPV6_EXTHDR_ISSET_FH(p) (p)->ip6eh.fh_set +#define IPV6_EXTHDR_SET_RH(p) (p)->ip6eh.rh_set = TRUE +#define IPV6_EXTHDR_ISSET_RH(p) (p)->ip6eh.rh_set void DecodeIPV6RegisterTests(void); diff --git a/src/defrag.c b/src/defrag.c index 6ed46fe872..488f9113ea 100644 --- a/src/defrag.c +++ b/src/defrag.c @@ -559,26 +559,27 @@ DefragInsertFrag(ThreadVars *tv, DecodeThreadVars *dtv, DefragTracker *tracker, else if (tracker->af == AF_INET6) { more_frags = IPV6_EXTHDR_GET_FH_FLAG(p); frag_offset = IPV6_EXTHDR_GET_FH_OFFSET(p); - data_offset = (uint8_t *)p->ip6eh.ip6fh + sizeof(IPV6FragHdr) - GET_PKT_DATA(p); - data_len = IPV6_GET_PLEN(p) - ( - ((uint8_t *)p->ip6eh.ip6fh + sizeof(IPV6FragHdr)) - - ((uint8_t *)p->ip6h + sizeof(IPV6Hdr))); + data_offset = p->ip6eh.fh_data_offset; + data_len = p->ip6eh.fh_data_len; frag_end = frag_offset + data_len; ip_hdr_offset = (uint8_t *)p->ip6h - GET_PKT_DATA(p); - frag_hdr_offset = (uint8_t *)p->ip6eh.ip6fh - GET_PKT_DATA(p); + frag_hdr_offset = p->ip6eh.fh_header_offset; + + SCLogDebug("mf %s frag_offset %u data_offset %u, data_len %u, " + "frag_end %u, ip_hdr_offset %u, frag_hdr_offset %u", + more_frags ? "true" : "false", frag_offset, data_offset, + data_len, frag_end, ip_hdr_offset, frag_hdr_offset); /* handle unfragmentable exthdrs */ if (ip_hdr_offset + IPV6_HEADER_LEN < frag_hdr_offset) { - SCLogDebug("we have exthdrs before fraghdr %u bytes (%u hdrs total)", - (uint32_t)(frag_hdr_offset - (ip_hdr_offset + IPV6_HEADER_LEN)), - p->ip6eh.ip6_exthdrs_cnt); + SCLogDebug("we have exthdrs before fraghdr %u bytes", + (uint32_t)(frag_hdr_offset - (ip_hdr_offset + IPV6_HEADER_LEN))); /* get the offset of the 'next' field in exthdr before the FH, * relative to the buffer start */ - int t_offset = (int)((p->ip6eh.ip6_exthdrs[p->ip6eh.ip6_exthdrs_cnt - 2].data - 2) - GET_PKT_DATA(p)); /* store offset and FH 'next' value for updating frag buffer below */ - ip6_nh_set_offset = (int)t_offset; + ip6_nh_set_offset = p->ip6eh.fh_prev_hdr_offset; ip6_nh_set_value = IPV6_EXTHDR_GET_FH_NH(p); SCLogDebug("offset %d, value %u", ip6_nh_set_offset, ip6_nh_set_value); } @@ -1109,7 +1110,6 @@ IPV6BuildTestPacket(uint32_t id, uint16_t off, int mf, const char content, fh->ip6fh_nxt = IPPROTO_ICMP; fh->ip6fh_ident = htonl(id); fh->ip6fh_offlg = htons((off << 3) | mf); - p->ip6eh.ip6fh = fh; pcontent = SCCalloc(1, content_len); if (unlikely(pcontent == NULL)) diff --git a/src/detect-fragoffset.c b/src/detect-fragoffset.c index 28d66e9bf8..28d467b670 100644 --- a/src/detect-fragoffset.c +++ b/src/detect-fragoffset.c @@ -87,7 +87,7 @@ int DetectFragOffsetMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet if (PKT_IS_IPV4(p)) { frag = IPV4_GET_IPOFFSET(p); } else if (PKT_IS_IPV6(p)) { - if(IPV6_EXTHDR_FH(p)) { + if (IPV6_EXTHDR_ISSET_FH(p)) { frag = IPV6_EXTHDR_GET_FH_OFFSET(p); } else { return 0;