Skip to Content
[CAIDA - Center for Applied Internet Data Analysis logo]
The Center for Applied Internet Data Analysis
corsaro_dos.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 #include <assert.h>
31 #include <inttypes.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <time.h>
35 
36 #include "libtrace.h"
37 #ifdef HAVE_LIBPACKETDUMP
38 #include "libpacketdump.h"
39 #endif
40 
41 #include "khash.h"
42 #include "ksort.h"
43 #include "utils.h"
44 
45 #include "corsaro_io.h"
46 #include "corsaro_file.h"
47 #include "corsaro_log.h"
48 #include "corsaro_plugin.h"
49 
50 #include "corsaro_dos.h"
51 
61 #define CORSARO_DOS_MAGIC 0x45444F53
62 
64 #define PLUGIN_NAME "dos"
65 
72 #define PLUGIN_NAME_DEPRECATED "edgar_dos"
73 
76  PLUGIN_NAME, /* name */
77  CORSARO_PLUGIN_ID_DOS, /* id */
78  CORSARO_DOS_MAGIC, /* magic */
79  CORSARO_PLUGIN_GENERATE_PTRS(corsaro_dos), /* func ptrs */
81 };
82 
94 #define CORSARO_DOS_INTERVAL 300
95 
97 #define CORSARO_DOS_VECTOR_TIMEOUT CORSARO_DOS_INTERVAL
98 
100 #define CORSARO_DOS_ATTACK_VECTOR_MIN_PACKETS 25
101 
103 #define CORSARO_DOS_ATTACK_VECTOR_MIN_DURATION 60
104 
106 #define CORSARO_DOS_ATTACK_VECTOR_MIN_PPM 30
107 
109 #define CORSARO_DOS_ATTACK_VECTOR_BYTECNT (4+4+4+4+4+8+4+8+4+8+4+4+4+4+4)
110 
112 #define CORSARO_DOS_PPM_WINDOW_SIZE 60
113 
115 #define CORSARO_DOS_PPM_WINDOW_PRECISION 10
116 
118 #define CORSARO_DOS_PPS_BUCKET_CNT (CORSARO_DOS_PPM_WINDOW_SIZE/ \
119  CORSARO_DOS_PPM_WINDOW_PRECISION)
120 
127 KHASH_SET_INIT_INT(32xx)
128 
129 
130 typedef struct ppm_window
131 {
133  uint32_t window_start;
135  uint64_t buckets[CORSARO_DOS_PPS_BUCKET_CNT];
137  uint8_t current_bucket;
139  uint64_t max_ppm;
140 } ppm_window_t;
141 
146 typedef struct attack_vector
147 {
152  uint8_t *initial_packet;
153 
155  uint32_t initial_packet_len;
156 
158  uint32_t attacker_ip;
159 
161  uint32_t responder_ip;
162 
164  uint32_t target_ip;
165 
167  uint64_t packet_cnt;
168 
170  uint32_t interval_packet_cnt;
171 
173  uint64_t byte_cnt;
174 
176  uint32_t interval_byte_cnt;
177 
179  ppm_window_t ppm_window;
180 
182  struct timeval start_time;
183 
185  struct timeval latest_time;
186 
188  kh_32xx_t *attack_ip_hash;
189 
191  kh_32xx_t *attack_port_hash;
192 
194  kh_32xx_t *target_port_hash;
195 
197  uint32_t attack_ip_cnt;
198 
200 
201 /* need to create an attack_vector_in structure when we write the reading
202  stuff */
203 
210 {
211  attack_vector_t *av = NULL;
212  if((av = malloc_zero(sizeof(attack_vector_t))) == NULL)
213  {
214  corsaro_log(__func__, corsaro, "could not malloc memory for attack vector");
215  return NULL;
216  }
217 
218  av->attack_ip_hash = kh_init(32xx);
219  assert(av->attack_ip_hash != NULL);
220 
221  av->attack_port_hash = kh_init(32xx);
222  assert(av->attack_port_hash != NULL);
223 
224  av->target_port_hash = kh_init(32xx);
225  assert(av->target_port_hash != NULL);
226 
227  return av;
228 }
229 
235 {
236  if(av == NULL)
237  {
238  return;
239  }
240 
241  if(av->initial_packet != NULL)
242  {
243  /*trace_destroy_packet(av->initial_packet);*/
244  free(av->initial_packet);
245  }
246 
247  if(av->attack_ip_hash != NULL)
248  {
249  kh_destroy(32xx, av->attack_ip_hash);
250  }
251  if(av->attack_port_hash != NULL)
252  {
253  kh_destroy(32xx, av->attack_port_hash);
254  }
255  if(av->target_port_hash != NULL)
256  {
257  kh_destroy(32xx, av->target_port_hash);
258  }
259 
260  free(av);
261  return;
262 }
263 
269 {
270  assert(av != NULL);
271 
272  av->interval_packet_cnt = 0;
273  av->interval_byte_cnt = 0;
274  av->attack_ip_cnt = kh_size(av->attack_ip_hash);
275 }
276 
278 #define attack_vector_hash_equal(a, b) ( \
279  (a)->target_ip == (b)->target_ip \
280  )
281 
286 static inline khint32_t attack_vector_hash_func(attack_vector_t *av)
287 {
288  return (khint32_t)av->target_ip*59;
289 }
290 
292 KHASH_INIT(av, attack_vector_t*, char, 0,
294 
296 struct corsaro_dos_state_t {
298  uint32_t first_interval;
301  uint16_t number_mismatched_packets;
303  khash_t(av) *attack_hash;
305  corsaro_file_t *outfile;
306 };
307 
309 struct corsaro_dos_in_state_t {
311  corsaro_in_record_type_t expected_type;
313  int vector_total;
315  int vector_cnt;
316 };
317 
319 #define STATE(corsaro) \
320  (CORSARO_PLUGIN_STATE(corsaro, dos,CORSARO_PLUGIN_ID_DOS))
321 
322 #define STATE_IN(corsaro) \
323  (CORSARO_PLUGIN_STATE(corsaro, dos_in, \
324  CORSARO_PLUGIN_ID_DOS))
325 
326 #define PLUGIN(corsaro) \
327  (CORSARO_PLUGIN_PLUGIN(corsaro, CORSARO_PLUGIN_ID_DOS))
328 
335  uint32_t time)
336 {
337  if(vector->latest_time.tv_sec + CORSARO_DOS_VECTOR_TIMEOUT < time)
338  {
339  return 1;
340  }
341  return 0;
342 }
343 
347 static void attack_vector_update_ppm(ppm_window_t *ppm_window)
348 {
349  int i;
350  uint64_t this_ppm;
351 
352  /* calculate the ppm for the current window in the buckets */
353  this_ppm = 0;
354  for(i = 0; i < CORSARO_DOS_PPS_BUCKET_CNT; i++)
355  {
356  this_ppm += ppm_window->buckets[i];
357  }
358  if(this_ppm > ppm_window->max_ppm)
359  {
360  ppm_window->max_ppm = this_ppm;
361  }
362 }
363 
441  struct timeval tv)
442 {
443  int bucket_offset;
444  int i;
445 
446  ppm_window_t *ppm_window = &vector->ppm_window;
447 
448  bucket_offset = (tv.tv_sec-ppm_window->window_start)/
450 
451  /* this packet is outside of the current bucket */
452  if(bucket_offset > 0)
453  {
454  attack_vector_update_ppm(ppm_window);
455 
456  /* zero out the first n buckets in the window */
457  for(i = 0; i < bucket_offset && i < 6; i++)
458  {
459  ppm_window->current_bucket =
460  (ppm_window->current_bucket+1) % CORSARO_DOS_PPS_BUCKET_CNT;
461  ppm_window->buckets[ppm_window->current_bucket] = 0;
462  }
463  /* move the start of the window to the end of the zeroed buckets */
464  ppm_window->window_start += bucket_offset*
466 
467  }
468 
469  /* add this packet to current bucket */
470  ppm_window->buckets[ppm_window->current_bucket]++;
471 
472  return;
473 }
474 
483  attack_vector_t *vector,
484  uint32_t time)
485 {
486  struct timeval duration;
487  uint64_t ppm;
488 
489  if(vector->packet_cnt < CORSARO_DOS_ATTACK_VECTOR_MIN_PACKETS)
490  {
491  /* not enough packets */
492  return 0;
493  }
494 
495  if(timeval_subtract(&duration, &vector->latest_time,
496  &vector->start_time) == 1)
497  {
498  corsaro_log(__func__, corsaro, "last packet seen before first packet!");
499  return -1;
500  }
501  if(duration.tv_sec < CORSARO_DOS_ATTACK_VECTOR_MIN_DURATION)
502  {
503  /* not long enough */
504  return 0;
505  }
506 
507  attack_vector_update_ppm(&vector->ppm_window);
508  ppm = vector->ppm_window.max_ppm;
509 
511  {
512  /* not high enough velocity */
513  return 0;
514  }
515 
516  return 1;
517 }
518 
526 {
527  uint32_t tmp;
528  char t_ip[16];
529 
530  tmp = htonl(vector->target_ip);
531  inet_ntop(AF_INET,&tmp, &t_ip[0], 16);
532 
533  corsaro_file_printf(corsaro, STATE(corsaro)->outfile,
534  "%s"
535  ",%"PRIu32
536  ",%"PRIu32
537  ",%"PRIu32
538  ",%"PRIu32
539  ",%"PRIu64
540  ",%"PRIu32
541  ",%"PRIu64
542  ",%"PRIu32
543  ",%"PRIu64
544  ",%"PRIu32".%06"PRIu32
545  ",%"PRIu32".%06"PRIu32
546  "\n",
547  t_ip,
548  kh_size(vector->attack_ip_hash),
549  kh_size(vector->attack_ip_hash)-vector->attack_ip_cnt,
550  kh_size(vector->attack_port_hash),
551  kh_size(vector->target_port_hash),
552  vector->packet_cnt,
553  vector->interval_packet_cnt,
554  vector->byte_cnt,
555  vector->interval_byte_cnt,
556  vector->ppm_window.max_ppm,
557  (uint32_t)vector->start_time.tv_sec,
558  (uint32_t)vector->start_time.tv_usec,
559  (uint32_t)vector->latest_time.tv_sec,
560  (uint32_t)vector->latest_time.tv_usec);
561  return 0;
562 }
563 
571 {
572  uint8_t av_bytes[CORSARO_DOS_ATTACK_VECTOR_BYTECNT];
573  uint8_t *ptr = &av_bytes[0];
574 
575  /*
576  uint8_t *pkt_buf = NULL;
577  libtrace_linktype_t linktype;
578  uint32_t pkt_length;
579  */
580 
581  /* dump the attack vector details */
582 
583  bytes_htonl(ptr, vector->target_ip);
584  ptr+=4;
585 
586  bytes_htonl(ptr, kh_size(vector->attack_ip_hash));
587  ptr+=4;
588 
589  bytes_htonl(ptr, kh_size(vector->attack_ip_hash)-vector->attack_ip_cnt);
590  ptr+=4;
591 
592  bytes_htonl(ptr, kh_size(vector->attack_port_hash));
593  ptr+=4;
594 
595  bytes_htonl(ptr, kh_size(vector->target_port_hash));
596  ptr+=4;
597 
598  bytes_htonll(ptr, vector->packet_cnt);
599  ptr+=8;
600 
601  bytes_htonl(ptr, vector->interval_packet_cnt);
602  ptr+=4;
603 
604  bytes_htonll(ptr, vector->byte_cnt);
605  ptr+=8;
606 
607  bytes_htonl(ptr, vector->interval_byte_cnt);
608  ptr+=4;
609 
610  bytes_htonll(ptr, vector->ppm_window.max_ppm);
611  ptr+=8;
612 
613  bytes_htonl(ptr, vector->start_time.tv_sec);
614  ptr+=4;
615 
616  bytes_htonl(ptr, vector->start_time.tv_usec);
617  ptr+=4;
618 
619  bytes_htonl(ptr, vector->latest_time.tv_sec);
620  ptr+=4;
621 
622  bytes_htonl(ptr, vector->latest_time.tv_usec);
623  ptr+=4;
624 
625  /* dump the initial packet using trace_get_packet_buffer */
626  /*
627  if((pkt_buf = trace_get_packet_buffer(vector->initial_packet,
628  &linktype, NULL)) == NULL ||
629  (pkt_length = trace_get_capture_length(vector->initial_packet)) == 0)
630  {
631  corsaro_log(__func__, "could not get packet buffer");
632  return -1;
633  }
634  */
635 
636  /* add the size of the packet to the byte array before we dump it */
637  bytes_htonl(ptr, vector->initial_packet_len);
638 
639  if(corsaro_file_write(corsaro, STATE(corsaro)->outfile, &av_bytes[0],
642  {
643  corsaro_log(__func__, corsaro, "could not dump vector byte array to file");
644  return -1;
645  }
646 
647  if(corsaro_file_write(corsaro, STATE(corsaro)->outfile, vector->initial_packet,
648  vector->initial_packet_len) !=
649  vector->initial_packet_len)
650  {
651  corsaro_log(__func__, corsaro, "could not dump packet to file");
652  return -1;
653  }
654 
655  return 0;
656 }
657 
660  corsaro_in_record_type_t *record_type,
662 {
663  off_t bytes_read;
664 
665  if((bytes_read =
666  corsaro_io_read_bytes(corsaro, record,
667  sizeof(corsaro_dos_header_t))) !=
668  sizeof(corsaro_dos_header_t))
669  {
670  corsaro_log_in(__func__, corsaro, "failed to read dos header from file");
671  *record_type = CORSARO_IN_RECORD_TYPE_NULL;
672  return bytes_read;
673  }
674 
675  ((corsaro_dos_header_t *)record->buffer)->attack_vector_cnt =
676  ntohl(((corsaro_dos_header_t *)record->buffer)->attack_vector_cnt);
677 
678  assert(bytes_read == sizeof(corsaro_dos_header_t));
679 
680  *record_type = CORSARO_IN_RECORD_TYPE_DOS_HEADER;
681  STATE_IN(corsaro)->vector_total = ((corsaro_dos_header_t *)
682  record->buffer)->attack_vector_cnt;
683 
684  STATE_IN(corsaro)->expected_type = (STATE_IN(corsaro)->vector_total == 0) ?
687 
688  return bytes_read;
689 }
690 
693 {
694  /* short-circuit if the packet is empty */
695  if(av->initial_packet_len == 0)
696  {
697  return 0;
698  }
699 
700  /* we need to byte swap */
701  av->target_ip = ntohl(av->target_ip);
702  av->attacker_ip_cnt = ntohl(av->attacker_ip_cnt);
704  av->attack_port_cnt = ntohl(av->attack_port_cnt);
705  av->target_port_cnt = ntohl(av->target_port_cnt);
706  av->packet_cnt = ntohll(av->packet_cnt);
707  av->interval_packet_cnt = ntohl(av->interval_packet_cnt);
708  av->byte_cnt = ntohll(av->byte_cnt);
709  av->interval_byte_cnt = ntohl(av->interval_byte_cnt);
710  av->max_ppm = ntohll(av->max_ppm);
711  av->start_time_sec = ntohl(av->start_time_sec);
712  av->start_time_usec = ntohl(av->start_time_usec);
713  av->latest_time_sec = ntohl(av->latest_time_sec);
714  av->latest_time_usec = ntohl(av->latest_time_usec);
715  av->initial_packet_len = ntohl(av->initial_packet_len);
716 
717  /* NULL it just in case */
718  av->initial_packet = NULL;
719  return 1;
720 }
721 
724  corsaro_in_record_type_t *record_type,
726 {
727  off_t bytes_read;
728 
729  /* the number of bytes that should be read after the first read */
730  /* this is the size of the attack vector less the size of the pointer */
731  off_t bsbread = sizeof(corsaro_dos_attack_vector_in_t)
732  -sizeof(uint8_t*);
733 
735 
736  /* read the attack vector in record, but not the pointer to the packet
737  we will need to find the length before we read it in */
738 
739  if((bytes_read = corsaro_io_read_bytes(corsaro, record, bsbread)) != bsbread)
740  {
741  corsaro_log_in(__func__, corsaro,
742  "failed to read dos attack vector from file");
743  *record_type = CORSARO_IN_RECORD_TYPE_NULL;
744  return bytes_read;
745  }
746 
747  av = (corsaro_dos_attack_vector_in_t *)record->buffer;
748 
749  if(validate_attack_vector(av) != 1)
750  {
751  corsaro_log_in(__func__, corsaro, "could not validate attack vector");
752  *record_type = CORSARO_IN_RECORD_TYPE_NULL;
753  return -1;
754  }
755 
756  /* now read the packet into the buffer right after the attack vector */
757  if((bytes_read +=
758  corsaro_io_read_bytes_offset(corsaro, record,
760  av->initial_packet_len))
761  != (bsbread += av->initial_packet_len))
762  {
763  corsaro_log_in(__func__, corsaro,
764  "failed to read initial packet from file");
765  *record_type = CORSARO_IN_RECORD_TYPE_NULL;
766  return bytes_read;
767  }
768 
769  /* update the pointer */
771 
773 
774  if(++(STATE_IN(corsaro)->vector_cnt) == STATE_IN(corsaro)->vector_total)
775  {
776  STATE_IN(corsaro)->expected_type = CORSARO_IN_RECORD_TYPE_IO_INTERVAL_END;
777  STATE_IN(corsaro)->vector_total = 0;
778  STATE_IN(corsaro)->vector_cnt = 0;
779  }
780 
781  assert(bytes_read == sizeof(corsaro_dos_attack_vector_in_t)-sizeof(uint8_t*)
782  +av->initial_packet_len);
783 
784  return bytes_read;
785 }
786 
789 {
790  g->mismatched_pkt_cnt = ntohl(g->mismatched_pkt_cnt);
791  g->attack_vector_cnt = ntohl(g->attack_vector_cnt);
793 
794  return 1;
795 }
796 
797 /* == PUBLIC PLUGIN FUNCS BELOW HERE == */
798 
801 {
802  return &corsaro_dos_plugin;
803 }
804 
806 int corsaro_dos_probe_filename(const char *fname)
807 {
808  /* look for 'corsaro_dos' in the name */
809  if(corsaro_plugin_probe_filename(fname, &corsaro_dos_plugin) == 0)
810  {
811  if(strstr(fname, PLUGIN_NAME_DEPRECATED) != NULL)
812  {
813  return 1;
814  }
815  }
816  else
817  {
818  return 1;
819  }
820  return 0;
821 }
822 
828 {
829  /* unfortunately we cant detect this in corsaro 0.6 files.
830  alistair was an idiot and forgot to write an magic number for the
831  DOS plugin. */
832  return -1;
833 }
834 
837 {
838  struct corsaro_dos_state_t *state;
839  /* retrieve a pointer to the plugin struct with our name and id */
840  corsaro_plugin_t *plugin = PLUGIN(corsaro);
841  assert(plugin != NULL);
842 
843  /*
844  * allocate memory for the state structure which will hold a pointer to the
845  * output file and other statistics
846  */
847  if((state = malloc_zero(sizeof(struct corsaro_dos_state_t))) == NULL)
848  {
849  corsaro_log(__func__, corsaro,
850  "could not malloc corsaro_dos_state_t");
851  goto err;
852  }
853  /*
854  * register the state structure with the plugin manager
855  * this associates it with our plugin id so it can be retrieved later
856  */
857  corsaro_plugin_register_state(corsaro->plugin_manager, plugin, state);
858 
859  /* init the hash table for attack vectors */
860  state->attack_hash = kh_init(av);
861 
862  return 0;
863 
864  err:
865  corsaro_dos_close_output(corsaro);
866  return -1;
867 }
868 
871 {
872  struct corsaro_dos_in_state_t *state;
873  corsaro_plugin_t *plugin = PLUGIN(corsaro);
874  assert(plugin != NULL);
875 
876  if((state = malloc_zero(sizeof(struct corsaro_dos_in_state_t)))
877  == NULL)
878  {
879  corsaro_log_in(__func__, corsaro,
880  "could not malloc corsaro_dos_state_t");
881  goto err;
882  }
883  corsaro_plugin_register_state(corsaro->plugin_manager, plugin, state);
884 
885  /* we initially expect an corsaro interval record */
886  state->expected_type = CORSARO_IN_RECORD_TYPE_IO_INTERVAL_START;
887 
888  /* don't set the vector_cnt until we actually see a header record */
889 
890  return 0;
891 
892  err:
893  corsaro_dos_close_input(corsaro);
894  return -1;
895 }
896 
899 {
900  struct corsaro_dos_in_state_t *state = STATE_IN(corsaro);
901 
902  if(state != NULL)
903  {
904  corsaro_plugin_free_state(corsaro->plugin_manager, PLUGIN(corsaro));
905  }
906  return 0;
907 }
908 
911 {
912  struct corsaro_dos_state_t *state = STATE(corsaro);
913 
914  if(state != NULL)
915  {
916  if(state->attack_hash != NULL)
917  {
918  kh_free(av, state->attack_hash, &attack_vector_free);
919  kh_destroy(av, state->attack_hash);
920  state->attack_hash = NULL;
921  }
922 
923  if(state->outfile != NULL)
924  {
925  corsaro_file_close(corsaro, state->outfile);
926  state->outfile = NULL;
927  }
928  corsaro_plugin_free_state(corsaro->plugin_manager, PLUGIN(corsaro));
929  }
930  return 0;
931 }
932 
935  corsaro_in_record_type_t *record_type,
937 {
938  struct corsaro_dos_in_state_t *state = STATE_IN(corsaro);
939 
940  off_t bytes_read = -1;
941 
942  /* this code is adapted from corsaro_flowtuple.c */
943  /* we have 5 different types of records that could be in this file */
944  switch(state->expected_type)
945  {
947  /* ask the io subsystem to read it for us */
948  bytes_read = corsaro_io_read_interval_start(corsaro, corsaro->file,
949  record_type, record);
950  if(bytes_read == sizeof(corsaro_interval_t))
951  {
952  state->expected_type = CORSARO_IN_RECORD_TYPE_DOS_HEADER;
953  }
954  break;
955 
957  /* we'll handle this one */
958  bytes_read = read_header(corsaro, record_type, record);
959  break;
960 
962  /* we'll handle this too */
963  bytes_read = read_attack_vector(corsaro, record_type, record);
964  break;
965 
967  /* ask the io subsystem to read it for us */
968  bytes_read = corsaro_io_read_interval_end(corsaro, corsaro->file,
969  record_type, record);
970  if(bytes_read == sizeof(corsaro_interval_t))
971  {
972  state->expected_type = CORSARO_IN_RECORD_TYPE_IO_INTERVAL_START;
973  }
974  break;
975 
976  default:
977  corsaro_log_in(__func__, corsaro, "invalid expected record type");
978  }
979 
980  return bytes_read;
981 }
982 
985  enum corsaro_in_record_type *record_type,
986  struct corsaro_in_record *record)
987 {
988  off_t bytes_read;
989 
990  if((bytes_read = corsaro_io_read_bytes(corsaro, record,
991  sizeof(corsaro_dos_global_header_t))) !=
993  {
994  *record_type = CORSARO_IN_RECORD_TYPE_NULL;
995  return bytes_read;
996  }
997 
999  != 1)
1000  {
1001  corsaro_log_in(__func__, corsaro, "could not validate global header");
1002  *record_type = CORSARO_IN_RECORD_TYPE_NULL;
1003  return -1;
1004  }
1005 
1007 
1008  assert(bytes_read == sizeof(corsaro_dos_global_header_t));
1009 
1010  return bytes_read;
1011 }
1012 
1015 {
1016  /* open the output file if it has been closed */
1017  if(STATE(corsaro)->outfile == NULL &&
1018  (STATE(corsaro)->outfile =
1019  corsaro_io_prepare_file(corsaro, PLUGIN(corsaro)->name,
1020  int_start)) == NULL)
1021  {
1022  corsaro_log(__func__, corsaro, "could not open %s output file",
1023  PLUGIN(corsaro)->name);
1024  return -1;
1025  }
1026 
1027  if(STATE(corsaro)->first_interval == 0)
1028  {
1029  /* -1 to simulate the end of the 'previous' interval */
1030  STATE(corsaro)->first_interval = int_start->time-1;
1031  }
1032 
1033  return 0;
1034 }
1035 
1038 {
1039  int this_interval = int_end->time-STATE(corsaro)->first_interval;
1040 
1041  khiter_t i;
1042  attack_vector_t *vector;
1043  attack_vector_t **attack_arr = NULL;
1044  int attack_arr_cnt = 0;
1045 
1046  uint8_t gbuf[12];
1047  uint8_t cntbuf[4];
1048 
1049  if(this_interval < CORSARO_DOS_INTERVAL)
1050  {
1051  /* we haven't run for long enough to dump */
1052  return 0;
1053  }
1054  else
1055  {
1056  /* we either have hit exactly the right amount of time,
1057  or we have gone for too long, dump now and reset the counter */
1058  STATE(corsaro)->first_interval = int_end->time;
1059  /* fall through and continue to dump */
1060  }
1061 
1062  /* this is an interval we care about */
1063 
1064  /* malloc an array big enough to hold the entire hash even though we wont
1065  need it to be that big */
1066  if((attack_arr =
1067  malloc(sizeof(attack_vector_t *)*
1068  kh_size(STATE(corsaro)->attack_hash))) == NULL)
1069  {
1070  corsaro_log(__func__, corsaro,
1071  "could not malloc array for attack vectors");
1072  return -1;
1073  }
1074 
1075  /* classify the flows and dump the attack ones */
1076 
1077  for(i = kh_begin(STATE(corsaro)->attack_hash);
1078  i != kh_end(STATE(corsaro)->attack_hash); ++i)
1079  {
1080  if(kh_exist(STATE(corsaro)->attack_hash, i))
1081  {
1082  vector = kh_key(STATE(corsaro)->attack_hash, i);
1083 
1084  if(attack_vector_is_expired(vector, int_end->time) != 0)
1085  {
1086  kh_del(av, STATE(corsaro)->attack_hash, i);
1087  attack_vector_free(vector);
1088  vector = NULL;
1089  }
1090  else if(attack_vector_is_attack(corsaro, vector, int_end->time) != 0)
1091  {
1092  /* this is an attack */
1093  /* add it to the attack array so we can know how many
1094  before we dump it */
1095  attack_arr[attack_arr_cnt] = vector;
1096  attack_arr_cnt++;
1097  }
1098  else
1099  {
1100  attack_vector_reset(vector);
1101  }
1102  }
1103  }
1104 
1105  corsaro_io_write_interval_start(corsaro, STATE(corsaro)->outfile,
1106  &corsaro->interval_start);
1107  if(corsaro->global_file != NULL)
1108  {
1109  corsaro_io_write_plugin_start(corsaro, corsaro->global_file,
1110  PLUGIN(corsaro));
1111  }
1112  if(CORSARO_FILE_MODE(STATE(corsaro)->outfile) == CORSARO_FILE_MODE_ASCII)
1113  {
1114  if(corsaro->global_file != NULL)
1115  {
1116  /* global stats */
1117  /* dump the number of mismatched packets and vectors */
1118  corsaro_file_printf(corsaro, corsaro->global_file,
1119  "mismatch: %"PRIu32"\n"
1120  "attack_vectors: %"PRIu32"\n"
1121  "non-attack_vectors: %"PRIu32"\n",
1122  STATE(corsaro)->number_mismatched_packets,
1123  attack_arr_cnt,
1124  kh_size(STATE(corsaro)->attack_hash)
1125  -attack_arr_cnt);
1126  }
1127 
1128  /* dump the number of vectors */
1129  corsaro_file_printf(corsaro, STATE(corsaro)->outfile, "%"PRIu32"\n",
1130  attack_arr_cnt);
1131  /* dump the vectors */
1132  for(i = 0; i < attack_arr_cnt; i++)
1133  {
1134  if(ascii_dump(corsaro, attack_arr[i]) != 0)
1135  {
1136  corsaro_log(__func__, corsaro, "could not dump hash");
1137  return -1;
1138  }
1139  /* reset the interval stats */
1140  attack_vector_reset(attack_arr[i]);
1141  }
1142  }
1143  else if(CORSARO_FILE_MODE(STATE(corsaro)->outfile) == CORSARO_FILE_MODE_BINARY)
1144  {
1145  if(corsaro->global_file != NULL)
1146  {
1147  /* global stats */
1148  bytes_htonl(&gbuf[0], STATE(corsaro)->number_mismatched_packets);
1149  bytes_htonl(&gbuf[4], attack_arr_cnt);
1150  bytes_htonl(&gbuf[8],
1151  kh_size(STATE(corsaro)->attack_hash)-attack_arr_cnt);
1152  if(corsaro_file_write(corsaro, corsaro->global_file,
1153  &gbuf[0], 12) != 12)
1154  {
1155  corsaro_log(__func__, corsaro,
1156  "could not dump global stats to file");
1157  return -1;
1158  }
1159  }
1160 
1161  /* dump the number of vectors */
1162  bytes_htonl(&cntbuf[0], attack_arr_cnt);
1163  if(corsaro_file_write(corsaro, STATE(corsaro)->outfile,
1164  &cntbuf[0], 4) != 4)
1165  {
1166  corsaro_log(__func__, corsaro,
1167  "could not dump vector count to file");
1168  return -1;
1169  }
1170  /* dump the vectors */
1171  for(i = 0; i < attack_arr_cnt; i++)
1172  {
1173  if(binary_dump(corsaro, attack_arr[i]) != 0)
1174  {
1175  corsaro_log(__func__, corsaro, "could not dump hash");
1176  return -1;
1177  }
1178  attack_vector_reset(attack_arr[i]);
1179  }
1180  }
1181  else
1182  {
1183  corsaro_log(__func__, corsaro, "invalid mode");
1184  return -1;
1185  }
1186  if(corsaro->global_file != NULL)
1187  {
1188  corsaro_io_write_plugin_end(corsaro, corsaro->global_file,
1189  PLUGIN(corsaro));
1190  }
1191  corsaro_io_write_interval_end(corsaro, STATE(corsaro)->outfile, int_end);
1192 
1193  STATE(corsaro)->number_mismatched_packets = 0;
1194 
1195  free(attack_arr);
1196 
1197  /* if we are rotating, now is when we should do it */
1198  if(corsaro_is_rotate_interval(corsaro))
1199  {
1200  /* close the current file */
1201  if(STATE(corsaro)->outfile != NULL)
1202  {
1203  corsaro_file_close(corsaro, STATE(corsaro)->outfile);
1204  STATE(corsaro)->outfile = NULL;
1205  }
1206  }
1207 
1208  return 0;
1209 }
1210 
1214 {
1215  libtrace_packet_t *ltpacket = LT_PKT(packet);
1216  void *temp = NULL;
1217  uint8_t proto;
1218  uint32_t remaining;
1219 
1220  libtrace_ip_t *ip_hdr = NULL;
1221  libtrace_icmp_t *icmp_hdr = NULL;
1222  libtrace_ip_t *inner_ip_hdr = NULL;
1223 
1224  /* borrowed from libtrace's protocols.h (used by trace_get_*_port) */
1225  struct ports_t {
1226  uint16_t src;
1227  uint16_t dst;
1228  };
1229 
1230  uint16_t attacker_port = 0;
1231  uint16_t target_port = 0;
1232 
1233  attack_vector_t findme;
1234 
1235  int khret;
1236  khiter_t khiter;
1237  attack_vector_t *vector = NULL;
1238  uint8_t *pkt_buf = NULL;
1239  libtrace_linktype_t linktype;
1240 
1241  struct timeval tv;
1242 
1244  {
1245  /* not a backscatter packet */
1246  return 0;
1247  }
1248 
1249  /* backscatter packet, lets find the flow */
1250  /* check for ipv4 */
1251  /* 10/19/12 ak replaced much more verbose code to get header with this */
1252  if((ip_hdr = trace_get_ip(ltpacket)) == NULL)
1253  {
1254  /* non-ipv4 packet */
1255  return 0;
1256  }
1257 
1258  /* get the transport header */
1259  if((temp = trace_get_transport(ltpacket, &proto, &remaining)) == NULL)
1260  {
1261  /* not enough payload */
1262  return 0;
1263  }
1264 
1265  findme.target_ip = 0;
1266 
1267  if(ip_hdr->ip_p == TRACE_IPPROTO_ICMP && remaining >= 2)
1268  {
1269  icmp_hdr = (libtrace_icmp_t *)temp;
1270 
1271  if((icmp_hdr->type == 3 ||
1272  icmp_hdr->type == 4 ||
1273  icmp_hdr->type == 5 ||
1274  icmp_hdr->type == 11 ||
1275  icmp_hdr->type == 12) &&
1276  ((temp = trace_get_payload_from_icmp(icmp_hdr, &remaining)) != NULL
1277  && remaining >= 20 && (inner_ip_hdr = (libtrace_ip_t *)temp) &&
1278  inner_ip_hdr->ip_v == 4))
1279  {
1280  /* icmp error message */
1281  if(inner_ip_hdr->ip_src.s_addr != ip_hdr->ip_dst.s_addr)
1282  {
1283  STATE(corsaro)->number_mismatched_packets++;
1284  }
1285 
1286  findme.target_ip = ntohl(inner_ip_hdr->ip_dst.s_addr);
1287 
1288  /* just extract the first four bytes of payload as ports */
1289  if((temp = trace_get_payload_from_ip(inner_ip_hdr, NULL,
1290  &remaining)) != NULL
1291  && remaining >= 4)
1292  {
1293  attacker_port = ntohs(((struct ports_t *)temp)->src);
1294  target_port = ntohs(((struct ports_t *)temp)->dst);
1295  }
1296  }
1297  else
1298  {
1299  findme.target_ip = ntohl(ip_hdr->ip_src.s_addr);
1300  attacker_port = ntohs(icmp_hdr->code);
1301  target_port = ntohs(icmp_hdr->type);
1302  }
1303  }
1304  else if((ip_hdr->ip_p == TRACE_IPPROTO_TCP ||
1305  ip_hdr->ip_p == TRACE_IPPROTO_UDP) &&
1306  remaining >= 4)
1307  {
1308  findme.target_ip = ntohl(ip_hdr->ip_src.s_addr);
1309  attacker_port = trace_get_destination_port(ltpacket);
1310  target_port = trace_get_source_port(ltpacket);
1311  }
1312 
1313  if(findme.target_ip == 0)
1314  {
1315  /* the packet is none of ICMP, TCP or UDP */
1316  return 0;
1317  }
1318 
1319  tv = trace_get_timeval(ltpacket);
1320 
1321  /* is this vector in the hash? */
1322  assert(STATE(corsaro)->attack_hash != NULL);
1323  if((khiter = kh_get(av, STATE(corsaro)->attack_hash, &findme))
1324  != kh_end(STATE(corsaro)->attack_hash))
1325  {
1326  /* the vector is in the hash */
1327  vector = kh_key(STATE(corsaro)->attack_hash, khiter);
1328 
1329  if(attack_vector_is_expired(vector, tv.tv_sec) != 0)
1330  {
1331  kh_del(av, STATE(corsaro)->attack_hash, khiter);
1332  attack_vector_free(vector);
1333  vector = NULL;
1334  }
1335  }
1336 
1337  if(vector == NULL)
1338  {
1339  /* create a new vector and fill it */
1340  if((vector = attack_vector_init(corsaro)) == NULL)
1341  {
1342  corsaro_log(__func__, corsaro, "failed to create new attack vector");
1343  return -1;
1344  }
1345 
1346  /* i think this may be buggy. do it the safe way for now
1347  vector->initial_packet = corsaro_mincopy_packet(packet);
1348  */
1349  vector->initial_packet_len = trace_get_capture_length(ltpacket);
1350 
1351  if((vector->initial_packet = malloc(vector->initial_packet_len)) == NULL)
1352  {
1353  corsaro_log(__func__, corsaro, "could not malloc initial packet");
1354  return -1;
1355  }
1356 
1357  if((pkt_buf = trace_get_packet_buffer(ltpacket,
1358  &linktype, NULL)) == NULL)
1359  {
1360  corsaro_log(__func__, corsaro, "could not get packet buffer");
1361  return -1;
1362  }
1363 
1364  memcpy(vector->initial_packet, pkt_buf, vector->initial_packet_len);
1365 
1366  vector->attacker_ip = ntohl(ip_hdr->ip_dst.s_addr);
1367  vector->responder_ip = ntohl(ip_hdr->ip_src.s_addr);
1368  vector->target_ip = findme.target_ip;
1369 
1370  vector->start_time = tv;
1371 
1372  vector->ppm_window.window_start = tv.tv_sec;
1373 
1374  /* add to the hash */
1375  khiter = kh_put(av, STATE(corsaro)->attack_hash, vector, &khret);
1376  }
1377 
1378  assert(vector != NULL);
1379 
1380  vector->packet_cnt++;
1381  vector->interval_packet_cnt++;
1382  vector->byte_cnt += ntohs(ip_hdr->ip_len);
1383  vector->interval_byte_cnt += ntohs(ip_hdr->ip_len);
1384 
1385  vector->latest_time = tv;
1386  /* update the pps window */
1387  attack_vector_update_ppm_window(vector, tv);
1388 
1389  /* add the attacker ip to the hash */
1390  kh_put(32xx, vector->attack_ip_hash, ntohl(ip_hdr->ip_dst.s_addr), &khret);
1391 
1392  /* add the ports to the hashes */
1393  kh_put(32xx, vector->attack_port_hash, attacker_port, &khret);
1394  kh_put(32xx, vector->target_port_hash, target_port, &khret);
1395 
1396  return 0;
1397 }
1398 
1399 /* ==== External Output Convenience Functions ==== */
1400 
1403  corsaro_dos_attack_vector_in_t *attack_vector,
1404  libtrace_packet_t *packet)
1405 {
1406  assert(packet != NULL);
1407 
1408  trace_construct_packet(packet, TRACE_TYPE_ETH,
1409  attack_vector->initial_packet,
1410  attack_vector->initial_packet_len);
1411 }
1412 
1415  corsaro_file_t *file,
1417 {
1418  assert(corsaro != NULL);
1419  assert(file != NULL);
1420  assert(header != NULL);
1421 
1422  return corsaro_file_printf(corsaro, file,
1423  "mismatch: %"PRIu32"\n"
1424  "attack_vectors: %"PRIu32"\n"
1425  "non-attack_vectors: %"PRIu32"\n",
1426  header->mismatched_pkt_cnt,
1427  header->attack_vector_cnt,
1428  header->non_attack_vector_cnt);
1429 
1430 }
1431 
1434 {
1435  assert(header != NULL);
1436 
1437  fprintf(stdout, "mismatch: %"PRIu32"\n"
1438  "attack_vectors: %"PRIu32"\n"
1439  "non-attack_vectors: %"PRIu32"\n",
1440  header->mismatched_pkt_cnt,
1441  header->attack_vector_cnt,
1442  header->non_attack_vector_cnt);
1443 }
1444 
1450  corsaro_file_t *file,
1452 {
1453  uint32_t tmp;
1454  char t_ip[16];
1455 
1456  assert(corsaro != NULL);
1457  assert(file != NULL);
1458  assert(av != NULL);
1459 
1460  tmp = htonl(av->target_ip);
1461  inet_ntop(AF_INET,&tmp, &t_ip[0], 16);
1462 
1463  return corsaro_file_printf(corsaro, file,
1464  "%s"
1465  ",%"PRIu32
1466  ",%"PRIu32
1467  ",%"PRIu32
1468  ",%"PRIu32
1469  ",%"PRIu64
1470  ",%"PRIu32
1471  ",%"PRIu64
1472  ",%"PRIu32
1473  ",%"PRIu64
1474  ",%"PRIu32".%06"PRIu32
1475  ",%"PRIu32".%06"PRIu32
1476  "\n",
1477  t_ip,
1478  av->attacker_ip_cnt,
1480  av->attack_port_cnt,
1481  av->target_port_cnt,
1482  av->packet_cnt,
1483  av->interval_packet_cnt,
1484  av->byte_cnt,
1485  av->interval_byte_cnt,
1486  av->max_ppm,
1487  av->start_time_sec,
1488  av->start_time_usec,
1489  av->latest_time_sec,
1490  av->latest_time_usec);
1491 
1492 }
1493 
1496 {
1497  uint32_t tmp;
1498  char t_ip[16];
1499  libtrace_packet_t *packet;
1500 
1501  assert(av != NULL);
1502 
1503  tmp = htonl(av->target_ip);
1504  inet_ntop(AF_INET,&tmp, &t_ip[0], 16);
1505 
1506  fprintf(stdout,
1507  "%s"
1508  ",%"PRIu32
1509  ",%"PRIu32
1510  ",%"PRIu32
1511  ",%"PRIu32
1512  ",%"PRIu64
1513  ",%"PRIu32
1514  ",%"PRIu64
1515  ",%"PRIu32
1516  ",%"PRIu64
1517  ",%"PRIu32".%06"PRIu32
1518  ",%"PRIu32".%06"PRIu32
1519  "\n",
1520  t_ip,
1521  av->attacker_ip_cnt,
1523  av->attack_port_cnt,
1524  av->target_port_cnt,
1525  av->packet_cnt,
1526  av->interval_packet_cnt,
1527  av->byte_cnt,
1528  av->interval_byte_cnt,
1529  av->max_ppm,
1530  av->start_time_sec,
1531  av->start_time_usec,
1532  av->latest_time_sec,
1533  av->latest_time_usec);
1534 
1535  /* this may get slow if you are dumping *lots* of dos records */
1536  if ((packet = trace_create_packet()) == NULL) {
1537  corsaro_log_file(__func__, NULL, "error creating libtrace packet");
1538  return;
1539  }
1540 
1542 
1543 #if HAVE_LIBPACKETDUMP
1544  fprintf(stdout, "START PACKET\n");
1545  trace_dump_packet(packet);
1546  fprintf(stdout, "\nEND PACKET\n");
1547 #else
1548  fprintf(stdout, "corsaro not built with libpacketdump support\n"
1549  "not dumping initial packet\n");
1550 #endif
1551 }
1552 
1555  corsaro_file_t *file,
1556  corsaro_dos_header_t *header)
1557 {
1558  assert(corsaro != NULL);
1559  assert(file != NULL);
1560  assert(header != NULL);
1561 
1562  return corsaro_file_printf(corsaro, file,
1563  "%"PRIu32"\n",
1564  header->attack_vector_cnt);
1565 
1566 }
1567 
1570 {
1571  assert(header != NULL);
1572 
1573  fprintf(stdout, "%"PRIu32"\n", header->attack_vector_cnt);
1574 
1575 }
1576 
1579  corsaro_file_t *file,
1580  corsaro_in_record_type_t record_type,
1582 {
1583  switch(record_type)
1584  {
1586  return corsaro_dos_global_header_fprint(corsaro, file,
1587  (corsaro_dos_global_header_t *)record->buffer);
1588  break;
1589 
1591  return corsaro_dos_header_fprint(corsaro, file,
1592  (corsaro_dos_header_t *)record->buffer);
1593  break;
1594 
1596  return corsaro_dos_attack_vector_fprint(corsaro, file,
1598  break;
1599 
1600  default:
1601  corsaro_log(__func__, corsaro, "record_type %d not a dos record",
1602  record_type);
1603  return -1;
1604  break;
1605  }
1606 
1607  return -1;
1608 }
1609 
1613 {
1614  switch(record_type)
1615  {
1618  (corsaro_dos_global_header_t *)record->buffer);
1619  break;
1620 
1623  (corsaro_dos_header_t *)record->buffer);
1624  break;
1625 
1629  break;
1630 
1631  default:
1632  corsaro_log_file(__func__, NULL,
1633  "record_type %d not a dos record",
1634  record_type);
1635  return -1;
1636  break;
1637  }
1638 
1639  return 0;
1640 }
Structure representing the start or end of an interval.
Definition: corsaro_int.h:156
uint32_t start_time_usec
The time of the initial packet (usec)
Definition: corsaro_dos.h:116
An opaque structure defining an corsaro input file.
Definition: corsaro_file.h:86
int corsaro_dos_probe_filename(const char *fname)
Implements the probe_filename function of the plugin API.
Definition: corsaro_dos.c:806
Header file dealing with the corsaro plugin manager.
uint32_t mismatched_pkt_cnt
The number of packets which had mismatched IP addresses in the header.
Definition: corsaro_dos.h:50
void bytes_htonl(uint8_t *bytes, uint32_t u32)
Convert a host ordered long to a network ordered byte array.
Definition: utils.c:57
static int read_attack_vector(corsaro_in_t *corsaro, corsaro_in_record_type_t *record_type, corsaro_in_record_t *record)
Read an attack vector record.
Definition: corsaro_dos.c:723
int corsaro_dos_close_output(corsaro_t *corsaro)
Implements the close_output function of the plugin API.
Definition: corsaro_dos.c:910
Header file dealing with the corsaro logging sub-system.
off_t corsaro_dos_header_fprint(corsaro_t *corsaro, corsaro_file_t *file, corsaro_dos_header_t *header)
Print a header record to stdout in ASCII format.
Definition: corsaro_dos.c:1554
An opaque structure defining an corsaro output file.
Definition: corsaro_file.h:60
int corsaro_dos_close_input(corsaro_in_t *corsaro)
Implements the close_input function of the plugin API.
Definition: corsaro_dos.c:898
static attack_vector_t * attack_vector_init(corsaro_t *corsaro)
Create an attack vector object.
Definition: corsaro_dos.c:209
off_t corsaro_file_printf(struct corsaro *corsaro, corsaro_file_t *file, const char *format,...)
Print a string to an corsaro file.
Definition: corsaro_file.c:214
static corsaro_plugin_t corsaro_dos_plugin
Common plugin information across all instances.
Definition: corsaro_dos.c:75
uint64_t packet_cnt
The number of packets that comprise this vector.
Definition: corsaro_dos.h:98
A reusable opaque structure for corsaro to read an input record into.
Definition: corsaro_int.h:350
#define CORSARO_DOS_INTERVAL
The interval that this plugin would like to dump at.
Definition: corsaro_dos.c:94
#define CORSARO_DOS_ATTACK_VECTOR_MIN_DURATION
The minimum number of seconds before a vector can be an attack.
Definition: corsaro_dos.c:103
corsaro_plugin_manager_t * plugin_manager
A pointer to the corsaro plugin manager state.
Definition: corsaro_int.h:336
int corsaro_dos_end_interval(corsaro_t *corsaro, corsaro_interval_t *int_end)
Implements the end_interval function of the plugin API.
Definition: corsaro_dos.c:1037
off_t corsaro_dos_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.
Definition: corsaro_dos.c:934
ASCII IO mode.
Definition: corsaro.h:153
#define LT_PKT(corsaro_packet)
Convenience macro to get to the libtrace packet inside an corsaro packet.
Definition: corsaro_int.h:227
Binary IO mode.
Definition: corsaro.h:155
void corsaro_dos_attack_vector_get_packet(corsaro_dos_attack_vector_in_t *attack_vector, libtrace_packet_t *packet)
Extract the initial packet from an attack vector record.
Definition: corsaro_dos.c:1402
uint32_t attack_vector_cnt
The number of attack vectors in this interval.
Definition: corsaro_dos.h:53
#define CORSARO_FILE_MODE(file)
Accessor macro for getting the mode of a file.
Definition: corsaro_file.h:113
int corsaro_dos_probe_magic(corsaro_in_t *corsaro, corsaro_file_in_t *file)
Implements the probe_magic function of the plugin API.
Definition: corsaro_dos.c:827
int corsaro_dos_record_print(corsaro_in_record_type_t record_type, corsaro_in_record_t *record)
Print any DoS record to a file in ASCII format.
Definition: corsaro_dos.c:1611
void corsaro_file_close(struct corsaro *corsaro, corsaro_file_t *file)
Closes an corsaro output file and frees the writer structure.
Definition: corsaro_file.c:230
#define CORSARO_DOS_MAGIC
The magic number for this plugin - "EDOS".
Definition: corsaro_dos.c:61
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.
off_t corsaro_io_read_bytes_offset(corsaro_in_t *corsaro, corsaro_in_record_t *record, off_t offset, off_t len)
Read the given number of bytes into the record buffer at the given offset.
Definition: corsaro_io.c:1326
#define CORSARO_DOS_PPM_WINDOW_PRECISION
The amount to slide the window by in seconds.
Definition: corsaro_dos.c:115
off_t corsaro_dos_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.
Definition: corsaro_dos.c:984
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
static void attack_vector_update_ppm(ppm_window_t *ppm_window)
Update the max ppm value given the current window values.
Definition: corsaro_dos.c:347
#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
corsaro_file_t * corsaro_io_prepare_file(corsaro_t *corsaro, const char *plugin_name, corsaro_interval_t *interval)
Uses the current settings to open an corsaro file for the given plugin.
Definition: corsaro_io.c:688
off_t corsaro_io_read_interval_end(corsaro_in_t *corsaro, corsaro_file_in_t *file, corsaro_in_record_type_t *record_type, corsaro_in_record_t *record)
Read the appropriate interval trailers from the file.
Definition: corsaro_io.c:1260
void corsaro_plugin_register_state(corsaro_plugin_manager_t *manager, corsaro_plugin_t *plugin, void *state)
Register the state for a plugin.
int corsaro_dos_init_output(corsaro_t *corsaro)
Implements the init_output function of the plugin API.
Definition: corsaro_dos.c:836
int corsaro_plugin_probe_filename(const char *fname, corsaro_plugin_t *plugin)
Check a filename to see if it contains a plugin's name.
off_t corsaro_io_write_interval_end(corsaro_t *corsaro, corsaro_file_t *file, corsaro_interval_t *int_end)
Write the appropriate interval trailers to the file.
Definition: corsaro_io.c:872
struct ppm_window ppm_window_t
Initialize the hash types needed to hold maps in vectors.
The end of an interval.
Definition: corsaro.h:115
uint32_t initial_packet_len
The length of the initial packet (bytes)
Definition: corsaro_dos.h:125
static void attack_vector_free(attack_vector_t *av)
Free the memory allocated to an attack vector object.
Definition: corsaro_dos.c:234
#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
Header file dealing with the low-level file IO.
static corsaro_in_record_t * record
A pointer to a corsaro record.
Definition: corsaro_main.c:76
void corsaro_log_in(const char *func, corsaro_in_t *corsaro, const char *format,...)
Write a formatted string to the logfile associated with an corsaro input object.
Definition: corsaro_log.c:121
static void attack_vector_update_ppm_window(attack_vector_t *vector, struct timeval tv)
Update the packet rate window.
Definition: corsaro_dos.c:440
off_t corsaro_dos_attack_vector_fprint(corsaro_t *corsaro, corsaro_file_t *file, corsaro_dos_attack_vector_in_t *av)
Print an attack vector record to stdout in ASCII format.
Definition: corsaro_dos.c:1449
KHASH_INIT(av, attack_vector_t *, char, 0, attack_vector_hash_func, attack_vector_hash_equal)
Initialize the hash functions and datatypes.
off_t corsaro_io_read_interval_start(corsaro_in_t *corsaro, corsaro_file_in_t *file, corsaro_in_record_type_t *record_type, corsaro_in_record_t *record)
Read the appropriate interval headers from the file.
Definition: corsaro_io.c:1232
uint32_t latest_time_sec
The time of the last packet (seconds)
Definition: corsaro_dos.h:119
#define PLUGIN_NAME
The name of this plugin.
Definition: corsaro_dos.c:64
int corsaro_is_rotate_interval(corsaro_t *corsaro)
Convenience function to determine if the output files should be rotated.
Definition: corsaro.c:1041
off_t corsaro_io_read_bytes(corsaro_in_t *corsaro, corsaro_in_record_t *record, off_t len)
Read the given number of bytes into the record.
Definition: corsaro_io.c:1317
struct attack_vector attack_vector_t
A record for a potential attack vector.
uint32_t interval_attacker_ip_cnt
Number of IP addresses the alleged attack has originated from in the current interval.
Definition: corsaro_dos.h:89
off_t corsaro_dos_record_fprint(corsaro_t *corsaro, corsaro_file_t *file, corsaro_in_record_type_t record_type, corsaro_in_record_t *record)
Print any DoS record to stdout in ASCII format.
Definition: corsaro_dos.c:1578
corsaro_packet_state_t state
The corsaro state associated with this packet.
Definition: corsaro_int.h:214
#define CORSARO_DOS_ATTACK_VECTOR_MIN_PACKETS
The minimum number of packets before a vector can be an attack.
Definition: corsaro_dos.c:100
uint8_t flags
Features of the packet that have been identified by earlier plugins.
Definition: corsaro_int.h:197
#define CORSARO_DOS_ATTACK_VECTOR_BYTECNT
The length (in bytes) of an attack vector record.
Definition: corsaro_dos.c:109
uint8_t * buffer
The buffer to read the record into.
Definition: corsaro_int.h:356
corsaro_interval_t interval_start
State for the current interval.
Definition: corsaro_int.h:292
off_t corsaro_io_write_plugin_end(corsaro_t *corsaro, corsaro_file_t *file, corsaro_plugin_t *plugin)
Write the appropriate plugin trailer to the file.
Definition: corsaro_io.c:905
Structure to hold a dos attack vector.
Definition: corsaro_dos.h:79
The packet is classified as backscatter.
Definition: corsaro_int.h:204
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
uint32_t time
The time this interval started/ended.
Definition: corsaro_int.h:165
off_t corsaro_file_write(struct corsaro *corsaro, corsaro_file_t *file, const void *buffer, off_t len)
Writes the contents of a buffer using an corsaro output file.
Definition: corsaro_file.c:142
#define CORSARO_DOS_PPS_BUCKET_CNT
The number of buckets.
Definition: corsaro_dos.c:118
Corsaro input state.
Definition: corsaro_int.h:323
#define STATE(corsaro)
Extends the generic plugin state convenience macro in corsaro_plugin.h.
Definition: corsaro_dos.c:319
off_t corsaro_dos_global_header_fprint(corsaro_t *corsaro, corsaro_file_t *file, corsaro_dos_global_header_t *header)
Print a global header record to stdout in ASCII format.
Definition: corsaro_dos.c:1414
void corsaro_dos_global_header_print(corsaro_dos_global_header_t *header)
Print a global header record to a file in ASCII format.
Definition: corsaro_dos.c:1433
The start of an interval.
Definition: corsaro.h:112
int corsaro_dos_start_interval(corsaro_t *corsaro, corsaro_interval_t *int_start)
Implements the start_interval function of the plugin API.
Definition: corsaro_dos.c:1014
static int validate_attack_vector(corsaro_dos_attack_vector_in_t *av)
Check an attack vector record is valid.
Definition: corsaro_dos.c:692
#define CORSARO_DOS_VECTOR_TIMEOUT
The length of time after which an inactive attack vector is expired.
Definition: corsaro_dos.c:97
#define CORSARO_DOS_ATTACK_VECTOR_MIN_PPM
The minimum packet rate before a vector can be an attack.
Definition: corsaro_dos.c:106
The corsaro_dos attack vector record.
Definition: corsaro.h:145
The corsaro_dos global header record.
Definition: corsaro.h:139
static int attack_vector_is_attack(corsaro_t *corsaro, attack_vector_t *vector, uint32_t time)
Determine whether a vector is indeed an attack vector.
Definition: corsaro_dos.c:482
uint32_t non_attack_vector_cnt
The number of potential attack vectors which were not classified as being part of an attack...
Definition: corsaro_dos.h:58
The corsaro_dos header record.
Definition: corsaro.h:142
static int binary_dump(corsaro_t *corsaro, attack_vector_t *vector)
Dump the given vector to the plugin output file in binary.
Definition: corsaro_dos.c:570
uint32_t interval_packet_cnt
The number of packets added to this vector in the current interval.
Definition: corsaro_dos.h:101
uint8_t * initial_packet
A copy of the packet that caused the vector to be created.
Definition: corsaro_dos.h:135
static int attack_vector_is_expired(attack_vector_t *vector, uint32_t time)
Check if a vector has had a packet added to it recently.
Definition: corsaro_dos.c:334
void corsaro_dos_header_print(corsaro_dos_header_t *header)
Print a header record to a file in ASCII format.
Definition: corsaro_dos.c:1569
static int read_header(corsaro_in_t *corsaro, corsaro_in_record_type_t *record_type, corsaro_in_record_t *record)
Read a dos header.
Definition: corsaro_dos.c:659
Header file dealing with the corsaro file IO.
The null type used for wildcard matching.
Definition: corsaro.h:100
#define attack_vector_hash_equal(a, b)
Compare two attack vectors for equality.
Definition: corsaro_dos.c:278
uint32_t latest_time_usec
The time of the last packet (usec)
Definition: corsaro_dos.h:122
uint32_t attack_vector_cnt
The number of attack vectors in this interval.
Definition: corsaro_dos.h:68
uint64_t byte_cnt
The number of bytes that comprise this vector.
Definition: corsaro_dos.h:104
void bytes_htonll(uint8_t *bytes, uint64_t u64)
Convert a host ordered long-long (64 bit) to a network ordered byte array.
Definition: utils.c:64
Structure to hold the dos header details for an interval.
Definition: corsaro_dos.h:65
uint32_t attacker_ip_cnt
Number of IP addresses the alleged attack has originated from.
Definition: corsaro_dos.h:85
uint32_t attack_port_cnt
Number of ports that alleged attack packets have originated from.
Definition: corsaro_dos.h:92
uint32_t target_port_cnt
Number of ports that alleged attack packets were directed to.
Definition: corsaro_dos.h:95
Corsaro output state.
Definition: corsaro_int.h:230
corsaro_file_t * global_file
The corsaro output file to write global output to.
Definition: corsaro_int.h:257
int timeval_subtract(struct timeval *result, const struct timeval *x, const struct timeval *y)
Find the delta between two timevals.
Definition: utils.c:88
static int ascii_dump(corsaro_t *corsaro, attack_vector_t *vector)
Dump the given vector to the plugin output file in ASCII.
Definition: corsaro_dos.c:525
void corsaro_dos_attack_vector_print(corsaro_dos_attack_vector_in_t *av)
Print an attack vector record to a file in ASCII format.
Definition: corsaro_dos.c:1495
int corsaro_dos_process_packet(corsaro_t *corsaro, corsaro_packet_t *packet)
Implements the process_packet function of the plugin API.
Definition: corsaro_dos.c:1212
static void attack_vector_reset(attack_vector_t *av)
Reset the per-interval counters in an attack vector.
Definition: corsaro_dos.c:268
static khint32_t attack_vector_hash_func(attack_vector_t *av)
Hash an attack vector.
Definition: corsaro_dos.c:286
uint32_t start_time_sec
The time of the initial packet (seconds)
Definition: corsaro_dos.h:113
off_t corsaro_io_write_interval_start(corsaro_t *corsaro, corsaro_file_t *file, corsaro_interval_t *int_start)
Write the appropriate interval headers to the file.
Definition: corsaro_io.c:856
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
uint32_t target_ip
The IP address of the alleged target of the attack.
Definition: corsaro_dos.h:82
#define PLUGIN(corsaro)
Extends the generic plugin plugin convenience macro in corsaro_plugin.h.
Definition: corsaro_dos.c:326
off_t corsaro_io_write_plugin_start(corsaro_t *corsaro, corsaro_file_t *file, corsaro_plugin_t *plugin)
Write the appropriate plugin header to the file.
Definition: corsaro_io.c:889
corsaro_plugin_t * corsaro_dos_alloc(corsaro_t *corsaro)
Implements the alloc function of the plugin API.
Definition: corsaro_dos.c:800
uint64_t max_ppm
The maximum packet rate observed thus far.
Definition: corsaro_dos.h:110
static int validate_global_header(corsaro_dos_global_header_t *g)
Check that a global file header record is valid.
Definition: corsaro_dos.c:788
enum corsaro_in_record_type corsaro_in_record_type_t
Corsaro input record types.
#define STATE_IN(corsaro)
Extends the generic plugin state convenience macro in corsaro_plugin.h.
Definition: corsaro_dos.c:322
An corsaro packet processing plugin.
uint32_t interval_byte_cnt
The number of bytes added to this vector in the current interval.
Definition: corsaro_dos.h:107
int corsaro_dos_init_input(corsaro_in_t *corsaro)
Implements the init_input function of the plugin API.
Definition: corsaro_dos.c:870
#define ntohll(x)
Byte-swap a 64-bit integer.
Definition: utils.h:66
#define PLUGIN_NAME_DEPRECATED
The old name of this plugin.
Definition: corsaro_dos.c:72
corsaro_file_in_t * file
The corsaro input file to read data from.
Definition: corsaro_int.h:329
Header file dealing with the internal corsaro functions.
Structure to hold the dos record in the global output file.
Definition: corsaro_dos.h:43