ntohs, ntohl, htons,htonl inet_aton等详解

本文详细介绍了网络编程中常见的字节序转换函数,包括ntohs、htonl、inet_addr等,以及它们在网络地址处理中的应用。

ntohs =net to host short int 16位
htons=host to net short int 16位
ntohs =net to host long int 32位
htonl=host to net 

  long int   32位
简述:
     将一个无符号短整形数从网络字节顺序转换为主机字节顺序。
     #include
     u_short PASCAL FAR ntohs( u_short netshort);
     netshort:一个以网络字节顺序表达的16位数。
注释:
     本函数将一个16位数由网络字节顺序转换为主机字节顺序。
返回值:
     ntohs()返回一个以主机字节顺序表达的数。

将主机的无符号短整形数转换成网络字节顺序。
#include
u_short PASCAL FAR htons( u_short hostshort);
hostshort:主机字节顺序表达的16位数。
注释:
本函数将一个16位数从主机字节顺序转换成网络字节顺序。
返回值:
htons()返回一个网络字节顺序的值。

这2个函数提供了主机字节顺序与网络字节顺序的转换

比如网络字节 为 00 01
u_short     a;如何直接对应的话     a=0100; 为什么呢?因为主机是从高字节到低字节的,所以应该转化后
a=ntohs(0001); 这样 a=0001;

首先,假设你已经有了一个sockaddr_in结构体ina,你有一个IP地址"132.241.5.10" 要储存在其中,你就要用到函数inet_addr(),将IP地址从 点数格式转换成无符号长整型。使用方法如下:
ina.sin_addr.s_addr = inet_addr("132.241.5.10");
; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; line-height: 160%; ">注意,inet_addr()返回的地址已经是网络字节格式,所以你无需再调用函数htonl()。
我们现在发现上面的代码片断不是十分完整的,因为它没有错误检查。显而易见,当inet_addr()发生错误时返回-1。记住这些二进制数字?(无符号数)-1仅仅和IP地址255.255.255.255相符合!这可是广播地址!大错特 错!记住要先进行错误检查。
好了,现在你可以将IP地址转换成长整型了。有没有其相反的方法呢?它可以将一个in_addr结构体输出成点数格式?这样的话,你就要用到函数 inet_ntoa()("ntoa"的含义是"network to ascii"),就像这样:
printf("%s",inet_ntoa(ina.sin_addr));
它将输出IP地址。需要注意的是inet_ntoa()将结构体in-addr作为一个参数,不是长整形。同样需要注意的是它返回的是一个指向一个字符的指针。它是一个由inet_ntoa()控制的静态的固定的指针,所以每次调用 inet_ntoa(),它就将覆盖上次调用时所得的IP地址。例如:
char *a1, *a2;
.
.
a1 = inet_ntoa(ina1.sin_addr);
a2 = inet_ntoa(ina2.sin_addr);
printf("address 1: %s ",a1);
printf("address 2: %s ",a2);
输出如下:
address 1: 132.241.5.10
address 2: 132.241.5.10
假如你需要保存这个IP地址,使用strcopy()函数来指向你自己的字符指针。
***********************************************************************************************************************************
htonl()表示将32位的主机字节顺序转化为32位的网络字节顺序 htons()表示将16位的主机字节顺序转化为16位的网络字节顺序(ip地址是32位的端口号是16位的 )
inet_ntoa()
简述:
     将网络地址转换成“.”点隔的字符串格式。
     #include
     char FAR* PASCAL FAR inet_ntoa( struct in_addr in);
     in:一个表示Internet主机地址的结构。
注释:
     本函数将一个用in参数所表示的Internet地址结构转换成以“.” 间隔的诸如“a.b.c.d”的字符串形式。请注意inet_ntoa()返回的字符串存放在WINDOWS套接口实现所分配的内存中。应用程序不应假设该内存是如何分配的。在同一个线程的下一个WINDOWS套接口调用前,数据将保证是有效。
返回值:
     若无错误发生,inet_ntoa()返回一个字符指针。否则的话,返回NVLL。其中的数据应在下一个WINDOWS套接口调用前复制出来。
参见:
     inet_addr().

测试代码如下
include
#include
#include
#include
p: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; line-height: 160%; ">int main(int aargc, char* argv[])
{
         struct in_addr addr1,addr2;
         ulong   l1,l2;
         l1= inet_addr("192.168.0.74");
         l2 = inet_addr("211.100.21.179");
         memcpy(&addr1, &l1, 4);
         memcpy(&addr2, &l2, 4);
         printf("%s : %s ", inet_ntoa(addr1), inet_ntoa(addr2));     //注意这一句的运行结果
         printf("%s ", inet_ntoa(addr1));
         printf("%s ", inet_ntoa(addr2));
         return 0;
}
实际运行结果如下:
192.168.0.74 : 192.168.0.74       //从这里可以看出,printf里的inet_ntoa只运行了一次。
192.168.0.74
211.100.21.179
inet_ntoa返回一个char *,而这个char *的空间是在inet_ntoa里面静态分配的,所以inet_ntoa后面的调用会覆盖上一次的调用。第一句printf的结果只能说明在printf里面的可变参数的求值是从右到左的,仅此而已。

