1 /*
2 * Copyright (c) 2002-2012 Balabit
3 * Copyright (c) 1998-2012 Balázs Scheidler
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 * As an additional exemption you are allowed to compile & link against the
20 * OpenSSL libraries as published by the OpenSSL project. See the file
21 * COPYING for details.
22 *
23 */
24
25 #include "parser/parser-expr.h"
26 #include "template/templates.h"
27 #include "logmatcher.h"
28
29 #include <string.h>
30
31 /* NOTE: consumes template */
32 void
log_parser_set_template(LogParser * self,LogTemplate * template)33 log_parser_set_template(LogParser *self, LogTemplate *template)
34 {
35 log_template_unref(self->template);
36 self->template = template;
37 }
38
39 gboolean
log_parser_process_message(LogParser * self,LogMessage ** pmsg,const LogPathOptions * path_options)40 log_parser_process_message(LogParser *self, LogMessage **pmsg, const LogPathOptions *path_options)
41 {
42 LogMessage *msg = *pmsg;
43 gboolean success;
44
45 if (G_LIKELY(!self->template))
46 {
47 NVTable *payload = nv_table_ref(msg->payload);
48 const gchar *value;
49 gssize value_len;
50
51 /* NOTE: the process function may set values in the LogMessage
52 * instance, which in turn can trigger nv_table_realloc() to be
53 * called. However in case nv_table_realloc() finds a refcounter > 1,
54 * it'll always _move_ the structure and leave the old one intact,
55 * until its refcounter drops to zero. If that wouldn't be the case,
56 * nv_table_realloc() could make our payload pointer and the
57 * LM_V_MESSAGE pointer we pass to process() go stale.
58 */
59
60 value = log_msg_get_value(msg, LM_V_MESSAGE, &value_len);
61 success = self->process(self, pmsg, path_options, value, value_len);
62 nv_table_unref(payload);
63 }
64 else
65 {
66 GString *input = g_string_sized_new(256);
67
68 log_template_format(self->template, msg, &DEFAULT_TEMPLATE_EVAL_OPTIONS, input);
69 success = self->process(self, pmsg, path_options, input->str, input->len);
70 g_string_free(input, TRUE);
71 }
72
73 if (!success)
74 stats_counter_inc(self->super.discarded_messages);
75
76 return success;
77 }
78
79 static void
log_parser_queue(LogPipe * s,LogMessage * msg,const LogPathOptions * path_options)80 log_parser_queue(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options)
81 {
82 LogParser *self = (LogParser *) s;
83 gboolean success;
84 gchar *parser_result;
85
86 msg_trace(">>>>>> parser rule evaluation begin",
87 evt_tag_str("rule", self->name),
88 log_pipe_location_tag(s),
89 evt_tag_printf("msg", "%p", msg));
90
91 success = log_parser_process_message(self, &msg, path_options);
92
93 if (success)
94 {
95 parser_result = "Forwarding message to the next LogPipe";
96 log_pipe_forward_msg(s, msg, path_options);
97 }
98 else
99 {
100 parser_result = "Dropping message from LogPipe";
101 if (path_options->matched)
102 (*path_options->matched) = FALSE;
103 log_msg_drop(msg, path_options, AT_PROCESSED);
104 }
105 msg_trace("<<<<<< parser rule evaluation result",
106 evt_tag_str("result", parser_result),
107 evt_tag_str("rule", self->name),
108 log_pipe_location_tag(s),
109 evt_tag_printf("msg", "%p", msg));
110 }
111
112 gboolean
log_parser_init_method(LogPipe * s)113 log_parser_init_method(LogPipe *s)
114 {
115 LogParser *self = (LogParser *) s;
116 GlobalConfig *cfg = log_pipe_get_config(s);
117
118 if (!self->name && s->expr_node)
119 self->name = cfg_tree_get_rule_name(&cfg->tree, ENC_PARSER, s->expr_node);
120
121 stats_lock();
122 StatsClusterKey sc_key;
123 stats_cluster_logpipe_key_set(&sc_key, SCS_PARSER, self->name, NULL );
124 stats_register_counter(1, &sc_key, SC_TYPE_DISCARDED, &self->super.discarded_messages);
125 stats_unlock();
126
127 return TRUE;
128 }
129
130 void
log_parser_free_method(LogPipe * s)131 log_parser_free_method(LogPipe *s)
132 {
133 LogParser *self = (LogParser *) s;
134
135 stats_lock();
136 StatsClusterKey sc_key;
137 stats_cluster_logpipe_key_set(&sc_key, SCS_PARSER, self->name, NULL );
138 stats_unregister_counter(&sc_key, SC_TYPE_DISCARDED, &self->super.discarded_messages);
139 stats_unlock();
140
141 g_free(self->name);
142 log_template_unref(self->template);
143 log_pipe_free_method(s);
144
145 }
146
147 void
log_parser_init_instance(LogParser * self,GlobalConfig * cfg)148 log_parser_init_instance(LogParser *self, GlobalConfig *cfg)
149 {
150 log_pipe_init_instance(&self->super, cfg);
151 self->super.init = log_parser_init_method;
152 self->super.deinit = log_parser_deinit_method;
153 self->super.free_fn = log_parser_free_method;
154 self->super.queue = log_parser_queue;
155 }
156