Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[linux-drm-fsl-dcu.git] / net / ipv4 / netfilter / ipt_CLUSTERIP.c
index 41589665fc5ddabc128690199ac266bc98494537..4fe28f2644759962e2dbcbd7a18c121e2a19deaf 100644 (file)
@@ -1,4 +1,4 @@
-/* Cluster IP hashmark target 
+/* Cluster IP hashmark target
  * (C) 2003-2004 by Harald Welte <laforge@netfilter.org>
  * based on ideas of Fabio Olive Leite <olive@unixforge.org>
  *
@@ -26,6 +26,7 @@
 
 #include <linux/netfilter_arp.h>
 
+#include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netfilter_ipv4/ipt_CLUSTERIP.h>
 #include <net/netfilter/nf_conntrack_compat.h>
@@ -40,8 +41,6 @@
 #define DEBUGP
 #endif
 
-#define ASSERT_READ_LOCK(x)
-
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
 MODULE_DESCRIPTION("iptables target for CLUSTERIP");
@@ -52,7 +51,7 @@ struct clusterip_config {
        atomic_t entries;                       /* number of entries/rules
                                                 * referencing us */
 
-       u_int32_t clusterip;                    /* the IP address */
+       __be32 clusterip;                       /* the IP address */
        u_int8_t clustermac[ETH_ALEN];          /* the MAC address */
        struct net_device *dev;                 /* device */
        u_int16_t num_total_nodes;              /* total number of nodes */
@@ -119,13 +118,12 @@ clusterip_config_entry_put(struct clusterip_config *c)
 }
 
 static struct clusterip_config *
