nf_nat_amanda.c (2518B)
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 20MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>"); 21MODULE_DESCRIPTION("Amanda NAT helper"); 22MODULE_LICENSE("GPL"); 23MODULE_ALIAS_NF_NAT_HELPER(NAT_HELPER_NAME); 24 25static struct nf_conntrack_nat_helper nat_helper_amanda = 26 NF_CT_NAT_HELPER_INIT(NAT_HELPER_NAME); 27 28static 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 for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) { 48 int res; 49 50 exp->tuple.dst.u.tcp.port = htons(port); 51 res = nf_ct_expect_related(exp, 0); 52 if (res == 0) 53 break; 54 else if (res != -EBUSY) { 55 port = 0; 56 break; 57 } 58 } 59 60 if (port == 0) { 61 nf_ct_helper_log(skb, exp->master, "all ports in use"); 62 return NF_DROP; 63 } 64 65 sprintf(buffer, "%u", port); 66 if (!nf_nat_mangle_udp_packet(skb, exp->master, ctinfo, 67 protoff, matchoff, matchlen, 68 buffer, strlen(buffer))) { 69 nf_ct_helper_log(skb, exp->master, "cannot mangle packet"); 70 nf_ct_unexpect_related(exp); 71 return NF_DROP; 72 } 73 return NF_ACCEPT; 74} 75 76static void __exit nf_nat_amanda_fini(void) 77{ 78 nf_nat_helper_unregister(&nat_helper_amanda); 79 RCU_INIT_POINTER(nf_nat_amanda_hook, NULL); 80 synchronize_rcu(); 81} 82 83static int __init nf_nat_amanda_init(void) 84{ 85 BUG_ON(nf_nat_amanda_hook != NULL); 86 nf_nat_helper_register(&nat_helper_amanda); 87 RCU_INIT_POINTER(nf_nat_amanda_hook, help); 88 return 0; 89} 90 91module_init(nf_nat_amanda_init); 92module_exit(nf_nat_amanda_fini);