-/* 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>
*
#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>
#define DEBUGP
#endif
-#define ASSERT_READ_LOCK(x)
-
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
MODULE_DESCRIPTION("iptables target for CLUSTERIP");
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 */
}
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;
}
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;
}
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)
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;
return c;
}
+#ifdef CONFIG_PROC_FS
static int
clusterip_add_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)
switch (iph->protocol) {
case IPPROTO_TCP:
case IPPROTO_UDP:
+ case IPPROTO_UDPLITE:
case IPPROTO_SCTP:
case IPPROTO_DCCP:
case IPPROTO_ICMP:
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:
return test_bit(hash - 1, &config->local_nodes);
}
-/***********************************************************************
- * IPTABLES TARGET
+/***********************************************************************
+ * IPTABLES TARGET
***********************************************************************/
static unsigned int
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;
}
/* 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]. */
* 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;
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;
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");
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;
}
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,
};
-/***********************************************************************
- * 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];
}
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));
}
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 */
.priority = -1
};
-/***********************************************************************
- * PROC DIR HANDLING
+/***********************************************************************
+ * PROC DIR HANDLING
***********************************************************************/
#ifdef CONFIG_PROC_FS
{
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);
{
#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;
{
int ret;
- ret = ipt_register_target(&clusterip_tgt);
+ ret = xt_register_target(&clusterip_tgt);
if (ret < 0)
return ret;
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;
}
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);