]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
ipv6: simplify ext hdr parsing and storage
authorVictor Julien <victor@inliniac.net>
Sun, 15 May 2016 11:35:10 +0000 (13:35 +0200)
committerVictor Julien <victor@inliniac.net>
Wed, 18 May 2016 15:38:20 +0000 (17:38 +0200)
This reduces size of the IPV6ExtHdr structure part of every packet
significantly.

Clean up macro's in the ipv6 header.

src/decode-ipv6.c
src/decode-ipv6.h
src/defrag.c
src/detect-fragoffset.c

index e63624219957162be7d48cddfc5140a1f8d704c8..c13b8806c9934ca531687d223d66cc350404cba4 100644 (file)
@@ -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_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_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_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 = 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 */
index da58d9e2b384be8fe981e2e211321d1debc0afd9..c30580cbf4b1a349c3f39c9f7efd9252d27735a6 100644 (file)
@@ -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);
 
index 6ed46fe8728877cc1b12cd79670fbbc53aeadf67..488f9113ea930ec0cdeaa1a87e99a68ad7a52e65 100644 (file)
@@ -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))
index 28d66e9bf848ccf5581a6343928d9a8dea5d869a..28d467b670441f24832e7fcc54877596e4c7cbf6 100644 (file)
@@ -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;