#include <linux/jhash.h>
#include <linux/bitops.h>
#include <linux/skbuff.h>
+#include <linux/slab.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
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 *
}
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;
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);
+ sprintf(buffer, "%pI4", &ip);
+ 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
-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)
+clusterip_tg(struct sk_buff *skb, const struct xt_target_param *par)
{
- const struct ipt_clusterip_tgt_info *cipinfo = targinfo;
+ const struct ipt_clusterip_tgt_info *cipinfo = par->targinfo;
struct nf_conn *ct;
enum ip_conntrack_info ctinfo;
u_int32_t hash;
/* special case: ICMP error handling. conntrack distinguishes between
* error messages (RELATED) and information requests (see below) */
- if (ip_hdr(skb)->protocol == IPPROTO_ICMP
- && (ctinfo == IP_CT_RELATED
- || ctinfo == IP_CT_RELATED+IP_CT_IS_REPLY))
+ if (ip_hdr(skb)->protocol == IPPROTO_ICMP &&
+ (ctinfo == IP_CT_RELATED ||
+ ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY))
return XT_CONTINUE;
/* ip_conntrack_icmp guarantees us that we only have ICMP_ECHO,
}
#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)) {
return XT_CONTINUE;
}
-static bool
-clusterip_tg_check(const char *tablename, const void *e_void,
- const struct xt_target *target, void *targinfo,
- unsigned int hook_mask)
+static bool clusterip_tg_check(const struct xt_tgchk_param *par)
{
- struct ipt_clusterip_tgt_info *cipinfo = targinfo;
- const struct ipt_entry *e = e_void;
+ struct ipt_clusterip_tgt_info *cipinfo = par->targinfo;
+ const struct ipt_entry *e = par->entryinfo;
struct clusterip_config *config;
return false;
}
- if (e->ip.dmsk.s_addr != htonl(0xffffffff)
- || e->ip.dst.s_addr == 0) {
+ if (e->ip.dmsk.s_addr != htonl(0xffffffff) ||
+ e->ip.dst.s_addr == 0) {
printk(KERN_ERR "CLUSTERIP: Please specify destination IP\n");
return false;
}
config = clusterip_config_find_get(e->ip.dst.s_addr, 1);
if (!config) {
if (!(cipinfo->flags & CLUSTERIP_FLAG_NEW)) {
- printk(KERN_WARNING "CLUSTERIP: no config found for %u.%u.%u.%u, need 'new'\n", NIPQUAD(e->ip.dst.s_addr));
+ printk(KERN_WARNING "CLUSTERIP: no config found for %pI4, need 'new'\n", &e->ip.dst.s_addr);
return false;
} else {
struct net_device *dev;
}
cipinfo->config = config;
- if (nf_ct_l3proto_try_module_get(target->family) < 0) {
+ if (nf_ct_l3proto_try_module_get(par->target->family) < 0) {
printk(KERN_WARNING "can't load conntrack support for "
- "proto=%d\n", target->family);
+ "proto=%u\n", par->target->family);
return false;
}
}
/* drop reference count of cluster config when rule is deleted */
-static void clusterip_tg_destroy(const struct xt_target *target, void *targinfo)
+static void clusterip_tg_destroy(const struct xt_tgdtor_param *par)
{
- struct ipt_clusterip_tgt_info *cipinfo = targinfo;
+ const struct ipt_clusterip_tgt_info *cipinfo = par->targinfo;
/* if no more entries are referencing the config, remove it
* from the list and destroy the proc entry */
clusterip_config_put(cipinfo->config);
- nf_ct_l3proto_module_put(target->family);
+ nf_ct_l3proto_module_put(par->target->family);
}
#ifdef CONFIG_COMPAT
static struct xt_target clusterip_tg_reg __read_mostly = {
.name = "CLUSTERIP",
- .family = AF_INET,
+ .family = NFPROTO_IPV4,
.target = clusterip_tg,
.checkentry = clusterip_tg_check,
.destroy = clusterip_tg_destroy,
#define HBUFFERLEN 30
char hbuffer[HBUFFERLEN];
int j,k;
- const char hexbuf[]= "0123456789abcdef";
for (k=0, j=0; k < HBUFFERLEN-3 && j < ETH_ALEN; j++) {
- hbuffer[k++]=hexbuf[(payload->src_hw[j]>>4)&15];
- hbuffer[k++]=hexbuf[payload->src_hw[j]&15];
+ hbuffer[k++] = hex_asc_hi(payload->src_hw[j]);
+ hbuffer[k++] = hex_asc_lo(payload->src_hw[j]);
hbuffer[k++]=':';
}
hbuffer[--k]='\0';
- printk("src %u.%u.%u.%u@%s, dst %u.%u.%u.%u\n",
- NIPQUAD(payload->src_ip), hbuffer,
- NIPQUAD(payload->dst_ip));
+ printk("src %pI4@%s, dst %pI4\n",
+ &payload->src_ip, hbuffer, &payload->dst_ip);
}
#endif
struct clusterip_config *c;
/* we don't care about non-ethernet and non-ipv4 ARP */
- if (arp->ar_hrd != htons(ARPHRD_ETHER)
- || arp->ar_pro != htons(ETH_P_IP)
- || arp->ar_pln != 4 || arp->ar_hln != ETH_ALEN)
+ if (arp->ar_hrd != htons(ARPHRD_ETHER) ||
+ arp->ar_pro != htons(ETH_P_IP) ||
+ arp->ar_pln != 4 || arp->ar_hln != ETH_ALEN)
return NF_ACCEPT;
/* we only want to mangle arp requests and replies */
- if (arp->ar_op != htons(ARPOP_REPLY)
- && arp->ar_op != htons(ARPOP_REQUEST))
+ if (arp->ar_op != htons(ARPOP_REPLY) &&
+ arp->ar_op != htons(ARPOP_REQUEST))
return NF_ACCEPT;
payload = (void *)(arp+1);
static struct nf_hook_ops cip_arp_ops __read_mostly = {
.hook = arp_mangle,
- .pf = NF_ARP,
+ .pf = NFPROTO_ARP,
.hooknum = NF_ARP_OUT,
.priority = -1
};
static void *clusterip_seq_start(struct seq_file *s, loff_t *pos)
{
- struct proc_dir_entry *pde = s->private;
- struct clusterip_config *c = pde->data;
+ struct clusterip_config *c = s->private;
unsigned int weight;
u_int32_t local_nodes;
struct clusterip_seq_position *idx;
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, ',');
if (!ret) {
struct seq_file *sf = file->private_data;
- struct proc_dir_entry *pde = PDE(inode);
- struct clusterip_config *c = pde->data;
+ struct clusterip_config *c = PDE(inode)->data;
- sf->private = pde;
+ sf->private = c;
clusterip_config_get(c);
}
static int clusterip_proc_release(struct inode *inode, struct file *file)
{
- struct proc_dir_entry *pde = PDE(inode);
- struct clusterip_config *c = pde->data;
+ struct clusterip_config *c = PDE(inode)->data;
int ret;
ret = seq_release(inode, file);
static ssize_t clusterip_proc_write(struct file *file, const char __user *input,
size_t size, loff_t *ofs)
{
+ struct clusterip_config *c = PDE(file->f_path.dentry->d_inode)->data;
#define PROC_WRITELEN 10
char buffer[PROC_WRITELEN+1];
- struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
- struct clusterip_config *c = pde->data;
unsigned long nodenum;
if (copy_from_user(buffer, input, PROC_WRITELEN))