Tutorial: Plugin Programming Cheatsheet

cheatsheet plugin development

Contents

This cheatsheet summarizes the most important callbacks, functions, macros and structures required to write your own plugins. For more details about the different aspects of writing your own plugins, refer to the t2PSkel plugin or to one of the tutorials.

Tutorials

Creating a New Plugin

Creating a New C Plugin

t2plugin -c pluginName

Creating a New Minimal C Plugin

t2plugin -c pluginName -m

Creating a New Minimal Sink Plugin

t2plugin -c pluginName -s

Creating a New Minimal t2buf Plugin

t2plugin -c pluginName -t

Creating a New C Plugin with a Specific Plugin Number

t2plugin -c pluginName -n 123

Creating a New C++ Plugin

[Tutorial] t2plugin -c pluginName --cpp

Creating a New Rust Plugin

[Tutorial] t2plugin -c pluginName --rust

Plugin Initialization

Without Any Dependencies to Other Plugins

With Dependency to One Plugin

With Dependency to Several Plugins

Callbacks

void t2Init()

Initialization: allocate memory here [Tutorial]

binary_value_t* t2PrintHeader()

Describe your flow output here [Tutorial]

void t2OnNewFlow(packet_t *packet, unsigned long flowIndex)

A new flow has been generated: reset its memory and try to determine if it is relevant for the plugin (protocol, ports, …) [Tutorial]

void t2OnLayer2(packet_t *packet, unsigned long flowIndex)

A new packet with a layer 2 (if it also has a layer 4, then flowIndex is equal to HASHTABLE_ENTRY_NOT_FOUND) [Tutorial]

void t2OnLayer4(packet_t *packet, unsigned long flowIndex)

A new packet with a layer 4 [Tutorial]

void t2OnFlowTerminate(unsigned long flowIndex, outputBuffer_t *buf)

A flow has been terminated: finish computations for this flow and push your data to the output buffer [Tutorial]

void t2Finalize()

Free the memory here [Tutorial]

void t2PluginReport(FILE *stream)

Contribute plugin specific information to the end report [Tutorial]

void t2Monitoring(FILE *stream, uint8_t state)

Monitoring mode [Tutorial]

void t2SaveState(FILE *stream)

Save the state of your plugin

void t2RestoreState(const char *str)

Restore the state of your plugin

void t2BufferToSink(outputBuffer_t buf, binary_value_t bv)

Dump the content of buf to a file, stream, … Use bv to decode it. (Sink plugins only) [Tutorial]

Accessing the Plugin Name

The T2_PLUGIN_INIT() and T2_PLUGIN_INIT_WITH_DEPS() macros both define the following static variable:

This variable being static, it can only be accessed in the pluginName.c file. However, nothing prevents you from redefining it in a different file! As an example, the plugin_name variable can be used with the macros defined here, e.g., T2_PLOG(plugin_name, "Andy was here!");

Accessing the Various Layers

Layer 2 Header

The layer 2 header (Ethernet) can be accessed as follows:

Layer 3 Header

The layer 3 header (IPv4, IPv6) can be accessed as follows:

Layer 4 Header

The layer 4 header (TCP, UDP, ICMP, SCTP, …) can be accessed as follows:

Layer 7 Header

The layer 7 header can be accessed as follows:

Selecting Flows by Port/Protocol

Selecting Flows by Port

Accessing the source/destination port:

Selecting Flows by Protocol

Describing Flow File Output in t2PrintHeader()

Bitfields and hexadecimal numbers (8, 16, 32 and 64 bits)

Signed integers (8, 16, 32 and 64 bits)

Unsigned integers (8, 16, 32 and 64 bits)

Floating point (float, double)

MAC addresses

IPv4, IPv6 and IPvX (IP version and IP) addresses

Timestamp, duration

Characters, strings and string classes (strings without quotes)

If the type of the column varies

Compounds, e.g., field1_field2

Existing types

