patch-2.4.21 linux-2.4.21/net/ipv4/netfilter/ip_nat_amanda.c
Next file: linux-2.4.21/net/ipv4/netfilter/ip_nat_core.c
Previous file: linux-2.4.21/net/ipv4/netfilter/ip_conntrack_tftp.c
Back to the patch index
Back to the overall index
- Lines: 227
- Date:
2003-06-13 07:51:39.000000000 -0700
- Orig file:
linux-2.4.20/net/ipv4/netfilter/ip_nat_amanda.c
- Orig date:
1969-12-31 16:00:00.000000000 -0800
diff -urN linux-2.4.20/net/ipv4/netfilter/ip_nat_amanda.c linux-2.4.21/net/ipv4/netfilter/ip_nat_amanda.c
@@ -0,0 +1,226 @@
+/* Amanda extension for TCP NAT alteration.
+ * (C) 2002 by Brian J. Murrell <netfilter@interlinx.bc.ca>
+ * based on a copy of HW's ip_nat_irc.c as well as other modules
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Module load syntax:
+ * insmod ip_nat_amanda.o
+ */
+
+#include <linux/module.h>
+#include <linux/netfilter_ipv4.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/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 network address translation module");
+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)
+{
+ 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);
+
+ 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;
+ else
+ newip = newdstip;
+
+ DEBUGP("nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
+
+ mr.rangesize = 1;
+ /* We don't want to manip the per-protocol, just the IPs. */
+ mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
+ mr.range[0].min_ip = mr.range[0].max_ip = newip;
+
+ if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
+ mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
+ mr.range[0].min = mr.range[0].max
+ = ((union ip_conntrack_manip_proto)
+ { htons(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)
+{
+ 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_conntrack_tuple t = exp->tuple;
+ int 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 + 10; 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));
+}
+
+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)
+{
+ int dir;
+
+ 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" : "???");
+ 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 (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;
+ }
+ exp->help.exp_amanda_info.offset = 0;
+ UNLOCK_BH(&ip_amanda_lock);
+
+ DEBUGP("ip_nat_amanda: NF_ACCEPT\n");
+ return NF_ACCEPT;
+}
+
+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)
+{
+ 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));
+
+ hlpr->tuple.dst.protonum = IPPROTO_UDP;
+ hlpr->tuple.src.u.udp.port = htons(10080);
+ hlpr->mask.src.u.udp.port = 0xFFFF;
+ hlpr->mask.dst.protonum = 0xFFFF;
+ hlpr->help = help;
+ 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;
+}
+
+
+module_init(init);
+module_exit(fini);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)