您的位置:首页 > 运维架构 > Linux

Linux netfilter源码分析(2)

2013-07-06 12:32 267 查看
二、ipt_table数据结构和表的初始化

2.1 include/linux/netfilter_ipv4/ip_tables.h struct ipt_table 表结构

struct ipt_table

{

struct list_head list;

/* 表链 */

char name[IPT_TABLE_MAXNAMELEN];

/* 表名,如"filter"、"nat"等,为了满足自动模块加载的设计,包含该表的模块应命名为iptable_'name'.o
*/

struct ipt_replace *table;

/* 表模子,初始为initial_table.repl */

unsigned int valid_hooks;

/* 位向量,标示本表所影响的HOOK */

rwlock_t lock;

/* 读写锁,初始为打开状态 */

struct ipt_table_info *private;

/* iptable的数据区,见下 */

struct module *me;

/* 是否在模块中定义 */

};

2.2 struct ipt_table_info是实际描述表的数据结构 ip_tables.c

struct ipt_table_info

{

unsigned int size;

/* 表大小 */

unsigned int number;

/* 表中的规则数 */

unsigned int initial_entries;

/* 初始的规则数,用于模块计数 */

unsigned int hook_entry[NF_IP_NUMHOOKS];

/* 记录所影响的HOOK的规则入口相对于下面的entries变量的偏移量 */

unsigned int underflow[NF_IP_NUMHOOKS];

/* 与hook_entry相对应的规则表上限偏移量,当无规则录入时,相应的hook_entry和underflow均为0
*/

char entries[0] ____cacheline_aligned;

/* 规则表入口 */

};

2.3 include/linux/netfilter_ipv4 规则用struct ipt_entry结构表示,包含匹配用的IP头部分、一个Target和0个或多个Match。由于Match数不定,所以一条规则实际的占用空间是可变的。结构定义如下

struct ipt_entry

{

struct ipt_ip ip;

/* 所要匹配的报文的IP头信息 */

unsigned int nfcache;

/* 位向量,标示本规则关心报文的什么部分,暂未使用 */

u_int16_t target_offset;

/* target区的偏移,通常target区位于match区之后,而match区则在ipt_entry的末尾;

初始化为sizeof(struct ipt_entry),即假定没有match */

u_int16_t next_offset;

/* 下一条规则相对于本规则的偏移,也即本规则所用空间的总和,

初始化为sizeof(struct ipt_entry)+sizeof(struct ipt_target),即没有match */

unsigned int comefrom;

/* 规则返回点,标记调用本规则的HOOK号,可用于检查规则的有效性 */

struct ipt_counters counters;

/* 记录该规则处理过的报文数和报文总字节数 */

unsigned char elems[0];

/*target或者是match的起始位置 */

}

2.4 iptables的初始化init(void) ,以filter表为例 iptable_filter.c

static int __init init(void)
{
int ret;

if (forward < 0 || forward > NF_MAX_VERDICT) {
printk("iptables forward must be 0 or 1\n");
return -EINVAL;
}

/* Entry 1 is the FORWARD hook */
initial_table.entries[1].target.verdict = -forward - 1;

/* Register table */
ret = ipt_register_table(&packet_filter); //注册filter表
if (ret < 0)
return ret;

/* Register hooks */
ret = nf_register_hook(&ipt_ops[0]); //注册三个HOOK
if (ret < 0)
goto cleanup_table;

ret = nf_register_hook(&ipt_ops[1]);
if (ret < 0)
goto cleanup_hook0;

ret = nf_register_hook(&ipt_ops[2]);
if (ret < 0)
goto cleanup_hook1;

return ret;

cleanup_hook1:
nf_unregister_hook(&ipt_ops[1]);
cleanup_hook0:
nf_unregister_hook(&ipt_ops[0]);
cleanup_table:
ipt_unregister_table(&packet_filter);

return ret;
}

/* ipt_register_table函数的参数packet_filter包含了待注册表的各个参数 */
static struct ipt_table packet_filter = {
.name = "filter",
.table = &initial_table.repl,
.valid_hooks = FILTER_VALID_HOOKS,
.lock = RW_LOCK_UNLOCKED,
.me = THIS_MODULE
};

/* 上面的&initial_table.repl是一个ipt_replace结构,也就是ipt_table-〉*table的初始值。
下面是ipt_replace结构的定义,它和ipt_table_info很相似,基本上就是用来初始化ipt_table中的ipt_table_info
*private的,这个结构不同于ipt_table_info之处在于,它还要保存表的旧的规则信息 */
struct ipt_replace
{
char name[IPT_TABLE_MAXNAMELEN]; /* 表名 */
unsigned int valid_hooks; /* 影响的hook */
unsigned int num_entries; /* entry数 */
unsigned int size; /* entry的总大小 */
unsigned int hook_entry[NF_IP_NUMHOOKS]; /* 规则入口的偏移值 */
unsigned int underflow[NF_IP_NUMHOOKS]; /* 规则的最大偏移值 */
unsigned int num_counters; /* 规则数 */
struct ipt_counters __user *counters;
struct ipt_entry entries[0]; /* 规则入口 */
};

/* 下面是initial_table.repl的初始化 */
static struct
{
struct ipt_replace repl;
struct ipt_standard entries[3];
struct ipt_error term;
} initial_table __initdata
= { { "filter", FILTER_VALID_HOOKS, 4,
sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error),
{ [NF_IP_LOCAL_IN] = 0,
[NF_IP_FORWARD] = sizeof(struct ipt_standard),
[NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 },
{ [NF_IP_LOCAL_IN] = 0,
[NF_IP_FORWARD] = sizeof(struct ipt_standard),
[NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 },
0, NULL, { } },
{
/* LOCAL_IN */
{ { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
0,
sizeof(struct ipt_entry),
sizeof(struct ipt_standard),
0, { 0, 0 }, { } },
{ { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
-NF_ACCEPT - 1 } },
/* FORWARD */
{ { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
0,
sizeof(struct ipt_entry),
sizeof(struct ipt_standard),
0, { 0, 0 }, { } },
{ { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
-NF_ACCEPT - 1 } },
/* LOCAL_OUT */
{ { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
0,
sizeof(struct ipt_entry),
sizeof(struct ipt_standard),
0, { 0, 0 }, { } },
{ { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
-NF_ACCEPT - 1 } }
},
/* ERROR */
{ { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
0,
sizeof(struct ipt_entry),
sizeof(struct ipt_error),
0, { 0, 0 }, { } },
{ { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
{ } },
"ERROR"
}
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: