[Oisf-devel] [PATCH 1/2] Modify Packet structure and prepare accessor.

Eric Leblond eleblond at edenwall.com
Mon Nov 15 23:35:45 UTC 2010


This patch modifies decode.c and decode.h to avoid the usage
by default of a bigger than 65535 bytes array in Packet structure.
The idea is that the packet are mainly under 1500 bytes size and
a bigger size must be supported but should not be the default.

If the packet length is bigger than DFLT_PAYLOAD_SIZE then the
data are stored in a dynamically allocated part of the memory.

To ease the modification of the rest of the code, functions to
access and set the payload/length in a Packet have been introduced.

Signed-off-by: Eric Leblond <eleblond at edenwall.com>
---
 src/decode.c          |   86 +++++++++++++++++++++++++++++++++++++++++++++++-
 src/decode.h          |   19 ++++++++++-
 src/tmqh-packetpool.c |   11 ++++++
 3 files changed, 112 insertions(+), 4 deletions(-)

diff --git a/src/decode.c b/src/decode.c
index d9e02a2..bb7a125 100644
--- a/src/decode.c
+++ b/src/decode.c
@@ -27,6 +27,7 @@
 #include "suricata.h"
 #include "decode.h"
 #include "util-debug.h"
+#include "util-mem.h"
 #include "app-layer-detect-proto.h"
 #include "tm-modules.h"
 #include "util-error.h"
