03dlist-kernel_list

本文详细介绍了链表数据结构的基础知识,包括链表节点定义、初始化、添加、删除节点等基本操作,以及如何实现链表的遍历,通过实例展示了链表在不同场景的应用。

list.h

 

struct list_head {
    struct list_head *prev;
    struct list_head *next;
};

#define LIST_HEAD(head) struct list_head head = {&head, &head}

static inline void INIT_LIST_HEAD(struct list_head *node)
{
    node->prev = node;
    node->next = node;
}

static inline void __list_add(struct list_head *node,
        struct list_head *prev,
        struct list_head *next)
{
    node->prev = prev;
    node->next = next;
    prev->next = node;
    next->prev = node;
}

static inline void list_add(struct list_head *node,
        struct list_head *head)
{
    __list_add(node, head, head->next);
}

static inline void list_add_tail(struct list_head *node,
        struct list_head *head)
{
    __list_add(node, head->prev, head);
}

static inline int list_emtpy(struct list_head *head)
{
    return head->next == head;
}

static inline void list_del(struct list_head *node)
{
    node->prev->next = node->next;
    node->next->prev = node->prev;
}

static inline void list_del_init(struct list_head *node)
{
    list_del(node);
    INIT_LIST_HEAD(node);
}

#define offsetof(type, member) \
    ((size_t)(&((type*)0)->member))

#define container_of(ptr, type, member) \
    ((type*)((char*)ptr - offsetof(type, member)))

/* @cur: ?..list_head?..?.复?舵.?
 * @head: 澶磋.?圭.?板.
 */
#define list_for_each(cur, head) \
    for (cur = (head)->next; \
        (cur) != (head); \
        cur = (cur)->next)
#define list_for_each_safe(cur, tmp, head) \
    for (cur = (head)->next, tmp = (cur)->next; \
        (cur) != (head); \
        cur = tmp, tmp = (tmp)->next)

#define list_for_each_entry(ptr, head, member) \
    for ( ptr = container_of((head)->next, typeof(*(ptr)), member); \
        &(ptr)->member != (head); \
        ptr = container_of((ptr)->member.next, typeof(*(ptr)), member) )

#define list_for_each_entry_safe(ptr, tmp, head, member) \
    for ( ptr = container_of((head)->next, typeof(*(ptr)), member); \
        (&(ptr)->member != (head)) && (tmp = container_of((ptr)->member.next, typeof(*(ptr)), member)); \
        ptr = tmp )

#define list_for_each_continue(cur, head) \
    for (cur = (cur)->next; \
        (cur) != (head); \
        cur = (cur)->next)

#define list_for_each_reverse(cur, head) \
    for (cur = (head)->prev; \
        (cur) != (head); \
        cur = (cur)->prev)


test.c

 

#include <stdio.h>
#include <string.h>
#include "list.h"

struct node {
    const char *name;
    size_t data;
    struct list_head list;
};

int main()
{
    LIST_HEAD(list);

    size_t i = 0;
    struct node s[] = { 
        {"jack", 10},
        {"mike", 20},
        {"mary", 12},
        {"tom", 15},
        {"peter", 17},
        {"kate", 18},
    };  

    for (i = 0; i < sizeof(s) / sizeof(struct node); i++) {
        list_add_tail(&s[i].list, &list);
    }   


 

    struct list_head *cur = NULL;
    struct list_head *tmp = NULL;
    struct node *pnode = NULL;
    struct node *ptmp = NULL;

    list_for_each_entry(pnode, &list, list) {
        printf("%s: %ld\n", pnode->name, pnode->data);
    }   
    printf("\n");

/*        list_for_each_safe(cur, tmp, &list) {
 *                pnode = container_of(cur, struct node, list);
 *                if (!strcmp(pnode->name, "tom")) {
 *                        list_del_init(cur);
 *                }
 *        }*/
    list_for_each_entry_safe(pnode, ptmp, &list, list) {
        if (!strcmp(pnode->name, "mary")) {
            list_del_init(&pnode->list);
        }
    }

    list_for_each(cur, &list) {
        pnode = container_of(cur, struct node, list);
        printf("%s: %ld\n", pnode->name, pnode->data);
    }

       return 0;

}

