MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
-MODULE_DESCRIPTION("iptables target for CLUSTERIP");
+MODULE_DESCRIPTION("Xtables: CLUSTERIP target");
struct clusterip_config {
struct list_head list; /* list of all configs */
kfree(c);
}
-/* increase the count of entries(rules) using/referencing this config */
-static inline void
-clusterip_config_entry_get(struct clusterip_config *c)
-{
- atomic_inc(&c->entries);
-}
-
/* decrease the count of entries using/referencing this config. If last
* entry(rule) is removed, remove the config from lists, but don't free it
* yet, since proc-files could still be holding references */
static inline void
clusterip_config_entry_put(struct clusterip_config *c)
{
+ write_lock_bh(&clusterip_lock);
if (atomic_dec_and_test(&c->entries)) {
- write_lock_bh(&clusterip_lock);
list_del(&c->list);
write_unlock_bh(&clusterip_lock);
#ifdef CONFIG_PROC_FS
remove_proc_entry(c->pde->name, c->pde->parent);
#endif
+ return;
}
+ write_unlock_bh(&clusterip_lock);
}
static struct clusterip_config *
__clusterip_config_find(__be32 clusterip)
{
- struct list_head *pos;
+ struct clusterip_config *c;
- list_for_each(pos, &clusterip_configs) {
- struct clusterip_config *c = list_entry(pos,
- struct clusterip_config, list);
+ list_for_each_entry(c, &clusterip_configs, list) {
if (c->clusterip == clusterip)
return c;
}
}
static struct clusterip_config *
-clusterip_config_init(struct ipt_clusterip_tgt_info *i, __be32 ip,
+clusterip_config_init(const struct ipt_clusterip_tgt_info *i, __be32 ip,
struct net_device *dev)
{
struct clusterip_config *c;
/* create proc dir entry */
sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(ip));
- c->pde = create_proc_entry(buffer, S_IWUSR|S_IRUSR,
- clusterip_procdir);
+ c->pde = proc_create_data(buffer, S_IWUSR|S_IRUSR,
+ clusterip_procdir,
+ &clusterip_proc_fops, c);
if (!c->pde) {
kfree(c);
return NULL;
}
}
- c->pde->proc_fops = &clusterip_proc_fops;
- c->pde->data = c;
#endif
write_lock_bh(&clusterip_lock);
}
/* node numbers are 1..n, not 0..n */
- return (hashval % config->num_total_nodes) + 1;
+ return (((u64)hashval * config->num_total_nodes) >> 32) + 1;
}
static inline int
***********************************************************************/
static unsigned int
-target(struct sk_buff **pskb,
- const struct net_device *in,
- const struct net_device *out,
- unsigned int hooknum,
- const struct xt_target *target,
- const void *targinfo)
+clusterip_tg(struct sk_buff *skb, const struct net_device *in,
+ const struct net_device *out, unsigned int hooknum,
+ const struct xt_target *target, const void *targinfo)
{
const struct ipt_clusterip_tgt_info *cipinfo = targinfo;
struct nf_conn *ct;
* is only decremented by destroy() - and ip_tables guarantees
* that the ->target() function isn't called after ->destroy() */
- ct = nf_ct_get(*pskb, &ctinfo);
+ ct = nf_ct_get(skb, &ctinfo);
if (ct == NULL) {
printk(KERN_ERR "CLUSTERIP: no conntrack!\n");
/* FIXME: need to drop invalid ones, since replies
/* special case: ICMP error handling. conntrack distinguishes between
* error messages (RELATED) and information requests (see below) */
- if (ip_hdr(*pskb)->protocol == IPPROTO_ICMP
+ if (ip_hdr(skb)->protocol == IPPROTO_ICMP
&& (ctinfo == IP_CT_RELATED
|| ctinfo == IP_CT_RELATED+IP_CT_IS_REPLY))
return XT_CONTINUE;
* TIMESTAMP, INFO_REQUEST or ADDRESS type icmp packets from here
* on, which all have an ID field [relevant for hashing]. */
- hash = clusterip_hashfn(*pskb, cipinfo->config);
+ hash = clusterip_hashfn(skb, cipinfo->config);
switch (ctinfo) {
case IP_CT_NEW:
}
#ifdef DEBUG
- DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+ nf_ct_dump_tuple_ip(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
#endif
pr_debug("hash=%u ct_hash=%u ", hash, ct->mark);
if (!clusterip_responsible(cipinfo->config, hash)) {
/* despite being received via linklayer multicast, this is
* actually a unicast IP packet. TCP doesn't like PACKET_MULTICAST */
- (*pskb)->pkt_type = PACKET_HOST;
+ skb->pkt_type = PACKET_HOST;
return XT_CONTINUE;
}
static bool
-checkentry(const char *tablename,
- const void *e_void,
- const struct xt_target *target,
- void *targinfo,
- unsigned int hook_mask)
+clusterip_tg_check(const char *tablename, const void *e_void,
+ const struct xt_target *target, void *targinfo,
+ unsigned int hook_mask)
{
struct ipt_clusterip_tgt_info *cipinfo = targinfo;
const struct ipt_entry *e = e_void;
return false;
}
- dev = dev_get_by_name(e->ip.iniface);
+ dev = dev_get_by_name(&init_net, e->ip.iniface);
if (!dev) {
printk(KERN_WARNING "CLUSTERIP: no such interface %s\n", e->ip.iniface);
return false;
if (nf_ct_l3proto_try_module_get(target->family) < 0) {
printk(KERN_WARNING "can't load conntrack support for "
- "proto=%d\n", target->family);
+ "proto=%u\n", target->family);
return false;
}
}
/* drop reference count of cluster config when rule is deleted */
-static void destroy(const struct xt_target *target, void *targinfo)
+static void clusterip_tg_destroy(const struct xt_target *target, void *targinfo)
{
- struct ipt_clusterip_tgt_info *cipinfo = targinfo;
+ const struct ipt_clusterip_tgt_info *cipinfo = targinfo;
/* if no more entries are referencing the config, remove it
* from the list and destroy the proc entry */
};
#endif /* CONFIG_COMPAT */
-static struct xt_target clusterip_tgt __read_mostly = {
+static struct xt_target clusterip_tg_reg __read_mostly = {
.name = "CLUSTERIP",
.family = AF_INET,
- .target = target,
- .checkentry = checkentry,
- .destroy = destroy,
+ .target = clusterip_tg,
+ .checkentry = clusterip_tg_check,
+ .destroy = clusterip_tg_destroy,
.targetsize = sizeof(struct ipt_clusterip_tgt_info),
#ifdef CONFIG_COMPAT
.compatsize = sizeof(struct compat_ipt_clusterip_tgt_info),
static unsigned int
arp_mangle(unsigned int hook,
- struct sk_buff **pskb,
+ struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
- struct arphdr *arp = arp_hdr(*pskb);
+ struct arphdr *arp = arp_hdr(skb);
struct arp_payload *payload;
struct clusterip_config *c;
return NF_ACCEPT;
}
-static struct nf_hook_ops cip_arp_ops = {
+static struct nf_hook_ops cip_arp_ops __read_mostly = {
.hook = arp_mangle,
.pf = NF_ARP,
.hooknum = NF_ARP_OUT,
static void *clusterip_seq_start(struct seq_file *s, loff_t *pos)
{
- struct proc_dir_entry *pde = s->private;
+ const struct proc_dir_entry *pde = s->private;
struct clusterip_config *c = pde->data;
unsigned int weight;
u_int32_t local_nodes;
static void *clusterip_seq_next(struct seq_file *s, void *v, loff_t *pos)
{
- struct clusterip_seq_position *idx = (struct clusterip_seq_position *)v;
+ struct clusterip_seq_position *idx = v;
*pos = ++idx->pos;
if (*pos >= idx->weight) {
static int clusterip_seq_show(struct seq_file *s, void *v)
{
- struct clusterip_seq_position *idx = (struct clusterip_seq_position *)v;
+ struct clusterip_seq_position *idx = v;
if (idx->pos != 0)
seq_putc(s, ',');
{
#define PROC_WRITELEN 10
char buffer[PROC_WRITELEN+1];
- struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+ const struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
struct clusterip_config *c = pde->data;
unsigned long nodenum;
#endif /* CONFIG_PROC_FS */
-static int __init ipt_clusterip_init(void)
+static int __init clusterip_tg_init(void)
{
int ret;
- ret = xt_register_target(&clusterip_tgt);
+ ret = xt_register_target(&clusterip_tg_reg);
if (ret < 0)
return ret;
nf_unregister_hook(&cip_arp_ops);
#endif /* CONFIG_PROC_FS */
cleanup_target:
- xt_unregister_target(&clusterip_tgt);
+ xt_unregister_target(&clusterip_tg_reg);
return ret;
}
-static void __exit ipt_clusterip_fini(void)
+static void __exit clusterip_tg_exit(void)
{
printk(KERN_NOTICE "ClusterIP Version %s unloading\n",
CLUSTERIP_VERSION);
remove_proc_entry(clusterip_procdir->name, clusterip_procdir->parent);
#endif
nf_unregister_hook(&cip_arp_ops);
- xt_unregister_target(&clusterip_tgt);
+ xt_unregister_target(&clusterip_tg_reg);
}
-module_init(ipt_clusterip_init);
-module_exit(ipt_clusterip_fini);
+module_init(clusterip_tg_init);
+module_exit(clusterip_tg_exit);