%PDF- %PDF-
| Direktori : /proc/thread-self/root/backups/router/usr/local/include/syslog-ng/logmsg/ |
| Current File : //proc/thread-self/root/backups/router/usr/local/include/syslog-ng/logmsg/logmsg.h |
/*
* Copyright (c) 2002-2013 Balabit
* Copyright (c) 1998-2013 Balázs Scheidler
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As an additional exemption you are allowed to compile & link against the
* OpenSSL libraries as published by the OpenSSL project. See the file
* COPYING for details.
*
*/
#ifndef LOGMSG_H_INCLUDED
#define LOGMSG_H_INCLUDED
#include "syslog-ng.h"
#include "gsockaddr.h"
#include "atomic.h"
#include "serialize.h"
#include "timeutils/unixtime.h"
#include "logmsg/nvtable.h"
#include "logmsg/tags.h"
#include "messages.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <iv_list.h>
typedef enum
{
AT_UNDEFINED,
AT_PROCESSED,
AT_ABORTED,
AT_SUSPENDED
} AckType;
#define IS_ACK_ABORTED(x) ((x) == AT_ABORTED ? 1 : 0)
#define IS_ABORTFLAG_ON(x) ((x) == 1 ? TRUE : FALSE)
#define IS_ACK_SUSPENDED(x) ((x) == AT_SUSPENDED ? 1 : 0)
#define IS_SUSPENDFLAG_ON(x) ((x) == 1 ? TRUE : FALSE)
#define STRICT_ROUND_TO_NEXT_EIGHT(x) ((x + 8) & ~7)
typedef struct _LogPathOptions LogPathOptions;
typedef void (*LMAckFunc)(LogMessage *lm, AckType ack_type);
#define LOGMSG_MAX_MATCHES 256
typedef enum
{
LM_TS_STAMP = 0,
LM_TS_RECVD = 1,
LM_TS_PROCESSED = 2,
LM_TS_MAX
} LogMessageTimeStamp;
/* builtin values */
enum
{
LM_V_NONE,
LM_V_HOST,
LM_V_HOST_FROM,
LM_V_MESSAGE,
LM_V_PROGRAM,
LM_V_PID,
LM_V_MSGID,
LM_V_SOURCE,
LM_V_LEGACY_MSGHDR,
/* NOTE: this is used as the number of "statically" allocated elements in
* an NVTable. NVTable may impose restrictions on this value (for
* instance had to be an even number earlier). So be sure to validate
* whether LM_V_MAX would fit NVTable if you add further enums here.
*/
LM_V_MAX,
/* these are dynamic values but with a predefined handle */
LM_V_RAWMSG,
LM_V_TRANSPORT,
LM_V_MSGFORMAT,
LM_V_FILE_NAME,
LM_V_PREDEFINED_MAX,
};
enum
{
/* means that the message is not valid utf8 */
LM_T_MSG_UTF8_SANITIZED,
/* missing <pri> value */
LM_T_SYSLOG_MISSING_PRI,
/* invalid <pri> value */
LM_T_SYSLOG_INVALID_PRI,
/* no timestamp present in the original message */
LM_T_SYSLOG_MISSING_TIMESTAMP,
/* hostname field does not seem valid, check-hostname(yes) failed */
LM_T_SYSLOG_INVALID_HOSTNAME,
/* we seem to have found an octet count in front of the message */
LM_T_SYSLOG_UNEXPECTED_FRAMING,
/* no date & host information in the syslog message */
LM_T_SYSLOG_RFC3164_MISSING_HEADER,
/* hostname field missing */
LM_T_SYSLOG_RFC5424_MISSING_HOSTNAME,
/* program field missing */
LM_T_SYSLOG_RFC5424_MISSING_APP_NAME,
/* pid field missing */
LM_T_SYSLOG_RFC5424_MISSING_PROCID,
/* msgid field missing */
LM_T_SYSLOG_RFC5424_MISSING_MSGID,
/* sdata field missing */
LM_T_SYSLOG_RFC5424_MISSING_SDATA,
/* invalid SDATA */
LM_T_SYSLOG_RFC5424_INVALID_SDATA,
/* sdata field missing */
LM_T_SYSLOG_RFC5424_MISSING_MESSAGE,
/* message field missing */
LM_T_SYSLOG_MISSING_MESSAGE,
LM_T_PREDEFINED_MAX,
};
enum
{
LM_VF_SDATA = 0x0001,
LM_VF_MATCH = 0x0002,
LM_VF_MACRO = 0x0004,
};
enum
{
/* these flags also matter when the message is serialized */
LF_OLD_UNPARSED = 0x0001,
/* message payload is guaranteed to be valid utf8 */
LF_UTF8 = 0x0001,
/* message was generated from within syslog-ng, doesn't matter if it came from the internal() source */
LF_INTERNAL = 0x0002,
/* message was received on a local transport, e.g. it was generated on the local machine */
LF_LOCAL = 0x0004,
/* message is a MARK mode */
LF_MARK = 0x0008,
/* state flags that only matter during syslog-ng runtime and never
* when a message is serialized */
LF_STATE_MASK = 0xFFF0,
LF_STATE_OWN_PAYLOAD = 0x0010,
LF_STATE_OWN_SADDR = 0x0020,
LF_STATE_OWN_DADDR = 0x0040,
LF_STATE_OWN_TAGS = 0x0080,
LF_STATE_OWN_SDATA = 0x0100,
LF_STATE_OWN_MASK = 0x01F0,
/* part of the state that is kept across clones */
LF_STATE_CLONED_MASK = 0xFE00,
LF_STATE_TRACING = 0x0200,
LF_CHAINED_HOSTNAME = 0x00010000,
/* NOTE: this flag is now unused. The original intent was to save whether
* LEGACY_MSGHDR was saved by the parser code. Now we simply check
* whether the length of ${LEGACY_MSGHDR} is non-zero. This used to be a
* slow operation (when name-value pairs were stored in a hashtable), now
* it is much faster. Also, this makes it possible to reproduce a message
* entirely based on name-value pairs. Without this change, even if
* LEGACY_MSGHDR was transferred (e.g. ewmm), the other side couldn't
* reproduce the original message, as this flag was not transferred.
*
* The flag remains here for documentation, and also because it is serialized in disk-buffers
*/
__UNUSED_LF_LEGACY_MSGHDR = 0x00020000,
};
typedef NVType LogMessageValueType;
enum _LogMessageValueType
{
/* Everything is represented as a string, formatted in a type specific
* automatically parseable format.
*
* Please note that these values are part of the serialized LogMessage
* format, so changing these would cause incompatibilities in type
* recognition. Add new types at the end.
*/
LM_VT_STRING = 0,
LM_VT_JSON = 1,
LM_VT_BOOLEAN = 2,
__COMPAT_LM_VT_INT32 = 3,
__COMPAT_LM_VT_INT64 = 4,
LM_VT_INTEGER = 4, /* equals to LM_VT_INT64 */
LM_VT_DOUBLE = 5,
LM_VT_DATETIME = 6,
LM_VT_LIST = 7,
LM_VT_NULL = 8,
LM_VT_BYTES = 9,
LM_VT_PROTOBUF = 10,
/* extremal value to indicate "unset" state.
*
* NOTE: THIS IS NOT THE DEFAULT for actual values even if type is
* unspecified, those cases default to LM_VT_STRING.
*/
LM_VT_NONE = 255
};
const gchar *log_msg_value_type_to_str(LogMessageValueType self);
gboolean log_msg_value_type_from_str(const gchar *in_str, LogMessageValueType *out_type);
typedef struct _LogMessageQueueNode
{
struct iv_list_head list;
LogMessage *msg;
guint ack_needed:1, embedded:1, flow_control_requested:1;
} LogMessageQueueNode;
/* NOTE: the members are ordered according to the presumed use frequency.
* The structure itself is 2 cachelines, the border is right after the "msg"
* member */
struct _LogMessage
{
/* if you change any of the fields here, be sure to adjust
* log_msg_clone_cow() as well to initialize fields properly */
/* ack_and_ref_and_abort_and_suspended is a 32 bit integer that is accessed in an atomic way.
* The upper half contains the ACK count (and the abort flag), the lower half
* the REF count. It is not a GAtomicCounter as due to ref/ack caching it has
* a lot of magic behind its implementation. See the logmsg.c file, around
* log_msg_ref/unref.
*/
/* FIXME: the structure has holes, but right now it's 1 byte short to make
* it smaller (it is possible to create a 7 byte contiguos block but 8
* byte alignment is needed. Let's check this with the inline-tags stuff */
gint ack_and_ref_and_abort_and_suspended;
/* NOTE: in theory this should be a size_t (or gsize), however that takes
* 8 bytes, and it's highly unlikely that we'd be using more than 4GB for
* a LogMessage */
guint allocated_bytes;
guint32 recvd_rawmsg_size;
AckRecord *ack_record;
LMAckFunc ack_func;
LogMessage *original;
/* message parts */
/* the contents of the members below is directly copied into another
* LogMessage with pointer values. To change any of the fields please use
* log_msg_set_*() functions, which will handle borrowed data members
* correctly.
*/
/* ==== start of directly copied part ==== */
UnixTime timestamps[LM_TS_MAX];
gulong *tags;
NVHandle *sdata;
GSockAddr *saddr;
GSockAddr *daddr;
NVTable *payload;
guint32 flags;
guint16 pri;
guint8 initial_parse:1,
recursed:1,
/* NOTE: proto is just 6 bits wide, but with that it fills a hole
* not taking any tolls on the structure size. Realistically, we'd
* be storing IPPROTO_UDP and TCP in there, which fits the 6 bits.
* This is closely related to saddr/daddr and indicates the IP
* protocol that was used to deliver the datagram carrying this
* LogMessage. */
proto:6;
guint8 num_matches;
guint32 host_id;
guint64 rcptid;
guint8 num_tags;
guint8 alloc_sdata;
guint8 num_sdata;
/* ==== end of directly copied part ==== */
guint8 num_nodes;
guint8 cur_node;
guint8 write_protected;
/* preallocated LogQueueNodes used to insert this message into a LogQueue */
LogMessageQueueNode nodes[0];
/* a preallocated space for the initial NVTable (payload) may follow */
};
extern NVRegistry *logmsg_registry;
extern const char logmsg_sd_prefix[];
extern const gint logmsg_sd_prefix_len;
extern gint logmsg_node_max;
LogMessage *log_msg_ref(LogMessage *m);
void log_msg_unref(LogMessage *m);
void log_msg_write_protect(LogMessage *m);
static inline gboolean
log_msg_is_write_protected(const LogMessage *self)
{
return self->write_protected;
}
LogMessage *log_msg_clone_cow(LogMessage *msg, const LogPathOptions *path_options);
LogMessage *log_msg_make_writable(LogMessage **pmsg, const LogPathOptions *path_options);
gboolean log_msg_write(LogMessage *self, SerializeArchive *sa);
gboolean log_msg_read(LogMessage *self, SerializeArchive *sa);
/* generic values that encapsulate log message fields, dynamic values and structured data */
NVHandle log_msg_get_value_handle(const gchar *value_name);
gboolean log_msg_is_value_name_valid(const gchar *value);
const gchar *log_msg_get_handle_name(NVHandle handle, gssize *length);
gboolean log_msg_is_handle_macro(NVHandle handle);
gboolean log_msg_is_handle_sdata(NVHandle handle);
gboolean log_msg_is_handle_match(NVHandle handle);
static inline gboolean
log_msg_is_handle_referencable_from_an_indirect_value(NVHandle handle)
{
if (handle == LM_V_NONE)
return FALSE;
/* macro values should not be referenced as they are dynamic, store the actual value instead */
if (log_msg_is_handle_macro(handle))
return FALSE;
/* matches are pretty temporary, so we should not reference them, as the
* next matching operation would overwrite them anyway */
if (log_msg_is_handle_match(handle))
return FALSE;
return TRUE;
}
static inline gboolean
log_msg_is_handle_settable_with_an_indirect_value(NVHandle handle)
{
return (handle >= LM_V_MAX);
}
const gchar *log_msg_get_macro_value(const LogMessage *self, gint id, gssize *value_len, LogMessageValueType *type);
const gchar *log_msg_get_match_with_type(const LogMessage *self, gint index_,
gssize *value_len, LogMessageValueType *type);
const gchar *log_msg_get_match_if_set_with_type(const LogMessage *self, gint index_,
gssize *value_len, LogMessageValueType *type);
static inline const gchar *
log_msg_get_value_if_set_with_type(const LogMessage *self, NVHandle handle,
gssize *value_len,
LogMessageValueType *type)
{
guint16 flags;
flags = nv_registry_get_handle_flags(logmsg_registry, handle);
if (G_UNLIKELY((flags & LM_VF_MACRO)))
return log_msg_get_macro_value(self, flags >> 8, value_len, type);
else
return nv_table_get_value(self->payload, handle, value_len, type);
}
static inline gboolean
log_msg_is_value_set(const LogMessage *self, NVHandle handle)
{
return nv_table_is_value_set(self->payload, handle);
}
static inline const gchar *
log_msg_get_value_with_type(const LogMessage *self, NVHandle handle, gssize *value_len, LogMessageValueType *type)
{
const gchar *result = log_msg_get_value_if_set_with_type(self, handle, value_len, type);
if (result)
return result;
if (type)
*type = LM_VT_NULL;
if (value_len)
*value_len = 0;
return "";
}
static inline const gchar *
log_msg_get_value(const LogMessage *self, NVHandle handle, gssize *value_len)
{
return log_msg_get_value_with_type(self, handle, value_len, NULL);
}
static inline const gchar *
log_msg_get_value_if_set(const LogMessage *self, NVHandle handle, gssize *value_len)
{
return log_msg_get_value_if_set_with_type(self, handle, value_len, NULL);
}
static inline const gchar *
log_msg_get_value_by_name(const LogMessage *self, const gchar *name, gssize *value_len)
{
NVHandle handle = log_msg_get_value_handle(name);
return log_msg_get_value(self, handle, value_len);
}
static inline const gchar *
log_msg_get_value_by_name_with_type(const LogMessage *self,
const gchar *name, gssize *value_len,
LogMessageValueType *type)
{
NVHandle handle = log_msg_get_value_handle(name);
return log_msg_get_value_with_type(self, handle, value_len, type);
}
static inline const gchar *
log_msg_get_value_name(NVHandle handle, gssize *name_len)
{
return nv_registry_get_handle_name(logmsg_registry, handle, name_len);
}
typedef gboolean (*LogMessageTagsForeachFunc)(const LogMessage *self, LogTagId tag_id, const gchar *name,
gpointer user_data);
void log_msg_set_value(LogMessage *self, NVHandle handle, const gchar *new_value, gssize length);
void log_msg_set_value_with_type(LogMessage *self, NVHandle handle,
const gchar *value, gssize value_len,
LogMessageValueType type);
void log_msg_set_value_indirect(LogMessage *self, NVHandle handle, NVHandle ref_handle,
guint16 ofs, guint16 len);
void log_msg_set_value_indirect_with_type(LogMessage *self, NVHandle handle, NVHandle ref_handle,
guint16 ofs, guint16 len, LogMessageValueType type);
void log_msg_unset_value(LogMessage *self, NVHandle handle);
void log_msg_unset_value_by_name(LogMessage *self, const gchar *name);
gboolean log_msg_values_foreach(const LogMessage *self, NVTableForeachFunc func, gpointer user_data);
NVHandle log_msg_get_match_handle(gint index_);
gint log_msg_get_match_index(NVHandle handle);
void log_msg_set_match(LogMessage *self, gint index, const gchar *value, gssize value_len);
void log_msg_set_match_with_type(LogMessage *self, gint index,
const gchar *value, gssize value_len,
LogMessageValueType type);
void log_msg_set_match_indirect(LogMessage *self, gint index, NVHandle ref_handle, guint16 ofs, guint16 len);
void log_msg_set_match_indirect_with_type(LogMessage *self, gint index, NVHandle ref_handle,
guint16 ofs, guint16 len, LogMessageValueType type);
void log_msg_unset_match(LogMessage *self, gint index_);
const gchar *log_msg_get_match_with_type(const LogMessage *self, gint index_, gssize *value_len,
LogMessageValueType *type);
const gchar *log_msg_get_match(const LogMessage *self, gint index_, gssize *value_len);
void log_msg_clear_matches(LogMessage *self);
void log_msg_truncate_matches(LogMessage *self, gint n);
static inline void
log_msg_set_value_by_name_with_type(LogMessage *self,
const gchar *name, const gchar *value, gssize length,
LogMessageValueType type)
{
NVHandle handle = log_msg_get_value_handle(name);
log_msg_set_value_with_type(self, handle, value, length, type);
}
static inline void
log_msg_set_value_by_name(LogMessage *self, const gchar *name, const gchar *value, gssize length)
{
log_msg_set_value_by_name_with_type(self, name, value, length, LM_VT_STRING);
}
static inline void
log_msg_set_value_to_string(LogMessage *self, NVHandle handle, const gchar *literal_string)
{
log_msg_set_value(self, handle, literal_string, strlen(literal_string));
}
void log_msg_rename_value(LogMessage *self, NVHandle from, NVHandle to);
void log_msg_append_format_sdata(const LogMessage *self, GString *result, guint32 seq_num);
void log_msg_format_sdata(const LogMessage *self, GString *result, guint32 seq_num);
void log_msg_clear_sdata(LogMessage *self);
void log_msg_set_tag_by_id_onoff(LogMessage *self, LogTagId id, gboolean on);
void log_msg_set_tag_by_id(LogMessage *self, LogTagId id);
void log_msg_set_tag_by_name(LogMessage *self, const gchar *name);
void log_msg_clear_tag_by_id(LogMessage *self, LogTagId id);
void log_msg_clear_tag_by_name(LogMessage *self, const gchar *name);
gboolean log_msg_is_tag_by_id(LogMessage *self, LogTagId id);
gboolean log_msg_is_tag_by_name(LogMessage *self, const gchar *name);
void log_msg_tags_foreach(const LogMessage *self, LogMessageTagsForeachFunc callback, gpointer user_data);
void log_msg_format_tags(const LogMessage *self, GString *result, gboolean include_localtags);
void log_msg_format_matches(const LogMessage *self, GString *result);
static inline void
log_msg_set_recvd_rawmsg_size(LogMessage *self, guint32 size)
{
self->recvd_rawmsg_size = size;
}
void log_msg_set_saddr(LogMessage *self, GSockAddr *saddr);
void log_msg_set_saddr_ref(LogMessage *self, GSockAddr *saddr);
void log_msg_set_daddr(LogMessage *self, GSockAddr *daddr);
void log_msg_set_daddr_ref(LogMessage *self, GSockAddr *daddr);
LogMessageQueueNode *log_msg_alloc_queue_node(LogMessage *msg, const LogPathOptions *path_options);
LogMessageQueueNode *log_msg_alloc_dynamic_queue_node(LogMessage *msg, const LogPathOptions *path_options);
void log_msg_free_queue_node(LogMessageQueueNode *node);
void log_msg_clear(LogMessage *self);
void log_msg_merge_context(LogMessage *self, LogMessage **context, gsize context_len);
LogMessage *log_msg_sized_new(gsize payload_size);
LogMessage *log_msg_new_mark(void);
LogMessage *log_msg_new_internal(gint prio, const gchar *msg);
LogMessage *log_msg_new_empty(void);
LogMessage *log_msg_new_local(void);
void log_msg_add_ack(LogMessage *msg, const LogPathOptions *path_options);
void log_msg_ack(LogMessage *msg, const LogPathOptions *path_options, AckType ack_type);
void log_msg_drop(LogMessage *msg, const LogPathOptions *path_options, AckType ack_type);
const LogPathOptions *log_msg_break_ack(LogMessage *msg, const LogPathOptions *path_options,
LogPathOptions *local_path_options);
void log_msg_refcache_start_producer(LogMessage *self);
void log_msg_refcache_start_consumer(LogMessage *self, const LogPathOptions *path_options);
void log_msg_refcache_stop(void);
void log_msg_registry_init(void);
void log_msg_registry_deinit(void);
void log_msg_global_init(void);
void log_msg_global_deinit(void);
void log_msg_stats_global_init(void);
void log_msg_registry_foreach(GHFunc func, gpointer user_data);
gint log_msg_lookup_time_stamp_name(const gchar *name);
gssize log_msg_get_size(LogMessage *self);
#define evt_tag_msg_reference(msg) \
evt_tag_printf("msg", "%p", (msg)), \
evt_tag_printf("rcptid", "%" G_GUINT64_FORMAT, (msg)->rcptid)
static inline EVTTAG *
evt_tag_msg_value(const gchar *name, LogMessage *msg, NVHandle value_handle)
{
gssize value_len;
const gchar *value = log_msg_get_value(msg, value_handle, &value_len);
return evt_tag_mem(name, value, value_len);
}
static inline EVTTAG *
evt_tag_msg_value_name(const gchar *name, NVHandle value_handle)
{
const gchar *value_name = log_msg_get_value_name(value_handle, NULL);
return evt_tag_str(name, value_name);
}
#endif