type description
bt_int_8 8-bit signed integer
bt_int_16 16-bit signed integer
bt_int_32 32-bit signed integer
bt_int_64 64-bit signed integer
bt_uint_8 8-bit unsigned integer
bt_uint_16 16-bit unsigned integer
bt_uint_32 32-bit unsigned integer
bt_uint_64 64-bit unsigned integer
bt_hex_8 8-bit hexadecimal number (unsigned integer)
bt_hex_16 16-bit hexadecimal number (unsigned integer)
bt_hex_32 32-bit hexadecimal number (unsigned integer)
bt_hex_64 64-bit hexadecimal number (unsigned integer)
bt_float Floating point number
bt_double Double precision floating point number
bt_char Single character
bt_string String
bt_string_class Unquoted string
bt_flow_direction A or B
bt_timestamp Date whose representation depends on B2T_TIMESTR in utils/bin2txt.h
bt_duration One uint64_t value for the seconds and one uint32_t value for the micro-/nano-seconds
bt_mac_addr MAC address
bt_ip4_addr IPv4 address
bt_ip6_addr IPv6 address
bt_ipx_addr IP address: version (8 bits), address (0, 4 or 16 bytes)

Generating Flow File Output in t2OnFlowTerminate()

Unsigned integers, bitfields and hexadecimal numbers (8, 16, 32 and 64 bits)

Signed integers (8, 16, 32 and 64 bits)

Floating point (float, double)

MAC

MAC addresses structures.

IPv4, IPv6 and IPvX (IP version and IP) addresses

IP Addresses structures

Timestamp, duration

Characters, strings and string classes (strings without quotes)

If the type of the column varies

Repetitive values

For repetitive values, use one of the OUTBUF_APPEND_ARRAY_*() macros

Optional strings (repetitive with 0 or 1 repetition)

More complex cases of repetitive values

For more complex cases of repetitive values, start by adding the number of repetitions, then add the values in a for loop

Special cases: 0 or 1 repetition

Adding Support for Environment / Runtime Configuration Flags

Using T2 file manager

Parsing Data with t2buf

Initialization in t2OnLayer2() or t2OnLayer4()

Reading data

Peeking into data (reading without consuming any bytes)

String encodings

Read strings

Hexdecode bytes

Read entire lines

Skipping data

Computing lengths

Searching for patterns

Structures

flow_t

The flow_t structure is defined in tranalyzer2/src/flow.h as follows:

typedef struct flow_s {
    // Pointers to the next and previous flow in LRU list
    struct flow_s *  lruNextFlow;
    struct flow_s *  lruPrevFlow;

    uint64_t         findex;                // flow index
    uint64_t         status;                // status of flow, e.g., fragmentation processing

    unsigned long    flowIndex;
    unsigned long    oppositeFlowIndex;

#if (SCTP_ACTIVATE > 0 && SCTP_STATFINDEX == 1)
    unsigned long    sctpFindex;
#endif // (SCTP_ACTIVATE > 0 && SCTP_STATFINDEX == 1)

    struct timeval   lastSeen;   // last time we've seen this flow
    struct timeval   firstSeen;  // first time we've seen this flow
    struct timeval   duration;   // lastSeen - firstSeen
                                 // (NOT available before flow completely terminated)

    /* --------------------------------------------------------------------- */
    /* Begin flow identification                                             */
    /* --------------------------------------------------------------------- */

#if IPV6_ACTIVATE > 0
    ipAddr_t         srcIP;
    ipAddr_t         dstIP;
#else // IPV6_ACTIVATE == 0
    ip4Addr_t        srcIP;
    ip4Addr_t        dstIP;
#endif // IPV6_ACTIVATE == 0

#if ETH_ACTIVATE > 0
    ethDS_t          ethDS;
#endif

#if (IPV6_ACTIVATE == 2 || ETH_ACTIVATE > 0 || LAPD_ACTIVATE == 1)
    uint16_t         ethType;
#endif

    uint16_t         vlanId;

    union {
        struct {
            uint16_t srcPort;
            uint16_t dstPort;
        };
        uint32_t     fragID;
    };

#if SCTP_ACTIVATE & 2
    uint32_t         sctpVtag;
#endif // SCTP_ACTIVATE & 2

#if SCTP_ACTIVATE & 1
    uint16_t         sctpStrm;
#endif // SCTP_ACTIVATE & 1

    uint8_t          l4Proto;

    /* --------------------------------------------------------------------- */
    /* End flow identification                                               */
    /* --------------------------------------------------------------------- */

    float            timeout;               // timeout of this flow in seconds

    uint32_t         lastIPID;              // for duplicate IP ID detection

#if SUBNET_INIT != 0
    uint32_t         subnetNrSrc;
    uint32_t         subnetNrDst;
#endif // SUBNET_INIT != 0

    // for fragPend hash cleanup
#if IPV6_ACTIVATE > 0
    uint32_t        lastFragIPID;
#else // IPV6_ACTIVATE == 0
    uint16_t        lastFragIPID;
#endif // IPV6_ACTIVATE == 0

} __attribute__((packed)) flow_t;

