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

netfilter: core: support for NFPROTO_INET hook registration

Expand NFPROTO_INET in two hook registrations, one for NFPROTO_IPV4 and
another for NFPROTO_IPV6. Hence, we handle NFPROTO_INET from the core.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

+44 -9
+44 -9
net/netfilter/core.c
··· 316 316 return NULL; 317 317 } 318 318 319 - int nf_register_net_hook(struct net *net, const struct nf_hook_ops *reg) 319 + static int __nf_register_net_hook(struct net *net, int pf, 320 + const struct nf_hook_ops *reg) 320 321 { 321 322 struct nf_hook_entries *p, *new_hooks; 322 323 struct nf_hook_entries __rcu **pp; 323 324 324 - if (reg->pf == NFPROTO_NETDEV) { 325 + if (pf == NFPROTO_NETDEV) { 325 326 #ifndef CONFIG_NETFILTER_INGRESS 326 327 if (reg->hooknum == NF_NETDEV_INGRESS) 327 328 return -EOPNOTSUPP; ··· 332 331 return -EINVAL; 333 332 } 334 333 335 - pp = nf_hook_entry_head(net, reg->pf, reg->hooknum, reg->dev); 334 + pp = nf_hook_entry_head(net, pf, reg->hooknum, reg->dev); 336 335 if (!pp) 337 336 return -EINVAL; 338 337 ··· 350 349 351 350 hooks_validate(new_hooks); 352 351 #ifdef CONFIG_NETFILTER_INGRESS 353 - if (reg->pf == NFPROTO_NETDEV && reg->hooknum == NF_NETDEV_INGRESS) 352 + if (pf == NFPROTO_NETDEV && reg->hooknum == NF_NETDEV_INGRESS) 354 353 net_inc_ingress_queue(); 355 354 #endif 356 355 #ifdef HAVE_JUMP_LABEL 357 - static_key_slow_inc(&nf_hooks_needed[reg->pf][reg->hooknum]); 356 + static_key_slow_inc(&nf_hooks_needed[pf][reg->hooknum]); 358 357 #endif 359 358 BUG_ON(p == new_hooks); 360 359 nf_hook_entries_free(p); 361 360 return 0; 362 361 } 363 - EXPORT_SYMBOL(nf_register_net_hook); 364 362 365 363 /* 366 364 * nf_remove_net_hook - remove a hook from blob ··· 400 400 } 401 401 } 402 402 403 - void nf_unregister_net_hook(struct net *net, const struct nf_hook_ops *reg) 403 + void __nf_unregister_net_hook(struct net *net, int pf, 404 + const struct nf_hook_ops *reg) 404 405 { 405 406 struct nf_hook_entries __rcu **pp; 406 407 struct nf_hook_entries *p; 407 408 408 - pp = nf_hook_entry_head(net, reg->pf, reg->hooknum, reg->dev); 409 + pp = nf_hook_entry_head(net, pf, reg->hooknum, reg->dev); 409 410 if (!pp) 410 411 return; 411 412 ··· 418 417 return; 419 418 } 420 419 421 - nf_remove_net_hook(p, reg, reg->pf); 420 + nf_remove_net_hook(p, reg, pf); 422 421 423 422 p = __nf_hook_entries_try_shrink(pp); 424 423 mutex_unlock(&nf_hook_mutex); ··· 428 427 nf_queue_nf_hook_drop(net); 429 428 nf_hook_entries_free(p); 430 429 } 430 + 431 + void nf_unregister_net_hook(struct net *net, const struct nf_hook_ops *reg) 432 + { 433 + if (reg->pf == NFPROTO_INET) { 434 + __nf_unregister_net_hook(net, NFPROTO_IPV4, reg); 435 + __nf_unregister_net_hook(net, NFPROTO_IPV6, reg); 436 + } else { 437 + __nf_unregister_net_hook(net, reg->pf, reg); 438 + } 439 + } 431 440 EXPORT_SYMBOL(nf_unregister_net_hook); 441 + 442 + int nf_register_net_hook(struct net *net, const struct nf_hook_ops *reg) 443 + { 444 + int err; 445 + 446 + if (reg->pf == NFPROTO_INET) { 447 + err = __nf_register_net_hook(net, NFPROTO_IPV4, reg); 448 + if (err < 0) 449 + return err; 450 + 451 + err = __nf_register_net_hook(net, NFPROTO_IPV6, reg); 452 + if (err < 0) { 453 + __nf_unregister_net_hook(net, NFPROTO_IPV4, reg); 454 + return err; 455 + } 456 + } else { 457 + err = __nf_register_net_hook(net, reg->pf, reg); 458 + if (err < 0) 459 + return err; 460 + } 461 + 462 + return 0; 463 + } 464 + EXPORT_SYMBOL(nf_register_net_hook); 432 465 433 466 int nf_register_net_hooks(struct net *net, const struct nf_hook_ops *reg, 434 467 unsigned int n)