Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1007164
  • 博文数量: 442
  • 博客积分: 1146
  • 博客等级: 少尉
  • 技术积分: 1604
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-04 12:52
个人简介

123

文章分类

全部博文(442)

文章存档

2017年(3)

2016年(15)

2015年(132)

2014年(52)

2013年(101)

2012年(110)

2011年(29)

分类: LINUX

2015-02-28 11:59:38

第一节我们已经大概的分析了一下在Netfilter 中对规则(rule)的组织结构,这里我们来看一下具体实现。

1、大蓝图

table->chain->rule(match:target)


从上图所示,在内核空间,每个CPU上维护了一份rule的拷贝。这样做是为了减少锁的使用及增加硬件L1 cache的命中次数,以空间换时间

2table(表)

include/linux/netfilter/x_table.h

struct xt_table

{

    struct list_head list;

    unsigned int valid_hooks; /*该表中有效的hook点位图*/

    struct xt_table_info *private; //指向真正存储rule的结构体

    struct module *me;

    u_int8_t af; /* address/protocol family */

    const char name[XT_TABLE_MAXNAMELEN];//表名字

};

 

struct xt_table_info

{

    unsigned int size; //表的大小

    unsigned int number; //表中存的rule个数

    unsigned int initial_entries;//初始化表时创建的默认rule个数
  
//各个hook(chain)在表中的偏移量

    unsigned int hook_entry[NF_INET_NUMHOOKS]; 
    //各个hook(chain)中默认规则在表中的偏移量

    unsigned int underflow[NF_INET_NUMHOOKS];
    //数组,存储各个cpu上自己rule拷贝的内存首地址

    void *entries[1]; 

};

 

表的注册:

每个网络命名空间管理自己Netfilter中创建的table。并把这些表链接到相应的协议族链表里。

这样就可以通过用户空间传下来的表名查找到相应的表了。

struct net

{

struct netns_xt xt;

}

 

struct netns_xt 

{

    struct list_head tables[NFPROTO_NUMPROTO];

    #if defined(CONFIG_BRIDGE_NF_EBTABLES) || \

    defined(CONFIG_BRIDGE_NF_EBTABLES_MODULE)

    struct ebt_table *broute_table;

    struct ebt_table *frame_filter;

    struct ebt_table *frame_nat;

    #endif

};

struct xt_table *xt_register_table(struct net *net,

   const struct xt_table *input_table,

   struct xt_table_info *bootstrap,

   struct xt_table_info *newinfo)

{

    int ret;

    struct xt_table_info *private;

    struct xt_table *t, *table;

 

    /*申请x_table内存*/

    table = kmemdup(input_table, sizeof(struct xt_table), GFP_KERNEL);

    if (!table) {

        ret = -ENOMEM;

        goto out;

    }

 

    ret = mutex_lock_interruptible(&xt[table->af].mutex);

    if (ret != 0)

        goto out_free;

 

    /* 在命名空间里查找是否有相同名字的表 */

    list_for_each_entry(t, &net->xt.tables[table->af], list) {

        if (strcmp(t->name, table->name) == 0) {

            ret = -EEXIST;

            goto unlock;

        }

    }

 

    /* 初始化table_private*/

    table->private = bootstrap;

    if (!xt_replace_table(table, 0, newinfo, &ret))

        goto unlock;

    private = table->private;

    /* save number of initial entries */

    private->initial_entries = private->number;

     //把表挂到对应网络命名空间管理的链表上

    list_add(&table->list, &net->xt.tables[table->af]);

    mutex_unlock(&xt[table->af].mutex);

    return table;

 
unlock:

    mutex_unlock(&xt[table->af].mutex);

    out_free:

    kfree(table);

out:

    return ERR_PTR(ret);

}


3rule在内核中的定义和存储

不同的协议族定义的rule不同。为了通用,netfilter把各个协议族的一些共性的数据结构提取出来单独定义,各个协议族再自己定义自己独有的数据结构,并包含netfilter提供的通用数据结构。

 

我们以IPv4为例来看一下,通过用户空间的iptables所配置到内核中的每条rule是怎么存储的。

如图,ip_entry 是标准的匹配规则,ipt_entry_match是扩展的匹配规则,是可选项。每个rule最后带一个targetTraget有系统自带的,也有扩展的。

 

1、标准的匹配规则

struct ipt_entry

{

    struct ipt_ip ip; //五元组,ipv4报文通用的匹配元素

    /* Mark with fields that we care about. */

    unsigned int nfcache;

/*详见上图,rule首地址到target的偏移量*/

    /* Size of ipt_entry + matches */

    u_int16_t target_offset; 

    /* Size of ipt_entry + matches + target */
    /*下一条rule的偏移量*/

    u_int16_t next_offset;

 

    /* Back pointer */

    unsigned int comefrom;
    /*命中报文的统计计数*/

    /* Packet and byte counters. */

    struct xt_counters counters;

 

    /* The matches (if any), then the target. */

    unsigned char elems[0];

};

 

ipv4报文通用的匹配元素,源/目的ip地址/掩码,源/目的接口名/接口名掩码,传输层协议类型

struct ipt_ip 

{

    /* Source and destination IP addr */

    struct in_addr src, dst;

    /* Mask for src and dest IP addr */

    struct in_addr smsk, dmsk;

    char iniface[IFNAMSIZ], outiface[IFNAMSIZ];

    unsigned char iniface_mask[IFNAMSIZ], outiface_mask[IFNAMSIZ];

    /* Protocol, 0 = ANY */

    u_int16_t proto;

 

    /* Flags word */

    u_int8_t flags;

    /* Inverse flags */
    //位图,每一位代表以上匹配元素配置时是否是带!符号(取反)

    u_int8_t invflags;

};


(未完待续)

阅读(791) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~