X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fipv4%2Fnetfilter%2Fip_conntrack_amanda.c;h=a604b1ccfdaa8c83b86f00744296f26afad07d98;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=a54ef782f8b5827a4f17dd39959a10fbb27fea14;hpb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;p=linux-2.6.git diff --git a/net/ipv4/netfilter/ip_conntrack_amanda.c b/net/ipv4/netfilter/ip_conntrack_amanda.c index a54ef782f..a604b1ccf 100644 --- a/net/ipv4/netfilter/ip_conntrack_amanda.c +++ b/net/ipv4/netfilter/ip_conntrack_amanda.c @@ -18,15 +18,16 @@ * */ +#include #include #include #include #include #include +#include #include #include -#include #include #include @@ -35,23 +36,30 @@ static unsigned int master_timeout = 300; MODULE_AUTHOR("Brian J. Murrell "); MODULE_DESCRIPTION("Amanda connection tracking module"); MODULE_LICENSE("GPL"); -module_param(master_timeout, int, 0600); +module_param(master_timeout, uint, 0600); MODULE_PARM_DESC(master_timeout, "timeout for the master connection"); -static char *conns[] = { "DATA ", "MESG ", "INDEX " }; +static const char *conns[] = { "DATA ", "MESG ", "INDEX " }; /* This is slow, but it's simple. --RR */ -static char amanda_buffer[65536]; -static DECLARE_LOCK(amanda_buffer_lock); +static char *amanda_buffer; +static DEFINE_SPINLOCK(amanda_buffer_lock); -static int help(struct sk_buff *skb, +unsigned int (*ip_nat_amanda_hook)(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + unsigned int matchoff, + unsigned int matchlen, + struct ip_conntrack_expect *exp); +EXPORT_SYMBOL_GPL(ip_nat_amanda_hook); + +static int help(struct sk_buff **pskb, struct ip_conntrack *ct, enum ip_conntrack_info ctinfo) { struct ip_conntrack_expect *exp; - struct ip_ct_amanda_expect *exp_amanda_info; - char *amp, *data, *data_limit, *tmp; + char *data, *data_limit, *tmp; unsigned int dataoff, i; u_int16_t port, len; + int ret = NF_ACCEPT; /* Only look at packets from the Amanda server */ if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) @@ -59,22 +67,20 @@ static int help(struct sk_buff *skb, /* increase the UDP timeout of the master connection as replies from * Amanda clients to the server can be quite delayed */ - ip_ct_refresh_acct(ct, ctinfo, NULL, master_timeout * HZ); + ip_ct_refresh(ct, *pskb, master_timeout * HZ); /* No data? */ - dataoff = skb->nh.iph->ihl*4 + sizeof(struct udphdr); - if (dataoff >= skb->len) { + dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr); + if (dataoff >= (*pskb)->len) { if (net_ratelimit()) - printk("amanda_help: skblen = %u\n", skb->len); + printk("amanda_help: skblen = %u\n", (*pskb)->len); return NF_ACCEPT; } - LOCK_BH(&amanda_buffer_lock); - amp = skb_header_pointer(skb, dataoff, - skb->len - dataoff, amanda_buffer); - BUG_ON(amp == NULL); - data = amp; - data_limit = amp + skb->len - dataoff; + spin_lock_bh(&amanda_buffer_lock); + skb_copy_bits(*pskb, dataoff, amanda_buffer, (*pskb)->len - dataoff); + data = amanda_buffer; + data_limit = amanda_buffer + (*pskb)->len - dataoff; *data_limit = '\0'; /* Search for the CONNECT string */ @@ -97,37 +103,44 @@ static int help(struct sk_buff *skb, if (port == 0 || len > 5) break; - exp = ip_conntrack_expect_alloc(); - if (exp == NULL) + exp = ip_conntrack_expect_alloc(ct); + if (exp == NULL) { + ret = NF_DROP; goto out; + } + + exp->expectfn = NULL; + exp->flags = 0; exp->tuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; + exp->tuple.src.u.tcp.port = 0; exp->tuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip; exp->tuple.dst.protonum = IPPROTO_TCP; + exp->tuple.dst.u.tcp.port = htons(port); + exp->mask.src.ip = 0xFFFFFFFF; + exp->mask.src.u.tcp.port = 0; exp->mask.dst.ip = 0xFFFFFFFF; - exp->mask.dst.protonum = 0xFFFF; + exp->mask.dst.protonum = 0xFF; exp->mask.dst.u.tcp.port = 0xFFFF; - exp_amanda_info = &exp->help.exp_amanda_info; - exp_amanda_info->offset = tmp - amp; - exp_amanda_info->port = port; - exp_amanda_info->len = len; - - exp->tuple.dst.u.tcp.port = htons(port); - - ip_conntrack_expect_related(exp, ct); + if (ip_nat_amanda_hook) + ret = ip_nat_amanda_hook(pskb, ctinfo, + tmp - amanda_buffer, + len, exp); + else if (ip_conntrack_expect_related(exp) != 0) + ret = NF_DROP; + ip_conntrack_expect_put(exp); } out: - UNLOCK_BH(&amanda_buffer_lock); - return NF_ACCEPT; + spin_unlock_bh(&amanda_buffer_lock); + return ret; } static struct ip_conntrack_helper amanda_helper = { .max_expected = ARRAY_SIZE(conns), .timeout = 180, - .flags = IP_CT_HELPER_F_REUSE_EXPECT, .me = THIS_MODULE, .help = help, .name = "amanda", @@ -136,20 +149,33 @@ static struct ip_conntrack_helper amanda_helper = { .dst = { .protonum = IPPROTO_UDP }, }, .mask = { .src = { .u = { 0xFFFF } }, - .dst = { .protonum = 0xFFFF }, + .dst = { .protonum = 0xFF }, }, }; -static void __exit fini(void) +static void __exit ip_conntrack_amanda_fini(void) { ip_conntrack_helper_unregister(&amanda_helper); + kfree(amanda_buffer); } -static int __init init(void) +static int __init ip_conntrack_amanda_init(void) { - return ip_conntrack_helper_register(&amanda_helper); + int ret; + + amanda_buffer = kmalloc(65536, GFP_KERNEL); + if (!amanda_buffer) + return -ENOMEM; + + ret = ip_conntrack_helper_register(&amanda_helper); + if (ret < 0) { + kfree(amanda_buffer); + return ret; + } + return 0; + + } -PROVIDES_CONNTRACK(amanda); -module_init(init); -module_exit(fini); +module_init(ip_conntrack_amanda_init); +module_exit(ip_conntrack_amanda_fini);