linux/include/net/netfilter/nf_conntrack_ecache.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2/*
   3 * connection tracking event cache.
   4 */
   5
   6#ifndef _NF_CONNTRACK_ECACHE_H
   7#define _NF_CONNTRACK_ECACHE_H
   8#include <net/netfilter/nf_conntrack.h>
   9
  10#include <net/net_namespace.h>
  11#include <net/netfilter/nf_conntrack_expect.h>
  12#include <linux/netfilter/nf_conntrack_common.h>
  13#include <linux/netfilter/nf_conntrack_tuple_common.h>
  14#include <net/netfilter/nf_conntrack_extend.h>
  15
  16enum nf_ct_ecache_state {
  17        NFCT_ECACHE_UNKNOWN,            /* destroy event not sent */
  18        NFCT_ECACHE_DESTROY_FAIL,       /* tried but failed to send destroy event */
  19        NFCT_ECACHE_DESTROY_SENT,       /* sent destroy event after failure */
  20};
  21
  22struct nf_conntrack_ecache {
  23        unsigned long cache;            /* bitops want long */
  24        u16 missed;                     /* missed events */
  25        u16 ctmask;                     /* bitmask of ct events to be delivered */
  26        u16 expmask;                    /* bitmask of expect events to be delivered */
  27        enum nf_ct_ecache_state state:8;/* ecache state */
  28        u32 portid;                     /* netlink portid of destroyer */
  29};
  30
  31static inline struct nf_conntrack_ecache *
  32nf_ct_ecache_find(const struct nf_conn *ct)
  33{
  34#ifdef CONFIG_NF_CONNTRACK_EVENTS
  35        return nf_ct_ext_find(ct, NF_CT_EXT_ECACHE);
  36#else
  37        return NULL;
  38#endif
  39}
  40
  41static inline struct nf_conntrack_ecache *
  42nf_ct_ecache_ext_add(struct nf_conn *ct, u16 ctmask, u16 expmask, gfp_t gfp)
  43{
  44#ifdef CONFIG_NF_CONNTRACK_EVENTS
  45        struct net *net = nf_ct_net(ct);
  46        struct nf_conntrack_ecache *e;
  47
  48        if (!ctmask && !expmask && net->ct.sysctl_events) {
  49                ctmask = ~0;
  50                expmask = ~0;
  51        }
  52        if (!ctmask && !expmask)
  53                return NULL;
  54
  55        e = nf_ct_ext_add(ct, NF_CT_EXT_ECACHE, gfp);
  56        if (e) {
  57                e->ctmask  = ctmask;
  58                e->expmask = expmask;
  59        }
  60        return e;
  61#else
  62        return NULL;
  63#endif
  64}
  65
  66#ifdef CONFIG_NF_CONNTRACK_EVENTS
  67
  68/* This structure is passed to event handler */
  69struct nf_ct_event {
  70        struct nf_conn *ct;
  71        u32 portid;
  72        int report;
  73};
  74
  75struct nf_ct_event_notifier {
  76        int (*fcn)(unsigned int events, struct nf_ct_event *item);
  77};
  78
  79int nf_conntrack_register_notifier(struct net *net,
  80                                   struct nf_ct_event_notifier *nb);
  81void nf_conntrack_unregister_notifier(struct net *net,
  82                                      struct nf_ct_event_notifier *nb);
  83
  84void nf_ct_deliver_cached_events(struct nf_conn *ct);
  85int nf_conntrack_eventmask_report(unsigned int eventmask, struct nf_conn *ct,
  86                                  u32 portid, int report);
  87
  88#else
  89
  90static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct)
  91{
  92}
  93
  94static inline int nf_conntrack_eventmask_report(unsigned int eventmask,
  95                                                struct nf_conn *ct,
  96                                                u32 portid,
  97                                                int report)
  98{
  99        return 0;
 100}
 101
 102#endif
 103
 104static inline void
 105nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct)
 106{
 107#ifdef CONFIG_NF_CONNTRACK_EVENTS
 108        struct net *net = nf_ct_net(ct);
 109        struct nf_conntrack_ecache *e;
 110
 111        if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb))
 112                return;
 113
 114        e = nf_ct_ecache_find(ct);
 115        if (e == NULL)
 116                return;
 117
 118        set_bit(event, &e->cache);
 119#endif
 120}
 121
 122static inline int
 123nf_conntrack_event_report(enum ip_conntrack_events event, struct nf_conn *ct,
 124                          u32 portid, int report)
 125{
 126#ifdef CONFIG_NF_CONNTRACK_EVENTS
 127        const struct net *net = nf_ct_net(ct);
 128
 129        if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb))
 130                return 0;
 131
 132        return nf_conntrack_eventmask_report(1 << event, ct, portid, report);
 133#else
 134        return 0;
 135#endif
 136}
 137
 138static inline int
 139nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct)
 140{
 141#ifdef CONFIG_NF_CONNTRACK_EVENTS
 142        const struct net *net = nf_ct_net(ct);
 143
 144        if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb))
 145                return 0;
 146
 147        return nf_conntrack_eventmask_report(1 << event, ct, 0, 0);
 148#else
 149        return 0;
 150#endif
 151}
 152
 153#ifdef CONFIG_NF_CONNTRACK_EVENTS
 154
 155struct nf_exp_event {
 156        struct nf_conntrack_expect *exp;
 157        u32 portid;
 158        int report;
 159};
 160
 161struct nf_exp_event_notifier {
 162        int (*fcn)(unsigned int events, struct nf_exp_event *item);
 163};
 164
 165int nf_ct_expect_register_notifier(struct net *net,
 166                                   struct nf_exp_event_notifier *nb);
 167void nf_ct_expect_unregister_notifier(struct net *net,
 168                                      struct nf_exp_event_notifier *nb);
 169
 170void nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
 171                               struct nf_conntrack_expect *exp,
 172                               u32 portid, int report);
 173
 174void nf_conntrack_ecache_pernet_init(struct net *net);
 175void nf_conntrack_ecache_pernet_fini(struct net *net);
 176
 177int nf_conntrack_ecache_init(void);
 178void nf_conntrack_ecache_fini(void);
 179
 180#else /* CONFIG_NF_CONNTRACK_EVENTS */
 181
 182static inline void nf_ct_expect_event_report(enum ip_conntrack_expect_events e,
 183                                             struct nf_conntrack_expect *exp,
 184                                             u32 portid,
 185                                             int report)
 186{
 187}
 188
 189static inline void nf_conntrack_ecache_pernet_init(struct net *net)
 190{
 191}
 192
 193static inline void nf_conntrack_ecache_pernet_fini(struct net *net)
 194{
 195}
 196
 197static inline int nf_conntrack_ecache_init(void)
 198{
 199        return 0;
 200}
 201
 202static inline void nf_conntrack_ecache_fini(void)
 203{
 204}
 205
 206#endif /* CONFIG_NF_CONNTRACK_EVENTS */
 207
 208static inline void nf_conntrack_ecache_delayed_work(struct net *net)
 209{
 210#ifdef CONFIG_NF_CONNTRACK_EVENTS
 211        if (!delayed_work_pending(&net->ct.ecache_dwork)) {
 212                schedule_delayed_work(&net->ct.ecache_dwork, HZ);
 213                net->ct.ecache_dwork_pending = true;
 214        }
 215#endif
 216}
 217
 218static inline void nf_conntrack_ecache_work(struct net *net)
 219{
 220#ifdef CONFIG_NF_CONNTRACK_EVENTS
 221        if (net->ct.ecache_dwork_pending) {
 222                net->ct.ecache_dwork_pending = false;
 223                mod_delayed_work(system_wq, &net->ct.ecache_dwork, 0);
 224        }
 225#endif
 226}
 227
 228#endif /*_NF_CONNTRACK_ECACHE_H*/
 229