|
@@ -73,6 +73,8 @@ void nf_conntrack_unregister_notifier(struct net *net,
|
|
struct nf_ct_event_notifier *nb);
|
|
struct nf_ct_event_notifier *nb);
|
|
|
|
|
|
void nf_ct_deliver_cached_events(struct nf_conn *ct);
|
|
void nf_ct_deliver_cached_events(struct nf_conn *ct);
|
|
|
|
+int nf_conntrack_eventmask_report(unsigned int eventmask, struct nf_conn *ct,
|
|
|
|
+ u32 portid, int report);
|
|
|
|
|
|
static inline void
|
|
static inline void
|
|
nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct)
|
|
nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct)
|
|
@@ -90,70 +92,26 @@ nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct)
|
|
set_bit(event, &e->cache);
|
|
set_bit(event, &e->cache);
|
|
}
|
|
}
|
|
|
|
|
|
-static inline int
|
|
|
|
-nf_conntrack_eventmask_report(unsigned int eventmask,
|
|
|
|
- struct nf_conn *ct,
|
|
|
|
- u32 portid,
|
|
|
|
- int report)
|
|
|
|
-{
|
|
|
|
- int ret = 0;
|
|
|
|
- struct net *net = nf_ct_net(ct);
|
|
|
|
- struct nf_ct_event_notifier *notify;
|
|
|
|
- struct nf_conntrack_ecache *e;
|
|
|
|
-
|
|
|
|
- rcu_read_lock();
|
|
|
|
- notify = rcu_dereference(net->ct.nf_conntrack_event_cb);
|
|
|
|
- if (notify == NULL)
|
|
|
|
- goto out_unlock;
|
|
|
|
-
|
|
|
|
- e = nf_ct_ecache_find(ct);
|
|
|
|
- if (e == NULL)
|
|
|
|
- goto out_unlock;
|
|
|
|
-
|
|
|
|
- if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) {
|
|
|
|
- struct nf_ct_event item = {
|
|
|
|
- .ct = ct,
|
|
|
|
- .portid = e->portid ? e->portid : portid,
|
|
|
|
- .report = report
|
|
|
|
- };
|
|
|
|
- /* This is a resent of a destroy event? If so, skip missed */
|
|
|
|
- unsigned long missed = e->portid ? 0 : e->missed;
|
|
|
|
-
|
|
|
|
- if (!((eventmask | missed) & e->ctmask))
|
|
|
|
- goto out_unlock;
|
|
|
|
-
|
|
|
|
- ret = notify->fcn(eventmask | missed, &item);
|
|
|
|
- if (unlikely(ret < 0 || missed)) {
|
|
|
|
- spin_lock_bh(&ct->lock);
|
|
|
|
- if (ret < 0) {
|
|
|
|
- /* This is a destroy event that has been
|
|
|
|
- * triggered by a process, we store the PORTID
|
|
|
|
- * to include it in the retransmission. */
|
|
|
|
- if (eventmask & (1 << IPCT_DESTROY) &&
|
|
|
|
- e->portid == 0 && portid != 0)
|
|
|
|
- e->portid = portid;
|
|
|
|
- else
|
|
|
|
- e->missed |= eventmask;
|
|
|
|
- } else
|
|
|
|
- e->missed &= ~missed;
|
|
|
|
- spin_unlock_bh(&ct->lock);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-out_unlock:
|
|
|
|
- rcu_read_unlock();
|
|
|
|
- return ret;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static inline int
|
|
static inline int
|
|
nf_conntrack_event_report(enum ip_conntrack_events event, struct nf_conn *ct,
|
|
nf_conntrack_event_report(enum ip_conntrack_events event, struct nf_conn *ct,
|
|
u32 portid, int report)
|
|
u32 portid, int report)
|
|
{
|
|
{
|
|
|
|
+ const struct net *net = nf_ct_net(ct);
|
|
|
|
+
|
|
|
|
+ if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb))
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
return nf_conntrack_eventmask_report(1 << event, ct, portid, report);
|
|
return nf_conntrack_eventmask_report(1 << event, ct, portid, report);
|
|
}
|
|
}
|
|
|
|
|
|
static inline int
|
|
static inline int
|
|
nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct)
|
|
nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct)
|
|
{
|
|
{
|
|
|
|
+ const struct net *net = nf_ct_net(ct);
|
|
|
|
+
|
|
|
|
+ if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb))
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
return nf_conntrack_eventmask_report(1 << event, ct, 0, 0);
|
|
return nf_conntrack_eventmask_report(1 << event, ct, 0, 0);
|
|
}
|
|
}
|
|
|
|
|