1 扩展主要数据结构
如图所示:
2 添加扩展
nf_ct_ext_add的流程图:
3 扩展的限制
连接跟踪模块加载时的初始化函数里会判断各种扩展类型数据的总长度是否大于255,大于255则编译报错。缘由是扩展功能结构体nf_ct_ext的len为u8,即len不能大于255,否则len会溢出。len是扩展功能的数据总长度,包含结构体头部。
int nf_conntrack_init_start(void)
{
int max_factor = 8;
int ret = -ENOMEM;
int i;
/* struct nf_ct_ext uses u8 to store offsets/size */
BUILD_BUG_ON(total_extension_size() > 255u);
seqcount_init(&nf_conntrack_generation);
……
}
total_extension_size计算内核所有扩展类型的数据总长度,如果NF_CT_EXT_NUM大于实际计算的扩展类型数则编译报错。
static __always_inline unsigned int total_extension_size(void)
{
/* remember to add new extensions below */
#ifdef CONFIG_FWOS_BASE
BUILD_BUG_ON(NF_CT_EXT_NUM > 11);
#else
BUILD_BUG_ON(NF_CT_EXT_NUM > 9);
#endif
return sizeof(struct nf_ct_ext) + //扩展头部,32
sizeof(struct nf_conn_help) //help扩展,56字节
#if IS_ENABLED(CONFIG_NF_NAT)
+ sizeof(struct nf_conn_nat) //nat扩展,8字节
#endif
+ sizeof(struct nf_conn_seqadj) //24字节
+ sizeof(struct nf_conn_acct) //32
#ifdef CONFIG_NF_CONNTRACK_EVENTS
+ sizeof(struct nf_conntrack_ecache) //24
#endif
#ifdef CONFIG_NF_CONNTRACK_TIMESTAMP
+ sizeof(struct nf_conn_tstamp) //16
#endif
#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
+ sizeof(struct nf_conn_timeout) //8
#endif
#ifdef CONFIG_NF_CONNTRACK_LABELS
+ sizeof(struct nf_conn_labels) //16
#endif
#if IS_ENABLED(CONFIG_NETFILTER_SYNPROXY)
+ sizeof(struct nf_conn_synproxy) //12
#endif
#ifdef CONFIG_FWOS_BASE
+ sizeof(struct common_extend_info) //自定义扩展,用于快转功能,88
#endif
#if 0
+ sizeof(struct utm_conn)
+ sizeof(struct expect_extend_info)
+ sizeof(struct opc_extend_info)
+ sizeof(struct dpi_proto_learn)
+ sizeof(struct dpi_extend_info)
#endif
;
};
即内核关于扩展功能的限制是所有扩展类型数据的长度总和不能超过255,除非更改扩展功能结构体的len类型。
4 增加自定义扩展功能的步骤
1)enum nf_ct_ext_id里增加一个自定义扩展的ID
2)定义一个nf_ct_ext_type类型的结构体,指明该自定义扩展的数据长度和ID等
3)通过扩展注册函数nf_ct_extend_register把nf_ct_ext_type类型的结构体赋值到数组nf_ct_ext_types[id]里
4)用扩展添加函数nf_ct_ext_add封装一个自定义扩展添加函数,返回值为该自定义扩展的数据结构体指针
5)用扩展查找函数nf_ct_ext_find封装一个自定义扩展查找函数,返回值为该自定义扩展的数据结构体指针
6)在连接跟踪框架合适的位置调用自定义扩展扩展添加函数
7)需要读写该自定义扩展数据时,调用自定义扩展查找函数获取对应的数据指针进行读写
8)total_extension_size里加上该自定义扩展数据长度的计算