iptables iptc_init函数

本文深入解析iptables的初始化过程,包括通过socket通信与内核交互,获取表信息和规则详情。阐述了用户空间与内核空间的数据结构映射,以及ioctl和getsockopt函数在规则获取中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

iptc_init(): 根据指定的表名获取内核中该表的自身信息和表中所有规则

fcntl(fd, F_SETFD, FD_CLOEXEC)
fcntl(int fd, int cmd, long arg): 用来操作文件描述符一些特性。fcntl不仅可以施加建议性锁,还可以施加强制锁。同时,fcntl还可以对文件某一记录进行上锁,也就是记录锁。
F_SETFD 设置close-on-exec 旗标。该旗标以参数arg 的FD_CLOEXEC位决定

=========用户空间==========

对于ipv4和ipv6都被宏定义为TC_INIT

// libip4tc.c 
#define TC_INIT     iptc_init

// libip6tc.c 
#define TC_INIT     ip6tc_init

struct xtc_handle *
TC_INIT(const char *tablename)

1、创建sockfd = socket(TC_AF, SOCK_RAW, IPPROTO_RAW),与内核进行通信

2、将tablename设置到STRUCT_GETINFO info的name中,通过getsockopt(sockfd, TC_IPPROTO, SO_GET_INFO, &info, sizeof(info)),获取STRUCT_GETINFO信息,对于结构体用户空间、内核空间如何使用,结构体注释已经明确说明了

// libiptc/libip4tc.c
#define STRUCT_GETINFO struct ipt_getinfo

// libiptc/libip6tc.c
#define STRUCT_GETINFO struct ip6t_getinfo

// include/linuxe/netfileter_ipv4/ip_tables.h(来自内核)
/* The argument to IPT_SO_GET_INFO */
struct ipt_getinfo {
    /* Which table: caller fills this in. */
    char name[XT_TABLE_MAXNAMELEN];

    /* kernel fills these in */
    /* Which hook entry points are valid: bitmask */
    unsigned int valid_hooks;

    /* Hook entry points: one per netfilter hook. */
    unsigned int hook_entry[NF_INET_NUMHOOKS];

    /* Underflow points */
    unsigned int underflow[NF_INET_NUMHOOKS];

    /* Number of entries */
    unsigned int num_entries;

    /* size of entries */
    unsigned int size;
};

<<<<<<<<<<(1)

// libiptc/libiptc.c
struct xtc_handle {
    int sockfd;
    int chaned;

    struct list_head chains;

    struct chain_head *chain_iterator_cur;
    struct rule_head *rule_iterator_cur;

    unsigned int num_chains;        /* Number of user defined chains */

    struct chain_head **chain_index;    /* array for fast chain list access */
    unsigned int chain_index_sz;    /* size of chain index array */

    int sorted_offsets;

    STRUCT_GETINFO info;
    STRUCT_GET_ENTRIES *entries;
};

3、根据获取的STRUCT_GETINFO中的size信息,进行struct xtc_handle的分配{alloc_handle(STRUCT_GETINFO *info)},然后将xtc_handle中的sockfd、info、 entries->size进行赋值

4、再通过getsockopt获取entries的信息{getsockopt(sockfd, TC_IPPROTO, SO_GET_ENTRIES, H->entries, &tmp)}

// libiptc/libip4tc.c 
#define STRUCT_GET_ENTRIES struct ipt_get_entries

// libiptc/libip6tc.c 
#define STRUCT_GET_ENTRIES struct ip6t_get_entries

// include/linux/netfilter_ipv4/ip_tables.h
/* The argument to IPT_SO_GET_ENTRIES. */
struct ipt_get_entries {
    /* Which table: user fills this in. */
    char name[XT_TABLE_MAXNAMELEN];

    /* User fills this in: total entry size. */
    unsigned int size;

    /* The entries. */
    struct ipt_entry entrytable[0];
};

 

=========内核空间==========

1、内核模块通过函数do_ipt_get_ctl得到IPT_SO_GET_INFO命令,通过get_info获取信息

2、get_info首先从user参数中获取tablename: copy_from_user(name, user, sizeof(name));【根据用户空间的步骤2得知,用户空间传入的:q参数类型为STRUCT_GETINFO,但是这个位置获取的为字符串name,因此STRUCT_GETINFO第一个参数必须是name,并且一样大小的name空间】

3、根据name从内核空间中查找到xt_table t = try_then_request_module(xt_find_table_lock(net, AF_INET, name), "iptable_%s", name);

4、从获取的table中,从中拷贝出valid_hooks/hook_entry/under_flow/num_entries/size/name放置到新构建的ipt_getinfo info结构体中

5、调用copy_to_user到用户空间{copy_to_user(user, info, *len)}, 并对表进行解锁(获取表时进行了lock)

<<<<<<<<<<(1)

内核定义的几个数据结构用于与用户空间交互

1、IPT_SO_GET_INFO
 

>>>>>>>>ipv4的定义<<<<<<<<
// 在用户空间(iptables)中被重定义为 
#define STRUCT_GETINFO struct ipt_getinfo

// 在内核空间中定义为:
/* The argument to IPT_SO_GET_INFO */
struct ipt_getinfo{
    /* Which table: caller fills this in. */
    char name[XT_TABLE_MAXNAMELEN];

    /* Kernel fills these in. */
    /* Which hook entry points are valid: bitmask */
    unsigned int valid_hooks;

    /* Hook entry points: one per-netfilter hooks. */
    unsigned int hook_entry[NF_INET_NUMHOOKS];

    /* Underflow points */
    unsigned int underflow[NF_INET_NUMHOOKS];

    /* Number of entries */
    unsigned int num_entries;

    /* Size of entries*/
    unsigned int size;
};


>>>>>>>>ipv6的定义与ipv4类同<<<<<<<<

2、IPT_SO_GET_ENTRIES
 

// 在用户空间(iptables)被重定义为
#define STRUCT_GET_ENTRIES struct ipt_get_entries

// 在内核空间中的定义
/* The argument to IPT_SO_GET_ENTRIES. */
struct ipt_get_entries {
    /* Which table: user fills this in. */
    char name[XT_TABLE_MAXNAMELEN];

    /* User fills this in: total entry size. */
    unsigned int size;

    /* The entries */
    struct ipt_entry entrytable[0];
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值