From c4f2fe4bd775152ed275d4383279c0487b7fb4f2 Mon Sep 17 00:00:00 2001 From: Victor Julien Date: Fri, 31 Oct 2008 09:54:29 +0100 Subject: [PATCH] Implement per packet variables and switch the http stuff to it. --- src/Makefile.am | 2 + src/decode.h | 16 ++++ src/detect-pcre.c | 31 +++++-- src/detect-pcre.h | 19 ++-- src/detect-pktvar.c | 211 ++++++++++++++++++++++++++++++++++++++++++++ src/detect-pktvar.h | 17 ++++ src/detect.c | 10 ++- src/detect.h | 1 + src/log-httplog.c | 47 ++++------ src/pkt-var.c | 93 +++++++++++++++++++ src/pkt-var.h | 11 +++ 11 files changed, 413 insertions(+), 45 deletions(-) create mode 100644 src/detect-pktvar.c create mode 100644 src/detect-pktvar.h create mode 100644 src/pkt-var.c create mode 100644 src/pkt-var.h diff --git a/src/Makefile.am b/src/Makefile.am index a31d318753..9ccb2d64e8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -16,6 +16,7 @@ flow-queue.c flow-queue.h \ flow-hash.c flow-hash.h \ flow-util.c flow-util.h \ flow-var.c flow-var.h \ +pkt-var.c pkt-var.h \ host.c host.h \ detect.c detect.h \ detect-engine.c detect-engine.h \ @@ -30,6 +31,7 @@ detect-parse.c detect-parse.h \ detect-content.c detect-content.h \ detect-uricontent.c detect-uricontent.h \ detect-flowvar.c detect-flowvar.h \ +detect-pktvar.c detect-pktvar.h \ detect-pcre.c detect-pcre.h \ detect-depth.c detect-depth.h \ detect-nocase.c detect-nocase.h \ diff --git a/src/decode.h b/src/decode.h index c756888fbe..f41382081d 100644 --- a/src/decode.h +++ b/src/decode.h @@ -170,6 +170,15 @@ typedef struct _HttpUri { u_int8_t cnt; } HttpUri; +typedef struct _PktVar { + char *name; + u_int8_t *value; + u_int16_t value_len; + struct _PktVar *next; /* right now just implement this as a list, + * in the long run we have thing of something + * faster. */ +} PktVar; + typedef struct _Packet { /* Addresses, Ports and protocol @@ -214,6 +223,9 @@ typedef struct _Packet struct _Flow *flow; u_int8_t flowflags; + /* pkt vars */ + PktVar *pktvar; + /* header pointers */ EthernetHdr *ethh; @@ -272,6 +284,8 @@ typedef struct _PacketQueue { u_int16_t dbg_maxlen; #endif /* DBG_PERF */ } PacketQueue; + + /* clear key vars so we don't need to call the expensive * memset or bzero */ @@ -297,6 +311,8 @@ typedef struct _PacketQueue { (p)->flowflags = 0; \ (p)->alerts.cnt = 0; \ (p)->http_uri.cnt = 0; \ + PktVarFree((p)->pktvar); \ + (p)->pktvar = NULL; \ } diff --git a/src/detect-pcre.c b/src/detect-pcre.c index 68ad80bdee..352af9bc89 100644 --- a/src/detect-pcre.c +++ b/src/detect-pcre.c @@ -5,13 +5,15 @@ #include "debug.h" #include "decode.h" #include "detect.h" + +#include "pkt-var.h" #include "flow-var.h" #include "detect-pcre.h" #include "detect-engine-mpm.h" -#define PARSE_CAPTURE_REGEX "\\(\\?P\\<([A-z0-9_]+)\\>" +#define PARSE_CAPTURE_REGEX "\\(\\?P\\<([A-z]+)\\_([A-z0-9_]+)\\>" #define PARSE_REGEX "(?http_uri.raw_size[pmt->pkt_cnt] = ret; p->http_uri.cnt = pmt->pkt_cnt + 1; } else { - FlowVarAdd(p->flow, pe->capname, (u_int8_t *)str_ptr, ret); + if (pe->flags & DETECT_PCRE_CAPTURE_PKT) { + PktVarAdd(p, pe->capname, (u_int8_t *)str_ptr, ret); + } else if (pe->flags & DETECT_PCRE_CAPTURE_FLOW) { + FlowVarAdd(p->flow, pe->capname, (u_int8_t *)str_ptr, ret); + } } } } @@ -150,19 +157,25 @@ int DetectPcreSetup (Signature *s, SigMatch *m, char *regexstr) #define MAX_SUBSTRINGS 30 int ret = 0, res = 0; int ov[MAX_SUBSTRINGS]; - const char *capture_str_ptr = NULL; + const char *capture_str_ptr = NULL, *type_str_ptr = NULL; //printf("DetectPcreSetup: \'%s\'\n", regexstr); ret = pcre_exec(parse_capture_regex, parse_capture_regex_study, regexstr, strlen(regexstr), 0, 0, ov, MAX_SUBSTRINGS); if (ret > 1) { - res = pcre_get_substring((char *)regexstr, ov, MAX_SUBSTRINGS, 1, &capture_str_ptr); + res = pcre_get_substring((char *)regexstr, ov, MAX_SUBSTRINGS, 1, &type_str_ptr); + if (res < 0) { + printf("DetectPcreSetup: pcre_get_substring failed\n"); + return -1; + } + res = pcre_get_substring((char *)regexstr, ov, MAX_SUBSTRINGS, 2, &capture_str_ptr); if (res < 0) { printf("DetectPcreSetup: pcre_get_substring failed\n"); return -1; } } - //printf("DetectPcreSetup: \'%s\'\n", capture_str_ptr ? capture_str_ptr : "NULL"); + //printf("DetectPcreSetup: type \'%s\'\n", type_str_ptr ? type_str_ptr : "NULL"); + //printf("DetectPcreSetup: capture \'%s\'\n", capture_str_ptr ? capture_str_ptr : "NULL"); ret = pcre_exec(parse_regex, parse_regex_study, regexstr, strlen(regexstr), 0, 0, ov, MAX_SUBSTRINGS); if (ret < 0) { @@ -202,6 +215,13 @@ int DetectPcreSetup (Signature *s, SigMatch *m, char *regexstr) if (capture_str_ptr != NULL) { pd->capname = strdup((char *)capture_str_ptr); } + if (type_str_ptr != NULL) { + if (strcmp(type_str_ptr,"pkt") == 0) { + pd->flags |= DETECT_PCRE_CAPTURE_PKT; + } else if (strcmp(type_str_ptr,"flow") == 0) { + pd->flags |= DETECT_PCRE_CAPTURE_FLOW; + } + } //printf("DetectPcreSetup: pd->capname %s\n", pd->capname ? pd->capname : "NULL"); if (op != NULL) { @@ -276,6 +296,7 @@ int DetectPcreSetup (Signature *s, SigMatch *m, char *regexstr) SigMatchAppend(s,m,sm); + if (type_str_ptr != NULL) pcre_free((char *)type_str_ptr); if (capture_str_ptr != NULL) pcre_free((char *)capture_str_ptr); if (re != NULL) free(re); if (op_ptr != NULL) free(op_ptr); diff --git a/src/detect-pcre.h b/src/detect-pcre.h index 5472616c45..3598373dd9 100644 --- a/src/detect-pcre.h +++ b/src/detect-pcre.h @@ -1,15 +1,18 @@ #ifndef __DETECT_PCRE_H__ #define __DETECT_PCRE_H__ -#define DETECT_PCRE_DISTANCE 0x01 -#define DETECT_PCRE_WITHIN 0x02 -#define DETECT_PCRE_RELATIVE 0x04 +#define DETECT_PCRE_DISTANCE 0x0001 +#define DETECT_PCRE_WITHIN 0x0002 +#define DETECT_PCRE_RELATIVE 0x0004 -#define DETECT_PCRE_DISTANCE_NEXT 0x08 -#define DETECT_PCRE_WITHIN_NEXT 0x10 +#define DETECT_PCRE_DISTANCE_NEXT 0x0008 +#define DETECT_PCRE_WITHIN_NEXT 0x0010 -#define DETECT_PCRE_RAWBYTES 0x20 -#define DETECT_PCRE_URI 0x40 +#define DETECT_PCRE_RAWBYTES 0x0020 +#define DETECT_PCRE_URI 0x0040 + +#define DETECT_PCRE_CAPTURE_PKT 0x0080 +#define DETECT_PCRE_CAPTURE_FLOW 0x0100 typedef struct _DetectPcreData { /* pcre options */ @@ -23,7 +26,7 @@ typedef struct _DetectPcreData { int32_t within; int32_t distance; - u_int8_t flags; + u_int16_t flags; char *capname; } DetectPcreData; diff --git a/src/detect-pktvar.c b/src/detect-pktvar.c new file mode 100644 index 0000000000..d61acc90ad --- /dev/null +++ b/src/detect-pktvar.c @@ -0,0 +1,211 @@ +/* Simple pktvar content match part of the detection engine. + * + * Copyright (C) 2008 by Victor Julien */ + +#include +#include +#include "decode.h" +#include "detect.h" +#include "threads.h" +#include "pkt-var.h" +#include "detect-pktvar.h" +#include "util-binsearch.h" + +#define PARSE_REGEX "(.*),(.*)" +static pcre *parse_regex; +static pcre_extra *parse_regex_study; + +int DetectPktvarMatch (ThreadVars *, PatternMatcherThread *, Packet *, Signature *, SigMatch *); +int DetectPktvarSetup (Signature *, SigMatch *, char *); + +void DetectPktvarRegister (void) { + sigmatch_table[DETECT_PKTVAR].name = "pktvar"; + sigmatch_table[DETECT_PKTVAR].Match = DetectPktvarMatch; + sigmatch_table[DETECT_PKTVAR].Setup = DetectPktvarSetup; + sigmatch_table[DETECT_PKTVAR].Free = NULL; + sigmatch_table[DETECT_PKTVAR].RegisterTests = NULL; + + const char *eb; + int eo; + int opts = 0; + + parse_regex = pcre_compile(PARSE_REGEX, opts, &eb, &eo, NULL); + if(parse_regex == NULL) + { + printf("pcre compile of \"%s\" failed at offset %d: %s\n", PARSE_REGEX, eo, eb); + goto error; + } + + parse_regex_study = pcre_study(parse_regex, 0, &eb); + if(eb != NULL) + { + printf("pcre study failed: %s\n", eb); + goto error; + } + + return; + +error: + return; +} + +/* + * returns 0: no match + * 1: match + * -1: error + */ + +int DetectPktvarMatch (ThreadVars *t, PatternMatcherThread *pmt, Packet *p, Signature *s, SigMatch *m) +{ + int ret = 0; + DetectPktvarData *pd = (DetectPktvarData *)m->ctx; + + PktVar *pv = PktVarGet(p, pd->name); + if (pv != NULL) { + u_int8_t *ptr = BinSearch(pv->value, pv->value_len, pd->content, pd->content_len); + if (ptr != NULL) + ret = 1; + } + + return ret; +} + +int DetectPktvarSetup (Signature *s, SigMatch *m, char *rawstr) +{ + DetectPktvarData *cd = NULL; + SigMatch *sm = NULL; + char *str = rawstr; + char dubbed = 0; + u_int16_t len; + char *varname = NULL, *varcontent = NULL; +#define MAX_SUBSTRINGS 30 + int ret = 0, res = 0; + int ov[MAX_SUBSTRINGS]; + + ret = pcre_exec(parse_regex, parse_regex_study, rawstr, strlen(rawstr), 0, 0, ov, MAX_SUBSTRINGS); + if (ret > 1) { + const char *str_ptr; + res = pcre_get_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 1, &str_ptr); + if (res < 0) { + printf("DetectPcreSetup: pcre_get_substring failed\n"); + return -1; + } + varname = (char *)str_ptr; + + if (ret > 2) { + res = pcre_get_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 2, &str_ptr); + if (res < 0) { + printf("DetectPcreSetup: pcre_get_substring failed\n"); + return -1; + } + varcontent = (char *)str_ptr; + } + } + + printf("DetectPktvarSetup: varname %s, varcontent %s\n", varname, varcontent); + + if (varcontent[0] == '\"' && varcontent[strlen(varcontent)-1] == '\"') { + str = strdup(varcontent+1); + str[strlen(varcontent)-2] = '\0'; + dubbed = 1; + } + + len = strlen(str); + if (len == 0) + return -1; + + cd = malloc(sizeof(DetectPktvarData)); + if (cd == NULL) { + printf("DetectPktvarSetup malloc failed\n"); + goto error; + } + + char converted = 0; + + { + u_int16_t i, x; + u_int8_t bin = 0, binstr[3] = "", binpos = 0; + for (i = 0, x = 0; i < len; i++) { + // printf("str[%02u]: %c\n", i, str[i]); + if (str[i] == '|') { + if (bin) { + bin = 0; + } else { + bin = 1; + } + } else { + if (bin) { + if (isdigit(str[i]) || + str[i] == 'A' || str[i] == 'a' || + str[i] == 'B' || str[i] == 'b' || + str[i] == 'C' || str[i] == 'c' || + str[i] == 'D' || str[i] == 'd' || + str[i] == 'E' || str[i] == 'e' || + str[i] == 'F' || str[i] == 'f') { + // printf("part of binary: %c\n", str[i]); + + binstr[binpos] = (char)str[i]; + binpos++; + + if (binpos == 2) { + u_int8_t c = strtol((char *)binstr, (char **) NULL, 16) & 0xFF; +#ifdef DEBUG + printf("Binstr %X\n", c); +#endif + binpos = 0; + str[x] = c; + x++; + converted = 1; + } + } else if (str[i] == ' ') { + // printf("space as part of binary string\n"); + } + } else { + str[x] = str[i]; + x++; + } + } + } +//#ifdef DEBUG + for (i = 0; i < x; i++) { + if (isprint(str[i])) printf("%c", str[i]); + else printf("\\x%02u", str[i]); + } + printf("\n"); +//#endif + + if (converted) + len = x; + } + + cd->content = malloc(len); + if (cd->content == NULL) + return -1; + + cd->name = strdup(varname); + memcpy(cd->content, str, len); + cd->content_len = len; + cd->flags = 0; + + /* Okay so far so good, lets get this into a SigMatch + * and put it in the Signature. */ + sm = SigMatchAlloc(); + if (sm == NULL) + goto error; + + sm->type = DETECT_FLOWVAR; + sm->ctx = (void *)cd; + + SigMatchAppend(s,m,sm); + + if (dubbed) free(str); + return 0; + +error: + if (dubbed) free(str); + if (cd) free(cd); + if (sm) free(sm); + return -1; +} + + diff --git a/src/detect-pktvar.h b/src/detect-pktvar.h new file mode 100644 index 0000000000..5cf93bd08f --- /dev/null +++ b/src/detect-pktvar.h @@ -0,0 +1,17 @@ +#ifndef __DETECT_PKTVAR_H__ +#define __DETECT_PKTVAR_H__ + +#define DETECT_CONTENT_NOCASE 0x01 + +typedef struct _DetectPktvarData { + char *name; + u_int8_t *content; + u_int8_t content_len; + u_int8_t flags; +} DetectPktvarData; + +/* prototypes */ +void DetectPktvarRegister (void); + +#endif /* __DETECT_PKTVAR_H__ */ + diff --git a/src/detect.c b/src/detect.c index ce265b037f..a37c20c057 100644 --- a/src/detect.c +++ b/src/detect.c @@ -37,6 +37,7 @@ #include "detect-flow.h" #include "detect-dsize.h" #include "detect-flowvar.h" +#include "detect-pktvar.h" #include "detect-noalert.h" #include "action-globals.h" @@ -76,21 +77,21 @@ void SigLoadSignatures (void) /* The next 3 rules handle HTTP header capture. */ /* http_uri -- for uricontent */ - sig = SigInit("alert tcp any any -> any $HTTP_PORTS (msg:\"HTTP URI cap\"; flow:to_server; content:\"GET \"; depth:4; pcre:\"/^GET (?P.*) HTTP\\/\\d\\.\\d\\r\\n/G\"; noalert; sid:1;)"); + sig = SigInit("alert tcp any any -> any $HTTP_PORTS (msg:\"HTTP URI cap\"; flow:to_server; content:\"GET \"; depth:4; pcre:\"/^GET (?P.*) HTTP\\/\\d\\.\\d\\r\\n/G\"; noalert; sid:1;)"); if (sig) { prevsig = sig; g_de_ctx->sig_list = sig; } /* http_host -- for the log-httplog module */ - sig = SigInit("alert tcp any any -> any $HTTP_PORTS (msg:\"HTTP host cap\"; flow:to_server; content:\"Host:\"; pcre:\"/^Host: (?P.*)\\r\\n/m\"; noalert; sid:2;)"); + sig = SigInit("alert tcp any any -> any $HTTP_PORTS (msg:\"HTTP host cap\"; flow:to_server; content:\"Host:\"; pcre:\"/^Host: (?P.*)\\r\\n/m\"; noalert; sid:2;)"); if (sig == NULL) return; prevsig->next = sig; prevsig = sig; /* http_ua -- for the log-httplog module */ - sig = SigInit("alert tcp any any -> any $HTTP_PORTS (msg:\"HTTP UA cap\"; flow:to_server; content:\"User-Agent:\"; pcre:\"/^User-Agent: (?P.*)\\r\\n/m\"; noalert; sid:3;)"); + sig = SigInit("alert tcp any any -> any $HTTP_PORTS (msg:\"HTTP UA cap\"; flow:to_server; content:\"User-Agent:\"; pcre:\"/^User-Agent: (?P.*)\\r\\n/m\"; noalert; sid:3;)"); if (sig == NULL) return; prevsig->next = sig; @@ -740,7 +741,7 @@ static DetectAddressGroup *GetHeadPtr(DetectAddressGroupsHead *head, int family) return grhead; } -#define MAX_UNIQ_GROUPS 5 +#define MAX_UNIQ_GROUPS 8 /* set unique_groups to 0 for no grouping. * @@ -2279,6 +2280,7 @@ void SigTableSetup(void) { DetectFlowRegister(); DetectDsizeRegister(); DetectFlowvarRegister(); + DetectPktvarRegister(); DetectNoalertRegister(); u_int8_t i = 0; diff --git a/src/detect.h b/src/detect.h index a1474d76ae..5bb121e954 100644 --- a/src/detect.h +++ b/src/detect.h @@ -215,6 +215,7 @@ enum { DETECT_FLOW, DETECT_DSIZE, DETECT_FLOWVAR, + DETECT_PKTVAR, DETECT_NOALERT, DETECT_ADDRESS, diff --git a/src/log-httplog.c b/src/log-httplog.c index 593e4fc052..ded975d650 100644 --- a/src/log-httplog.c +++ b/src/log-httplog.c @@ -18,8 +18,7 @@ #include "vips.h" #include "debug.h" #include "detect.h" -#include "flow.h" -#include "flow-var.h" +#include "pkt-var.h" #include "threadvars.h" #include "tm-modules.h" @@ -78,33 +77,29 @@ int LogHttplogIPv4(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) LogHttplogThread *aft = (LogHttplogThread *)data; int i; char timebuf[64], hostname[256] = "unknown", ua[256] = "unknown"; - FlowVar *fv; + PktVar *pv; u_int16_t size; /* XXX add a better check for this */ if (p->http_uri.cnt == 0) return 0; - /* we need a lock */ - mutex_lock(&p->flow->m); - - fv = FlowVarGet(p->flow, "http_host"); - if (fv != NULL) { - size = fv->value_len; + pv = PktVarGet(p, "http_host"); + if (pv != NULL) { + size = pv->value_len; if (size >= sizeof(hostname)) size = sizeof(hostname) - 1; - strncpy(hostname,(char *)fv->value,size); + strncpy(hostname,(char *)pv->value,size); } - fv = FlowVarGet(p->flow, "http_ua"); - if (fv != NULL) { - size = fv->value_len; + pv = PktVarGet(p, "http_ua"); + if (pv != NULL) { + size = pv->value_len; if (size >= sizeof(ua)) size = sizeof(ua) - 1; - strncpy(ua,(char *)fv->value,size); + strncpy(ua,(char *)pv->value,size); } - mutex_unlock(&p->flow->m); CreateTimeString(&p->ts, timebuf, sizeof(timebuf)); @@ -125,33 +120,29 @@ int LogHttplogIPv6(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) LogHttplogThread *aft = (LogHttplogThread *)data; int i; char timebuf[64], hostname[256] = "unknown", ua[256] = "unknown"; - FlowVar *fv; + PktVar *pv; u_int16_t size; /* XXX add a better check for this */ if (p->http_uri.cnt == 0) return 0; - /* we need a lock */ - mutex_lock(&p->flow->m); - - fv = FlowVarGet(p->flow, "http_host"); - if (fv != NULL) { - size = fv->value_len; + pv = PktVarGet(p, "http_host"); + if (pv != NULL) { + size = pv->value_len; if (size >= sizeof(hostname)) size = sizeof(hostname) - 1; - strncpy(hostname,(char *)fv->value,size); + strncpy(hostname,(char *)pv->value,size); } - fv = FlowVarGet(p->flow, "http_ua"); - if (fv != NULL) { - size = fv->value_len; + pv = PktVarGet(p, "http_ua"); + if (pv != NULL) { + size = pv->value_len; if (size >= sizeof(ua)) size = sizeof(ua) - 1; - strncpy(ua,(char *)fv->value,size); + strncpy(ua,(char *)pv->value,size); } - mutex_unlock(&p->flow->m); CreateTimeString(&p->ts, timebuf, sizeof(timebuf)); diff --git a/src/pkt-var.c b/src/pkt-var.c new file mode 100644 index 0000000000..9749730e34 --- /dev/null +++ b/src/pkt-var.c @@ -0,0 +1,93 @@ +/* implement per packet vars */ + +/* TODO + * - move away from a linked list implementation + * - use different datatypes, such as string, int, etc. + * - have more than one instance of the same var, and be able to match on a + * specific one, or one all at a time. So if a certain capture matches + * multiple times, we can operate on all of them. + */ + +#include +#include "decode.h" +#include "pkt-var.h" + +/* puts a new value into a pktvar */ +void PktVarUpdate(PktVar *pv, u_int8_t *value, u_int16_t size) { + if (pv->value) free(pv->value); + pv->value = value; + pv->value_len = size; +} + +/* get the pktvar with name 'name' from the pkt + * + * name is a normal string*/ +PktVar *PktVarGet(Packet *p, char *name) { + PktVar *pv = p->pktvar; + + for (;pv != NULL; pv = pv->next) { + if (pv->name && strcmp(pv->name, name) == 0) + return pv; + } + + return NULL; +} + +/* add a pktvar to the pkt, or update it */ +void PktVarAdd(Packet *p, char *name, u_int8_t *value, u_int16_t size) { + //printf("Adding packet var \"%s\" with value(%d) \"%s\"\n", name, size, value); + + PktVar *pv = PktVarGet(p, name); + if (pv == NULL) { + pv = malloc(sizeof(PktVar)); + if (pv == NULL) + return; + + pv->name = name; + pv->value = value; + pv->value_len = size; + pv->next = NULL; + + PktVar *tpv = p->pktvar; + if (p->pktvar == NULL) p->pktvar = pv; + else { + while(tpv) { + if (tpv->next == NULL) { + tpv->next = pv; + return; + } + + tpv = tpv->next; + } + } + } else { + PktVarUpdate(pv, value, size); + } +} + +void PktVarFree(PktVar *pv) { + if (pv == NULL) + return; + + pv->name = NULL; + if (pv->value) free(pv->value); + + if (pv->next) PktVarFree(pv->next); +} + +void PktVarPrint(PktVar *pv) { + u_int16_t i; + + if (pv == NULL) + return; + + printf("Name \"%s\", Value \"", pv->name); + for (i = 0; i < pv->value_len; i++) { + if (isprint(pv->value[i])) printf("%c", pv->value[i]); + else printf("\\%02X", pv->value[i]); + } + printf("\", Len \"%u\"\n", pv->value_len); + + PktVarPrint(pv->next); +} + diff --git a/src/pkt-var.h b/src/pkt-var.h new file mode 100644 index 0000000000..ce168f5042 --- /dev/null +++ b/src/pkt-var.h @@ -0,0 +1,11 @@ +/* Copyright (c) 2008 Victor Julien */ +#ifndef __PKT_VAR_H__ +#define __PKT_VAR_H__ + +void PktVarAdd(Packet *, char *, u_int8_t *, u_int16_t); +PktVar *PktVarGet(Packet *, char *); +void PktVarFree(PktVar *); +void PktVarPrint(PktVar *); + +#endif /* __PKT_VAR_H__ */ +