linux/net/netfilter/nf_nat_amanda.c
<<
>>
Prefs
   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
  22#define NAT_HELPER_NAME "amanda"
  23
  24MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>");
  25MODULE_DESCRIPTION("Amanda NAT helper");
  26MODULE_LICENSE("GPL");
  27MODULE_ALIAS_NF_NAT_HELPER(NAT_HELPER_NAME);
  28
  29static struct nf_conntrack_nat_helper nat_helper_amanda =
  30        NF_CT_NAT_HELPER_INIT(NAT_HELPER_NAME);
  31
  32static unsigned int help(struct sk_buff *skb,
  33                         enum ip_conntrack_info ctinfo,
  34                         unsigned int protoff,
  35                         unsigned int matchoff,
  36                         unsigned int matchlen,
  37                         struct nf_conntrack_expect *exp)
  38{
  39        char buffer[sizeof("65535")];
  40        u_int16_t port;
  41
  42        /* Connection comes from client. */
  43        exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
  44        exp->dir = IP_CT_DIR_ORIGINAL;
  45
  46        /* When you see the packet, we need to NAT it the same as the
  47         * this one (ie. same IP: it will be TCP and master is UDP). */
  48        exp->expectfn = nf_nat_follow_master;
  49
  50        /* Try to get same port: if not, try to change it. */
  51        for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
  52                int res;
  53
  54                exp->tuple.dst.u.tcp.port = htons(port);
  55                res = nf_ct_expect_related(exp);
  56                if (res == 0)
  57                        break;
  58                else if (res != -EBUSY) {
  59                        port = 0;
  60                        break;
  61                }
  62        }
  63
  64        if (port == 0) {
  65                nf_ct_helper_log(skb, exp->master, "all ports in use");
  66                return NF_DROP;
  67        }
  68
  69        sprintf(buffer, "%u", port);
  70        if (!nf_nat_mangle_udp_packet(skb, exp->master, ctinfo,
  71                                      protoff, matchoff, matchlen,
  72                                      buffer, strlen(buffer))) {
  73                nf_ct_helper_log(skb, exp->master, "cannot mangle packet");
  74                nf_ct_unexpect_related(exp);
  75                return NF_DROP;
  76        }
  77        return NF_ACCEPT;
  78}
  79
  80static void __exit nf_nat_amanda_fini(void)
  81{
  82        nf_nat_helper_unregister(&nat_helper_amanda);
  83        RCU_INIT_POINTER(nf_nat_amanda_hook, NULL);
  84        synchronize_rcu();
  85}
  86
  87static int __init nf_nat_amanda_init(void)
  88{
  89        BUG_ON(nf_nat_amanda_hook != NULL);
  90        nf_nat_helper_register(&nat_helper_amanda);
  91        RCU_INIT_POINTER(nf_nat_amanda_hook, help);
  92        return 0;
  93}
  94
  95module_init(nf_nat_amanda_init);
  96module_exit(nf_nat_amanda_fini);
  97