Skip to Content
[CAIDA - Center for Applied Internet Data Analysis logo]
The Center for Applied 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 "parse_cmd.h"
34 #include "utils.h"
35 
36 #include "corsaro_log.h"
37 
38 #include "corsaro_plugin.h"
39 
40 /* include the plugins that have been enabled */
41 #ifdef WITH_PLUGIN_PCAP
42 #include "corsaro_pcap.h"
43 #endif
44 
45 #ifdef WITH_PLUGIN_SIXT
46 #include "corsaro_flowtuple.h"
47 #endif
48 
49 #ifdef WITH_PLUGIN_DOS
50 #include "corsaro_dos.h"
51 #endif
52 
53 #ifdef WITH_PLUGIN_SMEE
54 #include "corsaro_smee.h"
55 #endif
56 
57 #ifdef WITH_PLUGIN_ANON
58 #include "corsaro_anon.h"
59 #endif
60 
61 #ifdef WITH_PLUGIN_GEODB
62 #include "corsaro_geodb.h"
63 #endif
64 
65 #ifdef WITH_PLUGIN_PFX2AS
66 #include "corsaro_pfx2as.h"
67 #endif
68 
69 #ifdef WITH_PLUGIN_FILTERGEO
70 #include "corsaro_filtergeo.h"
71 #endif
72 
73 #ifdef WITH_PLUGIN_FILTERPFX
74 #include "corsaro_filterpfx.h"
75 #endif
76 
77 /*
78  * add new plugin includes below using:
79  *
80  * #ifdef WITH_PLUGIN_<macro_name>
81  * #include "<full_name>.h"
82  * #endif
83  */
84 
85 
87 #define LOG(manager) (manager->logfile)
88 
89 #define MAXOPTS 1024
90 
91 #define PLUGIN_INIT_ADD(plugin) \
92  { \
93  tail = add_plugin(manager, tail, plugin##_alloc(), \
94  "##plugin##"); \
95  if(list == NULL) \
96  { \
97  list = tail; \
98  } \
99  plugin_cnt++; \
100  }
101 
102 #ifdef DEBUG
103 #ifdef ED_PLUGIN_INIT_ALL_ENABLED
104 static void corsaro_plugin_verify(corsaro_plugin_t *plugin)
105 {
106  /* some sanity checking to make sure this plugin has been implemented
107  with the features we need. #if 0 this for production */
108  assert(plugin != NULL);
109  assert(plugin->name != NULL);
110  assert(plugin->id > 0 && plugin->id <= CORSARO_PLUGIN_ID_MAX);
111  assert(plugin->magic > 0x010101); /* this is a pretty rough check */
112  assert(plugin->probe_filename != NULL);
113  assert(plugin->probe_magic != NULL);
114  assert(plugin->init_input != NULL);
115  assert(plugin->init_output != NULL);
116  assert(plugin->close_input != NULL);
117  assert(plugin->close_output != NULL);
118  assert(plugin->read_record != NULL);
119  assert(plugin->read_global_data_record != NULL);
120  assert(plugin->start_interval != NULL);
121  assert(plugin->end_interval != NULL);
122  assert(plugin->process_packet != NULL);
123 
124  /* don't set the next plugin yourself... duh */
125  assert(plugin->next == NULL);
126 }
127 #endif
128 #endif
129 
130 #ifdef ED_PLUGIN_INIT_ALL_ENABLED
131 static corsaro_plugin_t *add_plugin(corsaro_plugin_manager_t *manager,
132  corsaro_plugin_t *tail,
133  corsaro_plugin_t *p,
134  const char *name)
135 {
136  corsaro_plugin_t *plugin = NULL;
137 
138  /* before we add this plugin, let's check that the user wants it */
139  if(corsaro_plugin_is_enabled(manager, p) == 0)
140  {
141  return tail;
142  }
143 
144  /* we assume that we need to copy the plugin structure that the plugin
145  gives us. this allows us to use the same plugin twice at once */
146  if((plugin = malloc(sizeof(corsaro_plugin_t))) == NULL)
147  {
148  corsaro_log_file(__func__, NULL, "could not malloc plugin");
149  return NULL;
150  }
151  memcpy(plugin, p, sizeof(corsaro_plugin_t));
152 
153  /* make sure it initialized */
154  if(plugin == NULL)
155  {
156  corsaro_log_file(__func__, LOG(manager),
157  "%s plugin failed to initialize", name);
158  return tail;
159  }
160 
161 #ifdef DEBUG
162  corsaro_plugin_verify(plugin);
163 #endif
164 
165  /* create the default argv for the plugin */
166  plugin->argc = 1;
167  /* malloc the pointers for the array */
168  if((plugin->argv = malloc(sizeof(char*) * (plugin->argc+1))) == NULL)
169  {
170  corsaro_log_file(__func__, LOG(manager), "could not malloc plugin argv");
171  return NULL;
172  }
173  plugin->argv[0] = strndup(plugin->name, strlen(plugin->name));
174  plugin->argv[1] = NULL;
175 
176  if(tail != NULL)
177  {
178  assert(tail->next == NULL);
179  tail->next = plugin;
180  }
181  /*plugin->next = head;*/
182  return plugin;
183 }
184 #endif
185 
186 static int populate_plugin_arrays(corsaro_plugin_manager_t *manager,
187  int plugin_cnt,
188  corsaro_plugin_t *plugin_list)
189 {
190  corsaro_plugin_t *tmp = NULL;
191 
192  if(plugin_cnt == 0)
193  {
194  corsaro_log_file(__func__, LOG(manager),
195  "WARNING: No plugins are initialized");
196  }
197  else
198  {
199  /* build the plugins array */
200  if((manager->plugins = malloc_zero(sizeof(corsaro_plugin_t*)
201  *(CORSARO_PLUGIN_ID_MAX))) == NULL)
202  {
203  corsaro_log_file(__func__, LOG(manager),
204  "could not malloc plugin array");
205  return -1;
206  }
207  /* allocate the plugin state array */
208  if((manager->plugins_state = malloc_zero(sizeof(void*)
209  *(CORSARO_PLUGIN_ID_MAX))) == NULL)
210  {
211  corsaro_log_file(__func__, LOG(manager),
212  "could not malloc plugin state array");
213  return -1;
214  }
215  for(tmp=plugin_list;tmp!=NULL;tmp=tmp->next)
216  {
217  manager->plugins[tmp->id-1] = tmp;
218  }
219  manager->first_plugin = plugin_list;
220  manager->plugins_cnt = plugin_cnt;
221  }
222  return 0;
223 }
224 
225 static int copy_argv(corsaro_plugin_t *plugin, int argc, char *argv[])
226 {
227  int i;
228  plugin->argc = argc;
229 
230  /* malloc the pointers for the array */
231  if((plugin->argv = malloc(sizeof(char*) * (plugin->argc+1))) == NULL)
232  {
233  return -1;
234  }
235 
236  for (i = 0; i < plugin->argc; i++) {
237  if((plugin->argv[i] = malloc(strlen(argv[i]) + 1)) == NULL)
238  {
239  return -1;
240  }
241  strncpy(plugin->argv[i], argv[i], strlen(argv[i]) + 1);
242  }
243 
244  /* as per ANSI spec, the last element in argv must be a NULL pointer */
245  /* can't find the actual spec, but http://en.wikipedia.org/wiki/Main_function
246  as well as other sources confirm this is standard */
247  plugin->argv[plugin->argc] = NULL;
248 
249  return 0;
250 }
251 
255 {
256  corsaro_plugin_manager_t *manager = NULL;
257 
258  corsaro_plugin_t *list = NULL;
259 #ifdef ED_PLUGIN_INIT_ALL_ENABLED
260  corsaro_plugin_t *tail = NULL;
261 #endif
262  int plugin_cnt = 0;
263 
264  /* allocate the manager structure */
265  if((manager = malloc_zero(sizeof(corsaro_plugin_manager_t))) == NULL)
266  {
267  corsaro_log_file(__func__, logfile, "failed to malloc plugin manager");
268  return NULL;
269  }
270 
271  /* set the log file */
272  manager->logfile = logfile;
273 
274  /* NOTE: the order that plugins are listed in configure.ac
275  will be the order that they are run. */
276 
277  /* this macro is generated by ED_WITH_PLUGIN macro calls in configure.ac */
278  /* basically, what will happen is that an ordered linked list of plugins
279  will be built, which we will then turn into an array and store in the
280  manager structure. this allows plugins to be accessed in both
281  sequential and random access fashion */
282 
283 #ifdef ED_PLUGIN_INIT_ALL_ENABLED
284  ED_PLUGIN_INIT_ALL_ENABLED
285 #endif
286 
287  if(populate_plugin_arrays(manager, plugin_cnt, list) != 0)
288  {
290  return NULL;
291  }
292 
293  return manager;
294 }
295 
297 {
298  int i;
299  corsaro_plugin_t *p = NULL;
300  corsaro_plugin_t *tail = NULL;
301  corsaro_plugin_t *head = NULL;
302 
303  if(manager->plugins_enabled != NULL)
304  {
305  /* we need to go through the list of plugins and recreate the list
306  with only plugins which are in the plugins_enabled array */
307  for(i = 0; i < manager->plugins_enabled_cnt; i++)
308  {
309  p = manager->plugins[manager->plugins_enabled[i]-1];
310 
311  /* if this is the first enabled plugin, then this will be the head */
312  if(head == NULL)
313  {
314  head = p;
315  }
316 
317  /* if there was a plugin before, connect it to this one */
318  if(tail != NULL)
319  {
320  tail->next = p;
321  }
322 
323  /* make this the last plugin in the list (so far) */
324  tail = p;
325 
326  /* disconnect the rest of the list */
327  tail->next = NULL;
328  }
329 
330  /* NB we dont need to free any unused plugins as the all plugins
331  get free'd anyway when the manager gets free'd */
332 
333  /* we now have a list starting at head */
334  manager->first_plugin = head;
335 
336  }
337 
338  return 0;
339 }
340 
342 {
343  int i, j;
344 
345  assert(manager != NULL);
346 
347  if(manager->plugins != NULL)
348  {
349  /* each plugin MUST already have been closed by now */
350  for(i = 0; i < CORSARO_PLUGIN_ID_MAX; i++)
351  {
352  if(manager->plugins[i] != NULL)
353  {
354  /* free the argument strings */
355  for(j = 0; j < manager->plugins[i]->argc; j++)
356  {
357  free(manager->plugins[i]->argv[j]);
358  manager->plugins[i]->argv[j] = NULL;
359  }
360  free(manager->plugins[i]->argv);
361  manager->plugins[i]->argv = NULL;
362  manager->plugins[i]->argc = 0;
363 
364  free(manager->plugins[i]);
365  manager->plugins[i] = NULL;
366  }
367  }
368  free(manager->plugins);
369  manager->plugins = NULL;
370  }
371 
372  if(manager->plugins_state != NULL)
373  {
374  /* as above, state will be freed by calls to the each plugins close
375  function */
376  free(manager->plugins_state);
377  manager->plugins_state = NULL;
378  }
379 
380  if(manager->plugins_enabled != NULL)
381  {
382  free(manager->plugins_enabled);
383  manager->plugins_enabled = NULL;
384  }
385 
386  manager->first_plugin = NULL;
387  manager->plugins_cnt = 0;
388 
389  /* we are NOT responsible for the logfile pointer */
390  /* should maybe think about making files use reference counting? */
391 
392  free(manager);
393 }
394 
396  int id)
397 {
398  assert(manager != NULL);
399  if(id < 0 || id > CORSARO_PLUGIN_ID_MAX)
400  {
401  return NULL;
402  }
403 
404  return manager->plugins[id-1];
405 }
406 
408  uint32_t magic)
409 {
410  assert(manager != NULL);
411  corsaro_plugin_t *p = NULL;
412  while((p = corsaro_plugin_next(manager, p)) != NULL)
413  {
414  if(p->magic == magic)
415  {
416  return p;
417  }
418  }
419  return NULL;
420 }
421 
423  const char *name)
424 {
425  corsaro_plugin_t *p = NULL;
426  while((p = corsaro_plugin_next(manager, p)) != NULL)
427  {
428  if(strlen(name) == strlen(p->name) &&
429  strncasecmp(name, p->name, strlen(p->name)) == 0)
430  {
431  return p;
432  }
433  }
434  return NULL;
435 }
436 
438  corsaro_plugin_t *plugin)
439 {
440  /* plugins have already been freed, or not init'd */
441  assert(manager != NULL && manager->plugins != NULL
442  && manager->plugins_cnt != 0);
443 
444  /* they are asking for the beginning of the list */
445  if(plugin == NULL)
446  {
447  return manager->first_plugin;
448  }
449 
450  /* otherwise, give them the next one */
451  return plugin->next;
452 }
453 
455  corsaro_plugin_t *plugin,
456  void *state)
457 {
458  assert(manager != NULL);
459  assert(plugin != NULL);
460  assert(state != NULL);
461 
462  manager->plugins_state[plugin->id-1] = state;
463 }
464 
466  corsaro_plugin_t *plugin)
467 {
468  assert(manager != NULL);
469  assert(plugin != NULL);
470 
471  free(manager->plugins_state[plugin->id-1]);
472  manager->plugins_state[plugin->id-1] = NULL;
473 }
474 
475 int corsaro_plugin_probe_filename(const char *fname, corsaro_plugin_t *plugin)
476 {
477  assert(fname != NULL);
478  assert(plugin != NULL && plugin->name != NULL);
479 
480  if(strstr(fname, plugin->name) != NULL)
481  {
482  return 1;
483  }
484  return 0;
485 }
486 
488  int id)
489 {
490  corsaro_plugin_t *plugin = NULL;
491  if((plugin = corsaro_plugin_get_by_id(manager, id)) == NULL)
492  {
493  return NULL;
494  }
495  return plugin->name;
496 }
497 
499  uint32_t magic)
500 {
501  corsaro_plugin_t *plugin = NULL;
502  if((plugin = corsaro_plugin_get_by_magic(manager, magic)) == NULL)
503  {
504  return NULL;
505  }
506  return plugin->name;
507 }
508 
510  corsaro_plugin_t *plugin)
511 {
512  int i;
513 
514  if(manager->plugins_enabled == NULL)
515  {
516  /* no plugins have been explicitly enabled, therefore all plugins
517  are implicitly enabled */
518  return 1;
519  }
520 
521  for(i=0; i<manager->plugins_enabled_cnt; i++)
522  {
523  if(manager->plugins_enabled[i] == plugin->id)
524  {
525  return 1;
526  }
527  }
528 
529  return 0;
530 }
531 
533  const char *plugin_name,
534  const char *plugin_args)
535 {
536  corsaro_plugin_t *plugin = NULL;
537  int i;
538  char *local_args = NULL;
539  char *process_argv[MAXOPTS];
540  int process_argc = 0;
541 
542  assert(manager != NULL);
543 
544  /* first, let us find the plugin with this name */
545  if((plugin = corsaro_plugin_get_by_name(manager, plugin_name)) == NULL)
546  {
547  corsaro_log_file(__func__, LOG(manager),
548  "No plugin found with the name '%s'", plugin_name);
549  corsaro_log_file(__func__, LOG(manager),
550  "Is corsaro compiled with all necessary plugins?");
551  return -1;
552  }
553 
554  corsaro_log(__func__, NULL, "enabling %s", plugin_name);
555 
556  /* now lets set the arguments for the plugin */
557  /* we do this here, before we check if it is enabled to allow the args
558  to be re-set, so long as it is before the plugin is started */
559  if(plugin_args != NULL && strlen(plugin_args) > 0)
560  {
561  /* parse the args into argc and argv */
562  local_args = strdup(plugin_args);
563  parse_cmd(local_args, &process_argc, process_argv, MAXOPTS, plugin_name);
564  }
565 
566  /* remove the default arguments from the plugin (but only if new ones have
567  been given to us */
568  assert(plugin->argv != NULL && plugin->argc == 1);
569  if(process_argc > 0)
570  {
571  free(plugin->argv[0]);
572  free(plugin->argv);
573  plugin->argc = 0;
574 
575  if(copy_argv(plugin, process_argc, process_argv) != 0)
576  {
577  if(local_args != NULL)
578  {
579  corsaro_log(__func__, NULL, "freeing local args");
580  free(local_args);
581  }
582  return -1;
583  }
584 
585  if(local_args != NULL)
586  {
587  /* this is the storage for the strings until copy_argv is complete */
588  free(local_args);
589  }
590  }
591 
592  /* now we need to ensure it isn't already enabled */
593  for(i = 0; i < manager->plugins_enabled_cnt; i++)
594  {
595  if(plugin->id == manager->plugins_enabled[i])
596  {
597  return 0;
598  }
599  }
600 
601  /* now we need to remalloc the array */
602  if((manager->plugins_enabled = realloc(manager->plugins_enabled,
603  sizeof(uint16_t)*
604  (manager->plugins_enabled_cnt+1)
605  )) == NULL)
606  {
607  corsaro_log_file(__func__, LOG(manager),
608  "could not extend the enabled plugins array");
609  return -1;
610  }
611 
612  /* now we shall store this id in this spot! */
613  manager->plugins_enabled[manager->plugins_enabled_cnt++] = plugin->id;
614 
615  return 0;
616 }
int corsaro_plugin_is_enabled(corsaro_plugin_manager_t *manager, corsaro_plugin_t *plugin)
Determine whether this plugin is enabled for use.
const char * name
The name of this plugin used in the ascii output and eventually to allow plugins to be enabled and di...
Header file dealing with the corsaro plugin manager.
Header file dealing with the corsaro logging sub-system.
An opaque structure defining an corsaro output file.
Definition: corsaro_file.h:60
int(* close_input)(struct corsaro_in *corsaro)
Concludes an input file and cleans up the plugin data.
char ** argv
Array of plugin arguments This is populated by the plugin manager in corsaro_plugin_enable_plugin.
int(* close_output)(struct corsaro *corsaro)
Concludes an output file and cleans up the plugin data.
int corsaro_plugin_enable_plugin(corsaro_plugin_manager_t *manager, const char *plugin_name, const char *plugin_args)
Attempt to enable a plugin by its name.
corsaro_plugin_t * corsaro_plugin_next(corsaro_plugin_manager_t *manager, corsaro_plugin_t *plugin)
Retrieve the next plugin in the list.
uint16_t plugins_cnt
The number of active plugins.
Header file which exports corsaro_flowtuple plugin API.
void corsaro_plugin_free_state(corsaro_plugin_manager_t *manager, corsaro_plugin_t *plugin)
Free the state for a plugin.
corsaro_plugin_t * corsaro_plugin_get_by_magic(corsaro_plugin_manager_t *manager, uint32_t id)
Attempt to retrieve a plugin by magic number (not by using magic)
void ** plugins_state
A pointer to the array of plugin states.
uint16_t * plugins_enabled
An array of plugin ids that have been enabled by the user.
Header file for common utility functions.
void corsaro_plugin_manager_free(corsaro_plugin_manager_t *manager)
Free the plugin manager and all in-use plugins.
Holds the metadata for the plugin manager.
int corsaro_plugin_manager_start(corsaro_plugin_manager_t *manager)
Start the plugin manager.
const char * corsaro_plugin_get_name_by_id(corsaro_plugin_manager_t *manager, int id)
Get the name of a plugin given it's ID number.
void corsaro_plugin_register_state(corsaro_plugin_manager_t *manager, corsaro_plugin_t *plugin, void *state)
Register the state for a plugin.
int corsaro_plugin_probe_filename(const char *fname, corsaro_plugin_t *plugin)
Check a filename to see if it contains a plugin's name.
const char * corsaro_plugin_get_name_by_magic(corsaro_plugin_manager_t *manager, uint32_t magic)
Get the name of a plugin given it's magic number.
void * malloc_zero(const size_t size)
Allocate memory and set it to zero.
Definition: utils.c:78
int(* init_output)(struct corsaro *corsaro)
Initialises an output file using the plugin.
int argc
Count of arguments in argv.
corsaro_plugin_manager_t * corsaro_plugin_manager_init()
Initialize the plugin manager and all in-use plugins.
int(* probe_filename)(const char *fname)
Given a filename, return if this is the most likely plugin.
int(* start_interval)(struct corsaro *corsaro, struct corsaro_interval *int_start)
Starts a new interval.
const corsaro_plugin_id_t id
The corsaro plugin id for this plugin.
corsaro_plugin_t * corsaro_plugin_get_by_id(corsaro_plugin_manager_t *manager, int id)
Attempt to retrieve a plugin by id.
struct corsaro_plugin * next
Next pointer, should always be NULL - used by the plugin manager.
corsaro_plugin_t * corsaro_plugin_get_by_name(corsaro_plugin_manager_t *manager, const char *name)
Attempt to retrieve a plugin by name.
void corsaro_log_file(const char *func, corsaro_file_t *logfile, const char *format,...)
Write a formatted string to a generic log file.
Definition: corsaro_log.c:132
int(* end_interval)(struct corsaro *corsaro, struct corsaro_interval *int_end)
Ends an interval.
corsaro_plugin_t ** plugins
A pointer to the array of plugins in use.
int(* process_packet)(struct corsaro *corsaro, struct corsaro_packet *packet)
Process a packet.
uint16_t plugins_enabled_cnt
The number of plugin ids in the plugins_enabled array.
Maximum plugin ID assigned.
off_t(* read_global_data_record)(struct corsaro_in *corsaro, enum corsaro_in_record_type *record_type, struct corsaro_in_record *record)
Reads a plugin global data block from an input file.
int(* init_input)(struct corsaro_in *corsaro)
Initialises an input file using the plugin.
void corsaro_log(const char *func, corsaro_t *corsaro, const char *format,...)
Write a formatted string to the logfile associated with an corsaro object.
Definition: corsaro_log.c:113
const uint32_t magic
The magic number for this plugin's data.
corsaro_file_t * logfile
A pointer to the logfile to use.
corsaro_plugin_t * first_plugin
A pointer to the first plugin in the list.
An corsaro packet processing plugin.
int(* probe_magic)(struct corsaro_in *corsaro, corsaro_file_in_t *file)
Given a file, looks at next 4 bytes to determine if this is the right plugin.
off_t(* read_record)(struct corsaro_in *corsaro, enum corsaro_in_record_type *record_type, struct corsaro_in_record *record)
Reads the next block of plugin data from an input file.
Header file dealing with the internal corsaro functions.