1/* 2 * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net> 3 * Copyright (c) 2012 Pablo Neira Ayuso <pablo@netfilter.org> 4 * Copyright (c) 2012 Intel Corporation 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2, as published by the Free Software Foundation. 9 * 10 */ 11 12#include <linux/module.h> 13#include <linux/init.h> 14#include <linux/skbuff.h> 15#include <linux/ip.h> 16#include <linux/string.h> 17#include <linux/netlink.h> 18#include <linux/netfilter.h> 19#include <linux/netfilter_ipv4.h> 20#include <linux/netfilter/nfnetlink.h> 21#include <linux/netfilter/nf_tables.h> 22#include <net/netfilter/nf_conntrack.h> 23#include <net/netfilter/nf_nat.h> 24#include <net/netfilter/nf_nat_core.h> 25#include <net/netfilter/nf_tables.h> 26#include <net/netfilter/nf_nat_l3proto.h> 27#include <net/ip.h> 28 29struct nft_nat { 30 enum nft_registers sreg_addr_min:8; 31 enum nft_registers sreg_addr_max:8; 32 enum nft_registers sreg_proto_min:8; 33 enum nft_registers sreg_proto_max:8; 34 enum nf_nat_manip_type type:8; 35 u8 family; 36 u16 flags; 37}; 38 39static void nft_nat_eval(const struct nft_expr *expr, 40 struct nft_data data[NFT_REG_MAX + 1], 41 const struct nft_pktinfo *pkt) 42{ 43 const struct nft_nat *priv = nft_expr_priv(expr); 44 enum ip_conntrack_info ctinfo; 45 struct nf_conn *ct = nf_ct_get(pkt->skb, &ctinfo); 46 struct nf_nat_range range; 47 48 memset(&range, 0, sizeof(range)); 49 if (priv->sreg_addr_min) { 50 if (priv->family == AF_INET) { 51 range.min_addr.ip = (__force __be32) 52 data[priv->sreg_addr_min].data[0]; 53 range.max_addr.ip = (__force __be32) 54 data[priv->sreg_addr_max].data[0]; 55 56 } else { 57 memcpy(range.min_addr.ip6, 58 data[priv->sreg_addr_min].data, 59 sizeof(struct nft_data)); 60 memcpy(range.max_addr.ip6, 61 data[priv->sreg_addr_max].data, 62 sizeof(struct nft_data)); 63 } 64 range.flags |= NF_NAT_RANGE_MAP_IPS; 65 } 66 67 if (priv->sreg_proto_min) { 68 range.min_proto.all = (__force __be16) 69 data[priv->sreg_proto_min].data[0]; 70 range.max_proto.all = (__force __be16) 71 data[priv->sreg_proto_max].data[0]; 72 range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED; 73 } 74 75 range.flags |= priv->flags; 76 77 data[NFT_REG_VERDICT].verdict = 78 nf_nat_setup_info(ct, &range, priv->type); 79} 80 81static const struct nla_policy nft_nat_policy[NFTA_NAT_MAX + 1] = { 82 [NFTA_NAT_TYPE] = { .type = NLA_U32 }, 83 [NFTA_NAT_FAMILY] = { .type = NLA_U32 }, 84 [NFTA_NAT_REG_ADDR_MIN] = { .type = NLA_U32 }, 85 [NFTA_NAT_REG_ADDR_MAX] = { .type = NLA_U32 }, 86 [NFTA_NAT_REG_PROTO_MIN] = { .type = NLA_U32 }, 87 [NFTA_NAT_REG_PROTO_MAX] = { .type = NLA_U32 }, 88 [NFTA_NAT_FLAGS] = { .type = NLA_U32 }, 89}; 90 91static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr, 92 const struct nlattr * const tb[]) 93{ 94 struct nft_nat *priv = nft_expr_priv(expr); 95 u32 family; 96 int err; 97 98 err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); 99 if (err < 0) 100 return err; 101 102 if (tb[NFTA_NAT_TYPE] == NULL || 103 (tb[NFTA_NAT_REG_ADDR_MIN] == NULL && 104 tb[NFTA_NAT_REG_PROTO_MIN] == NULL)) 105 return -EINVAL; 106 107 switch (ntohl(nla_get_be32(tb[NFTA_NAT_TYPE]))) { 108 case NFT_NAT_SNAT: 109 priv->type = NF_NAT_MANIP_SRC; 110 break; 111 case NFT_NAT_DNAT: 112 priv->type = NF_NAT_MANIP_DST; 113 break; 114 default: 115 return -EINVAL; 116 } 117 118 if (tb[NFTA_NAT_FAMILY] == NULL) 119 return -EINVAL; 120 121 family = ntohl(nla_get_be32(tb[NFTA_NAT_FAMILY])); 122 if (family != AF_INET && family != AF_INET6) 123 return -EAFNOSUPPORT; 124 if (family != ctx->afi->family) 125 return -EOPNOTSUPP; 126 priv->family = family; 127 128 if (tb[NFTA_NAT_REG_ADDR_MIN]) { 129 priv->sreg_addr_min = 130 ntohl(nla_get_be32(tb[NFTA_NAT_REG_ADDR_MIN])); 131 132 err = nft_validate_input_register(priv->sreg_addr_min); 133 if (err < 0) 134 return err; 135 136 if (tb[NFTA_NAT_REG_ADDR_MAX]) { 137 priv->sreg_addr_max = 138 ntohl(nla_get_be32(tb[NFTA_NAT_REG_ADDR_MAX])); 139 140 err = nft_validate_input_register(priv->sreg_addr_max); 141 if (err < 0) 142 return err; 143 } else { 144 priv->sreg_addr_max = priv->sreg_addr_min; 145 } 146 } 147 148 if (tb[NFTA_NAT_REG_PROTO_MIN]) { 149 priv->sreg_proto_min = 150 ntohl(nla_get_be32(tb[NFTA_NAT_REG_PROTO_MIN])); 151 152 err = nft_validate_input_register(priv->sreg_proto_min); 153 if (err < 0) 154 return err; 155 156 if (tb[NFTA_NAT_REG_PROTO_MAX]) { 157 priv->sreg_proto_max = 158 ntohl(nla_get_be32(tb[NFTA_NAT_REG_PROTO_MAX])); 159 160 err = nft_validate_input_register(priv->sreg_proto_max); 161 if (err < 0) 162 return err; 163 } else { 164 priv->sreg_proto_max = priv->sreg_proto_min; 165 } 166 } 167 168 if (tb[NFTA_NAT_FLAGS]) { 169 priv->flags = ntohl(nla_get_be32(tb[NFTA_NAT_FLAGS])); 170 if (priv->flags & ~NF_NAT_RANGE_MASK) 171 return -EINVAL; 172 } 173 174 return 0; 175} 176 177static int nft_nat_dump(struct sk_buff *skb, const struct nft_expr *expr) 178{ 179 const struct nft_nat *priv = nft_expr_priv(expr); 180 181 switch (priv->type) { 182 case NF_NAT_MANIP_SRC: 183 if (nla_put_be32(skb, NFTA_NAT_TYPE, htonl(NFT_NAT_SNAT))) 184 goto nla_put_failure; 185 break; 186 case NF_NAT_MANIP_DST: 187 if (nla_put_be32(skb, NFTA_NAT_TYPE, htonl(NFT_NAT_DNAT))) 188 goto nla_put_failure; 189 break; 190 } 191 192 if (nla_put_be32(skb, NFTA_NAT_FAMILY, htonl(priv->family))) 193 goto nla_put_failure; 194 195 if (priv->sreg_addr_min) { 196 if (nla_put_be32(skb, NFTA_NAT_REG_ADDR_MIN, 197 htonl(priv->sreg_addr_min)) || 198 nla_put_be32(skb, NFTA_NAT_REG_ADDR_MAX, 199 htonl(priv->sreg_addr_max))) 200 goto nla_put_failure; 201 } 202 203 if (priv->sreg_proto_min) { 204 if (nla_put_be32(skb, NFTA_NAT_REG_PROTO_MIN, 205 htonl(priv->sreg_proto_min)) || 206 nla_put_be32(skb, NFTA_NAT_REG_PROTO_MAX, 207 htonl(priv->sreg_proto_max))) 208 goto nla_put_failure; 209 } 210 211 if (priv->flags != 0) { 212 if (nla_put_be32(skb, NFTA_NAT_FLAGS, htonl(priv->flags))) 213 goto nla_put_failure; 214 } 215 216 return 0; 217 218nla_put_failure: 219 return -1; 220} 221 222static int nft_nat_validate(const struct nft_ctx *ctx, 223 const struct nft_expr *expr, 224 const struct nft_data **data) 225{ 226 return nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); 227} 228 229static struct nft_expr_type nft_nat_type; 230static const struct nft_expr_ops nft_nat_ops = { 231 .type = &nft_nat_type, 232 .size = NFT_EXPR_SIZE(sizeof(struct nft_nat)), 233 .eval = nft_nat_eval, 234 .init = nft_nat_init, 235 .dump = nft_nat_dump, 236 .validate = nft_nat_validate, 237}; 238 239static struct nft_expr_type nft_nat_type __read_mostly = { 240 .name = "nat", 241 .ops = &nft_nat_ops, 242 .policy = nft_nat_policy, 243 .maxattr = NFTA_NAT_MAX, 244 .owner = THIS_MODULE, 245}; 246 247static int __init nft_nat_module_init(void) 248{ 249 return nft_register_expr(&nft_nat_type); 250} 251 252static void __exit nft_nat_module_exit(void) 253{ 254 nft_unregister_expr(&nft_nat_type); 255} 256 257module_init(nft_nat_module_init); 258module_exit(nft_nat_module_exit); 259 260MODULE_LICENSE("GPL"); 261MODULE_AUTHOR("Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>"); 262MODULE_ALIAS_NFT_EXPR("nat"); 263