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
  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