This page will provide you with all of the basic information required to create an Xplico dissector for a protocol that uses TCP (e.g. HTTP, Telnet, FTP, etc). The page will walk you through a step-by-step tutorial of creating a basic dissector for a made up HELLOWORLD protocol. This tutorial was based off of Xplico 0.7.1.
Dissector modules are located in the “xplico-0.7.1\Dissectors” folder. Each dissector has a sub-directory within the Dissectors directory. For simplicity and convention, name the folder the name of the dissector. There are 3 files in this directory:
This is without a doubt the most difficult part of creating a dissector module. Most of the other code that is needed can usually be copied from another dissector module and tailored slightly to your new module without much understanding of how the Xplico Framework works behind the scenes. This is not the case with the helloworld.c file. This code not only contains the meat of your new dissector, but it also requires a much more intricate understanding of how Xplico works and interacts with dissector modules. Additionally, matters get further complicated by the fact that Xplico interacts differently based on the type of dissector module. In this tutorial, we are only going to focus on writing a dissector module for a protocol over TCP. The following methods are either required or highly recommended:
/* helloworld.c * ... */ #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #include <unistd.h> #include <pcap.h> #include <linux/tcp.h> #include "proto.h" #include "dmemory.h" #include "etypes.h" #include "flow.h" #include "log.h" #include "dnsdb.h" #include "helloworld.h" #include "pei.h" #define HELLOWORLD_TMP_DIR "helloworld" /* info id */ static int ip_id; static int ipv6_id; static int ip_src_id; static int ip_dst_id; static int ipv6_src_id; static int ipv6_dst_id; static int tcp_id; static int port_src_id; static int port_dst_id; static int lost_id; static int helloworld_id; /* pei id */ static int pei_msg_id; static volatile unsigned int incr; //This function assumes that the flow is in fact a helloworld flow // (due to the simple fact that the function is being called) //Since the HELLOWORLD protocol is over TCP, the Xplico TCP dissector re-builds the // TCP stream for us and provides all of the packets in order to the HELLOWORLD // dissector static packet *HelloworldDissector(int flow_id) { packet *pkt; const pstack_f *tcp, *ip; FILE *fp; pei *ppei; time_t cap_sec, end_cap; pei_component *cmpn; int count = 0; ftval ip_host, port; unsigned short port_num = 0; bool ipv6 = FALSE; char host[HELLOWORLD_HOST_NAME_SIZE] = {0}; char msg[HELLOWORLD_MSG_BUF_SIZE] = {0}; char cmd_file[HELLOWORLD_FILENAME_PATH_SIZE] = {0}; printf("HelloworldDissector - Helloworld id: %d\n", flow_id); LogPrintf(LV_DEBUG, "HelloworldDissector1 - flow_id: %d", flow_id); //open a file that we will write the protocol information that we want to report // in this case we are just writing the 8 byte HELLOWORLD message to the file sprintf(cmd_file, "%s/%s/helloworld_%lu_%i.txt", ProtTmpDir(), HELLOWORLD_TMP_DIR, time(NULL), incr); incr++; fp = fopen(cmd_file, "w"); //obtain tcp and ip structures corresponding to this flow tcp = FlowStack(flow_id); /* tcp frame */ ip = ProtGetNxtFrame(tcp); /* ip/ipv6 frame */ //obtain the destination port number ProtGetAttr(tcp, port_dst_id, &port); port_num = port.uint16; //determine whether the flow is ipv4 or ipv6 and obtain the destination host/ip address if (ProtFrameProtocol(ip) == ipv6_id) { ipv6 = TRUE; } if (ipv6 == FALSE) { //ipv4 ProtGetAttr(ip, ip_dst_id, &ip_host); if (DnsDbSearch(&(ip_host), FT_IPv4, host, HELLOWORLD_FILENAME_PATH_SIZE) != 0) { FTString(&(ip_host), FT_IPv4, host); } } else { //ipv6 ProtGetAttr(ip, ipv6_dst_id, &ip_host); if (DnsDbSearch(&(ip_host), FT_IPv6, host, HELLOWORLD_FILENAME_PATH_SIZE) != 0) { FTString(&(ip_host), FT_IPv6, host); } } printf("HelloworldDissector - host:%s:%i - flow_id: %d\n", host, port_num, flow_id); LogPrintf(LV_DEBUG, "HelloworldDissector1.1 - host:%s:%i - flow_id: %d", host, port_num, flow_id); /* first packet */ pkt = FlowGetPkt(flow_id); //This is a basic sanity check to make sure that the flow actually contains packets // However, this function already assumes that this flow is in fact a helloworld flow due // to the simple fact that this function was called. if (pkt != NULL) { /* pei definition */ PeiNew(&ppei, helloworld_id); PeiCapTime(ppei, pkt->cap_sec); PeiMarker(ppei, pkt->serial); PeiStackFlow(ppei, tcp); cap_sec = pkt->cap_sec; } //loop through all of the packets in the flow to dissect the helloworld protocol information // this assumes that the entire 40 bytes of the helloworld protocol is contained in a single // packet and not split between multiple packets. // - There is no guerentee that the tcp/ip driver of the operating system sending the helloworld // message will not split up the data into multiple packets. // - However, in this case, since there are only 40 bytes of data it is highly likely that the // data will not be split up into multiple packets. while (pkt != NULL) { count++; LogPrintf(LV_DEBUG, "HelloworldDissector2 - %i", count); //verify the packet is a HELLOWORLD packet if(pkt->len == 40) { //verify the start and end headers of the protocol if ( (strncmp(pkt->data, "helloworldstarts", 16) == 0) && (strncmp((pkt->data + 24), "helloworldending", 16) == 0) ) { printf("HelloworldDissector - FOUND A HELLOWORLD PROTOCOL MESSAGE\n"); LogPrintf(LV_DEBUG, "HelloworldDissector3 - FOUND A HELLOWORLD PROTOCOL MESSAGE"); strncpy(msg, (pkt->data + 16), 8); fwrite(msg, 1, 8, fp); //write the msg to the file //compose pei /* msg */ PeiNewComponent(&cmpn, pei_msg_id); PeiCompCapTime(cmpn, pkt->cap_sec); PeiCompAddStingBuff(cmpn, msg); PeiCompAddFile(cmpn, "Helloworld Message", cmd_file, 8); PeiAddComponent(ppei, cmpn); //insert pei PeiIns(ppei); printf("HelloworldDissector inserted new message %s\n", msg); LogPrintf(LV_DEBUG, "HelloworldDissector4 inserted new message \"%s\"", msg); break; } } //new/next packet within the flow PktFree(pkt); pkt = FlowGetPkt(flow_id); } //end while //close file if (fp != NULL) { fclose(fp); } printf("HelloworldDissector... bye bye\n"); LogPrintf(LV_DEBUG, "HelloworldDissector5 - flow_id: %d", flow_id); return NULL; } //This is the worker function for both the Verify and Check routines. //It gets called on a per-packet basis - the reason it loops calling "FlowGetPktCp", is because // there is no guerentee that all of the data for a valid HELLOWORLD packet is contained in the // same packet - it could be split up like so: // packet1: helloworldstartsmes // packet2: sage1helloworldending static bool HelloworldVerifyCheck(int flow_id, bool check) { packet *pkt; short cnt, cnt_lim; int count = 0; cnt = 0; pkt = FlowGetPktCp(flow_id); /* numer of packets to verify */ cnt_lim = HELLOWORLD_PKT_CHECK_LIMIT; LogPrintf(LV_DEBUG, "HelloworldVerifyCheck1 - flow_id: %d", flow_id); if (!check) { //Verify LogPrintf(LV_DEBUG, "HelloworldVerifyCheck2 (verify) - flow_id: %d", flow_id); cnt_lim = 1; do { count++; LogPrintf(LV_DEBUG, "HelloworldVerifyCheck3 - flow_id: %d - %i", flow_id, count); while (pkt != NULL && pkt->len == 0) { PktFree(pkt); pkt = FlowGetPktCp(flow_id); } if (pkt != NULL && pkt->data != NULL && pkt->len != 0) { LogPrintf(LV_DEBUG, "HelloworldVerifyCheck4 - flow_id: %d - %i - len:%u - raw:%u", flow_id, count, pkt->len, pkt->raw_len); if (40 == pkt->len) { LogPrintf(LV_DEBUG, "HelloworldVerifyCheck5 - flow_id: %d - pktlen: %u", flow_id, pkt->len); cnt++; } } PktFree(pkt); pkt = FlowGetPktCp(flow_id); } while (pkt != NULL); } else { //Check LogPrintf(LV_DEBUG, "HelloworldVerifyCheck2 (check) - flow_id: %d", flow_id); do { count++; LogPrintf(LV_DEBUG, "HelloworldVerifyCheck3 - flow_id: %d - %i", flow_id, count); if (pkt != NULL && ((pkt->data != NULL && pkt->len != 0) || pkt->raw_len != 0) ) { //printf("helloworld.c - HelloworldVerifyCheck - flow_id: %d\n", flow_id); LogPrintf(LV_DEBUG, "HelloworldVerifyCheck4 - flow_id: %d - %i - len:%u - raw:%u", flow_id, count, pkt->len, pkt->raw_len); if (40 == pkt->len || 94 == pkt->raw_len) { LogPrintf(LV_DEBUG, "HelloworldVerifyCheck5 - flow_id: %d - pktlen: %u", flow_id, pkt->len); cnt++; } else { break; } } PktFree(pkt); pkt = FlowGetPktCp(flow_id); } while (pkt != NULL); } if (pkt != NULL) PktFree(pkt); if (cnt >= cnt_lim) { LogPrintf(LV_DEBUG, "HelloworldVerifyCheck6 - flow_id: %d - RETURN TRUE RETURN TRUE", flow_id;) return TRUE; } LogPrintf(LV_DEBUG, "HelloworldVerifyCheck6 - flow_id: %d", flow_id); return FALSE; } //Verify gets called for every packet within every flow that matches a certain criteria. // Specifically, any flow that has the certain TCP port number as specified in the // "DissectRegist" function under "dep" //Works hand-in-hand with the Check function. If either one of the functions return TRUE, // then the flow is identified as a HELLOWORLD protocol and the Verify and Check functions // do not get called for any more packets in this flow. //The first Dissector to "claim" a flow (by returning TRUE) gets it and no more Verify or // Check functions get called on the flow from ANY dissector at the same Network Stack Layer. //The Verify function gets called before the Check function //Order: Each Dissectors Verify method (if criteria meets) in order of Dissector, then each // Dissectors Check function in order of Dissector static bool HelloworldVerify(int flow_id) { //printf("helloworld.c - HelloworldVerify - flow_id: %d\n", flow_id); LogPrintf(LV_DEBUG, "HelloworldVerify - flow_id: %d", flow_id); return HelloworldVerifyCheck(flow_id, FALSE); } //Check gets called for every packet within every flow until a dissector returns TRUE in // its Check function. Once a dissector returns TRUE, the flow is identified as that // particular protocol and Check does not get called for any other packets in that flow. // This is defined in the "DissectRegist" function under "hdep" //Returning true in this function identifies the flow as a HELLOWORLD protocol and the // flow then gets passed to the HelloworldDissector function. //Every Dissector Check function gets called - the first Dissector to return TRUE gets // the flow and no other Dissector at the same Network Stack Layer can also identify the // flow as their own. static bool HelloworldCheck(int flow_id) { //printf("helloworld.c - HelloworldCheck - flow_id: %d\n", flow_id); LogPrintf(LV_DEBUG, "HelloworldCheck - flow_id: %d", flow_id); return HelloworldVerifyCheck(flow_id, TRUE); } //This is the very first function that gains execution within the HELLOWORLD dissector //Registers the HELLOWORLD dissector as a protocol on top of TCP and sets a Check, // Verify, and Dissector function for the protocol //Defines the components of a HELLOWORLD protocol that will be identified ("msg") //The name of this function must be "DissecRegist" int DissecRegist(void) { proto_heury_dep hdep; proto_dep dep; pei_cmpt peic; printf("Helloworld DissecRegist\n"); LogPrintf(LV_DEBUG, "Helloworld - DissecRegist."); memset(&hdep, 0, sizeof(proto_heury_dep)); memset(&dep, 0, sizeof(proto_dep)); memset(&peic, 0, sizeof(pei_cmpt)); /* protocol name */ ProtName("Helloworld", "helloworld"); /* hdep: tcp */ hdep.name = "tcp"; hdep.ProtCheck = HelloworldCheck; hdep.pktlim = HELLOWORLD_PKT_LIMIT; ProtHeuDep(&hdep); /* dep: tcp */ dep.name = "tcp"; dep.attr = "tcp.dstport"; dep.type = FT_UINT16; dep.val.uint16 = TCP_PORT_HELLOWORLD; dep.ProtCheck = HelloworldVerify; dep.pktlim = HELLOWORLD_PKT_LIMIT; ProtDep(&dep); /* PEI components */ peic.abbrev = "msg"; peic.desc = "Message Sent"; ProtPeiComponent(&peic); /* dissectors subdissectors registration */ ProtDissectors(NULL, HelloworldDissector, NULL, NULL); return 0; } //Initializes HELLOWORLD dissector information //The name of this function must be "DissectInit" int DissectInit(void) { char helloworld_dir[256]; /* part of file name */ incr = 0; printf("Helloworld DissectInit\n"); LogPrintf(LV_DEBUG, "Helloworld - DissectInit."); /* info id */ ip_id = ProtId("ip"); ipv6_id = ProtId("ipv6"); tcp_id = ProtId("tcp"); ip_dst_id = ProtAttrId(ip_id, "ip.dst"); ip_src_id = ProtAttrId(ip_id, "ip.src"); ipv6_dst_id = ProtAttrId(ipv6_id, "ipv6.dst"); ipv6_src_id = ProtAttrId(ipv6_id, "ipv6.src"); port_dst_id = ProtAttrId(tcp_id, "tcp.dstport"); port_src_id = ProtAttrId(tcp_id, "tcp.srcport"); lost_id = ProtAttrId(tcp_id, "tcp.lost"); helloworld_id = ProtId("helloworld"); /* pei id */ pei_msg_id = ProtPeiComptId(helloworld_id, "msg"); /* helloworld tmp directory */ sprintf(helloworld_dir, "%s/%s", ProtTmpDir(), HELLOWORLD_TMP_DIR); mkdir(helloworld_dir, 0x01FF); return 0; }
/* helloworld.h * ... */ #ifndef __HELLOWORLD_H__ #define __HELLOWORLD_H__ /* standard port */ #define TCP_PORT_HELLOWORLD 2233 #define HELLOWORLD_FILENAME_PATH_SIZE 256 #define HELLOWORLD_HOST_NAME_SIZE 256 //The protocol only specifies an 8 byte message - so 16 bytes is excessive //The database has a 16 byte varcar variable for the message #define HELLOWORLD_MSG_BUF_SIZE 16 /* packets limit for HelloworldVerify, HelloworldCheck */ #define HELLOWORLD_PKT_LIMIT 10 #define HELLOWORLD_PKT_CHECK_LIMIT 1 #endif /* __HELLOWORLD_H__ */
The Makefile can be easily created by copying a Makefile from a different Dissector Module and changing all of the instances of the other dissector's name with the name of your new dissector, helloworld.
# Makefile # ... # # dissector name DIS_NAME = dis_helloworld # dissector library (.so) DIS_SO = $(DIS_NAME).so # sub directory SUBDIRS = # src file SRC = dis_log.c helloworld.c # To make it visible export CC CCPP ROOT_DIR CFLAGS LDFLAGS INCLUDE_DIR all: subdir $(DIS_SO) $(DIS_SO): $(SRC:.c=.o) $(CC) $(CFLAGS) -shared -Wl,-soname,$@ -o $@ $(SRC:.c=.o) $(LDFLAGS) subdir: @for dir in $(SUBDIRS) ; \ do $(MAKE) -C $$dir || exit 1; \ done \ clean: @for dir in $(SUBDIRS) ; do $(MAKE) -C $$dir clean || exit 1; done rm -f *.o *.so *~ include/*~ .depend *.expand .depend: $(SRC) $(CC) -M $(CFLAGS) $(SRC) > $@ include ../Makefilelog sinclude .depend
In addition to the main dissector module code that needs to be created (as shown above), other code needs to be added into existing Xplico source files. Many of these files can be easily modified by looking at another dissector and slightly tailoring it to your new one.
Add helloworld into the SUBDIRS list
SUBDIRS += helloworld
Add the helloworld directory path
#define XS_HELLOWORLD_DIR_PATH XS_DB_INSTALL_DIR"/pol_%d/sol_%d/helloworld"
Add the helloworld database query template
#define XS_QUERY_HELLOWORLD_TEMPLATE "INSERT INTO helloworld (sol_id, pol_id, source_id, capture_date, flow_info, msg) VALUES (%i, %i, %i, "XPCAP_DATE", '%s', '%s')"
Add helloworld static global variables (~line 276)
/* helloworld */ static int helloworld_id; static int pei_helloworld_msg_id;
Implement a new function named DispHelloworld (~line 4588)
static int DispHelloworld(pei *ppei) { pei_component *cmpn; char query[XS_QUERY_DIM]; char rep[XS_QUERY_DIM]; char flow_info[XS_STR_PATH]; int pol, sess, src_id; const pstack_f *frame; ftval val, ip; char *msg; char *name; char *path; //path is the same as mfile from cli.c //printf("helloworld - lite.c - DispHelloworld\n"); LogPrintf(LV_DEBUG, "Helloworld - lite.c - DispHelloworld1"); /* search pol and session */ frame = ProtStackSearchProt(ppei->stack, pol_id); if (frame) { ProtGetAttr(frame, pol_polid_id, &val); pol = val.int32; ProtGetAttr(frame, pol_sesid_id, &val); sess = val.int32; } else { sess = pol = 1; } /* search source ip */ src_id = -1; frame = ProtStackSearchProt(ppei->stack, ip_id); if (frame) { ProtGetAttr(frame, ip_src_id, &ip); src_id = DispHostSrch(&ip, FT_IPv4); if (src_id == -1) { /* search in db */ FTString(&ip, FT_IPv4, flow_info); src_id = DispHostDb(flow_info, pol, sess); if (src_id == -1) { query[0] = '\0'; /* insert record */ DnsDbSearch(&ip, FT_IPv4, query, XS_QUERY_DIM); src_id = DispHostDbIns(flow_info, query, pol, sess); } DispHostIns(&ip, FT_IPv4, src_id); } } else if (ipv6_id != -1) { frame = ProtStackSearchProt(ppei->stack, ipv6_id); if (frame) { ProtGetAttr(frame, ipv6_src_id, &ip); src_id = DispHostSrch(&ip, FT_IPv6); if (src_id == -1) { /* search in db */ FTString(&ip, FT_IPv6, flow_info); src_id = DispHostDb(flow_info, pol, sess); if (src_id == -1) { query[0] = '\0'; /* insert record */ DnsDbSearch(&ip, FT_IPv6, query, XS_QUERY_DIM); src_id = DispHostDbIns(flow_info, query, pol, sess); } DispHostIns(&ip, FT_IPv6, src_id); } } } msg = NULL; path = NULL; cmpn = ppei->components; while (cmpn != NULL) { if (cmpn->eid == pei_helloworld_msg_id) { msg = cmpn->strbuf; path = cmpn->file_path; } cmpn = cmpn->next; } LogPrintf(LV_DEBUG, "Helloworld - lite.c - DispHelloworld2"); /* compose query and insert record */ if (path) { LogPrintf(LV_DEBUG, "Helloworld - lite.c - path:%s - DispHelloworld3", path); /* new path */ name = strrchr(path, '/'); name++; sprintf(rep, XS_HELLOWORLD_DIR_PATH"/%s", pol, sess, name); rename(path, rep); DispFilePaths(pol, rep); /* flow info */ sprintf(flow_info, XS_HELLOWORLD_DIR_PATH"/flow_%s.xml", pol, sess, name); DispFlowInfo(flow_info, ppei->stack); /* query */ sprintf(query, XS_QUERY_HELLOWORLD_TEMPLATE, sess, pol, src_id, PEI_TIME(ppei->time_cap), flow_info, msg); if (DispQuery(query, NULL) != 0) { printf("query: %s\n", query); LogPrintf(LV_DEBUG, "Helloworld - lite.c - query:%s - DispHelloworld4", query); } } return 0; }
Add helloworld code into DispInit function (~line 5008)
helloworld_id = ProtId("helloworld"); if (helloworld_id != -1) { pei_helloworld_msg_id = ProtPeiComptId(helloworld_id, "msg"); }
Add helloworld code into DispInsPei function (~line 5147)
else if (ppei->prot_id == helloworld_id) { ret = DispHelloworld(ppei); }
Add static global variables for helloworld (~line 262)
/* helloworld */ static int helloworld_id; static int pei_helloworld_msg_id;
static unsigned long npop, nsmtp, nimap, nhttp, nftp, nipp, npjl, nmms, ntftp, ndns, nnntp, nfbwc, ntelnet, nwebmail, nhttpfile, ngrptcp, ngrpudp, nrtp, nsip, narp, nirc, npltk_exp, npltk, msn, nbo, mgcp, webmsn, syslog, helloworld;
Implement a new function named DispDirHelloworld (~line 450)
static inline int DispDirHelloworld(char *src, char *msg) { char dir[XCLI_STR_DIM]; //printf("helloworld - cli.c - DispDirHelloworld\n"); LogPrintf(LV_DEBUG, "Helloworld - cli.c - msg:%s - DispDirHelloworld", msg); sprintf(dir, "%s/%s", xdecode, src); mkdir(dir, 0x01FF); sprintf(dir, "%s/%s/helloworld/", xdecode, src); mkdir(dir, 0x01FF); sprintf(dir, "%s/%s/helloworld/%s", xdecode, src, msg); mkdir(dir, 0x01FF); return 0; }
Implement a new function named DispHelloworld (~line 2345)
static int DispHelloworld(pei *ppei) { pei_component *cmpn; char new_path[XCLI_STR_DIM]; char ip_src[XCLI_STR_DIM]; char *name; char *msg, *mfile; //printf("helloworld - cli.c - DispHelloworld\n"); LogPrintf(LV_DEBUG, "Helloworld - cli.c - DispHelloworld1"); msg = NULL; cmpn = ppei->components; while (cmpn != NULL) { if (cmpn->eid == pei_helloworld_msg_id) { msg = cmpn->strbuf; mfile = cmpn->file_path; } cmpn = cmpn->next; } if (msg != NULL) { LogPrintf(LV_DEBUG, "Helloworld - cli.c - msg:%s - DispHelloworld2", msg); /* dir name and creation */ if (DispIp(ppei->stack, ip_src) == NULL) return -1; DispDirHelloworld(ip_src, msg); if (mfile == NULL) { printf("helloworld - mfile is NULL - error\n"); } printf("Message: %s, filepath: %s\n", msg, mfile); name = strrchr(mfile, '/'); name++; sprintf(new_path, "%s/%s/helloworld/%s/%s", xdecode, ip_src, msg, name); rename(mfile, new_path); DispFilePaths(new_path); } LogPrintf(LV_DEBUG, "Helloworld - cli.c - DispHelloworld3"); return 0; }
Add code to the DispInit function (~line 2412)
helloworld = 0;
helloworld_id = ProtId("helloworld"); if (helloworld_id != -1) { pei_helloworld_msg_id = ProtPeiComptId(helloworld_id, "msg"); }
Add code to the DispEnd function (~line 2755)
printf("\thelloworld: %lu\n", helloworld);
Add code to the DispInsPei function (~line 2914)
else if (ppei->prot_id == helloworld_id) { if (ppei->ret == FALSE) helloworld++; ret = DispHelloworld(ppei); }
This file needs to be created. It should correspond with the query template definition (XS_QUERY_HELLOWORLD_TEMPLATE) added in “lite.h”
-- -- Tabella delle connessioni helloworld -- CREATE TABLE IF NOT EXISTS helloworlds ( id INTEGER NOT NULL PRIMARY KEY, sol_id INT( 10 ) NOT NULL REFERENCES sols(id) ON DELETE CASCADE ON UPDATE CASCADE, pol_id INT( 10 ) NOT NULL REFERENCES pols(id) ON DELETE CASCADE ON UPDATE CASCADE, source_id INT( 10 ) NOT NULL REFERENCES sources(id) ON DELETE CASCADE ON UPDATE CASCADE, capture_date TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00', decoding_date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, viewed_date TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00', first_visualization_user_id INT( 10 ) NOT NULL DEFAULT '0', flow_info VARCHAR( 255 ) NOT NULL, msg VARCHAR( 16 ) );
Add the following code to this file:
sqlite3 $DIR_BASE/xplico.db < helloworlds.sql
Add to corresponding config file in “/opt/xplico/cfg” (see Run Xplico)
MODULE=dis_helloworld.so LOG=FEWITDS
Run Xplico with web interface
Note: uses xplico_install_lite.cfg config file by default
/opt/xplico/script/sqlite_demo.sh
Run Xplico via the command line (cli)
Note: uses xplico_cli.cfg config file by default
cd /opt/xplico/bin ./xplico -m pcap -f /path/to/pcap/helloworld_dump.pcap
Run Xplico via the command line (cli) - with checksum verification disabled
Note: This may be necessary depending on how you captured your network dump
http://wiki.wireshark.org/CaptureSetup/Offloading
cd /opt/xplico/bin ./xplico -c ../cfg/xplico_cli_nc.cfg -m pcap -f /path/to/pcap/helloworld_dump.pcap
There are several things that this basic dissector module does not account for in order to make it less complex. This section discusses more advanced concepts for creating robust and production-ready dissectors.