packet_t

The packet_t structure is defined in tranalyzer2/src/packet.h as follows:

typedef struct {
#if (FDURLIMIT > 0 && FDLSFINDEX == 1)
    uint64_t findex;
#endif //(FDURLIMIT > 0 && FDLSFINDEX == 1)

    uint64_t status;

    /* --------------------------------------------------------------------- */
    /* Pointers (network order)                                              */
    /* --------------------------------------------------------------------- */

    const struct pcap_pkthdr * const pcapHdrP;

    const uint8_t * const   raw_packet;    // Beginning of the packet
    const uint8_t * const   end_packet;    // Beyond the end of the packet
                                           // (raw_packet + snapLen);

    const uint8_t *         l2HdrP;        // Layer 2 (Ethernet, LLC, LAPD, ...)
    const uint8_t *         l3HdrP;        // Layer 3 (IPv4, IPv6, ...)
    const uint8_t *         l4HdrP;        // Layer 4 (TCP, UDP, ICMP, IGMP, SCTP, ...)
    const uint8_t *         l7HdrP;        // Layer 7 (payload)

    const etherLLCHeader_t* etherLLC;      // Ethernet header LLC part if present (set but not used)
    const pppHu_t *         pppHdrP;       // PPP header
    const pppoEH_t *        pppoeHdrP;     // PPPoE header
    const uint32_t *        mplsHdrP;      // MPLS pointer
    const uint32_t *        vlanHdrP;      // VLAN pointer

    // GRE headers
    const greHeader_t *     greHdrP;       // GRE v1,2 header
    const uint8_t     *     greL3HdrP;     // L3 header before GRE header

    // GTP headers
    const uint8_t *         gtpHdrP;       // GTP v0,1,2 header (set but no used)

    // L2TP headers
    const uint16_t *        l2tpHdrP;      // L2TPv2 header
    const uint8_t  *        l2tpL3HdrP;    // L3 header before L2TP header

    // IPv6 headers
    const ip6OptHdr_t *     ip6HHOptHdrP;  // IPv6 Hop-by-Hop Option header
    const ip6OptHdr_t *     ip6DOptHdrP;   // IPv6 Destination Option header
    const ip6FragHdr_t *    ip6FragHdrP;   // IPv6 Fragment header
    const ip6RouteHdr_t *   ip6RouteHdrP;  // IPv6 Routing header (set but not used)

    // Teredo headers
    const uint8_t *         trdoOIHdrP;    // Teredo Origin Indication header
    const uint8_t *         trdoAHdrP;     // Teredo Authentication header

#if SCTP_ACTIVATE > 0
    const uint8_t *         l7SctpHdrP;    // First SCTP payload
#endif // SCTP_ACTIVATE > 0

    /* --------------------------------------------------------------------- */
    /* Lengths (host order)                                                  */
    /*   - Snap lengths can be truncated due to limited snaplength           */
    /*     (derived by header dissection)                                    */
    /* --------------------------------------------------------------------- */

    const uint32_t          rawLen;          // extracted from pcapHdrP
    uint32_t                l2Len;           // derived from IP header length field + length of L2 header (set but not used)
    uint32_t                len;             // derived from IP header length field, defined by PACKETLENGTH in packetCapture.h:
                                             //   0: Including L2-4 header,
                                             //   1: including L3-4 header,
                                             //   2: Including L4 header,
                                             //   3: Only payload L7

    // Snap lengths (can be truncated due to limited snaplength, derived by header dissection)
    const uint32_t          snapLen;         // extracted from pcapHdrP
    uint32_t                snapL2Len;       // includes L2 header
    uint32_t                snapL3Len;       // includes L3 header
    uint16_t                snapL4Len;       // includes L4 header
    uint16_t                snapL7Len;       // only higher packet payload (L7)

    uint16_t                l7Len;           // L7 length

#if SCTP_ACTIVATE > 0
    uint16_t                snapSctpL7Len;   // only higher packet payload (L7)
#endif // SCTP_ACTIVATE > 0

    uint16_t                l2HdrLen;        // set but not used
    uint16_t                l3HdrLen;
    uint16_t                l4HdrLen;

    /* --------------------------------------------------------------------- */
    /* Flow identification (IP addresses, ports and protocols (host order),  */
    /* headers count and description, ...                                    */
    /* --------------------------------------------------------------------- */

#if IPV6_ACTIVATE > 0
    ipAddr_t                srcIP;
    ipAddr_t                dstIP;
#else // IPV6_ACTIVATE == 0
    ip4Addr_t               srcIP;
    ip4Addr_t               dstIP;
#endif // IPV6_ACTIVATE == 0

#if ((SUBNET_INIT != 0) || (AGGREGATIONFLAG & (SUBNET | SRCIP | DSTIP)))
#if IPV6_ACTIVATE > 0
    ipAddr_t                srcIPC;
    ipAddr_t                dstIPC;
#else // IPV6_ACTIVATE == 0
    ip4Addr_t               srcIPC;
    ip4Addr_t               dstIPC;
#endif // IPV6_ACTIVATE == 0

    uint32_t                subnetNrSrc;
    uint32_t                subnetNrDst;
    uint16_t                srcPortC;
    uint16_t                dstPortC;
    uint8_t                 l4ProtoC;
#endif // ((SUBNET_INIT != 0) || (AGGREGATIONFLAG & (SUBNET | SRCIP | DSTIP)))

    uint16_t                vlanId;
    uint16_t                srcPort;
    uint16_t                dstPort;
    uint16_t                ethType;
    uint16_t                outerEthType;
    uint16_t                l3Proto;                    // IPv4, IPv6, L2TPv2/3, ...

    // Headers description, e.g., eth:ipv4:tcp
#if T2_PRI_HDRDESC == 1
    uint16_t                numHdrDesc;                 // Number of headers description
    uint16_t                hdrDescPos;                 // Headers description position
    char                    hdrDesc[T2_HDRDESC_LEN];    // Headers description
#endif // T2_PRI_HDRDESC == 1

    uint8_t                 l4Proto;                    // TCP, UDP, ICMP, IGMP, ...
    uint8_t                 mplsHdrCnt;
    uint8_t                 vlanHdrCnt;

#if SCTP_ACTIVATE > 0
    uint8_t                 sctpPad;                    // SCTP padding of content
#endif // SCTP_ACTIVATE > 0

} packet_t;

