1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* Amanda extension for TCP NAT alteration. |
3 | * (C) 2002 by Brian J. Murrell <netfilter@interlinx.bc.ca> |
4 | * based on a copy of HW's ip_nat_irc.c as well as other modules |
5 | * (C) 2006-2012 Patrick McHardy <kaber@trash.net> |
6 | */ |
7 | |
8 | #include <linux/kernel.h> |
9 | #include <linux/module.h> |
10 | #include <linux/skbuff.h> |
11 | #include <linux/udp.h> |
12 | |
13 | #include <net/netfilter/nf_conntrack_helper.h> |
14 | #include <net/netfilter/nf_conntrack_expect.h> |
15 | #include <net/netfilter/nf_nat_helper.h> |
16 | #include <linux/netfilter/nf_conntrack_amanda.h> |
17 | |
18 | #define NAT_HELPER_NAME "amanda" |
19 | |
20 | MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>" ); |
21 | MODULE_DESCRIPTION("Amanda NAT helper" ); |
22 | MODULE_LICENSE("GPL" ); |
23 | MODULE_ALIAS_NF_NAT_HELPER(NAT_HELPER_NAME); |
24 | |
25 | static struct nf_conntrack_nat_helper nat_helper_amanda = |
26 | NF_CT_NAT_HELPER_INIT(NAT_HELPER_NAME); |
27 | |
28 | static unsigned int help(struct sk_buff *skb, |
29 | enum ip_conntrack_info ctinfo, |
30 | unsigned int protoff, |
31 | unsigned int matchoff, |
32 | unsigned int matchlen, |
33 | struct nf_conntrack_expect *exp) |
34 | { |
35 | char buffer[sizeof("65535" )]; |
36 | u_int16_t port; |
37 | |
38 | /* Connection comes from client. */ |
39 | exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port; |
40 | exp->dir = IP_CT_DIR_ORIGINAL; |
41 | |
42 | /* When you see the packet, we need to NAT it the same as the |
43 | * this one (ie. same IP: it will be TCP and master is UDP). */ |
44 | exp->expectfn = nf_nat_follow_master; |
45 | |
46 | /* Try to get same port: if not, try to change it. */ |
47 | port = nf_nat_exp_find_port(exp, ntohs(exp->saved_proto.tcp.port)); |
48 | if (port == 0) { |
49 | nf_ct_helper_log(skb, ct: exp->master, fmt: "all ports in use" ); |
50 | return NF_DROP; |
51 | } |
52 | |
53 | sprintf(buf: buffer, fmt: "%u" , port); |
54 | if (!nf_nat_mangle_udp_packet(skb, ct: exp->master, ctinfo, |
55 | protoff, match_offset: matchoff, match_len: matchlen, |
56 | rep_buffer: buffer, strlen(buffer))) { |
57 | nf_ct_helper_log(skb, ct: exp->master, fmt: "cannot mangle packet" ); |
58 | nf_ct_unexpect_related(exp); |
59 | return NF_DROP; |
60 | } |
61 | return NF_ACCEPT; |
62 | } |
63 | |
64 | static void __exit nf_nat_amanda_fini(void) |
65 | { |
66 | nf_nat_helper_unregister(nat: &nat_helper_amanda); |
67 | RCU_INIT_POINTER(nf_nat_amanda_hook, NULL); |
68 | synchronize_rcu(); |
69 | } |
70 | |
71 | static int __init nf_nat_amanda_init(void) |
72 | { |
73 | BUG_ON(nf_nat_amanda_hook != NULL); |
74 | nf_nat_helper_register(nat: &nat_helper_amanda); |
75 | RCU_INIT_POINTER(nf_nat_amanda_hook, help); |
76 | return 0; |
77 | } |
78 | |
79 | module_init(nf_nat_amanda_init); |
80 | module_exit(nf_nat_amanda_fini); |
81 | |