Chinaunix首页 | 论坛 | 博客
  • 博客访问: 391685
  • 博文数量: 87
  • 博客积分: 2571
  • 博客等级: 少校
  • 技术积分: 920
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-29 13:10
文章分类

全部博文(87)

文章存档

2012年(49)

2011年(7)

2010年(26)

2009年(5)

分类: LINUX

2010-04-29 13:50:54

 
Netfilter使用一张全局hash表来定义报文的连接状态,它定义在ip_conntrack_core.c中,用指针struct list_head *ip_conntrack_hash来描述该表。这个hash表的大小是有限制的,在模块装载的时候确定,可以由用户指定,由ip_conntrack_htable_size记录,其默认值是根据当前内存的大小计算出来,采用了tcp协议栈中确定hash表大小的算法。每个hash节点均是一个链表的首部,该链表存放了该hash值的所有冲突项。连接跟踪表就由ip_conntrack_htable_size 条链表构成,整个连接跟踪表大小使用全局变量ip_conntrack_max描述,与hash表的关系是ip_conntrack_max = 8 * ip_conntrack_htable_size。
每个hash链表的节点都是一个ip_conntrack_tuple_hash结构:
struct ip_conntrack_tuple_hash
{
     struct list_head list;
     struct ip_conntrack_tuple tuple;
};
其中list用于链接冲突链表,tuple则用于存放标识连接的最基本信息,如果两个数据包的tuple完全相同,则它们属于同一个连接。因为每一个连接上的数据流都是双向的,所以需要两个tuple来分别标识不同方向上的流量。从Socket套接字角度来讲,连接两端用“地址+端口”的形式来唯一标识一个连接(对于没有端口的协议,如ICMP,可以使用其它办法替代),因此tuple保存了“来源地址/来源端口+目的地址/目的端口”来标识一个连接。
Netfilter用结构struct ip_conntrack_tuple 结构来封装这个“来源”和“目的”:
 

struct ip_conntrack_tuple
{
     struct ip_conntrack_manip src;
     /* These are the parts of the tuple which are fixed. */
     struct {
         u_int32_t ip;
         union {
              /* Add other protocols here. */
              u_int16_t all;
              struct {
                   u_int16_t port;
              } tcp;
              struct {
                   u_int16_t port;
              } udp;
              struct {
                   u_int8_t type, code;
              } icmp;
              struct {
                   u_int16_t port;
              } sctp;
              struct {
                   __be16 key; /* key is 32bit, 
                            * pptp only uses 16 */

              } gre;
         } u;
         /* The protocol. */
         u_int8_t protonum;
         /* The direction (for tuplehash) */
         u_int8_t dir;/*描述数据流方向*/
     } dst;
};


    tuple 结构仅仅用来标识一个连接,并不是描述一条完整的连接状态,netfilter将数据包转换成tuple结构,并根据其计算hash,在相应的链表上查询,获取相应的连接状态,如果没有查到,则表示是一个新的连接。
内核中,描述一个包的连接状态,使用了struct ip_conntrack 结构,可以在ip_conntrack.h中看到它的定义:
 

struct ip_conntrack
{
/* Usage count in here is 1 for hash table/destruct timer, 1 per skb,
           plus 1 for any connection(s) we are `master' for */

    struct nf_conntrack ct_general; 结构的引用计数
/* Have we seen traffic both ways yet? (bitset) */
    unsigned long status; 结构的状态,
/* Timer function; drops refcnt when it goes off. */
    struct timer_list timeout; 结构的老化定时器,避免过分暂用内存
#ifdef CONFIG_IP_NF_CT_ACCT
/* Accounting Information (same cache line as other written members) */
    struct ip_conntrack_counter counters[IP_CT_DIR_MAX]; 计数器,分别统计两个方向上的流量
#endif
/* If we were expected by an expectation, this will be it */
    struct ip_conntrack *master; 指向创建本结构的expect,关于expect后续会介绍
/* Current number of expected connections */
    unsigned int expecting; 与本结构关联的expect的数量
/* Unique ID that identifies this conntrack*/
    unsigned int id;
/* Helper, if any. */
    struct ip_conntrack_helper *helper; 与本结构相关的helper,与expect相关
/* Storage reserved for other modules: */
    union ip_conntrack_proto proto;
    union ip_conntrack_help help;
#ifdef CONFIG_IP_NF_NAT_NEEDED
    struct {
        struct ip_nat_info info;
        union ip_conntrack_nat_help help;
#if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \
defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE)
        int masq_index;
#endif
    } nat; nat相关数据结构
#endif /* CONFIG_IP_NF_NAT_NEEDED */

#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
    u_int32_t mark;
#endif

#ifdef CONFIG_IP_NF_CONNTRACK_SECMARK
    u_int32_t secmark;
#endif

/* Traversed often, so hopefully in different cacheline to top */
/* These are my tuples; original and reply */
    struct ip_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX]; 不同方向的tuple
}

union ip_conntrack_proto proto:对不同的协议,连接所需记录的参数不同,proto记录了和协议相关的私有内容。
union ip_conntrack_help help:记录了协议相关的内容,如ftp协议,h.323协议等

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