|
Packit |
1422b7 |
/**
|
|
Packit |
1422b7 |
* @file ptree.h
|
|
Packit |
1422b7 |
* @brief The parse tree object.
|
|
Packit |
1422b7 |
* @class ln_ptree ptree.h
|
|
Packit |
1422b7 |
*//*
|
|
Packit |
1422b7 |
* Copyright 2013 by Rainer Gerhards and Adiscon GmbH.
|
|
Packit |
1422b7 |
*
|
|
Packit |
1422b7 |
* Modified by Pavel Levshin (pavel@levshin.spb.ru) in 2013
|
|
Packit |
1422b7 |
*
|
|
Packit |
1422b7 |
* This file is meant to be included by applications using liblognorm.
|
|
Packit |
1422b7 |
* For lognorm library files themselves, include "lognorm.h".
|
|
Packit |
1422b7 |
*
|
|
Packit |
1422b7 |
* This file is part of liblognorm.
|
|
Packit |
1422b7 |
*
|
|
Packit |
1422b7 |
* This library is free software; you can redistribute it and/or
|
|
Packit |
1422b7 |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
1422b7 |
* License as published by the Free Software Foundation; either
|
|
Packit |
1422b7 |
* version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
1422b7 |
*
|
|
Packit |
1422b7 |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
1422b7 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
1422b7 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
1422b7 |
* Lesser General Public License for more details.
|
|
Packit |
1422b7 |
*
|
|
Packit |
1422b7 |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
1422b7 |
* License along with this library; if not, write to the Free Software
|
|
Packit |
1422b7 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
Packit |
1422b7 |
*
|
|
Packit |
1422b7 |
* A copy of the LGPL v2.1 can be found in the file "COPYING" in this distribution.
|
|
Packit |
1422b7 |
*/
|
|
Packit |
1422b7 |
#ifndef LIBLOGNORM_PTREE_H_INCLUDED
|
|
Packit |
1422b7 |
#define LIBLOGNORM_PTREE_H_INCLUDED
|
|
Packit |
1422b7 |
#include <stdio.h>
|
|
Packit |
1422b7 |
#include <libestr.h>
|
|
Packit |
1422b7 |
|
|
Packit |
1422b7 |
#define ORIGINAL_MSG_KEY "originalmsg"
|
|
Packit |
1422b7 |
#define UNPARSED_DATA_KEY "unparsed-data"
|
|
Packit |
1422b7 |
|
|
Packit |
1422b7 |
typedef struct ln_ptree ln_ptree; /**< the parse tree object */
|
|
Packit |
1422b7 |
typedef struct ln_fieldList_s ln_fieldList_t;
|
|
Packit |
1422b7 |
|
|
Packit |
1422b7 |
/**
|
|
Packit |
1422b7 |
* List of supported fields inside parse tree.
|
|
Packit |
1422b7 |
* This list holds all fields and their description. While normalizing,
|
|
Packit |
1422b7 |
* fields are tried in the order of this list. So the enqeue order
|
|
Packit |
1422b7 |
* dictates precedence during parsing.
|
|
Packit |
1422b7 |
*
|
|
Packit |
1422b7 |
* value list. This is a single-linked list. In a later stage, we should
|
|
Packit |
1422b7 |
* optimize it so that frequently used fields are moved "up" towards
|
|
Packit |
1422b7 |
* the root of the list. In any case, we do NOT expect this list to
|
|
Packit |
1422b7 |
* be long, as the parser should already have gotten quite specific when
|
|
Packit |
1422b7 |
* we hit a fieldconst .
|
|
Packit |
1422b7 |
*/
|
|
Packit |
1422b7 |
struct ln_fieldList_s {
|
|
Packit |
1422b7 |
es_str_t *name; /**< field name */
|
|
Packit |
1422b7 |
es_str_t *data; /**< extra data to be passed to parser */
|
|
Packit |
1422b7 |
es_str_t *raw_data; /**< extra untouched (unescaping is not done) data availble to be used by parser */
|
|
Packit |
1422b7 |
void *parser_data; /** opaque data that the field-parser understands */
|
|
Packit |
1422b7 |
void (*parser_data_destructor)(void **); /** destroy opaque data that field-parser understands */
|
|
Packit |
1422b7 |
int (*parser)(const char*, size_t, size_t*, const ln_fieldList_t *,
|
|
Packit |
1422b7 |
size_t*, struct json_object **); /**< parser to use */
|
|
Packit |
1422b7 |
ln_ptree *subtree; /**< subtree to follow if parser succeeded */
|
|
Packit |
1422b7 |
ln_fieldList_t *next; /**< list housekeeping, next node (or NULL) */
|
|
Packit |
1422b7 |
unsigned char isIPTables; /**< special parser: iptables! */
|
|
Packit |
1422b7 |
};
|
|
Packit |
1422b7 |
|
|
Packit |
1422b7 |
|
|
Packit |
1422b7 |
/* parse tree object
|
|
Packit |
1422b7 |
*/
|
|
Packit |
1422b7 |
struct ln_ptree {
|
|
Packit |
1422b7 |
ln_ctx ctx; /**< our context */
|
|
Packit |
1422b7 |
ln_ptree **parentptr; /**< pointer to *us* *inside* the parent
|
|
Packit |
1422b7 |
BUT this is NOT a pointer to the parent! */
|
|
Packit |
1422b7 |
ln_fieldList_t *froot; /**< root of field list */
|
|
Packit |
1422b7 |
ln_fieldList_t *ftail; /**< tail of field list */
|
|
Packit |
1422b7 |
struct {
|
|
Packit |
1422b7 |
unsigned isTerminal:1; /**< designates this node a terminal sequence? */
|
|
Packit |
1422b7 |
} flags;
|
|
Packit |
1422b7 |
struct json_object *tags; /* tags to assign to events of this type */
|
|
Packit |
1422b7 |
/* the respresentation below requires a lof of memory but is
|
|
Packit |
1422b7 |
* very fast. As an alternate approach, we can use a hash table
|
|
Packit |
1422b7 |
* where we ignore control characters. That should work quite well.
|
|
Packit |
1422b7 |
* But we do not do this in the initial step.
|
|
Packit |
1422b7 |
*/
|
|
Packit |
1422b7 |
ln_ptree *subtree[256];
|
|
Packit |
1422b7 |
unsigned short lenPrefix; /**< length of common prefix, 0->none */
|
|
Packit |
1422b7 |
union {
|
|
Packit |
1422b7 |
unsigned char *ptr; /**< use if data element is too large */
|
|
Packit |
1422b7 |
unsigned char data[16]; /**< fast lookup for small string */
|
|
Packit |
1422b7 |
} prefix; /**< a common prefix string for all of this node */
|
|
Packit |
1422b7 |
struct {
|
|
Packit |
1422b7 |
unsigned visited;
|
|
Packit |
1422b7 |
unsigned backtracked; /**< incremented when backtracking was initiated */
|
|
Packit |
1422b7 |
unsigned terminated;
|
|
Packit |
1422b7 |
} stats; /**< usage statistics */
|
|
Packit |
1422b7 |
};
|
|
Packit |
1422b7 |
|
|
Packit |
1422b7 |
|
|
Packit |
1422b7 |
/* Methods */
|
|
Packit |
1422b7 |
|
|
Packit |
1422b7 |
/**
|
|
Packit |
1422b7 |
* Allocates and initializes a new parse tree node.
|
|
Packit |
1422b7 |
* @memberof ln_ptree
|
|
Packit |
1422b7 |
*
|
|
Packit |
1422b7 |
* @param[in] ctx current library context. This MUST match the
|
|
Packit |
1422b7 |
* context of the parent.
|
|
Packit |
1422b7 |
* @param[in] parent pointer to the new node inside the parent
|
|
Packit |
1422b7 |
*
|
|
Packit |
1422b7 |
* @return pointer to new node or NULL on error
|
|
Packit |
1422b7 |
*/
|
|
Packit |
1422b7 |
struct ln_ptree* ln_newPTree(ln_ctx ctx, struct ln_ptree** parent);
|
|
Packit |
1422b7 |
|
|
Packit |
1422b7 |
|
|
Packit |
1422b7 |
/**
|
|
Packit |
1422b7 |
* Free a parse tree and destruct all members.
|
|
Packit |
1422b7 |
* @memberof ln_ptree
|
|
Packit |
1422b7 |
*
|
|
Packit |
1422b7 |
* @param[in] tree pointer to ptree to free
|
|
Packit |
1422b7 |
*/
|
|
Packit |
1422b7 |
void ln_deletePTree(struct ln_ptree *tree);
|
|
Packit |
1422b7 |
|
|
Packit |
1422b7 |
/**
|
|
Packit |
1422b7 |
* Free a parse tree node and destruct all members.
|
|
Packit |
1422b7 |
* @memberof ln_ptree
|
|
Packit |
1422b7 |
*
|
|
Packit |
1422b7 |
* @param[in] node pointer to free
|
|
Packit |
1422b7 |
*/
|
|
Packit |
1422b7 |
void ln_deletePTreeNode(ln_fieldList_t *node);
|
|
Packit |
1422b7 |
|
|
Packit |
1422b7 |
/**
|
|
Packit |
1422b7 |
* Add a field description to the a tree.
|
|
Packit |
1422b7 |
* The field description will be added as last field. Fields are
|
|
Packit |
1422b7 |
* parsed in the order they have been added, so be sure to care
|
|
Packit |
1422b7 |
* about the order if that matters.
|
|
Packit |
1422b7 |
* @memberof ln_ptree
|
|
Packit |
1422b7 |
*
|
|
Packit |
1422b7 |
* @param[in] tree pointer to ptree to modify
|
|
Packit |
1422b7 |
* @param[in] fielddescr a fully populated (and initialized)
|
|
Packit |
1422b7 |
* field description node
|
|
Packit |
1422b7 |
* @returns 0 on success, something else otherwise
|
|
Packit |
1422b7 |
*/
|
|
Packit |
1422b7 |
int ln_addFDescrToPTree(struct ln_ptree **tree, ln_fieldList_t *node);
|
|
Packit |
1422b7 |
|
|
Packit |
1422b7 |
|
|
Packit |
1422b7 |
/**
|
|
Packit |
1422b7 |
* Add a literal to a ptree.
|
|
Packit |
1422b7 |
* Creates new tree nodes as necessary.
|
|
Packit |
1422b7 |
* @memberof ln_ptree
|
|
Packit |
1422b7 |
*
|
|
Packit |
1422b7 |
* @param[in] tree root of tree where to add
|
|
Packit |
1422b7 |
* @param[in] str literal (string) to add
|
|
Packit |
1422b7 |
* @param[in] offs offset of where in literal adding should start
|
|
Packit |
1422b7 |
*
|
|
Packit |
1422b7 |
* @return NULL on error, otherwise pointer to deepest tree added
|
|
Packit |
1422b7 |
*/
|
|
Packit |
1422b7 |
struct ln_ptree*
|
|
Packit |
1422b7 |
ln_addPTree(struct ln_ptree *tree, es_str_t *str, size_t offs);
|
|
Packit |
1422b7 |
|
|
Packit |
1422b7 |
|
|
Packit |
1422b7 |
/**
|
|
Packit |
1422b7 |
* Display the content of a ptree (debug function).
|
|
Packit |
1422b7 |
* This is a debug aid that spits out a textual representation
|
|
Packit |
1422b7 |
* of the provided ptree via multiple calls of the debug callback.
|
|
Packit |
1422b7 |
*
|
|
Packit |
1422b7 |
* @param tree ptree to display
|
|
Packit |
1422b7 |
* @param level recursion level, must be set to 0 on initial call
|
|
Packit |
1422b7 |
*/
|
|
Packit |
1422b7 |
void ln_displayPTree(struct ln_ptree *tree, int level);
|
|
Packit |
1422b7 |
|
|
Packit |
1422b7 |
|
|
Packit |
1422b7 |
/**
|
|
Packit |
1422b7 |
* Generate a DOT graph.
|
|
Packit |
1422b7 |
* Well, actually it does not generate the graph itself, but a
|
|
Packit |
1422b7 |
* control file that is suitable for the GNU DOT tool. Such a file
|
|
Packit |
1422b7 |
* can be very useful to understand complex sample databases
|
|
Packit |
1422b7 |
* (not to mention that it is probably fun for those creating
|
|
Packit |
1422b7 |
* samples).
|
|
Packit |
1422b7 |
* The dot commands are appended to the provided string.
|
|
Packit |
1422b7 |
*
|
|
Packit |
1422b7 |
* @param[in] tree ptree to display
|
|
Packit |
1422b7 |
* @param[out] str string which receives the DOT commands.
|
|
Packit |
1422b7 |
*/
|
|
Packit |
1422b7 |
void ln_genDotPTreeGraph(struct ln_ptree *tree, es_str_t **str);
|
|
Packit |
1422b7 |
|
|
Packit |
1422b7 |
|
|
Packit |
1422b7 |
/**
|
|
Packit |
1422b7 |
* Build a ptree based on the provided string, but only if necessary.
|
|
Packit |
1422b7 |
* The passed-in tree is searched and traversed for str. If a node exactly
|
|
Packit |
1422b7 |
* matching str is found, that node is returned. If no exact match is found,
|
|
Packit |
1422b7 |
* a new node is added. Existing nodes may be split, if a so-far common
|
|
Packit |
1422b7 |
* prefix needs to be split in order to add the new node.
|
|
Packit |
1422b7 |
*
|
|
Packit |
1422b7 |
* @param[in] tree root of the current tree
|
|
Packit |
1422b7 |
* @param[in] str string to be added
|
|
Packit |
1422b7 |
* @param[in] offs offset into str where match needs to start
|
|
Packit |
1422b7 |
* (this is required for recursive calls to handle
|
|
Packit |
1422b7 |
* common prefixes)
|
|
Packit |
1422b7 |
* @return NULL on error, otherwise the ptree leaf that
|
|
Packit |
1422b7 |
* corresponds to the parameters passed.
|
|
Packit |
1422b7 |
*/
|
|
Packit |
1422b7 |
struct ln_ptree * ln_buildPTree(struct ln_ptree *tree, es_str_t *str, size_t offs);
|
|
Packit |
1422b7 |
|
|
Packit |
1422b7 |
/* internal helper for displaying stats */
|
|
Packit |
1422b7 |
void ln_fullPTreeStats(ln_ctx ctx, FILE *const fp, const int extendedStats);
|
|
Packit |
1422b7 |
|
|
Packit |
1422b7 |
#endif /* #ifndef LOGNORM_PTREE_H_INCLUDED */
|