int main(int argc, char *argv[]) { if (argc < 2) { fprintf(stderr, "Usage: %s <interface> [whitelist]\n", argv[0]); return 1; } struct timeval start_timeval; gettimeofday(&start_timeval, NULL); start_timestamp_microseconds = start_timeval.tv_sec * NUM_MICROS_PER_SECOND + start_timeval.tv_usec; initialize_bismark_id(); if (argc < 3 || initialize_domain_whitelist(argv[2])) { fprintf(stderr, "Error loading domain whitelist; whitelisting disabled.\n"); } #ifndef DISABLE_ANONYMIZATION if (anonymization_init()) { fprintf(stderr, "Error initializing anonymizer\n"); return 1; } #endif #ifdef ENABLE_FREQUENT_UPDATES if (anonymize_mac(bismark_mac, bismark_mac)) { fprintf(stderr, "Error anonymizing router MAC address\n"); } #endif packet_series_init(&packet_data); flow_table_init(&flow_table); dns_table_init(&dns_table, &domain_whitelist); #ifdef ENABLE_HTTP_URL http_table_init(&http_table); #endif address_table_init(&address_table); drop_statistics_init(&drop_statistics); #ifdef ENABLE_FREQUENT_UPDATES device_throughput_table_init(&device_throughput_table); #endif upload_failures_init(&upload_failures, UPLOAD_FAILURES_FILENAME); initialize_signal_handler(); set_next_alarm(); /* By default, pcap uses an internal buffer of 500 KB. Any packets that * overflow this buffer will be dropped. pcap_stats tells the number of * dropped packets. * * Because pcap does its own buffering, we don't need to run packet * processing in a separate thread. (It would be easier to just increase * the buffer size if we experience performance problems.) */ pcap_handle = initialize_pcap(argv[1]); if (!pcap_handle) { return 1; } return pcap_loop(pcap_handle, -1, process_packet, NULL); }
int main(int argc, char *argv[]) { if (argc < 2) { fprintf(stderr, "Usage: %s <interface> [whitelist]\n", argv[0]); return 1; } struct timeval start_timeval; gettimeofday(&start_timeval, NULL); start_timestamp_microseconds = start_timeval.tv_sec * NUM_MICROS_PER_SECOND + start_timeval.tv_usec; if (initialize_bismark_id()) { return 1; } if (argc < 3 || initialize_domain_whitelist(argv[2])) { fprintf(stderr, "Error loading domain whitelist; whitelisting disabled.\n"); } #ifndef DISABLE_ANONYMIZATION if (anonymization_init()) { fprintf(stderr, "Error initializing anonymizer\n"); return 1; } #endif packet_series_init(&packet_data); flow_table_init(&flow_table); dns_table_init(&dns_table, &domain_whitelist); address_table_init(&address_table); drop_statistics_init(&drop_statistics); #ifdef ENABLE_FREQUENT_UPDATES device_throughput_table_init(&device_throughput_table); #endif if (pthread_mutex_init(&update_lock, NULL)) { perror("Error initializing mutex"); return 1; } sigset_t signal_set; sigemptyset(&signal_set); sigaddset(&signal_set, SIGINT); sigaddset(&signal_set, SIGTERM); if (pthread_sigmask(SIG_BLOCK, &signal_set, NULL)) { perror("Error calling pthread_sigmask"); return 1; } if (pthread_create(&signal_thread, NULL, handle_signals, &signal_set)) { perror("Error creating signal handling thread"); return 1; } if (pthread_create(&update_thread, NULL, updater, NULL)) { perror("Error creating updates thread"); return 1; } #ifdef ENABLE_FREQUENT_UPDATES if (pthread_create(&frequent_update_thread, NULL, frequent_updater, NULL)) { perror("Error creating frequent updates thread"); return 1; } #endif /* By default, pcap uses an internal buffer of 500 KB. Any packets that * overflow this buffer will be dropped. pcap_stats tells the number of * dropped packets. * * Because pcap does its own buffering, we don't need to run packet * processing in a separate thread. (It would be easier to just increase * the buffer size if we experience performance problems.) */ pcap_handle = initialize_pcap(argv[1]); if (!pcap_handle) { return 1; } return pcap_loop(pcap_handle, -1, process_packet, NULL); }
/* Write an update to UPDATE_FILENAME. This is the file that will be sent to the * server. The data is compressed on-the-fly using gzip. */ static void write_update() { struct pcap_stat statistics; int have_pcap_statistics; if (pcap_handle) { have_pcap_statistics = !pcap_stats(pcap_handle, &statistics); #ifndef NDEBUG if (!have_pcap_statistics) { pcap_perror(pcap_handle, "Error fetching pcap statistics"); } #endif } else { have_pcap_statistics = 0; } #ifndef DISABLE_FLOW_THRESHOLDING if (flow_table_write_thresholded_ips(&flow_table, start_timestamp_microseconds, sequence_number)) { #ifndef NDEBUG fprintf(stderr, "Couldn't write thresholded flows log\n"); #endif } #endif #ifndef NDEBUG printf("Writing differential log to %s\n", PENDING_UPDATE_FILENAME); #endif gzFile handle = gzopen (PENDING_UPDATE_FILENAME, "wb"); if (!handle) { #ifndef NDEBUG perror("Could not open update file for writing"); #endif exit(1); } dns_table_mark_unanonymized(&dns_table, &flow_table); time_t current_timestamp = time(NULL); if (!gzprintf(handle, "%d\n%s\n", FILE_FORMAT_VERSION, BUILD_ID)) { #ifndef NDEBUG perror("Error writing update"); #endif exit(1); } if (!gzprintf(handle, "%s %" PRId64 " %d %" PRId64 "\n", bismark_id, start_timestamp_microseconds, sequence_number, (int64_t)current_timestamp)) { #ifndef NDEBUG perror("Error writing update"); #endif exit(1); } if (have_pcap_statistics) { if (!gzprintf(handle, "%u %u %u\n", statistics.ps_recv, statistics.ps_drop, statistics.ps_ifdrop)) { #ifndef NDEBUG perror("Error writing update"); #endif exit(1); } } if (!gzprintf(handle, "\n")) { #ifndef NDEBUG perror("Error writing update"); #endif exit(1); } if (sequence_number == 0) { if (domain_whitelist_write_update(&domain_whitelist, handle)) { exit(1); } } else { if (!gzprintf(handle, "\n")) { #ifndef NDEBUG perror("Error writing update"); #endif exit(1); } } #ifndef DISABLE_ANONYMIZATION if (anonymization_write_update(handle)) { exit(1); } #else if (!gzprintf(handle, "UNANONYMIZED\n\n")) { #ifndef NDEBUG perror("Error writing update"); #endif exit(1); } #endif if (packet_series_write_update(&packet_data, handle) || flow_table_write_update(&flow_table, handle) || dns_table_write_update(&dns_table, handle) || address_table_write_update(&address_table, handle) || drop_statistics_write_update(&drop_statistics, handle)) { exit(1); } gzclose(handle); char update_filename[FILENAME_MAX]; snprintf(update_filename, FILENAME_MAX, UPDATE_FILENAME, bismark_id, start_timestamp_microseconds, sequence_number); if (rename(PENDING_UPDATE_FILENAME, update_filename)) { #ifndef NDEBUG perror("Could not stage update"); #endif exit(1); } ++sequence_number; packet_series_init(&packet_data); flow_table_advance_base_timestamp(&flow_table, current_timestamp); dns_table_destroy(&dns_table); dns_table_init(&dns_table, &domain_whitelist); drop_statistics_init(&drop_statistics); }