文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>iptable netfilter

iptable netfilter

时间:2010-08-10  来源:pop_zhang

net/ipv4/netfilter/iptable_filter.c

static int __init iptable_filter_init(void)  -->
nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));

struct nf_hook_ops
{
        struct list_head list;

        /* User fills in from here down. */
        nf_hookfn *hook;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
        struct module *owner;
#endif
        int pf;
        int hooknum;
        /* Hooks are ordered in ascending priority. */
        int priority;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
        struct module *owner;
#endif
};

typedef unsigned int nf_hookfn(unsigned int hooknum,
                               struct sk_buff **skb,
                               const struct net_device *in,
                               const struct net_device *out,
                               int (*okfn)(struct sk_buff *));


static struct nf_hook_ops ipt_ops[] = {
        {  
                .hook           = ipt_hook,
                .owner          = THIS_MODULE,
                .pf             = PF_INET,
                .hooknum        = NF_IP_LOCAL_IN,
                .priority       = NF_IP_PRI_FILTER,
        }, 
        {  
                .hook           = ipt_hook,
                .owner          = THIS_MODULE,
                .pf             = PF_INET,
                .hooknum        = NF_IP_FORWARD,
                .priority       = NF_IP_PRI_FILTER,
        }, 
        {  
                .hook           = ipt_local_out_hook,
                .owner          = THIS_MODULE,
                .pf             = PF_INET,
                .hooknum        = NF_IP_LOCAL_OUT,
                .priority       = NF_IP_PRI_FILTER,
        }, 
};



hook number

/* After promisc drops, checksum checks. */
#define NF_IP_PRE_ROUTING       0
/* If the packet is destined for this box. */
#define NF_IP_LOCAL_IN          1
/* If the packet is destined for another interface. */
#define NF_IP_FORWARD           2
/* Packets coming from a local process. */
#define NF_IP_LOCAL_OUT         3
/* Packets about to hit the wire. */
#define NF_IP_POST_ROUTING      4
#define NF_IP_NUMHOOKS          5


hook priority

enum nf_ip_hook_priorities {
        NF_IP_PRI_FIRST = INT_MIN,
        NF_IP_PRI_CONNTRACK_DEFRAG = -400,
        NF_IP_PRI_RAW = -300,
        NF_IP_PRI_SELINUX_FIRST = -225,
        NF_IP_PRI_CONNTRACK = -200,
        NF_IP_PRI_MANGLE = -150,
        NF_IP_PRI_NAT_DST = -100,
        NF_IP_PRI_FILTER = 0,
        NF_IP_PRI_NAT_SRC = 100,
        NF_IP_PRI_SELINUX_LAST = 225,
        NF_IP_PRI_CONNTRACK_HELPER = INT_MAX - 2,
        NF_IP_PRI_NAT_SEQ_ADJUST = INT_MAX - 1,
        NF_IP_PRI_CONNTRACK_CONFIRM = INT_MAX,
        NF_IP_PRI_LAST = INT_MAX,
};


net/netfilter/core.c
int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n)
{
        unsigned int i;
        int err = 0;

        for (i = 0; i < n; i++) {
                err = nf_register_hook(&reg[i]);
                if (err)
                        goto err;
        }  
        return err;

err:
        if (i > 0)
                nf_unregister_hooks(reg, i);
        return err;
}

kernel/linux/include/linux/net.h
#define NPROTO          33              /* should be enough for now..   */

kernel/linux/include/linux/netfilter.h
/* Largest hook number + 1 */
#define NF_MAX_HOOKS 8


net/netfilter/core.c

struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS] __read_mostly;
EXPORT_SYMBOL(nf_hooks);
// This variable using for lock the list operation, need more study
static DEFINE_MUTEX(nf_hook_mutex);
int nf_register_hook(struct nf_hook_ops *reg)
{
        struct list_head *i;
        int err;

        err = mutex_lock_interruptible(&nf_hook_mutex);
        if (err < 0)
                return err;
        list_for_each(i, &nf_hooks[reg->pf][reg->hooknum]) {
                if (reg->priority < ((struct nf_hook_ops *)i)->priority)
                        break;
        }  
        list_add_rcu(&reg->list, i->prev);
        mutex_unlock(&nf_hook_mutex);
        return 0;
}



/**
 * list_for_each        -       iterate over a list
 * @pos:        the &struct list_head to use as a loop cursor.
 * @head:       the head for your list.
 */
