Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: nft_synproxy: add synproxy stateful object support

Register a new synproxy stateful object type into the stateful object
infrastructure.

Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Fernando Fernandez Mancera and committed by
Pablo Neira Ayuso
ee394f96 3474a2c6

+124 -22
+2 -1
include/uapi/linux/netfilter/nf_tables.h
··· 1481 1481 #define NFT_OBJECT_CT_TIMEOUT 7 1482 1482 #define NFT_OBJECT_SECMARK 8 1483 1483 #define NFT_OBJECT_CT_EXPECT 9 1484 - #define __NFT_OBJECT_MAX 10 1484 + #define NFT_OBJECT_SYNPROXY 10 1485 + #define __NFT_OBJECT_MAX 11 1485 1486 #define NFT_OBJECT_MAX (__NFT_OBJECT_MAX - 1) 1486 1487 1487 1488 /**
+122 -21
net/netfilter/nft_synproxy.c
··· 24 24 const struct tcphdr *tcp, 25 25 struct synproxy_net *snet, 26 26 struct nf_synproxy_info *info, 27 - struct nft_synproxy *priv) 27 + const struct nft_synproxy *priv) 28 28 { 29 29 this_cpu_inc(snet->stats->syn_received); 30 30 if (tcp->ece && tcp->cwr) ··· 41 41 NF_SYNPROXY_OPT_ECN); 42 42 } 43 43 44 - static void nft_synproxy_eval_v4(const struct nft_expr *expr, 44 + static void nft_synproxy_eval_v4(const struct nft_synproxy *priv, 45 45 struct nft_regs *regs, 46 46 const struct nft_pktinfo *pkt, 47 47 const struct tcphdr *tcp, 48 48 struct tcphdr *_tcph, 49 49 struct synproxy_options *opts) 50 50 { 51 - struct nft_synproxy *priv = nft_expr_priv(expr); 52 51 struct nf_synproxy_info info = priv->info; 53 52 struct net *net = nft_net(pkt); 54 53 struct synproxy_net *snet = synproxy_pernet(net); ··· 72 73 } 73 74 74 75 #if IS_ENABLED(CONFIG_NF_TABLES_IPV6) 75 - static void nft_synproxy_eval_v6(const struct nft_expr *expr, 76 + static void nft_synproxy_eval_v6(const struct nft_synproxy *priv, 76 77 struct nft_regs *regs, 77 78 const struct nft_pktinfo *pkt, 78 79 const struct tcphdr *tcp, 79 80 struct tcphdr *_tcph, 80 81 struct synproxy_options *opts) 81 82 { 82 - struct nft_synproxy *priv = nft_expr_priv(expr); 83 83 struct nf_synproxy_info info = priv->info; 84 84 struct net *net = nft_net(pkt); 85 85 struct synproxy_net *snet = synproxy_pernet(net); ··· 103 105 } 104 106 #endif /* CONFIG_NF_TABLES_IPV6*/ 105 107 106 - static void nft_synproxy_eval(const struct nft_expr *expr, 107 - struct nft_regs *regs, 108 - const struct nft_pktinfo *pkt) 108 + static void nft_synproxy_do_eval(const struct nft_synproxy *priv, 109 + struct nft_regs *regs, 110 + const struct nft_pktinfo *pkt) 109 111 { 110 112 struct synproxy_options opts = {}; 111 113 struct sk_buff *skb = pkt->skb; ··· 138 140 139 141 switch (skb->protocol) { 140 142 case htons(ETH_P_IP): 141 - nft_synproxy_eval_v4(expr, regs, pkt, tcp, &_tcph, &opts); 143 + nft_synproxy_eval_v4(priv, regs, pkt, tcp, &_tcph, &opts); 142 144 return; 143 145 #if IS_ENABLED(CONFIG_NF_TABLES_IPV6) 144 146 case htons(ETH_P_IPV6): 145 - nft_synproxy_eval_v6(expr, regs, pkt, tcp, &_tcph, &opts); 147 + nft_synproxy_eval_v6(priv, regs, pkt, tcp, &_tcph, &opts); 146 148 return; 147 149 #endif 148 150 } 149 151 regs->verdict.code = NFT_BREAK; 150 152 } 151 153 152 - static int nft_synproxy_init(const struct nft_ctx *ctx, 153 - const struct nft_expr *expr, 154 - const struct nlattr * const tb[]) 154 + static int nft_synproxy_do_init(const struct nft_ctx *ctx, 155 + const struct nlattr * const tb[], 156 + struct nft_synproxy *priv) 155 157 { 156 158 struct synproxy_net *snet = synproxy_pernet(ctx->net); 157 - struct nft_synproxy *priv = nft_expr_priv(expr); 158 159 u32 flags; 159 160 int err; 160 161 ··· 203 206 return err; 204 207 } 205 208 206 - static void nft_synproxy_destroy(const struct nft_ctx *ctx, 207 - const struct nft_expr *expr) 209 + static void nft_synproxy_do_destroy(const struct nft_ctx *ctx) 208 210 { 209 211 struct synproxy_net *snet = synproxy_pernet(ctx->net); 210 212 ··· 225 229 nf_ct_netns_put(ctx->net, ctx->family); 226 230 } 227 231 228 - static int nft_synproxy_dump(struct sk_buff *skb, const struct nft_expr *expr) 232 + static int nft_synproxy_do_dump(struct sk_buff *skb, struct nft_synproxy *priv) 229 233 { 230 - const struct nft_synproxy *priv = nft_expr_priv(expr); 231 - 232 234 if (nla_put_be16(skb, NFTA_SYNPROXY_MSS, htons(priv->info.mss)) || 233 235 nla_put_u8(skb, NFTA_SYNPROXY_WSCALE, priv->info.wscale) || 234 236 nla_put_be32(skb, NFTA_SYNPROXY_FLAGS, htonl(priv->info.options))) ··· 238 244 return -1; 239 245 } 240 246 247 + static void nft_synproxy_eval(const struct nft_expr *expr, 248 + struct nft_regs *regs, 249 + const struct nft_pktinfo *pkt) 250 + { 251 + const struct nft_synproxy *priv = nft_expr_priv(expr); 252 + 253 + nft_synproxy_do_eval(priv, regs, pkt); 254 + } 255 + 241 256 static int nft_synproxy_validate(const struct nft_ctx *ctx, 242 257 const struct nft_expr *expr, 243 258 const struct nft_data **data) 244 259 { 245 260 return nft_chain_validate_hooks(ctx->chain, (1 << NF_INET_LOCAL_IN) | 246 261 (1 << NF_INET_FORWARD)); 262 + } 263 + 264 + static int nft_synproxy_init(const struct nft_ctx *ctx, 265 + const struct nft_expr *expr, 266 + const struct nlattr * const tb[]) 267 + { 268 + struct nft_synproxy *priv = nft_expr_priv(expr); 269 + 270 + return nft_synproxy_do_init(ctx, tb, priv); 271 + } 272 + 273 + static void nft_synproxy_destroy(const struct nft_ctx *ctx, 274 + const struct nft_expr *expr) 275 + { 276 + nft_synproxy_do_destroy(ctx); 277 + } 278 + 279 + static int nft_synproxy_dump(struct sk_buff *skb, const struct nft_expr *expr) 280 + { 281 + struct nft_synproxy *priv = nft_expr_priv(expr); 282 + 283 + return nft_synproxy_do_dump(skb, priv); 247 284 } 248 285 249 286 static struct nft_expr_type nft_synproxy_type; ··· 296 271 .maxattr = NFTA_SYNPROXY_MAX, 297 272 }; 298 273 274 + static int nft_synproxy_obj_init(const struct nft_ctx *ctx, 275 + const struct nlattr * const tb[], 276 + struct nft_object *obj) 277 + { 278 + struct nft_synproxy *priv = nft_obj_data(obj); 279 + 280 + return nft_synproxy_do_init(ctx, tb, priv); 281 + } 282 + 283 + static void nft_synproxy_obj_destroy(const struct nft_ctx *ctx, 284 + struct nft_object *obj) 285 + { 286 + nft_synproxy_do_destroy(ctx); 287 + } 288 + 289 + static int nft_synproxy_obj_dump(struct sk_buff *skb, 290 + struct nft_object *obj, bool reset) 291 + { 292 + struct nft_synproxy *priv = nft_obj_data(obj); 293 + 294 + return nft_synproxy_do_dump(skb, priv); 295 + } 296 + 297 + static void nft_synproxy_obj_eval(struct nft_object *obj, 298 + struct nft_regs *regs, 299 + const struct nft_pktinfo *pkt) 300 + { 301 + const struct nft_synproxy *priv = nft_obj_data(obj); 302 + 303 + nft_synproxy_do_eval(priv, regs, pkt); 304 + } 305 + 306 + static void nft_synproxy_obj_update(struct nft_object *obj, 307 + struct nft_object *newobj) 308 + { 309 + struct nft_synproxy *newpriv = nft_obj_data(newobj); 310 + struct nft_synproxy *priv = nft_obj_data(obj); 311 + 312 + priv->info = newpriv->info; 313 + } 314 + 315 + static struct nft_object_type nft_synproxy_obj_type; 316 + static const struct nft_object_ops nft_synproxy_obj_ops = { 317 + .type = &nft_synproxy_obj_type, 318 + .size = sizeof(struct nft_synproxy), 319 + .init = nft_synproxy_obj_init, 320 + .destroy = nft_synproxy_obj_destroy, 321 + .dump = nft_synproxy_obj_dump, 322 + .eval = nft_synproxy_obj_eval, 323 + .update = nft_synproxy_obj_update, 324 + }; 325 + 326 + static struct nft_object_type nft_synproxy_obj_type __read_mostly = { 327 + .type = NFT_OBJECT_SYNPROXY, 328 + .ops = &nft_synproxy_obj_ops, 329 + .maxattr = NFTA_SYNPROXY_MAX, 330 + .policy = nft_synproxy_policy, 331 + .owner = THIS_MODULE, 332 + }; 333 + 299 334 static int __init nft_synproxy_module_init(void) 300 335 { 301 - return nft_register_expr(&nft_synproxy_type); 336 + int err; 337 + 338 + err = nft_register_obj(&nft_synproxy_obj_type); 339 + if (err < 0) 340 + return err; 341 + 342 + err = nft_register_expr(&nft_synproxy_type); 343 + if (err < 0) 344 + goto err; 345 + 346 + return 0; 347 + 348 + err: 349 + nft_unregister_obj(&nft_synproxy_obj_type); 350 + return err; 302 351 } 303 352 304 353 static void __exit nft_synproxy_module_exit(void) 305 354 { 306 - return nft_unregister_expr(&nft_synproxy_type); 355 + nft_unregister_expr(&nft_synproxy_type); 356 + nft_unregister_obj(&nft_synproxy_obj_type); 307 357 } 308 358 309 359 module_init(nft_synproxy_module_init); ··· 387 287 MODULE_LICENSE("GPL"); 388 288 MODULE_AUTHOR("Fernando Fernandez <ffmancera@riseup.net>"); 389 289 MODULE_ALIAS_NFT_EXPR("synproxy"); 290 + MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_SYNPROXY);