Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
0004  * Copyright (c) 2012 Pablo Neira Ayuso <pablo@netfilter.org>
0005  * Copyright (c) 2012 Intel Corporation
0006  */
0007 
0008 #include <linux/module.h>
0009 #include <linux/init.h>
0010 #include <linux/skbuff.h>
0011 #include <linux/ip.h>
0012 #include <linux/string.h>
0013 #include <linux/netlink.h>
0014 #include <linux/netfilter.h>
0015 #include <linux/netfilter_ipv4.h>
0016 #include <linux/netfilter/nfnetlink.h>
0017 #include <linux/netfilter/nf_tables.h>
0018 #include <net/netfilter/nf_conntrack.h>
0019 #include <net/netfilter/nf_nat.h>
0020 #include <net/netfilter/nf_tables.h>
0021 #include <net/ip.h>
0022 
0023 struct nft_nat {
0024     u8          sreg_addr_min;
0025     u8          sreg_addr_max;
0026     u8          sreg_proto_min;
0027     u8          sreg_proto_max;
0028     enum nf_nat_manip_type  type:8;
0029     u8          family;
0030     u16         flags;
0031 };
0032 
0033 static void nft_nat_setup_addr(struct nf_nat_range2 *range,
0034                    const struct nft_regs *regs,
0035                    const struct nft_nat *priv)
0036 {
0037     switch (priv->family) {
0038     case AF_INET:
0039         range->min_addr.ip = (__force __be32)
0040                 regs->data[priv->sreg_addr_min];
0041         range->max_addr.ip = (__force __be32)
0042                 regs->data[priv->sreg_addr_max];
0043         break;
0044     case AF_INET6:
0045         memcpy(range->min_addr.ip6, &regs->data[priv->sreg_addr_min],
0046                sizeof(range->min_addr.ip6));
0047         memcpy(range->max_addr.ip6, &regs->data[priv->sreg_addr_max],
0048                sizeof(range->max_addr.ip6));
0049         break;
0050     }
0051 }
0052 
0053 static void nft_nat_setup_proto(struct nf_nat_range2 *range,
0054                 const struct nft_regs *regs,
0055                 const struct nft_nat *priv)
0056 {
0057     range->min_proto.all = (__force __be16)
0058         nft_reg_load16(&regs->data[priv->sreg_proto_min]);
0059     range->max_proto.all = (__force __be16)
0060         nft_reg_load16(&regs->data[priv->sreg_proto_max]);
0061 }
0062 
0063 static void nft_nat_setup_netmap(struct nf_nat_range2 *range,
0064                  const struct nft_pktinfo *pkt,
0065                  const struct nft_nat *priv)
0066 {
0067     struct sk_buff *skb = pkt->skb;
0068     union nf_inet_addr new_addr;
0069     __be32 netmask;
0070     int i, len = 0;
0071 
0072     switch (priv->type) {
0073     case NFT_NAT_SNAT:
0074         if (nft_pf(pkt) == NFPROTO_IPV4) {
0075             new_addr.ip = ip_hdr(skb)->saddr;
0076             len = sizeof(struct in_addr);
0077         } else {
0078             new_addr.in6 = ipv6_hdr(skb)->saddr;
0079             len = sizeof(struct in6_addr);
0080         }
0081         break;
0082     case NFT_NAT_DNAT:
0083         if (nft_pf(pkt) == NFPROTO_IPV4) {
0084             new_addr.ip = ip_hdr(skb)->daddr;
0085             len = sizeof(struct in_addr);
0086         } else {
0087             new_addr.in6 = ipv6_hdr(skb)->daddr;
0088             len = sizeof(struct in6_addr);
0089         }
0090         break;
0091     }
0092 
0093     for (i = 0; i < len / sizeof(__be32); i++) {
0094         netmask = ~(range->min_addr.ip6[i] ^ range->max_addr.ip6[i]);
0095         new_addr.ip6[i] &= ~netmask;
0096         new_addr.ip6[i] |= range->min_addr.ip6[i] & netmask;
0097     }
0098 
0099     range->min_addr = new_addr;
0100     range->max_addr = new_addr;
0101 }
0102 
0103 static void nft_nat_eval(const struct nft_expr *expr,
0104              struct nft_regs *regs,
0105              const struct nft_pktinfo *pkt)
0106 {
0107     const struct nft_nat *priv = nft_expr_priv(expr);
0108     enum ip_conntrack_info ctinfo;
0109     struct nf_conn *ct = nf_ct_get(pkt->skb, &ctinfo);
0110     struct nf_nat_range2 range;
0111 
0112     memset(&range, 0, sizeof(range));
0113 
0114     if (priv->sreg_addr_min) {
0115         nft_nat_setup_addr(&range, regs, priv);
0116         if (priv->flags & NF_NAT_RANGE_NETMAP)
0117             nft_nat_setup_netmap(&range, pkt, priv);
0118     }
0119 
0120     if (priv->sreg_proto_min)
0121         nft_nat_setup_proto(&range, regs, priv);
0122 
0123     range.flags = priv->flags;
0124 
0125     regs->verdict.code = nf_nat_setup_info(ct, &range, priv->type);
0126 }
0127 
0128 static const struct nla_policy nft_nat_policy[NFTA_NAT_MAX + 1] = {
0129     [NFTA_NAT_TYPE]      = { .type = NLA_U32 },
0130     [NFTA_NAT_FAMILY]    = { .type = NLA_U32 },
0131     [NFTA_NAT_REG_ADDR_MIN]  = { .type = NLA_U32 },
0132     [NFTA_NAT_REG_ADDR_MAX]  = { .type = NLA_U32 },
0133     [NFTA_NAT_REG_PROTO_MIN] = { .type = NLA_U32 },
0134     [NFTA_NAT_REG_PROTO_MAX] = { .type = NLA_U32 },
0135     [NFTA_NAT_FLAGS]     = { .type = NLA_U32 },
0136 };
0137 
0138 static int nft_nat_validate(const struct nft_ctx *ctx,
0139                 const struct nft_expr *expr,
0140                 const struct nft_data **data)
0141 {
0142     struct nft_nat *priv = nft_expr_priv(expr);
0143     int err;
0144 
0145     err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT);
0146     if (err < 0)
0147         return err;
0148 
0149     switch (priv->type) {
0150     case NFT_NAT_SNAT:
0151         err = nft_chain_validate_hooks(ctx->chain,
0152                            (1 << NF_INET_POST_ROUTING) |
0153                            (1 << NF_INET_LOCAL_IN));
0154         break;
0155     case NFT_NAT_DNAT:
0156         err = nft_chain_validate_hooks(ctx->chain,
0157                            (1 << NF_INET_PRE_ROUTING) |
0158                            (1 << NF_INET_LOCAL_OUT));
0159         break;
0160     }
0161 
0162     return err;
0163 }
0164 
0165 static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
0166             const struct nlattr * const tb[])
0167 {
0168     struct nft_nat *priv = nft_expr_priv(expr);
0169     unsigned int alen, plen;
0170     u32 family;
0171     int err;
0172 
0173     if (tb[NFTA_NAT_TYPE] == NULL ||
0174         (tb[NFTA_NAT_REG_ADDR_MIN] == NULL &&
0175          tb[NFTA_NAT_REG_PROTO_MIN] == NULL))
0176         return -EINVAL;
0177 
0178     switch (ntohl(nla_get_be32(tb[NFTA_NAT_TYPE]))) {
0179     case NFT_NAT_SNAT:
0180         priv->type = NF_NAT_MANIP_SRC;
0181         break;
0182     case NFT_NAT_DNAT:
0183         priv->type = NF_NAT_MANIP_DST;
0184         break;
0185     default:
0186         return -EOPNOTSUPP;
0187     }
0188 
0189     if (tb[NFTA_NAT_FAMILY] == NULL)
0190         return -EINVAL;
0191 
0192     family = ntohl(nla_get_be32(tb[NFTA_NAT_FAMILY]));
0193     if (ctx->family != NFPROTO_INET && ctx->family != family)
0194         return -EOPNOTSUPP;
0195 
0196     switch (family) {
0197     case NFPROTO_IPV4:
0198         alen = sizeof_field(struct nf_nat_range, min_addr.ip);
0199         break;
0200     case NFPROTO_IPV6:
0201         alen = sizeof_field(struct nf_nat_range, min_addr.ip6);
0202         break;
0203     default:
0204         if (tb[NFTA_NAT_REG_ADDR_MIN])
0205             return -EAFNOSUPPORT;
0206         break;
0207     }
0208     priv->family = family;
0209 
0210     if (tb[NFTA_NAT_REG_ADDR_MIN]) {
0211         err = nft_parse_register_load(tb[NFTA_NAT_REG_ADDR_MIN],
0212                           &priv->sreg_addr_min, alen);
0213         if (err < 0)
0214             return err;
0215 
0216         if (tb[NFTA_NAT_REG_ADDR_MAX]) {
0217             err = nft_parse_register_load(tb[NFTA_NAT_REG_ADDR_MAX],
0218                               &priv->sreg_addr_max,
0219                               alen);
0220             if (err < 0)
0221                 return err;
0222         } else {
0223             priv->sreg_addr_max = priv->sreg_addr_min;
0224         }
0225 
0226         priv->flags |= NF_NAT_RANGE_MAP_IPS;
0227     }
0228 
0229     plen = sizeof_field(struct nf_nat_range, min_addr.all);
0230     if (tb[NFTA_NAT_REG_PROTO_MIN]) {
0231         err = nft_parse_register_load(tb[NFTA_NAT_REG_PROTO_MIN],
0232                           &priv->sreg_proto_min, plen);
0233         if (err < 0)
0234             return err;
0235 
0236         if (tb[NFTA_NAT_REG_PROTO_MAX]) {
0237             err = nft_parse_register_load(tb[NFTA_NAT_REG_PROTO_MAX],
0238                               &priv->sreg_proto_max,
0239                               plen);
0240             if (err < 0)
0241                 return err;
0242         } else {
0243             priv->sreg_proto_max = priv->sreg_proto_min;
0244         }
0245 
0246         priv->flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
0247     }
0248 
0249     if (tb[NFTA_NAT_FLAGS]) {
0250         priv->flags |= ntohl(nla_get_be32(tb[NFTA_NAT_FLAGS]));
0251         if (priv->flags & ~NF_NAT_RANGE_MASK)
0252             return -EOPNOTSUPP;
0253     }
0254 
0255     return nf_ct_netns_get(ctx->net, family);
0256 }
0257 
0258 static int nft_nat_dump(struct sk_buff *skb, const struct nft_expr *expr)
0259 {
0260     const struct nft_nat *priv = nft_expr_priv(expr);
0261 
0262     switch (priv->type) {
0263     case NF_NAT_MANIP_SRC:
0264         if (nla_put_be32(skb, NFTA_NAT_TYPE, htonl(NFT_NAT_SNAT)))
0265             goto nla_put_failure;
0266         break;
0267     case NF_NAT_MANIP_DST:
0268         if (nla_put_be32(skb, NFTA_NAT_TYPE, htonl(NFT_NAT_DNAT)))
0269             goto nla_put_failure;
0270         break;
0271     }
0272 
0273     if (nla_put_be32(skb, NFTA_NAT_FAMILY, htonl(priv->family)))
0274         goto nla_put_failure;
0275 
0276     if (priv->sreg_addr_min) {
0277         if (nft_dump_register(skb, NFTA_NAT_REG_ADDR_MIN,
0278                       priv->sreg_addr_min) ||
0279             nft_dump_register(skb, NFTA_NAT_REG_ADDR_MAX,
0280                       priv->sreg_addr_max))
0281             goto nla_put_failure;
0282     }
0283 
0284     if (priv->sreg_proto_min) {
0285         if (nft_dump_register(skb, NFTA_NAT_REG_PROTO_MIN,
0286                       priv->sreg_proto_min) ||
0287             nft_dump_register(skb, NFTA_NAT_REG_PROTO_MAX,
0288                       priv->sreg_proto_max))
0289             goto nla_put_failure;
0290     }
0291 
0292     if (priv->flags != 0) {
0293         if (nla_put_be32(skb, NFTA_NAT_FLAGS, htonl(priv->flags)))
0294             goto nla_put_failure;
0295     }
0296 
0297     return 0;
0298 
0299 nla_put_failure:
0300     return -1;
0301 }
0302 
0303 static void
0304 nft_nat_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
0305 {
0306     const struct nft_nat *priv = nft_expr_priv(expr);
0307 
0308     nf_ct_netns_put(ctx->net, priv->family);
0309 }
0310 
0311 static struct nft_expr_type nft_nat_type;
0312 static const struct nft_expr_ops nft_nat_ops = {
0313     .type           = &nft_nat_type,
0314     .size           = NFT_EXPR_SIZE(sizeof(struct nft_nat)),
0315     .eval           = nft_nat_eval,
0316     .init           = nft_nat_init,
0317     .destroy        = nft_nat_destroy,
0318     .dump           = nft_nat_dump,
0319     .validate   = nft_nat_validate,
0320     .reduce     = NFT_REDUCE_READONLY,
0321 };
0322 
0323 static struct nft_expr_type nft_nat_type __read_mostly = {
0324     .name           = "nat",
0325     .ops            = &nft_nat_ops,
0326     .policy         = nft_nat_policy,
0327     .maxattr        = NFTA_NAT_MAX,
0328     .owner          = THIS_MODULE,
0329 };
0330 
0331 #ifdef CONFIG_NF_TABLES_INET
0332 static void nft_nat_inet_eval(const struct nft_expr *expr,
0333                   struct nft_regs *regs,
0334                   const struct nft_pktinfo *pkt)
0335 {
0336     const struct nft_nat *priv = nft_expr_priv(expr);
0337 
0338     if (priv->family == nft_pf(pkt) ||
0339         priv->family == NFPROTO_INET)
0340         nft_nat_eval(expr, regs, pkt);
0341 }
0342 
0343 static const struct nft_expr_ops nft_nat_inet_ops = {
0344     .type           = &nft_nat_type,
0345     .size           = NFT_EXPR_SIZE(sizeof(struct nft_nat)),
0346     .eval           = nft_nat_inet_eval,
0347     .init           = nft_nat_init,
0348     .destroy        = nft_nat_destroy,
0349     .dump           = nft_nat_dump,
0350     .validate   = nft_nat_validate,
0351     .reduce     = NFT_REDUCE_READONLY,
0352 };
0353 
0354 static struct nft_expr_type nft_inet_nat_type __read_mostly = {
0355     .name           = "nat",
0356     .family     = NFPROTO_INET,
0357     .ops            = &nft_nat_inet_ops,
0358     .policy         = nft_nat_policy,
0359     .maxattr        = NFTA_NAT_MAX,
0360     .owner          = THIS_MODULE,
0361 };
0362 
0363 static int nft_nat_inet_module_init(void)
0364 {
0365     return nft_register_expr(&nft_inet_nat_type);
0366 }
0367 
0368 static void nft_nat_inet_module_exit(void)
0369 {
0370     nft_unregister_expr(&nft_inet_nat_type);
0371 }
0372 #else
0373 static int nft_nat_inet_module_init(void) { return 0; }
0374 static void nft_nat_inet_module_exit(void) { }
0375 #endif
0376 
0377 static int __init nft_nat_module_init(void)
0378 {
0379     int ret = nft_nat_inet_module_init();
0380 
0381     if (ret)
0382         return ret;
0383 
0384     ret = nft_register_expr(&nft_nat_type);
0385     if (ret)
0386         nft_nat_inet_module_exit();
0387 
0388     return ret;
0389 }
0390 
0391 static void __exit nft_nat_module_exit(void)
0392 {
0393     nft_nat_inet_module_exit();
0394     nft_unregister_expr(&nft_nat_type);
0395 }
0396 
0397 module_init(nft_nat_module_init);
0398 module_exit(nft_nat_module_exit);
0399 
0400 MODULE_LICENSE("GPL");
0401 MODULE_AUTHOR("Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>");
0402 MODULE_ALIAS_NFT_EXPR("nat");
0403 MODULE_DESCRIPTION("Network Address Translation support");