#include "arp_scanner.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <net/if.h> #include <sys/ioctl.h> #include <linux/if_packet.h> #include <time.h> #include <errno.h> #include "json_api.h" // 加载配置 int load_config(arp_config_t *config) { if (config == NULL) { fprintf(stderr, "错误: 配置指针为空\n"); return -1; } // 使用ds_read读取配置 ds_read(ARPD_CONFIG_PATH, config, sizeof(arp_config_t)); return 0; } S32 arp_scanner_init() { memset(&g_scanner, 0, sizeof(arp_scanner_t)); // 创建原始套接字 g_scanner.raw_socket = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP)); if (g_scanner.raw_socket < 0) { perror("socket"); return -1; } // 初始化互斥锁 if (pthread_mutex_init(&g_scanner.lock, NULL) != 0) { close(g_scanner.raw_socket); return -1; } // 从配置文件加载配置 if (load_config(&g_scanner.config) != 0) { // 加载失败时使用默认值 g_scanner.config.enabled = FALSE; g_scanner.config.scan_interval = 60; g_scanner.config.validity_period = 300; g_scanner.config.packet_interval = 100; g_scanner.config.start_ip = ip_to_int("192.168.1.100"); g_scanner.config.end_ip = ip_to_int("192.168.1.200"); // 默认网络接口 strcpy(g_scanner.config.interface, "eth0"); fprintf(stderr, "Using default configuration\n"); } return 0; } S32 arp_scanner_start(void) { pthread_mutex_lock(&g_scanner.lock); g_scanner.scanning = TRUE; g_scanner.stop_requested = FALSE; pthread_mutex_unlock(&g_scanner.lock); return 0; } int arp_scanner_stop(void) { pthread_mutex_lock(&g_scanner.lock); g_scanner.stop_requested = TRUE; pthread_mutex_unlock(&g_scanner.lock); return 0; } int arp_scanner_cleanup(void) { arp_scanner_stop(); if (g_scanner.raw_socket >= 0) { close(g_scanner.raw_socket); } pthread_mutex_destroy(&g_scanner.lock); return 0; } int arp_scanner_scan(void) { if (!g_scanner.config.enabled) return -1; struct ifreq ifr; strcpy(ifr.ifr_name, g_scanner.config.interface); // 获取接口索引 if (ioctl(g_scanner.raw_socket, SIOCGIFINDEX, &ifr) < 0) { perror("ioctl"); return -1; } // 绑定到接口 struct sockaddr_ll saddr; memset(&saddr, 0, sizeof(saddr)); saddr.sll_family = AF_PACKET; saddr.sll_ifindex = ifr.ifr_ifindex; saddr.sll_protocol = htons(ETH_P_ARP); if (bind(g_scanner.raw_socket, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { perror("bind"); return -1; } // 发送ARP请求 for (uint32_t ip = g_scanner.config.start_ip; ip <= g_scanner.config.end_ip && !g_scanner.stop_requested; ip++) { arp_scanner_send_arp_request(ip); usleep(g_scanner.config.packet_interval * 1000); } // 处理ARP回复 arp_scanner_process_reply(); // 清理过期条目 arp_scanner_clean_old_entries(); g_scanner.last_scan_time = time(NULL); return 0; } int arp_scanner_send_arp_request(uint32_t target_ip) { struct ifreq ifr; strcpy(ifr.ifr_name, g_scanner.config.interface); // 获取接口MAC地址 if (ioctl(g_scanner.raw_socket, SIOCGIFHWADDR, &ifr) < 0) { perror("ioctl"); return -1; } unsigned char *src_mac = (unsigned char *)ifr.ifr_hwaddr.sa_data; // 获取接口IP地址 if (ioctl(g_scanner.raw_socket, SIOCGIFADDR, &ifr) < 0) { perror("ioctl"); return -1; } struct sockaddr_in *ipaddr = (struct sockaddr_in *)&ifr.ifr_addr; uint32_t src_ip = ipaddr->sin_addr.s_addr; // 构建ARP请求包 arp_packet_t packet; // 以太网头部 memset(packet.eth_header.h_dest, 0xFF, 6); // 广播地址 memcpy(packet.eth_header.h_source, src_mac, 6); packet.eth_header.h_proto = htons(ETH_P_ARP); // ARP头部 packet.arp_header.ar_hrd = htons(ARPHRD_ETHER); packet.arp_header.ar_pro = htons(ETH_P_IP); packet.arp_header.ar_hln = 6; packet.arp_header.ar_pln = 4; packet.arp_header.ar_op = htons(ARPOP_REQUEST); memcpy(packet.sender_mac, src_mac, 6); memcpy(packet.sender_ip, &src_ip, 4); memset(packet.target_mac, 0, 6); memcpy(packet.target_ip, &target_ip, 4); // 发送包 struct sockaddr_ll dest; memset(&dest, 0, sizeof(dest)); dest.sll_family = AF_PACKET; dest.sll_ifindex = ifr.ifr_ifindex; dest.sll_halen = ETH_ALEN; memset(dest.sll_addr, 0xFF, ETH_ALEN); ssize_t sent = sendto(g_scanner.raw_socket, &packet, sizeof(packet), 0, (struct sockaddr *)&dest, sizeof(dest)); return (sent == sizeof(packet)) ? 0 : -1; } int arp_scanner_process_reply(void) { fd_set readfds; struct timeval tv; int ret; int max_fd = g_scanner.raw_socket; // 设置超时时间为2秒,用于等待ARP回复 tv.tv_sec = 2; tv.tv_usec = 0; // 循环处理所有可用的ARP回复 while (1) { FD_ZERO(&readfds); FD_SET(g_scanner.raw_socket, &readfds); ret = select(max_fd + 1, &readfds, NULL, NULL, &tv); if (ret < 0) { if (errno == EINTR) { // 被信号中断,继续等待 continue; } perror("select"); break; } else if (ret == 0) { // 超时,没有更多数据 break; } if (FD_ISSET(g_scanner.raw_socket, &readfds)) { arp_packet_t packet; struct sockaddr_ll saddr; socklen_t saddr_len = sizeof(saddr); // 接收ARP数据包 ssize_t received = recvfrom(g_scanner.raw_socket, &packet, sizeof(packet), 0, (struct sockaddr *)&saddr, &saddr_len); if (received < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { continue; } perror("recvfrom"); continue; } // 检查接收到的数据包长度 if (received < (ssize_t)(sizeof(struct ethhdr) + sizeof(struct arphdr))) { // 数据包太短,不是有效的ARP包 continue; } // 验证以太网类型是否为ARP if (ntohs(packet.eth_header.h_proto) != ETH_P_ARP) { continue; } // 验证ARP硬件类型为以太网 if (ntohs(packet.arp_header.ar_hrd) != ARPHRD_ETHER) { continue; } // 验证ARP协议类型为IP if (ntohs(packet.arp_header.ar_pro) != ETH_P_IP) { continue; } // 检查是否是ARP回复 if (ntohs(packet.arp_header.ar_op) == ARPOP_REPLY) { // 提取发送者IP和MAC地址 uint32_t sender_ip; memcpy(&sender_ip, packet.sender_ip, 4); char mac_str[MAX_MAC_LEN]; mac_to_string(packet.sender_mac, mac_str); // 检查IP是否在扫描范围内 if (sender_ip >= g_scanner.config.start_ip && sender_ip <= g_scanner.config.end_ip) { // 添加到ARP条目表 arp_scanner_add_entry(sender_ip, mac_str); // 打印调试信息 char ip_str[MAX_IP_LEN]; int_to_ip(sender_ip, ip_str); printf("Received ARP reply from %s [%s]\n", ip_str, mac_str); } } } } return 0; } int arp_scanner_add_entry(uint32_t ip, const char *mac) { if (!mac) { return -1; } pthread_mutex_lock(&g_scanner.lock); time_t now = time(NULL); int found_index = -1; BOOL is_new_host = FALSE; // 检查是否已存在该IP的条目 for (int i = 0; i < g_scanner.entry_count; i++) { if (g_scanner.entries[i].ip == ip) { found_index = i; break; } } if (found_index >= 0) { // 更新现有条目 strncpy(g_scanner.entries[found_index].mac, mac, MAX_MAC_LEN - 1); g_scanner.entries[found_index].mac[MAX_MAC_LEN - 1] = '\0'; g_scanner.entries[found_index].last_seen = now; } else { // 添加新条目 if (g_scanner.entry_count < MAX_ARP_ENTRIES) { arp_entry_t *entry = &g_scanner.entries[g_scanner.entry_count]; entry->ip = ip; strncpy(entry->mac, mac, MAX_MAC_LEN - 1); entry->mac[MAX_MAC_LEN - 1] = '\0'; entry->last_seen = now; entry->first_seen = now; g_scanner.entry_count++; is_new_host = TRUE; } else { // ARP表已满,找到最旧的条目替换 time_t oldest_time = now; int oldest_index = 0; for (int i = 0; i < g_scanner.entry_count; i++) { if (g_scanner.entries[i].last_seen < oldest_time) { oldest_time = g_scanner.entries[i].last_seen; oldest_index = i; } } // 替换最旧的条目 arp_entry_t *entry = &g_scanner.entries[oldest_index]; entry->ip = ip; strncpy(entry->mac, mac, MAX_MAC_LEN - 1); entry->mac[MAX_MAC_LEN - 1] = '\0'; entry->last_seen = now; entry->first_seen = now; is_new_host = TRUE; } } pthread_mutex_unlock(&g_scanner.lock); // 如果是新发现的主机,打印到串口 if (is_new_host) { char ip_str[MAX_IP_LEN]; int_to_ip(ip, ip_str); printf("NEW HOST: IP=%s, MAC=%s\n", ip_str, mac); } return 0; } void arp_scanner_clean_old_entries(void) { pthread_mutex_lock(&g_scanner.lock); time_t now = time(NULL); int write_index = 0; for (int read_index = 0; read_index < g_scanner.entry_count; read_index++) { if (now - g_scanner.entries[read_index].last_seen <= g_scanner.config.validity_period) { // 条目未过期,保留 if (write_index != read_index) { g_scanner.entries[write_index] = g_scanner.entries[read_index]; } write_index++; } else { // 条目过期,打印日志 char ip_str[MAX_IP_LEN]; int_to_ip(g_scanner.entries[read_index].ip, ip_str); printf("EXPIRED: IP=%s, MAC=%s\n", ip_str, g_scanner.entries[read_index].mac); } } // 更新条目计数 int expired_count = g_scanner.entry_count - write_index; g_scanner.entry_count = write_index; pthread_mutex_unlock(&g_scanner.lock); if (expired_count > 0) { printf("Cleaned %d expired ARP entries\n", expired_count); } } int arp_scanner_remove_entry(uint32_t ip) { pthread_mutex_lock(&g_scanner.lock); int found_index = -1; // 查找要删除的条目 for (int i = 0; i < g_scanner.entry_count; i++) { if (g_scanner.entries[i].ip == ip) { found_index = i; break; } } if (found_index >= 0) { // 移动后续条目覆盖要删除的条目 for (int i = found_index; i < g_scanner.entry_count - 1; i++) { g_scanner.entries[i] = g_scanner.entries[i + 1]; } g_scanner.entry_count--; char ip_str[MAX_IP_LEN]; int_to_ip(ip, ip_str); printf("Removed ARP entry: %s\n", ip_str); } pthread_mutex_unlock(&g_scanner.lock); return (found_index >= 0) ? 0 : -1; } // 工具函数 uint32_t ip_to_int(const char *ip) { if (!ip) { return 0; } struct in_addr addr; if (inet_pton(AF_INET, ip, &addr) != 1) { fprintf(stderr, "Invalid IP address: %s\n", ip); return 0; } return addr.s_addr; } void int_to_ip(uint32_t ip_int, char *ip_str) { if (!ip_str) { return; } struct in_addr addr; addr.s_addr = ip_int; inet_ntop(AF_INET, &addr, ip_str, MAX_IP_LEN); } void mac_to_string(const unsigned char *mac, char *mac_str) { if (!mac || !mac_str) { return; } snprintf(mac_str, MAX_MAC_LEN, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); } 将上述文件的函数封装到int arpd_start_scan(struct _DS_HANDLE_CONTEXT *context, JSON_OBJPTR param) { // 创建响应JSON对象 context->res_obj = jso_new_obj(); if (NULL == context->res_obj) { DS_ERROR("Create new json object failed."); context->error_code = SLP_ESYSTEM; return ERROR; } // 关键修改:启动前先执行初始化 int init_result = arp_scanner_init(); if (init_result != 0) { jso_add_string(context->res_obj, "status", "error"); jso_add_string(context->res_obj, "message", "Scanner initialization failed"); return ERROR; } // 启动扫描 int start_result = arp_scanner_start(); if (start_result == 0) { jso_add_string(context->res_obj, "status", "success"); jso_add_string(context->res_obj, "message", "Scan started successfully"); // 添加扫描配置信息 pthread_mutex_lock(&g_scanner.lock); jso_add_bool(context->res_obj, "enabled", g_scanner.config.enabled); jso_add_int(context->res_obj, "scan_interval", g_scanner.config.scan_interval); jso_add_int(context->res_obj, "validity_period", g_scanner.config.validity_period); char start_ip_str[MAX_IP_LEN], end_ip_str[MAX_IP_LEN]; int_to_ip(g_scanner.config.start_ip, start_ip_str); int_to_ip(g_scanner.config.end_ip, end_ip_str); jso_add_string(context->res_obj, "start_ip", start_ip_str); jso_add_string(context->res_obj, "end_ip", end_ip_str); jso_add_string(context->res_obj, "interface", g_scanner.config.interface); pthread_mutex_unlock(&g_scanner.lock); } else { jso_add_string(context->res_obj, "status", "error"); jso_add_string(context->res_obj, "message", "Failed to start scan"); } return start_result; } // 停止扫描 // 停止扫描 int arpd_stop_scan(struct _DS_HANDLE_CONTEXT *context, JSON_OBJPTR param) { // 创建响应JSON对象 context->res_obj = jso_new_obj(); if (NULL == context->res_obj) { DS_ERROR("Create new json object failed."); context->error_code = SLP_ESYSTEM; return ERROR; } // 获取当前扫描状态 pthread_mutex_lock(&g_scanner.lock); BOOL was_scanning = g_scanner.scanning; int entry_count = g_scanner.entry_count; time_t last_scan_time = g_scanner.last_scan_time; pthread_mutex_unlock(&g_scanner.lock); // 执行停止操作 int stop_result = arp_scanner_stop(); // 构建响应 if (stop_result == 0) { jso_add_string(context->res_obj, "status", "success"); jso_add_string(context->res_obj, "action", was_scanning ? "Scan stopped" : "No active scan to stop"); // 添加扫描结果统计 jso_add_bool(context->res_obj, "was_scanning", was_scanning); jso_add_int(context->res_obj, "entry_count", entry_count); // 添加时间信息 char last_scan_str[32]; if (last_scan_time > 0) { format_timestamp(last_scan_time, last_scan_str); jso_add_string(context->res_obj, "last_scan_time", last_scan_str); } else { jso_add_string(context->res_obj, "last_scan_time", "Never scanned"); } // 添加配置信息 pthread_mutex_lock(&g_scanner.lock); jso_add_bool(context->res_obj, "enabled", g_scanner.config.enabled); jso_add_int(context->res_obj, "scan_interval", g_scanner.config.scan_interval); pthread_mutex_unlock(&g_scanner.lock); } else { jso_add_string(context->res_obj, "status", "error"); jso_add_string(context->res_obj, "message", "Failed to stop scan"); jso_add_int(context->res_obj, "error_code", stop_result); } return stop_result; }中,arpd_start_scan需要真正实现启动扫描并扫描的过程

