首先我们先来分析下ipset_hash_mac.c文件
在每个文件的开始位置
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jozsef Kadlecsik <[email protected]>");
IP_SET_MODULE_DESC("hash:mac", IPSET_TYPE_REV_MIN, IPSET_TYPE_REV_MAX);
MODULE_ALIAS("ip_set_hash:mac");
下面好好看下这个宏,IP_SET_MODULE_DESC
从字面意思上看,IP_SET_MODULE_DESC:ipset模块的描述
#define _IP_SET_MODULE_DESC(a, b, c) \
MODULE_DESCRIPTION(a " type of IP sets, revisions " b "-" c)
#define IP_SET_MODULE_DESC(a, b, c) \
_IP_SET_MODULE_DESC(a, __stringify(b), __stringify(c))
__stringify是个什么东西?
把传入的参数直接转化为字符串
https://blog.csdn.net/duanlove/article/details/7974889
最开始的时候,我就是IP_SET_MODULE_DESC这块第一个参数填写错了,
dimension的含义
opt设置的IPSET_OPT_ETHER
.opt = IPSET_OPT_ETHER
因为我们要添加新的类型,所以可能需要创建IPSET_OPT_STRING
1.枚举定义
data.h文件中的
enum ipset_opt {
IPSET_OPT_NONE = 0,
/* Common ones */
IPSET_SETNAME,
IPSET_OPT_TYPENAME,
IPSET_OPT_FAMILY,
/* ADT-specific options */
IPSET_OPT_ETHER,//mac对应的枚举在这里!!!
IPSET_OPT_NAME,
IPSET_OPT_NAMEREF,
IPSET_OPT_IP2,
IPSET_OPT_CIDR2,
IPSET_OPT_IP2_TO,
IPSET_OPT_PROTO,
IPSET_OPT_IFACE,
};
2 注册时添充need和full的值
3.IPSET_ADT_FLAGS宏定义,这个宏的调用位置?
#define IPSET_ADT_FLAGS \
(IPSET_FLAG(IPSET_OPT_IP) \
| IPSET_FLAG(IPSET_OPT_IP_TO) \
| IPSET_FLAG(IPSET_OPT_CIDR) \
| IPSET_FLAG(IPSET_OPT_MARK) \
| IPSET_FLAG(IPSET_OPT_PORT) \
| IPSET_FLAG(IPSET_OPT_PORT_TO) \
| IPSET_FLAG(IPSET_OPT_TIMEOUT) \
| IPSET_FLAG(IPSET_OPT_ETHER) \
| IPSET_FLAG(IPSET_OPT_NAME) \
| IPSET_FLAG(IPSET_OPT_NAMEREF) \
| IPSET_FLAG(IPSET_OPT_IP2) \
| IPSET_FLAG(IPSET_OPT_CIDR2) \
| IPSET_FLAG(IPSET_OPT_PROTO) \
| IPSET_FLAG(IPSET_OPT_IFACE) \
| IPSET_FLAG(IPSET_OPT_CADT_FLAGS)\
| IPSET_FLAG(IPSET_OPT_BEFORE) \
| IPSET_FLAG(IPSET_OPT_PHYSDEV) \
| IPSET_FLAG(IPSET_OPT_NOMATCH) \
| IPSET_FLAG(IPSET_OPT_PACKETS) \
| IPSET_FLAG(IPSET_OPT_BYTES) \
| IPSET_FLAG(IPSET_OPT_ADT_COMMENT)\
| IPSET_FLAG(IPSET_OPT_SKBMARK) \
| IPSET_FLAG(IPSET_OPT_SKBPRIO) \
| IPSET_FLAG(IPSET_OPT_SKBQUEUE))
另外还有一个IPSET_CREATE_FLAGS是做什么使用的?
4.ipset_data_sizeof 计算特定数据类型的长度
其中计算IPSET_OPT_ETHER类型的长度,
case IPSET_OPT_ETHER:
return ETH_ALEN;
5.ipset_data_get函数
case IPSET_OPT_ETHER:
return data->adt.ether;
亲自验证下何时调用ipset_data_get函数中的IPSET_OPT_ETHER分支?
6.ipset_data_set函数
/* ADT-specific options */
case IPSET_OPT_ETHER:
memcpy(data->adt.ether, value, ETH_ALEN);
break;
在编写输出函数时遇到了问题
在ipset_hash_mac.c文件中,ipset_hash_mac0结构体定义如下:
parse回调函数,负责解析用户输入的参数,并设置到内核中
print回调函数,在执行ipset list命令时,显示字符串
何时调用elem的parse函数呢?
在parse.c文件中的parse_elem宏,去解析每一个元素,这个解析的是命令行内容,
#define parse_elem(s, t, d, str) \
do { \
if (!(t)->elem[d - 1].parse) \
goto internal; \
ret = (t)->elem[d - 1].parse(s, (t)->elem[d - 1].opt, str); \
if (ret) \
goto out; \
} while (0)
ipset_parse_elem函数中调用的parse_elem宏,
根据type->dimension的值是否为IPSET_DIM_ONE,IPSET_DIM_TWO,IPSET_DIM_THREE来进一步调用parse_elem函数
何时调用elem的print回调函数呢?
int
ipset_print_elem(char *buf, unsigned int len,
const struct ipset_data *data, enum ipset_opt opt UNUSED,
uint8_t env)
{
const struct ipset_type *type;
int size, offset = 0;
assert(buf);
assert(len > 0);
assert(data);
type = ipset_data_get(data, IPSET_OPT_TYPE);
if (!type)
return -1;
size = type->elem[IPSET_DIM_ONE - 1].print(buf, len, data,
type->elem[IPSET_DIM_ONE - 1].opt, env);
SNPRINTF_FAILURE(size, len, offset);
IF_D(ipset_data_test(data, type->elem[IPSET_DIM_TWO - 1].opt),
"print second elem");
if (type->dimension == IPSET_DIM_ONE ||
(type->last_elem_optional &&
!ipset_data_test(data, type->elem[IPSET_DIM_TWO - 1].opt)))
return offset;
size = snprintf(buf + offset, len, IPSET_ELEM_SEPARATOR);
SNPRINTF_FAILURE(size, len, offset);
size = type->elem[IPSET_DIM_TWO - 1].print(buf + offset, len, data,
type->elem[IPSET_DIM_TWO - 1].opt, env);
SNPRINTF_FAILURE(size, len, offset);
if (type->dimension == IPSET_DIM_TWO ||
(type->last_elem_optional &&
!ipset_data_test(data, type->elem[IPSET_DIM_THREE - 1].opt)))
return offset;
size = snprintf(buf + offset, len, IPSET_ELEM_SEPARATOR);
SNPRINTF_FAILURE(size, len, offset);
size = type->elem[IPSET_DIM_THREE - 1].print(buf + offset, len, data,
type->elem[IPSET_DIM_THREE - 1].opt, env);
SNPRINTF_FAILURE(size, len, offset);
return offset;
}
现在使用ipset add命令时,报错 ipset v7.1: Element cannot be added to the set: it's already added
我先过一下hash:mac类型的集合的流程,然后再考虑说其他的。
参考文章
云风的博客
https://blog.codingnow.com/2018/05/ineffective_debugger.html