@@ -107,8 +108,8 @@ Packet *PacketPseudoPktSetup(Packet *parent, uint8_t *pkt, uint16_t len, uint8_t
 
     /* copy packet and set lenght, proto */
     p->tunnel_proto = proto;
-    p->pktlen = len;
-    memcpy(&p->pkt, pkt, len);
+    SET_PKT_LEN(p, len);
+    CopyDataToPacket(p, pkt, len);
     p->recursion_level = parent->recursion_level + 1;
     p->ts.tv_sec = parent->ts.tv_sec;
     p->ts.tv_usec = parent->ts.tv_usec;
@@ -243,3 +244,84 @@ DecodeThreadVars *DecodeThreadVarsAlloc() {
 
     return dtv;
 }
+
+inline int CopyDataToPacket(Packet *p, uint8_t *pktdata, int pktlen)
+{
+    if (pktlen > MAX_PAYLOAD_SIZE) {
+        /* too big */
+        return -1;
+    }
+    if (! p->ext_pkt) {
+        if (pktlen < DFLT_PAYLOAD_SIZE) {
+            memcpy(&p->pkt, pktdata, pktlen);
+            SET_PKT_LEN(p, (size_t)pktlen);
+        } else {
+            /* here we need a dynamic allocation */
+            p->ext_pkt = SCMalloc(MAX_PAYLOAD_SIZE);
+            memcpy(p->ext_pkt, pktdata, pktlen);
+            SET_PKT_LEN(p, (size_t)pktlen);
+        }
+    } else {
+            memcpy(p->ext_pkt, pktdata, pktlen);
+            SET_PKT_LEN(p, (size_t)pktlen);
+    }
+    return 0;
+}
+
+inline int CopyDataToPacketOffset(Packet *p, int offset, uint8_t *data, int datalen)
+{
+    if (offset + datalen > MAX_PAYLOAD_SIZE) {
+            /* too big */
+            return -1;
+    }
+
+    if (! p->ext_pkt) {
+        if (offset + datalen < DFLT_PAYLOAD_SIZE) {
+            memcpy(&p->pkt + offset, data, datalen);
+        } else {
+            /* here we need a dynamic allocation. This case should rarely
+             * occur as there is a high probability the first frag has
+             * reveal the packet size*/
+            p->ext_pkt = SCMalloc(MAX_PAYLOAD_SIZE);
+            /* copy initial data */
+            memcpy(p->ext_pkt, &p->pkt, p->pktlen);
+            /* copy data as asked */
+            memcpy(p->ext_pkt + offset, data, datalen);
+            /* modify part of the struct ipv4 that were pointing to pkt array
+             * using the fact that offset is the same*/
+            if (p->ethh) {
+                p->ethh = (EthernetHdr *)((uint8_t *)p->ext_pkt + ((uint8_t *)p->ethh - p->pkt));
+            }
+            if (p->ip4h) {
+                p->ip4h = (IPV4Hdr *)((uint8_t *)p->ext_pkt + ((uint8_t *)p->ip4h - p->pkt));
+            }
+            if (p->ip6h) {
+                p->ip6h = (IPV6Hdr *)((uint8_t *)p->ext_pkt + ((uint8_t *)p->ip6h - p->pkt));
+            }
+            if (p->tcph) {
+                p->tcph = (TCPHdr *)((uint8_t *)p->ext_pkt + ((uint8_t *)p->tcph - p->pkt));
+            }
+            if (p->udph) {
+                p->udph = (UDPHdr *)((uint8_t *)p->ext_pkt + ((uint8_t *)p->udph - p->pkt));
+            }
+            if (p->icmpv4h) {
+                p->icmpv4h = (ICMPV4Hdr *)((uint8_t *)p->ext_pkt + ((uint8_t *)p->icmpv4h - p->pkt));
+            }
+            if (p->icmpv6h) {
+                p->icmpv6h = (ICMPV6Hdr *)((uint8_t *)p->ext_pkt + ((uint8_t *)p->icmpv6h - p->pkt));
+            }
+            if (p->ppph) {
+                p->ppph = (PPPHdr *)((uint8_t *)p->ext_pkt + ((uint8_t *)p->ppph - p->pkt));
+            }
+            if (p->greh) {
+                p->greh = (GREHdr *)((uint8_t *)p->ext_pkt + ((uint8_t *)p->greh - p->pkt));
+            }
+            if (p->vlanh) {
+                p->vlanh = (VLANHdr *)((uint8_t *)p->ext_pkt + ((uint8_t *)p->vlanh - p->pkt));
+            }
+        }
+    } else {
+        memcpy(p->ext_pkt + offset, data, datalen);
+    }
+    return 0;
+}
diff --git a/src/decode.h b/src/decode.h
index b911ed5..66fb319 100644
--- a/src/decode.h
+++ b/src/decode.h
@@ -57,6 +57,10 @@
 
 #include "detect-reference.h"
 
+#define DFLT_PAYLOAD_SIZE 1500
+/* storage: maximum ip packet size + link header */
+#define MAX_PAYLOAD_SIZE IPV6_HEADER_LEN + 65536 + 28
+
 #ifdef __SC_CUDA_SUPPORT__
 #define CUDA_MAX_PAYLOAD_SIZE 1500
 #endif
@@ -163,6 +167,14 @@ typedef struct Address_ {
 #define GET_TCP_SRC_PORT(p)  ((p)->sp)
 #define GET_TCP_DST_PORT(p)  ((p)->dp)
 
+#define GET_PKT_LEN(p) ((p)->pktlen)
+#define GET_PKT_DATA(p) ((((p)->ext_pkt) == NULL ) ? (p)->pkt : (p)->ext_pkt)
+
+#define SET_PKT_LEN(p, len) do { \
+    (p)->pktlen = len;		 \
+    } while (0)
+
+
 /* Port is just a uint16_t */
 typedef uint16_t Port;
 #define SET_PORT(v, p) ((p) = (v))
@@ -347,8 +359,9 @@ typedef struct Packet_
     uint8_t *payload;
     uint16_t payload_len;
 
-    /* storage: maximum ip packet size + link header */
-    uint8_t pkt[IPV6_HEADER_LEN + 65536 + 28];
+    /* storage: set to DFLT_PAYLOAD_SIZE and extended via allocation if necessary */
+    uint8_t pkt[DFLT_PAYLOAD_SIZE];
+    uint8_t *ext_pkt;
     uint32_t pktlen;
 
     PacketAlerts alerts;
@@ -634,6 +647,8 @@ typedef struct DecodeThreadVars_
 void DecodeRegisterPerfCounters(DecodeThreadVars *, ThreadVars *);
 Packet *PacketPseudoPktSetup(Packet *parent, uint8_t *pkt, uint16_t len, uint8_t proto);
 Packet *PacketGetFromQueueOrAlloc(void);
+int CopyDataToPacket(Packet *p, uint8_t *pktdata, int pktlen);
+int CopyDataToPacketOffset(Packet *p, int offset, uint8_t *data, int datalen);
 
 DecodeThreadVars *DecodeThreadVarsAlloc();
 
diff --git a/src/tmqh-packetpool.c b/src/tmqh-packetpool.c
index 1cc028b..adc9310 100644
--- a/src/tmqh-packetpool.c
+++ b/src/tmqh-packetpool.c
@@ -186,6 +186,11 @@ void TmqhOutputPacketpool(ThreadVars *t, Packet *p)
     /* we're done with the tunnel root now as well */
     if (proot == 1) {
         SCLogDebug("getting rid of root pkt... alloc'd %s", p->root->flags & PKT_ALLOC ? "true" : "false");
+        /* if p->root uses extended data, free them */
+        if (p->root->ext_pkt) {
+            SCFree(p->root->ext_pkt);
+            p->root->ext_pkt = NULL;
+        }
         if (p->root->flags & PKT_ALLOC) {
             PACKET_CLEANUP(p->root);
             SCFree(p->root);
@@ -196,6 +201,12 @@ void TmqhOutputPacketpool(ThreadVars *t, Packet *p)
         }
     }
 
+    /* if p uses extended data, free them */
+    if (p->ext_pkt) {
+        SCFree(p->ext_pkt);
+        p->ext_pkt = NULL;
+    }
+
     SCLogDebug("getting rid of tunnel pkt... alloc'd %s (root %p)", p->flags & PKT_ALLOC ? "true" : "false", p->root);
     if (p->flags & PKT_ALLOC) {
         PACKET_CLEANUP(p);
-- 
1.7.1




More information about the Oisf-devel mailing list