Linux 2.6.18.8内核中netfilter分析


1 简单介绍

在2.6.16内核的netfilter中,netfilter一个重大修正思想就是将netfilter作为一个协议无关的框架,表现在内核结构树中单独建立net/netfilter目录,而在以前netfilter是附着在各个协议目录之下的,如在net/ipv4, net/ipv6等目录下。现在虽然各协议目录下也都有,但主要是处理和各协议相关的东西了,而一些共同的东西,就都放在net/netfilter目录下,文件名也有所改变,虽然现在还不是很独立,比如说net/netfilter/nf_conntrack_core.c和net/ipv4/netfilter/ip_conntrack_core.c就仍然很相似,让人觉得没必要那么分,但不少和协议无关的匹配和目标模块已经和协议分离,只在此目录下有,而不放在协议目录下了。

在net/netfilter下的匹配和目标模块文件名称都以“xt_”打头,如 xt_comment.c,xt_policy.c等

目标模块有:

xt_CLASSIFY.c
xt_NFQUEUE.c
xt_NOTRACK.c

为了和iptables兼容(因为iptables找模块文件前缀是按“ipt_”或“ip6t_”找的),这些文件中增加了一个新的宏定义:MODULE_ALIAS,来表示模块的别名。

如在xt_limit.c中就如下定义:
MODULE_ALIAS("ipt_limit");
MODULE_ALIAS("ip6t_limit");

在include/linux/netfilter_ipv4/ip_tables.h中进行了以下定义:
#define ipt_match xt_match
#define ipt_target xt_target
#define ipt_table xt_table

2 代码分析

以下是新匹配和目标模块的结构定义:
struct xt_match
{
   struct list_head list;

   const char name[XT_FUNCTION_MAXNAMELEN-1];

   /* Return true or false: return FALSE and set *hotdrop = 1 to
      force immediate packet drop. */
   /* Arguments changed since 2.6.9, as this must now handle
      non-linear skb, using skb_header_pointer and
      skb_ip_make_writable. */
   int (*match)(const struct sk_buff *skb,
          const struct net_device *in,
          const struct net_device *out,
          const struct xt_match *match,
          const void *matchinfo,
          int offset,
          unsigned int protoff,
          int *hotdrop);

   /* Called when user tries to insert an entry of this type. */
   /* Should return true or false. */
   int (*checkentry)(const char *tablename,
            const void *ip,
            const struct xt_match *match,
            void *matchinfo,
            unsigned int matchinfosize,
            unsigned int hook_mask);

   /* Called when entry of this type deleted. */
   void (*destroy)(const struct xt_match *match, void *matchinfo,
           unsigned int matchinfosize);

   /* Called when userspace align differs from kernel space one */
   int (*compat)(void *match, void **dstptr, int *size, int convert);

   /* Set this to THIS_MODULE if you are a module, otherwise NULL */
   struct module *me;

   char *table;
   unsigned int matchsize;
   unsigned int hooks;
   unsigned short proto;

   unsigned short family;
   u_int8_t revision;
};

/* Registration hooks for targets. */
struct xt_target
{
   struct list_head list;

   const char name[XT_FUNCTION_MAXNAMELEN-1];

   /* Returns verdict. Argument order changed since 2.6.9, as this
      must now handle non-linear skbs, using skb_copy_bits and
      skb_ip_make_writable. */
   unsigned int (*target)(struct sk_buff **pskb,
                const struct net_device *in,
                const struct net_device *out,
                unsigned int hooknum,
                const struct xt_target *target,
                const void *targinfo,
                void *userdata);

   /* Called when user tries to insert an entry of this type:
      hook_mask is a bitmask of hooks from which it can be
      called. */
   /* Should return true or false. */
   int (*checkentry)(const char *tablename,
            const void *entry,
            const struct xt_target *target,
            void *targinfo,
            unsigned int targinfosize,
            unsigned int hook_mask);

   /* Called when entry of this type deleted. */
   void (*destroy)(const struct xt_target *target, void *targinfo,
           unsigned int targinfosize);

   /* Called when userspace align differs from kernel space one */
   int (*compat)(void *target, void **dstptr, int *size, int convert);

   /* Set this to THIS_MODULE if you are a module, otherwise NULL */
   struct module *me;

   char *table;
   unsigned int targetsize;
   unsigned int hooks;
   unsigned short proto;

   unsigned short family;
   u_int8_t revision;
};

/* Furniture shopping... */
struct xt_table
{
   struct list_head list;

   /* A unique name... */
   char name[XT_TABLE_MAXNAMELEN];

   /* What hooks you will enter on */
   unsigned int valid_hooks;

   /* Lock for the curtain */
   rwlock_t lock;

   /* Man behind the curtain... */
   //struct ip6t_table_info *private;
   void *private;

   /* Set this to THIS_MODULE if you are a module, otherwise NULL */
   struct module *me;

   int af;        /* address/protocol family */
};

/* 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];
   unsigned int underflow[NF_IP_NUMHOOKS];

   /* ipt_entry tables: one per CPU */
   char *entries[NR_CPUS];
};

/* 主要结构 */
struct xt_af {
   struct mutex mutex;
   struct list_head match;
   struct list_head target;
   struct list_head tables;
   struct mutex compat_mutex;
};

/*数据结构的管理模块 */
static struct xt_af *xt;

/* netfilter模块初始化*/
static int __init xt_init(void)
{
   int i;

/* 每种协议分配一个资源 */
   xt = kmalloc(sizeof(struct xt_af) * NPROTO, GFP_KERNEL);
   if (!xt)
       return -ENOMEM;

   for (i = 0; i < NPROTO; i++) {
       mutex_init(&xt.mutex);
#ifdef CONFIG_COMPAT
       mutex_init(&xt.compat_mutex);
#endif

       /* 初始化table, target, match资源 */
       INIT_LIST_HEAD(&xt.target);
       INIT_LIST_HEAD(&xt.match);
       INIT_LIST_HEAD(&xt.tables);
   }
   return 0;
}
  • 1
  • 2
  • 3
  • 下一页

相关内容