xref: /openbmc/linux/net/netfilter/nf_nat_amanda.c (revision c92c2717)
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