把这一个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 <liuyan11@tp-link.com.hk>
*\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 <linux/if_packet.h>
#include <time.h>
#include <pthread.h>
#include <libubox/blobmsg_json.h>
#include <libubus.h>
#include <libubox/blobmsg.h>
/**************************************************************************************************/
/* 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阶段对数据模型的参数进行初始化 */