-__clusterip_config_find(u_int32_t clusterip)
+__clusterip_config_find(__be32 clusterip)
 {
        struct list_head *pos;
 
-       ASSERT_READ_LOCK(&clusterip_lock);
        list_for_each(pos, &clusterip_configs) {
-               struct clusterip_config *c = list_entry(pos, 
+               struct clusterip_config *c = list_entry(pos,
                                        struct clusterip_config, list);
                if (c->clusterip == clusterip) {
                        return c;
@@ -136,7 +134,7 @@ __clusterip_config_find(u_int32_t clusterip)
 }
 
 static inline struct clusterip_config *
-clusterip_config_find_get(u_int32_t clusterip, int entry)
+clusterip_config_find_get(__be32 clusterip, int entry)
 {
        struct clusterip_config *c;
 
@@ -166,11 +164,10 @@ clusterip_config_init_nodelist(struct clusterip_config *c,
 }
 
 static struct clusterip_config *
-clusterip_config_init(struct ipt_clusterip_tgt_info *i, u_int32_t ip,
+clusterip_config_init(struct ipt_clusterip_tgt_info *i, __be32 ip,
                        struct net_device *dev)
 {
        struct clusterip_config *c;
-       char buffer[16];
 
        c = kzalloc(sizeof(*c), GFP_ATOMIC);
        if (!c)
@@ -187,12 +184,17 @@ clusterip_config_init(struct ipt_clusterip_tgt_info *i, u_int32_t ip,
        atomic_set(&c->entries, 1);
 
 #ifdef CONFIG_PROC_FS
-       /* create proc dir entry */
-       sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(ip));
-       c->pde = create_proc_entry(buffer, S_IWUSR|S_IRUSR, clusterip_procdir);
-       if (!c->pde) {
-               kfree(c);
-               return NULL;
+       {
+               char buffer[16];
+
+               /* create proc dir entry */
+               sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(ip));
+               c->pde = create_proc_entry(buffer, S_IWUSR|S_IRUSR,
+                                          clusterip_procdir);
+               if (!c->pde) {
+                       kfree(c);
+                       return NULL;
+               }
        }
        c->pde->proc_fops = &clusterip_proc_fops;
        c->pde->data = c;
@@ -205,6 +207,7 @@ clusterip_config_init(struct ipt_clusterip_tgt_info *i, u_int32_t ip,
        return c;
 }
 
+#ifdef CONFIG_PROC_FS
 static int
 clusterip_add_node(struct clusterip_config *c, u_int16_t nodenum)
 {
@@ -226,12 +229,13 @@ clusterip_del_node(struct clusterip_config *c, u_int16_t nodenum)
        if (nodenum == 0 ||
            nodenum > c->num_total_nodes)
                return 1;
-               
+
        if (test_and_clear_bit(nodenum - 1, &c->local_nodes))
                return 0;
 
        return 1;
 }
+#endif
 
 static inline u_int32_t
 clusterip_hashfn(struct sk_buff *skb, struct clusterip_config *config)
@@ -244,6 +248,7 @@ clusterip_hashfn(struct sk_buff *skb, struct clusterip_config *config)
        switch (iph->protocol) {
        case IPPROTO_TCP:
        case IPPROTO_UDP:
+       case IPPROTO_UDPLITE:
        case IPPROTO_SCTP:
        case IPPROTO_DCCP:
        case IPPROTO_ICMP:
@@ -265,7 +270,7 @@ clusterip_hashfn(struct sk_buff *skb, struct clusterip_config *config)
                                      config->hash_initval);
                break;
        case CLUSTERIP_HASHMODE_SIP_SPT:
-               hashval = jhash_2words(ntohl(iph->saddr), sport, 
+               hashval = jhash_2words(ntohl(iph->saddr), sport,
                                       config->hash_initval);
                break;
        case CLUSTERIP_HASHMODE_SIP_SPT_DPT:
@@ -292,8 +297,8 @@ clusterip_responsible(struct clusterip_config *config, u_int32_t hash)
        return test_bit(hash - 1, &config->local_nodes);
 }
 
-/*********************************************************************** 
- * IPTABLES TARGET 
+/***********************************************************************
+ * IPTABLES TARGET
  ***********************************************************************/
 
 static unsigned int
@@ -316,7 +321,7 @@ target(struct sk_buff **pskb,
        if (mark == NULL) {
                printk(KERN_ERR "CLUSTERIP: no conntrack!\n");
                        /* FIXME: need to drop invalid ones, since replies
-                        * to outgoing connections of other nodes will be 
+                        * to outgoing connections of other nodes will be
                         * marked as INVALID */
                return NF_DROP;
        }
@@ -324,11 +329,11 @@ target(struct sk_buff **pskb,
        /* special case: ICMP error handling. conntrack distinguishes between
         * error messages (RELATED) and information requests (see below) */
        if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP
-           && (ctinfo == IP_CT_RELATED 
+           && (ctinfo == IP_CT_RELATED
                || ctinfo == IP_CT_RELATED+IP_CT_IS_REPLY))
-               return IPT_CONTINUE;
+               return XT_CONTINUE;
 
-       /* ip_conntrack_icmp guarantees us that we only have ICMP_ECHO, 
+       /* ip_conntrack_icmp guarantees us that we only have ICMP_ECHO,
         * TIMESTAMP, INFO_REQUEST or ADDRESS type icmp packets from here
         * on, which all have an ID field [relevant for hashing]. */
 
@@ -364,15 +369,15 @@ target(struct sk_buff **pskb,
         * actually a unicast IP packet. TCP doesn't like PACKET_MULTICAST */
        (*pskb)->pkt_type = PACKET_HOST;
 
-       return IPT_CONTINUE;
+       return XT_CONTINUE;
 }
 
 static int
 checkentry(const char *tablename,
           const void *e_void,
           const struct xt_target *target,
-           void *targinfo,
-           unsigned int hook_mask)
+          void *targinfo,
+          unsigned int hook_mask)
 {
        struct ipt_clusterip_tgt_info *cipinfo = targinfo;
        const struct ipt_entry *e = e_void;
@@ -387,7 +392,7 @@ checkentry(const char *tablename,
                return 0;
 
        }
-       if (e->ip.dmsk.s_addr != 0xffffffff
+       if (e->ip.dmsk.s_addr != htonl(0xffffffff)
            || e->ip.dst.s_addr == 0) {
                printk(KERN_ERR "CLUSTERIP: Please specify destination IP\n");
                return 0;
@@ -432,7 +437,7 @@ checkentry(const char *tablename,
                                return 0;
                        }
 
-                       config = clusterip_config_init(cipinfo, 
+                       config = clusterip_config_init(cipinfo,
                                                        e->ip.dst.s_addr, dev);
                        if (!config) {
                                printk(KERN_WARNING "CLUSTERIP: cannot allocate config\n");
@@ -444,6 +449,12 @@ checkentry(const char *tablename,
                cipinfo->config = config;
        }
 
+       if (nf_ct_l3proto_try_module_get(target->family) < 0) {
+               printk(KERN_WARNING "can't load conntrack support for "
+                                   "proto=%d\n", target->family);
+               return 0;
+       }
+
        return 1;
 }
 
@@ -457,10 +468,13 @@ static void destroy(const struct xt_target *target, void *targinfo)
        clusterip_config_entry_put(cipinfo->config);
 
        clusterip_config_put(cipinfo->config);
+
+       nf_ct_l3proto_module_put(target->family);
 }
 
-static struct ipt_target clusterip_tgt = {
+static struct xt_target clusterip_tgt = {
        .name           = "CLUSTERIP",
+       .family         = AF_INET,
        .target         = target,
        .targetsize     = sizeof(struct ipt_clusterip_tgt_info),
        .checkentry     = checkentry,
@@ -469,20 +483,20 @@ static struct ipt_target clusterip_tgt = {
 };
 
 
-/*********************************************************************** 
- * ARP MANGLING CODE 
+/***********************************************************************
+ * ARP MANGLING CODE
  ***********************************************************************/
 
 /* hardcoded for 48bit ethernet and 32bit ipv4 addresses */
 struct arp_payload {
        u_int8_t src_hw[ETH_ALEN];
-       u_int32_t src_ip;
+       __be32 src_ip;
        u_int8_t dst_hw[ETH_ALEN];
-       u_int32_t dst_ip;
+       __be32 dst_ip;
 } __attribute__ ((packed));
 
 #ifdef CLUSTERIP_DEBUG
-static void arp_print(struct arp_payload *payload) 
+static void arp_print(struct arp_payload *payload)
 {
 #define HBUFFERLEN 30
        char hbuffer[HBUFFERLEN];
@@ -496,7 +510,7 @@ static void arp_print(struct arp_payload *payload)
        }
        hbuffer[--k]='\0';
 
-       printk("src %u.%u.%u.%u@%s, dst %u.%u.%u.%u\n", 
+       printk("src %u.%u.%u.%u@%s, dst %u.%u.%u.%u\n",
                NIPQUAD(payload->src_ip), hbuffer,
                NIPQUAD(payload->dst_ip));
 }
@@ -526,13 +540,13 @@ arp_mangle(unsigned int hook,
 
        payload = (void *)(arp+1);
 
-       /* if there is no clusterip configuration for the arp reply's 
+       /* if there is no clusterip configuration for the arp reply's
         * source ip, we don't want to mangle it */
        c = clusterip_config_find_get(payload->src_ip, 0);
        if (!c)
                return NF_ACCEPT;
 
-       /* normally the linux kernel always replies to arp queries of 
+       /* normally the linux kernel always replies to arp queries of
         * addresses on different interfacs.  However, in the CLUSTERIP case
         * this wouldn't work, since we didn't subscribe the mcast group on
         * other interfaces */
@@ -563,8 +577,8 @@ static struct nf_hook_ops cip_arp_ops = {
        .priority = -1
 };
 
-/*********************************************************************** 
- * PROC DIR HANDLING 
+/***********************************************************************
+ * PROC DIR HANDLING
  ***********************************************************************/
 
 #ifdef CONFIG_PROC_FS
@@ -626,7 +640,7 @@ static int clusterip_seq_show(struct seq_file *s, void *v)
 {
        struct clusterip_seq_position *idx = (struct clusterip_seq_position *)v;
 
-       if (idx->pos != 0) 
+       if (idx->pos != 0)
                seq_putc(s, ',');
 
        seq_printf(s, "%u", idx->bit);
@@ -680,7 +694,7 @@ static ssize_t clusterip_proc_write(struct file *file, const char __user *input,
 {
 #define PROC_WRITELEN  10
        char buffer[PROC_WRITELEN+1];
-       struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode);
+       struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
        struct clusterip_config *c = pde->data;
        unsigned long nodenum;
 
@@ -716,7 +730,7 @@ static int __init ipt_clusterip_init(void)
 {
        int ret;
 
-       ret = ipt_register_target(&clusterip_tgt);
+       ret = xt_register_target(&clusterip_tgt);
        if (ret < 0)
                return ret;
 
@@ -737,10 +751,12 @@ static int __init ipt_clusterip_init(void)
                CLUSTERIP_VERSION);
        return 0;
 
+#ifdef CONFIG_PROC_FS
 cleanup_hook:
        nf_unregister_hook(&cip_arp_ops);
+#endif /* CONFIG_PROC_FS */
 cleanup_target:
-       ipt_unregister_target(&clusterip_tgt);
+       xt_unregister_target(&clusterip_tgt);
        return ret;
 }
 
@@ -752,7 +768,7 @@ static void __exit ipt_clusterip_fini(void)
        remove_proc_entry(clusterip_procdir->name, clusterip_procdir->parent);
 #endif
        nf_unregister_hook(&cip_arp_ops);
-       ipt_unregister_target(&clusterip_tgt);
+       xt_unregister_target(&clusterip_tgt);
 }
 
 module_init(ipt_clusterip_init);