The metaevent module

Events are records, composed of fields, that the various input and dissection modules provide to the Orchids detection engine. Those are ordinary, regular events.

Orchids also allows you to create new events during the execution of a rule. Those events are called synthetic events, or metaevents.  It is the purpose of the metaevent module to provide primitives to post such synthetic events.

Posting synthetic events is useful to make detection hierarchical. For an example,  imagine that attempting to unduly connect to some machine $host  is detected by a rule connect_attempt.rule,  and that you would like to detect when the same intruder tries to connect to two machines.  One possibility is to write connect_attempt.rule as a rule that, instead of reporting, would post a synthetic event containing the offending intruder identity and the $host it tried to connect to.  That can be done by writing:

inject_event (.{ = $host, .meta.intruder = $attacker});

in the connect_attempt.rule rule, posting the synthetic event given as argument to inject_event.  (Any list of records enclosed between .{ and } is a synthetic event, see “synthetic event” in the expressions page.  The meta module does not exist: this is a so-called virtual module, see below. Also the list of fields was kept minimal for the illustration.)

Then a second rule that tries to detect two connection attempts by the same intruder might include code such as:

state first_connection {
  expect (defined( goto second_connection;
state second_connection {
  $host1 =;
  $attacker = .meta.intruder; // record data from first connection
  expect (.meta.intruder==$attacker)
    // wait for another meta event with the same $attacker
    // (no need to check defined( here)
    goto alert;
state alert! {
  $host2 =;

Virtual modules

So what is meta in that example?

Just like the generic module, the metaevent module is a meta-module, one that allows you to define new, so-called virtual modules.  Any event field in Orchids is of the form .module-name.field-name, so you cannot just write any random event field: either you use fields from some existing modules (which is not what we want to do here), or you create some fresh, specifically designed, virtual modules.

Such virtual modules are declared inside the configuration options for the metaevent module.  Contrarily to the generic module, we do not specify regular expressions here, just lists of fields with their types.

Configuration options

<module metaevent>

contains a list of declarations of virtual modules.  Virtual modules work exactly like actual modules, except you do not need to load any shared library at start-up time to start them.  You start each virtual module by a declaration of the form:

<vmod module-name>

Inside such a declaration, you can declare fields with their names and types:

  • str_field field-name description: a field of type str (string)
  • bstr_field field-name description: a field of type bstr (binary string)
  • int_field field-name description: a field of type int
  • uint_field field-name description: a field of type uint (unsigned int)
  • float_field field-name description: a field of type float (floating-point number)
  • ipv4_field field-name description: a field of type ipv4 (IPv4 address)
  • ipv6_field field-name description: a field of type ipv4 (IPv6 address)
  • ctime_field field-name description: a field of type ctime (Unix date)
  • timeval_field field-name description: a field of type timeval (duration)
  • snmpoid_field field-name description: a field of type snmpoid (SNMP object identifier)


<vmod meta>
  str_field host "The current host"
  str_field action "A text description of the action done"
  ipv4_field intruder "The attacker's IP address"
  ctime_field time "The detection time"

Note that you are not forced to use all the fields declared in a given virtual module.  It is perfectly fair to build events with only some of the fields, just as we did with the meta virtual module.




  • inject_event : eventint
    inject the given event into the Orchids event queue; the event can be a synthetic event, or one obtained by current_event, possibly enriched: see synthetic events on the expressions page

    • returns: 1 (true)
  • current_event : → event
    the current event