OreBolt-OS/modules/orebolt-nettap/scalpel.c

161 lines
5.2 KiB
C
Executable File

/*
* scalpel.c -- USB Virtual Network Tap (Nettap) module
*
* SPDX-License-Identifier: GPL-2.0-or-later
*
* USB virtual network tap. Captures IP packets from usb0 via raw
* AF_PACKET socket, parses src/dst IPv4 addresses, displays them
* on an LVGL console, and coalesces writes to disk via the
* flash-safe timed logger.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <linux/if_ether.h>
#include <linux/input.h>
#include "h2_ui.h"
#include "log_manager.h"
#define NUM_WINDOWS 5
#define CONSOLE_MAX_LINES 20
const log_window_t window_durations[NUM_WINDOWS] = {
WINDOW_30S, WINDOW_1M, WINDOW_2M, WINDOW_5M, WINDOW_10M
};
const char *window_labels[NUM_WINDOWS] = {
"30 SECONDS", "1 MINUTE", "2 MINUTES", "5 MINUTES", "10 MINUTES"
};
static lv_obj_t *console;
static timed_logger_t *logger;
static void process_ip_packet(const uint8_t *pkt, ssize_t pkt_len) {
uint16_t ethertype = ((uint16_t)pkt[12] << 8) | pkt[13];
if (ethertype != 0x0800) return;
if (pkt_len < 34) return;
char display_row[64];
snprintf(display_row, sizeof(display_row),
"IP: %d.%d.%d.%d -> %d.%d.%d.%d",
pkt[26], pkt[27], pkt[28], pkt[29],
pkt[30], pkt[31], pkt[32], pkt[33]);
char log_row[128];
snprintf(log_row, sizeof(log_row),
"[%ld] SIZE:%ld %d.%d.%d.%d->%d.%d.%d.%d\n",
(long)time(NULL), (long)pkt_len,
pkt[26], pkt[27], pkt[28], pkt[29],
pkt[30], pkt[31], pkt[32], pkt[33]);
if (logger) timed_log_write(logger, log_row);
lv_list_add_text(console, display_row);
static int line_count;
line_count++;
if (line_count > CONSOLE_MAX_LINES) {
lv_obj_clean(console);
line_count = 0;
}
}
int main(void) {
init_h2_graphics_runtime("USB TAP MANAGER NODE");
LOG_INF("nettap module started");
lv_obj_t *scr = lv_scr_act();
lv_obj_t *title = lv_label_create(scr);
lv_label_set_text(title, "USB VIRTUAL NETTAP");
lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 10);
lv_obj_set_style_text_color(title, COLOR_PRIMARY, LV_PART_MAIN);
lv_obj_t *config_card = lv_obj_create(scr);
lv_obj_set_size(config_card, 290, 160);
lv_obj_align(config_card, LV_ALIGN_CENTER, 0, 15);
lv_obj_set_style_bg_color(config_card, lv_color_make(22, 28, 38), LV_PART_MAIN);
lv_obj_t *cfg_lbl = lv_label_create(config_card);
lv_label_set_text(cfg_lbl, "SET DATA FLUSH TIME WINDOW:");
lv_obj_align(cfg_lbl, LV_ALIGN_TOP_MID, 0, 10);
lv_obj_t *window_lbl = lv_label_create(config_card);
lv_obj_align(window_lbl, LV_ALIGN_CENTER, 0, -5);
lv_obj_set_style_text_color(window_lbl, COLOR_ACCENT, LV_PART_MAIN);
int input_fd = open("/dev/input/event0", O_RDONLY | O_NONBLOCK);
struct input_event ev;
int sel = 1;
while (1) {
lv_label_set_text(window_lbl, window_labels[sel]);
lv_timer_handler();
if (input_fd < 0) { usleep(15000); continue; }
if (read(input_fd, &ev, sizeof(struct input_event)) <= 0) { usleep(15000); continue; }
if (ev.type == EV_REL && ev.code == 0) {
if (ev.value > 0 && sel < NUM_WINDOWS - 1) sel++;
if (ev.value < 0 && sel > 0) sel--;
}
if (ev.type == EV_KEY && ev.value == 1 && ev.code == H2_KEY_PLAY) break;
usleep(15000);
}
logger = timed_log_init("/data/loot_drop/tether_stream.log", window_durations[sel]);
lv_obj_del(config_card);
console = lv_list_create(scr);
lv_obj_set_size(console, 300, 160);
lv_obj_align(console, LV_ALIGN_CENTER, 0, 15);
int sysfd = open("/sys/class/net/usb0/operstate", O_WRONLY);
if (sysfd >= 0) {
(void)write(sysfd, "up", 2);
close(sysfd);
}
int sock_raw = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sock_raw >= 0) {
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, "usb0", IFNAMSIZ - 1);
if (ioctl(sock_raw, SIOCGIFINDEX, &ifr) >= 0) {
fcntl(sock_raw, F_SETFL, O_NONBLOCK);
lv_obj_t *l = lv_list_add_text(console, "NETTAP ACTIVE: Listening on usb0...");
lv_obj_set_style_text_color(l, COLOR_ACCENT, LV_PART_MAIN);
LOG_INF("nettap listening on usb0, flush window: %s", window_labels[sel]);
}
}
uint8_t pkt_buf[2048];
while (1) {
lv_timer_handler();
if (sock_raw >= 0) {
ssize_t pkt_len = recvfrom(sock_raw, pkt_buf, sizeof(pkt_buf), 0, NULL, NULL);
if (pkt_len > 0) process_ip_packet(pkt_buf, pkt_len);
}
if (logger && (time(NULL) - logger->window_start >= logger->window_duration))
timed_log_flush_to_media(logger);
if (input_fd >= 0 && read(input_fd, &ev, sizeof(struct input_event)) > 0) {
if (ev.type == EV_KEY && ev.code == H2_KEY_BACK && ev.value == 1) break;
}
usleep(5000);
}
if (logger) timed_log_close(logger);
if (sock_raw >= 0) close(sock_raw);
if (input_fd >= 0) close(input_fd);
LOG_INF("nettap module exited");
return 0;
}