/* abandon all hope, this shit is a mess */ #include #include #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 /*define DEFCON level stuff */ #define DEFCON_URL "https://defconwarningsystem.com/code.dat" unsigned int level; unsigned int cooldown = 1800; unsigned int cooldown_timer = 0; bool cooldown_reset = false; size_t write_data(void *ptr1, size_t size, size_t nmemb, FILE *stream) { size_t written = fwrite(ptr1, size, nmemb, stream); return written; }; /* 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; int term_rows, term_cols; /* declare ncurses windows */ WINDOW * sdr; WINDOW * rss; WINDOW * defcon; /* startup screen! :3 */ 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 reusable functions */ void get_terminal_size(int *rows, int *cols) { struct winsize w; ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); *rows = w.ws_row; *cols = w.ws_col; } /* 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; } /* 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_startup = fgetc(fp); printf("DEFCON level cache file found! last known level: %d\n", last_known_startup); 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!\n"RESET); COMMS_AVAILABLE = false; } /* get terminal size */ get_terminal_size(&term_rows, &term_cols); printf("terminal size: "); printf(YELLOW"%dx%d\n"RESET, term_rows, term_cols); 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); } if (COMMS_AVAILABLE == true && CURL_AVAILABLE == true) { printf(GREEN"initializing DEFCON level parser...\n"RESET); } } /* 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); init_pair(8, COLOR_WHITE, COLOR_RED); init_pair(9, COLOR_WHITE, COLOR_GREEN); } void print_centered(WINDOW *win, const char *text) { int width = getmaxx(win); int height = getmaxy(win)/2; int length = strlen(text); int start_col = (width - length) / 2; mvwprintw(win, height, start_col, "%s", text); } /* define rtl-sdr specific functions and general SDR workflow - WIP */ /* 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); } } void draw_bar_graph(double *data, int size) { wclear(sdr); double max_value = 0.0; wattron(sdr, COLOR_PAIR(6)); wprintw(sdr, "center frequency: %.3f MHz gain: %d bandwidth: %.3f MHz", center_freq / (double)MHz, rtlsdr_get_tuner_gain(dev), bandwidth / (double)MHz); wattroff(sdr, 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]; } } wattron(sdr, COLOR_PAIR(4)); for (int i = 0; i < size; i++) { mvwprintw(sdr, i + 1, 0, "%.3f MHz: ", bottom / (double)MHz + i * step / (double)MHz); for (int j = 0; j < data[i] * 50 / max_value; j++) { wprintw(sdr, ">"); } } wattroff(sdr, COLOR_PAIR(4)); wrefresh(sdr); } 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 = getmaxy(sdr)-2, 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); } /* RSS feed functions & workflow - WIP */ /* DEFCON level functions */ char fetch_defcon_level() { CURL *curl; CURLcode res; FILE *fp; unsigned int current_level = 5; //nothing ever happens unsigned int last_known; cooldown_timer++; if(cooldown_timer > cooldown_reset){ cooldown_reset = true; } if (cooldown_reset = true) { curl = curl_easy_init(); if (curl) { fp = fopen(".last_known_defcon", "w"); if (fp == NULL) { perror("fopen"); return current_level; } curl_easy_setopt(curl, CURLOPT_URL, DEFCON_URL); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); res = curl_easy_perform(curl); if (res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } else { fseek(fp, 0, SEEK_SET); int ch = fgetc(fp); if (isdigit(ch)){ current_level = ch - '0'; // read the DEFCON level from the file last_known = current_level; } } fclose(fp); curl_easy_cleanup(curl); } else { print_centered(defcon, "HTTP request failed :("); } return current_level; } else { current_level = last_known; return current_level; } } void print_file_lines_ncurses(const char *filename, WINDOW *win) { FILE *file = fopen(filename, "r"); if (file == NULL) { perror("fopen"); return; } char line[256]; int y = 1; while (fgets(line, sizeof(line), file) != NULL) { mvwprintw(win, y++, 1, "%s", line); wrefresh(win); } fclose(file); } /* main dashboard function */ void start_dashboard() { initscr(); cbreak(); noecho(); init_colors(); refresh(); WINDOW * sdr = newwin(term_rows/2-2, term_cols/2, 1, 1); WINDOW * rss = newwin(term_rows-2, term_cols/2-2, 1, term_cols/2+2); WINDOW * defcon = newwin(term_rows/2, term_cols/2, term_rows/2, 1); box(sdr, 0, 0); box(rss, 0, 0); box(defcon, 0, 0); wrefresh(sdr); wrefresh(rss); wrefresh(defcon); while(true) { /* SDR window */ if (SDR_PRESENT == true) { rtl_sdr_waterfall(); } else { wbkgd(sdr, COLOR_PAIR(8)); print_centered(sdr, "SDR NOT AVAILABLE"); wrefresh(sdr); usleep(1000000); } /* RSS window */ if (COMMS_AVAILABLE == true && CURL_AVAILABLE == true) { wbkgd(rss, COLOR_PAIR(9)); print_centered(rss, "RSS FEED AVAILABLE"); wrefresh(rss); usleep(1000000); } else { wbkgd(rss, COLOR_PAIR(8)); print_centered(rss, "RSS FEEED NOT AVAILABLE"); wrefresh(rss); usleep(1000000); } /* DEFCON window */ if (COMMS_AVAILABLE == true && CURL_AVAILABLE == true) { level = fetch_defcon_level(); switch(level) { case 5: wbkgd(defcon, COLOR_PAIR(4)); print_file_lines_ncurses("./ascii/level5", defcon); wprintw(defcon, " DEFCON 5 - NOTHING EVER HAPPENS"); break; case 4: wbkgd(defcon, COLOR_PAIR(2)); print_file_lines_ncurses("./ascii/level4", defcon); wprintw(defcon, " DEFCON 4 - UNLIKELY TO HAPPEN"); break; case 3: wbkgd(defcon, COLOR_PAIR(5)); print_file_lines_ncurses("./ascii/level3", defcon); wprintw(defcon, " DEFCON 3 - MAYBE IT WILL HAPPEN"); break; case 2: wbkgd(defcon, COLOR_PAIR(3)); print_file_lines_ncurses("./ascii/level2", defcon); wprintw(defcon, " DEFCON 2 - SOMETHING WILL HAPPEN"); break; case 1: wbkgd(defcon, COLOR_PAIR(1)); print_file_lines_ncurses("./ascii/level1", defcon); wprintw(defcon, " DEFCON 1 - IT IS HAPPENING"); break; default: wbkgd(defcon, COLOR_PAIR(4)); print_file_lines_ncurses("./ascii/level5", defcon); wprintw(defcon, " DEFCON 5 - NOTHING EVER HAPPENS"); //because nothing ever happens break; } wrefresh(defcon); usleep(1000000); } else { wbkgd(defcon, COLOR_PAIR(8)); print_centered(defcon, "DEFCON CHECK NOT AVAILABLE"); wrefresh(defcon); usleep(1000000); } rtlsdr_close(dev); endwin(); } } int main() { startup_screen(); startup_checks(); start_dashboard(); return 0; }