Linux2.6.17内核中匹配和目标相对2.4的变化

zestroly 2011-01-10

本文档的Copyleft归yfydz所有,使用GPL发布,可以自由拷贝,转载,转载时请保持文档的完整性,严禁用于任何商业用途。

msn:yfydz_no1@hotmail.com

来源:http://yfydz.cublog.cn

在2.6.17内核的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_connbyte.c
xt_connmark.c
xt_conntrack.c
xt_dccp.c
xt_esp.c
xt_helper.c
xt_length.c
xt_limit.c
xt_mac.c
xt_mark.c
xt_multiport.c
xt_physdev.c
xt_pkttype.c
xt_policy.c
xt_realm.c
xt_sctp.c
xt_state.c
xt_string.c
xt_tcpmaa.c
xt_tcpudp.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");

以下是新匹配和目标模块的结构定义:

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;
};
在include/linux/netfilter_ipv4/ip_tables.h中进行了以下定义:
#define ipt_match xt_match
#define ipt_target xt_target
#define ipt_table xt_table
 
而和老的2.4内核的struct ipt_match和struct ipt_target结构的主要区别是增加了compat函数,以及struct modulde *me参数后面的一系列参数,是和协议相关的,比如limit匹配,分别为ipv4和ipv6定义了匹配结构后,只有family参数不同,一个是 AF_INET,另一个是AF_INET6,其他都相同,而挂接时并不会有问题,因为这些模块都分别挂接到不同协议族的链表:

/* net/netfilter/x_tables.c */
int
xt_register_match(struct xt_match *match)
{
 int ret, af = match->family;
 ret = mutex_lock_interruptible(&xt[af].mutex);
 if (ret != 0)
  return ret;
 list_add(&match->list, &xt[af].match);
 mutex_unlock(&xt[af].mutex);
 return ret;
}

但在进行实际匹配目标查找时会进行名字、协议族、表名、挂接点、协议等的比较,如匹配的检查:

int xt_check_match(const struct xt_match *match, unsigned short family,
                   unsigned int size, const char *table, unsigned int hook_mask,
     unsigned short proto, int inv_proto)
{
 if (XT_ALIGN(match->matchsize) != size) {
  printk("%s_tables: %s match: invalid size %Zu != %u\n",
         xt_prefix[family], match->name,
         XT_ALIGN(match->matchsize), size);
  return -EINVAL;
 }
 if (match->table && strcmp(match->table, table)) {
  printk("%s_tables: %s match: only valid in %s table, not %s\n",
         xt_prefix[family], match->name, match->table, table);
  return -EINVAL;
 }
 if (match->hooks && (hook_mask & ~match->hooks) != 0) {
  printk("%s_tables: %s match: bad hook_mask %u\n",
         xt_prefix[family], match->name, hook_mask);
  return -EINVAL;
 }
 if (match->proto && (match->proto != proto || inv_proto)) {
  printk("%s_tables: %s match: only valid for protocol %u\n",
         xt_prefix[family], match->name, match->proto);
  return -EINVAL;
 }
 return 0;
}

目前2.6.17内核中支持了三类协议族,IPv4/IPv6/ARP,在各协议族中查找相应模块用的前缀为:
static const char *xt_prefix[NPROTO] = {
 [AF_INET]  = "ip",
 [AF_INET6]  = "ip6",
 [NF_ARP] = "arp",
};
对应的具体前缀分别为“ipt”、“ip6t”、“arpt”。

相关推荐

蜗牛慢爬的李成广 / 0评论 2020-01-28