MAC Addresses

The ethDS_t structure is defined in tranalyzer2/src/networkHeaders.h as follows:

IP Addresses

The ipAddr_t, ipVAddr_t and ip4Addr_t, structures are defined in tranalyzer2/src/ipaddr.h as follows:

ethernetHeader_t

The ethernetHeader_t structure is defined in tranalyzer2/src/networkHeaders.h as follows:

ipHeader_t

The ipHeader_t structure is defined in tranalyzer2/src/proto/ipv4.h as follows:

ip6Header_t

The ip6Header_t structure is defined in tranalyzer2/src/proto/ipv6.h as follows:

tcpHeader_t

The tcpHeader_t structure is defined in tranalyzer2/src/proto/tcp.h as follows:

udpHeader_t

The udpHeader_t structure is defined in tranalyzer2/src/proto/udp.h as follows:

icmpHeader_t

The icmpHeader_t structure is defined in tranalyzer2/src/proto/icmp.h as follows:

sctpHeader_t

The sctpHeader_t structure is defined in tranalyzer2/src/sctp.h as follows:

Reporting Errors, Warnings and Other Information

Reporting Aggregated Bitfields

Reporting Hexadecimal Numbers

Reporting Numbers

Reporting MAC Addresses

Reporting IP Addresses

Reporting Subnet Information

