1 /* Amanda extension for TCP NAT alteration.
2 * (C) 2002 by Brian J. Murrell <netfilter@interlinx.bc.ca>
3 * based on a copy of HW's ip_nat_irc.c as well as other modules
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
11 * insmod ip_nat_amanda.o
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/netfilter.h>
17 #include <linux/skbuff.h>
19 #include <linux/udp.h>
23 #include <linux/netfilter_ipv4.h>
24 #include <linux/netfilter_ipv4/ip_nat.h>
25 #include <linux/netfilter_ipv4/ip_nat_helper.h>
26 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
27 #include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
30 MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>");
31 MODULE_DESCRIPTION("Amanda NAT helper");
32 MODULE_LICENSE("GPL");
35 amanda_nat_expected(struct sk_buff **pskb,
37 struct ip_conntrack *ct,
38 struct ip_nat_info *info)
40 struct ip_conntrack *master = master_ct(ct);
41 struct ip_ct_amanda_expect *exp_amanda_info;
42 struct ip_nat_range range;
47 IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
49 if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
50 newip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
52 newip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
54 /* We don't want to manip the per-protocol, just the IPs. */
55 range.flags = IP_NAT_RANGE_MAP_IPS;
56 range.min_ip = range.max_ip = newip;
58 if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
59 exp_amanda_info = &ct->master->help.exp_amanda_info;
60 range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
62 = ((union ip_conntrack_manip_proto)
63 { .udp = { htons(exp_amanda_info->port) } });
66 return ip_nat_setup_info(ct, &range, hooknum);
69 static int amanda_data_fixup(struct ip_conntrack *ct,
70 struct sk_buff **pskb,
71 enum ip_conntrack_info ctinfo,
72 struct ip_conntrack_expect *exp)
74 struct ip_ct_amanda_expect *exp_amanda_info;
75 struct ip_conntrack_tuple t = exp->tuple;
76 char buffer[sizeof("65535")];
79 /* Alter conntrack's expectations. */
80 exp_amanda_info = &exp->help.exp_amanda_info;
81 t.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
82 for (port = exp_amanda_info->port; port != 0; port++) {
83 t.dst.u.tcp.port = htons(port);
84 if (ip_conntrack_change_expect(exp, &t) == 0)
90 sprintf(buffer, "%u", port);
91 return ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
92 exp_amanda_info->offset,
94 buffer, strlen(buffer));
97 static unsigned int help(struct ip_conntrack *ct,
98 struct ip_conntrack_expect *exp,
99 struct ip_nat_info *info,
100 enum ip_conntrack_info ctinfo,
101 unsigned int hooknum,
102 struct sk_buff **pskb)
104 int dir = CTINFO2DIR(ctinfo);
107 /* Only mangle things once: original direction in POST_ROUTING
108 and reply direction on PRE_ROUTING. */
109 if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
110 || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY)))
113 /* if this exectation has a "offset" the packet needs to be mangled */
114 if (exp->help.exp_amanda_info.offset != 0)
115 if (!amanda_data_fixup(ct, pskb, ctinfo, exp))
117 exp->help.exp_amanda_info.offset = 0;
122 static struct ip_nat_helper ip_nat_amanda_helper;
124 static void __exit fini(void)
126 ip_nat_helper_unregister(&ip_nat_amanda_helper);
129 static int __init init(void)
131 struct ip_nat_helper *hlpr = &ip_nat_amanda_helper;
133 hlpr->tuple.dst.protonum = IPPROTO_UDP;
134 hlpr->tuple.src.u.udp.port = htons(10080);
135 hlpr->mask.src.u.udp.port = 0xFFFF;
136 hlpr->mask.dst.protonum = 0xFFFF;
139 hlpr->me = THIS_MODULE;
140 hlpr->expect = amanda_nat_expected;
141 hlpr->name = "amanda";
143 return ip_nat_helper_register(hlpr);
146 NEEDS_CONNTRACK(amanda);