Skip to Content
[CAIDA - Center for Applied Internet Data Analysis logo]
The Center for Applied Internet Data Analysis
corsaro_filterpfx.c
Go to the documentation of this file.
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 <arpa/inet.h>
30 
31 #include <assert.h>
32 #include <inttypes.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <unistd.h>
37 
38 #include "libtrace.h"
39 
40 #include "patricia.h"
41 #include "utils.h"
42 
43 #include "corsaro_log.h"
44 #include "corsaro_plugin.h"
45 
46 #ifdef WITH_PLUGIN_SIXT
47 #include "corsaro_flowtuple.h"
48 #endif
49 
50 #include "corsaro_filterpfx.h"
51 
61 #define CORSARO_FILTERPFX_MAGIC 0x46504658
62 
64 #define PLUGIN_NAME "filterpfx"
65 
67 #define BUFFER_LEN 1024
68 
71 #define MAX_COMMAND_LINE_PREFIXES 100
72 
75  PLUGIN_NAME, /* name */
77  CORSARO_FILTERPFX_MAGIC, /* magic */
78 #ifdef WITH_PLUGIN_SIXT
79  CORSARO_PLUGIN_GENERATE_PTRS_FT(corsaro_filterpfx), /* func ptrs */
80 #else
81  CORSARO_PLUGIN_GENERATE_PTRS(corsaro_filterpfx),
82 #endif
84 };
85 
87 struct corsaro_filterpfx_state_t {
89  patricia_tree_t *trie;
91  char *pfx_file;
93  char *cmd_prefixes[MAX_COMMAND_LINE_PREFIXES];
95  int cmd_prefix_cnt;
97  int destination;
100  int invert;
101 };
102 
104 #define STATE(corsaro) \
105  (CORSARO_PLUGIN_STATE(corsaro, filterpfx, CORSARO_PLUGIN_ID_FILTERPFX))
106 
108 #define PLUGIN(corsaro) \
109  (CORSARO_PLUGIN_PLUGIN(corsaro, CORSARO_PLUGIN_ID_FILTERPFX))
110 
112 static void usage(corsaro_plugin_t *plugin)
113 {
114  fprintf(stderr,
115  "plugin usage: %s [-di] [-p pfx [-p pfx]] [-f pfx_file]\n"
116  " -d use destination address (default: source)\n"
117  " -f read prefixes from the given file\n"
118  " -i invert the matching (default: find matches)\n"
119  " -p prefix to match against, -p can be used "
120  "up to %d times\n",
121  plugin->argv[0],
123 }
124 
127 {
128  corsaro_plugin_t *plugin = PLUGIN(corsaro);
129  struct corsaro_filterpfx_state_t *state = STATE(corsaro);
130  int opt;
131 
132  /* remember the storage for the argv strings belongs to us, we don't need
133  to strdup them */
134 
135  /* NB: remember to reset optind to 1 before using getopt! */
136  optind = 1;
137 
138  while((opt = getopt(plugin->argc, plugin->argv, "p:f:di?")) >= 0)
139  {
140  switch(opt)
141  {
142  case 'd':
143  state->destination = 1;
144 
145  case 'f':
146  state->pfx_file = optarg;
147  break;
148 
149  case 'i':
150  state->invert = 1;
151  break;
152 
153  case 'p':
154  if(state->cmd_prefix_cnt == MAX_COMMAND_LINE_PREFIXES)
155  {
156  fprintf(stderr, "ERROR: A maximum of %d prefixes can be "
157  "specified using the -p option.\n"
158  "Consider using the -f option instead\n",
160  usage(plugin);
161  return -1;
162  }
163  state->cmd_prefixes[state->cmd_prefix_cnt] = optarg;
164  state->cmd_prefix_cnt++;
165  break;
166 
167  case '?':
168  case ':':
169  default:
170  usage(plugin);
171  return -1;
172  }
173  }
174 
175  if(state->pfx_file == NULL && state->cmd_prefix_cnt == 0)
176  {
177  fprintf(stderr, "ERROR: %s requires either '-f' or '-p' to be specified\n",
178  plugin->argv[0]);
179  usage(plugin);
180  return -1;
181  }
182 
183  if(state->pfx_file != NULL && state->cmd_prefix_cnt > 0)
184  {
185  fprintf(stderr,
186  "WARNING: both -f and -p used, all specified prefixes "
187  "will be used\n");
188  }
189 
190  return 0;
191 }
192 
194 static int add_prefix(corsaro_t *corsaro, char *pfx_str)
195 {
196  prefix_t *pfx = NULL;
197  patricia_node_t *trie_node = NULL;
198 
199  /* no sanity checking, let libpatricia sort it out */
200  if((pfx = ascii2prefix(AF_INET, pfx_str)) == NULL)
201  {
202  /* invalid prefix? */
203  /* skip it, or explode? */
204 
205  /* explode, but only if asserts are on */
206  corsaro_log(__func__, corsaro, "failed to parse prefix '%s'",
207  pfx_str);
208  assert(0);
209  }
210 
211  /* shove it in the trie */
212  if((trie_node = patricia_lookup(STATE(corsaro)->trie, pfx)) == NULL)
213  {
214  corsaro_log(__func__, corsaro, "failed to insert prefix in trie");
215  return -1;
216  }
217 
218  return 0;
219 }
220 
223 {
224  char buffer[BUFFER_LEN];
225 
226  while(corsaro_file_rgets(file, &buffer, BUFFER_LEN) > 0)
227  {
228  /* hack off the newline */
229  chomp(buffer);
230 
231  if(add_prefix(corsaro, buffer) != 0)
232  {
233  return -1;
234  }
235  }
236 
237  return 0;
238 }
239 
242  uint32_t ip_addr)
243 {
244  struct corsaro_filterpfx_state_t *plugin_state = STATE(corsaro);
245  patricia_node_t *node = NULL;
246  prefix_t pfx;
247  pfx.family = AF_INET;
248  pfx.bitlen = 32;
249  pfx.ref_count = 0;
250  pfx.add.sin.s_addr = ip_addr;
251 
252  if((node = patricia_search_best2(plugin_state->trie,
253  &pfx, 1)) == NULL)
254  {
255  /* this address is NOT covered by a prefix */
256  if(plugin_state->invert == 0)
257  {
259  }
260  }
261  else
262  {
263  if(plugin_state->invert != 0)
264  {
266  }
267  }
268 
269  return 0;
270 }
271 
272 /* == PUBLIC PLUGIN FUNCS BELOW HERE == */
273 
276 {
277  return &corsaro_filterpfx_plugin;
278 }
279 
281 int corsaro_filterpfx_probe_filename(const char *fname)
282 {
283  /* this writes no files! */
284  return 0;
285 }
286 
289  corsaro_file_in_t *file)
290 {
291  /* this writes no files! */
292  return 0;
293 }
294 
297 {
298  struct corsaro_filterpfx_state_t *state;
299  corsaro_plugin_t *plugin = PLUGIN(corsaro);
300  corsaro_file_in_t *file = NULL;
301  int i;
302 
303  assert(plugin != NULL);
304 
305  if((state = malloc_zero(sizeof(struct corsaro_filterpfx_state_t))) == NULL)
306  {
307  corsaro_log(__func__, corsaro,
308  "could not malloc corsaro_maxmind_state_t");
309  return -1;
310  }
311  corsaro_plugin_register_state(corsaro->plugin_manager, plugin, state);
312 
313  /* parse the arguments */
314  if(parse_args(corsaro) != 0)
315  {
316  /* parse args calls usage itself, so do not goto err here */
317  return -1;
318  }
319 
320  /* initialize the trie */
321  state->trie = New_Patricia(32);
322  assert(state->trie != NULL);
323 
324  /* read in prefixes from the pfx_file (if there is one) */
325  if(state->pfx_file != NULL)
326  {
327  if((file = corsaro_file_ropen(state->pfx_file)) == NULL)
328  {
329  corsaro_log(__func__, corsaro,
330  "failed to open prefix file '%s'", state->pfx_file);
331 
332  goto err;
333  }
334 
335  if(read_pfx_file(corsaro, file) != 0)
336  {
337  corsaro_log(__func__, corsaro,
338  "failed to read prefix file '%s'", state->pfx_file);
339  goto err;
340  }
341 
342  /* close the prefix file */
343  corsaro_file_rclose(file);
344  file = NULL;
345  }
346 
347  /* add the prefixes that have been manually specified */
348  for(i = 0; i < state->cmd_prefix_cnt; i++)
349  {
350  if(add_prefix(corsaro, state->cmd_prefixes[i]) != 0)
351  {
352  goto err;
353  }
354  }
355 
356  return 0;
357 
358  err:
359  if(file != NULL)
360  {
361  corsaro_file_rclose(file);
362  }
363  if(state->trie != NULL)
364  {
365  Destroy_Patricia(state->trie, NULL);
366  state->trie = NULL;
367  }
368  usage(plugin);
369  return -1;
370 }
371 
374 {
375  assert(0);
376  return -1;
377 }
378 
381 {
382  assert(0);
383  return -1;
384 }
385 
388 {
389  struct corsaro_filterpfx_state_t *state = STATE(corsaro);
390  if(state != NULL)
391  {
392  if(state->trie != NULL)
393  {
394  Destroy_Patricia(state->trie, NULL);
395  state->trie = NULL;
396  }
397  corsaro_plugin_free_state(corsaro->plugin_manager, PLUGIN(corsaro));
398  }
399  return 0;
400 }
401 
404  corsaro_in_record_type_t *record_type,
406 {
407  assert(0);
408  return -1;
409 }
410 
413  enum corsaro_in_record_type *record_type,
414  struct corsaro_in_record *record)
415 {
416  /* we write nothing to the global file. someone messed up */
417  return -1;
418 }
419 
422  corsaro_interval_t *int_start)
423 {
424  /* we don't care */
425  return 0;
426 }
427 
430  corsaro_interval_t *int_end)
431 {
432  /* we don't care */
433  return 0;
434 }
435 
439 {
440  libtrace_packet_t *ltpacket = LT_PKT(packet);
441  libtrace_ip_t *ip_hdr = NULL;
442  uint32_t ip_addr;
443 
444  /* check for ipv4 */
445  if((ip_hdr = trace_get_ip(ltpacket)) == NULL)
446  {
447  /* not an ip packet */
448  return 0;
449  }
450 
451  ip_addr = (STATE(corsaro)->destination == 0) ? ip_hdr->ip_src.s_addr :
452  ip_hdr->ip_dst.s_addr;
453 
454  return process_generic(corsaro, &packet->state, ip_addr);
455 }
456 
457 #ifdef WITH_PLUGIN_SIXT
458 
459 int corsaro_filterpfx_process_flowtuple(corsaro_t *corsaro,
460  corsaro_flowtuple_t *flowtuple,
461  corsaro_packet_state_t *state)
462 {
463  uint32_t ip_addr;
464 
465  ip_addr = (STATE(corsaro)->destination == 0) ?
468 
469  return process_generic(corsaro, state, ip_addr);
470 }
471 
473 int corsaro_filterpfx_process_flowtuple_class_start(corsaro_t *corsaro,
474  corsaro_flowtuple_class_start_t *class)
475 {
476  /* we dont care about these */
477  return 0;
478 }
479 
481 int corsaro_filterpfx_process_flowtuple_class_end(corsaro_t *corsaro,
482  corsaro_flowtuple_class_end_t *class)
483 {
484  /* dont care */
485  return 0;
486 }
487 #endif
Structure representing the start or end of an interval.
Definition: corsaro_int.h:156
#define PLUGIN_NAME
The name of this plugin.
An opaque structure defining an corsaro input file.
Definition: corsaro_file.h:86
Plugins which write output should ignore this packet.
Definition: corsaro_int.h:207
Header file dealing with the corsaro plugin manager.
off_t corsaro_file_rgets(corsaro_file_in_t *file, void *buffer, off_t len)
Reads a string from an corsaro input file into the provided buffer.
Definition: corsaro_file.c:343
Header file dealing with the corsaro logging sub-system.
A reusable opaque structure for corsaro to read an input record into.
Definition: corsaro_int.h:350
off_t corsaro_filterpfx_read_global_data_record(struct corsaro_in *corsaro, enum corsaro_in_record_type *record_type, struct corsaro_in_record *record)
Implements the read_global_data_record function of the plugin API.
char ** argv
Array of plugin arguments This is populated by the plugin manager in corsaro_plugin_enable_plugin.
uint32_t corsaro_flowtuple_get_destination_ip(corsaro_flowtuple_t *flowtuple)
Convenience function to get the destination IP address from a FlowTuple.
#define LT_PKT(corsaro_packet)
Convenience macro to get to the libtrace packet inside an corsaro packet.
Definition: corsaro_int.h:227
int corsaro_filterpfx_init_input(corsaro_in_t *corsaro)
Implements the init_input function of the plugin API.
int corsaro_filterpfx_end_interval(corsaro_t *corsaro, corsaro_interval_t *int_end)
Implements the end_interval function of the plugin API.
static int read_pfx_file(corsaro_t *corsaro, corsaro_file_in_t *file)
Read a file containing a list of prefixes.
int corsaro_filterpfx_start_interval(corsaro_t *corsaro, corsaro_interval_t *int_start)
Implements the start_interval function of the plugin API.
static corsaro_plugin_t corsaro_filterpfx_plugin
Common plugin information across all instances.
Header file which exports corsaro_flowtuple plugin API.
#define BUFFER_LEN
The length of the static line buffer.
static libtrace_packet_t * packet
A pointer to a libtrace packet.
Definition: corsaro_main.c:67
void corsaro_plugin_free_state(corsaro_plugin_manager_t *manager, corsaro_plugin_t *plugin)
Free the state for a plugin.
Header file for common utility functions.
A lightweight wrapper around a libtrace packet.
Definition: corsaro_int.h:211
corsaro_plugin_manager_t * plugin_manager
A pointer to the corsaro plugin manager state.
Definition: corsaro_int.h:273
#define CORSARO_PLUGIN_GENERATE_PTRS(plugin)
Convenience macro that defines all the function pointers for the corsaro plugin API.
corsaro_in_record_type
Corsaro input record types.
Definition: corsaro.h:97
void corsaro_plugin_register_state(corsaro_plugin_manager_t *manager, corsaro_plugin_t *plugin, void *state)
Register the state for a plugin.
uint32_t corsaro_flowtuple_get_source_ip(corsaro_flowtuple_t *flowtuple)
Convenience function to get the source IP address from a FlowTuple.
void corsaro_file_rclose(corsaro_file_in_t *file)
Closes an corsaro input file and frees the reader structure.
Definition: corsaro_file.c:428
#define CORSARO_PLUGIN_GENERATE_TAIL
Convenience macro that defines all the 'remaining' blank fields in a corsaro plugin object...
void * malloc_zero(const size_t size)
Allocate memory and set it to zero.
Definition: utils.c:78
int corsaro_filterpfx_close_input(corsaro_in_t *corsaro)
Implements the close_input function of the plugin API.
static corsaro_in_record_t * record
A pointer to a corsaro record.
Definition: corsaro_main.c:76
int argc
Count of arguments in argv.
corsaro_plugin_t * corsaro_filterpfx_alloc(corsaro_t *corsaro)
Implements the alloc function of the plugin API.
void chomp(char *line)
Remove a newline from the given string.
Definition: utils.c:114
corsaro_packet_state_t state
The corsaro state associated with this packet.
Definition: corsaro_int.h:214
uint8_t flags
Features of the packet that have been identified by earlier plugins.
Definition: corsaro_int.h:197
#define PLUGIN(corsaro)
Extends the generic plugin plugin convenience macro in corsaro_plugin.h.
int corsaro_filterpfx_close_output(corsaro_t *corsaro)
Implements the close_output function of the plugin API.
int corsaro_filterpfx_probe_magic(corsaro_in_t *corsaro, corsaro_file_in_t *file)
Implements the probe_magic function of the plugin API.
int corsaro_filterpfx_init_output(corsaro_t *corsaro)
Implements the init_output function of the plugin API.
Corsaro input state.
Definition: corsaro_int.h:323
#define MAX_COMMAND_LINE_PREFIXES
The max number of prefixes which can be supplied on the command line, if you have more than this...
#define CORSARO_FILTERPFX_MAGIC
The magic number for this plugin - "FPFX".
Corsaro state for a packet.
Definition: corsaro_int.h:194
static int process_generic(corsaro_t *corsaro, corsaro_packet_state_t *state, uint32_t ip_addr)
Common code between process_packet and process_flowtuple.
int corsaro_filterpfx_probe_filename(const char *fname)
Implements the probe_filename function of the plugin API.
int corsaro_filterpfx_process_packet(corsaro_t *corsaro, corsaro_packet_t *packet)
Implements the process_packet function of the plugin API.
Corsaro output state.
Definition: corsaro_int.h:230
corsaro_file_in_t * corsaro_file_ropen(const char *filename)
Creates a new corsaro file reader and opens the provided file for reading.
Definition: corsaro_file.c:256
static int add_prefix(corsaro_t *corsaro, char *pfx_str)
Parse a prefix string and add it to the trie.
static void usage(corsaro_plugin_t *plugin)
Print usage information to stderr.
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
off_t corsaro_filterpfx_read_record(struct corsaro_in *corsaro, corsaro_in_record_type_t *record_type, corsaro_in_record_t *record)
Implements the read_record function of the plugin API.
static int parse_args(corsaro_t *corsaro)
Parse the arguments given to the plugin.
enum corsaro_in_record_type corsaro_in_record_type_t
Corsaro input record types.
An corsaro packet processing plugin.
#define STATE(corsaro)
Extends the generic plugin state convenience macro in corsaro_plugin.h.
Header file dealing with the internal corsaro functions.