// Tranalyzer2 already looked up source and destination address for each packet
const uint32_t num = packet->subnetNrSrc;
//const uint32_t num = packet->subnetNrDst;
const uint_fast8_t ipver = PACKET_IPVER(packet);

// To lookup other addresses:
uint32_t netNum;
ipAddr_t ip = packet->srcIP;
SUBNET_TEST_IP(netNum, ip, ipver);
//SUBNET_TEST_IP4(netNum, ip); // for IPv4
//SUBNET_TEST_IP6(netNum, ip); // for IPv6

// Autonomous System Number
uint32_t asn;
SUBNET_ASN(asn, ipver, num);
//SUBNET4_ASN(asn, num); // for IPv4
//SUBNET6_ASN(asn, num); // for IPv6

// Country
char *country;
SUBNET_LOC(country, ipver, num);
//SUBNET4_LOC(country, num); // for IPv4
//SUBNET6_LOC(country, num); // for IPv6

// County
char *county;
SUBNET_CNTY(county, ipver, num);
//SUBNET_CNTY(county, num); // for IPv4
//SUBNET_CNTY(county, num); // for IPv6

// City
char *city;
SUBNET_CTY(city, ipver, num);
//SUBNET4_CTY(city, num); // for IPv4
//SUBNET6_CTY(city, num); // for IPv6

// Organization
char *org;
SUBNET_ORG(org, ipver, num);
//SUBNET4_ORG(org, num); // for IPv4
//SUBNET6_ORG(org, num); // for IPv6

// Hexadecimal code
uint32_t netID;
SUBNET_NETID(netID, ipver, num);
//SUBNET4_NETID(netID, num); // for IPv4
//SUBNET6_NETID(netID, num); // for IPv6

// Latitude, longitude and precision
float lat, lng, prec;
SUBNET_LAT(dest, ipver, num);     // Latitude
SUBNET_LNG(dest, ipver, num);     // Longitude
SUBNET_PREC(dest, ipver, num);    // Precision
//SUBNET4_LAT(dest, num);  // Latitude for IPv4
//SUBNET4_LNG(dest, num);  // Longitude for IPv4
//SUBNET4_PREC(dest, num)  // Precision for IPv4
//SUBNET6_LAT(dest, num);  // Latitude for IPv6
//SUBNET6_LNG(dest, num);  // Longitude for IPv6
//SUBNET6_PREC(dest, num)  // Precision for IPv6

Working with Strings

Miscellaneous Macros

Reporting Alarms (alarm mode)

The following snippet of code can be implemented in any callback receiving the flowIndex, i.e., t2OnNewFlow(), t2OnLayer2(), t2OnLayer4() and/or t2OnFlowTerminate().

For more details, refer to the Implementing the alarm mode capability tutorial.

Forcing Termination of a Flow (force mode)

For more details, refer to the Implementing the force mode capability tutorial.

Handy C Snippets

Creating (and Deleting) Folder for Saving Data

  • src/myPlugin.h
  • src/myPlugin.c

Loading a File From the Plugin Folder

Saving Data in a New File

Searching for a Needle in a Haystack

Working with Perl Compatible Regular Expressions (PCRE)

