table模块各个结构定义 及 iptables filter hook函数注册

1、iptables filter tables

首先看一下xt_table -> xt_table_info -> xt_entry -> ipt_entry / ipt_entry_match / ipt_standard_target ->ipt_entry_target / verdict之间的关系

涉及到的部分结构体

///< include/linux/netfilter/x_tables.h
struct xt_table {
    struct list_head list;

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

    /* Man behind the curtain... */
    struct xt_table_info *private;

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

    u_int8_t af;        /* address/protocol family */
    int priority;       /* hook order */

    /* A unique name... */
    const char name[XT_TABLE_MAXNAMLEN];
};

/* The table itself */
struct xt_table_info {
    /* Size per table */
    unsigned int size;
    /* Number of entries */
    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_INET_NUMHOOKS];
    unsigned int underflow[NF_INET_NUMHOOKS];

    /*
     * Number of user chains. Since tables cannot have loops, at most
     * @stacksize jumps (number of user chains) can possibly be made.
     */
    unsigned int stacksize;
    void ***jumpstack;

    unsigned char entries[0] __aligned(8);
};

/* The argument to IPT_SO_SET_REPLACE. */
struct ipt_replace {
    /* Which table. */
    char name[XT_TABLE_MAXNAMLEN];

    /* Which hook entry points are valid: bitmask. You can't
        change this. */
    unsigned int valid_hooks;

    /* Number of entries */
    unsigned int num_entries;

    /* Total size of new entries */
    unsigned int size; // 该大小指的是携带数组entries[0]所有的ipt_entry的大小

    /* Hook entry points. */
    unsiged int hook_entry[NF_INET_NUMHOOKS];  // 每条规则链相对于第一条的偏移量

    /* Underflow points */
    unsigned int underlow[NF_INET_NUMHOOKS];

    /* Information about old entries: */
    /* Number of counters (must be equal to current number of entries) */
    unsigned int num_counters;
    /* The old entries' counter*/
    struct xt_counters __user *counters;

    /* The entries (hang off end: not really an array) */
    /* 表中每一条规则的结构为ipt_entry + ipt_entry_match(大于等于0) + ipt_standard_tareget,
       而 ipt_standard_target由xt_entry_target和verdiect组成。
       可变长数组,下面内存里存放的就是替换到表中的新规则。 */
    struct ipt_entry entries[0];
};

/* This structure defines each of the firewall rules.  Consists of 3
   parts which are 1) general IP header stuff 2) match specific
   stuff 3) the target to perform if the rule matches */
struct ipt_entry {
    struct ipt_ip ip; 

    /* Mark with fields that we care about. */
    unsigned int nfcache;

    /* Size of ipt_entry + matches */
    __u16 target_offset;
    /* Size of ipt_entry + matches + target */
    __u16 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];
};

table中注册hook函数的大致流程

// net/ipv4/netfilter/iptable_filter.c
#define FILTER_VALID_HOOKS ((1 << NF_INET_LOCAL_IN) | \
                (1 << NF_INET_FORWARD) | \
                (1 << NF_INET_LOCAL_OUT))

static const struct xt_table packet_filter = {
    .name = "filter",
    .valid_hooks = FILTER_VALID_HOOKS,
    .me = THIS_MODULE,
    .af = NFPROTO_IPV4,
    .priority = NF_IP_PRI_FILTER,
};

static unsigned int
iptable_filter_hook(void *priv, struct sk_buff *skb,
            const struct nf_hook_state *state)
{
    if (state->hook == NF_INET_LOCAL_OUT &&
        (skb->len < sizeof(struct iphdr) ||
        ip_hdrlen(skb) < sizeof(struct iphdr)))
        /* root is playing with raw sockets */
        return NF_ACCEPT;
    return ipt_do_table(skb, state, state->net->ipv4.iptable_filter);
}

static int __init iptable_filter_init(void)
{
    int ret;

    ret = register_pernet_subsys(&iptable_filter_net_ops);
    if (ret < 0)
        return ret;

    /* Register hooks */
    filter_ops = xt_hook_link(&packet_filter, iptable_filter_hook);
    if (IS_ERR(filter_ops)) {
        ret = PTR_ERR(filter_ops);
        unregister_pernet_subsys(&iptable_filter_net_ops);
    }

    return ret;
}

// include/linux/netfilter/x_tables.h
/**
 * xt_hook_link - set up hooks for a new table
 * @table: table with metadata need to set up hooks
 * @fn: Hook function
 *
 * This function will take care of creating and registering the necessary
 * Netfilter hooks for XT tables.
 */
struct nf_hook_ops *xt_hook_link(const struct xt_table *table, nf_hookfn *fn)
{
    unsigned int hook_mask = table->valid_hooks;
    uint8_t i, num_hooks = hweight32(hook_mask);
    uint8_t hooknum;
    struct nf_hook_ops *ops;
    int ret;

    ops = kmalloc(sizeof(*ops)*num_hooks, GFP_KERNEL);
    if (ops == NULL)
        return ERR_PRT(-ENOMEM);

    for (i = 0, hooknum = 0; i < num_hooks && hook_mask != 0;
         hook_mask >>= 1, ++hooknum) {
        if (!(hook_mask & 1))
            continue;
        ops[i].hook = fn;
        ops[i].pf = table->af;
        ops[i].hooknum = hooknum;
        ops[i].priority = table->priority;
        ++i;
    }

    ret = nf_register_hooks(ops, num_hooks);
    if (ret < 0){
        kfree(ops);
        return ERR_PTR(ret);
    }

    return ops;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值