0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/kernel.h>
0009 #include <linux/module.h>
0010 #include <linux/skbuff.h>
0011 #include <linux/udp.h>
0012
0013 #include <net/netfilter/nf_conntrack_helper.h>
0014 #include <net/netfilter/nf_conntrack_expect.h>
0015 #include <net/netfilter/nf_nat_helper.h>
0016 #include <linux/netfilter/nf_conntrack_amanda.h>
0017
0018 #define NAT_HELPER_NAME "amanda"
0019
0020 MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>");
0021 MODULE_DESCRIPTION("Amanda NAT helper");
0022 MODULE_LICENSE("GPL");
0023 MODULE_ALIAS_NF_NAT_HELPER(NAT_HELPER_NAME);
0024
0025 static struct nf_conntrack_nat_helper nat_helper_amanda =
0026 NF_CT_NAT_HELPER_INIT(NAT_HELPER_NAME);
0027
0028 static unsigned int help(struct sk_buff *skb,
0029 enum ip_conntrack_info ctinfo,
0030 unsigned int protoff,
0031 unsigned int matchoff,
0032 unsigned int matchlen,
0033 struct nf_conntrack_expect *exp)
0034 {
0035 char buffer[sizeof("65535")];
0036 u_int16_t port;
0037
0038
0039 exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
0040 exp->dir = IP_CT_DIR_ORIGINAL;
0041
0042
0043
0044 exp->expectfn = nf_nat_follow_master;
0045
0046
0047 for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
0048 int res;
0049
0050 exp->tuple.dst.u.tcp.port = htons(port);
0051 res = nf_ct_expect_related(exp, 0);
0052 if (res == 0)
0053 break;
0054 else if (res != -EBUSY) {
0055 port = 0;
0056 break;
0057 }
0058 }
0059
0060 if (port == 0) {
0061 nf_ct_helper_log(skb, exp->master, "all ports in use");
0062 return NF_DROP;
0063 }
0064
0065 sprintf(buffer, "%u", port);
0066 if (!nf_nat_mangle_udp_packet(skb, exp->master, ctinfo,
0067 protoff, matchoff, matchlen,
0068 buffer, strlen(buffer))) {
0069 nf_ct_helper_log(skb, exp->master, "cannot mangle packet");
0070 nf_ct_unexpect_related(exp);
0071 return NF_DROP;
0072 }
0073 return NF_ACCEPT;
0074 }
0075
0076 static void __exit nf_nat_amanda_fini(void)
0077 {
0078 nf_nat_helper_unregister(&nat_helper_amanda);
0079 RCU_INIT_POINTER(nf_nat_amanda_hook, NULL);
0080 synchronize_rcu();
0081 }
0082
0083 static int __init nf_nat_amanda_init(void)
0084 {
0085 BUG_ON(nf_nat_amanda_hook != NULL);
0086 nf_nat_helper_register(&nat_helper_amanda);
0087 RCU_INIT_POINTER(nf_nat_amanda_hook, help);
0088 return 0;
0089 }
0090
0091 module_init(nf_nat_amanda_init);
0092 module_exit(nf_nat_amanda_fini);