Debugging

  1. Compile in debug mode:

    t2build -d myPlugin

  2. Run t2 in the gdb (Linux) or lldb (macOS) debugger:

    gt2 -r file.pcap

  3. Set a breakpoint:

    • On a specific line: b myFile.c:1234
    • On a specific function: b myFunc
  4. Set a conditional breakpoint:

    • On a specific line: b myFile.c:1234 if numPackets == 3
    • On a specific function: b myFunc if numPackets == 3
  5. Add a condition to an existing breakpoint:

    b myFile.c:1234

    Breakpoint 1 at 0x5674

    cond 1 numPackets == 3

    b myFunc

    Breakpoint 2 at 0x8535

    cond 2 numPackets == 3

  6. Start debugging:

    r

  7. Print the program trace (backtrace):

    bt

  8. Inspect the content of a variable:

    • Default format: p myVar
    • Hexadecimal: p /x myHexVar
  9. Jump to the next program line:

    n

  10. Step into a function:

s

  1. Continue running the program:

    c

  2. Quit gdb:

    q

Toggle Test

  1. List the flags to toggle in tests/myPlugin.flags:

    cat $T2PLHOME/myPlugin/tests/myPlugin.flags

    ...
    ETH_ACTIVATE     ../../tranalyzer2/src/networkHeaders.h
    ...
    MYBOOLEAN_FLAG   src/myPlugin.h
  2. Run t2test:

    t2test myPlugin

    Or if you have a lot of flags, start with:

    t2test myPlugin -J

    which is not exhaustive, but faster.

Scripts

If you need to write supporting scripts, the t2utils.sh helper file provides easy access to Tranalyzer2 scripts and programs and help ensures portability for different OS. Use it as follows (assuming your script resides in $T2PLHOME/myPlugin/scripts/, otherwise you will need to adapt the path in the third line (source ...)):

Access Tranalyzer scripts and utilities

T2 alias/script/utility T2 variable/function Description Example
tran "$T2HOME" location of tranalyzer2 source files, e.g., /home/user/tranalyzer2-0.9.0/ cd "$T2PLHOME"
tranpl "$T2PLHOME" location of the plugins source files, e.g., $T2HOME/plugins/ cd "$T2PLHOME/basicFlow"
"$SHOME" location of the script, e.g., $T2PLHOME/myPlugin/scripts/ cd "$SHOME"
"$SNAME" name of the script echo "$SNAME"
t2 T2 tranalyzer executable T2 -r file.pcap
t2build $T2BUILD build plugins $T2BUILD basicFlow
t2conf $T2CONF configure plugins $T2CONF basicFlow -D BFO_VLAN=1
tawk $TAWK post-processing with Tawk $TAWK 'aggr($l4Proto)' f_flows.txt
t2whois T2WHOIS query the anteaters subnet file T2WHOIS 1.2.3.4
t2b2t T2B2T convert T2 binary files T2B2T -l f_flows.bin
t2plot T2PLOT 2D/3D plot $T2PLOT file.txt

Function/variable wrappers for common utitilies

For maximum portability, make sure to replace your calls to awk, sed, … as follows:

Program T2 variable/function Example
awk AWK AWK '{ print $1 }' file.txt
gawk AWK AWK '{ print $1 }' file.txt
awk -v OFS='\t' -F '\t' AWKF AWKF '{ print $2 }' file.txt
gawk -v OFS='\t' -F '\t' AWKF AWKF '{ print $2 }' file.txt
sed $SED $SED 's/$/ Andy/' <<< "Hello"
gsed $SED $SED 's/$/ Andy/' <<< "Hello"
open (macOS) $OPEN $OPEN file.txt
xdg-open $OPEN $OPEN file.txt
readlink $READLINK $READLINK -f /tmp/../tmp/file.txt
greadlink $READLINK $READLINK -f /tmp/../tmp/file.txt

t2utils.sh: list of available functions

For usage details, refer to the well documented source code of t2utils.sh in $T2HOME/scripts/t2utils.sh:

