]> git.hungrycats.org Git - linux/commitdiff
[NETFILTER]: Fix amanda helpers, forward port from 2.4.x version.
authorPatrick McHardy <kaber@trash.net>
Tue, 24 Feb 2004 16:11:46 +0000 (08:11 -0800)
committerPatrick McHardy <kaber@trash.net>
Tue, 24 Feb 2004 16:11:46 +0000 (08:11 -0800)
include/linux/netfilter_ipv4/ip_conntrack_amanda.h
net/ipv4/netfilter/ip_conntrack_amanda.c
net/ipv4/netfilter/ip_nat_amanda.c

index 50726ea6b6417b81045027512f0ddf480f9349e8..75ee293bd08854e4607879d2366e17fc94667c38 100644 (file)
@@ -2,20 +2,11 @@
 #define _IP_CONNTRACK_AMANDA_H
 /* AMANDA tracking. */
 
-#ifdef __KERNEL__
-
-#include <linux/netfilter_ipv4/lockhelp.h>
-
-/* Protects amanda part of conntracks */
-DECLARE_LOCK_EXTERN(ip_amanda_lock);
-
-#endif
-
 struct ip_ct_amanda_expect
 {
        u_int16_t port;         /* port number of this expectation */
-       u_int16_t offset;       /* offset of the port specification in ctrl packet */
-       u_int16_t len;          /* the length of the port number specification */
+       u_int16_t offset;       /* offset of port in ctrl packet */
+       u_int16_t len;          /* length of the port number string */
 };
 
 #endif /* _IP_CONNTRACK_AMANDA_H */
index 9c30e71d56f6dcbd9bdeb06bdcbc7f1498c6c4bc..1b58c958cc91e2f7ea97e19f952e198eaa7eb251 100644 (file)
@@ -18,6 +18,7 @@
  *
  */
 
+#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/netfilter.h>
 #include <linux/ip.h>
@@ -36,50 +37,37 @@ MODULE_LICENSE("GPL");
 MODULE_PARM(master_timeout, "i");
 MODULE_PARM_DESC(master_timeout, "timeout for the master connection");
 
