29 #include <arpa/inet.h>
56 #ifdef CORSARO_SLASH_EIGHT
58 #define CORSARO_FLOWTUPLE_MAGIC 0x53495854
61 #define CORSARO_FLOWTUPLE_MAGIC 0x53495855
65 #define PLUGIN_NAME "flowtuple"
78 "flowtuple_backscatter",
92 struct corsaro_flowtuple_state_t {
100 struct corsaro_flowtuple_in_state_t {
110 #define STATE(corsaro) \
111 (CORSARO_PLUGIN_STATE(corsaro, flowtuple, CORSARO_PLUGIN_ID_FLOWTUPLE))
113 #define STATE_IN(corsaro) \
114 (CORSARO_PLUGIN_STATE(corsaro, flowtuple_in, CORSARO_PLUGIN_ID_FLOWTUPLE))
116 #define PLUGIN(corsaro) \
117 (CORSARO_PLUGIN_PLUGIN(corsaro, CORSARO_PLUGIN_ID_FLOWTUPLE))
133 libtrace_tcp_t *tcp_hdr = NULL;
134 libtrace_icmp_t *icmp_hdr = NULL;
137 if((temp = trace_get_layer3(packet, ðertype, &remaining)) == NULL ||
138 ethertype != TRACE_ETHERTYPE_IP)
141 corsaro_log(__func__, corsaro,
"non-ip packet found (ethertype: %x)",
147 if((temp = trace_get_transport(packet, &proto, &remaining)) == NULL)
154 if(proto == TRACE_IPPROTO_TCP && remaining >= 4)
156 tcp_hdr = (libtrace_tcp_t *)temp;
159 if((tcp_hdr->syn && tcp_hdr->ack) || tcp_hdr->rst)
169 else if(proto == TRACE_IPPROTO_ICMP && remaining >= 2)
171 icmp_hdr = (libtrace_icmp_t *)temp;
172 if(icmp_hdr->type == 0 ||
173 icmp_hdr->type == 3 ||
174 icmp_hdr->type == 4 ||
175 icmp_hdr->type == 5 ||
176 icmp_hdr->type == 11 ||
177 icmp_hdr->type == 12 ||
178 icmp_hdr->type == 14 ||
179 icmp_hdr->type == 16 ||
180 icmp_hdr->type == 18)
205 corsaro_log(__func__, corsaro,
"could not malloc array for sorted keys");
210 if(kh_size(hash) == 0)
216 for(i = kh_begin(hash); i != kh_end(hash); ++i)
218 if(kh_exist(hash, i))
220 *ptr = kh_key(hash, i);
225 ks_heapsort(sixt, kh_size(hash), *sorted);
232 kh_sixt_t *h =
STATE(corsaro)->st_hash[dist];
240 uint8_t *hptr = &hbuf[0];
247 bytes_htons(hptr, dist);
250 bytes_htonl(hptr, kh_size(h));
252 if(corsaro_file_write(corsaro,
STATE(corsaro)->outfile, &hbuf[0], 10) != 10)
254 corsaro_log(__func__, corsaro,
"could not dump byte flowtuple header to file");
260 if(
sort_hash(corsaro, h, &sorted_keys) != 0)
262 corsaro_log(__func__, corsaro,
"could not sort keys");
266 for(j = 0; j < kh_size(h); j++)
268 i = kh_get(sixt, h, sorted_keys[j]);
271 flowtuple = kh_key(h, i);
276 if(corsaro_file_write(corsaro,
STATE(corsaro)->outfile,
280 corsaro_log(__func__, corsaro,
281 "could not write flowtuple to file");
289 if(corsaro_file_write(corsaro,
STATE(corsaro)->outfile, &hbuf[0], 6) != 6)
291 corsaro_log(__func__, corsaro,
"could not dump flowtuple trailer to file");
306 kh_sixt_t *h =
STATE(corsaro)->st_hash[dist];
313 class_start.
count = kh_size(h);
323 if(
sort_hash(corsaro, h, &sorted_keys) != 0)
325 corsaro_log(__func__, corsaro,
"could not sort keys");
328 for(j = 0; j < kh_size(h); j++)
330 i = kh_get(sixt, h, sorted_keys[j]);
348 class->magic = ntohl(class->magic);
349 class->class_type = ntohs(class->class_type);
350 class->count = ntohl(class->count);
368 corsaro_io_read_bytes(corsaro, record,
378 corsaro_log_in(__func__, corsaro,
"could not validate flowtuple class");
379 corsaro_log_in(__func__, corsaro,
380 "it is possible this flowtuple file was written "
381 #ifdef CORSARO_SLASH_EIGHT
386 "optimizations enabled");
387 corsaro_log_in(__func__, corsaro,
"try rebuilding using the "
388 #ifdef CORSARO_SLASH_EIGHT
389 "--without-slash-eight "
391 "--with-slash-eight=0 "
414 class->magic = ntohl(class->magic);
415 class->class_type = ntohs(class->class_type);
433 corsaro_io_read_bytes(corsaro, record,
443 corsaro_log_in(__func__, corsaro,
"could not validate flowtuple class end");
452 record->
buffer)->class_type ==
474 if((bytes_read = corsaro_io_read_bytes(corsaro, record,
484 corsaro_log_in(__func__, corsaro,
"could not validate flowtuple");
508 int corsaro_flowtuple_probe_filename(
const char *fname)
511 return corsaro_plugin_probe_filename(fname, &corsaro_flowtuple_plugin);
520 len = corsaro_file_rpeek(corsaro, file, buffer,
sizeof(buffer));
524 buffer[i++] ==
'S' && buffer[i++] ==
'I' &&
525 buffer[i++] ==
'X' && (buffer[i] ==
'T' || buffer[i] ==
'U'))
539 struct corsaro_flowtuple_state_t *state;
541 assert(plugin != NULL);
543 if((state = malloc_zero(
sizeof(
struct corsaro_flowtuple_state_t))) == NULL)
545 corsaro_log(__func__, corsaro,
546 "could not malloc corsaro_flowtuple_state_t");
549 corsaro_plugin_register_state(corsaro->
plugin_manager, plugin, state);
552 if((state->outfile = corsaro_io_prepare_file(corsaro, plugin->
name)) == NULL)
554 corsaro_log(__func__, corsaro,
"could not open %s output file",
561 assert(state->st_hash[i] == NULL);
562 state->st_hash[i] = kh_init(sixt);
563 assert(state->st_hash[i] != NULL);
569 corsaro_flowtuple_close_output(corsaro);
575 struct corsaro_flowtuple_in_state_t *state;
577 assert(plugin != NULL);
579 if((state = malloc_zero(
sizeof(
struct corsaro_flowtuple_in_state_t))) == NULL)
581 corsaro_log_in(__func__, corsaro,
582 "could not malloc corsaro_flowtuple_state_t");
585 corsaro_plugin_register_state(corsaro->
plugin_manager, plugin, state);
595 corsaro_flowtuple_close_input(corsaro);
599 int corsaro_flowtuple_close_input(
corsaro_in_t *corsaro)
601 struct corsaro_flowtuple_in_state_t *state =
STATE_IN(corsaro);
610 int corsaro_flowtuple_close_output(
corsaro_t *corsaro)
613 struct corsaro_flowtuple_state_t *state =
STATE(corsaro);
619 if(state->st_hash[i] != NULL)
622 kh_destroy(sixt, state->st_hash[i]);
623 state->st_hash[i] = NULL;
627 if(state->outfile != NULL)
629 corsaro_file_close(corsaro, state->outfile);
630 state->outfile = NULL;
637 off_t corsaro_flowtuple_read_record(
struct corsaro_in *corsaro,
642 struct corsaro_flowtuple_in_state_t *state =
STATE_IN(corsaro);
644 off_t bytes_read = -1;
647 switch(state->expected_type)
651 bytes_read = corsaro_io_read_interval_start(corsaro, corsaro->
file,
652 record_type, record);
661 bytes_read = read_class_start(corsaro, record_type, record);
666 bytes_read = read_flowtuple(corsaro, record_type, record);
671 bytes_read = read_class_end(corsaro, record_type, record);
676 bytes_read = corsaro_io_read_interval_end(corsaro, corsaro->
file,
677 record_type, record);
685 corsaro_log_in(__func__, corsaro,
"invalid expected record type");
691 off_t corsaro_flowtuple_read_global_data_record(
struct corsaro_in *corsaro,
704 if(
STATE(corsaro)->st_hash[i] == NULL)
706 corsaro_log(__func__, corsaro,
707 "corsaro_flowtuple_init must be called first");
714 kh_clear(sixt,
STATE(corsaro)->st_hash[i]);
724 corsaro_io_write_interval_start(corsaro,
STATE(corsaro)->outfile,
734 corsaro_log(__func__, corsaro,
"could not dump hash");
739 corsaro_io_write_interval_end(corsaro,
STATE(corsaro)->outfile, int_end);
744 int corsaro_flowtuple_process_packet(
corsaro_t *corsaro,
747 libtrace_packet_t *ltpacket =
LT_PKT(packet);
748 libtrace_ip_t *ip_hdr = NULL;
749 libtrace_icmp_t *icmp_hdr = NULL;
750 libtrace_tcp_t *tcp_hdr = NULL;
754 if((ip_hdr = trace_get_ip(ltpacket)) != NULL)
757 t.
ip_len = ip_hdr->ip_len;
759 t.
src_ip = ip_hdr->ip_src.s_addr;
765 t.
ttl = ip_hdr->ip_ttl;
767 if(ip_hdr->ip_p == TRACE_IPPROTO_ICMP &&
768 (icmp_hdr = trace_get_icmp(ltpacket)) != NULL)
775 if(ip_hdr->ip_p == TRACE_IPPROTO_TCP &&
776 (tcp_hdr = trace_get_tcp(ltpacket)) != NULL)
781 (tcp_hdr->cwr << 7) |
782 (tcp_hdr->ece << 6) |
783 (tcp_hdr->urg << 5) |
784 (tcp_hdr->ack << 4) |
785 (tcp_hdr->psh << 3) |
786 (tcp_hdr->rst << 2) |
787 (tcp_hdr->syn << 1) |
792 t.
src_port = htons(trace_get_source_port(ltpacket));
793 t.
dst_port = htons(trace_get_destination_port(ltpacket));
799 corsaro_log(__func__, corsaro,
"could not classify packet");
805 packet->
state.
flags |= CORSARO_PACKET_STATE_FLAG_BACKSCATTER;
810 corsaro_log(__func__, corsaro,
"could not increment value for flowtuple");
827 assert(flowtuple != NULL);
834 assert(flowtuple != NULL);
842 char ip_a[INET_ADDRSTRLEN];
843 char ip_b[INET_ADDRSTRLEN];
846 assert(corsaro != NULL);
847 assert(file != NULL);
848 assert(flowtuple != NULL);
851 inet_ntop(AF_INET,&tmp, &ip_a[0], 16);
853 inet_ntop(AF_INET, &tmp, &ip_b[0], 16);
855 return corsaro_file_printf(corsaro, file,
"%s|%s"
857 "|%"PRIu8
"|%"PRIu8
"|0x%02"PRIx8
876 assert(flowtuple != NULL);
879 inet_ntop(AF_INET,&tmp, &ip_a[0], 16);
881 inet_ntop(AF_INET, &tmp, &ip_b[0], 16);
883 fprintf(stdout,
"%s|%s"
885 "|%"PRIu8
"|%"PRIu8
"|0x%02"PRIx8
901 return corsaro_file_printf(corsaro, file,
902 "START %s %"PRIu32
"\n",
909 fprintf(stdout,
"START %s %"PRIu32
"\n",
class_names[class->class_type],
916 return corsaro_file_printf(corsaro, file,
"END %s\n",
922 fprintf(stdout,
"END %s\n",
class_names[class->class_type]);
947 corsaro_log(__func__, corsaro,
"record_type %d not a flowtuple record",
976 corsaro_log_file(__func__, NULL,
"record_type %d not a flowtuple record",
993 kh_sixt_t *hash = (kh_sixt_t *)h;
998 assert(hash != NULL);
1001 if((khiter = kh_get(sixt, hash, t)) == kh_end(hash))
1006 corsaro_log_file(__func__, NULL,
"malloc failed");
1014 khiter = kh_put(sixt, hash, new_6t, &khret);
1023 new_6t = kh_key(hash, khiter);