#define list_for_each(pos, head) \
        for (pos = (head)->next; prefetch(pos->next), pos != (head); \
                pos = pos->next)



kernel/linux/include/linux/list.h

/**
 * list_add_rcu - add a new entry to rcu-protected list
 * @new: new entry to be added
 * @head: list head to add it after
 *
 * Insert a new entry after the specified head.
 * This is good for implementing stacks.
 *
 * The caller must take whatever precautions are necessary
 * (such as holding appropriate locks) to avoid racing
 * with another list-mutation primitive, such as list_add_rcu()
 * or list_del_rcu(), running on this same list.
 * However, it is perfectly legal to run concurrently with
 * the _rcu list-traversal primitives, such as
 * list_for_each_entry_rcu().
 */
static inline void list_add_rcu(struct list_head *new, struct list_head *head)
{
        __list_add_rcu(new, head, head->next);
}



/*
 * Insert a new entry between two known consecutive entries.
 *
 * This is only for internal list manipulation where we know
 * the prev/next entries already!
 */
static inline void __list_add_rcu(struct list_head * new,
                struct list_head * prev, struct list_head * next)
{
        new->next = next;
        new->prev = prev;
        smp_wmb();
        next->prev = new;
        prev->next = new;
}




nf_hooks contents

 list
 ipt_hook
 nf_hooksTHIS_MODULE
 PF_INET
 NF_IP_LOCAL_IN
 NF_IP_PRI_FILTER

 list
 ipt_hook
 THIS_MODULE
 PF_INET
 NF_IP_FORWARD
 NF_IP_PRI_FILTER

 
 list
 ipt_local_out_hook
 THIS_MODULE
 PF_INET
 NF_IP_LOCAL_OUT
 NF_IP_PRI_FILTER
       
Hooks invoked when receiving packet from interface

net/ipv4/ip_input.c
Receive ip packets


/*
 * Main IP Receive routine.
 */
int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
{
        struct iphdr *iph;
        u32 len;
#if defined(CONFIG_MIPS_BRCM)
        __u8 iph_ihl, iph_version;
#endif


        /* When the interface is in promisc. mode, drop all the crap
         * that it receives, do not try to analyse it.
         */
        if (skb->pkt_type == PACKET_OTHERHOST)
                goto drop;

        IP_INC_STATS_BH(IPSTATS_MIB_INRECEIVES);

        if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
                IP_INC_STATS_BH(IPSTATS_MIB_INDISCARDS);
                goto out;
        }

        if (!pskb_may_pull(skb, sizeof(struct iphdr)))
                goto inhdr_error;

        iph = skb->nh.iph;

        /*
         * RFC1122: 3.1.2.2 MUST silently discard any IP frame that fails the checksum.
         *
         * Is the datagram acceptable?
         *
         * 1. Length at least the size of an ip header
         * 2. Version of 4
         * 3. Checksums correctly. [Speed optimisation for later, skip loopback checksums]
         * 4. Doesn't have a bogus length
         */

#if defined(CONFIG_MIPS_BRCM)
        iph_ihl = *(__u8 *)iph & 0xf;
        iph_version = *(__u8 *)iph >> 4;

        if (iph_ihl < 5 || iph_version != 4)
#else
        if (iph->ihl < 5 || iph->version != 4)
#endif
                goto inhdr_error;

#if defined(CONFIG_MIPS_BRCM)
        if (!pskb_may_pull(skb, iph_ihl*4))
#else
        if (!pskb_may_pull(skb, iph->ihl*4))
#endif
                goto inhdr_error;

        iph = skb->nh.iph;

#if defined(CONFIG_MIPS_BRCM)
        if (unlikely(ip_fast_csum((u8 *)iph, iph_ihl)))
#else
        if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl)))
#endif

                goto inhdr_error;

        len = ntohs(iph->tot_len);
        if (skb->len < len || len < (iph->ihl*4))
                goto inhdr_error;

        /* Our transport medium may have padded the buffer out. Now we know it
         * is IP we can trim to the true length of the frame.
         * Note this now means skb->len holds ntohs(iph->tot_len).
         */
        if (pskb_trim_rcsum(skb, len)) {
                IP_INC_STATS_BH(IPSTATS_MIB_INDISCARDS);
                goto drop;
        }

        /* Remove any debris in the socket control block */
        memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));

        return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
                       ip_rcv_finish);

This macro NF_HOOK call iptable nf_hook



inhdr_error:
        IP_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
drop:



        kfree_skb(skb);