【2025年10月最新优化算法】混沌增强领导者黏菌算法(Matlab代码实现)内容概要:本文档介绍了2025年10月最新提出的混沌增强领导者黏菌算法(Matlab代码实现),属于智能优化算法领域的一项前沿研究。该算法结合混沌机制与黏菌优化算法,通过引入领导者策略提升搜索效率和全局寻优能力,适用于复杂工程优化问题的求解。文档不仅提供完整的Matlab实现代码,还涵盖了算法原理、性能验证及与其他优化算法的对比分析,体现了较强的科研复现性和应用拓展性。此外,文中列举了大量相关科研方向和技术应用场景,展示其在微电网调度、路径规划、图像处理、信号分析、电力系统优化等多个领域的广泛应用潜力。; 适合人群:具备一定编程基础和优化理论知识,从事科研工作的研究生、博士生及高校教师,尤其是关注智能优化算法及其在工程领域应用的研发人员;熟悉Matlab编程环境者更佳。; 使用场景及目标:①用于解决复杂的连续空间优化问题,如函数优化、参数辨识、工程设计等;②作为新型元启发式算法的学习与教学案例;③支持高水平论文复现与算法改进创新,推动在微电网、无人机路径规划、电力系统等实际系统中的集成应用; 其他说明:资源包含完整Matlab代码和复现指导,建议结合具体应用场景进行调试与拓展,鼓励在此基础上开展算法融合与性能优化研究。
编译错误 src/cliLanDnsHandlers.c:67:5: error: unknown type name ‘dlist_t’ dlist_t list; // 链表节点 ^~~~~~~ src/cliLanDnsHandlers.c:76:8: error: unknown type name ‘dlist_t’ static dlist_t g_landns_list = DLIST_HEAD_INIT(g_landns_list); // 全局链表头 ^~~~~~~ src/cliLanDnsHandlers.c:76:32: error: implicit declaration of function ‘DLIST_HEAD_INIT’ [-Werror=implicit-function-declaration] static dlist_t g_landns_list = DLIST_HEAD_INIT(g_landns_list); // 全局链表头 ^~~~~~~~~~~~~~~ src/cliLanDnsHandlers.c:76:32: error: initializer element is not constant src/cliLanDnsHandlers.c: In function ‘find_landns_node’: src/cliLanDnsHandlers.c:101:5: error: implicit declaration of function ‘dlist_for_each_entry’; did you mean ‘dlist_foreach_safe’? [-Werror=implicit-function-declaration] dlist_for_each_entry(node, &g_landns_list, list) { ^~~~~~~~~~~~~~~~~~~~ dlist_foreach_safe src/cliLanDnsHandlers.c:101:48: error: ‘list’ undeclared (first use in this function); did you mean ‘DList’? dlist_for_each_entry(node, &g_landns_list, list) { ^~~~ DList src/cliLanDnsHandlers.c:101:48: note: each undeclared identifier is reported only once for each function it appears in src/cliLanDnsHandlers.c:101:54: error: expected ‘;’ before ‘{’ token dlist_for_each_entry(node, &g_landns_list, list) { ^ src/cliLanDnsHandlers.c:107:1: error: no return statement in function returning non-void [-Werror=return-type] } ^ src/cliLanDnsHandlers.c: In function ‘create_new_node’: src/cliLanDnsHandlers.c:123:5: error: implicit declaration of function ‘dlist_add_tail’; did you mean ‘dlistTail’? [-Werror=implicit-function-declaration] dlist_add_tail(&new_node->list, &g_landns_list); ^~~~~~~~~~~~~~ dlistTail src/cliLanDnsHandlers.c: In function ‘cli_lanDnsAddProfile’: src/cliLanDnsHandlers.c:133:10: error: ‘g_in_landns_mode’ undeclared (first use in this function); did you mean ‘find_landns_node’? if (!g_in_landns_mode) { ^~~~~~~~~~~~~~~~ find_landns_node src/cliLanDnsHandlers.c:155:18: error: implicit declaration of function ‘dmDnsServerRuleGetByName’; did you mean ‘dmDnsServerRuleDelById’? [-Werror=implicit-function-declaration] int db_ret = dmDnsServerRuleGetByName(profileName, &db_rule); ^~~~~~~~~~~~~~~~~~~~~~~~ dmDnsServerRuleDelById src/cliLanDnsHandlers.c:168:9: error: implicit declaration of function ‘INIT_DLIST_HEAD’; did you mean ‘UNIT_LIST_HAS’? [-Werror=implicit-function-declaration] INIT_DLIST_HEAD(&node->list); ^~~~~~~~~~~~~~~ UNIT_LIST_HAS src/cliLanDnsHandlers.c: In function ‘cli_lanDnsDeleteAttribute’: src/cliLanDnsHandlers.c:353:36: error: ‘CFG_DNSSERVER_RULE_T {aka struct <anonymous>}’ has no member named ‘alias_domains’ memset(g_current_edit->rule.alias_domains, 0, sizeof(g_current_edit->rule.alias_domains)); ^ src/cliLanDnsHandlers.c:353:82: error: ‘CFG_DNSSERVER_RULE_T {aka struct <anonymous>}’ has no member named ‘alias_domains’ memset(g_current_edit->rule.alias_domains, 0, sizeof(g_current_edit->rule.alias_domains)); ^ src/cliLanDnsHandlers.c: In function ‘cli_lanDnsShow’: src/cliLanDnsHandlers.c:531:20: error: ‘CFG_DNSSERVER_RULE_T {aka struct <anonymous>}’ has no member named ‘alias_domains’ if (strlen(rule->alias_domains) > 0) { ^~ src/cliLanDnsHandlers.c:532:49: error: ‘CFG_DNSSERVER_RULE_T {aka struct <anonymous>}’ has no member named ‘alias_domains’ cliPrintf(pCliEnv, "Aliases: %s\n", rule->alias_domains); ^~ src/cliLanDnsHandlers.c: In function ‘is_valid_network_list’: src/cliLanDnsHandlers.c:589:43: error: implicit declaration of function ‘is_cidr_format’ [-Werror=implicit-function-declaration] if (strcmp(token, "all") != 0 && !is_cidr_format(token)) { ^~~~~~~~~~~~~~ src/cliLanDnsHandlers.c: At top level: src/cliLanDnsHandlers.c:601:6: error: conflicting types for ‘is_cidr_format’ bool is_cidr_format(const char *cidr) { ^~~~~~~~~~~~~~ src/cliLanDnsHandlers.c:589:43: note: previous implicit declaration of ‘is_cidr_format’ was here if (strcmp(token, "all") != 0 && !is_cidr_format(token)) { ^~~~~~~~~~~~~~ src/cliLanDnsHandlers.c: In function ‘cli_lanDns_init’: src/cliLanDnsHandlers.c:619:5: error: implicit declaration of function ‘cli_register_command_set’; did you mean ‘cli_enter_lanDns’? [-Werror=implicit-function-declaration] cli_register_command_set("landns", lanDnsCmdTree, "LAN DNS Configuration"); ^~~~~~~~~~~~~~~~~~~~~~~~ cli_enter_lanDns src/cliLanDnsHandlers.c:619:40: error: ‘lanDnsCmdTree’ undeclared (first use in this function); did you mean ‘lanDns_node’? cli_register_command_set("landns", lanDnsCmdTree, "LAN DNS Configuration"); ^~~~~~~~~~~~~ lanDns_node src/cliLanDnsHandlers.c:620:5: error: ‘g_in_landns_mode’ undeclared (first use in this function); did you mean ‘find_landns_node’? g_in_landns_mode = false; ^~~~~~~~~~~~~~~~ find_landns_node src/cliLanDnsHandlers.c:622:5: error: implicit declaration of function ‘DLIST_INIT’; did you mean ‘DLIST_ITER’? [-Werror=implicit-function-declaration] DLIST_INIT(&g_landns_list); // 确保链表头正确初始化 ^~~~~~~~~~ DLIST_ITER src/cliLanDnsHandlers.c: In function ‘cli_enter_lanDns’: src/cliLanDnsHandlers.c:643:56: error: implicit declaration of function ‘dlist_count’; did you mean ‘dlistSort’? [-Werror=implicit-function-declaration] cliPrintf(pCliEnv, "%% Loaded %d DNS rules\n", dlist_count(&g_landns_list)); ^~~~~~~~~~~ dlistSort src/cliLanDnsHandlers.c:649:5: error: ‘g_in_landns_mode’ undeclared (first use in this function); did you mean ‘find_landns_node’? g_in_landns_mode = true; ^~~~~~~~~~~~~~~~ find_landns_node src/cliLanDnsHandlers.c: In function ‘cli_exit_lanDns’: src/cliLanDnsHandlers.c:657:5: error: implicit declaration of function ‘dlist_for_each_entry_safe’; did you mean ‘dlist_foreach_safe’? [-Werror=implicit-function-declaration] dlist_for_each_entry_safe(node, tmp, &g_landns_list, list) { ^~~~~~~~~~~~~~~~~~~~~~~~~ dlist_foreach_safe src/cliLanDnsHandlers.c:657:58: error: ‘list’ undeclared (first use in this function); did you mean ‘DList’? dlist_for_each_entry_safe(node, tmp, &g_landns_list, list) { ^~~~ DList src/cliLanDnsHandlers.c:657:64: error: expected ‘;’ before ‘{’ token dlist_for_each_entry_safe(node, tmp, &g_landns_list, list) { ^
10-20
<think>我们遇到了多个编译错误,主要涉及以下几个方面: 1. 未定义的链表类型和函数(dlist_t, DLIST_HEAD_INIT, dlist_for_each_entry等) 2. 未声明的变量(g_in_landns_mode) 3. 未声明的函数(dmDnsServerRuleGetByName, INIT_DLIST_HEAD) 4. 结构体成员不存在(alias_domains) 5. 函数隐式声明冲突(is_cidr_format) 6. 命令树未声明(lanDnsCmdTree) 为了解决这些问题,我们需要: 1. 确保链表相关类型和函数已定义。根据错误信息,我们可能使用了不存在的链表实现。我们需要使用项目中已有的链表实现(可能是自定义的或来自某个库)。假设项目中有一个双链表实现,我们可能要用到类似`struct list_head`的结构(参考Linux内核链表风格)。 2. 调整链表操作代码以匹配实际可用的链表函数。 3. 声明缺失的全局变量。 4. 确保函数`dmDnsServerRuleGetByName`在头文件中声明,并且该函数已经在其他地方实现(如果没有,我们需要实现它,但根据之前的讨论,我们假设它已经存在)。 5. 修正结构体成员名,例如将`alias_domains`改为正确的成员名(根据之前的代码,应该是`aliases`)。 6. 修正`is_cidr_format`函数的声明和定义顺序。 7. 声明命令树`lanDnsCmdTree`。 8. 包含必要的头文件。 下面是修正后的代码: ### 头文件包含和类型定义 假设我们使用类似于Linux内核的双链表实现,定义在`list.h`中。 ```c // 在cliLanDnsHandlers.c开头包含必要的头文件 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> #include "json.h" // JSON处理 #include "dmlib.h" // dmDnsServerRuleGetAll等函数 #include "list.h" // 链表实现 #include "cli.h" // CLI相关函数 #include "pal.h" // pal_getSystemTime // 定义链表节点类型(假设使用list_head) struct list_head { struct list_head *next, *prev; }; // 链表初始化宏 #define DLIST_HEAD_INIT(name) { &(name), &(name) } #define DLIST_HEAD(name) struct list_head name = DLIST_HEAD_INIT(name) #define INIT_LIST_HEAD(ptr) do { (ptr)->next = (ptr); (ptr)->prev = (ptr); } while (0) // 遍历链表 #define dlist_for_each_entry(pos, head, member) \ for (pos = list_entry((head)->next, typeof(*pos), member); \ &pos->member != (head); \ pos = list_entry(pos->member.next, typeof(*pos), member)) #define dlist_for_each_entry_safe(pos, n, head, member) \ for (pos = list_entry((head)->next, typeof(*pos), member), \ n = list_entry(pos->member.next, typeof(*pos), member); \ &pos->member != (head); \ pos = n, n = list_entry(n->member.next, typeof(*n), member)) // 链表操作函数 static inline void list_add_tail(struct list_head *new, struct list_head *head) { struct list_head *prev = head->prev; new->next = head; new->prev = prev; prev->next = new; head->prev = new; } static inline void list_del(struct list_head *entry) { entry->prev->next = entry->next; entry->next->prev = entry->prev; entry->next = (void*)0xDEADBEEF; entry->prev = (void*)0xDEADBEEF; } // 链表节点结构 typedef struct lanDns_node { CFG_DNSSERVER_RULE_T rule; bool is_new; bool modified; struct list_head list; // 链表节点(使用struct list_head) } lanDns_node_t; // 全局变量定义 static bool g_in_landns_mode = false; static lanDns_node_t *g_current_edit = NULL; static DLIST_HEAD(g_landns_list); // 全局链表头(使用宏定义) // 函数声明 static lanDns_node_t* find_landns_node(const char *name); static lanDns_node_t* create_new_node(const char *name); ``` ### 修正链表操作 使用`struct list_head`代替`dlist_t`,并调整链表操作函数。 ### 修正结构体成员名 将`alias_domains`改为`aliases`。 ### 实现`is_cidr_format`函数 确保该函数在使用前声明。 ### 定义命令树数组 确保命令树数组在使用前定义。 ### 修正后的代码示例 ```c // ... (头文件包含和类型定义如上) // 命令树数组(必须在函数使用前定义) CLI_COMMAND_T lanDnsCmdTree[] = { CMD("enter", cli_enter_lanDns, "Enter LAN DNS configuration mode"), CMD("exit", cli_exit_lanDns, "Exit LAN DNS configuration mode"), // ... 其他命令 CMD_END() }; // 查找节点函数 static lanDns_node_t* find_landns_node(const char *name) { lanDns_node_t *node; dlist_for_each_entry(node, &g_landns_list, list) { if (strcmp(node->rule.name, name) == 0) { return node; } } return NULL; } // 创建新节点函数 static lanDns_node_t* create_new_node(const char *name) { lanDns_node_t *new_node = malloc(sizeof(lanDns_node_t)); if (!new_node) { return NULL; } memset(new_node, 0, sizeof(lanDns_node_t)); INIT_LIST_HEAD(&new_node->list); safe_strncpy(new_node->rule.name, name, sizeof(new_node->rule.name)); safe_strncpy(new_node->rule.status, "on", sizeof(new_node->rule.status)); new_node->rule.ttl = 3600; safe_strncpy(new_node->rule.lan_networks, "all", sizeof(new_node->rule.lan_networks)); new_node->is_new = true; new_node->modified = true; list_add_tail(&new_node->list, &g_landns_list); return new_node; } // 属性删除函数(修正成员名) STATUS cli_lanDnsDeleteAttribute(cli_env *pCliEnv, char *attr) { // ... 其他代码 if (strcmp(attr, "alias") == 0) { memset(g_current_edit->rule.aliases, 0, sizeof(g_current_edit->rule.aliases)); g_current_edit->modified = true; cliPrintf(pCliEnv, "%% Aliases cleared\n"); } // ... 其他属性 } // 显示函数(修正成员名) STATUS cli_lanDnsShow(cli_env *pCliEnv) { // ... 其他代码 if (strlen(rule->aliases) > 0) { cliPrintf(pCliEnv, "Aliases: %s\n", rule->aliases); } // ... 其他代码 } // CIDR格式检查函数(在使用前声明) bool is_cidr_format(const char *cidr); // 初始化函数 void cli_lanDns_init(void) { cli_register_command_set("landns", lanDnsCmdTree, "LAN DNS Configuration"); g_in_landns_mode = false; g_current_edit = NULL; INIT_LIST_HEAD(&g_landns_list); } // 进入配置模式函数 STATUS cli_enter_lanDns(cli_env *pCliEnv) { // ... 其他代码 CFG_DNSSERVER_RULE_T **lst = NULL; if (dmDnsServerRuleGetAll(&lst) == ERR_NO_ERROR) { int count = 0; for (CFG_DNSSERVER_RULE_T **pp = lst; *pp; pp++) { lanDns_node_t *node = malloc(sizeof(lanDns_node_t)); if (node) { memset(node, 0, sizeof(lanDns_node_t)); memcpy(&node->rule, *pp, sizeof(CFG_DNSSERVER_RULE_T)); node->is_new = false; node->modified = false; INIT_LIST_HEAD(&node->list); list_add_tail(&node->list, &g_landns_list); count++; } } dmDnsServerRuleListFree(lst); cliPrintf(pCliEnv, "%% Loaded %d DNS rules\n", count); } else { cliPrintf(pCliEnv, "%% Warning: Failed to load DNS rules\n"); } g_in_landns_mode = true; return OK; } // 退出配置模式函数 STATUS cli_exit_lanDns(cli_env *pCliEnv) { lanDns_node_t *node, *tmp; dlist_for_each_entry_safe(node, tmp, &g_landns_list, list) { if (node->modified) { cliPrintf(pCliEnv, "%% Discarding uncommitted changes for profile '%s'\n", node->rule.name); list_del(&node->list); free(node); } } g_in_landns_mode = false; g_current_edit = NULL; return OK; } // CIDR格式检查函数实现 bool is_cidr_format(const char *cidr) { // ... 实现检查CIDR格式的代码 return true; // 简化示例 } ``` ### 修正关键点: 1. **链表实现**:使用`struct list_head`和对应的宏及函数。 2. **结构体成员名**:将`alias_domains`改为`aliases`(根据原始结构体定义)。 3. **函数声明**:确保`is_cidr_format`在使用前声明或定义。 4. **全局变量**:明确声明`g_in_landns_mode`和`g_landns_list`。 5. **链表初始化**:使用`INIT_LIST_HEAD`初始化链表头。 6. **命令树数组**:在使用前定义`lanDnsCmdTree`。 ### 注意事项: - 假设链表实现使用Linux内核风格,如果项目中有自己的链表实现,请调整为相应的函数和宏。 - `dmDnsServerRuleGetByName`函数需要在`dmlib.h`中声明,并在其他地方实现。 - 需要确保所有使用的函数(如`safe_strncpy`)都已定义。 ### 相关问题 §§相关问题§§: 1. 如何优化链表操作以提高配置模式下的性能? 2. 在多线程环境下,如何保证链表操作的安全性? 3. 如何扩展链表功能以支持快速查找和排序? 4. 在配置大量规则时(如超过1000条),如何避免加载时间过长? </think>根据编译错误,主要问题集中在链表实现和相关函数的使用上。以下是完整的修正方案: ### 链表实现修正 ```c /**************************************************************************************************/ /* LIST IMPLEMENTATION */ /**************************************************************************************************/ // 链表节点定义 typedef struct lanDns_node { CFG_DNSSERVER_RULE_T rule; bool is_new; bool modified; struct lanDns_node *next; // 使用指针而不是dlist_t } lanDns_node_t; // 全局链表头 static lanDns_node_t *g_landns_list = NULL; // 全局状态变量 static bool g_in_landns_mode = false; static lanDns_node_t *g_current_edit = NULL; // 链表初始化宏 #define DLIST_INIT(head) (head) = NULL // 链表遍历宏 #define dlist_for_each_entry(pos, head) \ for (pos = head; pos != NULL; pos = pos->next) // 安全遍历宏(支持删除) #define dlist_for_each_entry_safe(pos, n, head) \ for (pos = head, n = (pos ? pos->next : NULL); \ pos != NULL; \ pos = n, n = (n ? n->next : NULL)) // 添加节点到链表尾部 static void dlist_add_tail(lanDns_node_t **head, lanDns_node_t *new_node) { if (*head == NULL) { *head = new_node; } else { lanDns_node_t *current = *head; while (current->next != NULL) { current = current->next; } current->next = new_node; } new_node->next = NULL; } // 从链表删除节点 static void dlist_del(lanDns_node_t **head, lanDns_node_t *node) { if (*head == NULL || node == NULL) return; if (*head == node) { *head = node->next; } else { lanDns_node_t *prev = *head; while (prev->next != NULL && prev->next != node) { prev = prev->next; } if (prev->next == node) { prev->next = node->next; } } free(node); } // 链表节点计数 static int dlist_count(lanDns_node_t *head) { int count = 0; lanDns_node_t *current = head; while (current) { count++; current = current->next; } return count; } ``` ### 修正后的Profile处理函数 ```c /**************************************************************************************************/ /* PROFILE HANDLING FUNCTIONS */ /**************************************************************************************************/ // 查找节点辅助函数 static lanDns_node_t* find_landns_node(const char *name) { lanDns_node_t *node; dlist_for_each_entry(node, g_landns_list) { if (strcmp(node->rule.name, name) == 0) { return node; } } return NULL; } // 创建新节点辅助函数 static lanDns_node_t* create_new_node(const char *name) { lanDns_node_t *node = malloc(sizeof(lanDns_node_t)); if (!node) return NULL; memset(node, 0, sizeof(lanDns_node_t)); safe_strncpy(node->rule.name, name, sizeof(node->rule.name)); safe_strncpy(node->rule.status, "on", sizeof(node->rule.status)); node->rule.ttl = 3600; // 默认TTL // 使用正确的字段名:aliases 而不是 alias_domains safe_strncpy(node->rule.lan_networks, "all", sizeof(node->rule.lan_networks)); node->is_new = true; node->modified = true; // 添加到链表 dlist_add_tail(&g_landns_list, node); return node; } // Profile 处理函数 STATUS cli_lanDnsAddProfile(cli_env *pCliEnv, char *profileName) { if (!g_in_landns_mode) { cliPrintf(pCliEnv, "%% Please enter LAN DNS configuration mode first ('landns enter')\n"); return ERROR; } if (!profileName || strlen(profileName) == 0) { cliPrintf(pCliEnv, "%% Error: Profile name cannot be empty\n"); return ERROR; } // 1. 先在内存链表中查找 lanDns_node_t *node = find_landns_node(profileName); if (node) { g_current_edit = node; cliPrintf(pCliEnv, "%% Continuing editing profile: %s\n", profileName); return OK; } // 2. 内存中没有,检查数据库 CFG_DNSSERVER_RULE_T db_rule; memset(&db_rule, 0, sizeof(CFG_DNSSERVER_RULE_T)); int db_ret = dmDnsServerRuleGetByName(profileName, &db_rule); if (db_ret == ERR_NO_ERROR) { // 数据库中存在 - 创建内存节点 node = malloc(sizeof(lanDns_node_t)); if (!node) { cliPrintf(pCliEnv, "%% Memory allocation error\n"); return ERROR; } memcpy(&node->rule, &db_rule, sizeof(CFG_DNSSERVER_RULE_T)); node->is_new = false; node->modified = false; node->next = NULL; dlist_add_tail(&g_landns_list, node); g_current_edit = node; cliPrintf(pCliEnv, "%% Editing existing profile: %s\n", profileName); return OK; } // 3. 全新创建 node = create_new_node(profileName); if (!node) { cliPrintf(pCliEnv, "%% Error creating profile\n"); return ERROR; } g_current_edit = node; cliPrintf(pCliEnv, "%% Creating new profile: %s\n", profileName); cliPrintf(pCliEnv, "%% Use 'type' command to set rule type\n"); return OK; } ``` ### 修正后的属性删除函数 ```c /**************************************************************************************************/ /* ATTRIBUTE DELETION FUNCTION */ /**************************************************************************************************/ STATUS cli_lanDnsDeleteAttribute(cli_env *pCliEnv, char *attr) { if (!g_current_edit) { cliPrintf(pCliEnv, "%% No active profile to modify\n"); return ERROR; } if (!attr) { cliPrintf(pCliEnv, "%% Error: Attribute name must be specified\n"); return ERROR; } // 使用正确的字段名:aliases 而不是 alias_domains if (strcmp(attr, "alias") == 0) { memset(g_current_edit->rule.aliases, 0, sizeof(g_current_edit->rule.aliases)); g_current_edit->modified = true; cliPrintf(pCliEnv, "%% Aliases cleared\n"); } else if (strcmp(attr, "ipv4") == 0) { memset(g_current_edit->rule.ipv4_addrs, 0, sizeof(g_current_edit->rule.ipv4_addrs)); g_current_edit->modified = true; cliPrintf(pCliEnv, "%% IPv4 addresses cleared\n"); } else if (strcmp(attr, "ipv6") == 0) { memset(g_current_edit->rule.ipv6_addrs, 0, sizeof(g_current_edit->rule.ipv6_addrs)); g_current_edit->modified = true; cliPrintf(pCliEnv, "%% IPv6 addresses cleared\n"); } else if (strcmp(attr, "dns-server") == 0) { memset(g_current_edit->rule.dns_server, 0, sizeof(g_current_edit->rule.dns_server)); g_current_edit->modified = true; cliPrintf(pCliEnv, "%% DNS servers cleared\n"); } else if (strcmp(attr, "cname") == 0) { memset(g_current_edit->rule.cname, 0, sizeof(g_current_edit->rule.cname)); g_current_edit->modified = true; cliPrintf(pCliEnv, "%% CNAME target cleared\n"); } else { cliPrintf(pCliEnv, "%% Error: Unsupported attribute '%s'\n", attr); return ERROR; } return OK; } ``` ### 修正后的显示函数 ```c /**************************************************************************************************/ /* SHOW FUNCTION */ /**************************************************************************************************/ STATUS cli_lanDnsShow(cli_env *pCliEnv) { if (!g_current_edit) { cliPrintf(pCliEnv, "%% No active profile to show\n"); return ERROR; } CFG_DNSSERVER_RULE_T *rule = &g_current_edit->rule; cliPrintf(pCliEnv, "Profile: %s\n", rule->name); cliPrintf(pCliEnv, "Status: %s\n", rule->status); cliPrintf(pCliEnv, "Domain: %s\n", rule->domain); cliPrintf(pCliEnv, "Type: %s\n", rule->type); cliPrintf(pCliEnv, "TTL: %d\n", rule->ttl); // 使用正确的字段名:aliases 而不是 alias_domains if (strlen(rule->aliases) > 0) { cliPrintf(pCliEnv, "Aliases: %s\n", rule->aliases); } if (strlen(rule->lan_networks) > 0) { cliPrintf(pCliEnv, "LAN Networks: %s\n", rule->lan_networks); } if (strlen(rule->ipv4_addrs) > 0) { cliPrintf(pCliEnv, "IPv4: %s\n", rule->ipv4_addrs); } if (strlen(rule->ipv6_addrs) > 0) { cliPrintf(pCliEnv, "IPv6: %s\n", rule->ipv6_addrs); } if (strlen(rule->cname) > 0) { cliPrintf(pCliEnv, "CNAME: %s\n", rule->cname); } if (strlen(rule->dns_server) > 0) { cliPrintf(pCliEnv, "DNS Servers: %s\n", rule->dns_server); } cliPrintf(pCliEnv, "Changes: %s\n", g_current_edit->modified ? "Modified (not committed)" : "No changes"); cliPrintf(pCliEnv, "Status: %s\n", g_current_edit->is_new ? "New rule" : "Existing rule"); return OK; } ``` ### 修正后的初始化函数 ```c /**************************************************************************************************/ /* INITIALIZATION FUNCTIONS */ /**************************************************************************************************/ void cli_lanDns_init(void) { // 注册命令树(假设cli_register_command_set已声明) extern void cli_register_command_set(const char *name, CLI_COMMAND_T *cmd_tree, const char *desc); cli_register_command_set("landns", lanDnsCmdTree, "LAN DNS Configuration"); // 初始化全局状态 g_in_landns_mode = false; g_current_edit = NULL; g_landns_list = NULL; // 初始化链表头 } STATUS cli_enter_lanDns(cli_env *pCliEnv) { // 初始化链表 DLIST_INIT(g_landns_list); // 从数据库加载所有规则 CFG_DNSSERVER_RULE_T **lst = NULL; int count = 0; if (dmDnsServerRuleGetAll(&lst) == ERR_NO_ERROR) { for (CFG_DNSSERVER_RULE_T **pp = lst; *pp; pp++) { lanDns_node_t *node = malloc(sizeof(lanDns_node_t)); if (node) { memset(node, 0, sizeof(lanDns_node_t)); memcpy(&node->rule, *pp, sizeof(CFG_DNSSERVER_RULE_T)); node->is_new = false; node->modified = false; node->next = NULL; dlist_add_tail(&g_landns_list, node); count++; } } dmDnsServerRuleListFree(lst); cliPrintf(pCliEnv, "%% Loaded %d DNS rules\n", count); } else { cliPrintf(pCliEnv, "%% Warning: Failed to load DNS rules\n"); } g_in_landns_mode = true; return OK; } STATUS cli_exit_lanDns(cli_env *pCliEnv) { // 清理未提交的修改 lanDns_node_t *node, *next; dlist_for_each_entry_safe(node, next, g_landns_list) { if (node->modified) { cliPrintf(pCliEnv, "%% Discarding uncommitted changes for profile '%s'\n", node->rule.name); dlist_del(&g_landns_list, node); } } g_in_landns_mode = false; g_current_edit = NULL; return OK; } ``` ### CIDR格式验证函数 ```c /**************************************************************************************************/ /* VALIDATION FUNCTIONS */ /**************************************************************************************************/ // 检查CIDR格式 bool is_cidr_format(const char *cidr) { if (!cidr) return false; char copy[64]; safe_strncpy(copy, cidr, sizeof(copy)); char *slash = strchr(copy, '/'); if (!slash) return false; *slash = '\0'; char *mask_str = slash + 1; // 验证IP部分 struct in_addr addr; if (inet_pton(AF_INET, copy, &addr) != 1) { return false; } // 验证子网掩码部分 errno = 0; char *end; long mask = strtol(mask_str, &end, 10); if (errno != 0 || *end != '\0' || mask < 0 || mask > 32) { return false; } return true; } // 验证网络列表 static bool is_valid_network_list(const char *list) { if (!list || strlen(list) == 0) return false; char copy[256]; safe_strncpy(copy, list, sizeof(copy)); char *token = strtok(copy, ","); while (token != NULL) { // 跳过空格 while (*token == ' ') token++; // 检查是否为"all"或CIDR格式 if (strcmp(token, "all") != 0 && !is_cidr_format(token)) { return false; } token = strtok(NULL, ","); } return true; } ``` ### 命令树定义 ```c /**************************************************************************************************/ /* COMMAND TREE DEFINITION */ /**************************************************************************************************/ // 命令处理函数声明 STATUS cli_enter_lanDns(cli_env *pCliEnv); STATUS cli_exit_lanDns(cli_env *pCliEnv); STATUS cli_lanDnsAddProfile(cli_env *pCliEnv, char *profileName); // ... 其他函数声明 // 命令树定义 CLI_COMMAND_T lanDnsCmdTree[] = { CMD("enter", cli_enter_lanDns, "Enter LAN DNS configuration mode"), CMD("exit", cli_exit_lanDns, "Exit LAN DNS configuration mode"), CMD_ARG("profile", cli_lanDnsAddProfile, "Set or edit DNS profile"), CMD_ARG("type", cli_lanDnsAddType, "Set rule type (ip|cname|forward)"), CMD_ARG("domain", cli_lanDnsAddDomain, "Set primary domain name"), CMD_ARG("alias", cli_lanDnsAddAlias, "Add alias domain"), CMD_ARG("status", cli_lanDnsAddStatus, "Set status (on|off)"), CMD_ARG("ipv4", cli_lanDnsAddIpv4, "Set IPv4 address for IP type rule"), CMD_ARG("ipv6", cli_lanDnsAddIpv6, "Set IPv6 address for IP type rule"), CMD_ARG("cname", cli_lanDnsAddCname, "Set CNAME target for CNAME type rule"), CMD_ARG("dns-server", cli_lanDnsAddDnsServer, "Set DNS server for FORWARD type rule"), CMD_ARG("lan-networks", cli_lanDnsAddLanNetworks, "Set applicable LAN networks"), CMD_ARG("ttl", cli_lanDnsAddTtl, "Set TTL (time-to-live)"), CMD_ARG("no", cli_lanDnsDeleteAttribute, "Remove attribute (e.g. 'no ipv4')"), CMD("show", cli_lanDnsShow, "Show current configuration"), CMD("commit", cli_lanDnsCommit, "Commit changes to configuration"), CMD("cancel", cli_lanDnsCancel, "Discard changes and exit editing mode"), CMD_END() }; ``` ### 关键修正点总结 1. **链表实现**: - 使用简单的指针链表代替 `dlist_t` 类型 - 自定义链表操作函数 (`
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值