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_multi_range mr
;
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
;
55 /* We don't want to manip the per-protocol, just the IPs. */
56 mr
.range
[0].flags
= IP_NAT_RANGE_MAP_IPS
;
57 mr
.range
[0].min_ip
= mr
.range
[0].max_ip
= newip
;
59 if (HOOK2MANIP(hooknum
) == IP_NAT_MANIP_DST
) {
60 exp_amanda_info
= &ct
->master
->help
.exp_amanda_info
;
61 mr
.range
[0].flags
|= IP_NAT_RANGE_PROTO_SPECIFIED
;
62 mr
.range
[0].min
= mr
.range
[0].max
63 = ((union ip_conntrack_manip_proto
)
64 { .udp
= { htons(exp_amanda_info
->port
) } });
67 return ip_nat_setup_info(ct
, &mr
, hooknum
);
70 static int amanda_data_fixup(struct ip_conntrack
*ct
,
71 struct sk_buff
**pskb
,
72 enum ip_conntrack_info ctinfo
,
73 struct ip_conntrack_expect
*exp
)
75 struct ip_ct_amanda_expect
*exp_amanda_info
;
76 struct ip_conntrack_tuple t
= exp
->tuple
;
77 char buffer
[sizeof("65535")];
80 /* Alter conntrack's expectations. */
81 exp_amanda_info
= &exp
->help
.exp_amanda_info
;
82 t
.dst
.ip
= ct
->tuplehash
[IP_CT_DIR_ORIGINAL
].tuple
.dst
.ip
;
83 for (port
= exp_amanda_info
->port
; port
!= 0; port
++) {
84 t
.dst
.u
.tcp
.port
= htons(port
);
85 if (ip_conntrack_change_expect(exp
, &t
) == 0)
91 sprintf(buffer
, "%u", port
);
92 return ip_nat_mangle_udp_packet(pskb
, ct
, ctinfo
,
93 exp_amanda_info
->offset
,
95 buffer
, strlen(buffer
));
98 static unsigned int help(struct ip_conntrack
*ct
,
99 struct ip_conntrack_expect
*exp
,
100 struct ip_nat_info
*info
,
101 enum ip_conntrack_info ctinfo
,
102 unsigned int hooknum
,
103 struct sk_buff
**pskb
)
105 int dir
= CTINFO2DIR(ctinfo
);
108 /* Only mangle things once: original direction in POST_ROUTING
109 and reply direction on PRE_ROUTING. */
110 if (!((hooknum
== NF_IP_POST_ROUTING
&& dir
== IP_CT_DIR_ORIGINAL
)
111 || (hooknum
== NF_IP_PRE_ROUTING
&& dir
== IP_CT_DIR_REPLY
)))
114 /* if this exectation has a "offset" the packet needs to be mangled */
115 if (exp
->help
.exp_amanda_info
.offset
!= 0)
116 if (!amanda_data_fixup(ct
, pskb
, ctinfo
, exp
))
118 exp
->help
.exp_amanda_info
.offset
= 0;
123 static struct ip_nat_helper ip_nat_amanda_helper
;
125 static void __exit
fini(void)
127 ip_nat_helper_unregister(&ip_nat_amanda_helper
);
130 static int __init
init(void)
132 struct ip_nat_helper
*hlpr
= &ip_nat_amanda_helper
;
134 hlpr
->tuple
.dst
.protonum
= IPPROTO_UDP
;
135 hlpr
->tuple
.src
.u
.udp
.port
= htons(10080);
136 hlpr
->mask
.src
.u
.udp
.port
= 0xFFFF;
137 hlpr
->mask
.dst
.protonum
= 0xFFFF;
140 hlpr
->me
= THIS_MODULE
;
141 hlpr
->expect
= amanda_nat_expected
;
142 hlpr
->name
= "amanda";
144 return ip_nat_helper_register(hlpr
);
147 NEEDS_CONNTRACK(amanda
);