1 /* Copyright (C) 2007-2013 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Victor Julien <victor@inliniac.net>
22  *
23  * Packet Logger Output registration functions
24  */
25 
26 #include "suricata-common.h"
27 #include "tm-modules.h"
28 #include "output.h"
29 #include "output-packet.h"
30 #include "util-profiling.h"
31 #include "util-validate.h"
32 
33 typedef struct OutputLoggerThreadStore_ {
34     void *thread_data;
35     struct OutputLoggerThreadStore_ *next;
36 } OutputLoggerThreadStore;
37 
38 /** per thread data for this module, contains a list of per thread
39  *  data for the packet loggers. */
40 typedef struct OutputLoggerThreadData_ {
41     OutputLoggerThreadStore *store;
42 } OutputLoggerThreadData;
43 
44 /* logger instance, a module + a output ctx,
45  * it's perfectly valid that have multiple instances of the same
46  * log module (e.g. fast.log) with different output ctx'. */
47 typedef struct OutputPacketLogger_ {
48     PacketLogger LogFunc;
49     PacketLogCondition ConditionFunc;
50     OutputCtx *output_ctx;
51     struct OutputPacketLogger_ *next;
52     const char *name;
53     LoggerId logger_id;
54     ThreadInitFunc ThreadInit;
55     ThreadDeinitFunc ThreadDeinit;
56     ThreadExitPrintStatsFunc ThreadExitPrintStats;
57 } OutputPacketLogger;
58 
59 static OutputPacketLogger *list = NULL;
60 
OutputRegisterPacketLogger(LoggerId logger_id,const char * name,PacketLogger LogFunc,PacketLogCondition ConditionFunc,OutputCtx * output_ctx,ThreadInitFunc ThreadInit,ThreadDeinitFunc ThreadDeinit,ThreadExitPrintStatsFunc ThreadExitPrintStats)61 int OutputRegisterPacketLogger(LoggerId logger_id, const char *name,
62     PacketLogger LogFunc, PacketLogCondition ConditionFunc,
63     OutputCtx *output_ctx, ThreadInitFunc ThreadInit,
64     ThreadDeinitFunc ThreadDeinit,
65     ThreadExitPrintStatsFunc ThreadExitPrintStats)
66 {
67     OutputPacketLogger *op = SCMalloc(sizeof(*op));
68     if (op == NULL)
69         return -1;
70     memset(op, 0x00, sizeof(*op));
71 
72     op->LogFunc = LogFunc;
73     op->ConditionFunc = ConditionFunc;
74     op->output_ctx = output_ctx;
75     op->name = name;
76     op->ThreadInit = ThreadInit;
77     op->ThreadDeinit = ThreadDeinit;
78     op->ThreadExitPrintStats = ThreadExitPrintStats;
79     op->logger_id = logger_id;
80 
81     if (list == NULL)
82         list = op;
83     else {
84         OutputPacketLogger *t = list;
85         while (t->next)
86             t = t->next;
87         t->next = op;
88     }
89 
90     SCLogDebug("OutputRegisterPacketLogger happy");
91     return 0;
92 }
93 
OutputPacketLog(ThreadVars * tv,Packet * p,void * thread_data)94 static TmEcode OutputPacketLog(ThreadVars *tv, Packet *p, void *thread_data)
95 {
96     DEBUG_VALIDATE_BUG_ON(thread_data == NULL);
97 
98     if (list == NULL) {
99         /* No child loggers. */
100         return TM_ECODE_OK;
101     }
102 
103     OutputLoggerThreadData *op_thread_data = (OutputLoggerThreadData *)thread_data;
104     OutputPacketLogger *logger = list;
105     OutputLoggerThreadStore *store = op_thread_data->store;
106 
107     DEBUG_VALIDATE_BUG_ON(logger == NULL && store != NULL);
108     DEBUG_VALIDATE_BUG_ON(logger != NULL && store == NULL);
109     DEBUG_VALIDATE_BUG_ON(logger == NULL && store == NULL);
110 
111     while (logger && store) {
112         DEBUG_VALIDATE_BUG_ON(logger->LogFunc == NULL || logger->ConditionFunc == NULL);
113 
114         if ((logger->ConditionFunc(tv, (const Packet *)p)) == TRUE) {
115             PACKET_PROFILING_LOGGER_START(p, logger->logger_id);
116             logger->LogFunc(tv, store->thread_data, (const Packet *)p);
117             PACKET_PROFILING_LOGGER_END(p, logger->logger_id);
118         }
119 
120         logger = logger->next;
121         store = store->next;
122 
123         DEBUG_VALIDATE_BUG_ON(logger == NULL && store != NULL);
124         DEBUG_VALIDATE_BUG_ON(logger != NULL && store == NULL);
125     }
126 
127     return TM_ECODE_OK;
128 }
129 
130 /** \brief thread init for the packet logger
131  *  This will run the thread init functions for the individual registered
132  *  loggers */
OutputPacketLogThreadInit(ThreadVars * tv,const void * initdata,void ** data)133 static TmEcode OutputPacketLogThreadInit(ThreadVars *tv, const void *initdata, void **data)
134 {
135     OutputLoggerThreadData *td = SCMalloc(sizeof(*td));
136     if (td == NULL)
137         return TM_ECODE_FAILED;
138     memset(td, 0x00, sizeof(*td));
139 
140     *data = (void *)td;
141 
142     SCLogDebug("OutputPacketLogThreadInit happy (*data %p)", *data);
143 
144     OutputPacketLogger *logger = list;
145     while (logger) {
146         if (logger->ThreadInit) {
147             void *retptr = NULL;
148             if (logger->ThreadInit(tv, (void *)logger->output_ctx, &retptr) == TM_ECODE_OK) {
149                 OutputLoggerThreadStore *ts = SCMalloc(sizeof(*ts));
150 /* todo */      BUG_ON(ts == NULL);
151                 memset(ts, 0x00, sizeof(*ts));
152 
153                 /* store thread handle */
154                 ts->thread_data = retptr;
155 
156                 if (td->store == NULL) {
157                     td->store = ts;
158                 } else {
159                     OutputLoggerThreadStore *tmp = td->store;
160                     while (tmp->next != NULL)
161                         tmp = tmp->next;
162                     tmp->next = ts;
163                 }
164 
165                 SCLogDebug("%s is now set up", logger->name);
166             }
167         }
168 
169         logger = logger->next;
170     }
171 
172     return TM_ECODE_OK;
173 }
174 
OutputPacketLogThreadDeinit(ThreadVars * tv,void * thread_data)175 static TmEcode OutputPacketLogThreadDeinit(ThreadVars *tv, void *thread_data)
176 {
177     OutputLoggerThreadData *op_thread_data = (OutputLoggerThreadData *)thread_data;
178     OutputLoggerThreadStore *store = op_thread_data->store;
179     OutputPacketLogger *logger = list;
180 
181     while (logger && store) {
182         if (logger->ThreadDeinit) {
183             logger->ThreadDeinit(tv, store->thread_data);
184         }
185 
186         OutputLoggerThreadStore *next_store = store->next;
187         SCFree(store);
188         store = next_store;
189 
190         logger = logger->next;
191     }
192 
193     SCFree(op_thread_data);
194     return TM_ECODE_OK;
195 }
196 
OutputPacketLogExitPrintStats(ThreadVars * tv,void * thread_data)197 static void OutputPacketLogExitPrintStats(ThreadVars *tv, void *thread_data)
198 {
199     OutputLoggerThreadData *op_thread_data = (OutputLoggerThreadData *)thread_data;
200     OutputLoggerThreadStore *store = op_thread_data->store;
201     OutputPacketLogger *logger = list;
202 
203     while (logger && store) {
204         if (logger->ThreadExitPrintStats) {
205             logger->ThreadExitPrintStats(tv, store->thread_data);
206         }
207 
208         logger = logger->next;
209         store = store->next;
210     }
211 }
212 
OutputPacketLoggerGetActiveCount(void)213 static uint32_t OutputPacketLoggerGetActiveCount(void)
214 {
215     uint32_t cnt = 0;
216     for (OutputPacketLogger *p = list; p != NULL; p = p->next) {
217         cnt++;
218     }
219     return cnt;
220 }
221 
OutputPacketLoggerRegister(void)222 void OutputPacketLoggerRegister(void)
223 {
224     OutputRegisterRootLogger(OutputPacketLogThreadInit,
225         OutputPacketLogThreadDeinit, OutputPacketLogExitPrintStats,
226         OutputPacketLog, OutputPacketLoggerGetActiveCount);
227 }
228 
OutputPacketShutdown(void)229 void OutputPacketShutdown(void)
230 {
231     OutputPacketLogger *logger = list;
232     while (logger) {
233         OutputPacketLogger *next_logger = logger->next;
234         SCFree(logger);
235         logger = next_logger;
236     }
237 
238     /* reset list pointer */
239     list = NULL;
240 }
241