在笔记Netfilter之协议族初始化–AF_INET中,有看到在AF_INET的初始化过程中,有向Netfilter框架注册setsockopt()/getsockopt()接口,这是AF_INET协议族和用户空间相关程序(如iptables)沟通的接口,这篇笔记就来看看这组接口的实现。涉及的代码文件主要是:
代码路径 | 说明 |
---|---|
net/ipv4/netfilter/ip_tables.c | IPv4 Netfilter核心文件 |
1. 用户空间接口
如ip_tables_net_init()函数,用户空间接口为ipt_sockopts,所以SET操作最后由do_ipt_set_ctl()实现,GET操作由do_ipt_get_ctl()实现。
static struct nf_sockopt_ops ipt_sockopts = {
.pf = PF_INET,
.set_optmin = IPT_BASE_CTL,
.set_optmax = IPT_SO_SET_MAX+1,
.set = do_ipt_set_ctl,
#ifdef CONFIG_COMPAT
.compat_set = compat_do_ipt_set_ctl,
#endif
.get_optmin = IPT_BASE_CTL,
.get_optmax = IPT_SO_GET_MAX+1,
.get = do_ipt_get_ctl,
#ifdef CONFIG_COMPAT
.compat_get = compat_do_ipt_get_ctl,
#endif
.owner = THIS_MODULE,
};
2. 设置规则:do_ipt_set_ctl()
static int do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
{
int ret;
//调用者必须要有网络管理员权限,通常是root
if (!capable(CAP_NET_ADMIN))
return -EPERM;
//目前仅支持两个SET命令
switch (cmd) {
case IPT_SO_SET_REPLACE:
//该命令用于设置规则,这里要注意的是,设计防火墙规则的修改时,用户空间
//和内核空间是交换整个table的内容,并非单单修改指定的规则
ret = do_replace(sk->sk_net, user, len);
break