-DECLARE_LOCK(ip_amanda_lock);
-
-char *conns[] = { "DATA ", "MESG ", "INDEX " };
-
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
+static 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 int help(struct sk_buff *skb,
-               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
+                struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
 {
-       char *data, *data_limit;
-       int dir = CTINFO2DIR(ctinfo);
+       struct ip_conntrack_expect exp;
+       struct ip_ct_amanda_expect *exp_amanda_info;
+       char *data, *data_limit, *tmp;
        unsigned int dataoff, i;
-       struct ip_ct_amanda *info =
-                               (struct ip_ct_amanda *)&ct->help.ct_ftp_info;
 
-       /* Can't track connections formed before we registered */
-       if (!info)
+       /* Only look at packets from the Amanda server */
+       if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL)
                return NF_ACCEPT;
 
        /* increase the UDP timeout of the master connection as replies from
         * Amanda clients to the server can be quite delayed */
        ip_ct_refresh(ct, master_timeout * HZ);
 
-       /* If packet is coming from Amanda server */
-       if (dir == IP_CT_DIR_ORIGINAL)
-               return NF_ACCEPT;
-
        /* No data? */
        dataoff = skb->nh.iph->ihl*4 + sizeof(struct udphdr);
        if (dataoff >= skb->len) {
                if (net_ratelimit())
-                       printk("ip_conntrack_amanda_help: skblen = %u\n",
-                              (unsigned)skb->len);
+                       printk("amanda_help: skblen = %u\n", skb->len);
                return NF_ACCEPT;
        }
 
-       LOCK_BH(&ip_amanda_lock);
+       LOCK_BH(&amanda_buffer_lock);
        skb_copy_bits(skb, dataoff, amanda_buffer, skb->len - dataoff);
        data = amanda_buffer;
        data_limit = amanda_buffer + skb->len - dataoff;
@@ -89,84 +77,39 @@ static int help(struct sk_buff *skb,
        data = strstr(data, "CONNECT ");
        if (!data)
                goto out;
-
-       DEBUGP("ip_conntrack_amanda_help: CONNECT found in connection "
-                  "%u.%u.%u.%u:%u %u.%u.%u.%u:%u\n",
-                  NIPQUAD(iph->saddr), htons(udph->source),
-                  NIPQUAD(iph->daddr), htons(udph->dest));
        data += strlen("CONNECT ");
 
+       memset(&exp, 0, sizeof(exp));
+       exp.tuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
+       exp.tuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
+       exp.tuple.dst.protonum = IPPROTO_TCP;
+       exp.mask.src.ip = 0xFFFFFFFF;
+       exp.mask.dst.ip = 0xFFFFFFFF;
+       exp.mask.dst.protonum = 0xFFFF;
+       exp.mask.dst.u.tcp.port = 0xFFFF;
+
        /* Only search first line. */   
-       if (strchr(data, '\n'))
-               *strchr(data, '\n') = '\0';
+       if ((tmp = strchr(data, '\n')))
+               *tmp = '\0';
 
+       exp_amanda_info = &exp.help.exp_amanda_info;
        for (i = 0; i < ARRAY_SIZE(conns); i++) {
                char *match = strstr(data, conns[i]);
-               if (match) {
-                       char *portchr;
-                       struct ip_conntrack_expect expect;
-                       struct ip_ct_amanda_expect *exp_amanda_info =
-                               &expect.help.exp_amanda_info;
-
-                       memset(&expect, 0, sizeof(expect));
-
-                       data += strlen(conns[i]);
-                       /* this is not really tcp, but let's steal an
-                        * idea from a tcp stream helper :-) */
-                       // XXX expect.seq = data - amanda_buffer;
-                       exp_amanda_info->offset = data - amanda_buffer;
-// XXX DEBUGP("expect.seq = %p - %p = %d\n", data, amanda_buffer, expect.seq);
-DEBUGP("exp_amanda_info->offset = %p - %p = %d\n", data, amanda_buffer, exp_amanda_info->offset);
-                       portchr = data;
-                       exp_amanda_info->port = simple_strtoul(data, &data,10);
-                       exp_amanda_info->len = data - portchr;
-
-                       /* eat whitespace */
-                       while (*data == ' ')
-                               data++;
-                       DEBUGP("ip_conntrack_amanda_help: "
-                              "CONNECT %s request with port "
-                              "%u found\n", conns[i],
-                              exp_amanda_info->port);
-
-                       expect.tuple = ((struct ip_conntrack_tuple)
-                               { { ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip,
-                                   { 0 } },
-                                 { ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip,
-                                   { htons(exp_amanda_info->port) },
-                                   IPPROTO_TCP }});
-                       expect.mask = ((struct ip_conntrack_tuple)
-                               { { 0, { 0 } },
-                                 { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
-
-                       expect.expectfn = NULL;
-
-                       DEBUGP ("ip_conntrack_amanda_help: "
-                               "expect_related: %u.%u.%u.%u:%u - "
-                               "%u.%u.%u.%u:%u\n",
-                               NIPQUAD(expect.tuple.src.ip),
-                               ntohs(expect.tuple.src.u.tcp.port),
-                               NIPQUAD(expect.tuple.dst.ip),
-                               ntohs(expect.tuple.dst.u.tcp.port));
-                       if (ip_conntrack_expect_related(ct, &expect)
-                           == -EEXIST) {
-                               ;
-                               /* this must be a packet being resent */
-                               /* XXX - how do I get the
-                                *       ip_conntrack_expect that
-                                *       already exists so that I can
-                                *       update the .seq so that the
-                                *       nat module rewrites the port
-                                *       numbers?
-                                *       Perhaps I should use the
-                                *       exp_amanda_info instead of
-                                *       .seq.
-                                */
-                       }
-               }
+               if (!match)
+                       continue;
+               tmp = data = match + strlen(conns[i]);
+               exp_amanda_info->offset = data - amanda_buffer;
+               exp_amanda_info->port   = simple_strtoul(data, &data, 10);
+               exp_amanda_info->len    = data - tmp;
+               if (exp_amanda_info->port == 0 || exp_amanda_info->len > 5)
+                       break;
+
+               exp.tuple.dst.u.tcp.port = htons(exp_amanda_info->port);
+               ip_conntrack_expect_related(ct, &exp);
        }
- out:
-       UNLOCK_BH(&ip_amanda_lock);
+
+out:
+       UNLOCK_BH(&amanda_buffer_lock);
        return NF_ACCEPT;
 }
 
@@ -186,29 +129,16 @@ static struct ip_conntrack_helper amanda_helper = {
        },
 };
 
-static void fini(void)
+static void __exit fini(void)
 {
-       DEBUGP("ip_ct_amanda: unregistering helper for port 10080\n");
        ip_conntrack_helper_unregister(&amanda_helper);
 }
 
 static int __init init(void)
 {
-       int ret;
-
-       DEBUGP("ip_ct_amanda: registering helper for port 10080\n");
-       ret = ip_conntrack_helper_register(&amanda_helper);
-
-       if (ret) {
-               printk("ip_ct_amanda: ERROR registering helper\n");
-               fini();
-               return -EBUSY;
-       }
-       return 0;
+       return ip_conntrack_helper_register(&amanda_helper);
 }
 
 PROVIDES_CONNTRACK(amanda);
-EXPORT_SYMBOL(ip_amanda_lock);
-
 module_init(init);
 module_exit(fini);
index d3afbbd08a95be9445fd1b3e564a86af26cfd89b..811caadc025ca22f334b486608efa2a84ed4a592 100644 (file)
  *     insmod ip_nat_amanda.o
  */
 
+#include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter.h>
+#include <linux/skbuff.h>
 #include <linux/ip.h>
 #include <linux/udp.h>
-#include <linux/kernel.h>
 #include <net/tcp.h>
 #include <net/udp.h>
 
+#include <linux/netfilter_ipv4.h>
 #include <linux/netfilter_ipv4/ip_nat.h>
 #include <linux/netfilter_ipv4/ip_nat_helper.h>
-#include <linux/netfilter_ipv4/ip_nat_rule.h>
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
 #include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
 
 
-#if 0
-#define DEBUGP printk
-#define DUMP_OFFSET(x) printk("offset_before=%d, offset_after=%d, correction_pos=%u\n", x->offset_before, x->offset_after, x->correction_pos);
-#else
-#define DEBUGP(format, args...)
-#define DUMP_OFFSET(x)
-#endif
-
 MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>");
 MODULE_DESCRIPTION("Amanda NAT helper");
 MODULE_LICENSE("GPL");
 
-/* protects amanda part of conntracks */
-DECLARE_LOCK_EXTERN(ip_amanda_lock);
-
 static unsigned int
 amanda_nat_expected(struct sk_buff **pskb,
-                unsigned int hooknum,
-                struct ip_conntrack *ct,
-                struct ip_nat_info *info)
+                    unsigned int hooknum,
+                    struct ip_conntrack *ct,
+                    struct ip_nat_info *info)
 {
-       struct ip_nat_multi_range mr;
-       u_int32_t newdstip, newsrcip, newip;
-       u_int16_t port;
-       struct ip_ct_amanda_expect *exp_info;
        struct ip_conntrack *master = master_ct(ct);
+       struct ip_ct_amanda_expect *exp_amanda_info;
+       struct ip_nat_multi_range mr;
+       u_int32_t newip;
 
        IP_NF_ASSERT(info);
        IP_NF_ASSERT(master);
-
        IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
 
-       DEBUGP("nat_expected: We have a connection!\n");
-       exp_info = &ct->master->help.exp_amanda_info;
-
-       newdstip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
-       newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
-       DEBUGP("nat_expected: %u.%u.%u.%u->%u.%u.%u.%u\n",
-              NIPQUAD(newsrcip), NIPQUAD(newdstip));
-
-       port = exp_info->port;
-
        if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
-               newip = newsrcip;
+               newip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
        else
-               newip = newdstip;
-
-       DEBUGP("nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
+               newip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
 
        mr.rangesize = 1;
        /* We don't want to manip the per-protocol, just the IPs. */
@@ -81,121 +57,79 @@ amanda_nat_expected(struct sk_buff **pskb,
        mr.range[0].min_ip = mr.range[0].max_ip = newip;
 
        if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
+               exp_amanda_info = &ct->master->help.exp_amanda_info;
                mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
                mr.range[0].min = mr.range[0].max
                        = ((union ip_conntrack_manip_proto)
-                               { .udp = { htons(port) } });
+                               { .udp = { htons(exp_amanda_info->port) } });
        }
 
        return ip_nat_setup_info(ct, &mr, hooknum);
 }
 
 static int amanda_data_fixup(struct ip_conntrack *ct,
-                         struct sk_buff **pskb,
-                         enum ip_conntrack_info ctinfo,
-                         struct ip_conntrack_expect *expect)
+                             struct sk_buff **pskb,
+                             enum ip_conntrack_info ctinfo,
+                             struct ip_conntrack_expect *exp)
 {
-       u_int32_t newip;
-       /* DATA 99999 MESG 99999 INDEX 99999 */
-       char buffer[6];
-       struct ip_conntrack_expect *exp = expect;
-       struct ip_ct_amanda_expect *ct_amanda_info = &exp->help.exp_amanda_info;
+       struct ip_ct_amanda_expect *exp_amanda_info;
        struct ip_conntrack_tuple t = exp->tuple;
+       char buffer[sizeof("65535")];
        u_int16_t port;
 
-       MUST_BE_LOCKED(&ip_amanda_lock);
-
-       newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
-       DEBUGP ("ip_nat_amanda_help: newip = %u.%u.%u.%u\n", NIPQUAD(newip));
-
        /* Alter conntrack's expectations. */
-
-       /* We can read expect here without conntrack lock, since it's
-          only set in ip_conntrack_amanda, with ip_amanda_lock held
-          writable */
-
-       t.dst.ip = newip;
-       for (port = ct_amanda_info->port; port != 0; port++) {
+       exp_amanda_info = &exp->help.exp_amanda_info;
+       t.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
+       for (port = exp_amanda_info->port; port != 0; port++) {
                t.dst.u.tcp.port = htons(port);
                if (ip_conntrack_change_expect(exp, &t) == 0)
                        break;
        }
-
        if (port == 0)
                return 0;
 
        sprintf(buffer, "%u", port);
-
-       return ip_nat_mangle_udp_packet(pskb, ct, ctinfo, /* XXX exp->seq */ ct_amanda_info->offset, 
-                                       ct_amanda_info->len, buffer, strlen(buffer));
+       return ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
+                                       exp_amanda_info->offset,
+                                       exp_amanda_info->len,
+                                       buffer, strlen(buffer));
 }
 
 static unsigned int help(struct ip_conntrack *ct,
-                        struct ip_conntrack_expect *exp,
-                        struct ip_nat_info *info,
-                        enum ip_conntrack_info ctinfo,
-                        unsigned int hooknum,
-                        struct sk_buff **pskb)
+                         struct ip_conntrack_expect *exp,
+                         struct ip_nat_info *info,
+                         enum ip_conntrack_info ctinfo,
+                         unsigned int hooknum,
+                         struct sk_buff **pskb)
 {
-       int dir;
+       int dir = CTINFO2DIR(ctinfo);
+       int ret = NF_ACCEPT;
 
-       if (!exp)
-               DEBUGP("ip_nat_amanda: no exp!!");
-               
        /* Only mangle things once: original direction in POST_ROUTING
           and reply direction on PRE_ROUTING. */
-       dir = CTINFO2DIR(ctinfo);
        if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
-             || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
-               DEBUGP("ip_nat_amanda_help: Not touching dir %s at hook %s\n",
-                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
-                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
-                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
-                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT"
-                      : hooknum == NF_IP_LOCAL_IN ? "INPUT" : "???");
+             || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY)))
                return NF_ACCEPT;
