Blame view
net/netfilter/nft_masq.c
7.61 KB
d2912cb15 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-only |
9ba1f726b netfilter: nf_tab... |
2 |
/* |
cd7275146 netfilter: update... |
3 |
* Copyright (c) 2014 Arturo Borrero Gonzalez <arturo@debian.org> |
9ba1f726b netfilter: nf_tab... |
4 5 6 7 8 9 10 11 12 13 |
*/ #include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> #include <linux/netlink.h> #include <linux/netfilter.h> #include <linux/netfilter/nf_tables.h> #include <net/netfilter/nf_tables.h> #include <net/netfilter/nf_nat.h> |
bf8981a2a netfilter: nf_nat... |
14 |
#include <net/netfilter/nf_nat_masquerade.h> |
9ba1f726b netfilter: nf_tab... |
15 |
|
a9ce849e7 netfilter: nf_tab... |
16 17 18 19 20 21 22 |
struct nft_masq { u32 flags; enum nft_registers sreg_proto_min:8; enum nft_registers sreg_proto_max:8; }; static const struct nla_policy nft_masq_policy[NFTA_MASQ_MAX + 1] = { |
8a6bf5da1 netfilter: nft_ma... |
23 24 25 |
[NFTA_MASQ_FLAGS] = { .type = NLA_U32 }, [NFTA_MASQ_REG_PROTO_MIN] = { .type = NLA_U32 }, [NFTA_MASQ_REG_PROTO_MAX] = { .type = NLA_U32 }, |
9ba1f726b netfilter: nf_tab... |
26 |
}; |
9ba1f726b netfilter: nf_tab... |
27 |
|
a9ce849e7 netfilter: nf_tab... |
28 29 30 |
static int nft_masq_validate(const struct nft_ctx *ctx, const struct nft_expr *expr, const struct nft_data **data) |
75e8d06d4 netfilter: nf_tab... |
31 32 33 34 35 36 37 38 39 40 |
{ int err; err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); if (err < 0) return err; return nft_chain_validate_hooks(ctx->chain, (1 << NF_INET_POST_ROUTING)); } |
75e8d06d4 netfilter: nf_tab... |
41 |
|
a9ce849e7 netfilter: nf_tab... |
42 43 44 |
static int nft_masq_init(const struct nft_ctx *ctx, const struct nft_expr *expr, const struct nlattr * const tb[]) |
9ba1f726b netfilter: nf_tab... |
45 |
{ |
c593642c8 treewide: Use siz... |
46 |
u32 plen = sizeof_field(struct nf_nat_range, min_addr.all); |
9ba1f726b netfilter: nf_tab... |
47 |
struct nft_masq *priv = nft_expr_priv(expr); |
7210e4e38 netfilter: nf_tab... |
48 |
int err; |
8a6bf5da1 netfilter: nft_ma... |
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
if (tb[NFTA_MASQ_FLAGS]) { priv->flags = ntohl(nla_get_be32(tb[NFTA_MASQ_FLAGS])); if (priv->flags & ~NF_NAT_RANGE_MASK) return -EINVAL; } if (tb[NFTA_MASQ_REG_PROTO_MIN]) { priv->sreg_proto_min = nft_parse_register(tb[NFTA_MASQ_REG_PROTO_MIN]); err = nft_validate_register_load(priv->sreg_proto_min, plen); if (err < 0) return err; if (tb[NFTA_MASQ_REG_PROTO_MAX]) { priv->sreg_proto_max = nft_parse_register(tb[NFTA_MASQ_REG_PROTO_MAX]); err = nft_validate_register_load(priv->sreg_proto_max, plen); if (err < 0) return err; } else { priv->sreg_proto_max = priv->sreg_proto_min; } } |
9ba1f726b netfilter: nf_tab... |
75 |
|
36596dadf netfilter: nf_tab... |
76 |
return nf_ct_netns_get(ctx->net, ctx->family); |
9ba1f726b netfilter: nf_tab... |
77 |
} |
9ba1f726b netfilter: nf_tab... |
78 |
|
a9ce849e7 netfilter: nf_tab... |
79 |
static int nft_masq_dump(struct sk_buff *skb, const struct nft_expr *expr) |
9ba1f726b netfilter: nf_tab... |
80 81 |
{ const struct nft_masq *priv = nft_expr_priv(expr); |
8a6bf5da1 netfilter: nft_ma... |
82 83 |
if (priv->flags != 0 && nla_put_be32(skb, NFTA_MASQ_FLAGS, htonl(priv->flags))) |
9ba1f726b netfilter: nf_tab... |
84 |
goto nla_put_failure; |
8a6bf5da1 netfilter: nft_ma... |
85 86 87 88 89 90 91 |
if (priv->sreg_proto_min) { if (nft_dump_register(skb, NFTA_MASQ_REG_PROTO_MIN, priv->sreg_proto_min) || nft_dump_register(skb, NFTA_MASQ_REG_PROTO_MAX, priv->sreg_proto_max)) goto nla_put_failure; } |
9ba1f726b netfilter: nf_tab... |
92 93 94 95 96 |
return 0; nla_put_failure: return -1; } |
a9ce849e7 netfilter: nf_tab... |
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
static void nft_masq_ipv4_eval(const struct nft_expr *expr, struct nft_regs *regs, const struct nft_pktinfo *pkt) { struct nft_masq *priv = nft_expr_priv(expr); struct nf_nat_range2 range; memset(&range, 0, sizeof(range)); range.flags = priv->flags; if (priv->sreg_proto_min) { range.min_proto.all = (__force __be16)nft_reg_load16( ®s->data[priv->sreg_proto_min]); range.max_proto.all = (__force __be16)nft_reg_load16( ®s->data[priv->sreg_proto_max]); } regs->verdict.code = nf_nat_masquerade_ipv4(pkt->skb, nft_hook(pkt), &range, nft_out(pkt)); } static void nft_masq_ipv4_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr) { nf_ct_netns_put(ctx->net, NFPROTO_IPV4); } static struct nft_expr_type nft_masq_ipv4_type; static const struct nft_expr_ops nft_masq_ipv4_ops = { .type = &nft_masq_ipv4_type, .size = NFT_EXPR_SIZE(sizeof(struct nft_masq)), .eval = nft_masq_ipv4_eval, .init = nft_masq_init, .destroy = nft_masq_ipv4_destroy, .dump = nft_masq_dump, .validate = nft_masq_validate, }; static struct nft_expr_type nft_masq_ipv4_type __read_mostly = { .family = NFPROTO_IPV4, .name = "masq", .ops = &nft_masq_ipv4_ops, .policy = nft_masq_policy, .maxattr = NFTA_MASQ_MAX, .owner = THIS_MODULE, }; #ifdef CONFIG_NF_TABLES_IPV6 static void nft_masq_ipv6_eval(const struct nft_expr *expr, struct nft_regs *regs, const struct nft_pktinfo *pkt) { struct nft_masq *priv = nft_expr_priv(expr); struct nf_nat_range2 range; memset(&range, 0, sizeof(range)); range.flags = priv->flags; if (priv->sreg_proto_min) { range.min_proto.all = (__force __be16)nft_reg_load16( ®s->data[priv->sreg_proto_min]); range.max_proto.all = (__force __be16)nft_reg_load16( ®s->data[priv->sreg_proto_max]); } regs->verdict.code = nf_nat_masquerade_ipv6(pkt->skb, &range, nft_out(pkt)); } static void nft_masq_ipv6_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr) { nf_ct_netns_put(ctx->net, NFPROTO_IPV6); } static struct nft_expr_type nft_masq_ipv6_type; static const struct nft_expr_ops nft_masq_ipv6_ops = { .type = &nft_masq_ipv6_type, .size = NFT_EXPR_SIZE(sizeof(struct nft_masq)), .eval = nft_masq_ipv6_eval, .init = nft_masq_init, .destroy = nft_masq_ipv6_destroy, .dump = nft_masq_dump, .validate = nft_masq_validate, }; static struct nft_expr_type nft_masq_ipv6_type __read_mostly = { .family = NFPROTO_IPV6, .name = "masq", .ops = &nft_masq_ipv6_ops, .policy = nft_masq_policy, .maxattr = NFTA_MASQ_MAX, .owner = THIS_MODULE, }; static int __init nft_masq_module_init_ipv6(void) { |
610a43149 netfilter: nf_nat... |
191 |
return nft_register_expr(&nft_masq_ipv6_type); |
a9ce849e7 netfilter: nf_tab... |
192 193 194 195 196 |
} static void nft_masq_module_exit_ipv6(void) { nft_unregister_expr(&nft_masq_ipv6_type); |
a9ce849e7 netfilter: nf_tab... |
197 198 199 200 201 |
} #else static inline int nft_masq_module_init_ipv6(void) { return 0; } static inline void nft_masq_module_exit_ipv6(void) {} #endif |
071657d2c netfilter: nft_ma... |
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 |
#ifdef CONFIG_NF_TABLES_INET static void nft_masq_inet_eval(const struct nft_expr *expr, struct nft_regs *regs, const struct nft_pktinfo *pkt) { switch (nft_pf(pkt)) { case NFPROTO_IPV4: return nft_masq_ipv4_eval(expr, regs, pkt); case NFPROTO_IPV6: return nft_masq_ipv6_eval(expr, regs, pkt); } WARN_ON_ONCE(1); } static void nft_masq_inet_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr) { nf_ct_netns_put(ctx->net, NFPROTO_INET); } static struct nft_expr_type nft_masq_inet_type; static const struct nft_expr_ops nft_masq_inet_ops = { .type = &nft_masq_inet_type, .size = NFT_EXPR_SIZE(sizeof(struct nft_masq)), .eval = nft_masq_inet_eval, .init = nft_masq_init, .destroy = nft_masq_inet_destroy, .dump = nft_masq_dump, .validate = nft_masq_validate, }; static struct nft_expr_type nft_masq_inet_type __read_mostly = { .family = NFPROTO_INET, .name = "masq", .ops = &nft_masq_inet_ops, .policy = nft_masq_policy, .maxattr = NFTA_MASQ_MAX, .owner = THIS_MODULE, }; static int __init nft_masq_module_init_inet(void) { return nft_register_expr(&nft_masq_inet_type); } static void nft_masq_module_exit_inet(void) { nft_unregister_expr(&nft_masq_inet_type); } #else static inline int nft_masq_module_init_inet(void) { return 0; } static inline void nft_masq_module_exit_inet(void) {} #endif |
a9ce849e7 netfilter: nf_tab... |
256 257 258 259 260 261 262 |
static int __init nft_masq_module_init(void) { int ret; ret = nft_masq_module_init_ipv6(); if (ret < 0) return ret; |
071657d2c netfilter: nft_ma... |
263 264 265 266 267 |
ret = nft_masq_module_init_inet(); if (ret < 0) { nft_masq_module_exit_ipv6(); return ret; } |
a9ce849e7 netfilter: nf_tab... |
268 269 |
ret = nft_register_expr(&nft_masq_ipv4_type); if (ret < 0) { |
071657d2c netfilter: nft_ma... |
270 |
nft_masq_module_exit_inet(); |
a9ce849e7 netfilter: nf_tab... |
271 272 273 |
nft_masq_module_exit_ipv6(); return ret; } |
610a43149 netfilter: nf_nat... |
274 |
ret = nf_nat_masquerade_inet_register_notifiers(); |
a9ce849e7 netfilter: nf_tab... |
275 276 |
if (ret < 0) { nft_masq_module_exit_ipv6(); |
071657d2c netfilter: nft_ma... |
277 |
nft_masq_module_exit_inet(); |
a9ce849e7 netfilter: nf_tab... |
278 279 280 281 282 283 284 285 286 287 |
nft_unregister_expr(&nft_masq_ipv4_type); return ret; } return ret; } static void __exit nft_masq_module_exit(void) { nft_masq_module_exit_ipv6(); |
071657d2c netfilter: nft_ma... |
288 |
nft_masq_module_exit_inet(); |
a9ce849e7 netfilter: nf_tab... |
289 |
nft_unregister_expr(&nft_masq_ipv4_type); |
610a43149 netfilter: nf_nat... |
290 |
nf_nat_masquerade_inet_unregister_notifiers(); |
a9ce849e7 netfilter: nf_tab... |
291 292 293 294 |
} module_init(nft_masq_module_init); module_exit(nft_masq_module_exit); |
9ba1f726b netfilter: nf_tab... |
295 296 |
MODULE_LICENSE("GPL"); |
cd7275146 netfilter: update... |
297 |
MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>"); |
5142967ab netfilter: nf_tab... |
298 |
MODULE_ALIAS_NFT_EXPR("masq"); |