struct PktVar_ *next; /* right now just implement this as a list,
* in the long run we have thing of something
* faster. */
- uint8_t *value;
+ uint16_t key_len;
uint16_t value_len;
+ uint8_t *key;
+ uint8_t *value;
} PktVar;
#ifdef PROFILING
return -1;
}
+/** \brief Store flowvar in det_ctx so we can exec it post-match */
+int DetectVarStoreMatchKeyValue(DetectEngineThreadCtx *det_ctx,
+ uint8_t *key, uint16_t key_len,
+ uint8_t *buffer, uint16_t len, int type)
+{
+ DetectVarList *fs = SCCalloc(1, sizeof(*fs));
+ if (unlikely(fs == NULL))
+ return -1;
+
+ fs->len = len;
+ fs->type = type;
+ fs->buffer = buffer;
+ fs->key = key;
+ fs->key_len = key_len;
+
+ fs->next = det_ctx->varlist;
+ det_ctx->varlist = fs;
+ return 0;
+}
/** \brief Store flowvar in det_ctx so we can exec it post-match */
-int DetectVarStoreMatch(DetectEngineThreadCtx *det_ctx, uint32_t idx,
+int DetectVarStoreMatch(DetectEngineThreadCtx *det_ctx,
+ uint32_t idx,
uint8_t *buffer, uint16_t len, int type)
{
DetectVarList *fs = det_ctx->varlist;
}
if (fs == NULL) {
- fs = SCMalloc(sizeof(*fs));
+ fs = SCCalloc(1, sizeof(*fs));
if (unlikely(fs == NULL))
return -1;
prev = NULL;
fs = det_ctx->varlist;
while (fs != NULL) {
- if (fd->idx == fs->idx) {
+ if (fd->idx == 0 || fd->idx == fs->idx) {
SCLogDebug("adding to the flow %u:", fs->idx);
//PrintRawDataFp(stdout, fs->buffer, fs->len);
FlowVarAddStrNoLock(p->flow, fs->idx, fs->buffer, fs->len);
/* memory at fs->buffer is now the responsibility of
* the flowvar code. */
+ } else if (fs->type == DETECT_VAR_TYPE_PKT_POSTMATCH && fs->key && p) {
+ /* pkt key/value */
+ if (PktVarAddKeyValue(p, (uint8_t *)fs->key, fs->key_len,
+ (uint8_t *)fs->buffer, fs->len) == -1)
+ {
+ SCFree(fs->key);
+ SCFree(fs->buffer);
+ /* the rest of fs is freed below */
+ }
} else if (fs->type == DETECT_VAR_TYPE_PKT_POSTMATCH && p) {
- PktVarAdd(p, fs->idx, fs->buffer, fs->len);
+ if (PktVarAdd(p, fs->idx, fs->buffer, fs->len) == -1) {
+ SCFree(fs->buffer);
+ /* the rest of fs is freed below */
+ }
}
if (fs == det_ctx->varlist) {
void DetectFlowvarRegister (void);
int DetectFlowvarPostMatchSetup(Signature *s, uint32_t idx);
-int DetectVarStoreMatch(DetectEngineThreadCtx *, uint32_t, uint8_t *, uint16_t, int);
+int DetectVarStoreMatch(DetectEngineThreadCtx *,
+ uint32_t, uint8_t *, uint16_t, int);
+int DetectVarStoreMatchKeyValue(DetectEngineThreadCtx *,
+ uint8_t *, uint16_t, uint8_t *, uint16_t, int);
/* For use only by DetectFlowvarProcessList() */
void DetectVarProcessListInternal(DetectVarList *fs, Flow *f, Packet *p);
SCLogDebug("data %p/%u, type %u id %u p %p",
str_ptr, ret, pe->captypes[x], pe->capids[x], p);
- if (pe->captypes[x] == VAR_TYPE_PKT_VAR) {
+ if (pe->captypes[x] == VAR_TYPE_PKT_VAR_KV) {
+ /* get the value, as first capture is the key */
+ const char *str_ptr2;
+ int ret2 = pcre_get_substring((char *)ptr, ov, MAX_SUBSTRINGS, x+2, &str_ptr2);
+ if (unlikely(ret2 == 0)) {
+ break;
+ }
+ /* key length is limited to 256 chars */
+ uint16_t key_len = (ret < 0xff) ? (uint16_t)ret : 0xff;
+ capture_len = (ret2 < 0xffff) ? (uint16_t)ret2 : 0xffff;
+
+ (void)DetectVarStoreMatchKeyValue(det_ctx,
+ (uint8_t *)str_ptr, key_len,
+ (uint8_t *)str_ptr2, capture_len,
+ DETECT_VAR_TYPE_PKT_POSTMATCH);
+
+ } else if (pe->captypes[x] == VAR_TYPE_PKT_VAR) {
/* store max 64k. Errors are ignored */
capture_len = (ret < 0xffff) ? (uint16_t)ret : 0xffff;
(void)DetectVarStoreMatch(det_ctx, pe->capids[x],
char *name_array[DETECT_PCRE_CAPTURE_MAX] = { NULL };
int name_idx = 0;
int capture_cnt = 0;
+ int key = 0;
SCLogDebug("regexstr %s, pd %p", regexstr, pd);
}
SCLogDebug("name '%s'", name_array[name_idx]);
- if (strncmp(name_array[name_idx], "flow:", 5) == 0) {
+ if (strcmp(name_array[name_idx], "pkt:key") == 0) {
+ key = 1;
+ SCLogDebug("key-value/key");
+
+ pd->captypes[pd->idx] = VAR_TYPE_PKT_VAR_KV;
+ SCLogDebug("id %u type %u", pd->capids[pd->idx], pd->captypes[pd->idx]);
+ pd->idx++;
+
+ } else if (key == 1 && strcmp(name_array[name_idx], "pkt:value") == 0) {
+ SCLogDebug("key-value/value");
+ key = 0;
+
+ /* kv error conditions */
+ } else if (key == 0 && strcmp(name_array[name_idx], "pkt:value") == 0) {
+ return -1;
+ } else if (key == 1) {
+ return -1;
+
+ } else if (strncmp(name_array[name_idx], "flow:", 5) == 0) {
pd->capids[pd->idx] = VarNameStoreSetupAdd(name_array[name_idx]+5, VAR_TYPE_FLOW_VAR);
pd->captypes[pd->idx] = VAR_TYPE_FLOW_VAR;
pd->idx++;
typedef struct DetectVarList_ {
uint32_t idx; /**< flowvar name idx */
uint16_t len; /**< data len */
+ uint16_t key_len;
int type; /**< type of store candidate POSTMATCH or ALWAYS */
+ uint8_t *key;
uint8_t *buffer; /**< alloc'd buffer, may be freed by
post-match, post-non-match */
struct DetectVarList_ *next;
json_t *js_pktvars = NULL;
PktVar *pv = p->pktvar;
while (pv != NULL) {
- const char *varname = VarNameStoreLookupById(pv->id, VAR_TYPE_PKT_VAR);
- if (varname) {
+ if (pv->key || pv->id > 0) {
if (js_pktvars == NULL) {
- js_pktvars = json_object();
+ js_pktvars = json_array();
if (js_pktvars == NULL)
break;
}
+ json_t *js_pair = json_object();
+ if (js_pair == NULL) {
+ break;
+ }
- uint32_t len = pv->value_len;
- uint8_t printable_buf[len + 1];
- uint32_t offset = 0;
- PrintStringsToBuffer(printable_buf, &offset,
- sizeof(printable_buf),
- pv->value, pv->value_len);
-
- json_object_set_new(js_pktvars, varname,
- json_string((char *)printable_buf));
+ if (pv->key != NULL) {
+ uint32_t offset = 0;
+ uint8_t keybuf[pv->key_len + 1];
+ PrintStringsToBuffer(keybuf, &offset,
+ sizeof(keybuf),
+ pv->key, pv->key_len);
+ uint32_t len = pv->value_len;
+ uint8_t printable_buf[len + 1];
+ offset = 0;
+ PrintStringsToBuffer(printable_buf, &offset,
+ sizeof(printable_buf),
+ pv->value, pv->value_len);
+ json_object_set_new(js_pair, (char *)keybuf,
+ json_string((char *)printable_buf));
+ } else {
+ const char *varname = VarNameStoreLookupById(pv->id, VAR_TYPE_PKT_VAR);
+ uint32_t len = pv->value_len;
+ uint8_t printable_buf[len + 1];
+ uint32_t offset = 0;
+ PrintStringsToBuffer(printable_buf, &offset,
+ sizeof(printable_buf),
+ pv->value, pv->value_len);
+
+ json_object_set_new(js_pair, varname,
+ json_string((char *)printable_buf));
+ }
+ json_array_append_new(js_pktvars, js_pair);
}
pv = pv->next;
}
#include "pkt-var.h"
#include "util-debug.h"
-/* puts a new value into a pktvar */
-static void PktVarUpdate(PktVar *pv, uint8_t *value, uint16_t size)
-{
- if (pv->value)
- SCFree(pv->value);
- pv->value = value;
- pv->value_len = size;
-}
-
/* get the pktvar with name 'name' from the pkt
*
* name is a normal string*/
return NULL;
}
-/* add a pktvar to the pkt, or update it */
-void PktVarAdd(Packet *p, uint32_t id, uint8_t *value, uint16_t size)
+/**
+ * \brief add a key-value pktvar to the pkt
+ * \retval r 0 ok, -1 error
+ */
+int PktVarAddKeyValue(Packet *p, uint8_t *key, uint16_t ksize, uint8_t *value, uint16_t size)
{
- //printf("Adding packet var \"%s\" with value(%" PRId32 ") \"%s\"\n", name, size, value);
+ PktVar *pv = SCCalloc(1, sizeof(PktVar));
+ if (unlikely(pv == NULL))
+ return -1;
- PktVar *pv = PktVarGet(p, id);
- if (pv == NULL) {
- pv = SCMalloc(sizeof(PktVar));
- if (unlikely(pv == NULL))
- return;
+ pv->key = key;
+ pv->key_len = ksize;
+ pv->value = value;
+ pv->value_len = size;
- pv->id = id;
- 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 0;
+ }
+ tpv = tpv->next;
+ }
+ }
+ return 0;
+}
+
+/**
+ * \brief add a key-value pktvar to the pkt
+ * \retval r 0 ok, -1 error
+ */
+int PktVarAdd(Packet *p, uint32_t id, uint8_t *value, uint16_t size)
+{
+ PktVar *pv = SCCalloc(1, sizeof(PktVar));
+ if (unlikely(pv == NULL))
+ return -1;
+
+ pv->id = id;
+ pv->value = value;
+ pv->value_len = size;
- 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;
+ PktVar *tpv = p->pktvar;
+ if (p->pktvar == NULL)
+ p->pktvar = pv;
+ else {
+ while(tpv) {
+ if (tpv->next == NULL) {
+ tpv->next = pv;
+ return 0;
}
+ tpv = tpv->next;
}
- } else {
- PktVarUpdate(pv, value, size);
}
+ return 0;
}
void PktVarFree(PktVar *pv)
if (pv == NULL)
return;
+ if (pv->key != NULL)
+ SCFree(pv->key);
if (pv->value != NULL)
SCFree(pv->value);
PktVar *pv_next = pv->next;
#ifndef __PKT_VAR_H__
#define __PKT_VAR_H__
-void PktVarAdd(Packet *, uint32_t id, uint8_t *, uint16_t);
+int WARN_UNUSED PktVarAddKeyValue(Packet *, uint8_t *, uint16_t, uint8_t *, uint16_t);
+int WARN_UNUSED PktVarAdd(Packet *, uint32_t id, uint8_t *, uint16_t);
PktVar *PktVarGet(Packet *, uint32_t id);
void PktVarFree(PktVar *);
VAR_TYPE_PKT_BIT,
VAR_TYPE_PKT_INT,
VAR_TYPE_PKT_VAR,
+ VAR_TYPE_PKT_VAR_KV, // key-value
VAR_TYPE_FLOW_BIT,
VAR_TYPE_FLOW_INT,