linux/net/netfilter/xt_nat.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * (C) 1999-2001 Paul `Rusty' Russell
   4 * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
   5 * (C) 2011 Patrick McHardy <kaber@trash.net>
   6 */
   7
   8#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
   9
  10#include <linux/module.h>
  11#include <linux/skbuff.h>
  12#include <linux/netfilter.h>
  13#include <linux/netfilter/x_tables.h>
  14#include <net/netfilter/nf_nat.h>
  15
  16static int xt_nat_checkentry_v0(const struct xt_tgchk_param *par)
  17{
  18        const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
  19
  20        if (mr->rangesize != 1) {
  21                pr_info_ratelimited("multiple ranges no longer supported\n");
  22                return -EINVAL;
  23        }
  24        return nf_ct_netns_get(par->net, par->family);
  25}
  26
  27static int xt_nat_checkentry(const struct xt_tgchk_param *par)
  28{
  29        return nf_ct_netns_get(par->net, par->family);
  30}
  31
  32static void xt_nat_destroy(const struct xt_tgdtor_param *par)
  33{
  34        nf_ct_netns_put(par->net, par->family);
  35}
  36
  37static void xt_nat_convert_range(struct nf_nat_range2 *dst,
  38                                 const struct nf_nat_ipv4_range *src)
  39{
  40        memset(&dst->min_addr, 0, sizeof(dst->min_addr));
  41        memset(&dst->max_addr, 0, sizeof(dst->max_addr));
  42        memset(&dst->base_proto, 0, sizeof(dst->base_proto));
  43
  44        dst->flags       = src->flags;
  45        dst->min_addr.ip = src->min_ip;
  46        dst->max_addr.ip = src->max_ip;
  47        dst->min_proto   = src->min;
  48        dst->max_proto   = src->max;
  49}
  50
  51static unsigned int
  52xt_snat_target_v0(struct sk_buff *skb, const struct xt_action_param *par)
  53{
  54        const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
  55        struct nf_nat_range2 range;
  56        enum ip_conntrack_info ctinfo;
  57        struct nf_conn *ct;
  58
  59        ct = nf_ct_get(skb, &ctinfo);
  60        WARN_ON(!(ct != NULL &&
  61                 (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED ||
  62                  ctinfo == IP_CT_RELATED_REPLY)));
  63
  64        xt_nat_convert_range(&range, &mr->range[0]);
  65        return nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC);
  66}
  67
  68static unsigned int
  69xt_dnat_target_v0(struct sk_buff *skb, const struct xt_action_param *par)
  70{
  71        const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
  72        struct nf_nat_range2 range;
  73        enum ip_conntrack_info ctinfo;
  74        struct nf_conn *ct;
  75
  76        ct = nf_ct_get(skb, &ctinfo);
  77        WARN_ON(!(ct != NULL &&
  78                 (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)));
  79
  80        xt_nat_convert_range(&range, &mr->range[0]);
  81        return nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST);
  82}
  83
  84static unsigned int
  85xt_snat_target_v1(struct sk_buff *skb, const struct xt_action_param *par)
  86{
  87        const struct nf_nat_range *range_v1 = par->targinfo;
  88        struct nf_nat_range2 range;
  89        enum ip_conntrack_info ctinfo;
  90        struct nf_conn *ct;
  91
  92        ct = nf_ct_get(skb, &ctinfo);
  93        WARN_ON(!(ct != NULL &&
  94                 (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED ||
  95                  ctinfo == IP_CT_RELATED_REPLY)));
  96
  97        memcpy(&range, range_v1, sizeof(*range_v1));
  98        memset(&range.base_proto, 0, sizeof(range.base_proto));
  99
 100        return nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC);
 101}
 102
 103static unsigned int
 104xt_dnat_target_v1(struct sk_buff *skb, const struct xt_action_param *par)
 105{
 106        const struct nf_nat_range *range_v1 = par->targinfo;
 107        struct nf_nat_range2 range;
 108        enum ip_conntrack_info ctinfo;
 109        struct nf_conn *ct;
 110
 111        ct = nf_ct_get(skb, &ctinfo);
 112        WARN_ON(!(ct != NULL &&
 113                 (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)));
 114
 115        memcpy(&range, range_v1, sizeof(*range_v1));
 116        memset(&range.base_proto, 0, sizeof(range.base_proto));
 117
 118        return nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST);
 119}
 120
 121static unsigned int
 122xt_snat_target_v2(struct sk_buff *skb, const struct xt_action_param *par)
 123{
 124        const struct nf_nat_range2 *range = par->targinfo;
 125        enum ip_conntrack_info ctinfo;
 126        struct nf_conn *ct;
 127
 128        ct = nf_ct_get(skb, &ctinfo);
 129        WARN_ON(!(ct != NULL &&
 130                 (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED ||
 131                  ctinfo == IP_CT_RELATED_REPLY)));
 132
 133        return nf_nat_setup_info(ct, range, NF_NAT_MANIP_SRC);
 134}
 135
 136static unsigned int
 137xt_dnat_target_v2(struct sk_buff *skb, const struct xt_action_param *par)
 138{
 139        const struct nf_nat_range2 *range = par->targinfo;
 140        enum ip_conntrack_info ctinfo;
 141        struct nf_conn *ct;
 142
 143        ct = nf_ct_get(skb, &ctinfo);
 144        WARN_ON(!(ct != NULL &&
 145                 (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)));
 146
 147        return nf_nat_setup_info(ct, range, NF_NAT_MANIP_DST);
 148}
 149
 150static struct xt_target xt_nat_target_reg[] __read_mostly = {
 151        {
 152                .name           = "SNAT",
 153                .revision       = 0,
 154                .checkentry     = xt_nat_checkentry_v0,
 155                .destroy        = xt_nat_destroy,
 156                .target         = xt_snat_target_v0,
 157                .targetsize     = sizeof(struct nf_nat_ipv4_multi_range_compat),
 158                .family         = NFPROTO_IPV4,
 159                .table          = "nat",
 160                .hooks          = (1 << NF_INET_POST_ROUTING) |
 161                                  (1 << NF_INET_LOCAL_IN),
 162                .me             = THIS_MODULE,
 163        },
 164        {
 165                .name           = "DNAT",
 166                .revision       = 0,
 167                .checkentry     = xt_nat_checkentry_v0,
 168                .destroy        = xt_nat_destroy,
 169                .target         = xt_dnat_target_v0,
 170                .targetsize     = sizeof(struct nf_nat_ipv4_multi_range_compat),
 171                .family         = NFPROTO_IPV4,
 172                .table          = "nat",
 173                .hooks          = (1 << NF_INET_PRE_ROUTING) |
 174                                  (1 << NF_INET_LOCAL_OUT),
 175                .me             = THIS_MODULE,
 176        },
 177        {
 178                .name           = "SNAT",
 179                .revision       = 1,
 180                .checkentry     = xt_nat_checkentry,
 181                .destroy        = xt_nat_destroy,
 182                .target         = xt_snat_target_v1,
 183                .targetsize     = sizeof(struct nf_nat_range),
 184                .table          = "nat",
 185                .hooks          = (1 << NF_INET_POST_ROUTING) |
 186                                  (1 << NF_INET_LOCAL_IN),
 187                .me             = THIS_MODULE,
 188        },
 189        {
 190                .name           = "DNAT",
 191                .revision       = 1,
 192                .checkentry     = xt_nat_checkentry,
 193                .destroy        = xt_nat_destroy,
 194                .target         = xt_dnat_target_v1,
 195                .targetsize     = sizeof(struct nf_nat_range),
 196                .table          = "nat",
 197                .hooks          = (1 << NF_INET_PRE_ROUTING) |
 198                                  (1 << NF_INET_LOCAL_OUT),
 199                .me             = THIS_MODULE,
 200        },
 201        {
 202                .name           = "SNAT",
 203                .revision       = 2,
 204                .checkentry     = xt_nat_checkentry,
 205                .destroy        = xt_nat_destroy,
 206                .target         = xt_snat_target_v2,
 207                .targetsize     = sizeof(struct nf_nat_range2),
 208                .table          = "nat",
 209                .hooks          = (1 << NF_INET_POST_ROUTING) |
 210                                  (1 << NF_INET_LOCAL_IN),
 211                .me             = THIS_MODULE,
 212        },
 213        {
 214                .name           = "DNAT",
 215                .revision       = 2,
 216                .checkentry     = xt_nat_checkentry,
 217                .destroy        = xt_nat_destroy,
 218                .target         = xt_dnat_target_v2,
 219                .targetsize     = sizeof(struct nf_nat_range2),
 220                .table          = "nat",
 221                .hooks          = (1 << NF_INET_PRE_ROUTING) |
 222                                  (1 << NF_INET_LOCAL_OUT),
 223                .me             = THIS_MODULE,
 224        },
 225};
 226
 227static int __init xt_nat_init(void)
 228{
 229        return xt_register_targets(xt_nat_target_reg,
 230                                   ARRAY_SIZE(xt_nat_target_reg));
 231}
 232
 233static void __exit xt_nat_exit(void)
 234{
 235        xt_unregister_targets(xt_nat_target_reg, ARRAY_SIZE(xt_nat_target_reg));
 236}
 237
 238module_init(xt_nat_init);
 239module_exit(xt_nat_exit);
 240
 241MODULE_LICENSE("GPL");
 242MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
 243MODULE_ALIAS("ipt_SNAT");
 244MODULE_ALIAS("ipt_DNAT");
 245MODULE_ALIAS("ip6t_SNAT");
 246MODULE_ALIAS("ip6t_DNAT");
 247