-       }
-       DEBUGP("ip_nat_amanda_help: got beyond not touching: dir %s at hook %s for expect: ",
-                  dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
-                  hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
-                  : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
-                    : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT"
-                      : hooknum == NF_IP_LOCAL_IN ? "INPUT" : "???");
-       DUMP_TUPLE(&exp->tuple);
-
-       LOCK_BH(&ip_amanda_lock);
-// XXX if (exp->seq != 0)
+
+       /* if this exectation has a "offset" the packet needs to be mangled */
        if (exp->help.exp_amanda_info.offset != 0)
-               /*  if this packet has a "seq" it needs to have it's content mangled */
-               if (!amanda_data_fixup(ct, pskb, ctinfo, exp)) {
-                       UNLOCK_BH(&ip_amanda_lock);
-                       DEBUGP("ip_nat_amanda: NF_DROP\n");
-                       return NF_DROP;
-               }
+               if (!amanda_data_fixup(ct, pskb, ctinfo, exp))
+                       ret = NF_DROP;
        exp->help.exp_amanda_info.offset = 0;
-       UNLOCK_BH(&ip_amanda_lock);
 
-       DEBUGP("ip_nat_amanda: NF_ACCEPT\n");
-       return NF_ACCEPT;
+       return ret;
 }
 
 static struct ip_nat_helper ip_nat_amanda_helper;
 
