116958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy/* Amanda extension for TCP NAT alteration. 216958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy * (C) 2002 by Brian J. Murrell <netfilter@interlinx.bc.ca> 316958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy * based on a copy of HW's ip_nat_irc.c as well as other modules 4f229f6ce481ceb33a966311722b8ef0cb6c25de7Patrick McHardy * (C) 2006-2012 Patrick McHardy <kaber@trash.net> 516958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy * 616958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy * This program is free software; you can redistribute it and/or 716958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy * modify it under the terms of the GNU General Public License 816958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy * as published by the Free Software Foundation; either version 916958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy * 2 of the License, or (at your option) any later version. 1016958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy */ 1116958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy 1216958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy#include <linux/kernel.h> 1316958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy#include <linux/module.h> 1416958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy#include <linux/skbuff.h> 1516958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy#include <linux/udp.h> 1616958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy 1716958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy#include <net/netfilter/nf_conntrack_helper.h> 1816958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy#include <net/netfilter/nf_conntrack_expect.h> 191afc56794e03229fa53cfa3c5012704d226e1decPablo Neira Ayuso#include <net/netfilter/nf_nat_helper.h> 2016958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy#include <linux/netfilter/nf_conntrack_amanda.h> 2116958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy 2216958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardyMODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>"); 2316958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardyMODULE_DESCRIPTION("Amanda NAT helper"); 2416958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardyMODULE_LICENSE("GPL"); 2516958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardyMODULE_ALIAS("ip_nat_amanda"); 2616958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy 273db05fea51cdb162cfa8f69e9cfb9e228919d2a9Herbert Xustatic unsigned int help(struct sk_buff *skb, 2816958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy enum ip_conntrack_info ctinfo, 29051966c0c644a1c96092d4206e00704ade813c9aPatrick McHardy unsigned int protoff, 3016958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy unsigned int matchoff, 3116958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy unsigned int matchlen, 3216958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy struct nf_conntrack_expect *exp) 3316958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy{ 3416958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy char buffer[sizeof("65535")]; 3516958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy u_int16_t port; 3616958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy unsigned int ret; 3716958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy 3816958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy /* Connection comes from client. */ 3916958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port; 4016958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy exp->dir = IP_CT_DIR_ORIGINAL; 4116958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy 4216958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy /* When you see the packet, we need to NAT it the same as the 4316958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy * this one (ie. same IP: it will be TCP and master is UDP). */ 4416958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy exp->expectfn = nf_nat_follow_master; 4516958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy 4616958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy /* Try to get same port: if not, try to change it. */ 4716958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) { 48ab0cba25128e1435a59b1ec4ae0c7505548fed87Eric Dumazet int res; 495b92b61f3891517d18d0573ad2c939c81b59ecfePablo Neira Ayuso 5016958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy exp->tuple.dst.u.tcp.port = htons(port); 51ab0cba25128e1435a59b1ec4ae0c7505548fed87Eric Dumazet res = nf_ct_expect_related(exp); 52ab0cba25128e1435a59b1ec4ae0c7505548fed87Eric Dumazet if (res == 0) 535b92b61f3891517d18d0573ad2c939c81b59ecfePablo Neira Ayuso break; 54ab0cba25128e1435a59b1ec4ae0c7505548fed87Eric Dumazet else if (res != -EBUSY) { 555b92b61f3891517d18d0573ad2c939c81b59ecfePablo Neira Ayuso port = 0; 5616958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy break; 575b92b61f3891517d18d0573ad2c939c81b59ecfePablo Neira Ayuso } 5816958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy } 5916958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy 60b20ab9cc63ca4605aec154cf54faa8455749f3f6Pablo Neira Ayuso if (port == 0) { 61b20ab9cc63ca4605aec154cf54faa8455749f3f6Pablo Neira Ayuso nf_ct_helper_log(skb, exp->master, "all ports in use"); 6216958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy return NF_DROP; 63b20ab9cc63ca4605aec154cf54faa8455749f3f6Pablo Neira Ayuso } 6416958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy 6516958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy sprintf(buffer, "%u", port); 663db05fea51cdb162cfa8f69e9cfb9e228919d2a9Herbert Xu ret = nf_nat_mangle_udp_packet(skb, exp->master, ctinfo, 67051966c0c644a1c96092d4206e00704ade813c9aPatrick McHardy protoff, matchoff, matchlen, 6816958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy buffer, strlen(buffer)); 69b20ab9cc63ca4605aec154cf54faa8455749f3f6Pablo Neira Ayuso if (ret != NF_ACCEPT) { 70b20ab9cc63ca4605aec154cf54faa8455749f3f6Pablo Neira Ayuso nf_ct_helper_log(skb, exp->master, "cannot mangle packet"); 716823645d608541c2c69e8a99454936e058c294e0Patrick McHardy nf_ct_unexpect_related(exp); 72b20ab9cc63ca4605aec154cf54faa8455749f3f6Pablo Neira Ayuso } 7316958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy return ret; 7416958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy} 7516958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy 7616958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardystatic void __exit nf_nat_amanda_fini(void) 7716958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy{ 78a9b3cd7f323b2e57593e7215362a7b02fc933e3aStephen Hemminger RCU_INIT_POINTER(nf_nat_amanda_hook, NULL); 7916958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy synchronize_rcu(); 8016958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy} 8116958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy 8216958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardystatic int __init nf_nat_amanda_init(void) 8316958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy{ 84d1332e0ab84479d941de5cf4a69c71dfd385a25ePatrick McHardy BUG_ON(nf_nat_amanda_hook != NULL); 85a9b3cd7f323b2e57593e7215362a7b02fc933e3aStephen Hemminger RCU_INIT_POINTER(nf_nat_amanda_hook, help); 8616958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy return 0; 8716958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy} 8816958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardy 8916958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardymodule_init(nf_nat_amanda_init); 9016958900578b94585c2ab9a2d20d837b4d5e3ba6Patrick McHardymodule_exit(nf_nat_amanda_fini); 91