分类: LINUX
2010-01-22 16:33:37
本章主要是讲表以及表的注册,包括:
1. 表的结构体形态;
2. 表的注册过程;
3. 以filter表来例举表的初始模板形态以及注册;
int ipt_register_table(struct xt_table *table, const struct ipt_replace *repl)
前一个包含了表的基本信息,包含了表名,所影响的Hook类型,规则长度,入口等等;
后一个是一个表的模块,即初始化的规则等等。
{
int ret;
struct xt_table_info *newinfo;
static struct xt_table_info bootstrap
= { 0, 0, 0, { 0 }, { 0 }, { } };
void *loc_cpu_entry;
newinfo = xt_alloc_table_info(repl->size); // 以规则部分长度为repl->size申请struct xt_table_info
if (!newinfo)
return -ENOMEM;
/* choose the copy on our node/cpu
* but dont care of preemption
*/
loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
memcpy(loc_cpu_entry, repl->entries, repl->size); // 拷贝repl的规则到newinfo
ret = translate_table(table->name, table->valid_hooks, // 设置newinfo里面的一些域,
newinfo, loc_cpu_entry, repl->size, // 并进行一些检查
repl->num_entries,
repl->hook_entry,
repl->underflow);
if (ret != 0) {
xt_free_table_info(newinfo);
return ret;
}
ret = xt_register_table(table, &bootstrap, newinfo); // 基本就是用newinfo赋值到table->private
if (ret != 0) { // 下面解释
xt_free_table_info(newinfo);
return ret;
}
return 0;
}
表以及表的注册例子packet_filter:
/*
* This is the 1999 rewrite of IP Firewalling, aiming for kernel 2.3.x.
*
* Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
* Copyright (C) 2000-2004 Netfilter Core Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include
#include
#include
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Netfilter Core Team
MODULE_DESCRIPTION("iptables filter table");
#define FILTER_VALID_HOOKS ((1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT))
static struct
{
struct ipt_replace repl; // 据说比较重要,ipt_replace后面解释
struct ipt_standard entries[3]; /* 3个hook点,各自一条缺省规则,默认target为ACCEPT*/
struct ipt_error term; // 错误处理规则
} initial_table __initdata
= { { "filter", FILTER_VALID_HOOKS, 4, // 在ipt_register_table中被用到:&initial_table.repl
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, { } }, // 此处为该结构体的struct ipt_entry entries[0]成员,从该成员可以找到
以下注册的所有hook点的规则,所指向的有效内容包含以下四条规则
/*以下是四条规则:*/
/*默认三个hook点的规则,ACCEPT,这里repl.etnryies == entries*/
也就是说此表默认有三条ACCEPT的规则
{
/* 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), // target_offset
sizeof(struct ipt_standard), // next_offset
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"
}
}
};
static struct ipt_table packet_filter = {
.name = "filter",
.valid_hooks = FILTER_VALID_HOOKS,
.lock = RW_LOCK_UNLOCKED,
.me = THIS_MODULE,
.af = AF_INET,
};
/* The work comes in here from netfilter.c. */
static unsigned int
ipt_hook(unsigned int hook,
struct sk_buff **pskb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
return ipt_do_table(pskb, hook, in, out, &packet_filter, NULL);
}
static unsigned int
ipt_local_out_hook(unsigned int hook,
struct sk_buff **pskb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
/* root is playing with raw sockets. */
if ((*pskb)->len < sizeof(struct iphdr)
|| (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) {
if (net_ratelimit())
printk("ipt_hook: happy cracking.\n");
return NF_ACCEPT;
}
return ipt_do_table(pskb, hook, in, out, &packet_filter, NULL);
}
static struct nf_hook_ops ipt_ops[] = {
{
.hook = ipt_hook,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_LOCAL_IN,
.priority = NF_IP_PRI_FILTER,
},
{
.hook = ipt_hook,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_FORWARD,
.priority = NF_IP_PRI_FILTER,
},
{
.hook = ipt_local_out_hook,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_LOCAL_OUT,
.priority = NF_IP_PRI_FILTER,
},
};
/* Default to forward because I got too much mail already. */
static int forward = NF_ACCEPT;
module_param(forward, bool, 0000);
static int __init iptable_filter_init(void) // module加载执行注册。
{
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, &initial_table.repl); // 注册表
if (ret < 0)
return ret;
/* Register hooks */
ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); // 注册HOOK操作结构体
if (ret < 0) // 里面的.hook函数会操作表
goto cleanup_table; // .hook = ipt_hook()
return ret;
cleanup_table:
ipt_unregister_table(&packet_filter);
return ret;
}
static void __exit iptable_filter_fini(void)
{
nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
ipt_unregister_table(&packet_filter);
}
module_init(iptable_filter_init);
module_exit(iptable_filter_fini);
注册表时,结合上面的初始化赋值,我们可以对应到ipt_replace结构体的各个域:
name :"filter"
//filter表所影响的Hook类型
valid_hooks:FILTER_VALID_HOOKS
//初始化的规则数为4条,每个Hook类型(对应用户空间的“链”)初始化一条,并以一条“错误的规则”表示结束
num_entries:4
//标准的规则用struct ipt_standard,错误的规则用struct ipt_error描述
size:sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error)
//计算初始的各Hook点对应的初始规则的偏移值
hook_entry[NF_IP_NUMHOOKS]:
{ [NF_IP_LOCAL_IN] = 0,
[NF_IP_FORWARD] = sizeof(struct ipt_standard),
[NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 }
underflow[NF_IP_NUMHOOKS]:
{ [NF_IP_LOCAL_IN] = 0,
[NF_IP_FORWARD] = sizeof(struct ipt_standard),
[NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 }
//因为是初始化模块,不存在旧表,所以,这些保存旧表信息的参数均为空
num_counters:0
counters:NULL
entries[0]:{ }
int xt_register_table(struct xt_table *table,
struct xt_table_info *bootstrap,
struct xt_table_info *newinfo)
{
int ret;
struct xt_table_info *private;
ret = mutex_lock_interruptible(&xt[table->af].mutex);
if (ret != 0)
return ret;
/* Don't autoload: we'd eat our tail... */
if (list_named_find(&xt[table->af].tables, table->name)) {
ret = -EEXIST;
goto unlock;
}
/* Simplifies replace_table code. */
table->private = bootstrap;
rwlock_init(&table->lock);
if (!xt_replace_table(table, 0, newinfo, &ret)) // 用newinfo替换掉上面刚赋值的bootstrap
goto unlock; // 下面详细说明
private = table->private;
duprintf("table->private->number = %u\n", private->number);
/* save number of initial entries */
private->initial_entries = private->number;
list_prepend(&xt[table->af].tables, table); // 简单的挂接到xt中相关协议数组的结构体成员
// 的tables链表头上,重要
ret = 0;
unlock:
mutex_unlock(&xt[table->af].mutex);
return ret;
}
xt协议数组的初始化:
static int __init xt_init(void)
{
int i;
xt = kmalloc(sizeof(struct xt_af) * NPROTO, GFP_KERNEL); // #define NPROTO 32
if (!xt)
return -ENOMEM;
for (i = 0; i < NPROTO; i++) {
mutex_init(&xt[i].mutex);
#ifdef CONFIG_COMPAT
mutex_init(&xt[i].compat_mutex);
#endif
INIT_LIST_HEAD(&xt[i].target);
INIT_LIST_HEAD(&xt[i].match);
INIT_LIST_HEAD(&xt[i].tables);
}
return 0;
}
struct xt_table_info *
xt_replace_table(struct xt_table *table,
unsigned int num_counters,
struct xt_table_info *newinfo,
int *error)
{
struct xt_table_info *oldinfo, *private;
/* Do the substitution. */
write_lock_bh(&table->lock);
private = table->private;
/* Check inside lock: is the old number correct? */
if (num_counters != private->number) { // 检查
duprintf("num_counters != table->private->number (%u/%u)\n",
num_counters, private->number);
write_unlock_bh(&table->lock);
*error = -EAGAIN;
return NULL;
}
oldinfo = private;
table->private = newinfo; // 用newinfo替换掉原来的private
newinfo->initial_entries = oldinfo->initial_entries;
write_unlock_bh(&table->lock);
return oldinfo; // 没什么用
}
EXPORT_SYMBOL_GPL(xt_replace_table);
/* The table itself */
struct xt_table_info
{
/* Size per table */
unsigned int size; // 应该是规则的总大小
/* Number of entries: FIXME. --RR */
unsigned int number; // 规则总数
/* Initial number of entries. Needed for module usage count */
unsigned int initial_entries;
/* Entry points and underflows */
unsigned int hook_entry[NF_IP_NUMHOOKS]; // 各个HOOK点的规则偏移量
unsigned int underflow[NF_IP_NUMHOOKS];
/* ipt_entry tables: one per CPU */
char *entries[NR_CPUS]; // 表的规则
};