基于以下我提供的几段代码,结合起来写一个技术文档,我接下来一段一段的提供,先提供arp.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 21Aug25
*
* history \arg version, date, author, modification
*/
/**************************************************************************************************/
/* INCLUDE */
/**************************************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "arp.h"
#include "nsd_common.h"
#include "nvmp_common.h"
/**************************************************************************************************/
/* DEFINES */
/**************************************************************************************************/
/**************************************************************************************************/
/* TYPES */
/**************************************************************************************************/
/**************************************************************************************************/
/* VARIABLES */
/**************************************************************************************************/
/* 全局扫描器初始化 */
arp_scanner_t scanner =
{
.entries = NULL ,
.scanning = SCANNING_OFF,
.sockfd = -1,
};
/* 基于DMS的ubus方法注册 */
LOCAL DMS_CMD_METHOD arp_method[] =
{
DMS_CMD_METHOD_DESC("set_arp_config", set_arp_config),
DMS_CMD_METHOD_DESC("get_arp_config", get_arp_config),
DMS_CMD_METHOD_DESC("start_scan", start_scan),
DMS_CMD_METHOD_DESC("stop_scan", stop_scan),
DMS_CMD_METHOD_DESC("get_scan_status", get_scan_status),
DMS_CMD_METHOD_DESC("get_scan_result", get_scan_result),
DMS_CMD_METHOD_DESC("clear_result", clear_result),
};
LOCAL DMS_CMD_OBJ_CMD arp_call_cmd[] =
{
DMS_CMD_OBJ_CMD_DESC("arp", arp_method),
};
LOCAL DMS_CMD_OBJ arp_call_obj = DMS_CMD_OBJ_DESC("arp", arp_call_cmd);
/**************************************************************************************************/
/* FUNCTIONS */
/**************************************************************************************************/
LOCAL S32 arp_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, &arp_call_obj);
}
S32 set_arp_config(JSON_OBJPTR obj, JSON_OBJPTR* resp_obj)
{
NOT_USE(resp_obj);
/* 通过解析obj设置 */
arp_config_t *cfg;
memset(cfg, 0, sizeof(*cfg));
if (0 != jso_obj_get_int(obj, "enable", &cfg->enable)) // 无设置或没获取到
{
cfg->enable = scanner.config.enable; // 保持原配置值不变
}
if (0 != jso_obj_get_int(obj, "scan_interval", &cfg->scan_interval)) // 无设置或没获取到
{
cfg->scan_interval = scanner.config.scan_interval; // 保持原配置值不变
}
if (0 != jso_obj_get_int(obj, "send_interval", &cfg->send_interval)) // 无设置或没获取到
{
cfg->send_interval = scanner.config.send_interval; // 保持原配置值不变
}
if (0 != jso_obj_get_int(obj, "valid_time", &cfg->valid_time)) // 无设置或没获取到
{
cfg->valid_time = scanner.config.valid_time; // 保持原配置值不变
}
char *start_ip;
char *end_ip;
if (NULL == (start_ip = jso_obj_get_string_origin(obj, "start_ip")))
{
strncpy(&cfg->start_ip, &scanner.config.start_ip, sizeof(scanner.config.start_ip));
}
else
{
strncpy(&cfg->start_ip, &start_ip, sizeof(start_ip));
}
if (NULL == (end_ip = jso_obj_get_string_origin(obj, "end_ip")))
{
strncpy(&cfg->end_ip, &scanner.config.end_ip, sizeof(scanner.config.end_ip));
}
else
{
strncpy(&cfg->end_ip, &end_ip, sizeof(end_ip));
}
/* 更新scanner配置,并写入配置到flash*/
scanner.config = *cfg;
save_config(cfg);
return OK;
}
S32 get_arp_config(JSON_OBJPTR obj, JSON_OBJPTR* resp_obj)
{
NOT_USE(obj);
/* 将config转义输出到resp_obj */
jso_add_int(*resp_obj, "enable", scanner.config.enable);
jso_add_int(*resp_obj, "scan_interval", scanner.config.scan_interval);
jso_add_int(*resp_obj, "send_interval", scanner.config.send_interval);
jso_add_int(*resp_obj, "valid_time", scanner.config.valid_time);
jso_add_string(*resp_obj, "start_ip", (scanner.config.start_ip));
jso_add_string(*resp_obj, "end_ip", (scanner.config.end_ip));
return OK;
}
S32 start_scan(JSON_OBJPTR obj, JSON_OBJPTR* resp_obj)
{
NOT_USE(obj);
NOT_USE(resp_obj);
/* 启动arp扫描线程 */
if (pthread_create(&scanner.scan_thread, NULL, arp_scan_thread, &scanner) != 0)
{
perror("❌ 创建扫描线程失败");
close(scanner.sockfd);
return -1;
}
printf("扫描线程已启动\n");
pthread_detach(&scanner.scan_thread); // 线程分离,自动释放
return OK;
}
S32 stop_scan(JSON_OBJPTR obj, JSON_OBJPTR* resp_obj)
{
NOT_USE(obj);
NOT_USE(resp_obj);
scanner.scanning = SCANNING_OFF;
printf("stopped scanning.\n");
return OK;
}
S32 get_scan_status(JSON_OBJPTR obj, JSON_OBJPTR* resp_obj)
{
NOT_USE(obj);
jso_add_int(*resp_obj, "scanning", scanner.scanning);
return OK;
}
S32 get_scan_result(JSON_OBJPTR obj, JSON_OBJPTR* resp_obj)
{
NOT_USE(obj);
pthread_mutex_lock(&scanner.lock);
char res_buff[MAX_RES_BUFF][MAX_RES_LEN];
char key[KEY_LEN];
int count = 0;
arp_entry_t *entry = scanner.entries;
while (entry)
{
snprintf(res_buff[count], sizeof(res_buff[count]),
"[New Host] IP: %s, MAC: %02X:%02X:%02X:%02X:%02X:%02X \n",
entry->ip, entry->mac[0], entry->mac[1], entry->mac[2],
entry->mac[3], entry->mac[4], entry->mac[5]);
snprintf(key, sizeof(key), "scan_res%2d", count);
/* 通过resp_obj输出结果json */
jso_add_string(*resp_obj, key, res_buff[count]);
/* 取链表下一个节点 */
entry = entry->next;
}
pthread_mutex_unlock(&scanner.lock);
return OK;
}
S32 clear_result(JSON_OBJPTR obj, JSON_OBJPTR* resp_obj)
{
NOT_USE(obj);
NOT_USE(obj);
pthread_mutex_lock(&scanner.lock);
arp_entry_t *curr = scanner.entries;
while (curr)
{
arp_entry_t *next = curr->next;
free(curr); // 移除当前节点
curr = next; // 释放节点内存
}
scanner.entries = NULL; // 清空头指针
pthread_mutex_unlock(&scanner.lock);
return OK;
}
/*
* 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_config_t *cfg)
{
cfg->enable = DEFAULT_ENABLE;
cfg->scan_interval = DEFAULT_SCAN_INTERVAL;
cfg->send_interval = DEFAULT_SEND_INTERVAL;
strncpy(cfg->start_ip, DEFAULT_START_IP, sizeof(DEFAULT_START_IP));
strncpy(cfg->end_ip, DEFAULT_END_IP, sizeof(DEFAULT_END_IP));
return 0;
}
/* 将config通过DS写入flash */
int save_config(arp_config_t *cfg)
{
ds_advanced_write(ARP_CONFIG_PATH,
(arp_config_t *)cfg,
sizeof(cfg),
DS_FLAG_SAVE_FLASH);
return OK;
}
/* 打印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()
{
arp_config_t cfg;
memset(&cfg, 0, sizeof(cfg));
/* 从Flash加载配置 */
U32 ret_size = ds_read(ARP_CONFIG_PATH, &cfg, sizeof(cfg));
if ( 0 == ret_size)
{
printf("无配置信息");
/* 写入默认配置 */
load_default_config(&cfg);
save_config(&cfg); /* 写入到flash */
/* 若仍读取不到,报错处理*/
if ( 0 == ds_read(ARP_CONFIG_PATH, &cfg, sizeof(cfg)) )
{
return ERROR;
}
}
/* 打印配置信息 */
print_config(&cfg);
/* 配置赋值到扫描器 */
scanner.config = cfg;
/* 线程锁初始化 */
pthread_mutex_init(&scanner.lock, NULL);
/* 创建arp socket */
scanner.sockfd = create_arp_socket();
if (scanner.sockfd < 0)
{
fprintf(stderr, "创建arp socket失败\n");
return ERROR;
}
printf("ARP socket已创建\n");
/* 基于DMS的ubus服务注册 */
msg_attach_handler(MSGID_DMS_CMD, arp_call_handle);
return OK;
}
static int arp_reload(DS_MSG *msg)
{
/* 获取配置更新消息 */
if (ds_path_id_exist(msg->id, msg->num, ARP_CONFIG_PATH))
{
arp_start();
}
}
static int arp_start(void)
{
/* 启动arp扫描线程 */
if (pthread_create(&scanner.scan_thread, NULL, arp_scan_thread, &scanner) != 0)
{
perror("❌ 创建扫描线程失败");
close(scanner.sockfd);
return -1;
}
printf("扫描线程已启动\n");
pthread_detach(&scanner.scan_thread); // 线程分离,自动释放
return 0;
}
void arp_main()
{
/****************************************************************/
/***************** Desc of /arp/main ***************************/
/****************************************************************/
DS_OPT_DESC main_options[] =
{
DS_SWITCH_OPT(ARP_MAIN, enabled, OPT_FLAG_NORM),
};
DS_SEG_DESC main_segments[] =
{
DS_STRUCT_SEG("main", SEG_LIM_RW, SEG_GROUP_ROOT, ARP_MAIN, main_options),
};
DS_SECT_DESC arp_sections[] =
{
DS_STRUCT_SECT("main", main_segments),
};
DS_TBL_DESC arp_tables[] =
{
DS_STRUCT_TBL("arp", TBL_ATTR_STC, arp_sections),
};
DS_DAT_MON_DESC arp_data_monitor[] =
{
DS_DAT_MON(ARP_CONFIG_PATH, DATA_ATTRI_NOTIFY),
};
DS_MOD_DESC arp_module =
DS_STRUCT_MOD("arp", arp_init, NULL, arp_reload, arp_start,
NULL, arp_tables, arp_data_monitor);
MODULE *module_node = ds_register_module("arp", &arp_module);
SDM_ASSERT(NULL != module_node);
}
NSD_INIT(arp_main);
最新发布