时间: 2025-08-28 22:57:57 AIGC 浏览: 35
<think>我们需要在arpd_start_scan函数中真正启动扫描过程。根据之前的代码,扫描过程是在arp_scanner_scan函数中实现的,而arp_scanner_start函数只是设置了一些标志位,并没有真正执行扫描。 因此,我们需要在arpd_start_scan中调用arp_scanner_scan函数来执行扫描。但是,由于扫描过程可能会持续一段时间,我们不应该在HTTP请求处理线程中直接执行扫描(这会导致请求超时)。 正确的做法是:在arp_scanner_start中创建线程,然后在新的线程中执行扫描。这样,arpd_start_scan在调用arp_scanner_start后可以立即返回,而扫描任务在后台运行。 然而,观察现有的arp_scanner_start函数,它只是设置了标志位,并没有启动线程。而扫描函数arp_scanner_scan是一个阻塞函数,会执行整个扫描过程。 因此,我们需要重构: 1. 修改arp_scanner_start函数,使其创建一个线程,然后在该线程中调用arp_scanner_scan函数。 2. 确保arp_scanner_scan函数能够响应停止请求(通过g_scanner.stop_requested)。 但是,在现有的代码中,arp_scanner_scan函数已经包含了发送ARP请求和接收回复的过程,并且会检查g_scanner.stop_requested。所以,我们只需要将arp_scanner_scan放在一个线程中执行即可。 修改步骤: 1. 在arp_scanner_start中创建线程,线程函数为arp_scanner_scan_thread(我们新写一个函数,它内部调用arp_scanner_scan)。 2. 修改arp_scanner_scan函数,使其能够作为线程函数运行(目前它返回int,需要改为返回void*,并接受void*参数)。 3. 在arp_scanner_scan_thread中调用arp_scanner_scan,然后返回。 但是,由于arp_scanner_scan函数目前是阻塞执行整个扫描,我们也可以不改变它的返回值,而是用一个静态函数来包装。 另外,注意在arpd_start_scan中,我们调用了arp_scanner_init,这可能会重复初始化(因为init中创建了原始套接字和互斥锁)。我们需要考虑模块的初始化状态,避免重复初始化。 因此,我们还需要: 1. 在全局扫描器结构体中添加一个初始化标志,避免重复初始化。 2. 修改arp_scanner_init,使其在已经初始化的情况下直接返回成功。 考虑到时间,我们做如下调整: 方案A:不在arpd_start_scan中调用arp_scanner_init,而是要求模块在启动时已经初始化(比如在模块加载时初始化一次)。这样,arpd_start_scan只负责启动扫描。 方案B:在arpd_start_scan中检查是否初始化,如果没有则初始化。 根据现有代码,arp_scanner_init每次调用都会重新初始化g_scanner(包括创建原始套接字和互斥锁)。如果多次调用,会导致之前创建的套接字被关闭(因为重新memset为0,然后重新创建套接字,旧的套接字会泄漏),并且互斥锁也会被重新初始化(可能导致未定义行为)。 因此,我们需要一个全局的初始化标志,或者将初始化分为两部分:首次初始化和重复调用的处理。 这里,我们添加一个静态变量来记录初始化状态,或者修改g_scanner结构体,加入一个init_flag。 由于g_scanner是全局变量,我们可以在其中添加一个成员: BOOL initialized; 然后在arp_scanner_init中: if (g_scanner.initialized) { return 0; } ... 进行初始化 ... g_scanner.initialized = TRUE; 但是,我们目前的结构体定义中没有这个成员,所以需要修改结构体。 但是,由于问题要求封装到arpd_start_scan,并且不能改变已有结构体(题目没有说明是否可以改变),我们假设可以修改结构体。 如果无法修改结构体,我们可以使用一个静态变量。 这里,我们假设可以修改结构体,在arp_scanner_t中添加: BOOL initialized; 然后修改arp_scanner_init函数: if (g_scanner.initialized) { return 0; } ... 原来的初始化代码 ... g_scanner.initialized = TRUE; 另外,在清理函数arp_scanner_cleanup中,将initialized置为FALSE。 现在,我们按照以下步骤修改: 1. 修改结构体arp_scanner_t,添加成员:BOOL initialized; 2. 修改arp_scanner_init函数,避免重复初始化。 3. 创建一个新的线程函数,用于执行扫描。 4. 修改arp_scanner_start,使其创建线程并启动扫描线程。 5. 修改arp_scanner_scan函数,使其可以运行在独立的线程中(注意线程安全,尤其是停止请求的处理)。 但是,由于arp_scanner_scan函数目前是阻塞的,我们不需要改变它的内部,只需要在扫描线程中调用它。注意,在扫描线程中,我们不需要再循环扫描(因为扫描函数内部已经循环了),所以扫描线程只执行一次扫描。 另外,我们还需要考虑:扫描完成后,如何更新状态?在arp_scanner_scan函数中,扫描完成后会更新last_scan_time,并清理过期条目。所以,我们不需要额外处理。 新线程函数: static void* arp_scan_thread(void *arg) { // 调用扫描函数 arp_scanner_scan(); return NULL; } 然后,在arp_scanner_start中创建这个线程。 但是,注意arp_scanner_scan函数目前返回int,而且没有参数。我们可以保持它的原型不变,因为线程函数可以忽略返回值。 但是,pthread_create要求线程函数的签名是void* (*)(void*),所以我们需要一个符合签名的函数: static void* arp_scan_thread_wrapper(void *arg) { (void)arg; arp_scanner_scan(); return NULL; } 然后,在arp_scanner_start中: // 检查是否已经在扫描 if (g_scanner.scanning) { return ERROR_BUSY; } // 设置扫描状态 g_scanner.scanning = TRUE; g_scanner.stop_requested = FALSE; // 确保停止标志为假 // 创建线程 int ret = pthread_create(&g_scanner.scan_thread, NULL, arp_scan_thread_wrapper, NULL); if (ret != 0) { g_scanner.scanning = FALSE; return ERROR_THREAD; } return 0; 这样,扫描就会在后台线程中运行。 但是,注意arp_scanner_scan函数中会操作全局结构体,需要加锁的地方已经加了锁(比如在添加条目时)。另外,在扫描过程中,停止请求是通过g_scanner.stop_requested来控制的,我们通过arp_scanner_stop函数设置该标志,扫描循环中会检查。 因此,我们需要修改arp_scanner_stop函数,它目前只是设置标志位,但是并没有等待线程结束。所以,我们还需要一个停止函数来等待线程结束(比如在清理函数中等待)。 不过,在arpd_stop_scan中,我们只需要设置标志位,然后返回。扫描线程会在检测到标志位后退出。但是,我们无法立即知道线程何时结束。所以,在arpd_stop_scan中,我们设置标志位,然后返回,同时可以在响应中说明扫描正在停止。 如果用户需要知道扫描状态,可以设计另一个查询接口。 现在,我们修改arp_scanner_start函数,使其创建线程。同时,将arp_scanner_scan函数改为非阻塞方式(通过线程)。 但是,在arpd_start_scan中,我们调用了arp_scanner_start,它会立即返回,然后我们返回成功。这样,HTTP请求会立即返回,而扫描在后台运行。 因此,我们需要修改arpd_start_scan函数: int arpd_start_scan(struct _DS_HANDLE_CONTEXT *context, JSON_OBJPTR param) { // ... 创建响应对象 ... // 检查并初始化 if (!g_scanner.initialized) { if (arp_scanner_init() != 0) { // 错误处理 } } // 启动扫描(会启动线程) int start_result = arp_scanner_start(); // 根据start_result构建响应 // ... return start_result; } 注意:arp_scanner_start现在可能会返回错误(比如已经扫描中,或者线程创建失败)。 另外,我们还需要修改arp_scanner_scan函数,在扫描完成后将g_scanner.scanning设置为FALSE。因为扫描线程结束时,扫描就结束了。目前,在arp_scanner_scan函数中,扫描完成后并没有设置scanning为FALSE。所以,我们需要在arp_scanner_scan函数的最后加上: pthread_mutex_lock(&g_scanner.lock); g_scanner.scanning = FALSE; pthread_mutex_unlock(&g_scanner.lock); 这样,当扫描线程退出后,扫描状态就会更新。 但是,注意在扫描过程中,我们可能因为停止请求而提前退出,同样需要在退出前设置scanning为FALSE。 在arp_scanner_scan函数中,我们有一个循环,当遇到停止请求时会退出。在循环之后,我们应该设置scanning为FALSE。 所以,在arp_scanner_scan函数中,在return之前: // 扫描结束,更新状态 pthread_mutex_lock(&g_scanner.lock); g_scanner.scanning = FALSE; pthread_mutex_unlock(&g_scanner.lock); 这样,无论是正常完成还是被停止,扫描状态都会更新。 由于时间关系,我们只修改关键部分。 总结修改点: 1. 在arp_scanner_t结构体中添加:BOOL initialized; 2. 修改arp_scanner_init函数,避免重复初始化。 3. 编写线程包装函数:arp_scan_thread_wrapper,在其中调用arp_scanner_scan。 4. 修改arp_scanner_start函数,创建线程并启动扫描。 5. 在arp_scanner_scan函数的最后(所有返回路径),设置scanning为FALSE(注意加锁)。 6. 在arpd_start_scan中,调用arp_scanner_init和arp_scanner_start。 但是,注意arp_scanner_scan函数有多处返回,我们需要确保在所有返回路径上都设置了scanning为FALSE。我们可以使用goto或者一个清理代码块,但为了清晰,我们使用一个do{}while(0)块,并在末尾设置状态,然后在错误时提前返回。 修改arp_scanner_scan函数: int arp_scanner_scan(void) { // ... 原来的代码 ... // 在函数末尾,无论成功还是失败,都设置扫描状态为FALSE pthread_mutex_lock(&g_scanner.lock); g_scanner.scanning = FALSE; pthread_mutex_unlock(&g_scanner.lock); return 0; } 但是,注意在扫描过程中,如果用户调用了停止,我们设置了stop_requested,然后循环会退出,然后执行到末尾,设置scanning为FALSE。这符合预期。 另外,在扫描过程中,如果发生错误(比如绑定失败),我们也会提前返回,并设置scanning为FALSE。 现在,我们重新实现arp_scanner_start函数: S32 arp_scanner_start(void) { pthread_mutex_lock(&g_scanner.lock); // 检查是否已经在扫描 if (g_scanner.scanning) { pthread_mutex_unlock(&g_scanner.lock); return ERROR_BUSY; } // 设置状态标志 g_scanner.scanning = TRUE; g_scanner.stop_requested = FALSE; // 重置停止标志 // 创建线程 int ret = pthread_create(&g_scanner.scan_thread, NULL, arp_scan_thread_wrapper, NULL); if (ret != 0) { g_scanner.scanning = FALSE; // 创建线程失败,恢复状态 pthread_mutex_unlock(&g_scanner.lock); return ERROR_THREAD; } pthread_mutex_unlock(&g_scanner.lock); return 0; } 然后,我们实现线程包装函数: static void* arp_scan_thread_wrapper(void *arg) { // 执行扫描 arp_scanner_scan(); return NULL; } 注意:这个线程包装函数应该是静态的,或者只在当前文件中可见。因此,我们在.c文件中定义它,并加上static。 最后,修改arpd_start_scan函数,确保在调用arp_scanner_start之前已经初始化。 由于修改涉及多个文件,我们只给出关键修改。 由于问题要求封装到arpd_start_scan中,并且要真正启动扫描,我们按照上述方案修改。 但是,由于原始代码中arp_scanner_scan函数是阻塞的,现在放到线程中,所以arp_scanner_start会立即返回,这样arpd_start_scan也会立即返回,而扫描在后台进行。 这样,用户调用启动接口后,会立即得到响应,而扫描任务在后台运行。 因此,我们在响应中返回“扫描已启动”,而不是等待扫描完成。 现在,我们修改arpd_start_scan函数: int arpd_start_scan(struct _DS_HANDLE_CONTEXT *context, JSON_OBJPTR param) { // 创建响应JSON对象 context->res_obj = jso_new_obj(); if (NULL == context->res_obj) { DS_ERROR("Create new json object failed."); context->error_code = SLP_ESYSTEM; return ERROR; } // 检查是否已经初始化 pthread_mutex_lock(&g_scanner.lock); if (!g_scanner.initialized) { pthread_mutex_unlock(&g_scanner.lock); // 注意:arp_scanner_init内部会加锁,所以这里先解锁,然后调用初始化 int init_result = arp_scanner_init(); if (init_result != 0) { jso_add_string(context->res_obj, "status", "error"); jso_add_string(context->res_obj, "message", "Scanner initialization failed"); return ERROR; } } else { pthread_mutex_unlock(&g_scanner.lock); } // 启动扫描 int start_result = arp_scanner_start(); if (start_result == 0) { jso_add_string(context->res_obj, "status", "success"); jso_add_string(context->res_obj, "message", "Scan started successfully"); // 添加扫描配置信息(加锁读取) pthread_mutex_lock(&g_scanner.lock); jso_add_bool(context->res_obj, "enabled", g_scanner.config.enabled); jso_add_int(context->res_obj, "scan_interval", g_scanner.config.scan_interval); jso_add_int(context->res_obj, "validity_period", g_scanner.config.validity_period); char start_ip_str[MAX_IP_LEN], end_ip_str[MAX_IP_LEN]; int_to_ip(g_scanner.config.start_ip, start_ip_str); int_to_ip(g_scanner.config.end_ip, end_ip_str); jso_add_string(context->res_obj, "start_ip", start_ip_str); jso_add_string(context->res_obj, "end_ip", end_ip_str); jso_add_string(context->res_obj, "interface", g_scanner.config.interface); pthread_mutex_unlock(&g_scanner.lock); } else { jso_add_string(context->res_obj, "status", "error"); jso_add_string(context->res_obj, "message", "Failed to start scan"); // 可以根据错误码添加更详细的信息 if (start_result == ERROR_BUSY) { jso_add_string(context->res_obj, "detail", "Scanner is already running"); } else if (start_result == ERROR_THREAD) { jso_add_string(context->res_obj, "detail", "Failed to create scan thread"); } } return start_result; } 注意:在检查初始化时,我们加锁后判断,然后解锁,再调用初始化函数(因为初始化函数内部会加锁)。这样可以避免死锁。 由于arp_scanner_init函数内部会加锁,所以我们在调用它之前必须解锁。 最后,我们还需要在arp_scanner_scan函数的末尾(无论成功还是失败)设置scanning为FALSE,并更新last_scan_time(已经在函数中更新)。 但是,注意在扫描过程中,如果出现错误,我们可能没有更新last_scan_time。不过,在arp_scanner_scan函数中,我们只有在成功发送请求并接收回复后才更新last_scan_time。这取决于需求。 由于时间关系,我们只实现基本功能。 以上修改实现了在后台线程中执行扫描,使得arpd_start_scan可以立即返回。 注意:由于我们添加了initialized成员,需要在arp_scanner_init中设置: g_scanner.initialized = TRUE; 在arp_scanner_cleanup中设置: g_scanner.initialized = FALSE; 这样,下次启动扫描时,如果已经清理,则需要重新初始化。 由于原始代码中没有提供arp_scanner_cleanup的调用位置,我们假设在模块卸载时会调用。 现在,我们给出修改后的关键函数代码(伪代码,仅展示修改部分)。 由于修改点较多,请根据实际情况调整。</think>根据提供的代码,`arpd_start_scan` 函数需要真正实现启动扫描过程,而不仅仅是设置标志位。以下是完整的实现方案,包含必要的修改和优化: ### 关键修改点 1. **启动真正的扫描线程**: - 创建后台线程执行扫描任务 - 使用线程安全的方式管理扫描状态 2. **解决初始化问题**: - 避免重复初始化 - 确保资源正确创建 3. **增强错误处理**: - 添加详细的错误信息 - 处理各种失败场景 ### 完整实现代码 ```c // 全局扫描线程函数 static void* arp_scan_thread(void *arg) { // 执行扫描操作 int ret = arp_scanner_scan(); // 更新扫描状态 pthread_mutex_lock(&g_scanner.lock); g_scanner.scanning = (ret == 0); // 只有成功完成才保持扫描状态 pthread_mutex_unlock(&g_scanner.lock); return NULL; } int arpd_start_scan(struct _DS_HANDLE_CONTEXT *context, JSON_OBJPTR param) { // 创建响应JSON对象 context->res_obj = jso_new_obj(); if (NULL == context->res_obj) { DS_ERROR("Create new json object failed."); context->error_code = SLP_ESYSTEM; return ERROR; } // 关键修改1:避免重复初始化 pthread_mutex_lock(&g_scanner.lock); BOOL needs_init = (g_scanner.raw_socket < 0); pthread_mutex_unlock(&g_scanner.lock); if (needs_init) { int init_result = arp_scanner_init(); if (init_result != 0) { jso_add_string(context->res_obj, "status", "error"); jso_add_string(context->res_obj, "message", "Scanner initialization failed"); jso_add_int(context->res_obj, "error_code", init_result); return ERROR; } } // 关键修改2:检查扫描状态 pthread_mutex_lock(&g_scanner.lock); if (g_scanner.scanning) { pthread_mutex_unlock(&g_scanner.lock); jso_add_string(context->res_obj, "status", "error"); jso_add_string(context->res_obj, "message", "Scan already in progress"); return ERROR_BUSY; } // 关键修改3:启动真正的扫描线程 g_scanner.scanning = TRUE; g_scanner.stop_requested = FALSE; int ret = pthread_create(&g_scanner.scan_thread, NULL, arp_scan_thread, NULL); pthread_mutex_unlock(&g_scanner.lock); if (ret != 0) { jso_add_string(context->res_obj, "status", "error"); jso_add_string(context->res_obj, "message", "Failed to create scan thread"); jso_add_int(context->res_obj, "error_code", ret); return ERROR_THREAD; } // 成功响应 jso_add_string(context->res_obj, "status", "success"); jso_add_string(context->res_obj, "message", "Scan started successfully"); // 添加扫描配置信息 pthread_mutex_lock(&g_scanner.lock); jso_add_bool(context->res_obj, "enabled", g_scanner.config.enabled); jso_add_int(context->res_obj, "scan_interval", g_scanner.config.scan_interval); jso_add_int(context->res_obj, "validity_period", g_scanner.config.validity_period); char start_ip_str[MAX_IP_LEN], end_ip_str[MAX_IP_LEN]; int_to_ip(g_scanner.config.start_ip, start_ip_str); int_to_ip(g_scanner.config.end_ip, end_ip_str); jso_add_string(context->res_obj, "start_ip", start_ip_str); jso_add_string(context->res_obj, "end_ip", end_ip_str); jso_add_string(context->res_obj, "interface", g_scanner.config.interface); // 添加当前状态 jso_add_bool(context->res_obj, "is_scanning", g_scanner.scanning); jso_add_int(context->res_obj, "current_entry_count", g_scanner.entry_count); pthread_mutex_unlock(&g_scanner.lock); return OK; } ``` ### 需要修复的扫描函数 在 `arp_scanner_scan()` 函数中,需要添加线程安全处理和状态更新: ```c int arp_scanner_scan(void) { if (!g_scanner.config.enabled) { return -1; } // 确保套接字有效 if (g_scanner.raw_socket < 0) { return -1; } struct ifreq ifr; strcpy(ifr.ifr_name, g_scanner.config.interface); // 获取接口索引 if (ioctl(g_scanner.raw_socket, SIOCGIFINDEX, &ifr) < 0) { perror("ioctl"); return -1; } // 绑定到接口 struct sockaddr_ll saddr; memset(&saddr, 0, sizeof(saddr)); saddr.sll_family = AF_PACKET; saddr.sll_ifindex = ifr.ifr_ifindex; saddr.sll_protocol = htons(ETH_P_ARP); if (bind(g_scanner.raw_socket, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { perror("bind"); return -1; } // 发送ARP请求 for (uint32_t ip = g_scanner.config.start_ip; ip <= g_scanner.config.end_ip; ip++) { // 检查停止请求 pthread_mutex_lock(&g_scanner.lock); BOOL should_stop = g_scanner.stop_requested; pthread_mutex_unlock(&g_scanner.lock); if (should_stop) { break; } // 发送请求 if (arp_scanner_send_arp_request(ip) != 0) { // 发送失败时跳过 continue; } // 处理回复 arp_scanner_process_reply(); // 按配置间隔等待 usleep(g_scanner.config.packet_interval * 1000); } // 清理过期条目 arp_scanner_clean_old_entries(); // 更新最后扫描时间 pthread_mutex_lock(&g_scanner.lock); g_scanner.last_scan_time = time(NULL); pthread_mutex_unlock(&g_scanner.lock); return 0; } ``` ### 停止扫描的改进实现 ```c int arpd_stop_scan(struct _DS_HANDLE_CONTEXT *context, JSON_OBJPTR param) { // 创建响应JSON对象 context->res_obj = jso_new_obj(); if (NULL == context->res_obj) { DS_ERROR("Create new json object failed."); context->error_code = SLP_ESYSTEM; return ERROR; } // 获取当前扫描状态 pthread_mutex_lock(&g_scanner.lock); BOOL was_scanning = g_scanner.scanning; int entry_count = g_scanner.entry_count; time_t last_scan_time = g_scanner.last_scan_time; pthread_mutex_unlock(&g_scanner.lock); // 执行停止操作 int stop_result = arp_scanner_stop(); // 构建响应 if (stop_result == 0) { jso_add_string(context->res_obj, "status", "success"); jso_add_string(context->res_obj, "action", was_scanning ? "Scan stopped" : "No active scan to stop"); // 添加扫描结果统计 jso_add_bool(context->res_obj, "was_scanning", was_scanning); jso_add_int(context->res_obj, "entry_count", entry_count); // 添加时间信息 char last_scan_str[32]; if (last_scan_time > 0) { format_timestamp(last_scan_time, last_scan_str); jso_add_string(context->res_obj, "last_scan_time", last_scan_str); } else { jso_add_string(context->res_obj, "last_scan_time", "Never scanned"); } // 添加配置信息 pthread_mutex_lock(&g_scanner.lock); jso_add_bool(context->res_obj, "enabled", g_scanner.config.enabled); jso_add_int(context->res_obj, "scan_interval", g_scanner.config.scan_interval); pthread_mutex_unlock(&g_scanner.lock); } else { jso_add_string(context->res_obj, "status", "error"); jso_add_string(context->res_obj, "message", "Failed to stop scan"); jso_add_int(context->res_obj, "error_code", stop_result); } return stop_result; } // 改进的停止函数 int arp_scanner_stop(void) { pthread_mutex_lock(&g_scanner.lock); if (!g_scanner.scanning) { pthread_mutex_unlock(&g_scanner.lock); return ERROR_NOT_RUNNING; } // 设置停止标志 g_scanner.stop_requested = TRUE; // 等待线程结束(带超时) struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); ts.tv_sec += 5; // 5秒超时 int ret = pthread_timedjoin_np(g_scanner.scan_thread, NULL, &ts); if (ret == ETIMEDOUT) { // 超时处理:取消线程 pthread_cancel(g_scanner.scan_thread); } // 更新状态 g_scanner.scanning = FALSE; g_scanner.stop_requested = FALSE; pthread_mutex_unlock(&g_scanner.lock); return OK; } ``` ### 需要添加的辅助函数 ```c // 时间戳格式化函数 void format_timestamp(time_t timestamp, char *buffer) { if (!buffer) return; struct tm *timeinfo = localtime(&timestamp); strftime(buffer, 32, "%Y-%m-%d %H:%M:%S", timeinfo); } // IP地址转换函数 uint32_t ip_to_int(const char *ip) { if (!ip) return 0; struct in_addr addr; if (inet_pton(AF_INET, ip, &addr) != 1) { return 0; } return addr.s_addr; } void int_to_ip(uint32_t ip_int, char *ip_str) { if (!ip_str) return; struct in_addr addr; addr.s_addr = ip_int; inet_ntop(AF_INET, &addr, ip_str, MAX_IP_LEN); } ``` ### 关键优化点 1. **线程安全管理**: - 所有对全局变量的访问都需要加锁 - 使用 `pthread_mutex_trylock()` 避免死锁 2. **资源生命周期**: - 套接字在扫描线程中创建和关闭 - 避免在多个地方重复创建套接字 3. **错误恢复机制**: - 添加网络接口状态监控 - 实现自动重连机制 4. **性能优化**: - 使用批处理发送ARP请求 - 添加发送速率控制 5. **日志系统**: - 替换 `printf/fprintf` 为正式日志接口 - 添加不同级别的日志输出 ### 注意事项 1. **权限问题**: - 原始套接字需要 `CAP_NET_RAW` 权限 - 考虑在启动脚本中设置权限 2. **内存安全**: - 所有字符串操作使用安全版本(`strncpy` 等) - 添加缓冲区溢出检查 3. **跨平台兼容性**: - `pthread_timedjoin_np` 是GNU扩展,可替换为更通用的实现 - 使用 `clock_gettime` 替代平台特定函数
阅读全文

相关推荐

int arpd_get_scan_result(struct _DS_HANDLE_CONTEXT *context, JSON_OBJPTR param) { pthread_mutex_lock(&g_scanner.lock); // 创建根JSON对象 context->res_obj = jso_new_obj(); if (NULL == context->res_obj) { DS_ERROR("Create new json object failed."); pthread_mutex_unlock(&g_scanner.lock); context->error_code = SLP_ESYSTEM; return ERROR; } // 创建存储条目的JSON数组 JSON_OBJPTR entries_array = jso_new_array(); if (NULL == entries_array) { DS_ERROR("Create entries array failed."); pthread_mutex_unlock(&g_scanner.lock); context->error_code = SLP_ESYSTEM; return ERROR; } jso_add_item(context->res_obj, "entries", entries_array); // 遍历扫描结果并转换为JSON对象 for (int i = 0; i < g_scanner.entry_count; i++) { char ip_str[MAX_IP_LEN]; char first_seen_str[32]; char last_seen_str[32]; int_to_ip(g_scanner.entries[i].ip, ip_str); format_timestamp(g_scanner.entries[i].first_seen, first_seen_str); format_timestamp(g_scanner.entries[i].last_seen, last_seen_str); // 创建单条目的JSON对象 JSON_OBJPTR entry_obj = jso_new_obj(); if (entry_obj) { jso_add_string(entry_obj, "ip", ip_str); jso_add_string(entry_obj, "mac", g_scanner.entries[i].mac); jso_add_string(entry_obj, "first_seen", first_seen_str); jso_add_string(entry_obj, "last_seen", last_seen_str); jso_add_item(entries_array, NULL, entry_obj); // 添加到数组 } } // 添加统计信息 jso_add_int(context->res_obj, "total_entries", g_scanner.entry_count); char last_scan_time[32]; format_timestamp(g_scanner.last_scan_time, last_scan_time); jso_add_string(context->res_obj, "last_scan_time", last_scan_time); pthread_mutex_unlock(&g_scanner.lock); return 0; } 将这个arpd_start_scan函数里面加上下面这个文件中的init,相当于arpd_start是一个开关#include "arp_scanner.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <net/if.h> #include <sys/ioctl.h> #include #include <time.h> #include <errno.h> #include "json_api.h" // 加载配置 int load_config(arp_config_t *config) { if (config == NULL) { fprintf(stderr, "错误: 配置指针为空\n"); return -1; } // 使用ds_read读取配置 ds_read(ARPD_CONFIG_PATH, config, sizeof(arp_config_t)); return 0; } S32 arp_scanner_init() { memset(&g_scanner, 0, sizeof(arp_scanner_t)); // 创建原始套接字 g_scanner.raw_socket = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP)); if (g_scanner.raw_socket < 0) { perror("socket"); return -1; } // 初始化互斥锁 if (pthread_mutex_init(&g_scanner.lock, NULL) != 0) { close(g_scanner.raw_socket); return -1; } // 从配置文件加载配置 if (load_config(&g_scanner.config) != 0) { // 加载失败时使用默认值 g_scanner.config.enabled = FALSE; g_scanner.config.scan_interval = 60; g_scanner.config.validity_period = 300; g_scanner.config.packet_interval = 100; g_scanner.config.start_ip = ip_to_int("192.168.1.100"); g_scanner.config.end_ip = ip_to_int("192.168.1.200"); // 默认网络接口 strcpy(g_scanner.config.interface, "eth0"); fprintf(stderr, "Using default configuration\n"); } return 0; } S32 arp_scanner_start(void) { pthread_mutex_lock(&g_scanner.lock); g_scanner.scanning = TRUE; g_scanner.stop_requested = FALSE; pthread_mutex_unlock(&g_scanner.lock); return 0; } int arp_scanner_stop(void) { pthread_mutex_lock(&g_scanner.lock); g_scanner.stop_requested = TRUE; pthread_mutex_unlock(&g_scanner.lock); return 0; } int arp_scanner_cleanup(void) { arp_scanner_stop(); if (g_scanner.raw_socket >= 0) { close(g_scanner.raw_socket); } pthread_mutex_destroy(&g_scanner.lock); return 0; } int arp_scanner_scan(void) { if (!g_scanner.config.enabled) return -1; struct ifreq ifr; strcpy(ifr.ifr_name, g_scanner.config.interface); // 获取接口索引 if (ioctl(g_scanner.raw_socket, SIOCGIFINDEX, &ifr) < 0) { perror("ioctl"); return -1; } // 绑定到接口 struct sockaddr_ll saddr; memset(&saddr, 0, sizeof(saddr)); saddr.sll_family = AF_PACKET; saddr.sll_ifindex = ifr.ifr_ifindex; saddr.sll_protocol = htons(ETH_P_ARP); if (bind(g_scanner.raw_socket, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { perror("bind"); return -1; } // 发送ARP请求 for (uint32_t ip = g_scanner.config.start_ip; ip <= g_scanner.config.end_ip && !g_scanner.stop_requested; ip++) { arp_scanner_send_arp_request(ip); usleep(g_scanner.config.packet_interval * 1000); } // 处理ARP回复 arp_scanner_process_reply(); // 清理过期条目 arp_scanner_clean_old_entries(); g_scanner.last_scan_time = time(NULL); return 0; } int arp_scanner_send_arp_request(uint32_t target_ip) { struct ifreq ifr; strcpy(ifr.ifr_name, g_scanner.config.interface); // 获取接口MAC地址 if (ioctl(g_scanner.raw_socket, SIOCGIFHWADDR, &ifr) < 0) { perror("ioctl"); return -1; } unsigned char *src_mac = (unsigned char *)ifr.ifr_hwaddr.sa_data; // 获取接口IP地址 if (ioctl(g_scanner.raw_socket, SIOCGIFADDR, &ifr) < 0) { perror("ioctl"); return -1; } struct sockaddr_in *ipaddr = (struct sockaddr_in *)&ifr.ifr_addr; uint32_t src_ip = ipaddr->sin_addr.s_addr; // 构建ARP请求包 arp_packet_t packet; // 以太网头部 memset(packet.eth_header.h_dest, 0xFF, 6); // 广播地址 memcpy(packet.eth_header.h_source, src_mac, 6); packet.eth_header.h_proto = htons(ETH_P_ARP); // ARP头部 packet.arp_header.ar_hrd = htons(ARPHRD_ETHER); packet.arp_header.ar_pro = htons(ETH_P_IP); packet.arp_header.ar_hln = 6; packet.arp_header.ar_pln = 4; packet.arp_header.ar_op = htons(ARPOP_REQUEST); memcpy(packet.sender_mac, src_mac, 6); memcpy(packet.sender_ip, &src_ip, 4); memset(packet.target_mac, 0, 6); memcpy(packet.target_ip, &target_ip, 4); // 发送包 struct sockaddr_ll dest; memset(&dest, 0, sizeof(dest)); dest.sll_family = AF_PACKET; dest.sll_ifindex = ifr.ifr_ifindex; dest.sll_halen = ETH_ALEN; memset(dest.sll_addr, 0xFF, ETH_ALEN); ssize_t sent = sendto(g_scanner.raw_socket, &packet, sizeof(packet), 0, (struct sockaddr *)&dest, sizeof(dest)); return (sent == sizeof(packet)) ? 0 : -1; } int arp_scanner_process_reply(void) { fd_set readfds; struct timeval tv; int ret; int max_fd = g_scanner.raw_socket; // 设置超时时间为2秒,用于等待ARP回复 tv.tv_sec = 2; tv.tv_usec = 0; // 循环处理所有可用的ARP回复 while (1) { FD_ZERO(&readfds); FD_SET(g_scanner.raw_socket, &readfds); ret = select(max_fd + 1, &readfds, NULL, NULL, &tv); if (ret < 0) { if (errno == EINTR) { // 被信号中断,继续等待 continue; } perror("select"); break; } else if (ret == 0) { // 超时,没有更多数据 break; } if (FD_ISSET(g_scanner.raw_socket, &readfds)) { arp_packet_t packet; struct sockaddr_ll saddr; socklen_t saddr_len = sizeof(saddr); // 接收ARP数据包 ssize_t received = recvfrom(g_scanner.raw_socket, &packet, sizeof(packet), 0, (struct sockaddr *)&saddr, &saddr_len); if (received < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { continue; } perror("recvfrom"); continue; } // 检查接收到的数据包长度 if (received < (ssize_t)(sizeof(struct ethhdr) + sizeof(struct arphdr))) { // 数据包太短,不是有效的ARP包 continue; } // 验证以太网类型是否为ARP if (ntohs(packet.eth_header.h_proto) != ETH_P_ARP) { continue; } // 验证ARP硬件类型为以太网 if (ntohs(packet.arp_header.ar_hrd) != ARPHRD_ETHER) { continue; } // 验证ARP协议类型为IP if (ntohs(packet.arp_header.ar_pro) != ETH_P_IP) { continue; } // 检查是否是ARP回复 if (ntohs(packet.arp_header.ar_op) == ARPOP_REPLY) { // 提取发送者IP和MAC地址 uint32_t sender_ip; memcpy(&sender_ip, packet.sender_ip, 4); char mac_str[MAX_MAC_LEN]; mac_to_string(packet.sender_mac, mac_str); // 检查IP是否在扫描范围内 if (sender_ip >= g_scanner.config.start_ip && sender_ip <= g_scanner.config.end_ip) { // 添加到ARP条目表 arp_scanner_add_entry(sender_ip, mac_str); // 打印调试信息 char ip_str[MAX_IP_LEN]; int_to_ip(sender_ip, ip_str); printf("Received ARP reply from %s [%s]\n", ip_str, mac_str); } } } } return 0; } int arp_scanner_add_entry(uint32_t ip, const char *mac) { if (!mac) { return -1; } pthread_mutex_lock(&g_scanner.lock); time_t now = time(NULL); int found_index = -1; BOOL is_new_host = FALSE; // 检查是否已存在该IP的条目 for (int i = 0; i < g_scanner.entry_count; i++) { if (g_scanner.entries[i].ip == ip) { found_index = i; break; } } if (found_index >= 0) { // 更新现有条目 strncpy(g_scanner.entries[found_index].mac, mac, MAX_MAC_LEN - 1); g_scanner.entries[found_index].mac[MAX_MAC_LEN - 1] = '\0'; g_scanner.entries[found_index].last_seen = now; } else { // 添加新条目 if (g_scanner.entry_count < MAX_ARP_ENTRIES) { arp_entry_t *entry = &g_scanner.entries[g_scanner.entry_count]; entry->ip = ip; strncpy(entry->mac, mac, MAX_MAC_LEN - 1); entry->mac[MAX_MAC_LEN - 1] = '\0'; entry->last_seen = now; entry->first_seen = now; g_scanner.entry_count++; is_new_host = TRUE; } else { // ARP表已满,找到最旧的条目替换 time_t oldest_time = now; int oldest_index = 0; for (int i = 0; i < g_scanner.entry_count; i++) { if (g_scanner.entries[i].last_seen < oldest_time) { oldest_time = g_scanner.entries[i].last_seen; oldest_index = i; } } // 替换最旧的条目 arp_entry_t *entry = &g_scanner.entries[oldest_index]; entry->ip = ip; strncpy(entry->mac, mac, MAX_MAC_LEN - 1); entry->mac[MAX_MAC_LEN - 1] = '\0'; entry->last_seen = now; entry->first_seen = now; is_new_host = TRUE; } } pthread_mutex_unlock(&g_scanner.lock); // 如果是新发现的主机,打印到串口 if (is_new_host) { char ip_str[MAX_IP_LEN]; int_to_ip(ip, ip_str); printf("NEW HOST: IP=%s, MAC=%s\n", ip_str, mac); } return 0; } void arp_scanner_clean_old_entries(void) { pthread_mutex_lock(&g_scanner.lock); time_t now = time(NULL); int write_index = 0; for (int read_index = 0; read_index < g_scanner.entry_count; read_index++) { if (now - g_scanner.entries[read_index].last_seen <= g_scanner.config.validity_period) { // 条目未过期,保留 if (write_index != read_index) { g_scanner.entries[write_index] = g_scanner.entries[read_index]; } write_index++; } else { // 条目过期,打印日志 char ip_str[MAX_IP_LEN]; int_to_ip(g_scanner.entries[read_index].ip, ip_str); printf("EXPIRED: IP=%s, MAC=%s\n", ip_str, g_scanner.entries[read_index].mac); } } // 更新条目计数 int expired_count = g_scanner.entry_count - write_index; g_scanner.entry_count = write_index; pthread_mutex_unlock(&g_scanner.lock); if (expired_count > 0) { printf("Cleaned %d expired ARP entries\n", expired_count); } } void arp_scanner_print_results(void) { pthread_mutex_lock(&g_scanner.lock); printf("\n=== ARP Scan Results ===\n"); printf("Total hosts: %d\n", g_scanner.entry_count); printf("Last scan: %s", ctime(&g_scanner.last_scan_time)); printf("-----------------------------------------------\n"); printf("IP Address\t\tMAC Address\t\tFirst Seen\t\tLast Seen\n"); printf("-----------------------------------------------\n"); for (int i = 0; i < g_scanner.entry_count; i++) { char ip_str[MAX_IP_LEN]; int_to_ip(g_scanner.entries[i].ip, ip_str); char first_seen_str[64]; char last_seen_str[64]; struct tm *tm_info; tm_info = localtime(&g_scanner.entries[i].first_seen); strftime(first_seen_str, sizeof(first_seen_str), "%Y-%m-%d %H:%M:%S", tm_info); tm_info = localtime(&g_scanner.entries[i].last_seen); strftime(last_seen_str, sizeof(last_seen_str), "%Y-%m-%d %H:%M:%S", tm_info); printf("%-15s\t%s\t%s\t%s\n", ip_str, g_scanner.entries[i].mac, first_seen_str, last_seen_str); } printf("-----------------------------------------------\n"); pthread_mutex_unlock(&g_scanner.lock); } int arp_scanner_remove_entry(uint32_t ip) { pthread_mutex_lock(&g_scanner.lock); int found_index = -1; // 查找要删除的条目 for (int i = 0; i < g_scanner.entry_count; i++) { if (g_scanner.entries[i].ip == ip) { found_index = i; break; } } if (found_index >= 0) { // 移动后续条目覆盖要删除的条目 for (int i = found_index; i < g_scanner.entry_count - 1; i++) { g_scanner.entries[i] = g_scanner.entries[i + 1]; } g_scanner.entry_count--; char ip_str[MAX_IP_LEN]; int_to_ip(ip, ip_str); printf("Removed ARP entry: %s\n", ip_str); } pthread_mutex_unlock(&g_scanner.lock); return (found_index >= 0) ? 0 : -1; } // 工具函数 uint32_t ip_to_int(const char *ip) { if (!ip) { return 0; } struct in_addr addr; if (inet_pton(AF_INET, ip, &addr) != 1) { fprintf(stderr, "Invalid IP address: %s\n", ip); return 0; } return addr.s_addr; } void int_to_ip(uint32_t ip_int, char *ip_str) { if (!ip_str) { return; } struct in_addr addr; addr.s_addr = ip_int; inet_ntop(AF_INET, &addr, ip_str, MAX_IP_LEN); } void mac_to_string(const unsigned char *mac, char *mac_str) { if (!mac || !mac_str) { return; } snprintf(mac_str, MAX_MAC_LEN, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); }

在以下代码中,我想在线程拉起来之后再设置scanner.scanning=SCANNING_OFF,应该怎么做呢:#include "arp.h" #include "arp_scanner.h" #include "arp_config.h" #include <stdlib.h> #include <stdio.h> #include <string.h> #include <unistd.h> /* 静态全局变量初始化 */ static arp_scanner_t scanner = { .entries = NULL , .scanning = SCANNING_OFF, .sockfd = -1, }; /* 扫描器初始化 */ /* * fn static void load_default_config(arp_scanner_t *scanner) * brief 导入默认配置参数 * details None * * param[in] None * param[out]None * return None * * retval None * note None */ static int load_default_config(arp_scanner_t *scanner) { scanner->config.enable = DEFAULT_ENABLE; scanner->config.scan_interval = DEFAULT_SCAN_INTERVAL; scanner->config.send_interval = DEFAULT_SEND_INTERVAL; strncpy(scanner->config.start_ip, DEFAULT_START_IP, sizeof(DEFAULT_START_IP)); strncpy(scanner->config.end_ip, DEFAULT_END_IP, sizeof(DEFAULT_END_IP)); return 0; } // 打印ARP配置 void print_config(const arp_config_t *config) { printf("ARP 配置:\n"); printf(" 功能开关: %s\n", config->enable ? "开启" : "关闭"); printf(" 扫描周期: %d 秒\n", config->scan_interval); printf(" 有效期: %d 秒\n", config->valid_time); printf(" 发包间隔: %d 毫秒\n", config->send_interval); printf(" 起始IP: %s\n", config->start_ip); printf(" 结束IP: %s\n", config->end_ip); } static int arp_init() { /* 初始化扫描器 */ pthread_mutex_init(&scanner.lock, NULL); /* 加载默认配置 */ load_default_config(&scanner); print_config(&scanner.config); // 打印默认配置 /* 创建arp socket */ scanner.sockfd = create_arp_socket(); if (scanner.sockfd < 0) { fprintf(stderr, "创建arp socket失败\n"); return -1; } printf("ARP socket已创建\n"); return 0; } static int arp_reload() { /* */ // 配置修改后的消息通知及配置更新重载 } static int arp_start() { /* 启动arp扫描线程 */ if (pthread_create(&scanner.scan_thread, NULL, arp_scan_thread, &scanner) != 0) { perror("❌ 创建扫描线程失败"); close(scanner.sockfd); return -1; } printf("扫描线程已启动\n"); return 0; } static int arp_stop() { // printf("等待扫描进行(10秒)...\n"); // for (int i = 0; i < 10; i++) { // printf("扫描状态: %s\n", scanner.scanning ? "进行中" : "已停止"); // sleep(1); // } scanner.scanning = SCANNING_OFF; pthread_join(scanner.scan_thread, NULL); printf("扫描已停止\n"); return 0; } int main() { arp_init(); arp_start(); arp_stop(); }

#ifndef __ARP_SCANNER_H__ #define __ARP_SCANNER_H__ #include "nsd_common.h" #include <net/if.h> #include <netinet/if_ether.h> #include #define MAX_ARP_ENTRIES 1024 #define MAX_IP_LEN 16 #define MAX_MAC_LEN 18 typedef struct { uint32_t ip; char mac[MAX_MAC_LEN]; time_t last_seen; time_t first_seen; } arp_entry_t; typedef struct { BOOL enabled; uint32_t scan_interval; uint32_t validity_period; uint32_t packet_interval; uint32_t start_ip; uint32_t end_ip; char interface[IFNAMSIZ]; } arp_config_t; typedef struct { pthread_t scan_thread; pthread_mutex_t lock; BOOL scanning; BOOL stop_requested; arp_config_t config; arp_entry_t entries[MAX_ARP_ENTRIES]; int entry_count; time_t last_scan_time; int raw_socket; } arp_scanner_t; // ARP报文结构 typedef struct { struct ethhdr eth_header; struct arphdr arp_header; unsigned char sender_mac[6]; unsigned char sender_ip[4]; unsigned char target_mac[6]; unsigned char target_ip[4]; } arp_packet_t; // 函数声明 int arp_scanner_init(arp_scanner_t *scanner); int arp_scanner_start(arp_scanner_t *scanner); int arp_scanner_stop(arp_scanner_t *scanner); int arp_scanner_cleanup(arp_scanner_t *scanner); int arp_scanner_scan(arp_scanner_t *scanner); int arp_scanner_send_arp_request(arp_scanner_t *scanner, uint32_t target_ip); int arp_scanner_process_reply(arp_scanner_t *scanner); void arp_scanner_clean_old_entries(arp_scanner_t *scanner); void arp_scanner_print_results(arp_scanner_t *scanner); int arp_scanner_add_entry(arp_scanner_t *scanner, uint32_t ip, const char *mac); int arp_scanner_remove_entry(arp_scanner_t *scanner, uint32_t ip); // 工具函数 uint32_t ip_to_int(const char *ip); void int_to_ip(uint32_t ip_int, char *ip_str); void mac_to_string(const unsigned char *mac, char *mac_str); #endif #include "arp_scanner.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <net/if.h> #include <sys/ioctl.h> #include #include <time.h> #include <errno.h> S32 arp_scanner_init(arp_scanner_t *scanner) { if (!scanner) return -1; memset(scanner, 0, sizeof(arp_scanner_t)); // 创建原始套接字 scanner->raw_socket = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP)); if (scanner->raw_socket < 0) { perror("socket"); return -1; } // 初始化互斥锁 if (pthread_mutex_init(&scanner->lock, NULL) != 0) { close(scanner->raw_socket); return -1; } // 默认配置 strcpy(scanner->config.interface, "eth0"); scanner->config.scan_interval = 60; scanner->config.validity_period = 300; scanner->config.packet_interval = 100; return 0; } S32 arp_scanner_start(arp_scanner_t *scanner) { if (!scanner || !scanner->config.enabled) return -1; pthread_mutex_lock(&scanner->lock); scanner->scanning = TRUE; scanner->stop_requested = FALSE; pthread_mutex_unlock(&scanner->lock); return 0; } int arp_scanner_stop(arp_scanner_t *scanner) { if (!scanner) return -1; pthread_mutex_lock(&scanner->lock); scanner->stop_requested = TRUE; pthread_mutex_unlock(&scanner->lock); return 0; } int arp_scanner_cleanup(arp_scanner_t *scanner) { if (!scanner) return -1; arp_scanner_stop(scanner); if (scanner->raw_socket >= 0) { close(scanner->raw_socket); } pthread_mutex_destroy(&scanner->lock); return 0; } void *scan_thread_func(void *arg) { arp_scanner_t *scanner = (arp_scanner_t *)arg; while (!scanner->stop_requested) { arp_scanner_scan(scanner); // 等待扫描间隔 sleep(scanner->config.scan_interval); } pthread_mutex_lock(&scanner->lock); scanner->scanning = FALSE; pthread_mutex_unlock(&scanner->lock); return NULL; } int arp_scanner_scan(arp_scanner_t *scanner) { if (!scanner || !scanner->config.enabled) return -1; struct ifreq ifr; strcpy(ifr.ifr_name, scanner->config.interface); // 获取接口索引 if (ioctl(scanner->raw_socket, SIOCGIFINDEX, &ifr) < 0) { perror("ioctl"); return -1; } // 绑定到接口 struct sockaddr_ll saddr; memset(&saddr, 0, sizeof(saddr)); saddr.sll_family = AF_PACKET; saddr.sll_ifindex = ifr.ifr_ifindex; saddr.sll_protocol = htons(ETH_P_ARP); if (bind(scanner->raw_socket, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { perror("bind"); return -1; } // 发送ARP请求 for (uint32_t ip = scanner->config.start_ip; ip <= scanner->config.end_ip && !scanner->stop_requested; ip++) { arp_scanner_send_arp_request(scanner, ip); usleep(scanner->config.packet_interval * 1000); } // 处理ARP回复 arp_scanner_process_reply(scanner); // 清理过期条目 arp_scanner_clean_old_entries(scanner); scanner->last_scan_time = time(NULL); return 0; } int arp_scanner_send_arp_request(arp_scanner_t *scanner, uint32_t target_ip) { struct ifreq ifr; strcpy(ifr.ifr_name, scanner->config.interface); // 获取接口MAC地址 if (ioctl(scanner->raw_socket, SIOCGIFHWADDR, &ifr) < 0) { perror("ioctl"); return -1; } unsigned char *src_mac = (unsigned char *)ifr.ifr_hwaddr.sa_data; // 获取接口IP地址 if (ioctl(scanner->raw_socket, SIOCGIFADDR, &ifr) < 0) { perror("ioctl"); return -1; } struct sockaddr_in *ipaddr = (struct sockaddr_in *)&ifr.ifr_addr; uint32_t src_ip = ipaddr->sin_addr.s_addr; // 构建ARP请求包 arp_packet_t packet; // 以太网头部 memset(packet.eth_header.h_dest, 0xFF, 6); // 广播地址 memcpy(packet.eth_header.h_source, src_mac, 6); packet.eth_header.h_proto = htons(ETH_P_ARP); // ARP头部 packet.arp_header.ar_hrd = htons(ARPHRD_ETHER); packet.arp_header.ar_pro = htons(ETH_P_IP); packet.arp_header.ar_hln = 6; packet.arp_header.ar_pln = 4; packet.arp_header.ar_op = htons(ARPOP_REQUEST); memcpy(packet.sender_mac, src_mac, 6); memcpy(packet.sender_ip, &src_ip, 4); memset(packet.target_mac, 0, 6); memcpy(packet.target_ip, &target_ip, 4); // 发送包 struct sockaddr_ll dest; memset(&dest, 0, sizeof(dest)); dest.sll_family = AF_PACKET; dest.sll_ifindex = ifr.ifr_ifindex; dest.sll_halen = ETH_ALEN; memset(dest.sll_addr, 0xFF, ETH_ALEN); ssize_t sent = sendto(scanner->raw_socket, &packet, sizeof(packet), 0, (struct sockaddr *)&dest, sizeof(dest)); return (sent == sizeof(packet)) ? 0 : -1; } int arp_scanner_process_reply(arp_scanner_t *scanner) { if (!scanner) { return -1; } fd_set readfds; struct timeval tv; int ret; int max_fd = scanner->raw_socket; // 设置超时时间为2秒,用于等待ARP回复 tv.tv_sec = 2; tv.tv_usec = 0; // 循环处理所有可用的ARP回复 while (1) { FD_ZERO(&readfds); FD_SET(scanner->raw_socket, &readfds); ret = select(max_fd + 1, &readfds, NULL, NULL, &tv); if (ret < 0) { if (errno == EINTR) { // 被信号中断,继续等待 continue; } perror("select"); break; } else if (ret == 0) { // 超时,没有更多数据 break; } if (FD_ISSET(scanner->raw_socket, &readfds)) { arp_packet_t packet; struct sockaddr_ll saddr; socklen_t saddr_len = sizeof(saddr); // 接收ARP数据包 ssize_t received = recvfrom(scanner->raw_socket, &packet, sizeof(packet), 0, (struct sockaddr *)&saddr, &saddr_len); if (received < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { continue; } perror("recvfrom"); continue; } // 检查接收到的数据包长度 if (received < (ssize_t)(sizeof(struct ethhdr) + sizeof(struct arphdr))) { // 数据包太短,不是有效的ARP包 continue; } // 验证以太网类型是否为ARP if (ntohs(packet.eth_header.h_proto) != ETH_P_ARP) { continue; } // 验证ARP硬件类型为以太网 if (ntohs(packet.arp_header.ar_hrd) != ARPHRD_ETHER) { continue; } // 验证ARP协议类型为IP if (ntohs(packet.arp_header.ar_pro) != ETH_P_IP) { continue; } // 检查是否是ARP回复 if (ntohs(packet.arp_header.ar_op) == ARPOP_REPLY) { // 提取发送者IP和MAC地址 uint32_t sender_ip; memcpy(&sender_ip, packet.sender_ip, 4); char mac_str[MAX_MAC_LEN]; mac_to_string(packet.sender_mac, mac_str); // 检查IP是否在扫描范围内 if (sender_ip >= scanner->config.start_ip && sender_ip <= scanner->config.end_ip) { // 添加到ARP条目表 arp_scanner_add_entry(scanner, sender_ip, mac_str); // 打印调试信息 char ip_str[MAX_IP_LEN]; int_to_ip(sender_ip, ip_str); printf("Received ARP reply from %s [%s]\n", ip_str, mac_str); } } } } return 0; } int arp_scanner_add_entry(arp_scanner_t *scanner, uint32_t ip, const char *mac) { if (!scanner || !mac) { return -1; } pthread_mutex_lock(&scanner->lock); time_t now = time(NULL); int found_index = -1; BOOL is_new_host = FALSE; // 检查是否已存在该IP的条目 for (int i = 0; i < scanner->entry_count; i++) { if (scanner->entries[i].ip == ip) { found_index = i; break; } } if (found_index >= 0) { // 更新现有条目 strncpy(scanner->entries[found_index].mac, mac, MAX_MAC_LEN - 1); scanner->entries[found_index].mac[MAX_MAC_LEN - 1] = '\0'; scanner->entries[found_index].last_seen = now; } else { // 添加新条目 if (scanner->entry_count < MAX_ARP_ENTRIES) { arp_entry_t *entry = &scanner->entries[scanner->entry_count]; entry->ip = ip; strncpy(entry->mac, mac, MAX_MAC_LEN - 1); entry->mac[MAX_MAC_LEN - 1] = '\0'; entry->last_seen = now; entry->first_seen = now; scanner->entry_count++; is_new_host = TRUE; } else { // ARP表已满,找到最旧的条目替换 time_t oldest_time = now; int oldest_index = 0; for (int i = 0; i < scanner->entry_count; i++) { if (scanner->entries[i].last_seen < oldest_time) { oldest_time = scanner->entries[i].last_seen; oldest_index = i; } } // 替换最旧的条目 arp_entry_t *entry = &scanner->entries[oldest_index]; entry->ip = ip; strncpy(entry->mac, mac, MAX_MAC_LEN - 1); entry->mac[MAX_MAC_LEN - 1] = '\0'; entry->last_seen = now; entry->first_seen = now; is_new_host = TRUE; } } pthread_mutex_unlock(&scanner->lock); // 如果是新发现的主机,打印到串口 if (is_new_host) { char ip_str[MAX_IP_LEN]; int_to_ip(ip, ip_str); printf("NEW HOST: IP=%s, MAC=%s\n", ip_str, mac); } return 0; } void arp_scanner_clean_old_entries(arp_scanner_t *scanner) { if (!scanner) { return; } pthread_mutex_lock(&scanner->lock); time_t now = time(NULL); int write_index = 0; for (int read_index = 0; read_index < scanner->entry_count; read_index++) { if (now - scanner->entries[read_index].last_seen <= scanner->config.validity_period) { // 条目未过期,保留 if (write_index != read_index) { scanner->entries[write_index] = scanner->entries[read_index]; } write_index++; } else { // 条目过期,打印日志 char ip_str[MAX_IP_LEN]; int_to_ip(scanner->entries[read_index].ip, ip_str); printf("EXPIRED: IP=%s, MAC=%s\n", ip_str, scanner->entries[read_index].mac); } } // 更新条目计数 int expired_count = scanner->entry_count - write_index; scanner->entry_count = write_index; pthread_mutex_unlock(&scanner->lock); if (expired_count > 0) { printf("Cleaned %d expired ARP entries\n", expired_count); } } void arp_scanner_print_results(arp_scanner_t *scanner) { if (!scanner) { return; } pthread_mutex_lock(&scanner->lock); printf("\n=== ARP Scan Results ===\n"); printf("Total hosts: %d\n", scanner->entry_count); printf("Last scan: %s", ctime(&scanner->last_scan_time)); printf("-----------------------------------------------\n"); printf("IP Address\t\tMAC Address\t\tFirst Seen\t\tLast Seen\n"); printf("-----------------------------------------------\n"); for (int i = 0; i < scanner->entry_count; i++) { char ip_str[MAX_IP_LEN]; int_to_ip(scanner->entries[i].ip, ip_str); char first_seen_str[64]; char last_seen_str[64]; struct tm *tm_info; tm_info = localtime(&scanner->entries[i].first_seen); strftime(first_seen_str, sizeof(first_seen_str), "%Y-%m-%d %H:%M:%S", tm_info); tm_info = localtime(&scanner->entries[i].last_seen); strftime(last_seen_str, sizeof(last_seen_str), "%Y-%m-%d %H:%M:%S", tm_info); printf("%-15s\t%s\t%s\t%s\n", ip_str, scanner->entries[i].mac, first_seen_str, last_seen_str); } printf("-----------------------------------------------\n"); pthread_mutex_unlock(&scanner->lock); } int arp_scanner_remove_entry(arp_scanner_t *scanner, uint32_t ip) { if (!scanner) { return -1; } pthread_mutex_lock(&scanner->lock); int found_index = -1; // 查找要删除的条目 for (int i = 0; i < scanner->entry_count; i++) { if (scanner->entries[i].ip == ip) { found_index = i; break; } } if (found_index >= 0) { // 移动后续条目覆盖要删除的条目 for (int i = found_index; i < scanner->entry_count - 1; i++) { scanner->entries[i] = scanner->entries[i + 1]; } scanner->entry_count--; char ip_str[MAX_IP_LEN]; int_to_ip(ip, ip_str); printf("Removed ARP entry: %s\n", ip_str); } pthread_mutex_unlock(&scanner->lock); return (found_index >= 0) ? 0 : -1; } // 工具函数 uint32_t ip_to_int(const char *ip) { if (!ip) { return 0; } struct in_addr addr; if (inet_pton(AF_INET, ip, &addr) != 1) { fprintf(stderr, "Invalid IP address: %s\n", ip); return 0; } return addr.s_addr; } void int_to_ip(uint32_t ip_int, char *ip_str) { if (!ip_str) { return; } struct in_addr addr; addr.s_addr = ip_int; inet_ntop(AF_INET, &addr, ip_str, MAX_IP_LEN); } void mac_to_string(const unsigned char *mac, char *mac_str) { if (!mac || !mac_str) { return; } snprintf(mac_str, MAX_MAC_LEN, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); } 重写一下这两个文件,要求从/./files/etc/default/arpd/arpd_conf中读取配置信息{ "arpd": { "enabled": "FALSE", "scan_interval": "60", "validity_period": "300", "packet_interval": "100", "start_ip": "192.168.1.100", "end_ip": "192.168.1.200" } },要求用ds_read()函数读取

将以下代码中的填充源和目标地址和IP部分补充完整// arp_scanner.c #include <sys/socket.h> #include #include <net/ethernet.h> #include <sys/ioctl.h> #include <netinet/in.h> #include <arpa/inet.h> #include <net/if.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "arp_scanner.h" // 创建原始ARP socket int create_arp_socket() { int sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP)); if (sock < 0) { perror("socket"); return -1; } return sock; } /* * fn static int send_arp_request(int sockfd, const char *src_ip, const char *dest_ip, const char *ifname) * brief 发送ARP请求 * details None * * param[in] sockfd 套接字 * param[in] src_ip 源ip * param[in] ifname 网卡名 * param[out]None * return None * * retval None * note None */ static int send_arp_request(int sockfd, const char *src_ip, const char *dest_ip, const char *ifname) { // 获取接口索引 struct ifreq ifr; strncpy(ifr.ifr_name, ifname, IFNAMSIZ); // IFNAMSIZ 网络接口大小默认16 if (ioctl(sockfd, SIOCGIFINDEX, &ifr) < 0) { perror("ioctl"); return -1; } // 构建以太网帧和ARP包 unsigned char packet[60] = {0}; struct ether_header *eth = (struct ether_header *)packet; struct ether_arp *arp = (struct ether_arp *)(packet + sizeof(struct ether_header)); // 填充以太网帧头 memset(eth->ether_dhost, 0xFF, 6); // 广播地址 // 填充ARP包 arp->arp_hrd = htons(ARPHRD_ETHER); arp->arp_pro = htons(ETHERTYPE_IP); arp->arp_hln = 6; arp->arp_pln = 4; arp->arp_op = htons(ARPOP_REQUEST); // 填充源和目标IP/MAC(此处省略) // 发送数据包 struct sockaddr_ll sa = { .sll_family = AF_PACKET, .sll_ifindex = ifr.ifr_ifindex, .sll_halen = ETH_ALEN, .sll_addr = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} // 广播 }; if (sendto(sockfd, packet, sizeof(packet), 0, (struct sockaddr*)&sa, sizeof(sa)) < 0) { perror("sendto"); return -1; } return 0; } // 接收ARP响应 void *arp_scan_thread(void *arg) { arp_scanner_t *scanner = (arp_scanner_t *)arg; scanner->scanning = 1; while (scanner->scanning) { // 清理过期条目 clean_expired_entries(scanner); // 遍历IP范围 for (uint32_t ip = inet_addr(scanner->config.start_ip); ip <= inet_addr(scanner->config.end_ip); ip = ntohl(ntohl(ip) + 1)) { if (!scanner->scanning) break; // 发送ARP请求 char dest_ip[16]; inet_ntop(AF_INET, &ip, dest_ip, sizeof(dest_ip)); send_arp_request(scanner->sockfd, "192.168.1.1", dest_ip, "eth0"); // 接收响应 unsigned char buffer[ETH_FRAME_LEN]; struct sockaddr_ll saddr; socklen_t saddr_len = sizeof(saddr); fd_set fds; struct timeval tv = { .tv_usec = scanner->config.send_interval * 1000 }; FD_ZERO(&fds); FD_SET(scanner->sockfd, &fds); if (select(scanner->sockfd + 1, &fds, NULL, NULL, &tv) > 0) { ssize_t len = recvfrom(scanner->sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&saddr, &saddr_len); if (len > 0) { process_arp_response(scanner, buffer, len); } } } // 等待扫描间隔 int sleep_count = scanner->config.scan_interval; while (sleep_count > 0 && scanner->scanning) { sleep(1); sleep_count--; } } close(scanner->sockfd); scanner->sockfd = -1; scanner->scanning = 0; return NULL; } // 处理ARP响应 void process_arp_response(arp_scanner_t *scanner, unsigned char *buffer, size_t len) { struct ether_arp *arp = (struct ether_arp *)(buffer + sizeof(struct ether_header)); // 提取IP和MAC char ip_str[INET_ADDRSTRLEN]; inet_ntop(AF_INET, arp->arp_spa, ip_str, sizeof(ip_str)); pthread_mutex_lock(&scanner->lock); // 检查是否是新主机 int is_new = 1; arp_entry_t *entry = scanner->entries; while (entry) { if (strcmp(entry->ip, ip_str) == 0) { memcpy(entry->mac, arp->arp_sha, 6); entry->last_seen = time(NULL); is_new = 0; break; } entry = entry->next; } // 发现新主机 if (is_new) { arp_entry_t *new_entry = malloc(sizeof(arp_entry_t)); strcpy(new_entry->ip, ip_str); memcpy(new_entry->mac, arp->arp_sha, 6); new_entry->last_seen = time(NULL); new_entry->next = scanner->entries; scanner->entries = new_entry; // 打印到串口 printf("[NEW HOST] IP: %s, MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", ip_str, arp->arp_sha[0], arp->arp_sha[1], arp->arp_sha[2], arp->arp_sha[3], arp->arp_sha[4], arp->arp_sha[5]); } pthread_mutex_unlock(&scanner->lock); } // 清理过期条目 void clean_expired_entries(arp_scanner_t *scanner) { time_t now = time(NULL); pthread_mutex_lock(&scanner->lock); arp_entry_t **pp = &scanner->entries; while (*pp) { arp_entry_t *entry = *pp; if (now - entry->last_seen > scanner->config.valid_time) { *pp = entry->next; free(entry); } else { pp = &entry->next; } } pthread_mutex_unlock(&scanner->lock); }

arp_final.c:16:0: warning: "IFNAMSIZ" redefined #define IFNAMSIZ 16 ^ In file included from arp_final.c:7:0: /usr/include/net/if.h:129:0: note: this is the location of the previous definition # define IFNAMSIZ IF_NAMESIZE ^ arp_final.c:68:8: error: redefinition of ‘struct ifreq’ struct ifreq { ^ In file included from arp_final.c:7:0: /usr/include/net/if.h:126:8: note: originally defined here struct ifreq ^ arp_final.c:69:10: error: expected ‘:’, ‘,’, ‘;’, ‘}’ or ‘__attribute__’ before ‘.’ token char ifr_name[IFNAMSIZ]; ^ arp_final.c: In function ‘if_nametoindex’: arp_final.c:125:16: error: ‘struct ifreq’ has no member named ‘ifr_ifrn’ strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1); ^ arp_final.c:134:15: error: ‘struct ifreq’ has no member named ‘ifr_ifru’ return ifr.ifr_ifru.ifru_metric; ^ arp_final.c: In function ‘get_local_mac’: arp_final.c:146:16: error: ‘struct ifreq’ has no member named ‘ifr_ifrn’ strncpy(ifr.ifr_name, ifname, IFNAMSIZ); ^ arp_final.c:153:20: error: ‘struct ifreq’ has no member named ‘ifr_ifru’ memcpy(mac, ifr.ifr_ifru.ifru_hwaddr.sa_data, MAC_LENGTH); ^ arp_final.c: In function ‘get_local_ip’: arp_final.c:166:16: error: ‘struct ifreq’ has no member named ‘ifr_ifrn’ strncpy(ifr.ifr_name, ifname, IFNAMSIZ); ^ arp_final.c:173:57: error: ‘struct ifreq’ has no member named ‘ifr_ifru’ struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_ifru.ifru_addr; ^ arp_final.c: In function ‘build_arp_packet’: arp_final.c:191:25: error: ‘ETH_P_IP’ undeclared (first use in this function) arp->ar_pro = htons(ETH_P_IP); ^ arp_final.c:191:25: note: each undeclared identifier is reported only once for each function it appears in arp_final.c: In function ‘send_arp’: arp_final.c:230:12: error: variable ‘dest’ has initializer but incomplete type struct sockaddr_ll dest = { ^ arp_final.c:231:9: error: unknown field ‘sll_family’ specified in initializer .sll_family = AF_PACKET, ^ arp_final.c:232:9: error: unknown field ‘sll_protocol’ specified in initializer .sll_protocol = htons(ETH_P_ARP), ^ arp_final.c:232:25: warning: excess elements in struct initializer .sll_protocol = htons(ETH_P_ARP), ^ arp_final.c:232:25: note: (near initialization for ‘dest’) arp_final.c:233:9: error: unknown field ‘sll_ifindex’ specified in initializer .sll_ifindex = if_nametoindex(ifname), ^ arp_final.c:233:24: warning: excess elements in struct initializer .sll_ifindex = if_nametoindex(ifname), ^ arp_final.c:233:24: note: (near initialization for ‘dest’) arp_final.c:234:9: error: unknown field ‘sll_halen’ specified in initializer .sll_halen = ETH_ALEN, ^ arp_final.c:24:18: warning: excess elements in struct initializer #define ETH_ALEN 6 ^ arp_final.c:234:22: note: in expansion of macro ‘ETH_ALEN’ .sll_halen = ETH_ALEN, ^ arp_final.c:24:18: note: (near initialization for ‘dest’) #define ETH_ALEN 6 ^ arp_final.c:234:22: note: in expansion of macro ‘ETH_ALEN’ .sll_halen = ETH_ALEN, ^ arp_final.c:235:9: error: unknown field ‘sll_addr’ specified in initializer .sll_addr = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} // 广播地址 ^ arp_final.c:235:21: error: extra brace group at end of initializer .sll_addr = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} // 广播地址 ^ arp_final.c:235:21: note: (near initialization for ‘dest’) arp_final.c:235:21: warning: excess elements in struct initializer arp_final.c:235:21: note: (near initialization for ‘dest’) arp_final.c:230:24: error: storage size of ‘dest’ isn’t known struct sockaddr_ll dest = { ^ arp_final.c: In function ‘find_or_create_node’: arp_final.c:275:5: warning: implicit declaration of function ‘list_for_each’ [-Wimplicit-function-declaration] list_for_each(pos, &arp_result_head) { ^ arp_final.c:275:42: error: expected ‘;’ before ‘{’ token list_for_each(pos, &arp_result_head) { ^ arp_final.c: In function ‘cleanup_thread’: arp_final.c:373:9: warning: implicit declaration of function ‘list_for_each_safe’ [-Wimplicit-function-declaration] list_for_each_safe(pos, next, &arp_result_head) { ^ arp_final.c:373:57: error: expected ‘;’ before ‘{’ token list_for_each_safe(pos, next, &arp_result_head) { ^ arp_final.c: In function ‘print_arp_table’: arp_final.c:403:42: error: expected ‘;’ before ‘{’ token list_for_each(pos, &arp_result_head) { 报错如上

我给你一个arp模块的代码,帮我进行模块注册,#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/ioctl.h> #include <net/ethernet.h> #include <arpa/inet.h> #include "arp.h" #include #include <time.h> #include <netinet/ether.h> #define ETH_HEADER_SIZE 14 #define ARP_PACKET_SIZE 42 #define INITIAL_SIZE 1024 unsigned int if_nametoindex(const char *ifname) { struct ifreq ifr; int sockfd; sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { perror("socket"); return 0; } memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1); if (ioctl(sockfd, SIOCGIFINDEX, &ifr) < 0) { close(sockfd); perror("ioctl"); return 0; } close(sockfd); return ifr.ifr_ifru.ifru_metric; } /*获取本机mac地址*/ void get_local_mac(uint8_t *mac) { struct ifreq ifr; int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); if (sock < 0) { perror("socket"); exit(EXIT_FAILURE); } // 使用eth0接口,可根据需要修改 strncpy(ifr.ifr_name, "ens33", IFNAMSIZ); if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) { perror("ioctl"); close(sock); exit(EXIT_FAILURE); } memcpy(mac, ifr.ifr_ifru.ifru_hwaddr.sa_data, 6); close(sock); } /*获取本机ip地址*/ void get_local_ip(struct in_addr *local_ip) { struct ifreq ifr; int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); if (sock < 0) { perror("socket"); exit(EXIT_FAILURE); } // 使用eth0接口,可根据需要修改 strncpy(ifr.ifr_name, "ens33", IFNAMSIZ); if (ioctl(sock, SIOCGIFADDR, &ifr) < 0) { perror("ioctl"); close(sock); exit(EXIT_FAILURE); } struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_ifru.ifru_addr; *local_ip = sin->sin_addr; close(sock); } /*发送ARP请求*/ void send_arp(int sock, struct _ARP_HDR_new *arp) { // 构建完整的以太网帧 uint8_t packet[ARP_PACKET_SIZE]; // 以太网目标地址(广播) memset(packet, 0xFF, 6); // 以太网源地址(本机MAC) //get_local_mac(packet + 6); struct in_addr local_ip; get_local_ip(&local_ip); memcpy(packet + 6, &local_ip, sizeof(local_ip)); // 以太网类型(ARP) packet[12] = 0x08; // ETH_P_ARP高位 packet[13] = 0x06; // ETH_P_ARP低位 // ARP包内容 memcpy(packet + ETH_HEADER_SIZE, arp, sizeof(*arp)); // 发送到网络接口 struct sockaddr_ll dest = { .sll_family = AF_PACKET, .sll_protocol = htons(ETH_P_ARP), .sll_ifindex = if_nametoindex("ens33"), // 使用eth0接口 .sll_halen = ETH_ALEN, .sll_addr = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} // 广播地址 }; if (sendto(sock, packet, ARP_PACKET_SIZE, 0, (struct sockaddr *)&dest, sizeof(dest)) < 0) { perror("sendto"); } } /*接收ARP包*/ int recv_arp(int sock, struct _ARP_HDR_new *arp_resp) { uint8_t buffer[ETH_FRAME_LEN]; ssize_t len = recv(sock, buffer, sizeof(buffer), 0); if (len < ETH_HEADER_SIZE) { return -1; // 接收失败 } // 检查是否为ARP包 if (buffer[12] != 0x08 || buffer[13] != 0x06) { return -1; // 非ARP包 } // 解析ARP包 struct _ARP_HDR_new *arp = (struct _ARP_HDR_new *)(buffer + ETH_HEADER_SIZE); // 检查是否为ARP响应 if (ntohs(arp->ar_op) != ARPOP_REPLY) { return -1; // 非ARP响应 } memcpy(arp_resp, arp, sizeof(arp)); return len; } // 查找或创建ARP条目 arp_entry* find_or_create_entry(arp_scanner *scanner, uint32_t ip) { // 首先尝试查找现有条目 for (int i = 0; i < scanner->entry_count; i++) { if (scanner->entries[i].ip == ip) { return &scanner->entries[i]; } } // 如果表已满,扩展容量 if (scanner->entry_count >= scanner->max_entries) { int new_size = scanner->max_entries * 2; arp_entry *new_entries = realloc(scanner->entries, new_size * sizeof(arp_entry)); if (!new_entries) { perror("realloc"); return NULL; } scanner->entries = new_entries; scanner->max_entries = new_size; } // 创建新条目 arp_entry *new_entry = &scanner->entries[scanner->entry_count++]; new_entry->ip = ip; memset(new_entry->mac, 0, ETH_ALEN); new_entry->last_update = time(NULL); new_entry->expire_time = new_entry->last_update + scanner->config.entry_ttl; return new_entry; } // 创建原始套接字 int create_arp_socket() { int sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP)); if (sock < 0) { perror("socket"); exit(EXIT_FAILURE); } return sock; } // 构建ARP请求报文 void build_arp_packet(struct _ARP_HDR_new *arp, uint32_t target_ip) { arp->ar_hrd = htons(ARPHRD_ETHER); arp->ar_pro = htons(ETHERTYPE_IP); arp->ar_hln = ETH_ALEN; arp->ar_pln = sizeof(in_addr_t); arp->ar_op = htons(ARPOP_REQUEST); // 设置源MAC(本机MAC) get_local_mac(arp->ar_sha); // 设置源IP(本机IP) struct in_addr local_ip; get_local_ip(&local_ip); memcpy(arp->ar_sip, &local_ip, sizeof(local_ip)); // 设置目标MAC(广播) memset(arp->ar_tha, 0x00, ETH_ALEN); // 设置目标IP memcpy(arp->ar_tip, &target_ip, sizeof(target_ip)); } // ARP扫描线程 void* scan_thread(void *arg) { arp_scanner *scanner = (arp_scanner*)arg; int sock = create_arp_socket(); while (scanner->config.enable_scan) { pthread_mutex_lock(&scanner->lock); config_t cfg = scanner->config; pthread_mutex_unlock(&scanner->lock); // 转换为主机字节序 uint32_t host_start_ip = ntohl(cfg.start_ip); uint32_t host_end_ip = ntohl(cfg.end_ip); // 打印当前扫描范围 char start_ip_str[INET_ADDRSTRLEN]; char end_ip_str[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &cfg.start_ip, start_ip_str, sizeof(start_ip_str)); inet_ntop(AF_INET, &cfg.end_ip, end_ip_str, sizeof(end_ip_str)); printf("[SCAN] Scanning from %s to %s\n", start_ip_str, end_ip_str); // 遍历IP范围(使用主机字节序递增) for (uint32_t host_ip = host_start_ip; host_ip <= host_end_ip; host_ip++) { uint32_t net_ip = htonl(host_ip); // 转回网络字节序 char ip_str[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &net_ip, ip_str, sizeof(ip_str)); printf("[SCAN] Sending ARP to %s\n", ip_str); struct _ARP_HDR_new arp_req; build_arp_packet(&arp_req, net_ip); // 发送ARP请求 send_arp(sock, &arp_req); // 按间隔等待 usleep(cfg.packet_interval * 1000); } // 等待扫描周期 sleep(cfg.scan_cycle); } close(sock); return NULL; } // ARP响应处理 void process_arp_response(arp_scanner *scanner, struct _ARP_HDR_new *arp) { uint32_t ip; memcpy(&ip, arp->ar_sip, sizeof(ip)); pthread_mutex_lock(&scanner->lock); // 查找或创建条目 arp_entry *entry = find_or_create_entry(scanner, ip); memcpy(entry->mac, arp->ar_sha, ETH_ALEN); entry->last_update = time(NULL); entry->expire_time = entry->last_update + scanner->config.entry_ttl; pthread_mutex_unlock(&scanner->lock); } // 超时清理线程 void* cleanup_thread(void *arg) { arp_scanner *scanner = (arp_scanner*)arg; while (1) { sleep(5); // 每5秒检查一次 pthread_mutex_lock(&scanner->lock); time_t now = time(NULL); for (int i = 0; i < scanner->entry_count; ) { if (scanner->entries[i].expire_time < now) { // 移除超时条目 memmove(&scanner->entries[i], &scanner->entries[i+1], (scanner->entry_count - i - 1) * sizeof(arp_entry)); scanner->entry_count--; } else { i++; } } pthread_mutex_unlock(&scanner->lock); } return NULL; } // 动态调整内存 void resize_entries(arp_scanner *scanner, int new_size) { arp_entry *new_entries = realloc(scanner->entries, new_size * sizeof(arp_entry)); if (new_entries) { scanner->entries = new_entries; scanner->max_entries = new_size; } } void update_config(arp_scanner *scanner, config_t new_config) { pthread_mutex_lock(&scanner->lock); // 验证IP范围有效性 if (ntohl(new_config.end_ip) < ntohl(new_config.start_ip)) { fprintf(stderr, "Invalid IP range\n"); } else { scanner->config = new_config; } pthread_mutex_unlock(&scanner->lock); } // 配置 config_t default_config = { .enable_scan = 1, .scan_cycle = 300, // 5分钟 .packet_interval = 100, // 100毫秒 .entry_ttl = 1800, // 30分钟 .start_ip=1, .end_ip=1 }; int main() { default_config.start_ip = inet_addr("192.168.157.1"); default_config.end_ip = inet_addr("192.168.157.254"); arp_scanner scanner = { .entries = malloc(INITIAL_SIZE * sizeof(arp_entry)), .entry_count = 0, .max_entries = INITIAL_SIZE, .config = default_config }; pthread_mutex_init(&scanner.lock, NULL); // 启动扫描线程 pthread_t scan_tid, cleanup_tid; pthread_create(&scan_tid, NULL, scan_thread, &scanner); pthread_create(&cleanup_tid, NULL, cleanup_thread, &scanner); // 启动ARP响应接收 int arp_sock = create_arp_socket(); while (1) { struct _ARP_HDR_new arp_resp; if (recv_arp(arp_sock, &arp_resp) > 0) { process_arp_response(&scanner, &arp_resp); } } // 清理资源 pthread_join(scan_tid, NULL); pthread_join(cleanup_tid, NULL); free(scanner.entries); close(arp_sock); return 0; }

我的arp代码需要提供ubus服务接口,至少提供以下接口:reload_config(重载配置)、start_scan(开始一次扫描)、stop_scan(停止扫描)、get_scan_status(扫描状态)、get_scan_result(获取最近一次的扫描结果)、clear_result(清除历史结果)。#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/ioctl.h> #include <net/ethernet.h> #include <arpa/inet.h> #include "arp.h" #include #include <time.h> #include <netinet/ether.h> #define ETH_HEADER_SIZE 14 #define ARP_PACKET_SIZE 42 #define INITIAL_SIZE 1024 unsigned int if_nametoindex(const char *ifname) { struct ifreq ifr; int sockfd; sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { perror("socket"); return 0; } memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1); if (ioctl(sockfd, SIOCGIFINDEX, &ifr) < 0) { close(sockfd); perror("ioctl"); return 0; } close(sockfd); return ifr.ifr_ifru.ifru_metric; } void get_local_mac(uint8_t *mac) { struct ifreq ifr; int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); if (sock < 0) { perror("socket"); exit(EXIT_FAILURE); } // 使用eth0接口,可根据需要修改 strncpy(ifr.ifr_name, "ens33", IFNAMSIZ); if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) { perror("ioctl"); close(sock); exit(EXIT_FAILURE); } memcpy(mac, ifr.ifr_ifru.ifru_hwaddr.sa_data, 6); close(sock); } void get_local_ip(struct in_addr *local_ip) { struct ifreq ifr; int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); if (sock < 0) { perror("socket"); exit(EXIT_FAILURE); } // 使用eth0接口,可根据需要修改 strncpy(ifr.ifr_name, "ens33", IFNAMSIZ); if (ioctl(sock, SIOCGIFADDR, &ifr) < 0) { perror("ioctl"); close(sock); exit(EXIT_FAILURE); } struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_ifru.ifru_addr; *local_ip = sin->sin_addr; close(sock); } // 发送ARP请求 void send_arp(int sock, struct _ARP_HDR_new *arp) { // 构建完整的以太网帧 uint8_t packet[ARP_PACKET_SIZE]; // 以太网目标地址(广播) memset(packet, 0xFF, 6); // 以太网源地址(本机MAC) //get_local_mac(packet + 6); struct in_addr local_ip; get_local_ip(&local_ip); memcpy(packet + 6, &local_ip, sizeof(local_ip)); // 以太网类型(ARP) packet[12] = 0x08; // ETH_P_ARP高位 packet[13] = 0x06; // ETH_P_ARP低位 // ARP包内容 memcpy(packet + ETH_HEADER_SIZE, arp, sizeof(*arp)); // 发送到网络接口 struct sockaddr_ll dest = { .sll_family = AF_PACKET, .sll_protocol = htons(ETH_P_ARP), .sll_ifindex = if_nametoindex("ens33"), // 使用eth0接口 .sll_halen = ETH_ALEN, .sll_addr = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} // 广播地址 }; if (sendto(sock, packet, ARP_PACKET_SIZE, 0, (struct sockaddr *)&dest, sizeof(dest)) < 0) { perror("sendto"); } } int recv_arp(int sock, struct _ARP_HDR_new *arp_resp) { uint8_t buffer[ETH_FRAME_LEN]; ssize_t len = recv(sock, buffer, sizeof(buffer), 0); if (len < ETH_HEADER_SIZE) { return -1; // 接收失败 } // 检查是否为ARP包 if (buffer[12] != 0x08 || buffer[13] != 0x06) { return -1; // 非ARP包 } // 解析ARP包 struct _ARP_HDR_new *arp = (struct _ARP_HDR_new *)(buffer + ETH_HEADER_SIZE); // 检查是否为ARP响应 if (ntohs(arp->ar_op) != ARPOP_REPLY) { return -1; // 非ARP响应 } memcpy(arp_resp, arp, sizeof(arp)); return len; } // 查找或创建ARP条目 arp_entry* find_or_create_entry(arp_scanner *scanner, uint32_t ip) { // 首先尝试查找现有条目 for (int i = 0; i < scanner->entry_count; i++) { if (scanner->entries[i].ip == ip) { return &scanner->entries[i]; } } // 如果表已满,扩展容量 if (scanner->entry_count >= scanner->max_entries) { int new_size = scanner->max_entries * 2; arp_entry *new_entries = realloc(scanner->entries, new_size * sizeof(arp_entry)); if (!new_entries) { perror("realloc"); return NULL; } scanner->entries = new_entries; scanner->max_entries = new_size; } // 创建新条目 arp_entry *new_entry = &scanner->entries[scanner->entry_count++]; new_entry->ip = ip; memset(new_entry->mac, 0, ETH_ALEN); new_entry->last_update = time(NULL); new_entry->expire_time = new_entry->last_update + scanner->config.entry_ttl; return new_entry; } // 创建原始套接字 int create_arp_socket() { int sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP)); if (sock < 0) { perror("socket"); exit(EXIT_FAILURE); } return sock; } // 构建ARP请求报文 void build_arp_packet(struct _ARP_HDR_new *arp, uint32_t target_ip) { arp->ar_hrd = htons(ARPHRD_ETHER); arp->ar_pro = htons(ETHERTYPE_IP); arp->ar_hln = ETH_ALEN; arp->ar_pln = sizeof(in_addr_t); arp->ar_op = htons(ARPOP_REQUEST); // 设置源MAC(本机MAC) get_local_mac(arp->ar_sha); // 设置源IP(本机IP) struct in_addr local_ip; get_local_ip(&local_ip); memcpy(arp->ar_sip, &local_ip, sizeof(local_ip)); // 设置目标MAC(广播) memset(arp->ar_tha, 0x00, ETH_ALEN); // 设置目标IP memcpy(arp->ar_tip, &target_ip, sizeof(target_ip)); } // ARP扫描线程 void* scan_thread(void *arg) { arp_scanner *scanner = (arp_scanner*)arg; int sock = create_arp_socket(); while (scanner->config.enable_scan) { pthread_mutex_lock(&scanner->lock); config_t cfg = scanner->config; pthread_mutex_unlock(&scanner->lock); // 转换为主机字节序 uint32_t host_start_ip = ntohl(cfg.start_ip); uint32_t host_end_ip = ntohl(cfg.end_ip); // 打印当前扫描范围 char start_ip_str[INET_ADDRSTRLEN]; char end_ip_str[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &cfg.start_ip, start_ip_str, sizeof(start_ip_str)); inet_ntop(AF_INET, &cfg.end_ip, end_ip_str, sizeof(end_ip_str)); printf("[SCAN] Scanning from %s to %s\n", start_ip_str, end_ip_str); // 遍历IP范围(使用主机字节序递增) for (uint32_t host_ip = host_start_ip; host_ip <= host_end_ip; host_ip++) { uint32_t net_ip = htonl(host_ip); // 转回网络字节序 char ip_str[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &net_ip, ip_str, sizeof(ip_str)); printf("[SCAN] Sending ARP to %s\n", ip_str); struct _ARP_HDR_new arp_req; build_arp_packet(&arp_req, net_ip); // 发送ARP请求 send_arp(sock, &arp_req); // 按间隔等待 usleep(cfg.packet_interval * 1000); } // 等待扫描周期 sleep(cfg.scan_cycle); } close(sock); return NULL; } // ARP响应处理 void process_arp_response(arp_scanner *scanner, struct _ARP_HDR_new *arp) { uint32_t ip; memcpy(&ip, arp->ar_sip, sizeof(ip)); pthread_mutex_lock(&scanner->lock); // 查找或创建条目 arp_entry *entry = find_or_create_entry(scanner, ip); memcpy(entry->mac, arp->ar_sha, ETH_ALEN); entry->last_update = time(NULL); entry->expire_time = entry->last_update + scanner->config.entry_ttl; pthread_mutex_unlock(&scanner->lock); } // 超时清理线程 void* cleanup_thread(void *arg) { arp_scanner *scanner = (arp_scanner*)arg; while (1) { sleep(5); // 每5秒检查一次 pthread_mutex_lock(&scanner->lock); time_t now = time(NULL); for (int i = 0; i < scanner->entry_count; ) { if (scanner->entries[i].expire_time < now) { // 移除超时条目 memmove(&scanner->entries[i], &scanner->entries[i+1], (scanner->entry_count - i - 1) * sizeof(arp_entry)); scanner->entry_count--; } else { i++; } } pthread_mutex_unlock(&scanner->lock); } return NULL; } // 动态调整内存 void resize_entries(arp_scanner *scanner, int new_size) { arp_entry *new_entries = realloc(scanner->entries, new_size * sizeof(arp_entry)); if (new_entries) { scanner->entries = new_entries; scanner->max_entries = new_size; } } void update_config(arp_scanner *scanner, config_t new_config) { pthread_mutex_lock(&scanner->lock); // 验证IP范围有效性 if (ntohl(new_config.end_ip) < ntohl(new_config.start_ip)) { fprintf(stderr, "Invalid IP range\n"); } else { scanner->config = new_config; } pthread_mutex_unlock(&scanner->lock); } // 配置 config_t default_config = { .enable_scan = 1, .scan_cycle = 300, // 5分钟 .packet_interval = 100, // 100毫秒 .entry_ttl = 1800, // 30分钟 .start_ip=1, .end_ip=1 }; int main() { default_config.start_ip = inet_addr("192.168.157.1"); default_config.end_ip = inet_addr("192.168.157.254"); arp_scanner scanner = { .entries = malloc(INITIAL_SIZE * sizeof(arp_entry)), .entry_count = 0, .max_entries = INITIAL_SIZE, .config = default_config }; pthread_mutex_init(&scanner.lock, NULL); // 启动扫描线程 pthread_t scan_tid, cleanup_tid; pthread_create(&scan_tid, NULL, scan_thread, &scanner); pthread_create(&cleanup_tid, NULL, cleanup_thread, &scanner); // 启动ARP响应接收 int arp_sock = create_arp_socket(); while (1) { struct _ARP_HDR_new arp_resp; if (recv_arp(arp_sock, &arp_resp) > 0) { process_arp_response(&scanner, &arp_resp); } } // 清理资源 pthread_join(scan_tid, NULL); pthread_join(cleanup_tid, NULL); free(scanner.entries); close(arp_sock); return 0; }

我给你一个我的arp的代码,帮我写接口,代码如下#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/ioctl.h> #include <net/ethernet.h> #include <arpa/inet.h> #include "arp.h" #include #include <time.h> #include <netinet/ether.h> #define ETH_HEADER_SIZE 14 #define ARP_PACKET_SIZE 42 #define INITIAL_SIZE 1024 unsigned int if_nametoindex(const char *ifname) { struct ifreq ifr; int sockfd; sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { perror("socket"); return 0; } memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1); if (ioctl(sockfd, SIOCGIFINDEX, &ifr) < 0) { close(sockfd); perror("ioctl"); return 0; } close(sockfd); return ifr.ifr_ifru.ifru_metric; } /*获取本机mac地址*/ void get_local_mac(uint8_t *mac) { struct ifreq ifr; int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); if (sock < 0) { perror("socket"); exit(EXIT_FAILURE); } // 使用eth0接口,可根据需要修改 strncpy(ifr.ifr_name, "ens33", IFNAMSIZ); if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) { perror("ioctl"); close(sock); exit(EXIT_FAILURE); } memcpy(mac, ifr.ifr_ifru.ifru_hwaddr.sa_data, 6); close(sock); } /*获取本机ip地址*/ void get_local_ip(struct in_addr *local_ip) { struct ifreq ifr; int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); if (sock < 0) { perror("socket"); exit(EXIT_FAILURE); } // 使用eth0接口,可根据需要修改 strncpy(ifr.ifr_name, "ens33", IFNAMSIZ); if (ioctl(sock, SIOCGIFADDR, &ifr) < 0) { perror("ioctl"); close(sock); exit(EXIT_FAILURE); } struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_ifru.ifru_addr; *local_ip = sin->sin_addr; close(sock); } /*发送ARP请求*/ void send_arp(int sock, struct _ARP_HDR_new *arp) { // 构建完整的以太网帧 uint8_t packet[ARP_PACKET_SIZE]; // 以太网目标地址(广播) memset(packet, 0xFF, 6); // 以太网源地址(本机MAC) //get_local_mac(packet + 6); struct in_addr local_ip; get_local_ip(&local_ip); memcpy(packet + 6, &local_ip, sizeof(local_ip)); // 以太网类型(ARP) packet[12] = 0x08; // ETH_P_ARP高位 packet[13] = 0x06; // ETH_P_ARP低位 // ARP包内容 memcpy(packet + ETH_HEADER_SIZE, arp, sizeof(*arp)); // 发送到网络接口 struct sockaddr_ll dest = { .sll_family = AF_PACKET, .sll_protocol = htons(ETH_P_ARP), .sll_ifindex = if_nametoindex("ens33"), // 使用eth0接口 .sll_halen = ETH_ALEN, .sll_addr = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} // 广播地址 }; if (sendto(sock, packet, ARP_PACKET_SIZE, 0, (struct sockaddr *)&dest, sizeof(dest)) < 0) { perror("sendto"); } } /*接收ARP包*/ int recv_arp(int sock, struct _ARP_HDR_new *arp_resp) { uint8_t buffer[ETH_FRAME_LEN]; ssize_t len = recv(sock, buffer, sizeof(buffer), 0); if (len < ETH_HEADER_SIZE) { return -1; // 接收失败 } // 检查是否为ARP包 if (buffer[12] != 0x08 || buffer[13] != 0x06) { return -1; // 非ARP包 } // 解析ARP包 struct _ARP_HDR_new *arp = (struct _ARP_HDR_new *)(buffer + ETH_HEADER_SIZE); // 检查是否为ARP响应 if (ntohs(arp->ar_op) != ARPOP_REPLY) { return -1; // 非ARP响应 } memcpy(arp_resp, arp, sizeof(arp)); return len; } // 查找或创建ARP条目 arp_entry* find_or_create_entry(arp_scanner *scanner, uint32_t ip) { // 首先尝试查找现有条目 for (int i = 0; i < scanner->entry_count; i++) { if (scanner->entries[i].ip == ip) { return &scanner->entries[i]; } } // 如果表已满,扩展容量 if (scanner->entry_count >= scanner->max_entries) { int new_size = scanner->max_entries * 2; arp_entry *new_entries = realloc(scanner->entries, new_size * sizeof(arp_entry)); if (!new_entries) { perror("realloc"); return NULL; } scanner->entries = new_entries; scanner->max_entries = new_size; } // 创建新条目 arp_entry *new_entry = &scanner->entries[scanner->entry_count++]; new_entry->ip = ip; memset(new_entry->mac, 0, ETH_ALEN); new_entry->last_update = time(NULL); new_entry->expire_time = new_entry->last_update + scanner->config.entry_ttl; return new_entry; } // 创建原始套接字 int create_arp_socket() { int sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP)); if (sock < 0) { perror("socket"); exit(EXIT_FAILURE); } return sock; } // 构建ARP请求报文 void build_arp_packet(struct _ARP_HDR_new *arp, uint32_t target_ip) { arp->ar_hrd = htons(ARPHRD_ETHER); arp->ar_pro = htons(ETHERTYPE_IP); arp->ar_hln = ETH_ALEN; arp->ar_pln = sizeof(in_addr_t); arp->ar_op = htons(ARPOP_REQUEST); // 设置源MAC(本机MAC) get_local_mac(arp->ar_sha); // 设置源IP(本机IP) struct in_addr local_ip; get_local_ip(&local_ip); memcpy(arp->ar_sip, &local_ip, sizeof(local_ip)); // 设置目标MAC(广播) memset(arp->ar_tha, 0x00, ETH_ALEN); // 设置目标IP memcpy(arp->ar_tip, &target_ip, sizeof(target_ip)); } // ARP扫描线程 void* scan_thread(void *arg) { arp_scanner *scanner = (arp_scanner*)arg; int sock = create_arp_socket(); while (scanner->config.enable_scan) { pthread_mutex_lock(&scanner->lock); config_t cfg = scanner->config; pthread_mutex_unlock(&scanner->lock); // 转换为主机字节序 uint32_t host_start_ip = ntohl(cfg.start_ip); uint32_t host_end_ip = ntohl(cfg.end_ip); // 打印当前扫描范围 char start_ip_str[INET_ADDRSTRLEN]; char end_ip_str[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &cfg.start_ip, start_ip_str, sizeof(start_ip_str)); inet_ntop(AF_INET, &cfg.end_ip, end_ip_str, sizeof(end_ip_str)); printf("[SCAN] Scanning from %s to %s\n", start_ip_str, end_ip_str); // 遍历IP范围(使用主机字节序递增) for (uint32_t host_ip = host_start_ip; host_ip <= host_end_ip; host_ip++) { uint32_t net_ip = htonl(host_ip); // 转回网络字节序 char ip_str[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &net_ip, ip_str, sizeof(ip_str)); printf("[SCAN] Sending ARP to %s\n", ip_str); struct _ARP_HDR_new arp_req; build_arp_packet(&arp_req, net_ip); // 发送ARP请求 send_arp(sock, &arp_req); // 按间隔等待 usleep(cfg.packet_interval * 1000); } // 等待扫描周期 sleep(cfg.scan_cycle); } close(sock); return NULL; } // ARP响应处理 void process_arp_response(arp_scanner *scanner, struct _ARP_HDR_new *arp) { uint32_t ip; memcpy(&ip, arp->ar_sip, sizeof(ip)); pthread_mutex_lock(&scanner->lock); // 查找或创建条目 arp_entry *entry = find_or_create_entry(scanner, ip); memcpy(entry->mac, arp->ar_sha, ETH_ALEN); entry->last_update = time(NULL); entry->expire_time = entry->last_update + scanner->config.entry_ttl; pthread_mutex_unlock(&scanner->lock); } // 超时清理线程 void* cleanup_thread(void *arg) { arp_scanner *scanner = (arp_scanner*)arg; while (1) { sleep(5); // 每5秒检查一次 pthread_mutex_lock(&scanner->lock); time_t now = time(NULL); for (int i = 0; i < scanner->entry_count; ) { if (scanner->entries[i].expire_time < now) { // 移除超时条目 memmove(&scanner->entries[i], &scanner->entries[i+1], (scanner->entry_count - i - 1) * sizeof(arp_entry)); scanner->entry_count--; } else { i++; } } pthread_mutex_unlock(&scanner->lock); } return NULL; } // 动态调整内存 void resize_entries(arp_scanner *scanner, int new_size) { arp_entry *new_entries = realloc(scanner->entries, new_size * sizeof(arp_entry)); if (new_entries) { scanner->entries = new_entries; scanner->max_entries = new_size; } } void update_config(arp_scanner *scanner, config_t new_config) { pthread_mutex_lock(&scanner->lock); // 验证IP范围有效性 if (ntohl(new_config.end_ip) < ntohl(new_config.start_ip)) { fprintf(stderr, "Invalid IP range\n"); } else { scanner->config = new_config; } pthread_mutex_unlock(&scanner->lock); } // 配置 config_t default_config = { .enable_scan = 1, .scan_cycle = 300, // 5分钟 .packet_interval = 100, // 100毫秒 .entry_ttl = 1800, // 30分钟 .start_ip=1, .end_ip=1 }; int main() { default_config.start_ip = inet_addr("192.168.157.1"); default_config.end_ip = inet_addr("192.168.157.254"); arp_scanner scanner = { .entries = malloc(INITIAL_SIZE * sizeof(arp_entry)), .entry_count = 0, .max_entries = INITIAL_SIZE, .config = default_config }; pthread_mutex_init(&scanner.lock, NULL); // 启动扫描线程 pthread_t scan_tid, cleanup_tid; pthread_create(&scan_tid, NULL, scan_thread, &scanner); pthread_create(&cleanup_tid, NULL, cleanup_thread, &scanner); // 启动ARP响应接收 int arp_sock = create_arp_socket(); while (1) { struct _ARP_HDR_new arp_resp; if (recv_arp(arp_sock, &arp_resp) > 0) { process_arp_response(&scanner, &arp_resp); } } // 清理资源 pthread_join(scan_tid, NULL); pthread_join(cleanup_tid, NULL); free(scanner.entries); close(arp_sock); return 0; } 需要写这几个接口,arp子模块需要提供基于DMS的ubus服务接口,至少提供以下接口用于客户端调用,使用TDCP协议: set_arp_config(设置功能开关、扫描周期、有效期、发包间隔、起始IP、结束IP地址) get_arp_config(获取功能开关、扫描周期、有效期、发包间隔、起始IP、结束IP地址) start_scan(开始一次扫描) stop_scan(停止扫描) get_scan_status(扫描状态) get_scan_result(获取最近一次的扫描结果) clear_result(清除历史结果)

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #include <net/if.h> #include <netinet/if_ether.h> #include <netinet/ether.h> #include <netpacket/packet.h> #define ETH_ARP 0x0806 // ARP协议以太网类型 #define ARP_REQUEST 1 // ARP请求操作码 #define ARP_REPLY 2 // ARP响应操作码 #define BUF_SIZE 1024 // ARP包头结构体 (RFC 826) struct arp_header { uint16_t htype; // 硬件类型 uint16_t ptype; // 协议类型 uint8_t hlen; // 硬件地址长度 uint8_t plen; // 协议地址长度 uint16_t oper; // 操作码 uint8_t sha[6]; // 发送方MAC uint8_t spa[4]; // 发送方IP uint8_t tha[6]; // 目标MAC uint8_t tpa[4]; // 目标IP }; int main(int argc, char *argv[]) { if (argc != 4) { fprintf(stderr, "Usage: %s <bridge_interface> <start_ip> <end_ip>\n", argv[0]); fprintf(stderr, "Example: %s br0 192.168.1.1 192.168.1.254\n"); exit(EXIT_FAILURE); } char *iface = argv[1]; // 桥接接口名,如br0 char *start_ip = argv[2]; // 起始IP char *end_ip = argv[3]; // 结束IP // 创建原始套接字 (AF_PACKET: 链路层访问) int sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (sock < 0) { perror("Socket creation failed"); exit(EXIT_FAILURE); } // 绑定到桥接接口 struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, iface, IFNAMSIZ); if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0) { perror("Bind to interface failed"); close(sock); exit(EXIT_FAILURE); } // 构造以太网帧 + ARP请求 uint8_t broadcast_mac[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // 广播MAC uint8_t local_mac[6]; struct ifreq mac_req; strncpy(mac_req.ifr_name, iface, IFNAMSIZ); if (ioctl(sock, SIOCGIFHWADDR, &mac_req) < 0) { // 获取本机MAC perror("Get MAC failed"); close(sock); exit(EXIT_FAILURE); } memcpy(local_mac, mac_req.ifr_hwaddr.sa_data, 6); // 发送ARP请求到每个IP struct sockaddr_ll sa; memset(&sa, 0, sizeof(sa)); sa.sll_family = AF_PACKET; sa.sll_ifindex = if_nametoindex(iface); sa.sll_halen = ETH_ALEN; memcpy(sa.sll_addr, broadcast_mac, 6); // 目标MAC=广播 for (uint32_t ip = ntohl(inet_addr(start_ip)); ip <= ntohl(inet_addr(end_ip)); ip++) { uint8_t packet[BUF_SIZE]; struct ethhdr *eth = (struct ethhdr *)packet; struct arp_header *arp = (struct arp_header *)(packet + sizeof(struct ethhdr)); // 填充以太网帧头 memcpy(eth->h_dest, broadcast_mac, 6); memcpy(eth->h_source, local_mac, 6); eth->h_proto = htons(ETH_ARP); // 类型=ARP // 填充ARP包头 arp->htype = htons(1); // 以太网 arp->ptype = htons(ETH_P_IP); // IPv4 arp->hlen = 6; // MAC长度 arp->plen = 4; // IP长度 arp->oper = htons(ARP_REQUEST); // 操作码=请求 memcpy(arp->sha, local_mac, 6); // 发送方MAC(本机) inet_pton(AF_INET, "0.0.0.0", arp->spa); // 发送方IP(通常设为0) memset(arp->tha, 0, 6); // 目标MAC(未知) uint32_t target_ip = htonl(ip); memcpy(arp->tpa, &target_ip, 4); // 目标IP // 发送数据包 if (sendto(sock, packet, sizeof(struct ethhdr) + sizeof(struct arp_header), 0, (struct sockaddr *)&sa, sizeof(sa)) < 0) { perror("Send ARP request failed"); } usleep(1000); // 避免洪水攻击,延迟1ms } // 捕获ARP响应 printf("Scanning MAC addresses on %s...\n", iface); printf("IP Address\t\tMAC Address\n"); printf("----------------------------------------\n"); while (1) { uint8_t buffer[BUF_SIZE]; ssize_t len = recvfrom(sock, buffer, BUF_SIZE, 0, NULL, NULL); if (len < 0) { perror("Packet receive error"); break; } // 检查以太网类型是否为ARP struct ethhdr *recv_eth = (struct ethhdr *)buffer; if (ntohs(recv_eth->h_proto) != ETH_ARP) continue; // 解析ARP包头 struct arp_header *recv_arp = (struct arp_header *)(buffer + sizeof(struct ethhdr)); if (ntohs(recv_arp->oper) != ARP_REPLY) continue; // 仅处理响应 // 打印IP和MAC char ip_str[INET_ADDRSTRLEN]; inet_ntop(AF_INET, recv_arp->spa, ip_str, INET_ADDRSTRLEN); printf("%-15s\t\t%02X:%02X:%02X:%02X:%02X:%02X\n", ip_str, recv_arp->sha[0], recv_arp->sha[1], recv_arp->sha[2], recv_arp->sha[3], recv_arp->sha[4], recv_arp->sha[5]); } close(sock); return 0; } 怎么修改

这是arp_scanner.c:/* Copyright (c) 2009-2025 TP-LINK Technologies CO.,LTD. * * file None * brief None * details None * * author Wei Gan <[email protected]> * version 1.0.0 * date 31Jul25 * * history \arg version, date, author, modification */ /**************************************************************************************************/ /* INCLUDE */ /**************************************************************************************************/ #include <sys/socket.h> #include #include <net/ethernet.h> #include <sys/ioctl.h> #include <netinet/in.h> #include <arpa/inet.h> #include <net/if.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "arp_scanner.h" /**************************************************************************************************/ /* DEFINES */ /**************************************************************************************************/ /**************************************************************************************************/ /* TYPES */ /**************************************************************************************************/ /**************************************************************************************************/ /* VARIABLES */ /**************************************************************************************************/ /**************************************************************************************************/ /* FUNCTIONS */ /**************************************************************************************************/ /* 创建原始socket */ int create_arp_socket() { int sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP)); if (sock < 0) { perror("socket"); return -1; } return sock; } /* * fn static int send_arp_request(int sockfd, const char *src_ip, const char *dest_ip, const char *ifname) * brief 发送ARP请求 * details None * * param[in] sockfd 套接字 * param[in] src_ip 源ip * param[in] ifname 网卡名 * param[out]None * return None * * retval None * note None */ static int send_arp_request(int sockfd, const char *src_ip, const char *dest_ip, const char *ifname) { // 获取接口索引 struct ifreq ifr; strncpy(ifr.ifr_name, ifname, IFNAMSIZ); if (ioctl(sockfd, SIOCGIFINDEX, &ifr) < 0) { perror("ioctl(SIOCGIFINDEX)"); return -1; } // 获取接口MAC地址 if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) < 0) { perror("ioctl(SIOCGIFHWADDR)"); return -1; } uint8_t src_mac[6]; memcpy(src_mac, ifr.ifr_hwaddr.sa_data, 6); // 构建以太网帧和ARP包 unsigned char packet[60] = {0}; struct ether_header *eth = (struct ether_header *)packet; struct ether_arp *arp = (struct ether_arp *)(packet + sizeof(struct ether_header)); /************** 填充以太网帧头 **************/ // 目标MAC: 广播地址 (FF:FF:FF:FF:FF:FF) memset(eth->ether_dhost, 0xFF, 6); // 源MAC: 接口MAC地址 memcpy(eth->ether_shost, src_mac, 6); // 以太网类型: ARP (0x0806) eth->ether_type = htons(ETHERTYPE_ARP); /************** 填充ARP包 **************/ // 硬件类型: 以太网 (1) arp->arp_hrd = htons(ARPHRD_ETHER); // 协议类型: IPv4 (0x0800) arp->arp_pro = htons(ETHERTYPE_IP); // 硬件地址长度: 6字节 (MAC) arp->arp_hln = 6; // 协议地址长度: 4字节 (IPv4) arp->arp_pln = 4; // 操作码: ARP请求 (1) arp->arp_op = htons(ARPOP_REQUEST); // 源MAC: 接口MAC地址 memcpy(arp->arp_sha, src_mac, 6); // 源IP: 将字符串转换为网络字节序 struct in_addr src_addr; if (inet_pton(AF_INET, src_ip, &src_addr) <= 0) { perror("inet_pton(src_ip)"); return -1; } memcpy(arp->arp_spa, &src_addr.s_addr, 4); // 目标MAC: ARP请求中设为全0 (未知) memset(arp->arp_tha, 0, 6); // 目标IP: 将字符串转换为网络字节序 struct in_addr dest_addr; if (inet_pton(AF_INET, dest_ip, &dest_addr) <= 0) { perror("inet_pton(dest_ip)"); return -1; } memcpy(arp->arp_tpa, &dest_addr.s_addr, 4); /************** 发送数据包 **************/ struct sockaddr_ll sa = { .sll_family = AF_PACKET, .sll_ifindex = ifr.ifr_ifindex, .sll_halen = ETH_ALEN, .sll_addr = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} // 广播 }; if (sendto(sockfd, packet, sizeof(packet), 0, (struct sockaddr*)&sa, sizeof(sa)) < 0) { perror("sendto"); return -1; } return 0; } /* 处理ARP响应 */ static void jiaprocess_arp_response(arp_scanner_t *scanner, unsigned char *buffer, size_t len) { struct ether_arp *arp = (struct ether_arp *)(buffer + sizeof(struct ether_header)); // 提取IP和MAC char ip_str[INET_ADDRSTRLEN]; inet_ntop(AF_INET, arp->arp_spa, ip_str, sizeof(ip_str)); pthread_mutex_lock(&scanner->lock); // 检查是否是新主机 int is_new = 1; arp_entry_t *entry = scanner->entries; while (entry) { if (strcmp(entry->ip, ip_str) == 0) { memcpy(entry->mac, arp->arp_sha, 6); entry->last_seen = time(NULL); is_new = 0; break; } entry = entry->next; } // 发现新主机 if (is_new) { arp_entry_t *new_entry = malloc(sizeof(arp_entry_t)); strcpy(new_entry->ip, ip_str); memcpy(new_entry->mac, arp->arp_sha, 6); new_entry->last_seen = time(NULL); new_entry->next = scanner->entries; scanner->entries = new_entry; // 打印到串口 printf("[NEW HOST] IP: %s, MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", ip_str, arp->arp_sha[0], arp->arp_sha[1], arp->arp_sha[2], arp->arp_sha[3], arp->arp_sha[4], arp->arp_sha[5]); } pthread_mutex_unlock(&scanner->lock); } /* 清理过期条目 */ static void clean_expired_entries(arp_scanner_t *scanner) { time_t now = time(NULL); pthread_mutex_lock(&scanner->lock); arp_entry_t **pp = &scanner->entries; // **pp 保存的是链表头节点地址 while (*pp) { arp_entry_t *entry = *pp; if (now - entry->last_seen > scanner->config.valid_time) { *pp = entry->next; free(entry); } else { pp = &entry->next; } } pthread_mutex_unlock(&scanner->lock); } /* 接收ARP响应 */ void *arp_scan_thread(void *arg) { arp_scanner_t *scanner = (arp_scanner_t *)arg; scanner->scanning = SCANNING_ON; while (scanner->scanning) { // 清理过期条目 clean_expired_entries(scanner); // 遍历IP范围 for (uint32_t ip = inet_addr(scanner->config.start_ip); ip <= inet_addr(scanner->config.end_ip); ip = ntohl(ntohl(ip) + 1)) { if (!scanner->scanning) break; // scanning为0,停止扫描 // 发送ARP请求 char dest_ip[16]; inet_ntop(AF_INET, &ip, dest_ip, sizeof(dest_ip)); send_arp_request(scanner->sockfd, SOURCE_IP, dest_ip, IFNAME); // 接收响应 unsigned char buffer[ETH_FRAME_LEN]; struct sockaddr_ll saddr; socklen_t saddr_len = sizeof(saddr); fd_set fds; // 设置发包间隔 struct timeval tv = { .tv_usec = scanner->config.send_interval * 1000 }; FD_ZERO(&fds); FD_SET(scanner->sockfd, &fds); if (select(scanner->sockfd + 1, &fds, NULL, NULL, &tv) > 0) { ssize_t len = recvfrom(scanner->sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&saddr, &saddr_len); if (len > 0) { process_arp_response(scanner, buffer, len); } } } // 等待扫描间隔 int sleep_count = scanner->config.scan_interval; while (sleep_count > 0 && scanner->scanning) { sleep(1); sleep_count--; } } close(scanner->sockfd); scanner->sockfd = -1; scanner->scanning = SCANNING_OFF; return NULL; }

把这一个arp.c的代码拆分为多个文件,显得专业.h .c /*!Copyright(c) 2022-2023 Shenzhen TP-LINK Technologies Co.Ltd. *All rights reserved. * *\file arp.c *\brief An solution of task. * *\author liuyan *\version 1.0.0 *\date 22/8/2024 * *\history \arg 1.0.0 22/8/2024. liuyan. Create the file. */ /**************************************************************************************************/ /* INCLUDE_FILES */ /**************************************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #include <netinet/if_ether.h> #include <net/if.h> #include <sys/ioctl.h> #include #include <time.h> #include #include #include #include /**************************************************************************************************/ /* DEFINES */ /**************************************************************************************************/ #define ARP_REQUEST 1 #define ARP_REPLY 2 #define INTERFACES "eth0" /* 系统中可用的网络接口 */ #define MAX_ARP_ENTRIES 256 /**************************************************************************************************/ /* TYPES */ /**************************************************************************************************/ typedef struct { int enable; /* 功能开关 */ int scan_interval; /* 扫描周期(秒)*/ int entry_timeout; /* 有效期(秒)__ARP_CONFIG_MAX */ int packet_interval; /* 发包间隔(毫秒) */ struct in_addr start_ip; /* 起始IP */ struct in_addr end_ip; /* 结束IP */ } arp_config_t; typedef struct { struct in_addr ip_addr; unsigned char mac_addr[6]; time_t last_seen; } arp_entry_t; /* 在全局变量 g_arp_config 的定义处添加默认值 */ static arp_config_t g_arp_config = { .enable = 0, .scan_interval = 60, .entry_timeout = 300, .packet_interval = 100, .start_ip = { .s_addr = 0x0A000201 }, /* 10.0.2.1 */ .end_ip = { .s_addr = 0x0A0002FF } /* 10.0.2.255 */ }; enum { ARP_CONFIG_ENABLE, ARP_CONFIG_SCAN_INTERVAL, ARP_CONFIG_ENTRY_TIMEOUT, ARP_CONFIG_PACKET_INTERVAL, ARP_CONFIG_START_IP, ARP_CONFIG_END_IP, __ARP_CONFIG_MAX }; static const struct blobmsg_policy arp_config_policy[__ARP_CONFIG_MAX] = { [ARP_CONFIG_ENABLE] = { .name = "enable", .type = BLOBMSG_TYPE_INT32 }, [ARP_CONFIG_SCAN_INTERVAL] = { .name = "scan_interval", .type = BLOBMSG_TYPE_INT32 }, [ARP_CONFIG_ENTRY_TIMEOUT] = { .name = "entry_timeout", .type = BLOBMSG_TYPE_INT32 }, [ARP_CONFIG_PACKET_INTERVAL] = { .name = "packet_interval", .type = BLOBMSG_TYPE_INT32 }, [ARP_CONFIG_START_IP] = { .name = "start_ip", .type = BLOBMSG_TYPE_STRING }, [ARP_CONFIG_END_IP] = { .name = "end_ip", .type = BLOBMSG_TYPE_STRING }, }; static arp_entry_t g_arp_entries[MAX_ARP_ENTRIES]; static int g_arp_entry_count = 0; static pthread_mutex_t arp_mutex = PTHREAD_MUTEX_INITIALIZER; /**************************************************************************************************/ /* LOCAL_PROTOTYPES */ /**************************************************************************************************/ /* 发送arp请求 */ void send_arp_request(int sock, struct sockaddr_ll *socket_address, unsigned char *src_mac, unsigned char *src_ip, unsigned char *dst_ip); /* 处理arp回复 */ void process_arp_reply(unsigned char *buffer, size_t length); /* arp回复线程 */ void* arp_reply_thread(void* arg); /* arp扫描线程 */ void* arp_scan_thread(void* arg); /* 开始arp扫描 */ void start_arp_scan(); /* 停止arp扫描 */ void stop_arp_scan(); /* 清除历史结果 */ void clear_arp_entries(); /* 设置arp的config */ void set_arp_config(arp_config_t *config); /* 获取arp的config */ void get_arp_config(arp_config_t *config); /* UBUS服务接口实现 */ int ubus_set_arp_config(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg); int ubus_get_arp_config(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg); int ubus_start_scan(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg); int ubus_stop_scan(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg); int ubus_get_scan_status(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg); int ubus_get_scan_result(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg); int ubus_clear_result(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg); /**************************************************************************************************/ /* PUBLIC_FUNCTIONS */ /**************************************************************************************************/ /* 发送arp请求 */ void send_arp_request(int sock, struct sockaddr_ll *socket_address, unsigned char *src_mac, unsigned char *src_ip, unsigned char *dst_ip) { unsigned char buffer[42]; struct ethhdr *eth = (struct ethhdr *)buffer; struct arp_header { unsigned short hw_type; unsigned short proto_type; unsigned char hw_len; unsigned char proto_len; unsigned short opcode; unsigned char src_mac[6]; unsigned char src_ip[4]; unsigned char dst_mac[6]; unsigned char dst_ip[4]; } *arp = (struct arp_header *)(buffer + 14); /* 填充以太网头部 */ memset(eth->h_dest, 0xff, 6); /* 广播地址 */ memcpy(eth->h_source, src_mac, 6); eth->h_proto = htons(ETH_P_ARP); /* 填充ARP报文 */ arp->hw_type = htons(1); arp->proto_type = htons(ETH_P_IP); arp->hw_len = 6; arp->proto_len = 4; arp->opcode = htons(ARP_REQUEST); memcpy(arp->src_mac, src_mac, 6); memcpy(arp->src_ip, src_ip, 4); memset(arp->dst_mac, 0x00, 6); /* 目标MAC地址未知 */ memcpy(arp->dst_ip, dst_ip, 4); /* 发送ARP请求 */ if (sendto(sock, buffer, 42, 0, (struct sockaddr *)socket_address, sizeof(struct sockaddr_ll)) < 0) { perror("sendto failed"); exit(1); } } /* 处理arp回复 */ void process_arp_reply(unsigned char *buffer, size_t length) { struct ethhdr *eth = (struct ethhdr *)buffer; int i; if (ntohs(eth->h_proto) == ETH_P_ARP) { struct arp_header { unsigned short hw_type; unsigned short proto_type; unsigned char hw_len; unsigned char proto_len; unsigned short opcode; unsigned char src_mac[6]; unsigned char src_ip[4]; unsigned char dst_mac[6]; unsigned char dst_ip[4]; } *arp = (struct arp_header *)(buffer + 14); if (ntohs(arp->opcode) == ARP_REPLY) { pthread_mutex_lock(&arp_mutex); /* 检查是否已经存在该IP的条目 */ int found = 0; for (i = 0; i < g_arp_entry_count; ++i) { if (memcmp(&g_arp_entries[i].ip_addr, arp->src_ip, sizeof(struct in_addr)) == 0) { memcpy(g_arp_entries[i].mac_addr, arp->src_mac, 6); g_arp_entries[i].last_seen = time(NULL); found = 1; break; } } /* 如果是新主机,打印到串口并添加到条目 */ if (!found && g_arp_entry_count < MAX_ARP_ENTRIES) { printf("New host found: %d.%d.%d.%d with MAC address %02x:%02x:%02x:%02x:%02x:%02x\n", arp->src_ip[0], arp->src_ip[1], arp->src_ip[2], arp->src_ip[3], arp->src_mac[0], arp->src_mac[1], arp->src_mac[2], arp->src_mac[3], arp->src_mac[4], arp->src_mac[5]); memcpy(&g_arp_entries[g_arp_entry_count].ip_addr, arp->src_ip, sizeof(struct in_addr)); memcpy(g_arp_entries[g_arp_entry_count].mac_addr, arp->src_mac, 6); g_arp_entries[g_arp_entry_count].last_seen = time(NULL); ++g_arp_entry_count; } pthread_mutex_unlock(&arp_mutex); } } } /* arp回复线程 */ void* arp_reply_thread(void* arg) { int sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP)); if (sock < 0) { perror("socket failed"); return NULL; } struct ifreq ifr; strncpy(ifr.ifr_name, INTERFACES, IFNAMSIZ); if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0) { perror("ioctl failed"); close(sock); return NULL; } struct sockaddr_ll socket_address; socket_address.sll_ifindex = ifr.ifr_ifindex; socket_address.sll_halen = ETH_ALEN; memset(socket_address.sll_addr, 0xff, 6); unsigned char buffer[1500]; while (1) { ssize_t length = recvfrom(sock, buffer, sizeof(buffer), 0, NULL, NULL); if (length < 0) { perror("recvfrom failed"); close(sock); return NULL; } process_arp_reply(buffer, length); } close(sock); return NULL; } /* arp扫描线程 */ void* arp_scan_thread(void* arg) { int sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP)); if (sock < 0) { perror("socket failed"); return NULL; } struct ifreq ifr; strncpy(ifr.ifr_name, INTERFACES, IFNAMSIZ); if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0) { perror("ioctl failed"); close(sock); return NULL; } struct sockaddr_ll socket_address; socket_address.sll_ifindex = ifr.ifr_ifindex; socket_address.sll_halen = ETH_ALEN; memset(socket_address.sll_addr, 0xff, 6); unsigned char src_mac[6]; if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) { perror("ioctl failed"); close(sock); return NULL; } memcpy(src_mac, ifr.ifr_hwaddr.sa_data, 6); unsigned char src_ip[4]; inet_pton(AF_INET, "10.0.2.15", src_ip); /* 这里使用实际的源IP地址 */ while (g_arp_config.enable) { struct in_addr current_ip = g_arp_config.start_ip; while (memcmp(¤t_ip, &g_arp_config.end_ip, sizeof(struct in_addr)) <= 0) { unsigned char dst_ip[4]; memcpy(dst_ip, ¤t_ip, 4); send_arp_request(sock, &socket_address, src_mac, src_ip, dst_ip); /* 更新IP地址 */ uint32_t ip_int = ntohl(current_ip.s_addr); current_ip.s_addr = htonl(ip_int + 1); usleep(g_arp_config.packet_interval * 1000); } sleep(g_arp_config.scan_interval); } close(sock); return NULL; } /* 开始arp扫描 */ void start_arp_scan() { pthread_t thread_id; g_arp_config.enable = 1; pthread_create(&thread_id, NULL, arp_scan_thread, NULL); pthread_detach(thread_id); } /* 停止arp扫描 */ void stop_arp_scan() { g_arp_config.enable = 0; } /* 清除历史结果 */ void clear_arp_entries() { pthread_mutex_lock(&arp_mutex); g_arp_entry_count = 0; pthread_mutex_unlock(&arp_mutex); } /* 配置管理功能 */ /* 设置arp的config */ void set_arp_config(arp_config_t *config) { memcpy(&g_arp_config, config, sizeof(arp_config_t)); if (config->enable) { start_arp_scan(); } else { stop_arp_scan(); } } /* 获取arp的config */ void get_arp_config(arp_config_t *config) { memcpy(config, &g_arp_config, sizeof(arp_config_t)); } /* UBUS服务接口实现 */ int ubus_set_arp_config(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { struct blob_attr *tb[__ARP_CONFIG_MAX]; arp_config_t config; blobmsg_parse(arp_config_policy, __ARP_CONFIG_MAX, tb, blob_data(msg), blob_len(msg)); if (tb[ARP_CONFIG_ENABLE]) { config.enable = blobmsg_get_u32(tb[ARP_CONFIG_ENABLE]); } if (tb[ARP_CONFIG_SCAN_INTERVAL]) { config.scan_interval = blobmsg_get_u32(tb[ARP_CONFIG_SCAN_INTERVAL]); } if (tb[ARP_CONFIG_ENTRY_TIMEOUT]) { config.entry_timeout = blobmsg_get_u32(tb[ARP_CONFIG_ENTRY_TIMEOUT]); } if (tb[ARP_CONFIG_PACKET_INTERVAL]) { config.packet_interval = blobmsg_get_u32(tb[ARP_CONFIG_PACKET_INTERVAL]); } if (tb[ARP_CONFIG_START_IP]) { inet_pton(AF_INET, blobmsg_get_string(tb[ARP_CONFIG_START_IP]), &config.start_ip); } if (tb[ARP_CONFIG_END_IP]) { inet_pton(AF_INET, blobmsg_get_string(tb[ARP_CONFIG_END_IP]), &config.end_ip); } set_arp_config(&config); return 0; } int ubus_get_arp_config(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { arp_config_t config; struct blob_buf b = { 0 }; get_arp_config(&config); blob_buf_init(&b, 0); blobmsg_add_u32(&b, "enable", config.enable); blobmsg_add_u32(&b, "scan_interval", config.scan_interval); blobmsg_add_u32(&b, "entry_timeout", config.entry_timeout); blobmsg_add_u32(&b, "packet_interval", config.packet_interval); char ip_str[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &config.start_ip, ip_str, sizeof(ip_str)); blobmsg_add_string(&b, "start_ip", ip_str); inet_ntop(AF_INET, &config.end_ip, ip_str, sizeof(ip_str)); blobmsg_add_string(&b, "end_ip", ip_str); ubus_send_reply(ctx, req, b.head); return 0; } int ubus_start_scan(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { start_arp_scan(); return 0; } int ubus_stop_scan(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { stop_arp_scan(); return 0; } int ubus_get_scan_status(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { struct blob_buf b = { 0 }; blob_buf_init(&b, 0); printf("scan_running: %d (1:enable; 0:disable)\n", g_arp_config.enable); blobmsg_add_u32(&b, "scan_running", g_arp_config.enable); if (req == NULL) { fprintf(stderr, "ubus_get_scan_status: req is NULL, this might be a test environment.\n"); return -1; } ubus_send_reply(ctx, req, b.head); return 0; } int ubus_get_scan_result(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { struct blob_buf b = { 0 }; blob_buf_init(&b, 0); pthread_mutex_lock(&arp_mutex); printf("host number:%d\n", g_arp_entry_count); printf("print ip and mac:\n"); if (0 == g_arp_entry_count) { printf("ip:None\tmac:None\n"); } int i; for (i = 0; i < g_arp_entry_count; ++i) { char ip_buf[INET_ADDRSTRLEN]; char mac_buf[18]; inet_ntop(AF_INET, &g_arp_entries[i].ip_addr, ip_buf, sizeof(ip_buf)); printf("ip address: %s\t", ip_buf); printf("mac address: %02x:%02x:%02x:%02x:%02x:%02x\n", g_arp_entries[i].mac_addr[0], g_arp_entries[i].mac_addr[1], g_arp_entries[i].mac_addr[2], g_arp_entries[i].mac_addr[3], g_arp_entries[i].mac_addr[4], g_arp_entries[i].mac_addr[5]); snprintf(mac_buf, sizeof(mac_buf), "%02x:%02x:%02x:%02x:%02x:%02x", g_arp_entries[i].mac_addr[0], g_arp_entries[i].mac_addr[1], g_arp_entries[i].mac_addr[2], g_arp_entries[i].mac_addr[3], g_arp_entries[i].mac_addr[4], g_arp_entries[i].mac_addr[5]); void *entry_table = blobmsg_open_table(&b, NULL); blobmsg_add_string(&b, "ip", ip_buf); blobmsg_add_string(&b, "mac", mac_buf); blobmsg_close_table(&b, entry_table); } pthread_mutex_unlock(&arp_mutex); if (req == NULL) { fprintf(stderr, "ubus_get_scan_result: req is NULL, this might be a test environment.\n"); return -1; } ubus_send_reply(ctx, req, b.head); return 0; } int ubus_clear_result(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { clear_arp_entries(); return 0; } static const struct ubus_method arp_methods[] = { UBUS_METHOD("set_arp_config", ubus_set_arp_config, arp_config_policy), UBUS_METHOD_NOARG("get_arp_config", ubus_get_arp_config), UBUS_METHOD_NOARG("start_scan", ubus_start_scan), UBUS_METHOD_NOARG("stop_scan", ubus_stop_scan), UBUS_METHOD_NOARG("get_scan_status", ubus_get_scan_status), UBUS_METHOD_NOARG("get_scan_result", ubus_get_scan_result), UBUS_METHOD_NOARG("clear_result", ubus_clear_result), }; static struct ubus_object_type arp_object_type = UBUS_OBJECT_TYPE("arp", arp_methods); struct ubus_object arp_object = { .name = "arp", .type = &arp_object_type, .methods = arp_methods, .n_methods = ARRAY_SIZE(arp_methods), }; static int arp_init() { /* 创建一个线程来处理ARP回复 */ pthread_t thread_id; pthread_create(&thread_id, NULL, arp_reply_thread, NULL); pthread_detach(thread_id); /* 初始化UBus */ uloop_init(); struct ubus_context *ctx = ubus_connect(NULL); if (!ctx) { fprintf(stderr, "Failed to connect to ubus\n"); return -1; } return 1; } struct ubus_context *ctx = NULL; static void arp_start() { /* 开始扫描 */ printf("\nStarting ARP scan...\n"); start_arp_scan(); printf("ARP scan started.\n"); } static void arp_stop() { /* 停止扫描 */ printf("\nStopping ARP scan...\n"); ubus_stop_scan(ctx, &arp_object, NULL, NULL, NULL); printf("ARP scan stopped.\n"); } static void arp_main() { DS_MOD_DESC arp_module = DS_STRUCT_MOD("arp", arp_init, NULL, NULL, arp_start, arp_stop, NULL, NULL); /* 将模块注册到ds_roor的链表上 */ MODULE *module_node = ds_register_module("arp", &arp_module); SDM_ASSERT(NULL != module_node); } NSD_INIT(arp_main); /* 注册到init_array,在init阶段对数据模型的参数进行初始化 */

大家在看

recommend-type

ispVM18.1.1

lattice 下载工具 ispVM tool FPGA/CPLD烧写工具,并口及适配器通用FPGA/CPLD烧写工具,并口及适配器通用
recommend-type

fonteditorV1.3.2.zip 字体工具

FontEditor为一款功能强大的字体编辑和字体格式转换工具,支持制作32*32的全字库。能将TTF,OTF矢量字库转换为BDF字符,可以很方便的将Windows已经安装到系统的矢量字库转换为BDF字库,并能将TTF,OTF文件直接转换成BDF格式,并支持BDF,FNT,FNB文件格式的互转换,随心所欲将windows字体应用于各种嵌入式系统中。并支持将GB2312,BIG5,GBK转换为UCS2,UTF8,并支持UCS2,UTF8编码的互转换   V1.2  运行环境:Win2003, WinXP, Win2000, NT, WinME   (1)BDF,FNT,FNB字体格式的互转换   (2)将Windows已经安装TTF转换为BDF格式   (3)将TTF文件导入转为BDF,FNT,FNB格式   (4)汉字查码   V1.25   (1)Windows已经安装TTF字体导入为BDF时,剔除无效字符   (2)将BDF,FNT,FNB导出为bitmap文件和字符宽度索引   (3)GB2312,BIG5,GBK转换为UCS2,UTF8,以及UCS2,UTF8互转换   V1.25.03   (1)将单个字符导出为Bitmap文件   (2)解决导出字库bitmap时,字符少于256个导出文件不正确的问题   (3)解决导出选择中字符实际上是导出所有字符的问题   V1.26   (1)增加修正字符点阵的功能,可对所有字符或者当前页字符的点阵大小和位移进行调整   (2)修正V1.25.03中导出位图文件选择取消无法退出程序的问题   V1.3   (1)增加导出全字库bitmap方式,同时支持二进制导出和ASCII码导出   (2)增强读取BDF文件的兼容性   (3)增加手动剔除无效字符功能   V1.3.2   (1)增加TTF文件导入调整字符点阵大小,控制位图的精度和导入位图的效果   运行环境:Win2003, WinXP, Win2000, NT, WinME
recommend-type

Mydac v8.6 Pro Full D7-XE7-XE8-Seatle 10

Mydac v8.6 Pro Full D7-XE7-XE8-Seatle 10
recommend-type

蒙特卡罗剂量模拟和可视化工具包:一组旨在帮助临床医生和研究人员使用 GEANT4 或 TOPAS 的 Matlab 函数-matlab开发

这里有 3 组代码,旨在帮助临床医生和研究人员将 GEANT4 或 TOPAS (MC) 与 3D Slicer 结合使用进行剂量可视化和比较 第一段代码“STLfromDicomRN.m”采用 Varian Eclipse 生成的双散射质子计划的 Dicom 计划文件,并以“.STL”格式生成计划中的Kong径和补偿器模型。 此文件使用 zip 文件中包含的“stlwrite”和“surf2solid”函数。 这些文件可以导入到 MC 模拟几何中。 第二个是一组用于处理Dicom剂量文件和分析剂量的代码。 “NormalizeDicomDose.m”代码将 MC 剂量标准化为 Eclipse 剂量等中心处的剂量,并包含有关如何标准化为其他点或体积的说明。 “ProfilePlot.m”代码只是生成比较两点之间两个剂量文件的剂量的剂量曲线。 包含的是一个 matlab gui,它在您
recommend-type

按时间抽取的蝶形运算流图-FFT原理以及实现

按时间抽取的蝶形运算流图:

最新推荐

recommend-type

基于vue3.x、Typescript、vite、Elementplus等,适配手机、平板、pc的后台开源免费模板库(vue2.x请切换vue-prev-.zip

基于vue3.x、Typescript、vite、Elementplus等,适配手机、平板、pc的后台开源免费模板库(vue2.x请切换vue-prev-.zip
recommend-type

信息安全与渗透测试,密码编码,爬虫,数据安全,网络安全,Web 安全.zip

信息安全与渗透测试,密码编码,爬虫,数据安全,网络安全,Web 安全.zip
recommend-type

wp404_Zynq_Flex_Waveform_中英文对照版_2025年.pdf

wp404_Zynq_Flex_Waveform_中英文对照版_2025年
recommend-type

CompileTimeRegularExpressioninC++-original.zip

CompileTimeRegularExpressioninC++-original.zip
recommend-type

PythonlibrarytoreadtheDHTseriesofhumidityandtemperaturesensorsonaR.zip

PythonlibrarytoreadtheDHTseriesofhumidityandtemperaturesensorsonaR.zip
recommend-type

bls-wasm:Node.js下WebAssembly实现的BLS签名技术

### 知识点说明 #### 标题解析 - **WebAssembly**: 是一种新的代码执行格式,旨在提供一种在现代浏览器和服务器上都能运行的安全、快速的代码执行方式。WebAssembly最初的目标是让网页可以运行高性能的应用程序,比如游戏或视频编辑工具,但随着技术的发展,其应用场景已经扩展到服务器端。Node.js通过引入WebAssembly支持,使得可以在其环境中利用WebAssembly的能力执行高度优化的代码。 - **Node.js**: 是一个基于Chrome V8引擎的JavaScript运行环境,它执行JavaScript代码不需要浏览器支持。Node.js被设计为能够构建快速、可扩展的网络应用程序,尤其擅长处理大量并发连接的场景。 - **BLS签名**:BLS(Boneh-Lynn-Shacham)签名是一种基于密码学的签名方案。它在安全性、效率和功能上优于传统的ECDSA和RSA签名算法。BLS签名特别适合于区块链等需要快速验证大量签名的场景。 #### 描述解析 - **密钥和签名模型**: 描述了BLS签名方案中的基本要素:`Fr:SecretKey` 表示秘密密钥,而 `G2:PublicKey` 表示公钥。G1用于表示签名。在密码学中,密钥和签名的生成、使用和管理是确保系统安全的基础。 - **以太坊2.0兼容性**: 提到如果需要与以太坊2.0兼容的签名/验证,需要参考某些文档或指南。这暗示了`bls-wasm`库在区块链领域的重要性,特别是针对以太坊这样的平台,其正在向2.0版本升级,而新的版本将会使用BLS签名来改进网络的安全性和性能。 #### 使用指南 - **Node.js使用**: 通过`require('bls-wasm')`语句引入模块,展示了如何在Node.js环境中集成`bls-wasm`模块。 - **浏览器使用**: 对于在浏览器中使用,需要引入`bls.js`,并且通过`require('bls-wasm/browser')`的方式引入。这反映了WebAssembly模块的跨平台特点,能够适应不同的运行环境。 - **React使用**: 通过类似的方式`const bls = require('bls-wasm/browser')`说明了在React项目中如何集成`bls-wasm`。 - **版本兼容性**: 提到v0.4.2版本破坏了入口点的向后兼容性,意味着从这个版本开始,库的API可能发生了变更,需要开发者注意更新。 #### 执照信息 - **修改了新的执照**: 说明了关于软件许可证的新变化,暗示了库的许可证可能由之前的版本有所更新,需要用户关注和遵守新的许可证条款。 #### 压缩包文件信息 - **bls-wasm-master**: 由于提供了压缩包文件的名称列表,暗示了一个名为`bls-wasm`的项目,可能包含源代码、编译后的文件、文档等。 ### 知识点的深入拓展 #### WebAssembly在Node.js中的应用 WebAssembly在Node.js中的主要优势在于性能的提升,特别是在处理CPU密集型任务时。WebAssembly模块可以运行C/C++、Rust等语言编写的代码,并且这些代码在WebAssembly的沙盒环境中执行得非常快。 #### BLS签名在区块链中的作用 区块链技术依赖于密码学来确保交易的安全性和验证性。BLS签名因其在密钥长度、签名长度、签名速度以及多签性能等方面的优点,非常适合被用于区块链网络。它允许验证者更快地验证交易,并提高了区块链的处理能力。 #### Node.js环境下的安全实践 在Node.js环境中使用BLS签名或任何加密算法时,应当遵循安全实践,例如确保密钥的安全管理,避免在不安全的通道中传输密钥,以及定期更新和轮换密钥等。 #### 跨平台兼容性的重要性 对于WebAssembly模块来说,能够在不同的环境(如Node.js、浏览器、React应用等)中无缝工作是至关重要的。开发者需要关注不同平台间的API差异和兼容性问题。 #### 软件许可证的遵守 软件许可证规定了开发者如何使用该软件,以及他们可以对软件进行哪些修改和分发。遵循许可证的规定不仅可以避免法律风险,还可以确保代码的使用和传播不会侵犯原作者的权益。 综上所述,`bls-wasm`模块作为一个在WebAssembly环境下运行的BLS签名工具,为Node.js和Web开发者提供了强大的密码学能力,特别是对于希望支持以太坊2.0等区块链技术的项目。开发者在使用这类工具时,需要关注性能、兼容性、安全性和许可证等多方面的要求。
recommend-type

提升Linux终端使用效率的实用指南

### 提升 Linux 终端使用效率的实用指南 #### 1. i3wm 窗口管理基础操作 在 i3wm 中,创建新的窗口块(tiles)就等同于打开应用程序,因为所有应用程序都以窗口块的形式呈现在窗口管理器的网格中。 - **创建窗口块**: - 打开终端:使用 `win + enter`。 - 打开其他应用程序:按下 `win + d`,屏幕左上角会弹出一个小对话框,输入应用程序名称,对话框会显示自动补全状态,当显示目标程序时,按下“打开”,应用程序将以窗口块形式打开。 - **窗口块布局调整**: - 打开更多应用程序会在工作区自动创建更多窗口块,并在网格中分
recommend-type

现有以下数据: String[] keyAry: [{"fields":[{"name":"类型"}, {"name":"中问题", "width":"400px"}, {"name":"小问题", "width":"400px"}]}] String[] value: [{"fieldvalues":[{"value":"人员","row":0,"col":0},{"value":"1","row":0,"col":1},{"value":"1","row":0,"col":2}]},{"fieldvalues":[{"value":"设施","row":1,"col":0},{"value":"2","row":1,"col":1},{"value":"2","row":1,"col":2}]}] 请使用java语言将以上数据转化为word的表格,具体格式如下: 类型 中问题 小问题 人员 1 1 设施 2 2 其中,表格第一行是keyAry数组的name属性,value数组中每个fieldvalues属性作为一行

<think> 我们使用Apache POI库来操作Word文档生成表格。 步骤: 1. 创建文档对象,并创建一个表格。 2. 首先,我们创建表头行(第一行),遍历keyAry数组,取出每个元素的name属性作为表头单元格的内容。 3. 然后,遍历value数组,每个元素代表一行数据。每个元素有一个fieldvalues数组,这个数组中的每个元素对应一个单元格。 4. 注意:keyAry数组的长度应该与fieldvalues数组的长度一致,因为它们分别代表列名和每列的值。 假设数据结构如下: keyAry: 数组,每个元素是一个对象,对象有name属性(表头名称) v
recommend-type

2000年代初的粉丝创神奇宝贝网站回顾

标题和描述中提到的“jps1:杰西(Jesse)基于粉丝的终极口袋妖怪网站(2000-2001)”反映了以下几个重要知识点: 1. 网站建设与维护的早期阶段:从2000到2001年的时间段中,互联网技术正处于快速发展时期,而杰西(Jesse)创建的这个口袋妖怪主题网站,可以被视作个人站长时代的早期代表作。这代表了早期网络用户利用有限资源进行个人兴趣爱好的分享和推广。 2. 基于粉丝的互动平台:这个网站明确指出是基于粉丝而创建的,这表明了网络社区中粉丝文化的存在和影响力。在那个时期,围绕特定兴趣(如口袋妖怪)形成的粉丝群体,通过这些网站交流信息、分享资源,这种基于共同兴趣建立的社区模式对后来的社交媒体和粉丝经济有着深远影响。 3. 个人网站的存档意义:杰西(Jesse)在描述中提到了出于存档目的而发布,这说明了这个网站对于网络历史保存的重要性。随着互联网内容的快速更迭,个人网站往往由于服务器迁移、技术更新等原因而丢失,因此存档个人网站是对互联网文化遗产的一种保护。 关于标签“JavaScript”,它指向了一个重要的知识点: 4. JavaScript在网络技术中的作用:标签“JavaScript”点出了该网站使用了JavaScript技术。作为早期的动态网页脚本语言,JavaScript在提高用户交互体验、网页特效实现等方面发挥了关键作用。尽管该网站发布的年份较早,但极有可能包含了一些基础的JavaScript代码,用于实现动态效果和基本的客户端交互。 至于“压缩包子文件的文件名称列表”中的“jps1-gh-pages”,它暗示了以下知识点: 5. GitHub Pages的使用:GitHub Pages是GitHub提供的一项服务,允许用户将网站内容部署到一个独立的域名下,通过“jps1-gh-pages”文件名我们可以推测,这个口袋妖怪网站可能是被部署在GitHub Pages上的。这表明了即使在早期,个人站长已经开始利用现代网络服务来托管和分享他们的项目。 6. 压缩文件的作用:文件名称中的“压缩”二字意味着该网站的文件内容可能是经过压缩处理的,这可能是为了便于存储和传输。在互联网早期,由于带宽和存储空间的限制,压缩文件是一种常见的数据管理手段。 总结以上知识点,可以归纳为: - 网站建设与维护的早期案例,以及个人站长时代的特点。 - 基于粉丝文化的网络社区,及其对后来社交媒体的影响。 - 个人网站的存档价值和对互联网文化遗产的贡献。 - JavaScript的早期应用以及它在改善用户交互体验方面的重要性。 - GitHub Pages的使用案例,以及压缩技术在网络数据管理中的应用。 从这些知识点可以看出,即便是早期的个人网站项目,也蕴含了丰富的技术和文化内涵,为理解互联网的发展和应用提供了重要的视角。
recommend-type

Linux终端实用工具与技巧

# Linux 终端实用工具与技巧 ## 1. gnuplot 绘图与导出 ### 1.1 绘制方程图形 任何方程都可以用特定方式绘制图形。例如,一个斜率为 5、y 轴截距为 3 的直线方程,可使用以下命令生成图形: ```bash plot 5*x + 3 ``` ### 1.2 导出图形为图像文件 虽然能在终端显示图表,但多数情况下,我们希望将图表导出为图像,用于报告或演示。可按以下步骤将 gnuplot 设置为导出图像文件: 1. 切换到 png 模式: ```bash set terminal png ``` 2. 指定图像文件的输出位置,否则屏幕将显示未处理的原始 png 数据: