这篇笔记记录了连接跟踪子系统对L3和L4协议的管理,核心代码涉及如下文件:
代码路径 | 说明 |
---|---|
net/netfilter/nf_conntrack_l3proto.c | 对L3和L4协议的管理 |
include/net/netfilter/nf_conntrack_l3proto.h | L3协议相关数据结构定义 |
include/net/netfilter/nf_conntrack_l4proto.h | L4协议相关数据结构定义 |
1. L3协议管理
每个支持连接跟踪子系统的L3协议(或者说协议族),都必须先向连接跟踪子系统注册自己,实际上就是提供一个struct nf_conntrack_l3proto对象。
1.1 struct nf_conntrack_l3proto
L3协议在连接跟踪子系统中的定义如下:
struct nf_conntrack_l3proto
{
//L3协议号,就是用协议族表示,如PF_INET
u_int16_t l3proto;
//协议的名字,如AF_INET协议族为“ipv4”
const char *name;
//根据skb内容计算tuple,tuple可以理解为连接的地址,每一个连接有两个tuple,
//分别表示数据传输的两个方向。nhoff表示L3首部在skb中的偏移,如果计算成功,
//返回true,否则返回false(必选回调)
int (*pkt_to_tuple)(const struct sk_buff *skb, unsigned int nhoff,
struct nf_conntrack_tuple *tuple);
//根据orig方向的tuple,计算其反方向的tuple
int (*invert_tuple)(struct nf_conntrack_tuple *inverse,
const struct nf_conntrack_tuple *orig);
int (*print_tuple)(struct seq_file *s, const struct nf_conntrack_tuple *);
//数据包进入连接跟踪子系统后,通过检查后,会调用该回调确定返回给Netfilter框架的值,
//一般来讲,连接跟踪子系统不应该过滤数据包,所以该函数大多数情况下应该返回NF_ACCEPT
int (*packet)(struct nf_conn *ct, const struct sk_buff *skb,
enum ip_conntrack_info ctinfo);
//如果输入的数据包属于一个新的连接,那么会调用该回调
int (*new)(struct nf_conn *ct, const struct sk_buff *skb);
//分析skb首部,解析出L4协议号保存在protonum中,L4报文开始位置距离skb第一个
//字节的偏移量保存在dataoff中,处理成功返回大于0(必选回调)
int (*get_l4proto)(const struct sk_buff *skb, unsigned int nhoff,
unsigned int *dataoff, u_int8_t *protonum);
//下面三个字段和Netlink相关,用于和用户空间通信,先忽略
int (*tuple_to_nlattr)(struct sk_buff *skb,
const struct nf_conntrack_tuple *t);
int (*nlattr_to_tuple)(struct nlattr *tb[]