/* abandon all hope, this shit is a mess */ #include #include #include #include #include #include #include #include /* define ANSI escape chars and math */ #define RESET "\033[0m" #define BOLD "\033[1m" #define UNDERLINE "\033[4m" #define BLINK "\033[5m" #define REVERSED "\033[7m" #define BLACK "\033[30m" #define RED "\033[31m" #define GREEN "\033[32m" #define YELLOW "\033[33m" #define BLUE "\033[34m" #define MAGENTA "\033[35m" #define CYAN "\033[36m" #define WHITE "\033[37m" #define BG_BLACK "\033[40m" #define BG_RED "\033[41m" #define BG_GREEN "\033[42m" #define BG_YELLOW "\033[43m" #define BG_BLUE "\033[44m" #define BG_MAGENTA "\033[45m" #define BG_CYAN "\033[46m" #define BG_WHITE "\033[47m" #define M_PI 3.14159265358979323846 /* declare global variables */ rtlsdr_dev_t *dev = NULL; uint32_t device_index = 0; uint32_t MHz = 1000000; uint32_t kHz = 1000; uint32_t bandwidth; uint32_t center_freq; bool SDR_PRESENT = false; bool RSS_LIST_PRESENT = false; bool COMMS_AVAILABLE = false; bool CURL_AVAILABLE = false; /* declare reusable functions */ /* read out shell command output */ char* readout(const char* command, char* buffer, size_t size) { FILE *fp = popen(command, "r"); if (fp == NULL) { perror("popen"); exit(EXIT_FAILURE); } if (fgets(buffer, size, fp) == NULL) { perror("fgets"); pclose(fp); exit(EXIT_FAILURE); } pclose(fp); /* remove the newline character at the end of the buffer */ buffer[strcspn(buffer, "\n")] = 0; return buffer; } void startup_screen() { printf("\n\n"); printf(CYAN" █████ ███ ████ \n"); printf(" ░░███ ░░░ ░░███ \n"); printf(" █████ ██████ ████████ ███████ ████ ████████ ██████ ░███ \n"); printf(" ███░░ ███░░███░░███░░███ ░░░███░ ░░███ ░░███░░███ ███░░███ ░███ \n"); printf("░░█████ ░███████ ░███ ░███ ░███ ░███ ░███ ░███ ░███████ ░███ \n"); printf(" ░░░░███░███░░░ ░███ ░███ ░███ ███ ░███ ░███ ░███ ░███░░░ ░███ \n"); printf(" ██████ ░░██████ ████ █████ ░░█████ █████ ████ █████░░██████ █████\n"); printf("░░░░░░ ░░░░░░ ░░░░ ░░░░░ ░░░░░ ░░░░░ ░░░░ ░░░░░ ░░░░░░ ░░░░░ \n\n"); printf(" v0.0.1\n" RESET); } /* declare functions for startup checks */ void util_check() { printf("curl: "); if (system("curl --version > /dev/null 2>&1") == 0) { printf(GREEN"OK\n"RESET); CURL_AVAILABLE = true; } else { printf(RED"FAIL\n"RESET); } printf("rtl-sdr: "); if (system("ls /usr/bin/rtl_sdr > /dev/null 2>&1") == 0) { printf(GREEN"OK\n"RESET); SDR_PRESENT = true; } else { printf(RED"FAIL\n"RESET); } } void rtl_sdr_check() { if (rtlsdr_open != NULL && SDR_PRESENT == true) { int index; const char* device_name; char serial[256], product[256], manufact[256]; device_name = rtlsdr_get_device_name(device_index); rtlsdr_get_device_usb_strings(index, manufact, product, serial); printf("device name: " GREEN); printf(device_name); printf("\n" RESET); printf(YELLOW"serial: %s\n", serial); printf("product: %s\n", product); printf("manufacturer: %s\n", manufact); printf(RESET); rtlsdr_close; } else { printf(RED"SDR not detected! skipping...\n"RESET); } } void defcon_level_check() { FILE *fp = fopen(".last_known_defcon", "r"); if ( fp == NULL) { printf(YELLOW"DEFCON level cache file not found or corrupted, creating new...\n"RESET); FILE *fp = fopen(".last_known_defcon", "w"); fputc(5, fp); fclose(fp); } else { int last_known = fgetc(fp); printf("DEFCON level cache file found! last known level: %d\n", last_known); fclose(fp); } } void rss_sources_check() { if (COMMS_AVAILABLE == true) { FILE *fp = fopen(".rss_feed_list", "r"); if ( fp == NULL) { printf(RED"RSS feed source list not found!\n"RESET); fclose(fp); } else { printf(GREEN"RSS feed source list found! sources:\n\n"RESET); RSS_LIST_PRESENT = true; int line_count = 0; char buffer[256]; while (fgets(buffer, sizeof(buffer), fp) != NULL) { line_count++; } char feed_source[line_count][256]; fseek(fp, 0, SEEK_SET); for (int i = 0; i < line_count; i++) { fgets(feed_source[i], sizeof(feed_source[i]), fp); printf(GREEN"%s\n"RESET, feed_source[i]); } fclose(fp); } } else { printf(RED"internet not available! skipping..."RESET); } } /* making sure program has everything it needs to run, more checks will be introduced as capabilities are added */ void startup_checks() { printf("######################################################################\n"); printf(MAGENTA"STARTUP CHECKS\n"RESET); printf("----------------------------------------------------------------------\n"); printf(MAGENTA"SYSTEM STATUS\n\n"RESET); printf("date: %s\n", readout("date \"+%D\"", (char[100]){0}, 100)); printf("time: %s\n", readout("date \"+%T\"", (char[100]){0}, 100)); /* internet connectivity check */ int status = system("ping -c 1 fsf.org > /dev/null 2>&1"); if (status == 0) { printf("internet connectivity status: "); printf(GREEN"online\n"RESET); COMMS_AVAILABLE = true; } else { printf("internet connectivity status: "); printf(RED"offline\n"RESET); printf(RED"internet-dependent capabilities will be unavailable!"RESET); COMMS_AVAILABLE = false; } printf("----------------------------------------------------------------------\n"); /* utilities presence check */ printf(MAGENTA"UTILITIES\n\n"RESET); util_check(); printf("----------------------------------------------------------------------\n"); printf(MAGENTA"SOFTWARE-DEFINED RADIO\n\n"RESET); rtl_sdr_check(); printf("----------------------------------------------------------------------\n"); printf(MAGENTA"DEFCON LEVEL STATUS\n\n"RESET); defcon_level_check(); printf("----------------------------------------------------------------------\n"); printf(MAGENTA"RSS AGGREGATOR CHECK\n\n"RESET); rss_sources_check(); printf("----------------------------------------------------------------------\n"); printf(MAGENTA"all checks finished!\n"RESET); printf("######################################################################\n"); printf(BLUE"initializing in 5 seconds...\n\n"RESET); usleep(5000000); if (SDR_PRESENT == true) { printf(GREEN"initializing RTL-SDR...\n"RESET); rtlsdr_open(&dev, device_index); } if (RSS_LIST_PRESENT == true && COMMS_AVAILABLE == true && CURL_AVAILABLE == true) { printf(GREEN"initializing RSS aggregator...\n"RESET); } } /* signal analysis function */ void fourier_transform(unsigned char *buf, double *out, int n) { for (int k = 0; k < n; k++) { double real = 0.0; double imag = 0.0; for (int t = 0; t < n; t++) { double angle = 2 * M_PI * t * k / n; real += buf[t] * cos(angle); imag -= buf[t] * sin(angle); } out[k] = sqrt(real * real + imag * imag); } } /* define functions for dashboard - WIP */ void init_colors() { start_color(); init_pair(1, COLOR_RED, COLOR_BLACK); init_pair(2, COLOR_GREEN, COLOR_BLACK); init_pair(3, COLOR_YELLOW, COLOR_BLACK); init_pair(4, COLOR_BLUE, COLOR_BLACK); init_pair(5, COLOR_MAGENTA, COLOR_BLACK); init_pair(6, COLOR_CYAN, COLOR_BLACK); init_pair(7, COLOR_WHITE, COLOR_BLACK); } void draw_bar_graph(double *data, int size) { clear(); double max_value = 0.0; attron(COLOR_PAIR(6)); printw("center frequency: %.3f MHz gain: %d bandwidth: %.3f MHz", center_freq / (double)MHz, rtlsdr_get_tuner_gain(dev), bandwidth / (double)MHz); attroff(COLOR_PAIR(6)); double bottom = center_freq - bandwidth / 2.0; double step = bandwidth / (double)size; for (int i = 0; i < size; i++) { if (data[i] > max_value) { max_value = data[i]; } } attron(COLOR_PAIR(4)); for (int i = 0; i < size; i++) { mvprintw(i + 1, 0, "%.3f MHz: ", bottom / (double)MHz + i * step / (double)MHz); for (int j = 0; j < data[i] * 50 / max_value; j++) { printw(">"); } } attroff(COLOR_PAIR(4)); refresh(); } /* define rtl-sdr specific functions and general SDR workflow - WIP */ void rtl_sdr_processing(unsigned char *buf, int buffer_length) { int n = buffer_length; double *out = (double *)malloc(n * sizeof(double)); fourier_transform(buf, out, n); /* debug for (int i = 0; i < n; i++) { printf("%f\n", out[i]); } */ draw_bar_graph(out, n); free(out); } void rtl_sdr_waterfall() { bandwidth = 10*MHz; rtlsdr_set_tuner_bandwidth(dev, bandwidth); uint32_t buffer_length = 40, n_read = 10; // example buffer length unsigned char *buffer = (unsigned char *)malloc(buffer_length); rtlsdr_set_center_freq(dev, 104*MHz); //104MHz for testing purposes center_freq = rtlsdr_get_center_freq(dev); rtlsdr_read_sync(dev, buffer, buffer_length, &n_read); rtl_sdr_processing(buffer, buffer_length); usleep(500000); } void sdr_not_available() { clear(); attron(COLOR_PAIR(1)); printw("SDR NOT AVAILABLE"); attroff(COLOR_PAIR(1)); refresh(); usleep(5000000); } /* DEFCON level functions */ /* main dashboard function */ void start_dashboard() { initscr(); cbreak(); noecho(); init_colors(); if (SDR_PRESENT == true) { do{ rtl_sdr_waterfall(); } while (true); } else { do{ sdr_not_available(); } while (true); } rtlsdr_close(dev); endwin(); } int main() { startup_screen(); startup_checks(); start_dashboard(); return 0; }