]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #627 in SNORT/snort3 from ~MIALTIZE/snort3:expected_flows to master
authorMichael Altizer (mialtize) <mialtize@cisco.com>
Fri, 30 Sep 2016 16:14:22 +0000 (12:14 -0400)
committerMichael Altizer (mialtize) <mialtize@cisco.com>
Fri, 30 Sep 2016 16:14:22 +0000 (12:14 -0400)
Squashed commit of the following:

commit 91133a83eca85bc05e403bce6973af2099e5159e
Author: Michael Altizer <mialtize@cisco.com>
Date:   Mon Sep 26 16:36:45 2016 -0400

    file_mempool: Fix initializing total pool size

commit 61ae01ad22a6a4f4093c749304023b5a25045633
Author: Michael Altizer <mialtize@cisco.com>
Date:   Mon Sep 26 13:40:23 2016 -0400

    expected: Push expected flow information through the DAQ module

commit 08aa5f9a79a724a61274854fcc37f05a0fc3d1da
Author: Michael Altizer <mialtize@cisco.com>
Date:   Mon Sep 26 12:22:04 2016 -0400

    sfdaq: Add SFDAQInstance::add_expected() call

commit 218769cb579189f0600b53c7c6abde063d34627f
Author: Michael Altizer <mialtize@cisco.com>
Date:   Mon Sep 26 13:34:57 2016 -0400

    expected: Expected cache revamp and related bugfixes

    - Change expected cache to use FlowKeys instead of ExpectKeys
    - Support expected flows where the full N-tuple is known
    - Fix SIP (ignored) expected flow creation logic
    - Fix AppID expected flow creation regarding IP proto/PktType
    - Add FTP data channel expected flow with type TCP rather than PDU
    - Many expected cache bugfixes

commit 686ff5e39c79b81472c794a18548e77146638348
Author: Michael Altizer <mialtize@cisco.com>
Date:   Mon Sep 26 12:34:51 2016 -0400

    ftp_data: Add expected data consumption to set service name and fix bugs

    - Set the parent flow key type from the flow rather than the packet when
    creating FTP-DATA flow data.
    - Correctly retrieve FTP-DATA flow data instead of FTP flow data when
    inspecting with FTP-DATA.

commit 2931ce2677e0a4c20454430f361d92f65c99a2f5
Author: Michael Altizer <mialtize@cisco.com>
Date:   Mon Sep 26 12:31:31 2016 -0400

    stream: Fix NPD in get_flow_data() when flow doesn't exist

commit b06e59efa081db48229bc098f89f1b906b993fd4
Author: Michael Altizer <mialtize@cisco.com>
Date:   Mon Sep 26 12:27:15 2016 -0400

    flow_key: Add address/port reversal reporting to init()

commit 994b52c89ffedd64ee69395707227589c913be1b
Author: Michael Altizer <mialtize@cisco.com>
Date:   Mon Sep 26 12:25:08 2016 -0400

    zhash: Add new node insertion reporting to get()

commit 60af08a53b8711d72aebbd8fc14690bbc493ddc5
Author: Michael Altizer <mialtize@cisco.com>
Date:   Mon Sep 26 12:23:34 2016 -0400

    ftp: Fix marking file get commands

commit 90aaa06a5f47b28e8c4d48c522944c0204c6ac9e
Author: Michael Altizer <mialtize@cisco.com>
Date:   Mon Sep 26 12:19:33 2016 -0400

    build: Remove lingering LibDAQ #ifdefs

commit 9c6f5d9e74d0a7a7deeb5dd702298c43b05ae2fd
Author: Michael Altizer <mialtize@cisco.com>
Date:   Mon Sep 26 12:16:48 2016 -0400

    defaults: Update FTP default config based on Snort2's hardcoded one

21 files changed:
lua/snort_defaults.lua
src/file_api/file_mempool.cc
src/flow/expect_cache.cc
src/flow/expect_cache.h
src/flow/flow_control.cc
src/flow/flow_control.h
src/flow/flow_key.cc
src/flow/flow_key.h
src/hash/zhash.cc
src/hash/zhash.h
src/network_inspectors/appid/appid_session.cc
src/packet_io/sfdaq.cc
src/packet_io/sfdaq.h
src/service_inspectors/ftp_telnet/ftp.cc
src/service_inspectors/ftp_telnet/ftp_data.cc
src/service_inspectors/ftp_telnet/ftpp_si.h
src/service_inspectors/ftp_telnet/pp_ftp.cc
src/service_inspectors/sip/sip_dialog.cc
src/stream/stream.cc
src/stream/stream.h
src/stream/tcp/tcp_session.cc

index bd8c6557b9cabac584f98dabbcd1d641fd48dac1..bc98c0fd6682d83bed1ca521bfe78d7272ea2508 100644 (file)
@@ -128,6 +128,36 @@ ftp_default_commands =
     XSEM XSEN XSHA1 XSHA256
 ]]
 
+ftp_default_data_chan_cmds = 
+[[
+    PORT PASV LPRT LPSV EPRT EPSV
+]]
+
+ftp_default_data_xfer_cmds =
+[[
+    RETR STOR STOU APPE LIST NLST
+]]
+
+ftp_default_file_put_cmds = 
+[[
+    STOR STOU
+]]
+
+ftp_default_file_get_cmds = 
+[[
+    RETR
+]]
+
+ftp_default_login_cmds = 
+[[
+    USER PASS
+]]
+
+ftp_default_encr_cmds = 
+[[
+    AUTH
+]]
+
 ftp_format_commands = 
 [[ 
     ACCT ADAT ALLO APPE AUTH CEL CLNT CMD CONF CWD DELE ENC EPRT EPSV ESTP
@@ -193,6 +223,12 @@ default_ftp_server =
     ignore_data_chan = true,
 
     ftp_cmds = ftp_default_commands,
+    data_chan_cmds = ftp_default_data_chan_cmds,
+    data_xfer_cmds = ftp_default_data_xfer_cmds,
+    file_put_cmds = ftp_default_file_put_cmds,
+    file_get_cmds = ftp_default_file_get_cmds,
+    login_cmds = ftp_default_login_cmds,
+    encr_cmds = ftp_default_encr_cmds,
     chk_str_fmt = ftp_format_commands,
     cmd_validity = ftp_command_specs
 }
index e855d99414a615fa0585dc52b4cac269410cf343..5fa52a43044a0e674bf2b48f47ef8e9438eeedee 100644 (file)
@@ -120,6 +120,7 @@ FileMemPool::FileMemPool(uint64_t num_objects, size_t o_size)
         return;
     }
 