-/* This function is intentionally _NOT_ defined as  __exit, because
- * it is needed by init() */
-static void fini(void)
+static void __exit fini(void)
 {
-       DEBUGP("ip_nat_amanda: unregistering nat helper\n");
        ip_nat_helper_unregister(&ip_nat_amanda_helper);
 }
 
 static int __init init(void)
 {
-       int ret = 0;
-       struct ip_nat_helper *hlpr;
-
-       hlpr = &ip_nat_amanda_helper;
-       memset(hlpr, 0, sizeof(struct ip_nat_helper));
+       struct ip_nat_helper *hlpr = &ip_nat_amanda_helper;
 
        hlpr->tuple.dst.protonum = IPPROTO_UDP;
        hlpr->tuple.src.u.udp.port = htons(10080);
@@ -205,20 +139,9 @@ static int __init init(void)
        hlpr->flags = 0;
        hlpr->me = THIS_MODULE;
        hlpr->expect = amanda_nat_expected;
-
        hlpr->name = "amanda";
 
-       DEBUGP
-           ("ip_nat_amanda: Trying to register nat helper\n");
-       ret = ip_nat_helper_register(hlpr);
-
-       if (ret) {
-               printk
-                   ("ip_nat_amanda: error registering nat helper\n");
-               fini();
-               return 1;
-       }
-       return ret;
+       return ip_nat_helper_register(hlpr);
 }
 
 NEEDS_CONNTRACK(amanda);