Functions

  • printbold
  • printerr
  • printinf
  • printok
  • printwrn
  • fatal
  • check_dependency
  • check_dependency_linux
  • check_dependency_osx
  • has_define
  • get_define
  • set_define
  • ask_default_no
  • ask_default_yes
  • find_most_recent_dir
  • find_most_recent_file
  • t2_build_exec
  • get_t2_exec
  • get_t2b2t_exec
  • get_t2whois_exec
  • abort_if_t2_exec_not_found
  • abort_if_t2b2t_exec_not_found
  • abort_if_t2whois_exec_not_found
  • t2_wget
  • t2_wget_n
  • replace_suffix
  • get_nproc
  • arg_is_option
  • validate_next_arg
  • validate_next_arg_exists
  • validate_next_dir
  • validate_next_file
  • validate_next_pcap
  • validate_next_num
  • validate_next_int
  • validate_next_float
  • validate_float
  • validate_int
  • validate_num
  • validate_ip
  • validate_pcap
  • abort_missing_arg
  • abort_option_unknown
  • abort_required_file
  • abort_required_dir
  • abort_required_file_or_dir
  • abort_with_help

Scripts and programs

  • AWK
  • AWKF
  • $OPEN
  • $READLINK
  • $SED
  • T2
  • T2B2T
  • T2WHOIS
  • $T2BUILD
  • $T2CONF
  • $T2PLOT
  • $TAWK

Folders

  • $SHOME
  • $T2HOME
  • $T2PLHOME

Colors

  • $BLUE
  • $GREEN
  • $ORANGE
  • $RED
  • $BLUE_BOLD
  • $GREEN_BOLD
  • $ORANGE_BOLD
  • $RED_BOLD
  • $BOLD
  • $NOCOLOR

Variables

  • $SNAME

Adding support for Bash/ZSH completion

Completions files for T2 scripts and utilities reside in $T2HOME/scripts/completions/{bash,zsh}/ and are named according to the name of the script/program prepended by an underscore, e.g., for myScript: $T2HOME/scripts/completions/bash/_myScript and $T2HOME/scripts/completions/zsh/_myScript. Make sure to replace all occurences of myScript with the name of your script.

Bash

Bash completions reside in $T2HOME/scripts/completions/bash/.

ZSH

ZSH completions reside in $T2HOME/scripts/completions/zsh/.

Documentation

tawk -V

In order for tawk to know about your variables, you need to create a file with the name of your variable in $T2HOME/scripts/tawk/vars/. The easiest is to copy one of the existing files, e.g.:

  • Bitfields:

    bt_hex_8 $T2HOME/scripts/tawk/vars/arpStat
    bt_hex_16 $T2HOME/scripts/tawk/vars/dhcpStat
    bt_hex_32 $T2HOME/scripts/tawk/vars/tcpOptions
    bt_hex_64 $T2HOME/scripts/tawk/vars/flowStat
  • Fixed values:

    Hexadecimals $T2HOME/scripts/tawk/vars/vtpCode
    Integers $T2HOME/scripts/tawk/vars/tftpErrC
    Strings $T2HOME/scripts/tawk/vars/tftpOpcode

Workflow

tran

cd scripts/tawk/vars

cp arpStat myprotoStat

vi myprotoStat

tawk -V myprotoStat



   The myprotoStat column is to be interpreted as follows:

      bit | myprotoStat | Description
      =============================================================================
        0 | 0x01        | Myproto detected
        1 | 0x02        | This is an information (blue)
        2 | 0x04        | This is a warning (orange)
        3 | 0x08        | This is an error (red)
        4 | 0x10        | Use a dash ("-") if a bit is not used
        5 | 0x20        | -
        6 | 0x40        | -
        7 | 0x80        | -
   
tawk -V myprotoStat=0x13


   The myprotoStat column with value 0x13 is to be interpreted as follows:

      bit | myprotoStat | Description
      =============================================================================
        0 | 0x01        | Myproto detected
        1 | 0x02        | This is an information (blue)
        4 | 0x10        | Use a dash ("-") if a bit is not used