+    total = 0;
     for (i=0; i<num_objects; i++)
     {
         void* data = ((char*)datapool) + (i * obj_size);
index af59cc876d2d28366b76110d004e1950cd9992cb..30cd584b034f0e91236f850c56509f20d7dea948 100644 (file)
 
 #include <assert.h>
 
-#include "time/packet_time.h"
 #include "hash/zhash.h"
+#include "packet_io/sfdaq.h"
 #include "protocols/packet.h"
-#include "stream/stream.h"
+#include "protocols/vlan.h"
 #include "sfip/sf_ip.h"
+#include "stream/stream.h"      // FIXIT-M bad dependency
+#include "time/packet_time.h"
 
 /* Reasonably small, and prime */
 // FIXIT-L size based on max_tcp + max_udp?
@@ -51,7 +53,7 @@ ExpectFlow::~ExpectFlow()
 
 void ExpectFlow::clear()
 {
-    while ( data )
+    while (data)
     {
         FlowData* fd = data;
         data = data->next;
@@ -63,7 +65,7 @@ void ExpectFlow::clear()
 struct ExpectNode
 {
     time_t expires = 0;
-    int reversed_key = 0;
+    bool reversed_key = false;
     int direction = 0;
     unsigned count = 0;
     int16_t appId = 0;
@@ -76,7 +78,7 @@ struct ExpectNode
 
 void ExpectNode::clear(ExpectFlow*& list)
 {
-    while ( head )
+    while (head)
     {
         ExpectFlow* p = head;
         head = head->next;
@@ -88,48 +90,6 @@ void ExpectNode::clear(ExpectFlow*& list)
     count = 0;
 }
 
-struct ExpectKey
-{
-    sfip_t ip1;
-    sfip_t ip2;
-    uint16_t port1;
-    uint16_t port2;
-    PktType protocol;
-
-    bool set(
-        const sfip_t *cliIP, uint16_t cliPort,
-        const sfip_t *srvIP, uint16_t srvPort,
-        PktType proto);
-};
-
-inline bool ExpectKey::set(
-    const sfip_t *cliIP, uint16_t cliPort,
-    const sfip_t *srvIP, uint16_t srvPort,
-    PktType proto )
-{
-    bool reverse;
-    SFIP_RET rval = sfip_compare(cliIP, srvIP);
-
-    if (rval == SFIP_LESSER || (rval == SFIP_EQUAL && cliPort < srvPort))
-    {
-        sfip_copy(ip1, cliIP);
-        port1 = cliPort;
-        sfip_copy(ip2, srvIP);
-        port2 = srvPort;
-        reverse = false;
-    }
-    else
-    {
-        sfip_copy(ip1, srvIP);
-        port1 = srvPort;
-        sfip_copy(ip2, cliIP);
-        port2 = cliPort;
-        reverse = true;
-    }
-    protocol = proto;
-    return reverse;
-}
-
 //-------------------------------------------------------------------------
 // private ExpectCache methods
 //-------------------------------------------------------------------------
@@ -151,141 +111,154 @@ void ExpectCache::prune()
     }
 }
 
-inline ExpectNode* ExpectCache::get_node(ExpectKey& key, bool& init)
+ExpectNode* ExpectCache::find_node_by_packet(Packet* p, FlowKey &key)
 {
-    ExpectNode* node;
-
-    if ( !free_list )
-        node = nullptr;
-    else
-        node = (ExpectNode*)hash_table->get(&key);
+    if (!hash_table->get_count())
+        return nullptr;
 
-    if ( node )
-        init = false;
+    const sfip_t* srcIP = p->ptrs.ip_api.get_src();
+    const sfip_t* dstIP = p->ptrs.ip_api.get_dst();
+    uint16_t vlanId = (p->proto_bits & PROTO_BIT__VLAN) ? layer::get_vlan_layer(p)->vid() : 0;
+    uint32_t mplsId = (p->proto_bits & PROTO_BIT__MPLS) ? p->ptrs.mplsHdr.label : 0;
+    uint16_t addressSpaceId = p->pkth->address_space_id;
+    PktType type = p->type();
+    IpProtocol ip_proto = p->get_ip_proto_next();
 
-    else
-    {
-        prune();
+    bool reversed_key = key.init(type, ip_proto, dstIP, p->ptrs.dp, srcIP, p->ptrs.sp,
+            vlanId, mplsId, addressSpaceId);
 
-        node = (ExpectNode*)hash_table->get(&key);
+    uint16_t port1;
+    uint16_t port2;
 
-        if ( !node )
+    /*
+        Lookup order:
+            1. Full match.
+            2. Unknown (zeroed) source port.
+            3. Unknown (zeroed) destination port.
+        If the client/server addresses were reversed during key creation, the
+        source port will be in port_l.
+    */
+    // FIXIT-P X This should be optimized to only do full matches when full keys
+    //      are present, likewise for partial keys.
+    ExpectNode* node = (ExpectNode*) hash_table->find(&key);
+    if (!node)
+    {
+        // FIXIT-M X This logic could fail if IPs were equal because the original key
+        // would always have been created with a 0 for src or dst port and put the
+        // known port in port_h.
+        if (reversed_key)
         {
-            ++overflows;
-            return nullptr;
+            port1 = key.port_l;
+            port2 = 0;
+            key.port_l = 0;
         }
-        else if ( !free_list )
+        else
         {
-            assert(false);
-            ++overflows;
-            return nullptr;
+            port1 = 0;
+            port2 = key.port_h;
+            key.port_h = 0;
+        }
+        node = (ExpectNode*) hash_table->find(&key);
+        if (!node)
+        {
+            key.port_l = port1;
+            key.port_h = port2;
+            node = (ExpectNode*) hash_table->find(&key);
+            if (!node)
+                return nullptr;
         }
     }
-    return node;
-}
-
-inline ExpectFlow* ExpectCache::get_flow(ExpectNode* node, unsigned flow_id, int16_t appId)
-{
-    if ( packet_time() > node->expires )
+    if (!node->head || (p->pkth->ts.tv_sec > node->expires))
     {
-        node->clear(free_list);
-        node->appId = appId;
-        ++prunes;
+        hash_table->remove(&key);
+        return nullptr;
     }
-    else if ( node->appId != appId )
+    /* Make sure the packet direction is correct */
+    switch (node->direction)
     {
-        if ( node->appId && appId )
-            // reject changing known appId
-            return nullptr;
+        case SSN_DIR_BOTH:
+            break;
 
-        // allow changing unknown appId
-        node->appId = appId;
+        case SSN_DIR_FROM_CLIENT:
+        case SSN_DIR_FROM_SERVER:
+            if (node->reversed_key != reversed_key)
+                return nullptr;
+            break;
     }
-    ExpectFlow* last = node->tail;
-
-    if ( !last )
-        return nullptr;
-
-    FlowData* fd = last->data;
-
-    while ( fd )
-    {
-        if ( fd->get_id() == flow_id )
-            return nullptr;
 
-        fd = fd->next;
-    }
-    return last;
+    return node;
 }
 
-inline bool ExpectCache::set_data(ExpectNode* node, ExpectFlow*& last, FlowData* fd)
+bool ExpectCache::process_expected(ExpectNode* node, FlowKey& key, Packet* p, Flow* lws)
 {
-    if ( !last )
-    {
-        if ( node->count >= MAX_LIST )
-        {
-            // fail when maxed out
-            ++overflows;
-            return false;
-        }
-        last = free_list;
-        free_list = free_list->next;
+    ExpectFlow* head;
+    FlowData* fd;
+    int ignoring = false;
 
-        if ( !node->tail )
-            node->head = last;
-        else
-            node->tail->next = last;
+    assert(node->count && node->head);
 
-        node->tail = last;
-        last->next = nullptr;
+    /* Pull the first set of expected flow data off of the Expect node and apply it
+        in its entirety to the target flow.  Discard the set (and potentially the
+        entire node, it empty) after this is done. */
+    node->count--;
+    head = node->head;
+    node->head = head->next;
 
-        node->count++;
-    }
-    if (last->data)
+    while ((fd = head->data))
     {
-        FlowData* prev_fd;
-        for (prev_fd = last->data; prev_fd && prev_fd->next; prev_fd = prev_fd->next);
-        prev_fd->next = fd;
+        head->data = fd->next;
+        lws->set_flow_data(fd);
+        ++realized;
+        fd->handle_expected(p);
     }
-    else
-        last->data = fd;
+    head->next = free_list;
+    free_list = head;
+
+    /* If this is 0, we're ignoring, otherwise setting id of new session */
+    if (!node->appId)
+        ignoring = node->direction ? true : false;
+    else if (lws->ssn_state.application_protocol != node->appId)
+        lws->ssn_state.application_protocol = node->appId;
+
+    if (!node->count)
+        hash_table->remove(&key);
 
-    return true;
+    return ignoring;
 }
 
 //-------------------------------------------------------------------------
 // public ExpectCache methods
 //-------------------------------------------------------------------------
 
-ExpectCache::ExpectCache (uint32_t max)
+ExpectCache::ExpectCache(uint32_t max)
 {
     // -size forces use of abs(size) ie w/o bumping up
-    hash_table = new ZHash(-MAX_HASH, sizeof(ExpectKey));
+    hash_table = new ZHash(-MAX_HASH, sizeof(FlowKey));
+    hash_table->set_keyops(FlowKey::hash, FlowKey::compare);
 
     nodes = new ExpectNode[max];
-
-    for ( unsigned i = 0; i < max; ++i )
+    for (unsigned i = 0; i < max; ++i)
         hash_table->push(nodes+i);
 
+    /* Preallocate a pool of ExpectFlows big enough to handle the worst case
+        requirement (max number of nodes * max flows per node) and add them all
+        to an initial free list. */
     max *= MAX_LIST;
-
     pool = new ExpectFlow[max];
     free_list = nullptr;
-
-    for ( unsigned i = 0; i < max; ++i )
+    for (unsigned i = 0; i < max; ++i)
     {
         ExpectFlow* p = pool + i;
         p->data = nullptr;
         p->next = free_list;
         free_list = p;
     }
-    memset(&zeroed, 0, sizeof(zeroed));
 
     expects = realized = 0;
     prunes = overflows = 0;
 }
 
-ExpectCache::~ExpectCache ()
+ExpectCache::~ExpectCache()
 {
     delete hash_table;
     delete[] nodes;
@@ -309,29 +282,74 @@ ExpectCache::~ExpectCache ()
  * existing appId, new appId and associated data is not stored.
  *
  */
-int ExpectCache::add_flow(
-    const sfip_t *cliIP, uint16_t cliPort,
-    const sfip_t *srvIP, uint16_t srvPort,
-    PktType protocol, char direction,
-    FlowData* fd, int16_t appId)
+int ExpectCache::add_flow(const Packet *ctrlPkt,
+    PktType type, IpProtocol ip_proto,
+    const sfip_t* cliIP, uint16_t cliPort,
+    const sfip_t* srvIP, uint16_t srvPort,
+    char direction, FlowData* fd, int16_t appId)
 {
-    // FIXIT-L sip inspector knows both ports
-    //assert(!cliPort || !srvPort);
+    /* Just pull the VLAN ID, MPLS ID, and Address Space ID from the
+        control packet until we have a use case for not doing so. */
+    uint16_t vlanId = (ctrlPkt->proto_bits & PROTO_BIT__VLAN) ? layer::get_vlan_layer(ctrlPkt)->vid() : 0;
+    uint32_t mplsId = (ctrlPkt->proto_bits & PROTO_BIT__MPLS) ? ctrlPkt->ptrs.mplsHdr.label : 0;
+    uint16_t addressSpaceId = ctrlPkt->pkth->address_space_id;
 
-    ExpectKey hashKey;
-    int reversed_key = hashKey.set(cliIP, cliPort, srvIP, srvPort, protocol);
+    FlowKey key;
+    bool reversed_key = key.init(type, ip_proto, cliIP, cliPort, srvIP, srvPort,
+            vlanId, mplsId, addressSpaceId);
 
-    bool init = true;
-    ExpectNode* node = get_node(hashKey, init);
+    ExpectNode* node;
+    ExpectFlow* last;
+    bool new_node = false;
 
-    if ( !node )
-        return -1;
+    node = (ExpectNode*) hash_table->get(&key, &new_node);
+    if (!node)
+    {
+        prune();
+        node = (ExpectNode*) hash_table->get(&key, &new_node);
+        /* The flow free list should never be empty if there was a node
+            to be (re-)used unless we managed to leak some.  Check just
+            in case.  Maybe assert instead? */
+        if (!node || !free_list)
+        {
+            ++overflows;
+            return -1;
+        }
+    }
 
-    ExpectFlow* last;
+    /* If the node is past its expiration date, whack it and reuse it. */
+    if (!new_node && packet_time() > node->expires)
+    {
+        node->clear(free_list);
+        new_node = true;
+    }
 
-    if ( !init )
-        last = get_flow(node, fd->get_id(), appId);
+    if (!new_node)
+    {
+        /* Requests will be rejected if the AppID doesn't match what has already been set. */
+        if (node->appId != appId)
+        {
+            if (node->appId && appId)
+                return -1;
+            node->appId = appId;
+        }
 
+        last = node->tail;
+        if (last)
+        {
+            FlowData* lfd = last->data;
+
+            while (lfd)
+            {
+                if (lfd->get_id() == fd->get_id())
+                {
+                    last = nullptr;
+                    break;
+                }
+                fd = fd->next;
+            }
+        }
+    }
     else
     {
         node->appId = appId;
@@ -340,126 +358,62 @@ int ExpectCache::add_flow(
         node->head = node->tail = nullptr;
         node->count = 0;
         last = nullptr;
+        /* Only add TCP and UDP expected flows for now via the DAQ module. */
+        if (ip_proto == IpProtocol::TCP || ip_proto == IpProtocol::UDP)
+            SFDAQ::get_local_instance()->add_expected(ctrlPkt, cliIP, cliPort, srvIP, srvPort,
+                    ip_proto, 1000, 0);
     }
-    if ( !set_data(node, last, fd) )
-        return -1;
-
-    node->expires = packet_time() + MAX_WAIT;
-    ++expects;
-
-    return 0;
-}
-
-bool ExpectCache::is_expected(Packet* p)
-{
-    if ( !hash_table->get_count() )
-        return false;
 
-    const sfip_t* srcIP = p->ptrs.ip_api.get_src();
-    const sfip_t* dstIP = p->ptrs.ip_api.get_dst();
-
-    ExpectKey key;
-    bool reversed_key = key.set(dstIP, p->ptrs.dp, srcIP, p->ptrs.sp, p->type());
-
-    uint16_t port1;
-    uint16_t port2;
-
-    if ( reversed_key )
-    {
-        key.port2 = 0;
-        port1 = 0;
-        port2 = p->ptrs.sp;
-    }
-    else
+    if (!last)
     {
-        key.port1 = 0;
-        port1 = p->ptrs.sp;
-        port2 = 0;
-    }
-
-    ExpectNode* node = (ExpectNode*)hash_table->find(&key);
+        if (node->count >= MAX_LIST)
+        {
+            // fail when maxed out
+            ++overflows;
+            return -1;
+        }
+        last = free_list;
+        free_list = free_list->next;
 
-    if ( !node )
-    {
-        // can't find with dp, so try sp ...
-        key.port1 = port1;
-        key.port2 = port2;
+        if (!node->tail)
+            node->head = last;
+        else
+            node->tail->next = last;
 
-        node = (ExpectNode*)hash_table->find(&key);
+        node->tail = last;
+        last->next = nullptr;
 
-        if ( !node )
-            return false;
-    }
-    // FIXIT-M X This should also include a lookup in the table for entries where both
-    // src and dst ports are known.
-    if ( !node->head || (p->pkth->ts.tv_sec > node->expires) )
-    {
-        hash_table->remove();
-        return false;
+        node->count++;
     }
-    /* Make sure the packet direction is correct */
-    switch (node->direction)
+    if (last->data)
     {
-    case SSN_DIR_BOTH:
-        break;
-
-    case SSN_DIR_FROM_CLIENT:
-    case SSN_DIR_FROM_SERVER:
-        if (node->reversed_key != reversed_key)
-            return false;
-        break;
+        FlowData* prev_fd;
+        for (prev_fd = last->data; prev_fd && prev_fd->next; prev_fd = prev_fd->next);
+        prev_fd->next = fd;
     }
+    else
+        last->data = fd;
+
+    node->expires = packet_time() + MAX_WAIT;
+    ++expects;
 
-    return true;
+    return 0;
 }
 
-char ExpectCache::process_expected(Packet* p, Flow* lws)
+bool ExpectCache::is_expected(Packet* p)
 {
-    int retVal = SSN_DIR_NONE;
-
-    ExpectNode* node = (ExpectNode*)hash_table->current();
-
-    if ( !node )
-        return retVal;
-
-    assert(node->count && node->head);
-
-    node->count--;
-    ExpectFlow* head = node->head;
-    node->head = head->next;
-
-    FlowData* fd;
-
-    while ((fd = head->data))
-    {
-        head->data = fd->next;
-        lws->set_flow_data(fd);
-        ++realized;
-        fd->handle_expected(p);
-    }
-    head->next = free_list;
-    free_list = head;
-
-    /* If this is 0, we're ignoring, otherwise setting id of new session */
-    if ( !node->appId )
-        retVal = node->direction;
-
-    else if ( lws->ssn_state.application_protocol != node->appId )
-    {
-        lws->ssn_state.application_protocol = node->appId;
-    }
-
-    if ( !node->count )
-        hash_table->remove();
-
-    return retVal;
+    FlowKey key;
+    return (find_node_by_packet(p, key) != nullptr);
 }
 
-char ExpectCache::check(Packet* p, Flow* lws)
+bool ExpectCache::check(Packet* p, Flow* lws)
 {
-    if ( !is_expected(p) )
-        return SSN_DIR_NONE;
+    FlowKey key;
+    ExpectNode* node = find_node_by_packet(p, key);
+
+    if (!node)
+        return false;
 
-    return process_expected(p, lws);
+    return process_expected(node, key, p, lws);
 }
 
index 8b2e4c67aa69ed8de0f19e043208db4b65485e40..f373dba7c6f347dbdd289fa4023b7e1086f4547f 100644 (file)
@@ -65,6 +65,8 @@
 #include "flow/flow.h"
 
 struct Packet;
+struct ExpectFlow;
+struct ExpectNode;
 
 class ExpectCache
 {
@@ -72,14 +74,13 @@ public:
     ExpectCache(uint32_t max);
     ~ExpectCache();
 
-    int add_flow(
-        const sfip_t *cliIP, uint16_t cliPort,
-        const sfip_t *srvIP, uint16_t srvPort,
-        PktType, char direction, FlowData*, int16_t appId = 0);
+    int add_flow(const Packet *ctrlPkt, PktType, IpProtocol,
+        const sfip_tcliIP, uint16_t cliPort,
+        const sfip_tsrvIP, uint16_t srvPort,
+        char direction, FlowData*, int16_t appId = 0);
 
     bool is_expected(Packet*);
-    char process_expected(Packet*, Flow*);
-    char check(Packet*, Flow*);
+    bool check(Packet*, Flow*);
 
     unsigned long get_expects() { return expects; }
     unsigned long get_realized() { return realized; }
@@ -89,15 +90,16 @@ public:
 private:
     void prune();
 
-    struct ExpectNode* get_node(struct ExpectKey&, bool&);
-    struct ExpectFlow* get_flow(ExpectNode*, uint32_t, int16_t);
+    ExpectNode* get_node(FlowKey&, bool&);
+    ExpectFlow* get_flow(ExpectNode*, uint32_t, int16_t);
     bool set_data(ExpectNode*, ExpectFlow*&, FlowData*);
+    ExpectNode* find_node_by_packet(Packet*, FlowKey&);
+    bool process_expected(ExpectNode*, FlowKey&, Packet*, Flow*);
 
 private:
     class ZHash* hash_table;
-    struct ExpectNode* nodes;
-    struct ExpectFlow* pool, * free_list;
-    sfip_t zeroed;
+    ExpectNode* nodes;
+    ExpectFlow* pool, * free_list;
 
     unsigned long expects, realized;
     unsigned long prunes, overflows;
index 504d8e8d3fe8bb58b9d90a0f520e92f8e5d82b7d..80a825a0051f4131f2906cb53a80e140636c715f 100644 (file)
@@ -754,9 +754,9 @@ void FlowControl::init_exp(uint32_t max)
     exp_cache = new ExpectCache(max);
 }
 
-char FlowControl::expected_flow(Flow* flow, Packet* p)
+bool FlowControl::expected_flow(Flow* flow, Packet* p)
 {
-    char ignore = exp_cache->check(p, flow);
+    bool ignore = exp_cache->check(p, flow);
 
     if ( ignore )
     {
@@ -772,22 +772,25 @@ char FlowControl::expected_flow(Flow* flow, Packet* p)
 }
 
 int FlowControl::add_expected(
+    const Packet* ctrlPkt, PktType type, IpProtocol ip_proto,
     const sfip_t *srcIP, uint16_t srcPort,
     const sfip_t *dstIP, uint16_t dstPort,
-    PktType type, char direction,
-    FlowData* fd)
+    char direction, FlowData* fd)
 {
     return exp_cache->add_flow(
-        srcIP, srcPort, dstIP, dstPort, type, direction, fd);
+        ctrlPkt, type, ip_proto, srcIP, srcPort, dstIP, dstPort,
+        direction, fd);
 }
 
 int FlowControl::add_expected(
+    const Packet* ctrlPkt, PktType type, IpProtocol ip_proto,
     const sfip_t *srcIP, uint16_t srcPort,
     const sfip_t *dstIP, uint16_t dstPort,
-    PktType type, int16_t appId, FlowData* fd)
+    int16_t appId, FlowData* fd)
 {
     return exp_cache->add_flow(
-        srcIP, srcPort, dstIP, dstPort, type, SSN_DIR_BOTH, fd, appId);
+        ctrlPkt, type, ip_proto, srcIP, srcPort, dstIP, dstPort,
+        SSN_DIR_BOTH, fd, appId);
 }
 
 bool FlowControl::is_expected(Packet* p)
index 6ea36bdefea7752fe5419061f0b20c63bc2beb17..1cc98e23267425d44dd3bf08cb8bab29069c3239 100644 (file)
@@ -74,18 +74,20 @@ public:
 
     void timeout_flows(time_t cur_time);
 
-    char expected_flow(Flow*, Packet*);
+    bool expected_flow(Flow*, Packet*);
     bool is_expected(Packet*);
 
     int add_expected(
+        const Packet* ctrlPkt, PktType, IpProtocol,
         const sfip_t *srcIP, uint16_t srcPort,
         const sfip_t *dstIP, uint16_t dstPort,
-        PktType, char direction, FlowData*);
+        char direction, FlowData*);
 
     int add_expected(
+        const Packet* ctrlPkt, PktType, IpProtocol,
         const sfip_t *srcIP, uint16_t srcPort,
         const sfip_t *dstIP, uint16_t dstPort,
-        PktType, int16_t appId, FlowData*);
+        int16_t appId, FlowData*);
 
     PegCount get_flows(PktType);
     PegCount get_total_prunes(PktType) const;
index 91d3e8d995458f2ac5997ddb5a809cb64c284519..dbd4b0dff54f30288d46dcee18ee22ff2975dd0d 100644 (file)
@@ -35,7 +35,7 @@
 // init foo
 //-------------------------------------------------------------------------
 
-inline void FlowKey::init4(
+inline bool FlowKey::init4(
     IpProtocol ip_proto,
     const sfip_t *srcIP, uint16_t srcPort,
     const sfip_t *dstIP, uint16_t dstPort,
@@ -43,6 +43,7 @@ inline void FlowKey::init4(
 {
     const uint32_t* src;
     const uint32_t* dst;
+    bool reversed = false;
 
     if ( ip_proto ==  IpProtocol::ICMPV4 )
     {
@@ -81,6 +82,7 @@ inline void FlowKey::init4(
         {
             port_l = dstPort;
             port_h = srcPort;
+            reversed = true;
         }
     }
     else
@@ -89,15 +91,18 @@ inline void FlowKey::init4(
         port_l = dstPort;
         COPY4(ip_h, src);
         port_h = srcPort;
+        reversed = true;
     }
     if (SnortConfig::mpls_overlapping_ip() &&
         ip::isPrivateIP(*src) && ip::isPrivateIP(*dst))
         mplsLabel = mplsId;
     else
         mplsLabel = 0;
+
+    return reversed;
 }
 
-inline void FlowKey::init6(
+inline bool FlowKey::init6(
     IpProtocol ip_proto,
     const sfip_t *srcIP, uint16_t srcPort,
     const sfip_t *dstIP, uint16_t dstPort,
@@ -105,6 +110,7 @@ inline void FlowKey::init6(
 {
     const sfip_t* src;
     const sfip_t* dst;
+    bool reversed = false;
 
     if ( ip_proto == IpProtocol::ICMPV4 )
     {
@@ -158,6 +164,7 @@ inline void FlowKey::init6(
         {
             port_l = dstPort;
             port_h = srcPort;
+            reversed = true;
         }
     }
     else
@@ -166,12 +173,15 @@ inline void FlowKey::init6(
         port_l = dstPort;
         COPY4(ip_h, src->ip32);
         port_h = srcPort;
+        reversed = true;
     }
 
     if (SnortConfig::mpls_overlapping_ip())
         mplsLabel = mplsId;
     else
         mplsLabel = 0;
+
+    return reversed;
 }
 
 void FlowKey::init_vlan(uint16_t vlanId)
@@ -199,35 +209,39 @@ void FlowKey::init_mpls(uint32_t mplsId)
         mplsLabel = 0;
 }
 
-void FlowKey::init(
+bool FlowKey::init(
     PktType type, IpProtocol ip_proto,
     const sfip_t *srcIP, uint16_t srcPort,
     const sfip_t *dstIP, uint16_t dstPort,
     uint16_t vlanId, uint32_t mplsId, uint16_t addrSpaceId)
 {
+    bool reversed;
+
     /* Because the key is going to be used for hash lookups,
-     * the lower of the values of the IP address field is
-     * stored in the ip_l and the port for that ip is
-     * stored in port_l.
+     * the key fields will be normalized such that the lower
+     * of the IP addresses is stored in ip_l and the port for
+     * that IP is stored in port_l.
      */
     if (srcIP->is_ip4())
     {
         version = 4;
-        init4(ip_proto, srcIP, srcPort, dstIP, dstPort, mplsId);
+        reversed = init4(ip_proto, srcIP, srcPort, dstIP, dstPort, mplsId);
     }
     else
     {
         version = 6;
-        init6(ip_proto, srcIP, srcPort, dstIP, dstPort, mplsId);
+        reversed = init6(ip_proto, srcIP, srcPort, dstIP, dstPort, mplsId);
     }
 
     pkt_type = type;
 
     init_vlan(vlanId);
     init_address_space(addrSpaceId);
+
+    return reversed;
 }
 
-void FlowKey::init(
+bool FlowKey::init(
     PktType type, IpProtocol ip_proto,
     const sfip_t *srcIP, const sfip_t *dstIP,
     uint32_t id, uint16_t vlanId,
@@ -252,6 +266,8 @@ void FlowKey::init(
 
     init_vlan(vlanId);
     init_address_space(addrSpaceId);
+
+    return false;
 }
 
 //-------------------------------------------------------------------------
index de1ddde86ffb3f61888c05af8d7fa706f4b0e0ed..70479e5dc31729633ef4f366ffc73f66125a1924 100644 (file)
@@ -41,13 +41,17 @@ struct FlowKey
     uint16_t   addressSpaceId;
     uint16_t   addressSpaceIdPad1;
 
-    void init(
+    /* The init() functions return true if the key IP/port fields were actively
+        normalized, reversing the source and destination addresses internally.
+        The IP-only init() will always return false as we will not reorder its
+        addresses at this time. */
+    bool init(
         PktType, IpProtocol,
         const sfip_t *srcIP, uint16_t srcPort,
         const sfip_t *dstIP, uint16_t dstPort,
         uint16_t vlanId, uint32_t mplsId, uint16_t addrSpaceId);
 
-    void init(
+    bool init(
         PktType, IpProtocol,
         const sfip_t *srcIP, const sfip_t *dstIP,
         uint32_t id, uint16_t vlanId,
@@ -62,13 +66,13 @@ struct FlowKey
     static int compare(const void* s1, const void* s2, size_t);
 
 private:
-    void init4(
+    bool init4(
         IpProtocol,
         const sfip_t *srcIP, uint16_t srcPort,
         const sfip_t *dstIP, uint16_t dstPort,
         uint32_t mplsId, bool order = true);
 
-    void init6(
+    bool init6(
         IpProtocol,
         const sfip_t *srcIP, uint16_t srcPort,
         const sfip_t *dstIP, uint16_t dstPort,
index ad27c54e4153f5c78c637f4d8a21d32432bc1710..61d54a1007b275aba89b53a808c1ca0dfaf255dc 100644 (file)
@@ -309,7 +309,7 @@ void* ZHash::pop()
     return pv;
 }
 
-void* ZHash::get(const void* key)
+void* ZHash::get(const void* key, bool *new_node)
 {
     int index = 0;
     ZHashNode* node = find_node_row(key, &index);
@@ -330,6 +330,9 @@ void* ZHash::get(const void* key)
 
     count++;
 
+    if (new_node)
+        *new_node = true;
+
     return node->data;
 }
 
index 6330ad0c178b5cafd06aa8e02e0fbbddbc222dd9..b2519273fa4d1cec22ada5d85547026f485220ec 100644 (file)
@@ -40,7 +40,7 @@ public:
     bool touch();
 
     void* find(const void* key);
-    void* get(const void* key);
+    void* get(const void* key, bool *new_node = nullptr);
 
     bool remove(const void* key);
     bool remove();
index 38c91fe3052494f939565bfd2973a36c1d6a9d0b..e3367ec5db16ffa9797d5fa1224acfe01b63773f 100644 (file)
@@ -446,14 +446,35 @@ AppIdSession::~AppIdSession()
     delete_shared_data();
 }
 
-AppIdSession* AppIdSession::create_future_session(const Packet* /*ctrlPkt*/, const sfip_t* cliIp, uint16_t cliPort,
+// FIXIT-L X Move this to somewhere more generally available/appropriate.
+static inline PktType get_pkt_type_from_ip_proto(IpProtocol proto)
+{
+    switch (proto)
+    {
+        case IpProtocol::TCP:
+            return PktType::TCP;
+        case IpProtocol::UDP:
+            return PktType::UDP;
+        case IpProtocol::ICMPV4:
+            return PktType::ICMP;
+        case IpProtocol::IP:
+            return PktType::IP;
+        default:
+            break;
+    }
+    return PktType::NONE;
+}
+
+AppIdSession* AppIdSession::create_future_session(const Packet* ctrlPkt, const sfip_t* cliIp, uint16_t cliPort,
     const sfip_t* srvIp, uint16_t srvPort, IpProtocol proto, int16_t app_id, int /*flags*/)
 {
     char src_ip[INET6_ADDRSTRLEN];
     char dst_ip[INET6_ADDRSTRLEN];
-    // FIXIT - not needed  until crtlPkt expectedSession is supported
+    // FIXIT - not needed  until ctrlPkt expectedSession is supported
     //struct _ExpectNode** node;
-    enum PktType protocol = ( enum PktType ) proto;
+    enum PktType type = get_pkt_type_from_ip_proto(proto);
+
+    assert(type != PktType::NONE);
 
     if (app_id_debug_session_flag)
     {
@@ -469,8 +490,8 @@ AppIdSession* AppIdSession::create_future_session(const Packet* /*ctrlPkt*/, con
 
     // FIXIT - 2.9.x set_application_protocol_id_expected has several new parameters, need to look
     // into what is required to support those here.
-    if ( Stream::set_application_protocol_id_expected(
-        /*crtlPkt,*/ cliIp, cliPort, srvIp, srvPort, protocol, app_id, session) )
+    if ( Stream::set_application_protocol_id_expected(ctrlPkt, type, proto, cliIp, cliPort, srvIp, srvPort,
+        app_id, session) )
     {
         if (app_id_debug_session_flag)
             LogMessage("AppIdDbg %s failed to create a related flow for %s-%u -> %s-%u %u\n",
index 1c00e682b8038747ea73de4b0fb0d039d08d0ec7..55b12bdb305967e68fe23da2fb51949454e7dc5e 100644 (file)
@@ -38,6 +38,7 @@ extern "C" {
 #include "sfdaq_config.h"
 #include "main/snort_config.h"
 #include "parser/parser.h"
+#include "protocols/vlan.h"
 #include "utils/util.h"
 
 using namespace std;
@@ -529,13 +530,62 @@ int SFDAQInstance::modify_flow_opaque(const DAQ_PktHdr_t* hdr, uint32_t opaque)
 {
     DAQ_ModFlow_t mod;
 
-#ifdef DAQ_MODFLOW_TYPE_OPAQUE
     mod.type = DAQ_MODFLOW_TYPE_OPAQUE;
     mod.length = sizeof(opaque);
     mod.value = &opaque;
-#else
-    mod.opaque = opaque;
-#endif
 
     return daq_modify_flow(daq_mod, daq_hand, hdr, &mod);
 }
+
+// FIXIT-L X Add Snort flag defitions for callers to use and translate/pass them through to the DAQ module
+int SFDAQInstance::add_expected(const Packet* ctrlPkt, const sfip_t* cliIP, uint16_t cliPort,
+        const sfip_t* srvIP, uint16_t srvPort, IpProtocol protocol, unsigned timeout_ms, unsigned /* flags */)
+{
+    DAQ_Data_Channel_Params_t daq_params;
+    DAQ_DP_key_t dp_key;
+
+    dp_key.src_af = cliIP->family;
+    if (cliIP->is_ip4())
+        dp_key.sa.src_ip4.s_addr = *cliIP->ip32;
+    else
+        memcpy(&dp_key.sa.src_ip6, cliIP->ip8, sizeof(dp_key.sa.src_ip6));
+    dp_key.src_port = cliPort;
+
+    dp_key.dst_af = srvIP->family;
+    if (srvIP->is_ip4())
+        dp_key.da.dst_ip4.s_addr = *srvIP->ip32;
+    else
+        memcpy(&dp_key.da.dst_ip6, srvIP->ip8, sizeof(dp_key.da.dst_ip6));
+    dp_key.dst_port = srvPort;
+
+    dp_key.protocol = (uint8_t) protocol;
+    dp_key.vlan_cnots = 1;
+    if (ctrlPkt->proto_bits & PROTO_BIT__VLAN)
+        dp_key.vlan_id = layer::get_vlan_layer(ctrlPkt)->vid();
+    else
+        dp_key.vlan_id = 0xFFFF;
+
+    if (ctrlPkt->proto_bits & PROTO_BIT__GTP)
+        dp_key.tunnel_type = DAQ_DP_TUNNEL_TYPE_GTP_TUNNEL;
+    else if (ctrlPkt->proto_bits & PROTO_BIT__MPLS)
+        dp_key.tunnel_type = DAQ_DP_TUNNEL_TYPE_MPLS_TUNNEL;
+/*
+    else if ( ctrlPkt->encapsulated )
+        dp_key.tunnel_type = DAQ_DP_TUNNEL_TYPE_OTHER_TUNNEL;
+*/
+    else
+        dp_key.tunnel_type = DAQ_DP_TUNNEL_TYPE_NON_TUNNEL;
+
+    memset(&daq_params, 0, sizeof(daq_params));
+    daq_params.timeout_ms = timeout_ms;
+/*
+    if (flags & DAQ_DC_FLOAT)
+        daq_params.flags |= DAQ_DATA_CHANNEL_FLOAT;
+    if (flags & DAQ_DC_ALLOW_MULTIPLE)
+        daq_params.flags |= DAQ_DATA_CHANNEL_ALLOW_MULTIPLE;
+    if (flags & DAQ_DC_PERSIST)
+        daq_params.flags |= DAQ_DATA_CHANNEL_PERSIST;
+*/
+
+    return daq_dp_add_dc(daq_mod, daq_hand, ctrlPkt->pkth, &dp_key, NULL, &daq_params);
+}
index 7bee63cea5331b9ebf2f6d9d73349ea17b3f4a3f..7629e46c88a29221b8e29f9d21e6e807a761a1f6 100644 (file)
@@ -29,8 +29,11 @@ extern "C" {
 #include <string>
 
 #include "main/snort_types.h"
+#include "protocols/protocol_ids.h"
 
+struct Packet;
 struct SnortConfig;
+struct sfip_t;
 
 class SFDAQInstance
 {
@@ -55,6 +58,9 @@ public:
     bool break_loop(int error);
     const DAQ_Stats_t* get_stats();
     int modify_flow_opaque(const DAQ_PktHdr_t*, uint32_t opaque);
+    int add_expected(const Packet* ctrlPkt, const sfip_t* cliIP, uint16_t cliPort,
+            const sfip_t* srvIP, uint16_t srvPort, IpProtocol, unsigned timeout_ms,
+            unsigned /* flags */);
 private:
     bool set_filter(const char*);
     std::string interface_spec;
index f6483565e5d522fa6ac85e0c10a9e1456062a3e6..a2576e6ae48f98b09ba37056d5487c25a8538471 100644 (file)
@@ -269,7 +269,7 @@ static int ProcessFTPDataChanCmdsList(
         FTPCmd->file_put_cmd = 1;
 
     if ( fc->flags & CMD_GET )
-        FTPCmd->data_xfer_cmd = 1;
+        FTPCmd->file_get_cmd = 1;
 
     if ( fc->flags & CMD_CHECK )
     {
index 024a9717abb97a00b9e021da4dbd92f6caf416b7..7cfed7c8abca87c1cdfab3a5247b9c93b9f769b7 100644 (file)
@@ -37,6 +37,8 @@
 #define s_help \
     "FTP data channel handler"
 
+static const char* const fd_svc_name = "ftp-data";
+
 static THREAD_LOCAL ProfileStats ftpdataPerfStats;
 static THREAD_LOCAL SimpleStats fdstats;
 
@@ -82,7 +84,7 @@ static int SnortFTPData(Packet* p)
         return -1;
 
     FtpDataFlowData* fd = (FtpDataFlowData*)
-        p->flow->get_flow_data(FtpFlowData::flow_id);
+        p->flow->get_flow_data(FtpDataFlowData::flow_id);
 
     FTP_DATA_SESSION* data_ssn = fd ? &fd->session : nullptr;
 
@@ -168,6 +170,8 @@ FtpDataFlowData::FtpDataFlowData(Packet* p) : FlowData(flow_id)
 
     session.ft_ssn.proto = FTPP_SI_PROTO_FTP_DATA;
     Stream::populate_flow_key(p, &session.ftp_key);
+    if (p->flow)
+        session.ftp_key.pkt_type = p->flow->pkt_type;
 }
 
 FtpDataFlowData::~FtpDataFlowData()
@@ -176,6 +180,13 @@ FtpDataFlowData::~FtpDataFlowData()
         snort_free(session.filename);
 }
 
+void FtpDataFlowData::handle_expected(Packet* p)
+{
+    // FIXIT-M X This is an ugly, ugly hack, but it's the way Wizard is doing it
+    if (!p->flow->service)
+        p->flow->service = fd_svc_name;
+}
+
 void FtpDataFlowData::handle_eof(Packet* p)
 {
     FTP_DATA_SESSION* data_ssn = &session;
@@ -287,7 +298,7 @@ const InspectApi fd_api =
     IT_SERVICE,
     (uint16_t)PktType::PDU,
     nullptr, // buffers
-    "ftp-data",
+    fd_svc_name,
     fd_init,
     nullptr, // pterm
     nullptr, // tinit
index c3c0d691a3a0b944f0c90644d22b5342349454c1..0df1736e2e3c0d099114c808e9fb40e131485f02 100644 (file)
@@ -220,6 +220,7 @@ public:
     static void init()
     { flow_id = FlowData::get_flow_id(); }
 
+    void handle_expected(Packet*) override;
     void handle_eof(Packet*) override;
 
 public:
index 33194a8b25cafbfb1f93c505e0a09d37a2da36a8..98849be99316d2a1d0a370ab533651546e949a4a 100644 (file)
@@ -984,6 +984,8 @@ int initialize_ftp(FTP_SESSION* session, Packet* p, int iMode)
  * Returns: int => return code indicating error or success
  *
  */
+// FIXIT-M X Expected flow operations are using hardcoded TCP PktType/IpProtocol,
+//      which could that bite us on the mythical FTP over UDP or SCTP?
 static int do_stateful_checks(FTP_SESSION* session, Packet* p,
     FTP_CLIENT_REQ* req, int rsp_code)
 {
@@ -1069,9 +1071,10 @@ static int do_stateful_checks(FTP_SESSION* session, Packet* p,
 
                                 /* Call into Streams to mark data channel as ftp-data */
                                 result = Stream::set_application_protocol_id_expected(
+                                    p, PktType::TCP, IpProtocol::TCP,
                                     &session->clientIP, session->clientPort,
                                     &session->serverIP, session->serverPort,
-                                    p->type(), ftp_data_app_id, fd);
+                                    ftp_data_app_id, fd);
 
                                 if (result < 0)
                                     delete fd;
@@ -1081,10 +1084,10 @@ static int do_stateful_checks(FTP_SESSION* session, Packet* p,
                                 /* Call into Streams to mark data channel as something
                                  * to ignore. */
                                 Stream::ignore_flow(
+                                    p, PktType::TCP, IpProtocol::TCP,
                                     &session->clientIP, session->clientPort,
                                     &session->serverIP, session->serverPort,
-                                    p->type(), SSN_DIR_BOTH,
-                                    FtpDataFlowData::flow_id);
+                                    SSN_DIR_BOTH, FtpDataFlowData::flow_id);
                             }
                         }
                     }
@@ -1141,9 +1144,10 @@ static int do_stateful_checks(FTP_SESSION* session, Packet* p,
 
                             /* Call into Streams to mark data channel as ftp-data */
                             result = Stream::set_application_protocol_id_expected(
+                                p, PktType::TCP, IpProtocol::TCP,
                                 &session->clientIP, session->clientPort,
                                 &session->serverIP, session->serverPort,
-                                p->type(), ftp_data_app_id, fd);
+                                ftp_data_app_id, fd);
 
                             if (result < 0)
                                 delete fd;
@@ -1153,10 +1157,10 @@ static int do_stateful_checks(FTP_SESSION* session, Packet* p,
                             /* Call into Streams to mark data channel as something
                              * to ignore. */
                             Stream::ignore_flow(
+                                p, PktType::TCP, IpProtocol::TCP,
                                 &session->clientIP, session->clientPort,
                                 &session->serverIP, session->serverPort,
-                                p->type(), SSN_DIR_BOTH,
-                                FtpDataFlowData::flow_id);
+                                SSN_DIR_BOTH, FtpDataFlowData::flow_id);
                         }
                     }
                 }
index 63c82be625b7b3e9f6fcab178b79a261546167eb..0d1701440816cc9f2cd7eff15ecf008fc5a7a817 100644 (file)
 #include <assert.h>
 
 #include "framework/data_bus.h"
-#include "main/snort_types.h"
-#include "main/snort_debug.h"
 #include "main/snort_config.h"
-#include "stream/stream.h"
+#include "main/snort_debug.h"
+#include "main/snort_types.h"
+#include "protocols/vlan.h"
 #include "sfip/sf_ip.h"
+#include "stream/stream.h"
 
 #include "sip_module.h"
 #include "sip.h"
@@ -408,18 +409,20 @@ static int SIP_ignoreChannels(SIP_DialogData* dialog, Packet* p, SIP_PROTO_CONF*
             sfip_to_str(&mdataB->maddress), mdataB->mport);
 
         /* Call into Streams to mark data channel as something to ignore. */
-        FlowData* fd = Stream::get_flow_data(
-            PktType::UDP, IpProtocol::UDP, &mdataA->maddress,mdataA->mport,
-            &mdataB->maddress, mdataB->mport, 0, 0, p->pkth->address_space_id,
-            SipFlowData::flow_id);
-        if ( fd )
+        Flow* ssn = Stream::get_flow(
+            PktType::UDP, IpProtocol::UDP, &mdataA->maddress,
+            mdataA->mport, &mdataB->maddress, mdataB->mport,
+            (p->proto_bits & PROTO_BIT__VLAN) ? layer::get_vlan_layer(p)->vid() : 0,
+            (p->proto_bits & PROTO_BIT__MPLS) ? p->ptrs.mplsHdr.label : 0,
+            p->pkth->address_space_id);
+        if (ssn)
         {
-            p->flow->set_ignore_direction(SSN_DIR_BOTH);
+            ssn->set_ignore_direction(SSN_DIR_BOTH);
         }
         else
         {
-            Stream::ignore_flow(&mdataA->maddress, mdataA->mport, &mdataB->maddress,
-                mdataB->mport, p->type(), SSN_DIR_BOTH, SipFlowData::flow_id);
+            Stream::ignore_flow(p, p->flow->pkt_type, p->get_ip_proto_next(), &mdataA->maddress,
+                mdataA->mport, &mdataB->maddress, mdataB->mport, SSN_DIR_BOTH, SipFlowData::flow_id);
         }
         sip_stats.ignoreChannels++;
         mdataA = mdataA->nextM;
index 05575244c44c8e14464a298510ab60fea12e7b08..d8557836d64c1041872535ace1ad908fb189ca57 100644 (file)
@@ -137,6 +137,8 @@ FlowData* Stream::get_flow_data(
     const FlowKey* key, unsigned flow_id)
 {
     Flow* flow = get_flow(key);
+    if (!flow)
+        return nullptr;
     return flow->get_flow_data(flow_id);
 }
 
@@ -153,7 +155,7 @@ FlowData* Stream::get_flow_data(
         vlan, mplsId, addressSpaceID);
 
     if (!flow)
-        return NULL;
+        return nullptr;
 
     return flow->get_flow_data(flow_id);
 }
@@ -178,14 +180,16 @@ void Stream::check_flow_closed(Packet* p)
 }
 
 int Stream::ignore_flow(
+    const Packet* ctrlPkt, PktType type, IpProtocol ip_proto,
     const sfip_t* srcIP, uint16_t srcPort,
     const sfip_t* dstIP, uint16_t dstPort,
-    PktType protocol, char direction,
-    uint32_t flow_id)
+    char direction, uint32_t flow_id)
 {
     assert(flow_con);
     FlowData* fd = new FlowData(flow_id);
-    return flow_con->add_expected(srcIP, srcPort, dstIP, dstPort, protocol, direction, fd);
+
+    return flow_con->add_expected(
+        ctrlPkt, type, ip_proto, srcIP, srcPort, dstIP, dstPort, direction, fd);
 }
 
 void Stream::proxy_started(Flow* flow, unsigned dir)
@@ -362,14 +366,15 @@ bool Stream::expected_flow(Flow* f, Packet* p)
 //-------------------------------------------------------------------------
 
 int Stream::set_application_protocol_id_expected(
+    const Packet* ctrlPkt, PktType type, IpProtocol ip_proto,
     const sfip_t* srcIP, uint16_t srcPort,
-    const sfip_t* dstIP, uint16_t dstPort,
-    PktType protocol, int16_t appId, FlowData* fd)
+    const sfip_t* dstIP, uint16_t dstPort, 
+    int16_t appId, FlowData* fd)
 {
     assert(flow_con);
 
     return flow_con->add_expected(
-        srcIP, srcPort, dstIP, dstPort, protocol, appId, fd);
+        ctrlPkt, type, ip_proto, srcIP, srcPort, dstIP, dstPort, appId, fd);
 }
 
 void Stream::set_application_protocol_id(
index a55085c54d5a73150ce8d4de18c0b18d322525f0..7fa80c140a6e7d0c296b1001e1cdd7b2cbd6a5b9 100644 (file)
@@ -108,8 +108,8 @@ public:
     // n-tuple parameters specified.  Inspection will be turned off for this expected session
     // when it arrives.
     static int ignore_flow(
-        const sfip_t *addr1, uint16_t p1, const sfip_t *addr2, uint16_t p2,
-        PktType, char dir, uint32_t ppId);
+        const Packet* ctrlPkt, PktType, IpProtocol, const sfip_t* srcIP, uint16_t srcPort,
+        const sfip_t* dstIP, uint16_t dstPort, char direction, uint32_t flow_id);
 
     // Resume inspection for flow.
     // FIXIT-L does resume work only for a flow that has been stopped by call to stop_inspection?
@@ -178,8 +178,8 @@ public:
     // Turn off inspection for potential session. Adds session identifiers to a hash table.
     // TCP only.
     static int set_application_protocol_id_expected(
-        const sfip_t *a1, uint16_t p1, const sfip_t *a2, uint16_t p2, PktType,
-        int16_t appId, FlowData*);
+        const Packet* ctrlPkt, PktType, IpProtocol, const sfip_t* srcIP, uint16_t srcPort,
+        const sfip_t* dstIP, uint16_t dstPort, int16_t appId, FlowData*);
 
     // Get pointer to application data for a flow based on the lookup tuples for cases where
     // Snort does not have an active packet that is relevant.
index 91fe763d71e5e40f84cb0586522ab77fbf15bc50..353e402f6b2aa38556e26181a28492df749768fe 100644 (file)
@@ -680,9 +680,7 @@ void TcpSession::update_paws_timestamps(TcpSegmentDescriptor& tsd)
 
 void TcpSession::check_for_session_hijack(TcpSegmentDescriptor& tsd)
 {
-#ifdef DAQ_PKT_FLAG_PRE_ROUTING
     if (!(tsd.get_pkt()->pkth->flags & DAQ_PKT_FLAG_PRE_ROUTING))
-#endif
     {
         uint32_t event_code = 0;
 
@@ -1022,7 +1020,6 @@ bool TcpSession::is_flow_handling_packets(Packet* p)
 
     // FIXIT-L expected flow should be checked by Stream before we get here
     // harmonize this with that and the checks above
-
     if ( Stream::expected_flow(flow, p) )
     {
         server->flush_policy = STREAM_FLPOLICY_IGNORE;