out:
        return NET_RX_DROP;
}




kernel/linux/include/linux/netfilter.h

        

#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \
        NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, INT_MIN)


#define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh) \
({int __ret; \
if ((__ret=nf_hook_thresh(pf, hook, &(skb), indev, outdev, okfn, thresh, 1)) == 1)\
        __ret = (okfn)(skb); \
__ret;}



/**
 *      nf_hook_thresh - call a netfilter hook
 *     
 *      Returns 1 if the hook has allowed the packet to pass.  The function
 *      okfn must be invoked by the caller in this case.  Any other return
 *      value indicates the packet has been consumed by the hook.
 */
static inline int nf_hook_thresh(int pf, unsigned int hook,
                                 struct sk_buff **pskb,
                                 struct net_device *indev,
                                 struct net_device *outdev,
                                 int (*okfn)(struct sk_buff *), int thresh,
                                 int cond)
{
        if (!cond)
                return 1;
#ifndef CONFIG_NETFILTER_DEBUG
        if (list_empty(&nf_hooks[pf][hook]))
                return 1;
#endif
        return nf_hook_slow(pf, hook, pskb, indev, outdev, okfn, thresh);
}

int nf_hook_slow(int pf, unsigned int hook, struct sk_buff **pskb,
                 struct net_device *indev, struct net_device *outdev,
                 int (*okfn)(struct sk_buff *), int thresh);




kernel/linux/net/netfilter/core.c

/* Returns 1 if okfn() needs to be executed by the caller,
 * -EPERM for NF_DROP, 0 otherwise. */
int nf_hook_slow(int pf, unsigned int hook, struct sk_buff **pskb,
                 struct net_device *indev,
                 struct net_device *outdev,
                 int (*okfn)(struct sk_buff *),
                 int hook_thresh)
{
        struct list_head *elem;
        unsigned int verdict;
        int ret = 0;

        /* We may already have this, but read-locks nest anyway */
        rcu_read_lock();

        elem = &nf_hooks[pf][hook];
next_hook:
        verdict = nf_iterate(&nf_hooks[pf][hook], pskb, hook, indev,
                             outdev, &elem, okfn, hook_thresh);
        if (verdict == NF_ACCEPT || verdict == NF_STOP) {
                ret = 1;
                goto unlock;
        } else if (verdict == NF_DROP) {
                kfree_skb(*pskb);
                ret = -EPERM;
        } else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) {
                NFDEBUG("nf_hook: Verdict = QUEUE.\n");
                if (!nf_queue(*pskb, elem, pf, hook, indev, outdev, okfn,
                              verdict >> NF_VERDICT_BITS))
                        goto next_hook;
        }
unlock:
        rcu_read_unlock();
        return ret;
}






unsigned int nf_iterate(struct list_head *head,
                        struct sk_buff **skb,
                        int hook,
                        const struct net_device *indev,
                        const struct net_device *outdev,
                        struct list_head **i,
                        int (*okfn)(struct sk_buff *),
                        int hook_thresh)
{
        unsigned int verdict;

        /*
         * The caller must not block between calls to this
         * function because of risk of continuing from deleted element.
         */
        list_for_each_continue_rcu(*i, head) {
                struct nf_hook_ops *elem = (struct nf_hook_ops *)*i;

                if (hook_thresh > elem->priority)
                        continue;

                /* Optimization: we don't need to hold module
                   reference here, since function can't sleep. --RR */
                verdict = elem->hook(hook, skb, indev, outdev,);  // registered hook function is invoked
                if (verdict != NF_ACCEPT) {
#ifdef CONFIG_NETFILTER_DEBUG
                        if (unlikely((verdict & NF_VERDICT_MASK)
                                                        > NF_MAX_VERDICT)) {
                                NFDEBUG("Evil return from %p(%u).\n",
                                        elem->hook, hook);
                                continue;
                        }
#endif
                        if (verdict != NF_REPEAT)
                                return verdict;
                        *i = (*i)->prev;
                }
        }
        return NF_ACCEPT;
}


相关阅读 更多 +
排行榜 更多 +
幸运硬币官方正版下载

幸运硬币官方正版下载

休闲益智 下载
宝宝来找茬手机版 v9.86.00.00 安卓版

宝宝来找茬手机版 v9.86.00.00 安卓版

休闲益智 下载
翻滚飞机大战最新版 v1.0.4 安卓版

翻滚飞机大战最新版 v1.0.4 安卓版

飞行射击 下载