linux/net/netfilter/nf_nat_amanda.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/* Amanda extension for TCP NAT alteration.
   3 * (C) 2002 by Brian J. Murrell <netfilter@interlinx.bc.ca>
   4 * based on a copy of HW's ip_nat_irc.c as well as other modules
   5 * (C) 2006-2012 Patrick McHardy <kaber@trash.net>
   6 */
   7
   8#include <linux/kernel.h>
   9#include <linux/module.h>
  10#include <linux/skbuff.h>
  11#include <linux/udp.h>
  12
  13#include <net/netfilter/nf_conntrack_helper.h>
  14#include <net/netfilter/nf_conntrack_expect.h>
  15#include <net/netfilter/nf_nat_helper.h>
  16#include <linux/netfilter/nf_conntrack_amanda.h>
  17
  18#define NAT_HELPER_NAME "amanda"
  19
  20MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>");
  21MODULE_DESCRIPTION("Amanda NAT helper");
  22MODULE_LICENSE("GPL");
  23MODULE_ALIAS_NF_NAT_HELPER(NAT_HELPER_NAME);
  24
  25static struct nf_conntrack_nat_helper nat_helper_amanda =
  26        NF_CT_NAT_HELPER_INIT(NAT_HELPER_NAME);
  27
  28static unsigned int help(struct sk_buff *skb,
  29                         enum ip_conntrack_info ctinfo,
  30                         unsigned int protoff,
  31                         unsigned int matchoff,
  32                         unsigned int matchlen,
  33                         struct nf_conntrack_expect *exp)
  34{
  35        char buffer[sizeof("65535")];
  36        u_int16_t port;
  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, 0);
  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        if (!nf_nat_mangle_udp_packet(skb, exp->master, ctinfo,
  67                                      protoff, matchoff, matchlen,
  68                                      buffer, strlen(buffer))) {
  69                nf_ct_helper_log(skb, exp->master, "cannot mangle packet");
  70                nf_ct_unexpect_related(exp);
  71                return NF_DROP;
  72        }
  73        return NF_ACCEPT;
  74}
  75
  76static void __exit nf_nat_amanda_fini(void)
  77{
  78        nf_nat_helper_unregister(&nat_helper_amanda);
  79        RCU_INIT_POINTER(nf_nat_amanda_hook, NULL);
  80        synchronize_rcu();
  81}
  82
  83static int __init nf_nat_amanda_init(void)
  84{
  85        BUG_ON(nf_nat_amanda_hook != NULL);
  86        nf_nat_helper_register(&nat_helper_amanda);
  87        RCU_INIT_POINTER(nf_nat_amanda_hook, help);
  88        return 0;
  89}
  90
  91module_init(nf_nat_amanda_init);
  92module_exit(nf_nat_amanda_fini);
  93