inet_aton,inet_addr和inet_ntoa在点分十进制数串(如,“192.168.1.10")与他的32位网络字节二进制值之前转换IPV4地址,有2个比较新的函数inet_pton和inet_ntop,这2个对IPV4和IPV6地址都能处理
       #include <sys/socket.h>
       #include <netinet/in.h>
       #include <arpa/inet.h>

       int inet_aton(const char *cp, struct in_addr *inp);

       in_addr_t inet_addr(const char *cp);

       char *inet_ntoa(struct in_addr in);

inet_aton() converts the Internet host address cp from the standard
       numbers-and-dots notation into binary data and stores it in the struc‐
       ture that inp points to. inet_aton() returns non-zero if the address is
       valid, zero if not.

inet_aton() 转换网络主机地址cp为二进制数值,并存储在struct in_addr结构中,即第二个参数*inp,函数返回非0表示cp主机有地有效,返回0表示主机地址无效。

The inet_addr() function converts the Internet host address cp from
       numbers-and-dots notation into binary data in network byte order.   If
       the input is invalid, INADDR_NONE (usually -1) is returned. This is an
       obsolete interface to inet_aton(), described immediately above; it is
       obsolete   because   -1 is a valid address (255.255.255.255), and
       inet_aton() provides a cleaner way to indicate error return.
inet_addr函数转换网络主机地址(如192.168.1.10)为网络字节序二进制值,如果参数char *cp无效,函数返回-1(INADDR_NONE),这个函数在处理地址为255.255.255.255时也返回- 1,255.255.255.255是一个有效的地址,不过inet_addr无法处理;

The inet_ntoa() function converts the Internet host address in given in
       network byte order to a string in standard numbers-and-dots notation.
       The string is returned in a statically allocated buffer, which subse‐
       quent calls will overwrite.
inet_ntoa 函数转换网络字节排序的地址为标准的ASCII以点分开的地址,,该函数返回指向点分开的字符串地址的指针,该字符串的空间为静态分配的,这意味着在第二次调用该函数时,上一次调用将会被重写(复盖),所以如果需要保存该串最后复制出来自己管理!


现在一般使用inet_aton和inet_ntoa来处理网络字节和主机字节之间的转换;

有两个更新的函数inet_pton和inet_ntop这2个函数能够处理ipv4和ipv6,原型如下
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int inet_pton(int af, const char *src, void *dst);

这个函数转换字符串到网络地址,第一个参数af是地址族,转换后存在dst中
inet_pton 是inet_addr的扩展,支持的多地址族有下列:

AF_INET
       src为指向字符型的地址,即ASCII的地址的首地址(ddd.ddd.ddd.ddd格式的),函数将该地址
       转换为in_addr的结构体,并复制在*dst中

AF_INET6
      
src为指向IPV6的地址,,函数将该地址
       转换为in6_addr的结构体,并复制在*dst中

如果函数出错将返回一个负值,并将errno设置为EAFNOSUPPORT,如果参数af指定的地址族和src格式不对,函数将返回0。

函数inet_ntop进行相反的转换原型如下
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt);
这个函数转换网络二进制结构到ASCII类型的地址,参数的作用和上面相同,只是多了一个参数socklen_t cnt,他是所指向缓存区dst的大小,避免溢出,如果缓存区太小无法存储地址的值,则返回一个空指针,并将errno置为ENOSPC
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <pthread.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <netinet/in.h> #include <net/if.h> #include <arpa/inet.h> #include <linux/if_packet.h> #include <linux/if_ether.h> #include <linux/if_arp.h> #include <sys/time.h> #include <errno.h> #define PROTO_ARP (0x0806) #define ETH2_HEADER_LEN (14) #define HW_TYPE (1) #define MAC_LENGTH (6) #define IPV4_LENGTH (4) #define ARP_REQUEST (0x01) #define ARP_REPLY (0x02) #define BUF_SIZE (60) #define MAX_IFNAME_LEN (16) #define MAX_IP_RANGE (256) #define ARP_PACKET_SIZE (1024) #define ARP_PATH (“arpsd/arp_config”) /* ARP头部结构 */ struct arp_header { unsigned short hardware_type; unsigned short protocol_type; unsigned char hardware_len; unsigned char protocol_len; unsigned short opcode; unsigned char sender_mac[MAC_LENGTH]; unsigned char sender_ip[IPV4_LENGTH]; unsigned char target_mac[MAC_LENGTH]; unsigned char target_ip[IPV4_LENGTH]; }; /* 扫描结果结构 / typedef struct arp_entry { char ip[16]; / IP地址 / char mac[18]; / MAC地址 / time_t timestamp; / 发现时间 */ } arp_result_t; /* 扫描配置参数 / typedef struct { U32 enable; / 功能开关 / U32 scan_cycle; / 扫描周期(秒) / U32 valid_time; / 有效期(秒) / U32 packet_interval; / 发包间隔(毫秒) / char start_ip[12]; / 起始IP / char end_ip[12]; / 结束IP / char ifname[MAX_IFNAME_LEN]; / 网络接口名 */ } arp_config_t; /* 扫描状态 / typedef enum { SCAN_IDLE, / 未运行 / SCAN_RUNNING, / 运行中 / SCAN_STOPPING / 停止中 */ } scan_status_t; LOCAL arp_config_t g_config = {0}; static scan_status_t g_scan_status = SCAN_IDLE; static pthread_t g_scan_thread; static arp_result_t g_results[MAX_IP_RANGE]; static int g_result_count = 0; static int g_scan_fd = -1; static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; /* 设置配置参数 */ LOCAL S32 set_arp_config_ubus(JSON_OBJPTR req_obj, JSON_OBJPTR *rply_obj) { jso_obj_get_int(req_obj,“enable”,&g_config.enable); jso_obj_get_int(req_obj,“scan_cycle”,&g_config.scan_cycle); jso_obj_get_int(req_obj,“valid_time”,&g_config.valid_time); jso_obj_get_int(req_obj,“packet_interval”,&g_config.packet_interval); memcpy(g_config.start_ip, jso_obj_get_string_origin(req_obj, “start_ip”), INET_ADDRSTRLEN); memcpy(g_config.end_ip, jso_obj_get_string_origin(req_obj, “end_ip”), INET_ADDRSTRLEN); memcpy(g_config.ifname, jso_obj_get_string_origin(req_obj, “ifname”), INET_ADDRSTRLEN); ds_advanced_write(ARP_PATH, &g_config, sizeof(arp_config_t), DS_FLAG_NOTIFY); return OK; } /* 获取配置参数 */ LOCAL S32 get_arp_config_ubus(JSON_OBJPTR req_obj, JSON_OBJPTR *rply_obj) { JSON_OBJPTR rsp_obj = NULL; if (NULL == (rsp_obj = jso_new_obj())) { return -1; } jso_add_int(rsp_obj, “enable”, g_config.enable); jso_add_int(rsp_obj, “scan_cycle”, g_config.scan_cycle); jso_add_int(rsp_obj, “valid_time”, g_config.valid_time); jso_add_int(rsp_obj, “packet_interval”, g_config.packet_interval); jso_add_string(rsp_obj, “start_ip”, g_config.start_ip); jso_add_string(rsp_obj, “end_ip”, g_config.end_ip); jso_add_string(rsp_obj, “start_ip”, g_config.start_ip); jso_add_string(rsp_obj, “ifname”, g_config.ifname); *rply_obj = rsp_obj; return OK; } LOCAL S32 start_scan_ubus(JSON_OBJPTR req_obj, JSON_OBJPTR rply_obj) { / 检查是否已在扫描 */ if (g_scan_status != SCAN_IDLE) { return -1; } /* 检查功能是否启用 */ if (!g_config.enable) { return -1; } /* 创建扫描线程 */ g_scan_status = SCAN_RUNNING; if (pthread_create(&g_scan_thread, NULL, scan_thread, NULL) != 0) { g_scan_status = SCAN_IDLE; pthread_mutex_unlock(&g_mutex); return -1; } return OK; } LOCAL S32 stop_scan_ubus(JSON_OBJPTR req_obj, JSON_OBJPTR rply_obj) { / 检查是否有扫描在运行 */ if (g_scan_status != SCAN_RUNNING) { return -1; } /* 设置停止标志 */ g_scan_status = SCAN_STOPPING; g_config.enable = 0; /* 等待线程结束 */ pthread_join(g_scan_thread, NULL); return OK; } LOCAL S32 get_scan_status_ubus(JSON_OBJPTR req_obj, JSON_OBJPTR *rply_obj) { JSON_OBJPTR rsp_obj = NULL; if (NULL == (rsp_obj = jso_new_obj())) { return -1; } jso_add_int(rsp_obj, “scan_status”, g_scan_status); *rply_obj = rsp_obj; return OK; } LOCAL S32 get_scan_result_ubus(JSON_OBJPTR req_obj, JSON_OBJPTR *rply_obj) { arp_result_t arp_result[MAX_IP_RANGE]; S32 index = 0; if (0 != g_result_count) { for (index = 0; index < g_result_count; index++) { JSON_OBJPTR rsp_obj = NULL; if (NULL == (rsp_obj = jso_new_obj())) { return -1; } inet_ntop(AF_INET, g_results[index].ip, arp_result[index].ip, sizeof(arp_result[index].ip)); sprintf(arp_result[index].mac, 18, “%02X:%02X:%02X:%02X:%02X:%02X”, g_results[index].mac[0], g_results[index].mac[1], g_results[index].mac[2], g_results[index].mac[3], g_results[index].mac[4], g_results[index].mac[5]); jso_add_string(rsp_obj, “IP”, arp_result[index].ip); jso_add_string(rsp_obj, “MAC”, arp_result[index].mac); *rply_obj = rsp_obj; } } else { return -1; } return OK; } int clear_result_ubus(JSON_OBJPTR req_obj, JSON_OBJPTR *rply_obj) { g_result_count = 0; return OK; } LOCAL DMS_CMD_METHOD arpsd_method[] = { DMS_CMD_METHOD_DESC(“set_arp_config”, set_arp_config_ubus), DMS_CMD_METHOD_DESC(“get_arp_config”, get_arp_config_ubus), DMS_CMD_METHOD_DESC(“start_scan”, start_scan_ubus), DMS_CMD_METHOD_DESC(“stop_scan”, stop_scan_ubus), DMS_CMD_METHOD_DESC(“get_scan_status”, get_scan_status_ubus), DMS_CMD_METHOD_DESC(“get_scan_result”, get_scan_result_ubus), DMS_CMD_METHOD_DESC(“clear_result”, clear_result_ubus), }; LOCAL DMS_CMD_OBJ_CMD arpsd_cmd[] = { DMS_CMD_OBJ_CMD_DESC(“arpsd”, arpsd_method), }; /* 注册ubus模块 */ LOCAL DMS_CMD_OBJ arpsd_call_obj = DMS_CMD_OBJ_DESC(“arpsd”, arpsd_cmd); LOCAL int arpsd_cmd_call_handle(dms_handler_t *handler, U8 *mbuf, U32 mlen, U32 sender_dms_id) { return dms_cmd_msg_parse(handler, mbuf, mlen, sender_dms_id, &arpsd_call_obj); } LOCAL int get_if_info(const char *ifname, uint32_t *ip, unsigned char *mac, int *ifindex) { struct ifreq ifr; int sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) { return -1; } /* 获取接口索引 */ strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1); if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0) { close(sock); return -1; } *ifindex = ifr.ifr_ifindex; /* 获取MAC地址 */ if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) { close(sock); return -1; } memcpy(mac, ifr.ifr_hwaddr.sa_data, 6); /* 获取IP地址 */ if (ioctl(sock, SIOCGIFADDR, &ifr) < 0) { close(sock); return -1; } struct sockaddr_in *ipaddr = (struct sockaddr_in *)&ifr.ifr_addr; *ip = ipaddr->sin_addr.s_addr; close(sock); return 0; } LOCAL int send_arp_request(int fd, int ifindex, const unsigned char *src_mac, uint32_t src_ip, uint32_t dst_ip) { int err = -1; unsigned char buffer[BUF_SIZE]; memset(buffer, 0, sizeof(buffer)); struct sockaddr_ll socket_address; socket_address.sll_family = AF_PACKET; socket_address.sll_protocol = htons(ETH_P_ARP); socket_address.sll_ifindex = ifindex; socket_address.sll_hatype = htons(ARPHRD_ETHER); socket_address.sll_pkttype = (PACKET_BROADCAST); socket_address.sll_halen = MAC_LENGTH; socket_address.sll_addr[6] = 0x00; socket_address.sll_addr[7] = 0x00; struct ethhdr *send_req = (struct ethhdr *) buffer; struct arp_header *arp_req = (struct arp_header *) (buffer + ETH2_HEADER_LEN); int index; ssize_t ret, length = 0; /* 广播 */ memset(send_req->h_dest, 0xff, MAC_LENGTH); memset(arp_req->target_mac, 0x00, MAC_LENGTH); /* 设置源地址 */ memcpy(send_req->h_source, src_mac, MAC_LENGTH); memcpy(arp_req->sender_mac, src_mac, MAC_LENGTH); memcpy(socket_address.sll_addr, src_mac, MAC_LENGTH); send_req->h_proto = htons(ETH_P_ARP); /* 建立ARP请求 */ arp_req->hardware_type = htons(HW_TYPE); arp_req->protocol_type = htons(ETH_P_IP); arp_req->hardware_len = MAC_LENGTH; arp_req->protocol_len = IPV4_LENGTH; arp_req->opcode = htons(ARP_REQUEST); memcpy(arp_req->sender_ip, &src_ip, sizeof(uint32_t)); memcpy(arp_req->target_ip, &dst_ip, sizeof(uint32_t)); ret = sendto(fd, buffer, 42, 0, (struct sockaddr *) &socket_address, sizeof(socket_address)); if (ret == -1) { perror("sendto():"); goto out; } err = 0; out: return err; } /* 接收ARP响应 */ LOCAL int recv_arp_response(int fd, const char *expected_ip, char *mac_buf, int timeout_s) { unsigned char buffer[ARP_PACKET_SIZE]; struct timeval tv = { .tv_sec = timeout_s, .tv_usec = (timeout_s - 1) * 1000 }; setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); ssize_t len = recv(fd, buffer, sizeof(buffer), 0); if (len < (ssize_t)(ETH2_HEADER_LEN + sizeof(struct arp_header))) { return -1; /* 超时或错误 */ } /* 解析ARP响应 */ struct arp_header *arp = (struct arp_header *)(buffer + ETH2_HEADER_LEN); if (ntohs(arp->opcode) != ARPOP_REPLY) { return -1; /* 不是ARP响应 */ } /* 检查IP是否匹配 */ struct in_addr expected_addr, sender_addr; inet_aton(expected_ip, &expected_addr); memcpy(&sender_addr, arp->sender_ip, 4); if (sender_addr.s_addr != expected_addr.s_addr) { return -1; /* IP不匹配 */ } /* 格式化MAC地址 */ snprintf(mac_buf, 18, "%02x:%02x:%02x:%02x:%02x:%02x", arp->sender_mac[0], arp->sender_mac[1], arp->sender_mac[2], arp->sender_mac[3], arp->sender_mac[4], arp->sender_mac[5]); return 0; } LOCAL void *scan_thread(void *arg) { unsigned char local_mac[6]; uint32_t local_ip; int ifindex; /* 获取接口信息 */ if (get_if_info(g_config.ifname, &local_ip, local_mac, &ifindex) != 0) { pthread_mutex_lock(&g_mutex); g_scan_status = SCAN_IDLE; pthread_mutex_unlock(&g_mutex); return NULL; } /* 创建原始套接字 */ g_scan_fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP)); if (g_scan_fd < 0) { pthread_mutex_lock(&g_mutex); g_scan_status = SCAN_IDLE; pthread_mutex_unlock(&g_mutex); return NULL; } /* 绑定到接口 */ struct sockaddr_ll sll = { .sll_family = AF_PACKET, .sll_protocol = htons(ETH_P_ARP), .sll_ifindex = ifindex }; if (bind(g_scan_fd, (struct sockaddr *)&sll, sizeof(sll)) < 0) { close(g_scan_fd); pthread_mutex_lock(&g_mutex); g_scan_status = SCAN_IDLE; pthread_mutex_unlock(&g_mutex); return NULL; } /* 解析IP范围 */ struct in_addr start_addr, end_addr; inet_aton(g_config.start_ip, &start_addr); inet_aton(g_config.end_ip, &end_addr); uint32_t start_ip = ntohl(start_addr.s_addr); uint32_t end_ip = ntohl(end_addr.s_addr); /* 主扫描循环 */ while (1) { pthread_mutex_lock(&g_mutex); if (g_scan_status == SCAN_STOPPING) { g_scan_status = SCAN_IDLE; pthread_mutex_unlock(&g_mutex); break; } g_result_count = 0; /* 重置结果计数 */ pthread_mutex_unlock(&g_mutex); time_t scan_start = time(NULL); /* 遍历IP范围 */ for (uint32_t ip = start_ip; ip <= end_ip; ip++) { pthread_mutex_lock(&g_mutex); if (g_scan_status == SCAN_STOPPING) { g_scan_status = SCAN_IDLE; pthread_mutex_unlock(&g_mutex); goto cleanup; } pthread_mutex_unlock(&g_mutex); /* 转换IP为字符串 */ struct in_addr target_addr = {.s_addr = htonl(ip)}; char ip_str[16]; strcpy(ip_str, inet_ntoa(target_addr)); /* 发送ARP请求 */ if (send_arp_request(g_scan_fd, ifindex, local_mac, local_ip, target_addr.s_addr) != 0) { continue; } /* 接收响应 */ char mac[18]; if (recv_arp_response(g_scan_fd, ip_str, mac, g_config.valid_time) == 0) { pthread_mutex_lock(&g_mutex); if (g_result_count < MAX_IP_RANGE) { strncpy(g_results[g_result_count].ip, ip_str, 16); strncpy(g_results[g_result_count].mac, mac, 18); g_results[g_result_count].timestamp = time(NULL); g_result_count++; } pthread_mutex_unlock(&g_mutex); } /* 等待发包间隔 */ usleep(g_config.packet_interval * 1000); } /* 计算并等待扫描周期 */ time_t elapsed = time(NULL) - scan_start; int sleep_time = g_config.scan_cycle - elapsed; if (sleep_time > 0) { while (sleep_time > 0) { pthread_mutex_lock(&g_mutex); if (g_scan_status == SCAN_STOPPING) { g_scan_status = SCAN_IDLE; pthread_mutex_unlock(&g_mutex); goto cleanup; } pthread_mutex_unlock(&g_mutex); sleep(1); sleep_time--; } } } cleanup: close(g_scan_fd); g_scan_fd = -1; return NULL; } LOCAL S32 arp_start_callback(DS_HANDLE_CONTEXT context, JSON_OBJPTR param) { / 检查是否已在扫描 */ if (g_scan_status != SCAN_IDLE) { return -1; } /* 检查功能是否启用 */ if (!g_config.enable) { return -1; } /* 创建扫描线程 */ g_scan_status = SCAN_RUNNING; if (pthread_create(&g_scan_thread, NULL, scan_thread, NULL) != 0) { g_scan_status = SCAN_IDLE; return -1; } return OK; } LOCAL S32 arp_stop_callback(DS_HANDLE_CONTEXT context, JSON_OBJPTR param) { / 检查是否有扫描在运行 */ if (g_scan_status != SCAN_RUNNING) { return -1; } /* 设置停止标志 */ g_scan_status = SCAN_STOPPING; g_config.enable = 0; /* 等待线程结束 */ pthread_join(g_scan_thread, NULL); return OK; } LOCAL S32 arp_clear_callback(DS_HANDLE_CONTEXT *context, JSON_OBJPTR param) { g_result_count = 0; return OK; } LOCAL S32 arpsd_unregister(void) { ds_unregister_action(“arpsd”, “start”, arp_start_callback); ds_unregister_action(“arpsd”, “stop”, arp_stop_callback); ds_unregister_action(“arpsd”, “clear”, arp_clear_callback); return OK; } LOCAL S32 arpsd_stop() { arpsd_unregister(); /* 取消注册的dms ubus调试方法 */ msg_detach_handler(MSGID_DMS_CMD, arpsd_cmd_call_handle); return OK; } LOCAL S32 arpsd_start() { /* 把配置文件读到本地 / if (0 == ds_read(ARP_PATH, (void)(&g_config), sizeof(arp_config_t))) { return -1; } return 0; } LOCAL S32 arpsd_register(void) { ds_register_action(“arpsd”, “start”, arp_start_callback); ds_register_action(“arpsd”, “stop”, arp_stop_callback); ds_register_action(“arpsd”, “clear”, arp_clear_callback); return OK; } LOCAL S32 arpsd_init() { arpsd_register(); /* 注册ubus call调试方法 */ msg_attach_handler(MSGID_DMS_CMD, arpsd_cmd_call_handle); return OK; } LOCAL void arpsd_main() { DS_MOD_DESC arpsd_module = DS_STRUCT_MOD(“arpsd”, arpsd_init, NULL, NULL, arpsd_start, arpsd_stop, NULL, NULL); /* 向ds注册模块 */ MODULE *module_node = ds_register_module("arpsd", &arpsd_module); NSD_ASSERT(NULL != module_node); } NSD_INIT(arpsd_main); LOCAL void arpsd_data_model() { /* 按层级声明模块配置参数 */ DS_ARR_DESC(start_ip_array, OPT_TYPE_STRING, arp_config_t, start_ip); DS_ARR_DESC(end_ip_array, OPT_TYPE_STRING, arp_config_t, end_ip); DS_ARR_DESC(ifname_array, OPT_TYPE_STRING, arp_config_t, start_ip); DS_OPT_DESC arpsd_options[] = { DS_U32_OPT(arp_config_t, enable, OPT_FLAG_NORM), DS_U32_OPT(arp_config_t, scan_cycle, OPT_FLAG_NORM), DS_U32_OPT(arp_config_t, valid_time, OPT_FLAG_NORM), DS_U32_OPT(arp_config_t, packet_interval, OPT_FLAG_NORM), DS_ARR_OPT(arp_config_t, start_ip, OPT_FLAG_NORM, &start_ip_array), DS_ARR_OPT(arp_config_t, end_ip, OPT_FLAG_NORM, &end_ip_array), DS_ARR_OPT(arp_config_t, ifname, OPT_FLAG_NORM, &ifname_array), }; DS_SEG_DESC arpsd_segments[] = { DS_STRUCT_SEG("arp_config", SEG_LIM_RW, SEG_GROUP_GUEST, scan_status_t, arpsd_options), }; DS_SECT_DESC arpsd_sections[] = { DS_STRUCT_SECT("arp_config", arpsd_segments), }; DS_TBL_DESC arpsd_tables[] = { DS_STRUCT_TBL("arp_config", TBL_ATTR_CFG, arpsd_sections), }; /* 向ds注册模块配置信息 */ DS_MOD_DESC arpsd_module = DS_STRUCT_MOD("arpsd", NULL, NULL, NULL, NULL, NULL, arpsd_tables, NULL); MODULE *module_node = ds_register_module("arpsd", &arpsd_module); NSD_ASSERT(NULL != module_node); } NSD_INIT(arpsd_data_model); 给出这个项目的完整设计文档,要详细具体完整
最新发布
08-29
#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 <pthread.h> #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); // 以太网类型(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, 0xFF, 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); // 遍历IP范围 for (uint32_t ip = cfg.start_ip; ip <= cfg.end_ip; ip++) { struct _ARP_HDR_new arp_req; build_arp_packet(&arp_req, 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只会询问一个ip地址,而且定时好像也没有效果,这是什么问题
08-27
这样可以满足基础需求了吗:/* * ARP 扫描子模块 - NVMP/NSD 框架版本 * * 功能: * 1. 通过 socket 发送和接收 ARP 报文,扫描指定 IP 范围内的主机 * 2. 支持配置开关、扫描周期、有效期、发包间隔、起始IP、结束IP、接口名 * 3. 扫描结果存储在内存,有效期过期删除 * 4. 新发现主机通过 ubus 调用 dmsd 的 set_arpd 上报 * 5. 通过 DS 框架注册为 NSD 子模块,支持配置管理和数据监控 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #include <sys/time.h> #include <net/if.h> #include <linux/if_arp.h> #include <linux/if_packet.h> #include <net/ethernet.h> #include <netinet/if_ether.h> #include <errno.h> #include <sys/ioctl.h> #include "nvmp_utils.h" #include "nsd_common.h" #include "dms_tool.h" /* ============================== * 一、数据模型定义 * ============================== */ /* 配置结构体(对应 DS 的 options) */ typedef struct { int enable; // 是否启用扫描 int scan_interval; // 扫描周期(秒) int valid_time; // 有效期(秒) int send_interval; // 发包间隔(毫秒) char start_ip[16]; // 起始 IP char end_ip[16]; // 结束 IP char ifname[16]; // 接口名 } arp_config_t; /* 扫描结果结构体 */ typedef struct { char ip[16]; char mac[18]; time_t last_seen; } arp_result_t; /* 全局变量 */ static arp_config_t g_config; static arp_result_t g_results[256]; static int g_result_count = 0; static int g_scanning = 0; static int g_periodic_scan = 0; static pthread_t g_scan_thread; static struct uloop_timeout scan_timer; static struct ubus_context *ctx; /* ============================== * 三、ARP 扫描逻辑 * ============================== */ /* 工具函数:MAC 转字符串 */ static void mac_to_str(const unsigned char *mac, char *str) { sprintf(str, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); } static void handle_new_host(const char *ip, const char *mac) { printf("[ARP] New host found: IP=%s, MAC=%s\n", ip, mac); // TODO: 后续替换为 ubus 上报 } /* 添加扫描结果 */ static void add_result(const char *ip, const char *mac) { for (int i = 0; i < g_result_count; i++) { if (strcmp(g_results[i].ip, ip) == 0) { g_results[i].last_seen = time(NULL); return; } } if (g_result_count < 256) { strncpy(g_results[g_result_count].ip, ip, sizeof(g_results[g_result_count].ip)); strncpy(g_results[g_result_count].mac, mac, sizeof(g_results[g_result_count].mac)); g_results[g_result_count].last_seen = time(NULL); g_result_count++; handle_new_host(ip, mac); } } /* 清理过期结果 */ static void clear_expired_results() { time_t now = time(NULL); for (int i = 0; i < g_result_count; i++) { if (difftime(now, g_results[i].last_seen) > g_config.valid_time) { memmove(&g_results[i], &g_results[i+1], (g_result_count - i - 1) * sizeof(arp_result_t)); g_result_count--; i--; } } } /* ARP 报文结构 */ struct arp_header { uint16_t htype; uint16_t ptype; uint8_t hlen; uint8_t plen; uint16_t oper; uint8_t sha[6]; uint8_t spa[4]; uint8_t tha[6]; uint8_t tpa[4]; } __attribute__((packed)); /* 发送 ARP 请求 */ static void send_arp_request(const char *target_ip) { int sockfd; struct ifreq ifr; unsigned char src_mac[6]; struct sockaddr_ll socket_address; char buffer[42]; struct arp_header *arp = (struct arp_header *)(buffer + 14); sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP)); if (sockfd < 0) return; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, g_config.ifname, IFNAMSIZ-1); ioctl(sockfd, SIOCGIFHWADDR, &ifr); memcpy(src_mac, ifr.ifr_hwaddr.sa_data, 6); ioctl(sockfd, SIOCGIFINDEX, &ifr); int ifindex = ifr.ifr_ifindex; struct ether_header *eth = (struct ether_header *)buffer; memset(eth->ether_dhost, 0xff, 6); memcpy(eth->ether_shost, src_mac, 6); eth->ether_type = htons(ETH_P_ARP); arp->htype = htons(ARPHRD_ETHER); arp->ptype = htons(ETH_P_IP); arp->hlen = 6; arp->plen = 4; arp->oper = htons(ARPOP_REQUEST); memcpy(arp->sha, src_mac, 6); ioctl(sockfd, SIOCGIFADDR, &ifr); memcpy(arp->spa, &((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr, 4); memset(arp->tha, 0x00, 6); inet_pton(AF_INET, target_ip, arp->tpa); socket_address.sll_ifindex = ifindex; socket_address.sll_halen = ETH_ALEN; memset(socket_address.sll_addr, 0xff, 6); sendto(sockfd, buffer, 42, 0, (struct sockaddr*)&socket_address, sizeof(socket_address)); close(sockfd); } /* 接收 ARP 响应 */ static void recv_arp_replies() { int sockfd; char buffer[65536]; sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP)); if (sockfd < 0) return; struct timeval tv = { .tv_sec = 1, .tv_usec = 0 }; setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); while (1) { ssize_t len = recv(sockfd, buffer, sizeof(buffer), 0); if (len <= 0) break; struct ether_header *eth = (struct ether_header *)buffer; if (ntohs(eth->ether_type) != ETH_P_ARP) continue; struct arp_header *arp = (struct arp_header *)(buffer + 14); if (ntohs(arp->oper) != ARPOP_REPLY) continue; char ip[16], mac[18]; inet_ntop(AF_INET, arp->spa, ip, sizeof(ip)); mac_to_str(arp->sha, mac); add_result(ip, mac); } close(sockfd); } /* 扫描一次 */ static void arp_scan() { struct in_addr start, end; inet_aton(g_config.start_ip, &start); inet_aton(g_config.end_ip, &end); for (uint32_t ip = ntohl(start.s_addr); ip <= ntohl(end.s_addr); ip++) { struct in_addr addr; addr.s_addr = htonl(ip); send_arp_request(inet_ntoa(addr)); usleep(g_config.send_interval * 1000); } recv_arp_replies(); clear_expired_results(); } /*启动周期扫描函数*/ static void *periodic_scan_thread(void *arg) { while (g_periodic_scan) { if (g_config.enable) { g_scanning = 1; printf("[ARP] Periodic scan started...\n"); arp_scan(); g_scanning = 0; printf("[ARP] Periodic scan complete.\n"); } sleep(g_config.scan_interval); // 用配置的周期 } return NULL; } /*启用周期扫描*/ void start_periodic_scan() { if (g_periodic_scan) { printf("[ARP] Periodic scan already running.\n"); return; } g_periodic_scan = 1; pthread_create(&g_scan_thread, NULL, periodic_scan_thread, NULL); printf("[ARP] Periodic scan enabled.\n"); } /* 停止周期扫描 */ void stop_periodic_scan() { if (!g_periodic_scan) { printf("[ARP] Periodic scan not running.\n"); return; } g_periodic_scan = 0;//设置停止标志 //强行终止扫描线程 pthread_cancel(g_scan_thread); pthread_join(g_scan_thread, NULL); g_scanning = 0; // 更新扫描状态 printf("[ARP] Periodic scan stopped.\n"); } LOCAL S32 arpdetect_set_arp_config(JSON_OBJPTR req_obj, JSON_OBJPTR *rply_obj) { json_get_int(req_obj, "enable", &g_config.enable); json_get_int(req_obj, "scan_interval", &g_config.scan_interval); json_get_int(req_obj, "valid_time", &g_config.valid_time); json_get_int(req_obj, "send_interval", &g_config.send_interval); json_get_string(req_obj, "start_ip", g_config.start_ip, sizeof(g_config.start_ip)); json_get_string(req_obj, "end_ip", g_config.end_ip, sizeof(g_config.end_ip)); json_get_string(req_obj, "ifname", g_config.ifname, sizeof(g_config.ifname)); printf("[ARP] Config updated from ubus.\n"); return 0; } LOCAL S32 arpdetect_get_arp_config(JSON_OBJPTR req_obj, JSON_OBJPTR *rply_obj) { *rply_obj = json_create_object(); json_add_int(*rply_obj, "enable", g_config.enable); json_add_int(*rply_obj, "scan_interval", g_config.scan_interval); json_add_int(*rply_obj, "valid_time", g_config.valid_time); json_add_int(*rply_obj, "send_interval", g_config.send_interval); json_add_string(*rply_obj, "start_ip", g_config.start_ip); json_add_string(*rply_obj, "end_ip", g_config.end_ip); json_add_string(*rply_obj, "ifname", g_config.ifname); return 0; } LOCAL S32 arpdetect_start_scan(JSON_OBJPTR req_obj, JSON_OBJPTR *rply_obj) { if (!g_config.enable) { printf("[ARP] Scan disabled.\n"); return -1; } if (g_scanning) { printf("[ARP] Scan already running.\n"); return -1; } g_scanning = 1; arp_scan(); g_scanning = 0; return 0; } LOCAL S32 arpdetect_stop_scan(JSON_OBJPTR req_obj, JSON_OBJPTR *rply_obj) { printf("[ARP] Stop scan requested.\n"); stop_periodic_scan(); return 0; } LOCAL S32 arpdetect_get_scan_status(JSON_OBJPTR req_obj, JSON_OBJPTR *rply_obj) { *rply_obj = json_create_object(); json_add_int(*rply_obj, "scanning", g_scanning); return 0; } LOCAL S32 arpdetect_get_scan_result(JSON_OBJPTR req_obj, JSON_OBJPTR *rply_obj) { *rply_obj = json_create_array(); for (int i = 0; i < g_result_count; i++) { JSON_OBJPTR item = json_create_object(); json_add_string(item, "ip", g_results[i].ip); json_add_string(item, "mac", g_results[i].mac); json_add_int(item, "last_seen", (int)g_results[i].last_seen); json_array_add(*rply_obj, item); } return 0; } LOCAL S32 arpdetect_clear_result(JSON_OBJPTR req_obj, JSON_OBJPTR *rply_obj) { g_result_count = 0; printf("[ARP] Results cleared.\n"); return 0; } /* ============================== * 四、生命周期函数 * ============================== */ LOCAL DMS_CMD_METHOD arpdetect_method[] = { DMS_CMD_METHOD_DESC("set_arp_config", arpdetect_set_arp_config), DMS_CMD_METHOD_DESC("get_arp_config", arpdetect_get_arp_config), DMS_CMD_METHOD_DESC("start_scan", arpdetect_start_scan), DMS_CMD_METHOD_DESC("stop_scan", arpdetect_stop_scan), DMS_CMD_METHOD_DESC("get_scan_status",arpdetect_get_scan_status), DMS_CMD_METHOD_DESC("get_scan_result",arpdetect_get_scan_result), DMS_CMD_METHOD_DESC("clear_result", arpdetect_clear_result), }; LOCAL DMS_CMD_OBJ_CMD arpdetect_call_cmd[] = { DMS_CMD_OBJ_CMD_DESC("arpdetect", arpdetect_method), }; LOCAL DMS_CMD_OBJ arpdetect_call_obj =DMS_CMD_OBJ_DESC("arpdetect", arpdetect_call_cmd); LOCAL S32 arpdetect_call_handle(dms_handler_t *handler, U8 *mbuf, U32 mlen, U32 sender_dms_id) { return dms_cmd_msg_parse(handler, mbuf, mlen, sender_dms_id, &arpdetect_call_obj); } static int load_arp_config(arp_config_t *cfg) { U32 ret = ds_read("arp.arp_config", cfg, sizeof(arp_config_t)); if (ret != sizeof(arp_config_t)) { printf("[ARP] Failed to read config from DS, ret=%u\n", ret); return -1; } printf("[ARP] Config loaded: enable=%d, scan_interval=%d, valid_time=%d, send_interval=%d, start_ip=%s, end_ip=%s, ifname=%s\n", cfg->enable, cfg->scan_interval, cfg->valid_time, cfg->send_interval, cfg->start_ip, cfg->end_ip, cfg->ifname); return 0; } LOCAL S32 arp_init(void) { msg_attach_handler(MSGID_DMS_CMD, arpdetect_call_handle); memset(&g_config, 0, sizeof(g_config)); g_result_count = 0; g_scanning = 0; g_periodic_scan=0; if (load_arp_config(&g_config) != 0) { // 读取失败时设置默认值 g_config.enable = 1; g_config.scan_interval = 60; g_config.valid_time = 300; g_config.send_interval = 10; strcpy(g_config.start_ip, "192.168.1.1"); strcpy(g_config.end_ip, "192.168.1.254"); strcpy(g_config.ifname, "br-lan"); printf("[ARP] Using default config.\n"); } if (g_config.enable) { start_periodic_scan(); } printf("[ARP] Module initialized.\n"); return OK; } LOCAL S32 arp_reload(void) { stop_periodic_scan(); printf("[ARP] Reloading config...\n"); if (load_arp_config(&g_config) != 0) { printf("[ARP] Reload failed, keeping old config.\n"); } clear_expired_results(); if (g_config.enable) { start_periodic_scan(); } printf("[ARP] Config reloaded.\n"); return OK; } /* ============================== * 五、模块描述与注册 * ============================== */ static void arp_main(void) { /* DS options 定义(配置项) */ DS_OPT_DESC arp_options[] = { DS_S32_OPT(arp_config_t, enable, OPT_FLAG_NORM), DS_S32_OPT(arp_config_t, scan_interval, OPT_FLAG_NORM), DS_S32_OPT(arp_config_t, valid_time, OPT_FLAG_NORM), DS_S32_OPT(arp_config_t, send_interval, OPT_FLAG_NORM), DS_STR_OPT(arp_config_t, start_ip, OPT_FLAG_NORM), DS_STR_OPT(arp_config_t, end_ip, OPT_FLAG_NORM), DS_STR_OPT(arp_config_t, ifname, OPT_FLAG_NORM), }; /* DS segments 定义(段) */ DS_SEG_DESC arp_segments[] = { DS_STRUCT_SEG("arp_config", SEG_LIM_RO, SEG_GROUP_ROOT, arp_config_t, arp_options), }; /* DS sections 定义(节) */ DS_SECT_DESC arp_sections[] = { DS_STRUCT_SECT("arp_config", arp_segments), }; /* DS tables 定义(表) */ DS_TBL_DESC arp_tables[] = { DS_STRUCT_TBL("arp", TBL_ATTR_STC, arp_sections), }; /* 当 arp_config 配置变化时通知模块 */ DS_DAT_MON_DESC arp_data_monitor[] = { DS_DAT_MON("arp.arp_config", DATA_ATTRI_NOTIFY), }; DS_MOD_DESC arp_module = DS_STRUCT_MOD("arp", arp_init, NULL, arp_reload, arpdetect_start_scan, arpdetect_stop_scan, arp_tables, arp_data_monitor); MODULE *module_node = ds_register_module("arp", &arp_module); SDM_ASSERT(NULL != module_node); } NSD_INIT(arp_main);
08-28
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值