Pending - build 142
+-- make all warnings optional
+-- fix ip and tcp policy defines
-- fix ip and icmp flow client/server ip init
-- added logging examples to usage
==== Headers
* Don't hesitate to create a new header if it is needed. Don't lump
- unrelated stuff into a header because it is convenient.
+ unrelated stuff into an header because it is convenient.
* Write header guards like this (leading underscores are reserved for
system stuff). In my_header.h:
* Includes from a different directory should specify parent directory.
This makes it clear exactly what is included and avoids the primordial
- soup that results from using -I this -I that -I the-other-thing ... .
+ soup that results from using -I this -I that -I the_other_thing ... .
// given:
src/foo/foo.cc
to reformat legacy code and anything that happens to need a makeover at
some point.
-The working config is crusty.cfg in the top level directory. It does well,
+The working config is crusty.cfg in the top level directory. It does well
but will munge some things. Specially formatted INDENT-OFF comments were
added in 2 places to avoid a real mess.
snort --markup --help-options rule
-NOTE: Snort++ stops reading command-line options after the "--help-*" and "--list-*" options,
-so any other options should be placed before them.
+NOTE: Snort++ stops reading command-line options after the "--help-*" and
+"--list-*" options, so any other options should be placed before them.
==== Sniffing and Logging
snort -r /path/to/my.pcap -K text -d -e
-NOTE: Command line options must be specified separately. "snort -de" won't work.
-You can still concatenate options and their arguments, however, so "snort -Ktext" will work.
+NOTE: Command line options must be specified separately. "snort -de" won't
+work. You can still concatenate options and their arguments, however, so
+"snort -Ktext" will work.
Dump packets from all pcaps in a directory:
NOTE: The "--lua" option can be specified multiple times.
-Run Snort++ in IDS mode on an entire directory of pcaps, processing each input source on a separate thread:
+Run Snort++ in IDS mode on an entire directory of pcaps, processing each
+input source on a separate thread:
snort -c $my_path/etc/snort/snort.lua --pcap-dir /path/to/pcap/dir \
--pcap-filter '*.pcap' --max-packet-threads 8
+=== Plugins
+
+Load external plugins and use the "ex" alert:
+
+ snort -c $my_path/etc/snort/snort.lua \
+ --plugin-path $my_path/lib/snort_extra \
+ -A alert_ex -r /path/to/my.pcap
+
+Test the LuaJIT rule option 'find' loaded from stdin:
+
+ snort -c $my_path/etc/snort/snort.lua \
+ --script-path $my_path/lib/snort_extra \
+ --stdin-rules -A cmg -r /path/to/my.pcap << END
+ alert tcp any any -> any 80 (
+ sid:3; msg:"found"; content:"GET";
+ find:"pat='HTTP/1%.%d'" ; )
+ END
+
+
=== Output Files
To make it simple to configure outputs when you run with multiple packet
{
if (raw.len < icmp::ICMP6_HEADER_MIN_LEN)
{
- DEBUG_WRAP(DebugMessage(DEBUG_DECODE,
- "WARNING: Truncated ICMP6 header (%d bytes).\n", raw.len); );
-
codec_event(codec, DECODE_ICMP6_HDR_TRUNC);
return false;
}
/* do a little validation */
if (raw.len < ip::IP4_HEADER_LEN)
{
- DEBUG_WRAP(DebugMessage(DEBUG_DECODE,
- "WARNING: Truncated IP4 header (%d bytes).\n", raw.len); );
-
if ((codec.codec_flags & CODEC_UNSURE_ENCAP) == 0)
codec_event(codec, DECODE_IP4_HDR_TRUNC);
return false;
void fpSetMaxPatternLen(FastPatternConfig* fp, unsigned int max_len)
{
if (fp->max_pattern_len != 0)
- ParseWarning("maximum pattern length redefined from %d to %d.\n",
+ ParseWarning(WARN_CONF, "maximum pattern length redefined from %d to %d.\n",
fp->max_pattern_len, max_len);
fp->max_pattern_len = max_len;
if ( tmp->fp )
{
if ( pmd )
- ParseWarning("only one fast_pattern content per rule allowed - ignored");
+ ParseWarning(WARN_RULES,
+ "only one fast_pattern content per rule allowed - ignored");
else if ( !pmd_can_be_fp(tmp, curr_cat) )
- ParseWarning("content ineligible for fast_pattern matcher - ignored");
+ ParseWarning(WARN_RULES,
+ "content ineligible for fast_pattern matcher - ignored");
else
pmd = tmp;
FatalError("Could not AddProtocolReference\n");
else if ( id >= MAX_PROTOCOL_ORDINAL )
- ParseWarning("protocol-ordinal=%d exceeds "
+ ParseWarning(WARN_RULES, "protocol-ordinal=%d exceeds "
"limit of %d for service=%s\n",id,MAX_PROTOCOL_ORDINAL,srvc);
}
else if ( id > 0 )
/* dup check */
if (strcasecmp(current->type, type) == 0)
{
- ParseWarning(
+ ParseWarning(WARN_CONF,
"Duplicate classification \"%s\""
"found, ignoring this line", type);
return;
{
decode_depth = decode_depth - 4;
}
- ParseWarning(
+ ParseWarning(WARN_CONF,
"%s: 'b64_decode_depth' is not a multiple of 4. "
"Rounding up to the next multiple of 4. The new 'b64_decode_depth' is %d.\n",
preproc_name, decode_depth);
}
else if (check_needed && (SIG_IGN != pre_handler) && (SIG_DFL!= pre_handler))
{
- ParseWarning("handler is already installed for signal %d.\n", sig);
+ ParseWarning(WARN_CONF, "handler is already installed for signal %d.\n", sig);
}
return 1;
}
{ "fast_pattern_offset", Parameter::PT_INT, nullptr, nullptr,
"number of leading characters of this content the fast pattern matcher should exclude" },
- { "fast_pattern_length", Parameter::PT_INT, nullptr, nullptr,
+ { "fast_pattern_length", Parameter::PT_INT, "1:", nullptr,
"maximum number of characters from this content the fast pattern matcher should use" },
{ "offset", Parameter::PT_STRING, nullptr, nullptr,
if ((fb->set > 0) && (fb->isset == 0))
{
- if ( snort_conf->logging_flags & LOGGING_FLAG__WARN_FLOWBITS )
- ParseWarning("flowbits key '%s' is set but not checked.", (char*)n->key);
+ ParseWarning(WARN_FLOWBITS, "flowbits key '%s' is set but not checked.",
+ (char*)n->key);
unchecked++;
}
else if ((fb->isset > 0) && (fb->set == 0))
{
- if ( snort_conf->logging_flags & LOGGING_FLAG__WARN_FLOWBITS )
- ParseWarning("flowbits key '%s' is checked but not ever set.", (char*)n->key);
+ ParseWarning(WARN_FLOWBITS, "flowbits key '%s' is checked but not ever set.",
+ (char*)n->key);
unset++;
}
else if ((fb->set == 0) && (fb->isset == 0))
{
if ( !warned )
{
- ParseWarning("payload replacements disabled because DAQ "
+ ParseWarning(WARN_DAQ, "payload replacements disabled because DAQ "
" can't replace packets.\n");
warned = 1;
}
// hosts module
//-------------------------------------------------------------------------
-// FIXIT-L these are cloned from ip_module.cc and tcp_module.cc
-
-#define ip_policies \
- "unknown | first | linux | bsd | bsd_right |last | windows | solaris"
-
-#define tcp_policies \
- "unknown | first | last | bsd | linux | old-linux | windows | win-2003 | " \
- "vista | solaris | hpux | hpux10 | irix | macos"
-
static const Parameter service_params[] =
{
{ "name", Parameter::PT_STRING, nullptr, nullptr,
{ "ip", Parameter::PT_ADDR, nullptr, "0.0.0.0/32",
"hosts address / cidr" },
- { "frag_policy", Parameter::PT_ENUM, ip_policies, "linux",
+ { "frag_policy", Parameter::PT_ENUM, IP_POLICIES, IP_POLICY_DEFAULT,
"defragmentation policy" },
- { "tcp_policy", Parameter::PT_ENUM, tcp_policies, "linux",
+ { "tcp_policy", Parameter::PT_ENUM, TCP_POLICIES, TCP_POLICY_DEFAULT,
"tcp reassembly policy" },
{ "services", Parameter::PT_LIST, service_params, nullptr,
else if ( v.is("frag_policy") )
{
- host->hostInfo.fragPolicy = v.get_long();
+ host->hostInfo.fragPolicy = v.get_long() + 1;
}
else if ( v.is("tcp_policy") )
{
- host->hostInfo.streamPolicy = v.get_long();
+ host->hostInfo.streamPolicy = v.get_long() + 1;
}
else if ( v.is("name") )
app->protocol = AddProtocolReference(v.get_string());
LOGGING_FLAG__QUIET = 0x00000002, /* -q */
LOGGING_FLAG__SYSLOG = 0x00000004, /* -M */
LOGGING_FLAG__SHOW_PLUGINS = 0x00000008, // --show-plugins
- LOGGING_FLAG__WARN_FLOWBITS = 0x00000010, // --warn-flowbits
- LOGGING_FLAG__WARN_UNKNOWN = 0x00000020, // --warn-unknown
};
enum TunnelFlags
else if (!ScAdapterInlineMode())
{
- ParseWarning("adapter is in passive mode; switching policy mode to tap.");
+ ParseWarning(WARN_DAQ, "adapter is in passive mode; switching policy mode to tap.");
p->policy_mode = POLICY_MODE__PASSIVE;
}
break;
//------------------------------------------------------
// output module stuff
- int output_flags;
- int logging_flags;
+ uint32_t output_flags;
+ uint32_t logging_flags;
+ uint32_t warning_flags;
uint8_t log_ipv6_extra;
uint16_t event_trace_max;
"<filter options> are standard BPF options, as seen in TCPDump" },
{ "--c2x", Parameter::PT_STRING, nullptr, nullptr,
- "output hex for given char" },
+ "output hex for given char (see also --x2c)" },
{ "--create-pidfile", Parameter::PT_IMPLIED, nullptr, nullptr,
"create PID file, even when not in Daemon mode" },
{ "--warn-all", Parameter::PT_IMPLIED, nullptr, nullptr,
"enable all warnings" },
+ { "--warn-conf", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "warn about configuration issues" },
+
+ { "--warn-daq", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "warn about DAQ issues, usually related to mode" },
+
{ "--warn-flowbits", Parameter::PT_IMPLIED, nullptr, nullptr,
"warn about flowbits that are checked but not set and vice-versa" },
- { "--warn-unknown", Parameter::PT_IMPLIED, nullptr, nullptr,
- "warn about unknown symbols in your config" },
+ { "--warn-hosts", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "warn about host table issues" },
+
+ { "--warn-rules", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "warn about duplicate rules and rule parsing issues" },
+
+ { "--warn-scripts", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "warn about issues discovered while processing Lua scripts" },
+
+ { "--warn-symbols", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "warn about unknown symbols in your Lua config" },
+
+ { "--warn-vars", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "warn about variable definition and usage issues" },
{ "--x2c", Parameter::PT_INT, nullptr, nullptr,
- "output ASCII char for given hex" },
+ "output ASCII char for given hex (see also --c2x)" },
{ nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
};
help_version(sc, v.get_string());
else if ( v.is("--warn-all") )
- {
- sc->logging_flags |= LOGGING_FLAG__WARN_FLOWBITS;
- sc->logging_flags |= LOGGING_FLAG__WARN_UNKNOWN;
- }
+ sc->warning_flags = 0xFFFFFFFF;
+
+ else if ( v.is("--warn-conf") )
+ sc->warning_flags |= (1 << WARN_CONF);
+
+ else if ( v.is("--warn-daq") )
+ sc->warning_flags |= (1 << WARN_DAQ);
+
else if ( v.is("--warn-flowbits") )
- sc->logging_flags |= LOGGING_FLAG__WARN_FLOWBITS;
+ sc->warning_flags |= (1 << WARN_FLOWBITS);
+
+ else if ( v.is("--warn-hosts") )
+ sc->warning_flags |= (1 << WARN_HOSTS);
+
+ else if ( v.is("--warn-rules") )
+ sc->warning_flags |= (1 << WARN_RULES);
+
+ else if ( v.is("--warn-scripts") )
+ sc->warning_flags |= (1 << WARN_SCRIPTS);
+
+ else if ( v.is("--warn-symbols") )
+ sc->warning_flags |= (1 << WARN_SYMBOLS);
- else if ( v.is("--warn-unknown") )
- sc->logging_flags |= LOGGING_FLAG__WARN_UNKNOWN;
+ else if ( v.is("--warn-vars") )
+ sc->warning_flags |= (1 << WARN_VARS);
else if ( v.is("--x2c") )
x2c(v.get_long());
{
static const char* ignore = nullptr;
- if ( !(snort_conf->logging_flags & LOGGING_FLAG__WARN_UNKNOWN) )
- return true;
-
if ( !ignore )
{
ignore = getenv("SNORT_IGNORE");
bool found = set_var(fqn, v);
if ( !found && !ignored(fqn) )
- ParseWarning("uknown symbol %s", fqn);
+ ParseWarning(WARN_SYMBOLS, "uknown symbol %s", fqn);
return found;
}
if ( !lua_isnumber(L, -1) )
{
- ParseWarning("%s is not a number", key);
+ ParseWarning(WARN_SCRIPTS, "%s is not a number", key);
lua_pop(L, 1);
return false;
}
if ( !lua_isstring(L, -1) )
{
- ParseWarning("%s is not a string", key);
+ ParseWarning(WARN_SCRIPTS, "%s is not a string", key);
lua_pop(L, 1);
return false;
}
if ( luaL_loadfile(L, f) )
{
- ParseWarning("can't load %s: %s", f, lua_tostring(L, -1));
+ ParseWarning(WARN_SCRIPTS, "can't load %s: %s", f, lua_tostring(L, -1));
return;
}
if ( lua_pcall(L, 0, 0, 0) )
{
- ParseWarning("can't init %s: %s", f, lua_tostring(L, -1));
+ ParseWarning(WARN_SCRIPTS, "can't init %s: %s", f, lua_tostring(L, -1));
return;
}
if ( !lua_istable(L, -1) )
{
- ParseWarning("can't get plugin from %s", f);
+ ParseWarning(WARN_SCRIPTS, "can't get plugin from %s", f);
return;
}
// FIXIT-L norm needs a nap policy mode
if ( mode == POLICY_MODE__PASSIVE )
{
- ParseWarning("normalizations disabled because not inline.");
+ ParseWarning(WARN_DAQ, "normalizations disabled because not inline.");
config.normalizer_flags = 0;
return true;
}
{
if ( ScReadMode() || Active_Open(sc->respond_device) )
{
- ParseWarning("active responses disabled since DAQ "
+ ParseWarning(WARN_DAQ, "active responses disabled since DAQ "
"can't inject packets.");
#ifndef REG_TEST
s_attempts = 0;
return 1;
if ( !(caps & DAQ_CAPA_BLOCK) )
- ParseWarning("inline mode configured but DAQ can't block packets.\n");
+ ParseWarning(WARN_DAQ, "inline mode configured but DAQ can't block packets.\n");
#if 0
// this is checked in normalize.c and sp_respond.c
// and warned/disabled only if it was configured
if ( !(caps & DAQ_CAPA_REPLACE) )
{
- ParseWarning("normalizations/replacements disabled "
+ ParseWarning(WARN_DAQ, "normalizations/replacements disabled "
" because DAQ can't replace packets.\n");
}
// this is checked in spp_stream.c and active.c
// and warned/disabled only if it was configured
if ( !(caps & DAQ_CAPA_INJECT) )
- ParseWarning("inline mode configured but DAQ can't "
+ ParseWarning(WARN_DAQ, "inline mode configured but DAQ can't "
"inject packets.\n");
#endif
return;
case SFIP_DUPLICATE:
- ParseWarning("Var '%s' redefined.", var);
+ ParseWarning(WARN_VARS, "Var '%s' redefined.", var);
break;
case SFIP_CONFLICT:
//OTN is for new policy group, salvage RTN
deleteRtnFromOtn(otn_new);
- ParseWarning(
+ ParseWarning(WARN_RULES,
"%d:%d duplicates previous rule. Using revision %d.",
otn_cur->sigInfo.generator, otn_cur->sigInfo.id, otn_cur->sigInfo.rev);
}
else
{
- ParseWarning(
+ ParseWarning(WARN_RULES,
"%d:%d duplicates previous rule. Using revision %d.",
otn_new->sigInfo.generator, otn_new->sigInfo.id, otn_new->sigInfo.rev);
}
else if ( c == '\\' )
state = esc ? 4 : 16;
else if ( c == '\n' )
- ParseWarning("line break in string on line %d\n", lines-1);
+ ParseWarning(WARN_RULES, "line break in string on line %d\n", lines-1);
else
s += c;
break;
break;
case 5: // unquoted escape
if ( c != '\n' && c != '\r' )
- ParseWarning("invalid escape on line %d\n", lines);
+ ParseWarning(WARN_RULES, "invalid escape on line %d\n", lines);
state = 0;
break;
case 6: // token
state = 11;
else if ( c == '\n' )
{
- ParseWarning("line break in commented string on line %d\n", lines-1);
+ ParseWarning(WARN_RULES, "line break in commented string on line %d\n", lines-1);
state = 11;
}
break;
}
else
{
- ParseWarning("\\x used with no following hex digits", lines-1);
+ ParseWarning(WARN_RULES, "\\x used with no following hex digits", lines-1);
s += c;
state = 3;
}
SnortConfig* sc = SnortConfNew();
sc->logging_flags = boot_conf->logging_flags;
+ sc->warning_flags = boot_conf->warning_flags;
VarNode* tmp = boot_conf->var_list;
const char* fname = get_snort_conf();
parse_errors++;
}
-void ParseWarning(const char* format, ...)
+void ParseWarning(WarningGroup wg, const char* format, ...)
{
+ if ( !(snort_conf->warning_flags & (1 << wg)) )
+ return;
+
char buf[STD_BUF+1];
va_list ap;
SO_PUBLIC NORETURN void ParseAbort(const char*, ...);
SO_PUBLIC void ParseError(const char*, ...);
-SO_PUBLIC void ParseWarning(const char*, ...);
SO_PUBLIC void ParseMessage(const char*, ...);
+enum WarningGroup
+{
+ WARN_DAQ, WARN_CONF, WARN_VARS, WARN_SYMBOLS, WARN_SCRIPTS,
+ WARN_HOSTS, WARN_RULES, WARN_FLOWBITS, WARN_MAX
+};
+
+SO_PUBLIC void ParseWarning(WarningGroup, const char*, ...);
+
int ParseBool(const char* arg);
int addRtnToOtn(struct OptTreeNode*, RuleTreeNode*);
}
else if ( rstat > 0 )
{
- ParseWarning("PortVar '%s', already defined.", po->name);
+ ParseWarning(WARN_VARS, "PortVar '%s', already defined.", po->name);
}
#if 0
break;
case SFIP_DUPLICATE:
- ParseWarning("Var '%s' redefined.", name);
+ ParseWarning(WARN_VARS, "Var '%s' redefined.", name);
break;
case SFIP_CONFLICT:
free(p->value);
p->value = SnortStrdup(value);
- ParseWarning("Var '%s' redefined\n", p->name);
+ ParseWarning(WARN_VARS, "Var '%s' redefined\n", p->name);
return p;
}
if ((telnet_config->ayt_threshold > 0) &&
!telnet_config->normalize)
{
- ParseWarning("telnet configuration check: using an "
+ ParseWarning(WARN_CONF, "telnet configuration check: using an "
"AreYouThere threshold requires telnet normalization to be "
"turned on.\n");
}
if ( telnet_config->detect_encrypted &&
!telnet_config->normalize)
{
- ParseWarning("telnet configuration check: checking for "
+ ParseWarning(WARN_CONF, "telnet configuration check: checking for "
"encrypted traffic requires telnet normalization to be turned on.\n");
}
// stream_ip module
//-------------------------------------------------------------------------
-// sequence must match FRAG_POLICY_* enum
-#define policies \
- "first | linux | bsd | bsd_right | last | windows | solaris"
-
static const RuleMap stream_ip_rules[] =
{
{ DEFRAG_IPOPTIONS, DEFRAG_IPOPTIONS_STR },
{ "min_ttl", Parameter::PT_INT, "1:255", "1",
"discard fragments with ttl below the minimum" },
- { "policy", Parameter::PT_ENUM, policies, "linux",
+ { "policy", Parameter::PT_ENUM, IP_POLICIES, IP_POLICY_DEFAULT,
"fragment reassembly policy" },
{ "session_timeout", Parameter::PT_INT, "1:86400", "30",
#include "flow/flow.h"
/* engine-based defragmentation policy enums */
-// must update parameter in defrag_module.cc if this changes
+// must update stream_api.h::IP_POLICIES if this changes
enum
{
FRAG_POLICY_FIRST = 1,
#define SSN_DIR_FROM_RESPONDER 0x02
#define SSN_DIR_BOTH 0x03
+// sequence must match FRAG_POLICY_* enum in stream_ip.h (1-based)
+#define IP_POLICIES \
+ "first | linux | bsd | bsd-right | last | windows | solaris"
+
+// sequence must match STREAM_POLICY_* defines in tcp_session.cc (1-based)
+#define TCP_POLICIES \
+ "first | last | linux | old-linux | bsd | macos | solaris | irix | " \
+ "hpux11 | hpux10 | windows | win-2003 | vista | proxy"
+
+#define IP_POLICY_DEFAULT "linux"
+#define TCP_POLICY_DEFAULT "bsd"
+
class Flow;
typedef int (* LogFunction)(Flow*, uint8_t** buf, uint32_t* len, uint32_t* type);
#define STREAM_TCP_NO_3WHS_STR \
"TCP session without 3-way handshake"
-// sequence must match STREAM_POLICY_* and REASSEMBLY_POLICY_* defines
-#define policies \
- "first | last | linux | old-linux | bsd | macos | solaris | irix | " \
- "hpux | hpux10 | windows | win-2003 | vista | proxy"
-
static const Parameter stream_tcp_small_params[] =
{
{ "count", Parameter::PT_INT, "0:2048", "0",
{ "max_pdu", Parameter::PT_INT, "1460:63780", "16384",
"maximum reassembled PDU size" },
- { "policy", Parameter::PT_ENUM, policies, "linux",
+ { "policy", Parameter::PT_ENUM, TCP_POLICIES, TCP_POLICY_DEFAULT,
"determines operating system characteristics like reassembly" },
{ "reassemble_async", Parameter::PT_BOOL, nullptr, "true",
#define STREAM_MAX_FLUSH_FACTOR 2048
/* target-based policy types */
+// changes to this enum require changes to stream_api.h::TCP_POLICIES
#define STREAM_POLICY_FIRST 1
#define STREAM_POLICY_LAST 2
#define STREAM_POLICY_LINUX 3
"first",
"last",
"linux",
- "old linux",
+ "old-linux",
"bsd",
"macos",
- "windows",
"solaris",
"irix",
"hpux11",
"hpux10",
"windows",
"win-2003",
- "vista"
+ "vista",
+ "proxy"
};
#ifdef DEBUG_STREAM_EX
{
if ( !sfat_insufficient_space_logged )
{
- ParseWarning(
+ ParseWarning(WARN_HOSTS,
"AttributeTable insertion failed: %d Insufficient "
"space in attribute table, only configured to store %d hosts\n",
ret, ScMaxAttrHosts());
}
else if ( !sfat_grammar_error_printed )
{
- ParseWarning(
+ ParseWarning(WARN_HOSTS,
"AttributeTable insertion failed: %d '%s'\n",
ret, rt_error_messages[ret]);
sfat_grammar_error_printed = true;