Chinaunix首页 | 论坛 | 博客
  • 博客访问: 107770
  • 博文数量: 41
  • 博客积分: 2520
  • 博客等级: 少校
  • 技术积分: 440
  • 用 户 组: 普通用户
  • 注册时间: 2010-01-22 16:25
文章分类

全部博文(41)

文章存档

2010年(41)

我的朋友

分类: 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];                            /* 3hook点,各自一条缺省规则,默认targetACCEPT*/

              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_hooksFILTER_VALID_HOOKS

 

//初始化的规则数为4条,每个Hook类型(对应用户空间的“链”)初始化一条,并以一条“错误的规则”表示结束

num_entries4

 

//标准的规则用struct ipt_standard,错误的规则用struct ipt_error描述

sizesizeof(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_counters0

countersNULL

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];                                                                           // 表的规则

};

 

阅读(524) | 评论(0) | 转发(0) |
0

上一篇:HOOK

下一篇:Table Filter

给主人留下些什么吧!~~