使用libipset在C语言中创建IpSet失败:提示“Invalid create command: missing settype”,终端命令可行但库调用无效(版本7.24)
Fixing "Invalid create command: missing settype" in libipset IPSET_CMD_CREATE
Let's break down why your libipset code is failing with the "missing settype" error, even though the equivalent terminal command works. The core issue is incorrect data type handling for several libipset options, plus a small oversight with the set name.
Root Causes
- Wrong parameter types for numeric options: Libipset's
ipset_session_data_setexpects specific data types for options likeIPSET_OPT_FAMILY,IPSET_OPT_MAXELEM, andIPSET_OPT_TIMEOUT—not string literals. Your terminal command accepts strings like "inet" or "65536" because the ipset CLI parses them, but the library API requires raw numeric values. - Hardcoded set name: You're passing "test_ip_set" to
IPSET_SETNAMEinstead of using the function'sip_set_nameparameter, which would create a set with a name different from what you intended. - Missing error checks for
ipset_session_data_set: You're not verifying if each option was set successfully, which could hide subtle issues. - Premature session cleanup: You called
ipset_session_fini(session)before checking the result ofipset_cmd, which could invalidate the session before retrieving the error message.
Corrected Code
#include <sys/socket.h> // For AF_INET #include <stdint.h> // For uint32_t IPSetInfo * netlinkhandler_create_ip_set(char *ip_set_name){ struct ipset_session *session; int ret; int af_inet = AF_INET; uint32_t maxelem = 65536; uint32_t timeout = 0; // Load ipset types (required before creating sessions) ipset_load_types(); session = ipset_session_init(NULL,NULL); if (!session) { log_info("FATAL: ipset_session_init failed! Cannot proceed.\n"); return NULL; } // Set set name (use function parameter instead of hardcoding) ret = ipset_session_data_set(session, IPSET_SETNAME, ip_set_name); if (ret != 0) { log_info("[ERROR] Failed to set setname: %s", ipset_session_report_msg(session)); ipset_session_fini(session); return NULL; } // Set set type (hash:ip,port) ret = ipset_session_data_set(session, IPSET_OPT_TYPENAME, "hash:ip,port"); if (ret != 0) { log_info("[ERROR] Failed to set settype: %s", ipset_session_report_msg(session)); ipset_session_fini(session); return NULL; } // Set family (use AF_INET integer instead of string "inet") ret = ipset_session_data_set(session, IPSET_OPT_FAMILY, &af_inet); if (ret != 0) { log_info("[ERROR] Failed to set family: %s", ipset_session_report_msg(session)); ipset_session_fini(session); return NULL; } // Set maxelem (pass uint32_t value instead of string) ret = ipset_session_data_set(session, IPSET_OPT_MAXELEM, &maxelem); if (ret != 0) { log_info("[ERROR] Failed to set maxelem: %s", ipset_session_report_msg(session)); ipset_session_fini(session); return NULL; } // Set timeout (pass uint32_t value instead of string) ret = ipset_session_data_set(session, IPSET_OPT_TIMEOUT, &timeout); if (ret != 0) { log_info("[ERROR] Failed to set timeout: %s", ipset_session_report_msg(session)); ipset_session_fini(session); return NULL; } // Execute create command ret = ipset_cmd(session, IPSET_CMD_CREATE, 0); if(ret !=0){ log_info("[ERROR][IPSET CREATION FAILED] [IPSET NAME: %s] %s",ip_set_name,ipset_session_report_msg(session)); ipset_session_fini(session); return NULL; } log_info("[INFO][IPSET CREATION SUCCESSFUL] [IPSET NAME: %s]",ip_set_name); IPSetInfo *new_ip_set = (IPSetInfo *)malloc(sizeof(IPSetInfo)); new_ip_set->ip_set_name=ip_set_name; new_ip_set->number_of_ips=0; pthread_mutex_init(&new_ip_set->lock, NULL); ipset_session_fini(session); return new_ip_set; }
Key Changes Explained
- Set name alignment: Replaced the hardcoded "test_ip_set" with the function's
ip_set_nameparameter to match your intended set name. - Numeric option fixes:
IPSET_OPT_FAMILY: UsesAF_INET(an integer fromsys/socket.h) instead of the string "inet".IPSET_OPT_MAXELEMandIPSET_OPT_TIMEOUT: Pass pointers touint32_tvariables holding the actual numeric values, not string literals.
- Early error handling: Added checks for each
ipset_session_data_setcall to catch configuration issues early and clean up resources properly. - Delayed session cleanup: Moved
ipset_session_fini(session)to after validating theipset_cmdresult, ensuring you can retrieve error messages from the session before it's destroyed.
Why This Fixes the "Missing Settype" Error
The original code passed invalid data types for non-string options, which corrupted the session's internal state. This made libipset unable to properly parse the set type you specified, leading to the misleading "missing settype" error. By passing the correct data types, you ensure the session is properly configured, and the set type is recognized correctly.
内容的提问来源于stack exchange,提问作者Vignesh
相关产品推荐
相关产品推荐

