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