"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "doc/devel/extending.txt" between
snort3-3.1.29.0.tar.gz and snort3-3.1.30.0.tar.gz

About: Snort 3 is a network intrusion prevention and detection system (IDS/IPS) combining the benefits of signature, protocol and anomaly-based inspection.

extending.txt  (snort3-3.1.29.0):extending.txt  (snort3-3.1.30.0)
skipping to change at line 305 skipping to change at line 305
{ return new FooLogger(); } { return new FooLogger(); }
}; };
Once the Factory is created, Inspector and appropriate Module are needed. Once the Factory is created, Inspector and appropriate Module are needed.
*Inspector::configure()* must initialize the logger factory. *Inspector::configure()* must initialize the logger factory.
bool FooInspector::configure(SnortConfig* sc) override bool FooInspector::configure(SnortConfig* sc) override
{ {
return TraceApi::override_logger_factory(sc, new FooFactory()); return TraceApi::override_logger_factory(sc, new FooFactory());
} }
=== Piglet Test Harness
In order to assist with plugin development, an experimental mode called "piglet"
mode
is provided. With piglet mode, you can call individual methods for a specific pl
ugin.
The piglet tests are specified as Lua scripts. Each piglet test script defines a
test
for a specific plugin.
Here is a minimal example of a piglet test script for the IPv4 Codec plugin:
plugin =
{
type = "piglet",
name = "codec::ipv4",
use_defaults = true,
test = function()
local daq_header = DAQHeader.new()
local raw_buffer = RawBuffer.new("some data")
local codec_data = CodecData.new()
local decode_data = DecodeData.new()
return Codec.decode(
daq_header,
raw_buffer,
codec_data,
decode_data
)
end
}
To run snort in piglet mode, first build snort with the ENABLE_PIGLET option tur
ned on
(pass the flag -DENABLE_PIGLET:BOOL=ON in cmake).
Then, run the following command:
snort --script-path $test_scripts --piglet
(where $test_scripts is the directory containing your piglet tests).
The test runner will generate a check-like output, indicating the
the results of each test script.
=== Piglet Lua API
This section documents the API that piglet exposes to Lua.
Refer to the piglet directory in the source tree for examples of usage.
Note: Because of the differences between the Lua and C\++ data model and type
system, not all parameters map directly to the parameters of the underlying
C\++ member functions. Every effort has been made to keep the mappings consist,
but there are still some differences. They are documented below.
==== Plugin Instances
For each test, piglet instantiates plugin specified in the ++name++ field of the
++plugin++ table. The virtual methods of the instance are exposed in a table
unique to each plugin type. The name of the table is the CamelCase name of the
plugin type.
For example, codec plugins have a virtual method called ++decode++. This method
is called like this:
Codec.decode(...)
*Codec*
* ++Codec.get_data_link_type() -> { int, int, ... }++
* ++Codec.get_protocol_ids() -> { int, int, ... }++
* ++Codec.decode(DAQHeader, RawBuffer, CodecData, DecodeData) -> bool++
* ++Codec.log(RawBuffer, uint[lyr_len])++
* ++Codec.encode(RawBuffer, EncState, Buffer) -> bool++
* ++Codec.update(uint[flags_hi], uint[flags_lo], RawBuffer, uint[lyr_len] -> int
++
* ++Codec.format(bool[reverse], RawBuffer, DecodeData)++
Differences:
* In ++Codec.update()++, the ++(uint64_t) flags++ parameter has been split into
++flags_hi++ and ++flags_lo++
*Inspector*
* ++Inspector.configure()++
* ++Inspector.tinit()++
* ++Inspector.tterm()++
* ++Inspector.likes(Packet)++
* ++Inspector.eval(Packet)++
* ++Inspector.clear(Packet)++
* ++Inspector.get_buf_from_key(string[key], Packet, RawBuffer) -> bool++
* ++Inspector.get_buf_from_id(uint[id], Packet, RawBuffer) -> bool++
* ++Inspector.get_buf_from_type(uint[type], Packet, RawBuffer) -> bool++
* ++Inspector.get_splitter(bool[to_server]) -> StreamSplitter++
Differences:
* In ++Inspector.configure()++, the ++SnortConfig*++ parameter is passed implici
tly.
* the overloaded ++get_buf()++ member function has been split into three separat
e methods.
*IpsOption*
* ++IpsOption.hash() -> int++
* ++IpsOption.is_relative() -> bool++
* ++IpsOption.fp_research() -> bool++
* ++IpsOption.get_cursor_type() -> int++
* ++IpsOption.eval(Cursor, Packet) -> int++
* ++IpsOption.action(Packet)++
*IpsAction*
* ++IpsAction.exec(Packet)++
*Logger*
* ++Logger.open()++
* ++Logger.close()++
* ++Logger.reset()++
* ++Logger.alert(Packet, string[message], Event)++
* ++Logger.log(Packet, string[message], Event)++
*SearchEngine*
Currently, SearchEngine does not expose any methods.
*SoRule*
Currently, SoRule does not expose any methods.
===== Interface Objects
Many of the plugins take C\++ classes and structs as arguments. These objects
are exposed to the Lua API as Lua userdata. Exposed objects are instantiated
by calling the ++new++ method from each object's method table.
For example, the DecodeData object can be instantiated and exposed to Lua
like this:
local decode_data = DecodeData.new(...)
Each object also exposes useful methods for getting and setting member variables
,
and calling the C\++ methods contained in the the object. These methods can
be accessed using the ++:++ accessor syntax:
decode_data:set({ sp = 80, dp = 3500 })
Since this is just syntactic sugar for passing the object as the first parameter
of the function ++DecodeData.set++, an equivalent form is:
decode_data.set(decode_data, { sp = 80, dp = 3500 })
or even:
DecodeData.set(decode_data, { sp = 80, dp = 3500 })
*Buffer*
* ++Buffer.new(string[data]) -> Buffer++
* ++Buffer.new(uint[length]) -> Buffer++
* ++Buffer.new(RawBuffer) -> Buffer++
* ++Buffer:allocate(uint[length]) -> bool++
* ++Buffer:clear()++
*CodecData*
* ++CodecData.new() -> CodecData++
* ++CodecData.new(uint[next_prot_id]) -> CodecData++
* ++CodecData.new(fields) -> CodecData++
* ++CodecData:get() -> fields++
* ++CodecData:set(fields)++
++fields++ is a table with the following contents:
* ++next_prot_id++
* ++lyr_len++
* ++invalid_bytes++
* ++proto_bits++
* ++codec_flags++
* ++ip_layer_cnt++
* ++ip6_extension_count++
* ++curr_ip6_extension++
* ++ip6_csum_proto++
*Cursor*
* ++Cursor.new() -> Cursor++
* ++Cursor.new(Packet) -> Cursor++
* ++Cursor.new(string[data]) -> Cursor++
* ++Cursor.new(RawBuffer) -> Cursor++
* ++Cursor:reset()++
* ++Cursor:reset(Packet)++
* ++Cursor:reset(string[data])++
* ++Cursor:reset(RawBuffer)++
*DAQHeader*
* ++DAQHeader.new() -> DAQHeader++
* ++DAQHeader.new(fields) -> DAQHeader++
* ++DAQHeader:get() -> fields++
* ++DAQHeader:set(fields)++
++fields++ is a table with the following contents:
* ++caplen++
* ++pktlen++
* ++ingress_index++
* ++egress_index++
* ++ingress_group++
* ++egress_group++
* ++flags++
* ++opaque++
*DecodeData*
* ++DecodeData.new() -> DecodeData++
* ++DecodeData.new(fields) -> DecodeData++
* ++DecodeData:reset()++
* ++DecodeData:get() -> fields++
* ++DecodeData:set(fields)++
* ++DecodeData:set_ipv4_hdr(RawBuffer, uint[offset])++
++fields++ is a table with the following contents:
* ++sp++
* ++dp++
* ++decode_flags++
* ++type++
*EncState*
* ++EncState.new() -> EncState++
* ++EncState.new(uint[flags_lo]) -> EncState++
* ++EncState.new(uint[flags_lo], uint[flags_hi]) -> EncState++
* ++EncState.new(uint[flags_lo], uint[flags_hi], uint[next_proto]) -> EncState++
* ++EncState.new(uint[flags_lo], uint[flags_hi], uint[next_proto], uint[ttl]) ->
EncState++
* ++EncState.new(uint[flags_lo], uint[flags_hi], uint[next_proto], uint[ttl], ui
nt[dsize]) -> EncState++
*Event*
* ++Event.new() -> Event++
* ++Event.new(fields) -> Event++
* ++Event:get() -> fields++
* ++Event:set(fields)++
++fields++ is a table with the following contents:
* ++event_id++
* ++event_reference++
* ++sig_info++
** ++generator++
** ++id++
** ++rev++
** ++class_id++
** ++priority++
** ++text_rule++
** ++num_services++
*Flow*
* ++Flow.new() -> Flow++
* ++Flow:reset()++
*Packet*
* ++Packet.new() -> Packet++
* ++Packet.new(string[data]) -> Packet++
* ++Packet.new(uint[size]) -> Packet++
* ++Packet.new(fields) -> Packet++
* ++Packet.new(RawBuffer) -> Packet++
* ++Packet.new(DAQHeader) -> Packet++
* ++Packet:set_decode_data(DecodeData)++
* ++Packet:set_data(uint[offset], uint[length])++
* ++Packet:set_flow(Flow)++
* ++Packet:get() -> fields++
* ++Packet:set() ++
* ++Packet:set(string[data]) ++
* ++Packet:set(uint[size]) ++
* ++Packet:set(fields) ++
* ++Packet:set(RawBuffer) ++
* ++Packet:set(DAQHeader) ++
++fields++ is a table with the following contents:
* ++packet_flags++
* ++xtradata_mask++
* ++proto_bits++
* ++application_protocol_ordinal++
* ++alt_dsize++
* ++num_layers++
* ++iplist_id++
* ++user_policy_id++
* ++ps_proto++
Note: ++Packet.new()++ and ++Packet:set()++ accept multiple arguments of the
types described above in any order
*RawBuffer*
* ++RawBuffer.new() -> RawBuffer++
* ++RawBuffer.new(uint[size]) -> RawBuffer++
* ++RawBuffer.new(string[data]) -> RawBuffer++
* ++RawBuffer:size() -> int++
* ++RawBuffer:resize(uint[size])++
* ++RawBuffer:write(string[data])++
* ++RawBuffer:write(string[data], uint[size])++
* ++RawBuffer:read() -> string++
* ++RawBuffer:read(uint[end]) -> string++
* ++RawBuffer:read(uint[start], uint[end]) -> string++
Note: calling ++RawBuffer.new()++ with no arguments returns a RawBuffer of size
0
*StreamSplitter*
* ++StreamSplitter:scan(Flow, RawBuffer) -> int, int++
* ++StreamSplitter:scan(Flow, RawBuffer, uint[len]) -> int, int++
* ++StreamSplitter:scan(Flow, RawBuffer, uint[len], uint[flags]) -> int, int++
* ++StreamSplitter:reassemble(Flow, uint[total], uint[offset], RawBuffer) -> int
, RawBuffer++
* ++StreamSplitter:reassemble(Flow, uint[total], uint[offset], RawBuffer, uint[l
en]) -> int, RawBuffer++
* ++StreamSplitter:reassemble(Flow, uint[total], uint[offset], RawBuffer, uint[l
en], uint[flags]) -> int, RawBuffer++
* ++StreamSplitter:finish(Flow) -> bool++
Note: StreamSplitter does not have a ++new()++ method, it must be created by an
inspector via
++Inspector.get_splitter()++
=== Performance Considerations for Developers
* Since C compilers evaluate compound conditional expression from left to
right, put the costly condition last. Put the often-false condition first
in && expression. Put the often-true condition first in || expression.
* Use emplace_back/emplace instead of push_back/insert on STL containers.
* In general, unordered_map is faster than map for frequent lookups using
integer key on relatively static collection of unsorted elements. Whereas,
map is faster for frequent insertions/deletions/iterations and for
non-integer key such as string or custom objects. Consider the same factors
when deciding ordered vs. unordered multimap and set.
* Iterate using range-based for loop with reference (i.e., auto&).
* Be mindful of construction and destruction of temporary objects which can
be wasteful. Consider using std::move, std::swap, lvalue reference (&),
and rvalue reference (&&).
* Avoid thread-local storage. When unavoidable, minimize frequent TLS access
by caching it to a local variable.
* When writing inter-library APIs, consider interfaces depending on use cases
to minimize context switching. For example, if two APIs foo() and bar() are
needed to call, combine these into a single API to minimize jumps.
 End of changes. 1 change blocks. 
0 lines changed or deleted 0 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)