time_t pt = packet_time();
struct tm st;
char buf[26];
+ SfIpString ip_str;
gmtime_r(&pt, &st);
asctime_r(&st, buf);
buf[sizeof(buf)-2] = '\0';
TextLog_Print(tlog, "%s, ", buf);
- TextLog_Print(tlog, "%s, %d, ", f->client_ip.ntoa(), f->client_port);
- TextLog_Print(tlog, "%s, %d", f->server_ip.ntoa(), f->server_port);
+ TextLog_Print(tlog, "%s, %d, ", f->client_ip.ntop(ip_str), f->client_port);
+ TextLog_Print(tlog, "%s, %d", f->server_ip.ntop(ip_str), f->server_port);
HttpEvent* he = (HttpEvent*)&e;
int32_t n;
{
if ( a.pkt->has_ip() or a.pkt->is_data() )
{
+ SfIpString ip_str;
print_label(a, "dst_addr");
- TextLog_Quote(json_log, a.pkt->ptrs.ip_api.get_dst()->ntoa());
+ TextLog_Quote(json_log, a.pkt->ptrs.ip_api.get_dst()->ntop(ip_str));
return true;
}
return false;
static bool ff_dst_ap(Args& a)
{
- const char* addr = "";
+ SfIpString addr = "";
unsigned port = 0;
if ( a.pkt->has_ip() or a.pkt->is_data() )
- addr = a.pkt->ptrs.ip_api.get_dst()->ntoa();
+ a.pkt->ptrs.ip_api.get_dst()->ntop(addr);
if ( a.pkt->proto_bits & (PROTO_BIT__TCP|PROTO_BIT__UDP) )
port = a.pkt->ptrs.dp;
{
if ( a.pkt->has_ip() or a.pkt->is_data() )
{
+ SfIpString ip_str;
print_label(a, "src_addr");
- TextLog_Quote(json_log, a.pkt->ptrs.ip_api.get_src()->ntoa());
+ TextLog_Quote(json_log, a.pkt->ptrs.ip_api.get_src()->ntop(ip_str));
return true;
}
return false;
static bool ff_src_ap(Args& a)
{
- const char* addr = "";
+ SfIpString addr = "";
unsigned port = 0;
if ( a.pkt->has_ip() or a.pkt->is_data() )
- addr = a.pkt->ptrs.ip_api.get_src()->ntoa();
+ a.pkt->ptrs.ip_api.get_src()->ntop(addr);
if ( a.pkt->proto_bits & (PROTO_BIT__TCP|PROTO_BIT__UDP) )
port = a.pkt->ptrs.sp;
static bool ff_target(Args& a)
{
- const char* addr;
+ SfIpString addr = "";
if ( a.event.sig_info->target == TARGET_SRC )
- addr = a.pkt->ptrs.ip_api.get_src()->ntoa();
+ a.pkt->ptrs.ip_api.get_src()->ntop(addr);
else if ( a.event.sig_info->target == TARGET_DST )
- addr = a.pkt->ptrs.ip_api.get_dst()->ntoa();
+ a.pkt->ptrs.ip_api.get_dst()->ntop(addr);
else
return false;
void print_pkt_info(Packet* p)
{
const char* dir;
- string dst_addr, src_addr;
+ SfIpString src_addr, dst_addr;
unsigned src_port = 0, dst_port = 0;
pkt = p; //save packet pointer for later
if ( pkt->has_ip() or pkt->is_data() )
{
- src_addr = string(pkt->ptrs.ip_api.get_src()->ntoa());
- dst_addr = string(pkt->ptrs.ip_api.get_dst()->ntoa());
+ pkt->ptrs.ip_api.get_src()->ntop(src_addr);
+ pkt->ptrs.ip_api.get_dst()->ntop(dst_addr);
}
if ( pkt->proto_bits & (PROTO_BIT__TCP|PROTO_BIT__UDP) )
}
trace_logf(detection, TRACE_RULE_EVAL,"packet %" PRIu64 " %s %s:%u %s:%u\n",
- pc.total_from_daq, dir, src_addr.c_str(), src_port, dst_addr.c_str(), dst_port);
+ pc.total_from_daq, dir, src_addr, src_port, dst_addr, dst_port);
}
void print_pattern(const PatternMatchData* pmd)
}
}
- DebugFormat(DEBUG_DETECT, "addr %s, port %d ", pkt_addr->ntoa(), pkt_port);
+ DEBUG_WRAP( SfIpString ip_str; )
+ DebugFormat(DEBUG_DETECT, "addr %s, port %d ", pkt_addr->ntop(ip_str), pkt_port);
if (!rule_addr)
goto bail;
RuleTreeNode* rtn = getRuntimeRtnFromOtn(otn);
void* log_list = rtn ? rtn->listhead : nullptr;
+ DEBUG_WRAP( SfIpString ip_str; )
switch (otn->tag->tag_type)
{
case TAG_SESSION:
DebugMessage(DEBUG_FLOW,"Setting session tag:\n");
DebugFormat(DEBUG_FLOW,"SIP: %s SP: %d ",
- p->ptrs.ip_api.get_src()->ntoa(), p->ptrs.sp);
+ p->ptrs.ip_api.get_src()->ntop(ip_str), p->ptrs.sp);
DebugFormat(DEBUG_FLOW,"DIP: %s DP: %d\n",
- p->ptrs.ip_api.get_dst()->ntoa(), p->ptrs.dp);
+ p->ptrs.ip_api.get_dst()->ntop(ip_str), p->ptrs.dp);
TagSession(p, otn->tag, p->pkth->ts.tv_sec, event_id, log_list);
break;
case TAG_HOST:
DebugMessage(DEBUG_FLOW,"Setting host tag:\n");
DebugFormat(DEBUG_FLOW,"SIP: %s SP: %d ",
- p->ptrs.ip_api.get_src()->ntoa(), p->ptrs.sp);
+ p->ptrs.ip_api.get_src()->ntop(ip_str), p->ptrs.sp);
DebugFormat(DEBUG_FLOW, "DIP: %s DP: %d\n",
- p->ptrs.ip_api.get_dst()->ntoa(), p->ptrs.dp);
+ p->ptrs.ip_api.get_dst()->ntop(ip_str), p->ptrs.dp);
TagHost(p, otn->tag, p->pkth->ts.tv_sec, event_id, log_list);
break;
TextLog_Print(tlog, " ");
}
- TextLog_Print(tlog, " %s:%d -> ", f->client_ip.ntoa(), f->client_port);
- TextLog_Print(tlog, "%s:%d, ", f->server_ip.ntoa(), f->server_port);
+ SfIpString ip_str;
+ TextLog_Print(tlog, " %s:%d -> ", f->client_ip.ntop(ip_str), f->client_port);
+ TextLog_Print(tlog, "%s:%d, ", f->server_ip.ntop(ip_str), f->server_port);
FileFlows* files = FileFlows::get_file_flows(f);
#include "detection/detection_engine.h"
#include "events/event_queue.h"
+#ifdef UNIT_TEST
+#include "catch/snort_catch.h"
+#endif
+
using namespace snort;
EncState::EncState(const ip::IpApi& api, EncodeFlags f, IpProtocol pr,
}
}
-/* Logic behind 'buf + size + 1' -- we're encoding the
+/* Logic behind 'buf + size' -- we're encoding the
* packet from the inside out. So, whenever we add
* data, 'allocating' N bytes means moving the pointer
* N characters farther from the end. For this scheme
* array
*/
Buffer::Buffer(uint8_t* buf, uint32_t size) :
- base(buf + size + 1),
+ base(buf + size),
end(0),
max_len(size),
off(0)
codec.codec_flags |= CODEC_ROUTING_SEEN;
}
+#ifdef UNIT_TEST
+TEST_CASE("init", "[buffer]")
+{
+ uint8_t raw_buf[2];
+ Buffer buf(&raw_buf[0], 1);
+ CHECK( buf.data() == &raw_buf[1] ); // 1 past the "known" buffer
+ CHECK( buf.size() == 0 );
+}
+
+TEST_CASE("alloc", "[buffer]")
+{
+ uint8_t raw_buf[1];
+ Buffer buf(raw_buf, 1);
+ buf.allocate(1);
+
+ CHECK( buf.data() == &raw_buf[0] );
+ CHECK( buf.size() == 1 );
+}
+
+TEST_CASE("multi alloc", "[buffer]")
+{
+ uint8_t raw_buf2[3];
+ Buffer buf2(raw_buf2, 3);
+ buf2.allocate(1);
+
+ CHECK( buf2.data() == &raw_buf2[2] );
+ CHECK( buf2.size() == 1 );
+
+ buf2.allocate(2);
+ CHECK( buf2.data() == &raw_buf2[0] );
+ CHECK( buf2.size() == 3 );
+}
+
+TEST_CASE("clear", "[buffer]")
+{
+ uint8_t raw_buf[2];
+ Buffer buf(raw_buf, 1);
+ buf.allocate(1);
+ buf.clear();
+
+ CHECK( buf.data() == &raw_buf[1] ); // 1 past the "known" buffer
+ CHECK( buf.size() == 0 );
+}
+#endif
using namespace snort;
-static THREAD_LOCAL uint8_t base64_decode_buf[DECODE_BLEN];
-static THREAD_LOCAL uint32_t base64_decode_size;
+struct Base64DecodeBuffer
+{
+ uint8_t data[DECODE_BLEN];
+ uint32_t size;
+};
+static THREAD_LOCAL Base64DecodeBuffer* base64_decode_buffer;
static THREAD_LOCAL ProfileStats base64PerfStats;
#define s_name "base64_decode"
#define BASE64DECODE_RELATIVE_FLAG 0x01
-typedef struct _Base64DecodeData
+struct Base64DecodeData
{
uint32_t bytes_to_decode;
uint32_t offset;
uint8_t flags;
-}Base64DecodeData;
+};
class Base64DecodeOption : public IpsOption
{
IpsOption::EvalStatus Base64DecodeOption::eval(Cursor& c, Packet*)
{
Profile profile(base64PerfStats);
- base64_decode_size = 0;
+ base64_decode_buffer->size = 0;
Base64DecodeData* idx = (Base64DecodeData*)&config;
const uint8_t* start_ptr = nullptr;
base64_size = idx->bytes_to_decode;
}
- if (sf_base64decode(base64_buf, base64_size, (uint8_t*)base64_decode_buf,
- sizeof(base64_decode_buf), &base64_decode_size) != 0)
+ if (sf_base64decode(base64_buf, base64_size, base64_decode_buffer->data,
+ sizeof(base64_decode_buffer->data), &base64_decode_buffer->size) != 0)
return NO_MATCH;
return MATCH;
{
Profile profile(base64PerfStats);
- if ( !base64_decode_size )
+ if ( !base64_decode_buffer->size )
return NO_MATCH;
- c.set(s_data_name, base64_decode_buf, base64_decode_size);
+ c.set(s_data_name, base64_decode_buffer->data, base64_decode_buffer->size);
return MATCH;
}
delete p;
}
+static void base64_data_tinit(SnortConfig*)
+{
+ base64_decode_buffer = new Base64DecodeBuffer();
+}
+
+static void base64_data_tterm(SnortConfig*)
+{
+ delete base64_decode_buffer;
+ base64_decode_buffer = nullptr;
+}
+
static const IpsApi base64_data_api =
{
{
0, 0,
nullptr,
nullptr,
- nullptr,
- nullptr,
+ base64_data_tinit,
+ base64_data_tterm,
base64_data_ctor,
base64_data_dtor,
nullptr
dst = p->ptrs.ip_api.get_dst();
src = p->ptrs.ip_api.get_src();
- const char* addr;
+ SfIpString addr;
if (SnortConfig::get_conf()->homenet.contains(dst) == SFIP_CONTAINS)
{
if (SnortConfig::get_conf()->homenet.contains(src) == SFIP_NOT_CONTAINS)
{
- addr = p->ptrs.ip_api.get_src()->ntoa();
+ p->ptrs.ip_api.get_src()->ntop(addr);
}
else
{
if (p->ptrs.sp >= p->ptrs.dp)
{
- addr = p->ptrs.ip_api.get_src()->ntoa();
+ p->ptrs.ip_api.get_src()->ntop(addr);
}
else
{
- addr = p->ptrs.ip_api.get_dst()->ntoa();
+ p->ptrs.ip_api.get_dst()->ntop(addr);
}
}
}
{
if (SnortConfig::get_conf()->homenet.contains(src) == SFIP_CONTAINS)
{
- addr = p->ptrs.ip_api.get_dst()->ntoa();
+ p->ptrs.ip_api.get_dst()->ntop(addr);
}
else
{
if (p->ptrs.sp >= p->ptrs.dp)
{
- addr = p->ptrs.ip_api.get_src()->ntoa();
+ p->ptrs.ip_api.get_src()->ntop(addr);
}
else
{
- addr = p->ptrs.ip_api.get_dst()->ntoa();
+ p->ptrs.ip_api.get_dst()->ntop(addr);
}
}
}
static void ff_dst_addr(Args& a)
{
if ( a.pkt->has_ip() or a.pkt->is_data() )
- TextLog_Puts(csv_log, a.pkt->ptrs.ip_api.get_dst()->ntoa());
+ {
+ SfIpString ip_str;
+ TextLog_Puts(csv_log, a.pkt->ptrs.ip_api.get_dst()->ntop(ip_str));
+ }
}
static void ff_dst_ap(Args& a)
{
- const char* addr = "";
+ SfIpString addr = "";
unsigned port = 0;
if ( a.pkt->has_ip() or a.pkt->is_data() )
- addr = a.pkt->ptrs.ip_api.get_dst()->ntoa();
+ a.pkt->ptrs.ip_api.get_dst()->ntop(addr);
if ( a.pkt->proto_bits & (PROTO_BIT__TCP|PROTO_BIT__UDP) )
port = a.pkt->ptrs.dp;
static void ff_src_addr(Args& a)
{
if ( a.pkt->has_ip() or a.pkt->is_data() )
- TextLog_Puts(csv_log, a.pkt->ptrs.ip_api.get_src()->ntoa());
+ {
+ SfIpString ip_str;
+ TextLog_Puts(csv_log, a.pkt->ptrs.ip_api.get_src()->ntop(ip_str));
+ }
}
static void ff_src_ap(Args& a)
{
- const char* addr = "";
+ SfIpString addr = "";
unsigned port = 0;
if ( a.pkt->has_ip() or a.pkt->is_data() )
- addr = a.pkt->ptrs.ip_api.get_src()->ntoa();
+ a.pkt->ptrs.ip_api.get_src()->ntop(addr);
if ( a.pkt->proto_bits & (PROTO_BIT__TCP|PROTO_BIT__UDP) )
port = a.pkt->ptrs.sp;
static void ff_target(Args& a)
{
- const char* addr;
+ SfIpString addr = "";
if ( a.event.sig_info->target == TARGET_SRC )
- addr = a.pkt->ptrs.ip_api.get_src()->ntoa();
+ a.pkt->ptrs.ip_api.get_src()->ntop(addr);
else if ( a.event.sig_info->target == TARGET_DST )
- addr = a.pkt->ptrs.ip_api.get_dst()->ntoa();
+ a.pkt->ptrs.ip_api.get_dst()->ntop(addr);
else
return;
// non-local for easy access from core
static THREAD_LOCAL DAQ_PktHdr_t s_pkth;
-static THREAD_LOCAL uint8_t s_data[65536];
+static THREAD_LOCAL uint8_t* s_data = nullptr;
static THREAD_LOCAL Packet* s_packet = nullptr;
static THREAD_LOCAL ContextSwitcher* s_switcher = nullptr;
*/
bool Snort::thread_init_privileged(const char* intf)
{
+ s_data = new uint8_t[65535];
show_source(intf);
SnortConfig::get_conf()->thread_config->implement_thread_affinity(STHREAD_TYPE_PACKET, get_instance_id());
// in case there are HA messages waiting, process them first
HighAvailabilityManager::process_receive();
+ PacketManager::thread_init();
}
void Snort::thread_term()
CleanupTag();
FileService::thread_term();
PacketTracer::thread_term();
+ PacketManager::thread_term();
Active::term();
delete s_switcher;
+ delete s_data;
}
void Snort::inspect(Packet* p)
#include "main/snort_config.h"
#include "packet_io/sfdaq.h"
#include "protocols/packet_manager.h"
-#include "utils/dnet_header.h"
using namespace snort;
// This is hardcoded into Snort++
extern const CodecApi* default_codec;
-// Local variables for various tasks
-static const uint16_t IP_ID_COUNT = 8192;
-static THREAD_LOCAL std::array<uint16_t, IP_ID_COUNT> s_id_pool {
- { 0 }
-};
-static THREAD_LOCAL rand_t* s_rand = nullptr;
-
/*
* Begin search from index 1. 0 is a special case in that it is the default
* codec and is actually a duplicate. i.e., we can find the 0 indexed
if (!grinder)
ParseError("Unable to find a Codec with data link type %d", daq_dlt);
-
- if ( s_rand )
- rand_close(s_rand);
-
- // rand_open() can yield valgrind errors because the
- // starting seed may come from "random stack contents"
- // (see man 3 dnet)
- s_rand = rand_open();
-
- if ( !s_rand )
- ParseError("rand_open() failed.");
-
- rand_get(s_rand, s_id_pool.data(), s_id_pool.size());
}
void CodecManager::thread_term()
if (wrap.api->tterm)
wrap.api->tterm();
}
-
- if ( s_rand )
- {
- rand_close(s_rand);
- s_rand = nullptr;
- }
}
void CodecManager::dump_plugins()
virtual void add_user(AppIdSession&, const char*, AppId, bool);
virtual void add_payload(AppIdSession&, AppId);
virtual void add_app(AppIdSession&, AppId, AppId, const char*);
+ virtual void finalize() {}
const std::string& get_name() const
{ return name; }
PatternClientDetector::finalize_client_port_patterns();
AppIdDiscovery::finalize_plugins();
http_matchers->finalize();
- SipUdpClientDetector::finalize_sip_ua();
ssl_detector_process_patterns();
dns_host_detector_process_patterns();
}
void ClientDiscovery::finalize_client_plugins()
{
+ for ( auto kv : tcp_detectors )
+ kv.second->finalize();
+
+ for ( auto kv : udp_detectors )
+ kv.second->finalize();
+
if ( tcp_patterns )
tcp_patterns->prep();
pattern);
}
-int SipUdpClientDetector::finalize_sip_ua()
+void SipUdpClientDetector::finalize()
{
- const int PATTERN_PART_MAX = 10;
- static THREAD_LOCAL tMlmpPattern patterns[PATTERN_PART_MAX];
int num_patterns;
DetectorAppSipPattern* patternNode;
detector_sip_config.sip_ua_matcher = mlmpCreate();
if ( !detector_sip_config.sip_ua_matcher )
- return -1;
+ return;
detector_sip_config.sip_server_matcher = mlmpCreate();
if ( !detector_sip_config.sip_server_matcher )
{
mlmpDestroy((tMlmpTree*)detector_sip_config.sip_ua_matcher);
detector_sip_config.sip_ua_matcher = nullptr;
- return -1;
+ return;
}
for ( patternNode = detector_sip_config.sip_ua_list; patternNode; patternNode =
mlmpProcessPatterns((tMlmpTree*)detector_sip_config.sip_ua_matcher);
mlmpProcessPatterns((tMlmpTree*)detector_sip_config.sip_server_matcher);
- return 0;
}
static int get_sip_client_app(void* patternMatcher, const char* pattern, uint32_t patternLen,
while ( media_a && media_b )
{
+ DEBUG_WRAP( snort::SfIpString ip_str; )
DebugFormat(DEBUG_SIP, "Adding future channels Source IP: %s Port: %hu\n",
- media_a->get_address()->ntoa(), media_a->get_port());
+ media_a->get_address()->ntop(ip_str), media_a->get_port());
DebugFormat(DEBUG_SIP, "Adding future channels Destine IP: %s Port: %hu\n",
- media_b->get_address()->ntoa(), media_b->get_port());
+ media_b->get_address()->ntop(ip_str), media_b->get_port());
createRtpFlow(asd, event.get_packet(), media_a->get_address(), media_a->get_port(),
media_b->get_address(), media_b->get_port(), IpProtocol::UDP, APP_ID_RTP);
int validate(AppIdDiscoveryArgs&) override;
+ void finalize() override;
+
+ // FIXIT-L revisit init so it's not split between static methods and constructor
static int sipUaPatternAdd(AppId, const char* clientVersion, const char* uaPattern);
static int sipServerPatternAdd(AppId, const char* clientVersion, const char* uaPattern);
- static int finalize_sip_ua();
+
+private:
+ static const int PATTERN_PART_MAX = 10;
+ tMlmpPattern patterns[PATTERN_PART_MAX];
};
class SipTcpClientDetector : public ClientDetector
{
SfIp in;
in.set(&p.ipv4_addr, AF_INET);
- LogMessage(" %s -> ", in.ntoa());
+ SfIpString ip_str;
+ LogMessage(" %s -> ", in.ntop(ip_str));
for (int i = 0; i < 6; i++)
{
p!=nullptr;
p =(IP_PORT*)sflist_next(&cur_ip) )
{
- printf("CIDR BLOCK: %c%s", p->notflag ? '!' : ' ', p->ip.get_addr()->ntoa());
+ SfIpString ip_str;
+ printf("CIDR BLOCK: %c%s", p->notflag ? '!' : ' ', p->ip.get_addr()->ntop(ip_str));
SF_LNODE* cur_port;
for ( PORTRANGE* pr=(PORTRANGE*)sflist_first(&p->portset.port_list, &cur_port);
static void make_open_port_info(Packet* p, uint16_t port)
{
DataBuffer& buf = DetectionEngine::get_alt_buffer(p);
-
- const char* addr = p->ptrs.ip_api.get_src()->ntoa();
+
+ SfIpString ip_str;
buf.len = safe_snprintf((char*)buf.data, sizeof(buf.data),
"Scanned IP: %s\n"
"Open Port: %hu\n",
- addr, port);
+ p->ptrs.ip_api.get_src()->ntop(ip_str), port);
}
static void PortscanAlertTcp(Packet* p, PS_PROTO* proto)
static void PrintIPPortSet(IP_PORT* p)
{
- char ip_str[80], output_str[80];
+ char output_str[80];
- SnortSnprintf(ip_str, sizeof(ip_str), "%s", p->ip.get_addr()->ntoa());
+ SfIpString ip_str;
+ p->ip.get_addr()->ntop(ip_str);
if (p->notflag)
SnortSnprintf(output_str, sizeof(output_str), " !%s", ip_str);
{
IPrepInfo* result;
- DEBUG_WRAP(DebugFormat(DEBUG_REPUTATION, "Lookup address: %s \n", ip->ntoa() ); );
+ DEBUG_WRAP( SfIpString ip_str; )
+ DebugFormat(DEBUG_REPUTATION, "Lookup address: %s \n", ip->ntop(ip_str));
if (!config->scanlocal)
{
if (ip->is_private() )
#ifdef DEBUG_MSGS
if (nullptr != sfrt_flat_lookup(ipAddr->get_addr(), config->iplist))
{
- DebugFormat(DEBUG_REPUTATION, "Find address before insert: %s\n", ipAddr->ntoa() );
+ snort::SfIpString ip_str;
+ DebugFormat(DEBUG_REPUTATION, "Find address before insert: %s\n", ipAddr->ntop(ip_str) );
}
else
{
+ snort::SfIpString ip_str;
DebugFormat(DEBUG_REPUTATION,
- "Can't find address before insert: %s\n", ipAddr->ntoa() );
+ "Can't find address before insert: %s\n", ipAddr->ntop(ip_str) );
}
#endif
result = (IPrepInfo*)sfrt_flat_lookup(ipAddr->get_addr(), config->iplist);
if (nullptr != result)
{
- DebugFormat(DEBUG_REPUTATION, "Find address after insert: %s \n", ipAddr->ntoa() );
+ snort::SfIpString ip_str;
+ DebugFormat(DEBUG_REPUTATION, "Find address after insert: %s \n", ipAddr->ntop(ip_str) );
DEBUG_WRAP(ReputationPrintRepInfo(result, (uint8_t*)config->iplist); );
}
#endif
else if (MEM_ALLOC_FAILURE == iRet)
{
iFinalRet = IP_MEM_ALLOC_FAILURE;
+ snort::SfIpString ip_str;
DEBUG_WRAP(DebugFormat(DEBUG_REPUTATION, "Insert error: %d for address: %s \n",iRet,
- ipAddr->ntoa() ); );
+ ipAddr->ntop(ip_str) ); );
}
else
{
iFinalRet = IP_INSERT_FAILURE;
+ snort::SfIpString ip_str;
DEBUG_WRAP(DebugFormat(DEBUG_REPUTATION, "Insert error: %d for address: %s \n",iRet,
- ipAddr->ntoa() ); );
+ ipAddr->ntop(ip_str) ); );
}
usageAfterAdd = sfrt_flat_usage(config->iplist);
{
snort::SfIp dev_ip;
dev_ip.set(&saddr->sin_addr, saddr->sin_family);
- printf("\t%s", dev_ip.ntoa());
+
+ snort::SfIpString ip;
+ printf("\t%s", dev_ip.ntop(ip));
}
else
printf("\tdisabled");
// Encoder Foo
static THREAD_LOCAL PegCount total_rebuilt_pkts = 0;
-static THREAD_LOCAL std::array<uint8_t, Codec::PKT_MAX> s_pkt { { 0 } };
+static THREAD_LOCAL std::array<uint8_t, Codec::PKT_MAX>* s_pkt;
+
+void PacketManager::thread_init()
+{
+ s_pkt = new std::array<uint8_t, Codec::PKT_MAX>{ {0} };
+}
+
+void PacketManager::thread_term()
+{
+ delete s_pkt;
+}
//-------------------------------------------------------------------------
// Private helper functions
TcpResponse type, EncodeFlags flags, const Packet* p, uint32_t& len,
const uint8_t* const payload, uint32_t payload_len)
{
- Buffer buf(s_pkt.data(), s_pkt.size());
+ Buffer buf(s_pkt->data(), s_pkt->size());
switch (type)
{
const uint8_t* PacketManager::encode_reject(UnreachResponse type,
EncodeFlags flags, const Packet* p, uint32_t& len)
{
- Buffer buf(s_pkt.data(), s_pkt.size());
+ Buffer buf(s_pkt->data(), s_pkt->size());
if (p->is_ip4())
{
class SO_PUBLIC PacketManager
{
public:
+ static void thread_init();
+ static void thread_term();
+
// decode this packet and set all relevant packet fields.
static void decode(Packet*, const struct _daq_pkthdr*, const uint8_t*, bool cooked = false);
while ((nullptr != mdataA)&&(nullptr != mdataB))
{
//void *ssn;
-
/* Call into Streams to mark data channel as something to ignore. */
Flow* ssn = Stream::get_flow(
PktType::UDP, IpProtocol::UDP, &mdataA->maddress,
bool fast_cont6(const SfIp& ip) const;
SfIpRet contains(const SfIp* ip) const;
- const char* ntoa() const;
+ const char* ntop(SfIpString) const;
SfIpRet compare(const SfCidr&) const;
private:
return ntohl(addr.get_ip6_ptr()[i]) == needle;
}
-inline const char* SfCidr::ntoa() const
+inline const char* SfCidr::ntop(SfIpString ip_str) const
{
- return addr.ntoa();
+ return addr.ntop(ip_str);
}
inline SfIpRet SfCidr::compare(const SfCidr& cidr2) const
return snort_inet_ntop(family, get_ptr(), buf, bufsize);
}
-/* Uses a static buffer to return a string representation of the IP */
-const char* SfIp::ntoa() const
+const char* SfIp::ntop(SfIpString str) const
{
- static THREAD_LOCAL char buf[INET6_ADDRSTRLEN];
-
- ntop(buf, sizeof(buf));
-
- return buf;
+ return snort_inet_ntop(family, get_ptr(), str, sizeof(SfIpString));
}
bool SfIp::is_mapped() const
namespace snort
{
-struct SfCidr;
+using SfIpString = char[INET6_ADDRSTRLEN];
+struct SfCidr;
struct SO_PUBLIC SfIp
{
/*
bool is_private() const;
const char* ntop(char* buf, int bufsize) const;
- const char* ntoa() const;
+ const char* ntop(SfIpString) const;
void obfuscate(SfCidr* ob);
inline std::ostream& operator<<(std::ostream& os, const SfIp* addr)
{
- char str[INET6_ADDRSTRLEN];
- sfip_ntop(addr, str, sizeof(str));
- os << str;
- return os;
+ SfIpString str;
+ return os << addr->ntop(str);
}
// FIXIT-L X This should be in utils_net if anywhere, but that makes it way harder to link into unit tests
if (p->flags & SFIP_ANY)
n += safe_snprintf(sfipvar_test_buff+n, SFIPVAR_TEST_BUFF_LEN - n, "any");
else if (p->flags & SFIP_NEGATED)
- n += safe_snprintf(sfipvar_test_buff+n, SFIPVAR_TEST_BUFF_LEN - n, "!%s",p->ip->ntoa());
+ {
+ SfIpString ip_str;
+ n += safe_snprintf(sfipvar_test_buff+n, SFIPVAR_TEST_BUFF_LEN - n, "!%s",p->ip->ntop(ip_str));
+ }
else
- n += safe_snprintf(sfipvar_test_buff+n, SFIPVAR_TEST_BUFF_LEN - n, "%s", p->ip->ntoa());
+ {
+ SfIpString ip_str;
+ n += safe_snprintf(sfipvar_test_buff+n, SFIPVAR_TEST_BUFF_LEN - n, "%s", p->ip->ntop(ip_str));
+ }
if (print_bits and !(p->flags & SFIP_ANY))
n += safe_snprintf(sfipvar_test_buff+n, SFIPVAR_TEST_BUFF_LEN - n, "/%d",
if ( s_debug )
{
- printf("Insert IP addr: %s, family: %d\n", ip.get_addr()->ntoa(), ip.get_family());
+ SfIpString ip_str;
+ printf("Insert IP addr: %s, family: %d\n", ip.get_addr()->ntop(ip_str), ip.get_family());
}
CHECK(sfrt_insert(&ip, ip.get_bits(), &(ip_entry->value), RT_FAVOR_TIME, dir) ==
RT_SUCCESS); // "sfrt_insert()"
if ( s_debug )
{
- printf("Lookup IP addr: %s, family: %d\n", ip2.ntoa(), ip2.get_family());
+ SfIpString ip_str;
+ printf("Lookup IP addr: %s, family: %d\n", ip2.ntop(ip_str), ip2.get_family());
}
result = (int*)sfrt_lookup(&ip2, dir);
if ( s_debug )
if ( s_debug )
{
- printf("IP addr: %s, family: %d\n", ip.get_addr()->ntoa(), ip.get_family());
+ SfIpString ip_str;
+ printf("IP addr: %s, family: %d\n", ip.get_addr()->ntop(ip_str), ip.get_family());
printf("value input: %d, output: %d\n", ip_entry->value, *result);
}
/* D A T A S T R U C T U R E S **********************************/
+
struct Fragment
{
- uint8_t* data; /* ptr to adjusted start position */
- uint16_t size; /* adjusted frag size */
- uint16_t offset; /* adjusted offset position */
+ Fragment(uint16_t flen, const uint8_t* fptr, int ord)
+ { init(flen, fptr, ord); }
+
+ Fragment(Fragment* other, int ord)
+ {
+ init(other->flen, other->fptr, ord);
+ data = fptr + (other->data - other->fptr);
+ size = other->size;
+ offset = other->offset;
+ last = other->last;
+ }
+
+ ~Fragment()
+ {
+ if ( fptr )
+ delete fptr;
+
+ ip_stats.nodes_released++;
+ }
+
+ uint8_t* data = nullptr; /* ptr to adjusted start position */
+ uint16_t size = 0; /* adjusted frag size */
+ uint16_t offset = 0; /* adjusted offset position */
- uint8_t* fptr; /* free pointer */
- uint16_t flen; /* free len, unneeded? */
+ uint8_t* fptr = nullptr; /* free pointer */
+ uint16_t flen = 0; /* free len, unneeded? */
- Fragment* prev;
- Fragment* next;
+ Fragment* prev = nullptr;
+ Fragment* next = nullptr;
- int ord;
- char last;
+ int ord = 0;
+ char last = 0;
+
+private:
+ inline void init(uint16_t flen, const uint8_t* fptr, int ord)
+ {
+ this->flen = flen;
+ this->fptr = new uint8_t[flen];
+ this->ord = ord;
+
+ memcpy(this->fptr, fptr, flen);
+
+ ip_stats.nodes_created++;
+ }
};
/* G L O B A L S **************************************************/
"SOLARIS"
};
-// FIXIT-M convert to session memcap
-static THREAD_LOCAL unsigned long mem_in_use = 0; /* memory in use, used for self pres */
-
THREAD_LOCAL ProfileStats fragPerfStats;
THREAD_LOCAL ProfileStats fragInsertPerfStats;
THREAD_LOCAL ProfileStats fragRebuildPerfStats;
ft->fraglist_count++;
}
-static void delete_frag(Fragment* frag)
-{
- /*
- * delete the fragment either in prealloc or dynamic mode
- */
- snort_free(frag->fptr);
- mem_in_use -= frag->flen;
-
- snort_free(frag);
- mem_in_use -= sizeof(Fragment);
-
- ip_stats.mem_in_use = mem_in_use;
- ip_stats.nodes_released++;
-}
-
static inline void delete_node(FragTracker* ft, Fragment* node)
{
trace_logf(stream_ip, "Deleting list node %p (p %p n %p)\n",
ft->fraglist_tail = node->prev;
}
- delete_frag(node);
+ delete node;
ft->fraglist_count--;
}
{
dump_me = idx;
idx = idx->next;
- delete_frag(dump_me);
+ delete dump_me;
}
ft->fraglist = nullptr;
if (ft->ip_options_data)
ft->frag_policy = p->flow->ssn_policy ? p->flow->ssn_policy : engine.frag_policy;
ft->engine = &engine;
- /*
- * get our first fragment storage struct
- */
- {
- f = (Fragment*)snort_calloc(sizeof(Fragment));
- mem_in_use += sizeof(Fragment);
-
- f->fptr = (uint8_t*)snort_calloc(fragLength);
- mem_in_use += fragLength;
-
- ip_stats.mem_in_use = mem_in_use;
- }
-
- ip_stats.nodes_created++;
-
/* initialize the fragment list */
ft->fraglist = nullptr;
- /*
- * setup the Fragment struct with the current packet's data
- */
- memcpy(f->fptr, fragStart, fragLength);
+ f = new Fragment(fragLength, fragStart, ft->ordinal++);
- f->size = f->flen = fragLength;
+ f->size = fragLength;
f->offset = frag_off;
- frag_end = f->offset + fragLength;
- f->ord = ft->ordinal++;
f->data = f->fptr; /* ptr to adjusted start position */
+
+ frag_end = f->offset + fragLength;
if (!(p->ptrs.decode_flags & DECODE_MF))
{
f->last = 1;
return FRAG_INSERT_ANOMALY;
}
- /*
- * grab/generate a new frag node
- */
- {
- /*
- * build a frag struct to track this particular fragment
- */
- newfrag = (Fragment*)snort_calloc(sizeof(Fragment));
- mem_in_use += sizeof(Fragment);
-
- /*
- * allocate some space to hold the actual data
- */
- newfrag->fptr = (uint8_t*)snort_calloc(fragLength);
- mem_in_use += fragLength;
-
- ip_stats.mem_in_use = mem_in_use;
- }
-
- ip_stats.nodes_created++;
-
- newfrag->flen = fragLength;
- memcpy(newfrag->fptr, fragStart, fragLength);
- newfrag->ord = ft->ordinal++;
+ newfrag = new Fragment(fragLength, fragStart, ft->ordinal++);
/*
* twiddle the frag values for overlaps
*/
int Defrag::dup_frag_node( FragTracker* ft, Fragment* left, Fragment** retFrag)
{
- Fragment* newfrag = nullptr; /* new frag container */
+ Fragment* newfrag = new Fragment(left, ft->ordinal++);
- /*
- * grab/generate a new frag node
- */
- {
- /*
- * build a frag struct to track this particular fragment
- */
- newfrag = (Fragment*)snort_calloc(sizeof(Fragment));
- mem_in_use += sizeof(Fragment);
-
- /*
- * allocate some space to hold the actual data
- */
- newfrag->fptr = (uint8_t*)snort_calloc(left->flen);
- mem_in_use += left->flen;
-
- ip_stats.mem_in_use = mem_in_use;
- }
-
- ip_stats.nodes_created++;
-
- newfrag->ord = ft->ordinal++;
- /*
- * twiddle the frag values for overlaps
- */
- newfrag->flen = left->flen;
- memcpy(newfrag->fptr, left->fptr, newfrag->flen);
- newfrag->data = newfrag->fptr + (left->data - left->fptr);
- newfrag->size = left->size;
- newfrag->offset = left->offset;
- newfrag->last = left->last;
-
- /*
- * insert the new frag into the list
- */
add_node(ft, left, newfrag);
trace_logf(stream_ip,
PegCount trackers_completed;// iFragComplete
PegCount nodes_created; // iFragInserts tracked a similar stat (# calls to insert)
PegCount nodes_released;
- PegCount mem_in_use; // frag_mem_in_use
PegCount reassembled_bytes; // total_ipreassembled_bytes
PegCount fragmented_bytes; // total_ipfragmented_bytes
};
{ CountType::SUM, "trackers_completed", "datagram trackers completed" },
{ CountType::SUM, "nodes_inserted", "fragments added to tracker" },
{ CountType::SUM, "nodes_deleted", "fragments deleted from tracker" },
- { CountType::NOW, "memory_used", "current memory usage in bytes" },
{ CountType::SUM, "reassembled_bytes", "total reassembled bytes" },
{ CountType::SUM, "fragmented_bytes", "total fragmented bytes" },
{ CountType::END, nullptr, nullptr }
if (!host)
return;
+ SfIpString ip_str;
DebugFormat(DEBUG_ATTRIBUTE, "Host IP: %s/%d\n",
- host->ipAddr.ntoa(),
+ host->ipAddr.ntop(ip_str),
host->ipAddr.get_bits());
DebugFormat(DEBUG_ATTRIBUTE,
#define ANY '\0'
-typedef enum
+enum ActionPNorm
{
PNORM_ACT_DQUOTES,
PNORM_ACT_NOP,
PNORM_ACT_SPACE,
PNORM_ACT_SQUOTES,
PNORM_ACT_WITHIN_QUOTES
-} ActionPNorm;
+};
// Actions for SFCC
-typedef enum
+enum ActionSFCC
{
SFCC_ACT_COMMA,
SFCC_ACT_DEC,
SFCC_ACT_OCT,
SFCC_ACT_QUIT,
SFCC_ACT_SPACE
-} ActionSFCC;
+};
// Actions for Unescape
-typedef enum
+enum ActionUnsc
{
UNESC_ACT_BACKSLASH,
UNESC_ACT_CONV,
UNESC_ACT_UBACKSLASH,
UNESC_ACT_UPERCENT,
UNESC_ACT_UNESCAPE
-} ActionUnsc;
+};
// Actions for Javascript norm
-typedef enum
+enum ActionJSNorm
{
ACT_NOP,
ACT_QUIT,
ACT_SFCC,
ACT_SPACE,
ACT_UNESCAPE
-} ActionJSNorm;
+};
static const int hex_lookup[256] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
-static THREAD_LOCAL char decoded_out[65535];
-
-typedef struct
+struct JSNorm
{
uint8_t state;
uint8_t event;
uint8_t match;
uint8_t other;
uint8_t action;
-} JSNorm;
+};
-typedef struct
+struct Dbuf
{
char* data;
uint16_t size;
uint16_t len;
-}Dbuf;
+};
-typedef struct
+struct PNormState
{
uint8_t fsm;
uint8_t fsm_other;
uint16_t num_spaces;
char* overwrite;
Dbuf output;
-}PNormState;
+};
-typedef struct
+struct SFCCState
{
uint8_t fsm;
uint8_t buf[MAX_BUF];
uint16_t cur_flags;
uint16_t alert_flags;
Dbuf output;
-} SFCCState;
+};
-typedef struct
+struct JSNormState
{
uint8_t fsm;
uint8_t prev_event;
uint8_t* unicode_map;
char* overwrite;
Dbuf dest;
-} JSNormState;
+};
-typedef struct
+struct UnescapeState
{
uint8_t fsm;
uint8_t multiple_levels;
char* overwrite;
ActionUnsc prev_action;
Dbuf output;
-} UnescapeState;
+};
// STATES for SFCC
#define S0 0
{ Z6+ 0, ANY, Z0+ 0, Z0+ 0, ACT_NOP }
};
-static void UnescapeDecode(const char*, uint16_t, const char**, char**, uint16_t*, JSState*, uint8_t*);
+static void UnescapeDecode(const char* src, uint16_t srclen, const char** ptr, char** dst, size_t dst_len,
+ uint16_t* bytes_copied, JSState* js, uint8_t* iis_unicode_map);
static inline int outBounds(const char* start, const char* end, const char* ptr)
{
}
static void StringFromCharCodeDecode(
- const char* src, uint16_t srclen, const char** ptr, char** dst,
+ const char* src, uint16_t srclen, const char** ptr, char** dst, size_t dst_len,
uint16_t* bytes_copied, JSState* js, uint8_t* iis_unicode_map)
{
const char* start = src;
SFCCState s;
s.buflen = 0;
s.fsm = 0;
- s.output.data = decoded_out;
- s.output.size = sizeof(decoded_out);
+ s.output.data = *dst;
+ s.output.size = dst_len;
s.output.len = 0;
s.cur_flags = s.alert_flags = 0;
{
js->alerts |= ALERT_MIXED_ENCODINGS;
}
- UnescapeDecode(s.output.data, s.output.len, (const char**)&(s.output.data), &(s.output.data),
- &(s.output.len), js, iis_unicode_map);
+ UnescapeDecode(s.output.data, s.output.len, (const char**)&(s.output.data), &s.output.data,
+ s.output.size, &(s.output.len), js, iis_unicode_map);
- *dst = s.output.data;
*bytes_copied = s.output.len;
}
return(Unescape_exec(s, (ActionUnsc)m->action, c, js));
}
-static void UnescapeDecode(const char* src, uint16_t srclen, const char** ptr, char** dst, uint16_t* bytes_copied,
- JSState* js, uint8_t* iis_unicode_map)
+static void UnescapeDecode(const char* src, uint16_t srclen, const char** ptr, char** dst, size_t dst_len,
+ uint16_t* bytes_copied, JSState* js, uint8_t* iis_unicode_map)
{
const char* start = src;
const char* end = src + srclen;
UnescapeState s;
s.iNorm = 0;
s.fsm = 0;
- s.output.data = decoded_out;
- s.output.size = sizeof(decoded_out);
+ s.output.data = *dst;
+ s.output.size = dst_len;
s.output.len = 0;
s.alert_flags = 0;
s.prev_event = 0;
}
PNormDecode(s.output.data, s.output.len, s.output.data, s.output.len, bytes_copied, js);
- *dst = s.output.data;
//*bytes_copied = s.output.len;
}
char* cur_ptr;
int iRet = RET_OK;
uint16_t bcopied = 0;
- char* dest;
+ // FIXIT-M this is large for stack. Move elsewhere.
+ char decoded_out[65535];
+ char* dest = decoded_out;
+
cur_ptr = s->dest.data+ s->dest.len;
switch (a)
{
{
s->dest.len = s->overwrite - s->dest.data;
}
- UnescapeDecode(src, srclen, ptr, &dest, &bcopied, js, s->unicode_map);
+ UnescapeDecode(src, srclen, ptr, &dest, sizeof(decoded_out), &bcopied, js, s->unicode_map);
WriteJSNorm(s, dest, bcopied, js);
break;
case ACT_SFCC:
{
s->dest.len = s->overwrite - s->dest.data;
}
- StringFromCharCodeDecode(src, srclen, ptr, &dest, &bcopied, js, s->unicode_map);
+ StringFromCharCodeDecode(src, srclen, ptr, &dest, sizeof(decoded_out), &bcopied, js, s->unicode_map);
WriteJSNorm(s, dest, bcopied, js);
break;
case ACT_QUIT:
#define MAX_ALLOWED_OBFUSCATION 1
-typedef struct
+struct JSState
{
int allowed_spaces;
int allowed_levels;
uint16_t alerts;
-} JSState;
+};
SO_PUBLIC int JSNormalizeDecode(
const char*, uint16_t, char*, uint16_t destlen, const char**, int*, JSState*, uint8_t*);
tmp.obfuscate(&obfunet);
}
- const char* tmp_buf = tmp.ntoa();
- SnortSnprintf(ab, sizeof(ab), "%s", tmp_buf);
+ SfIpString ip_str;
+ SnortSnprintf(ab, sizeof(ab), "%s", tmp.ntop(ip_str));
}
return ab;