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 4 * (C) 2006-2012 Patrick McHardy <kaber@trash.net> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 9 * 2 of the License, or (at your option) any later version. 10 */ 11 12#include <linux/kernel.h> 13#include <linux/module.h> 14#include <linux/skbuff.h> 15#include <linux/udp.h> 16 17#include <net/netfilter/nf_conntrack_helper.h> 18#include <net/netfilter/nf_conntrack_expect.h> 19#include <net/netfilter/nf_nat_helper.h> 20#include <linux/netfilter/nf_conntrack_amanda.h> 21 22MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>"); 23MODULE_DESCRIPTION("Amanda NAT helper"); 24MODULE_LICENSE("GPL"); 25MODULE_ALIAS("ip_nat_amanda"); 26 27static unsigned int help(struct sk_buff *skb, 28 enum ip_conntrack_info ctinfo, 29 unsigned int protoff, 30 unsigned int matchoff, 31 unsigned int matchlen, 32 struct nf_conntrack_expect *exp) 33{ 34 char buffer[sizeof("65535")]; 35 u_int16_t port; 36 unsigned int ret; 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); 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 ret = nf_nat_mangle_udp_packet(skb, exp->master, ctinfo, 67 protoff, matchoff, matchlen, 68 buffer, strlen(buffer)); 69 if (ret != NF_ACCEPT) { 70 nf_ct_helper_log(skb, exp->master, "cannot mangle packet"); 71 nf_ct_unexpect_related(exp); 72 } 73 return ret; 74} 75 76static void __exit nf_nat_amanda_fini(void) 77{ 78 RCU_INIT_POINTER(nf_nat_amanda_hook, NULL); 79 synchronize_rcu(); 80} 81 82static int __init nf_nat_amanda_init(void) 83{ 84 BUG_ON(nf_nat_amanda_hook != NULL); 85 RCU_INIT_POINTER(nf_nat_amanda_hook, help); 86 return 0; 87} 88 89module_init(nf_nat_amanda_init); 90module_exit(nf_nat_amanda_fini); 91