文章详情

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

iptable conntrack

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

struct ip_conntrack_helper;

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;

        /* Current number of expected connections */
        unsigned int expecting;

        /* Unique ID that identifies this conntrack*/
        unsigned int id;

        /* Helper, if any. */
        struct ip_conntrack_helper *helper;
        /* 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;
#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];
};




/* Fast function for those who don't want to parse /proc (and I don't
   blame them). */
/* Reversing the socket's dst/src point of view gives us the reply
   mapping. */
static int
getorigdst(struct sock *sk, int optval, void __user *user, int *len)
{
        struct inet_sock *inet = inet_sk(sk);
        struct ip_conntrack_tuple_hash *h;
        struct ip_conntrack_tuple tuple;

        IP_CT_TUPLE_U_BLANK(&tuple);
        tuple.src.ip = inet->rcv_saddr;
        tuple.src.u.tcp.port = inet->sport;
        tuple.dst.ip = inet->daddr;
        tuple.dst.u.tcp.port = inet->dport;
        tuple.dst.protonum = IPPROTO_TCP;

        /* We only do TCP at the moment: is there a better way? */
        if (strcmp(sk->sk_prot->name, "TCP")) {
                DEBUGP("SO_ORIGINAL_DST: Not a TCP socket\n");
                return -ENOPROTOOPT;
        }

        if ((unsigned int) *len < sizeof(struct sockaddr_in)) {
                DEBUGP("SO_ORIGINAL_DST: len %u not %u\n",
                       *len, sizeof(struct sockaddr_in));
                return -EINVAL;
        }

        h = ip_conntrack_find_get(&tuple, NULL);
        if (h) {
                struct sockaddr_in sin;
                struct ip_conntrack *ct = tuplehash_to_ctrack(h);
                sin.sin_family = AF_INET;
                sin.sin_port = ct->tuplehash[IP_CT_DIR_ORIGINAL]
                        .tuple.dst.u.tcp.port;
                sin.sin_addr.s_addr = ct->tuplehash[IP_CT_DIR_ORIGINAL]
                        .tuple.dst.ip;
                memset(sin.sin_zero, 0, sizeof(sin.sin_zero));

                DEBUGP("SO_ORIGINAL_DST: %u.%u.%u.%u %u\n",
                       NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
                ip_conntrack_put(ct);
                if (copy_to_user(user, &sin, sizeof(sin)) != 0)
                        return -EFAULT;
                else
                        return 0;
        }
        DEBUGP("SO_ORIGINAL_DST: Can't find %u.%u.%u.%u/%u-%u.%u.%u.%u/%u.\n",
               NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
               NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
        return -ENOENT;
}


net/ipv4/netfilter/ip_conntrack_core.c

int __init ip_conntrack_init(void)
{
        unsigned int i;
        int ret;

        /* Idea from tcp.c: use 1/16384 of memory. On i386: 32MB
         * machine has 256 buckets. >= 1GB machines have 8192 buckets. */
        if (!ip_conntrack_htable_size) {
                ip_conntrack_htable_size
                        = (((num_physpages << PAGE_SHIFT) / 16384)
                           / sizeof(struct list_head));
                if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
                        ip_conntrack_htable_size = 8192;
                if (ip_conntrack_htable_size < 16)
                        ip_conntrack_htable_size = 16;
        }
        ip_conntrack_max = 8 * ip_conntrack_htable_size;

        printk("ip_conntrack version %s (%u buckets, %d max)"
               " - %Zd bytes per conntrack\n", IP_CONNTRACK_VERSION,
               ip_conntrack_htable_size, ip_conntrack_max,
               sizeof(struct ip_conntrack));

        ret = nf_register_sockopt(&so_getorigdst);
        if (ret != 0) {
                printk(KERN_ERR "Unable to register netfilter socket option\n");
                return ret;
        }

        ip_conntrack_hash = alloc_hashtable(ip_conntrack_htable_size,
                                            &ip_conntrack_vmalloc);
        if (!ip_conntrack_hash) {
                printk(KERN_ERR "Unable to create ip_conntrack_hash\n");
                goto err_unreg_sockopt;
        }
        ip_conntrack_cachep = kmem_cache_create("ip_conntrack",
                                                sizeof(struct ip_conntrack), 0,
                                                0, NULL, NULL);
        if (!ip_conntrack_cachep) {
                printk(KERN_ERR "Unable to create ip_conntrack slab cache\n");
                goto err_free_hash;
        }

        ip_conntrack_expect_cachep = kmem_cache_create("ip_conntrack_expect",
                                        sizeof(struct ip_conntrack_expect),
                                        0, 0, NULL, NULL);
        if (!ip_conntrack_expect_cachep) {
                printk(KERN_ERR "Unable to create ip_expect slab cache\n");
                goto err_free_conntrack_slab;
        }

        /* Don't NEED lock here, but good form anyway. */
        write_lock_bh(&ip_conntrack_lock);
        for (i = 0; i < MAX_IP_CT_PROTO; i++)
                rcu_assign_pointer(ip_ct_protos[i], &ip_conntrack_generic_protocol);
        /* Sew in builtin protocols. */
        rcu_assign_pointer(ip_ct_protos[IPPROTO_TCP], &ip_conntrack_protocol_tcp);
        rcu_assign_pointer(ip_ct_protos[IPPROTO_UDP], &ip_conntrack_protocol_udp);
        rcu_assign_pointer(ip_ct_protos[IPPROTO_ICMP], &ip_conntrack_protocol_icmp);
        write_unlock_bh(&ip_conntrack_lock);

        /* For use by ipt_REJECT */
        rcu_assign_pointer(ip_ct_attach, ip_conntrack_attach);

        /* Set up fake conntrack:
            - to never be deleted, not in any hashes */
        atomic_set(&ip_conntrack_untracked.ct_general.use, 1);
        /* - and look it like as a confirmed connection */
        set_bit(IPS_CONFIRMED_BIT, &ip_conntrack_untracked.status);

        return ret;

err_free_conntrack_slab:
        kmem_cache_destroy(ip_conntrack_cachep);
err_free_hash:
        free_conntrack_hash(ip_conntrack_hash, ip_conntrack_vmalloc,
                            ip_conntrack_htable_size);
err_unreg_sockopt:
        nf_unregister_sockopt(&so_getorigdst);

        return -ENOMEM;
}


net/netfilter/nf_sockopt.c

/* Functions to register sockopt ranges (exclusive). */
int nf_register_sockopt(struct nf_sockopt_ops *reg)
{
        struct list_head *i;
        int ret = 0;

        if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0)
                return -EINTR;

        list_for_each(i, &nf_sockopts) {
                struct nf_sockopt_ops *ops = (struct nf_sockopt_ops *)i;
                if (ops->pf == reg->pf
                    && (overlap(ops->set_optmin, ops->set_optmax,
                                reg->set_optmin, reg->set_optmax)
                        || overlap(ops->get_optmin, ops->get_optmax,
                                   reg->get_optmin, reg->get_optmax))) {
                        NFDEBUG("nf_sock overlap: %u-%u/%u-%u v %u-%u/%u-%u\n",
                                ops->set_optmin, ops->set_optmax,
                                ops->get_optmin, ops->get_optmax,
                                reg->set_optmin, reg->set_optmax,
                                reg->get_optmin, reg->get_optmax);
                        ret = -EBUSY;
                        goto out;
                }
        }
        
        list_add(&reg->list, &nf_sockopts);
out:
        mutex_unlock(&nf_sockopt_mutex);
        return ret;
}
EXPORT_SYMBOL(nf_register_sockopt);



include/linux/netfilter.h

struct nf_sockopt_ops
{
        struct list_head list;
        
        int pf;
        
        /* Non-inclusive ranges: use 0/0/NULL to never get called. */
        int set_optmin;
        int set_optmax;
        int (*set)(struct sock *sk, int optval, void __user *user, unsigned int len);
        int (*compat_set)(struct sock *sk, int optval,
                        void __user *user, unsigned int len);

        int get_optmin;
        int get_optmax;
        int (*get)(struct sock *sk, int optval, void __user *user, int *len);
        int (*compat_get)(struct sock *sk, int optval,
                        void __user *user, int *len);

        /* Number of users inside set() or get(). */
        unsigned int use;
        struct task_struct *cleanup_task;
};


net/ipv4/netfilter/ip_conntrack_core.c

static struct nf_sockopt_ops so_getorigdst = {
        .pf = PF_INET,
        .get_optmin = SO_ORIGINAL_DST,
        .get_optmax = SO_ORIGINAL_DST+1,
        .get = &getorigdst,
};




相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载