@@ -281,6 +281,16 @@ nf_hook_entry_head(struct net *net, int pf, unsigned int hooknum,
281281 if (WARN_ON_ONCE (ARRAY_SIZE (net -> nf .hooks_bridge ) <= hooknum ))
282282 return NULL ;
283283 return net -> nf .hooks_bridge + hooknum ;
284+ #endif
285+ #ifdef CONFIG_NETFILTER_INGRESS
286+ case NFPROTO_INET :
287+ if (WARN_ON_ONCE (hooknum != NF_INET_INGRESS ))
288+ return NULL ;
289+ if (!dev || dev_net (dev ) != net ) {
290+ WARN_ON_ONCE (1 );
291+ return NULL ;
292+ }
293+ return & dev -> nf_hooks_ingress ;
284294#endif
285295 case NFPROTO_IPV4 :
286296 if (WARN_ON_ONCE (ARRAY_SIZE (net -> nf .hooks_ipv4 ) <= hooknum ))
@@ -311,20 +321,80 @@ nf_hook_entry_head(struct net *net, int pf, unsigned int hooknum,
311321 return NULL ;
312322}
313323
324+ static int nf_ingress_check (struct net * net , const struct nf_hook_ops * reg ,
325+ int hooknum )
326+ {
327+ #ifndef CONFIG_NETFILTER_INGRESS
328+ if (reg -> hooknum == hooknum )
329+ return - EOPNOTSUPP ;
330+ #endif
331+ if (reg -> hooknum != hooknum ||
332+ !reg -> dev || dev_net (reg -> dev ) != net )
333+ return - EINVAL ;
334+
335+ return 0 ;
336+ }
337+
338+ static inline bool nf_ingress_hook (const struct nf_hook_ops * reg , int pf )
339+ {
340+ if ((pf == NFPROTO_NETDEV && reg -> hooknum == NF_NETDEV_INGRESS ) ||
341+ (pf == NFPROTO_INET && reg -> hooknum == NF_INET_INGRESS ))
342+ return true;
343+
344+ return false;
345+ }
346+
347+ static void nf_static_key_inc (const struct nf_hook_ops * reg , int pf )
348+ {
349+ #ifdef CONFIG_JUMP_LABEL
350+ int hooknum ;
351+
352+ if (pf == NFPROTO_INET && reg -> hooknum == NF_INET_INGRESS ) {
353+ pf = NFPROTO_NETDEV ;
354+ hooknum = NF_NETDEV_INGRESS ;
355+ } else {
356+ hooknum = reg -> hooknum ;
357+ }
358+ static_key_slow_inc (& nf_hooks_needed [pf ][hooknum ]);
359+ #endif
360+ }
361+
362+ static void nf_static_key_dec (const struct nf_hook_ops * reg , int pf )
363+ {
364+ #ifdef CONFIG_JUMP_LABEL
365+ int hooknum ;
366+
367+ if (pf == NFPROTO_INET && reg -> hooknum == NF_INET_INGRESS ) {
368+ pf = NFPROTO_NETDEV ;
369+ hooknum = NF_NETDEV_INGRESS ;
370+ } else {
371+ hooknum = reg -> hooknum ;
372+ }
373+ static_key_slow_dec (& nf_hooks_needed [pf ][hooknum ]);
374+ #endif
375+ }
376+
314377static int __nf_register_net_hook (struct net * net , int pf ,
315378 const struct nf_hook_ops * reg )
316379{
317380 struct nf_hook_entries * p , * new_hooks ;
318381 struct nf_hook_entries __rcu * * pp ;
382+ int err ;
319383
320- if (pf == NFPROTO_NETDEV ) {
321- #ifndef CONFIG_NETFILTER_INGRESS
322- if (reg -> hooknum == NF_NETDEV_INGRESS )
323- return - EOPNOTSUPP ;
324- #endif
325- if (reg -> hooknum != NF_NETDEV_INGRESS ||
326- !reg -> dev || dev_net (reg -> dev ) != net )
327- return - EINVAL ;
384+ switch (pf ) {
385+ case NFPROTO_NETDEV :
386+ err = nf_ingress_check (net , reg , NF_NETDEV_INGRESS );
387+ if (err < 0 )
388+ return err ;
389+ break ;
390+ case NFPROTO_INET :
391+ if (reg -> hooknum != NF_INET_INGRESS )
392+ break ;
393+
394+ err = nf_ingress_check (net , reg , NF_INET_INGRESS );
395+ if (err < 0 )
396+ return err ;
397+ break ;
328398 }
329399
330400 pp = nf_hook_entry_head (net , pf , reg -> hooknum , reg -> dev );
@@ -345,12 +415,11 @@ static int __nf_register_net_hook(struct net *net, int pf,
345415
346416 hooks_validate (new_hooks );
347417#ifdef CONFIG_NETFILTER_INGRESS
348- if (pf == NFPROTO_NETDEV && reg -> hooknum == NF_NETDEV_INGRESS )
418+ if (nf_ingress_hook ( reg , pf ) )
349419 net_inc_ingress_queue ();
350420#endif
351- #ifdef CONFIG_JUMP_LABEL
352- static_key_slow_inc (& nf_hooks_needed [pf ][reg -> hooknum ]);
353- #endif
421+ nf_static_key_inc (reg , pf );
422+
354423 BUG_ON (p == new_hooks );
355424 nf_hook_entries_free (p );
356425 return 0 ;
@@ -403,12 +472,10 @@ static void __nf_unregister_net_hook(struct net *net, int pf,
403472
404473 if (nf_remove_net_hook (p , reg )) {
405474#ifdef CONFIG_NETFILTER_INGRESS
406- if (pf == NFPROTO_NETDEV && reg -> hooknum == NF_NETDEV_INGRESS )
475+ if (nf_ingress_hook ( reg , pf ) )
407476 net_dec_ingress_queue ();
408477#endif
409- #ifdef CONFIG_JUMP_LABEL
410- static_key_slow_dec (& nf_hooks_needed [pf ][reg -> hooknum ]);
411- #endif
478+ nf_static_key_dec (reg , pf );
412479 } else {
413480 WARN_ONCE (1 , "hook not found, pf %d num %d" , pf , reg -> hooknum );
414481 }
@@ -425,8 +492,12 @@ static void __nf_unregister_net_hook(struct net *net, int pf,
425492void nf_unregister_net_hook (struct net * net , const struct nf_hook_ops * reg )
426493{
427494 if (reg -> pf == NFPROTO_INET ) {
428- __nf_unregister_net_hook (net , NFPROTO_IPV4 , reg );
429- __nf_unregister_net_hook (net , NFPROTO_IPV6 , reg );
495+ if (reg -> hooknum == NF_INET_INGRESS ) {
496+ __nf_unregister_net_hook (net , NFPROTO_INET , reg );
497+ } else {
498+ __nf_unregister_net_hook (net , NFPROTO_IPV4 , reg );
499+ __nf_unregister_net_hook (net , NFPROTO_IPV6 , reg );
500+ }
430501 } else {
431502 __nf_unregister_net_hook (net , reg -> pf , reg );
432503 }
@@ -451,14 +522,20 @@ int nf_register_net_hook(struct net *net, const struct nf_hook_ops *reg)
451522 int err ;
452523
453524 if (reg -> pf == NFPROTO_INET ) {
454- err = __nf_register_net_hook (net , NFPROTO_IPV4 , reg );
455- if (err < 0 )
456- return err ;
457-
458- err = __nf_register_net_hook (net , NFPROTO_IPV6 , reg );
459- if (err < 0 ) {
460- __nf_unregister_net_hook (net , NFPROTO_IPV4 , reg );
461- return err ;
525+ if (reg -> hooknum == NF_INET_INGRESS ) {
526+ err = __nf_register_net_hook (net , NFPROTO_INET , reg );
527+ if (err < 0 )
528+ return err ;
529+ } else {
530+ err = __nf_register_net_hook (net , NFPROTO_IPV4 , reg );
531+ if (err < 0 )
532+ return err ;
533+
534+ err = __nf_register_net_hook (net , NFPROTO_IPV6 , reg );
535+ if (err < 0 ) {
536+ __nf_unregister_net_hook (net , NFPROTO_IPV4 , reg );
537+ return err ;
538+ }
462539 }
463540 } else {
464541 err = __nf_register_net_hook (net , reg -> pf , reg );
0 commit comments