Skip to Content
[CAIDA - Cooperative Association for Internet Data Analysis logo]
The Cooperative Association for Internet Data Analysis
corsaro_plugin.c
1 /*
2  * corsaro
3  *
4  * Alistair King, CAIDA, UC San Diego
5  * corsaro-info@caida.org
6  *
7  * Copyright (C) 2012 The Regents of the University of California.
8  *
9  * This file is part of corsaro.
10  *
11  * corsaro is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation, either version 3 of the License, or
14  * (at your option) any later version.
15  *
16  * corsaro is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with corsaro. If not, see <http://www.gnu.org/licenses/>.
23  *
24  */
25 
26 #include "config.h"
27 #include "corsaro_int.h"
28 
29 #include <assert.h>
30 #include <stdlib.h>
31 #include <string.h>
32 
33 #include "utils.h"
34 
35 #include "corsaro_log.h"
36 
37 #include "corsaro_plugin.h"
38 
39 /* include the plugins that have been enabled */
40 #ifdef WITH_PLUGIN_PCAP
41 #include "corsaro_pcap.h"
42 #endif
43 
44 #ifdef WITH_PLUGIN_SIXT
45 #include "corsaro_flowtuple.h"
46 #endif
47 
48 #ifdef WITH_PLUGIN_DOS
49 #include "corsaro_dos.h"
50 #endif
51 
52 /*
53  * add new plugin includes below using:
54  *
55  * #ifdef WITH_PLUGIN_<macro_name>
56  * #include "<full_name>.h"
57  * #endif
58  */
59 
61 #define LOG(manager) (manager->logfile)
62 
63 
64 #define PLUGIN_INIT_ADD(plugin) \
65  { \
66  tail = add_plugin(manager, tail, plugin##_alloc(), \
67  "##plugin##"); \
68  if(list == NULL) \
69  { \
70  list = tail; \
71  } \
72  plugin_cnt++; \
73  }
74 
75 #ifdef DEBUG
76 #ifdef ED_PLUGIN_INIT_ALL_ENABLED
77 static void corsaro_plugin_verify(corsaro_plugin_t *plugin)
78 {
79  /* some sanity checking to make sure this plugin has been implemented
80  with the features we need. #if 0 this for production */
81  assert(plugin != NULL);
82  assert(plugin->name != NULL);
83  assert(plugin->id > 0 && plugin->id <= CORSARO_PLUGIN_ID_MAX);
84  assert(plugin->magic > 0x010101); /* this is a pretty rough check */
85  assert(plugin->probe_filename != NULL);
86  assert(plugin->probe_magic != NULL);
87  assert(plugin->init_input != NULL);
88  assert(plugin->init_output != NULL);
89  assert(plugin->close_input != NULL);
90  assert(plugin->close_output != NULL);
91  assert(plugin->read_record != NULL);
92  assert(plugin->read_global_data_record != NULL);
93  assert(plugin->start_interval != NULL);
94  assert(plugin->end_interval != NULL);
95  assert(plugin->process_packet != NULL);
96 
97  /* don't set the next plugin yourself... duh */
98  assert(plugin->next == NULL);
99 }
100 #endif
101 #endif
102 
103 #ifdef ED_PLUGIN_INIT_ALL_ENABLED
104 static corsaro_plugin_t *add_plugin(corsaro_plugin_manager_t *manager,
105  corsaro_plugin_t *tail,
106  corsaro_plugin_t *p,
107  const char *name)
108 {
109  corsaro_plugin_t *plugin = NULL;
110 
111  /* before we add this plugin, let's check that the user wants it */
112  if(corsaro_plugin_is_enabled(manager, p) == 0)
113  {
114  return tail;
115  }
116 
117  /* we assume that we need to copy the plugin structure that the plugin
118  gives us. this allows us to use the same plugin twice at once */
119  if((plugin = malloc(sizeof(corsaro_plugin_t))) == NULL)
120  {
121  corsaro_log_file(__func__, NULL, "could not malloc plugin");
122  return NULL;
123  }
124  memcpy(plugin, p, sizeof(corsaro_plugin_t));
125 
126  /* make sure it initialized */
127  if(plugin == NULL)
128  {
129  corsaro_log_file(__func__, LOG(manager), "%s plugin failed to initialize", name);
130  return tail;
131  }
132 
133 #ifdef DEBUG
134  corsaro_plugin_verify(plugin);
135 #endif
136 
137  if(tail != NULL)
138  {
139  assert(tail->next == NULL);
140  tail->next = plugin;
141  }
142  /*plugin->next = head;*/
143  return plugin;
144 }
145 #endif
146 
147 static int populate_plugin_arrays(corsaro_plugin_manager_t *manager,
148  int plugin_cnt,
149  corsaro_plugin_t *plugin_list)
150 {
151  corsaro_plugin_t *tmp = NULL;
152 
153  if(plugin_cnt == 0)
154  {
155  corsaro_log_file(__func__, LOG(manager),
156  "WARNING: No plugins are initialized");
157  }
158  else
159  {
160  /* build the plugins array */
161  if((manager->plugins = malloc_zero(sizeof(corsaro_plugin_t*)
162  *(CORSARO_PLUGIN_ID_MAX))) == NULL)
163  {
164  corsaro_log_file(__func__, LOG(manager),
165  "could not malloc plugin array");
166  return -1;
167  }
168  /* allocate the plugin state array */
169  if((manager->plugins_state = malloc_zero(sizeof(void*)
170  *(CORSARO_PLUGIN_ID_MAX))) == NULL)
171  {
172  corsaro_log_file(__func__, LOG(manager),
173  "could not malloc plugin state array");
174  return -1;
175  }
176  for(tmp=plugin_list;tmp!=NULL;tmp=tmp->next)
177  {
178  manager->plugins[tmp->id-1] = tmp;
179  }
180  manager->first_plugin = plugin_list;
181  manager->plugins_cnt = plugin_cnt;
182  }
183  return 0;
184 }
185 
189 {
190  corsaro_plugin_manager_t *manager = NULL;
191 
192  corsaro_plugin_t *list = NULL;
193 #ifdef ED_PLUGIN_INIT_ALL_ENABLED
194  corsaro_plugin_t *tail = NULL;
195 #endif
196  int plugin_cnt = 0;
197 
198  /* allocate the manager structure */
199  if((manager = malloc_zero(sizeof(corsaro_plugin_manager_t))) == NULL)
200  {
201  corsaro_log_file(__func__, logfile, "failed to malloc plugin manager");
202  return NULL;
203  }
204 
205  /* set the log file */
206  manager->logfile = logfile;
207 
208  /* NOTE: the order that plugins are listed in configure.ac
209  will be the order that they are run. */
210 
211  /* this macro is generated by ED_WITH_PLUGIN macro calls in configure.ac */
212  /* basically, what will happen is that an ordered linked list of plugins
213  will be built, which we will then turn into an array and store in the
214  manager structure. this allows plugins to be accessed in both
215  sequential and random access fashion */
216 
217 #ifdef ED_PLUGIN_INIT_ALL_ENABLED
218  ED_PLUGIN_INIT_ALL_ENABLED
219 #endif
220 
221  if(populate_plugin_arrays(manager, plugin_cnt, list) != 0)
222  {
223  corsaro_plugin_manager_free(manager);
224  return NULL;
225  }
226 
227  return manager;
228 }
229 
230 int corsaro_plugin_manager_start(corsaro_plugin_manager_t *manager)
231 {
232  int i;
233  int enabled = 0;
234  int plugin_cnt = 0;
235  corsaro_plugin_t *p = NULL;
236  corsaro_plugin_t *tail = NULL;
237  corsaro_plugin_t *head = NULL;
238 
239  if(manager->plugins_enabled != NULL)
240  {
241  /* we need to go through the list of plugins and recreate the list
242  with only plugins which are in the plugins_enabled array */
243  while((p = corsaro_plugin_next(manager, p)) != NULL)
244  {
245  enabled = 0;
246  for(i = 0; i < manager->plugins_enabled_cnt; i++)
247  {
248  if(p->id == manager->plugins_enabled[i])
249  {
250  enabled = 1;
251  break;
252  }
253  }
254 
255  if(enabled == 1)
256  {
257  /* remember the first plugin */
258  if(head == NULL)
259  {
260  head = p;
261  }
262  /* in case we skipped over anything, we'll join the last
263  enabled plugin to this plugin*/
264  if(tail != NULL)
265  {
266  tail->next = p;
267  }
268  plugin_cnt++;
269  tail = p;
270  }
271  else
272  {
273  /* this plugin is no longer needed */
274  free(p);
275  manager->plugins[p->id-1] = NULL;
276  }
277  }
278 
279  /* disconnect the last plugin just in case */
280  tail->next = NULL;
281 
282  /* we now have a list starting at head */
283  manager->first_plugin = head;
284 
285  }
286 
287  return 0;
288 }
289 
290 void corsaro_plugin_manager_free(corsaro_plugin_manager_t *manager)
291 {
292  int i = 0;
293 
294  if(manager == NULL)
295  {
296  corsaro_log(__func__, NULL, "possible double-free of plugin manager");
297  return;
298  }
299 
300  if(manager->plugins != NULL)
301  {
302  /* each plugin MUST already have been closed by now */
303  for(i = 0; i < CORSARO_PLUGIN_ID_MAX; i++)
304  {
305  if(manager->plugins[i] != NULL)
306  {
307  free(manager->plugins[i]);
308  manager->plugins[i] = NULL;
309  }
310  }
311  free(manager->plugins);
312  manager->plugins = NULL;
313  }
314 
315  if(manager->plugins_state != NULL)
316  {
317  /* as above, state will be freed by calls to the each plugins close
318  function */
319  free(manager->plugins_state);
320  manager->plugins_state = NULL;
321  }
322 
323  manager->first_plugin = NULL;
324  manager->plugins_cnt = 0;
325 
326  /* we are NOT responsible for the logfile pointer */
327  /* should maybe think about making files use reference counting? */
328 
329  free(manager);
330 }
331 
332 corsaro_plugin_t *corsaro_plugin_get_by_id(corsaro_plugin_manager_t *manager,
333  int id)
334 {
335  assert(manager != NULL);
336  if(id < 0 || id > CORSARO_PLUGIN_ID_MAX)
337  {
338  return NULL;
339  }
340 
341  return manager->plugins[id-1];
342 }
343 
344 corsaro_plugin_t *corsaro_plugin_get_by_name(corsaro_plugin_manager_t *manager,
345  const char *name)
346 {
347  corsaro_plugin_t *p = NULL;
348  while((p = corsaro_plugin_next(manager, p)) != NULL)
349  {
350  if(strlen(name) == strlen(p->name) &&
351  strncasecmp(name, p->name, strlen(p->name)) == 0)
352  {
353  return p;
354  }
355  }
356  return NULL;
357 }
358 
359 corsaro_plugin_t *corsaro_plugin_next(corsaro_plugin_manager_t *manager,
360  corsaro_plugin_t *plugin)
361 {
362  /* plugins have already been freed, or not init'd */
363  if(manager == NULL || manager->plugins == NULL || manager->plugins_cnt == 0)
364  {
365  return NULL;
366  }
367 
368  /* they are asking for the beginning of the list */
369  if(plugin == NULL)
370  {
371  return manager->first_plugin;
372  }
373 
374  /* otherwise, give them the next one */
375  return plugin->next;
376 }
377 
378 void corsaro_plugin_register_state(corsaro_plugin_manager_t *manager,
379  corsaro_plugin_t *plugin,
380  void *state)
381 {
382  assert(manager != NULL);
383  assert(plugin != NULL);
384  assert(state != NULL);
385 
386  manager->plugins_state[plugin->id-1] = state;
387 }
388 
389 void corsaro_plugin_free_state(corsaro_plugin_manager_t *manager,
390  corsaro_plugin_t *plugin)
391 {
392  assert(manager != NULL);
393  assert(plugin != NULL);
394 
395  free(manager->plugins_state[plugin->id-1]);
396  manager->plugins_state[plugin->id-1] = NULL;
397 }
398 
399 int corsaro_plugin_probe_filename(const char *fname, corsaro_plugin_t *plugin)
400 {
401  assert(fname != NULL);
402  assert(plugin != NULL && plugin->name != NULL);
403 
404  if(strstr(fname, plugin->name) != NULL)
405  {
406  return 1;
407  }
408  return 0;
409 }
410 
411 const char *corsaro_plugin_get_name(corsaro_plugin_manager_t *manager,
412  int id)
413 {
414  corsaro_plugin_t *plugin = NULL;
415  if((plugin = corsaro_plugin_get_by_id(manager, id)) == NULL)
416  {
417  return NULL;
418  }
419  return plugin->name;
420 }
421 
422 int corsaro_plugin_is_enabled(corsaro_plugin_manager_t *manager,
423  corsaro_plugin_t *plugin)
424 {
425  int i;
426 
427  if(manager->plugins_enabled == NULL)
428  {
429  /* no plugins have been explicitly enabled, therefore all plugins
430  are implicitly enabled */
431  return 1;
432  }
433 
434  for(i=0; i<manager->plugins_enabled_cnt; i++)
435  {
436  if(manager->plugins_enabled[i] == plugin->id)
437  {
438  return 1;
439  }
440  }
441 
442  return 0;
443 }
444 
445 int corsaro_plugin_enable_plugin(corsaro_plugin_manager_t *manager,
446  const char *plugin_name)
447 {
448  corsaro_plugin_t *plugin = NULL;
449  int i;
450 
451  assert(manager != NULL);
452 
453  /* first, let us find the plugin with this name */
454  if((plugin = corsaro_plugin_get_by_name(manager, plugin_name)) == NULL)
455  {
456  corsaro_log_file(__func__, LOG(manager),
457  "No plugin found with the name %s\n", plugin_name);
458  corsaro_log_file(__func__, LOG(manager),
459  "Is corsaro compiled with all necessary plugins?");
460  return -1;
461  }
462 
463  /* now we need to ensure it isn't already enabled */
464  for(i = 0; i < manager->plugins_enabled_cnt; i++)
465  {
466  if(plugin->id == manager->plugins_enabled[i])
467  {
468  return 0;
469  }
470  }
471 
472  /* now we need to remalloc the array */
473  if((manager->plugins_enabled = realloc(manager->plugins_enabled,
474  sizeof(uint16_t)*
475  manager->plugins_enabled_cnt+1
476  )) == NULL)
477  {
478  corsaro_log_file(__func__, LOG(manager),
479  "could not extend the enabled plugins array");
480  return -1;
481  }
482 
483  /* now we shall store this id in this spot! */
484  manager->plugins_enabled[manager->plugins_enabled_cnt++] = plugin->id;
485 
486  return 0;
487 }