Loading include/linux/list_nulls.h +18 −0 Original line number Diff line number Diff line Loading @@ -56,6 +56,18 @@ static inline int hlist_nulls_empty(const struct hlist_nulls_head *h) return is_a_nulls(h->first); } static inline void hlist_nulls_add_head(struct hlist_nulls_node *n, struct hlist_nulls_head *h) { struct hlist_nulls_node *first = h->first; n->next = first; n->pprev = &h->first; h->first = n; if (!is_a_nulls(first)) first->pprev = &n->next; } static inline void __hlist_nulls_del(struct hlist_nulls_node *n) { struct hlist_nulls_node *next = n->next; Loading @@ -65,6 +77,12 @@ static inline void __hlist_nulls_del(struct hlist_nulls_node *n) next->pprev = pprev; } static inline void hlist_nulls_del(struct hlist_nulls_node *n) { __hlist_nulls_del(n); n->pprev = LIST_POISON2; } /** * hlist_nulls_for_each_entry - iterate over list of given type * @tpos: the type * to use as a loop cursor. Loading include/net/netfilter/nf_conntrack.h +2 −0 Original line number Diff line number Diff line Loading @@ -201,6 +201,8 @@ extern struct nf_conntrack_tuple_hash * __nf_conntrack_find(struct net *net, const struct nf_conntrack_tuple *tuple); extern void nf_conntrack_hash_insert(struct nf_conn *ct); extern void nf_ct_delete_from_lists(struct nf_conn *ct); extern void nf_ct_insert_dying_list(struct nf_conn *ct); extern void nf_conntrack_flush_report(struct net *net, u32 pid, int report); Loading include/net/netfilter/nf_conntrack_ecache.h +105 −70 Original line number Diff line number Diff line Loading @@ -6,61 +6,54 @@ #define _NF_CONNTRACK_ECACHE_H #include <net/netfilter/nf_conntrack.h> #include <linux/interrupt.h> #include <net/net_namespace.h> #include <net/netfilter/nf_conntrack_expect.h> #include <linux/netfilter/nf_conntrack_common.h> #include <linux/netfilter/nf_conntrack_tuple_common.h> #include <net/netfilter/nf_conntrack_extend.h> /* Connection tracking event bits */ /* Connection tracking event types */ enum ip_conntrack_events { /* New conntrack */ IPCT_NEW_BIT = 0, IPCT_NEW = (1 << IPCT_NEW_BIT), /* Expected connection */ IPCT_RELATED_BIT = 1, IPCT_RELATED = (1 << IPCT_RELATED_BIT), /* Destroyed conntrack */ IPCT_DESTROY_BIT = 2, IPCT_DESTROY = (1 << IPCT_DESTROY_BIT), /* Status has changed */ IPCT_STATUS_BIT = 3, IPCT_STATUS = (1 << IPCT_STATUS_BIT), IPCT_NEW = 0, /* new conntrack */ IPCT_RELATED = 1, /* related conntrack */ IPCT_DESTROY = 2, /* destroyed conntrack */ IPCT_STATUS = 3, /* status has changed */ IPCT_PROTOINFO = 4, /* protocol information has changed */ IPCT_HELPER = 5, /* new helper has been set */ IPCT_MARK = 6, /* new mark has been set */ IPCT_NATSEQADJ = 7, /* NAT is doing sequence adjustment */ IPCT_SECMARK = 8, /* new security mark has been set */ }; /* Update of protocol info */ IPCT_PROTOINFO_BIT = 4, IPCT_PROTOINFO = (1 << IPCT_PROTOINFO_BIT), enum ip_conntrack_expect_events { IPEXP_NEW = 0, /* new expectation */ }; /* New helper for conntrack */ IPCT_HELPER_BIT = 5, IPCT_HELPER = (1 << IPCT_HELPER_BIT), struct nf_conntrack_ecache { unsigned long cache; /* bitops want long */ unsigned long missed; /* missed events */ u32 pid; /* netlink pid of destroyer */ }; /* Mark is set */ IPCT_MARK_BIT = 6, IPCT_MARK = (1 << IPCT_MARK_BIT), static inline struct nf_conntrack_ecache * nf_ct_ecache_find(const struct nf_conn *ct) { return nf_ct_ext_find(ct, NF_CT_EXT_ECACHE); } /* NAT sequence adjustment */ IPCT_NATSEQADJ_BIT = 7, IPCT_NATSEQADJ = (1 << IPCT_NATSEQADJ_BIT), static inline struct nf_conntrack_ecache * nf_ct_ecache_ext_add(struct nf_conn *ct, gfp_t gfp) { struct net *net = nf_ct_net(ct); /* Secmark is set */ IPCT_SECMARK_BIT = 8, IPCT_SECMARK = (1 << IPCT_SECMARK_BIT), }; if (!net->ct.sysctl_events) return NULL; enum ip_conntrack_expect_events { IPEXP_NEW_BIT = 0, IPEXP_NEW = (1 << IPEXP_NEW_BIT), return nf_ct_ext_add(ct, NF_CT_EXT_ECACHE, gfp); }; #ifdef CONFIG_NF_CONNTRACK_EVENTS struct nf_conntrack_ecache { struct nf_conn *ct; unsigned int events; }; /* This structure is passed to event handler */ struct nf_ct_event { struct nf_conn *ct; Loading @@ -76,53 +69,88 @@ extern struct nf_ct_event_notifier *nf_conntrack_event_cb; extern int nf_conntrack_register_notifier(struct nf_ct_event_notifier *nb); extern void nf_conntrack_unregister_notifier(struct nf_ct_event_notifier *nb); extern void nf_ct_deliver_cached_events(const struct nf_conn *ct); extern void __nf_ct_event_cache_init(struct nf_conn *ct); extern void nf_ct_event_cache_flush(struct net *net); extern void nf_ct_deliver_cached_events(struct nf_conn *ct); static inline void nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct) { struct net *net = nf_ct_net(ct); struct nf_conntrack_ecache *ecache; local_bh_disable(); ecache = per_cpu_ptr(net->ct.ecache, raw_smp_processor_id()); if (ct != ecache->ct) __nf_ct_event_cache_init(ct); ecache->events |= event; local_bh_enable(); struct nf_conntrack_ecache *e; if (nf_conntrack_event_cb == NULL) return; e = nf_ct_ecache_find(ct); if (e == NULL) return; set_bit(event, &e->cache); } static inline void nf_conntrack_event_report(enum ip_conntrack_events event, static inline int nf_conntrack_eventmask_report(unsigned int eventmask, struct nf_conn *ct, u32 pid, 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(nf_conntrack_event_cb); if (notify == NULL) goto out_unlock; if (!net->ct.sysctl_events) 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, .pid = pid, .pid = e->pid ? e->pid : pid, .report = report }; notify->fcn(event, &item); /* This is a resent of a destroy event? If so, skip missed */ unsigned long missed = e->pid ? 0 : e->missed; 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 PID * to include it in the retransmission. */ if (eventmask & (1 << IPCT_DESTROY) && e->pid == 0 && pid != 0) e->pid = pid; else e->missed |= eventmask; } else e->missed &= ~missed; spin_unlock_bh(&ct->lock); } } out_unlock: rcu_read_unlock(); return ret; } static inline void static inline int nf_conntrack_event_report(enum ip_conntrack_events event, struct nf_conn *ct, u32 pid, int report) { return nf_conntrack_eventmask_report(1 << event, ct, pid, report); } static inline int nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct) { nf_conntrack_event_report(event, ct, 0, 0); return nf_conntrack_eventmask_report(1 << event, ct, 0, 0); } struct nf_exp_event { Loading @@ -145,6 +173,7 @@ nf_ct_expect_event_report(enum ip_conntrack_expect_events event, u32 pid, int report) { struct net *net = nf_ct_exp_net(exp); struct nf_exp_event_notifier *notify; rcu_read_lock(); Loading @@ -152,13 +181,16 @@ nf_ct_expect_event_report(enum ip_conntrack_expect_events event, if (notify == NULL) goto out_unlock; if (!net->ct.sysctl_events) goto out_unlock; { struct nf_exp_event item = { .exp = exp, .pid = pid, .report = report }; notify->fcn(event, &item); notify->fcn(1 << event, &item); } out_unlock: rcu_read_unlock(); Loading @@ -178,12 +210,16 @@ extern void nf_conntrack_ecache_fini(struct net *net); static inline void nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct) {} static inline void nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct) {} static inline void nf_conntrack_event_report(enum ip_conntrack_events event, static inline int nf_conntrack_eventmask_report(unsigned int eventmask, struct nf_conn *ct, u32 pid, int report) {} int report) { return 0; } static inline int nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct) { return 0; } static inline int nf_conntrack_event_report(enum ip_conntrack_events event, struct nf_conn *ct, u32 pid, int report) { return 0; } static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) {} static inline void nf_ct_expect_event(enum ip_conntrack_expect_events event, struct nf_conntrack_expect *exp) {} Loading @@ -191,7 +227,6 @@ static inline void nf_ct_expect_event_report(enum ip_conntrack_expect_events e, struct nf_conntrack_expect *exp, u32 pid, int report) {} static inline void nf_ct_event_cache_flush(struct net *net) {} static inline int nf_conntrack_ecache_init(struct net *net) { Loading include/net/netfilter/nf_conntrack_extend.h +2 −0 Original line number Diff line number Diff line Loading @@ -8,12 +8,14 @@ enum nf_ct_ext_id NF_CT_EXT_HELPER, NF_CT_EXT_NAT, NF_CT_EXT_ACCT, NF_CT_EXT_ECACHE, NF_CT_EXT_NUM, }; #define NF_CT_EXT_HELPER_TYPE struct nf_conn_help #define NF_CT_EXT_NAT_TYPE struct nf_conn_nat #define NF_CT_EXT_ACCT_TYPE struct nf_conn_counter #define NF_CT_EXT_ECACHE_TYPE struct nf_conntrack_ecache /* Extensions: optional stuff which isn't permanently in struct. */ struct nf_ct_ext { Loading include/net/netfilter/nf_conntrack_helper.h +2 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,8 @@ extern struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp); extern int __nf_ct_try_assign_helper(struct nf_conn *ct, gfp_t flags); extern void nf_ct_helper_destroy(struct nf_conn *ct); static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct) { return nf_ct_ext_find(ct, NF_CT_EXT_HELPER); Loading Loading
include/linux/list_nulls.h +18 −0 Original line number Diff line number Diff line Loading @@ -56,6 +56,18 @@ static inline int hlist_nulls_empty(const struct hlist_nulls_head *h) return is_a_nulls(h->first); } static inline void hlist_nulls_add_head(struct hlist_nulls_node *n, struct hlist_nulls_head *h) { struct hlist_nulls_node *first = h->first; n->next = first; n->pprev = &h->first; h->first = n; if (!is_a_nulls(first)) first->pprev = &n->next; } static inline void __hlist_nulls_del(struct hlist_nulls_node *n) { struct hlist_nulls_node *next = n->next; Loading @@ -65,6 +77,12 @@ static inline void __hlist_nulls_del(struct hlist_nulls_node *n) next->pprev = pprev; } static inline void hlist_nulls_del(struct hlist_nulls_node *n) { __hlist_nulls_del(n); n->pprev = LIST_POISON2; } /** * hlist_nulls_for_each_entry - iterate over list of given type * @tpos: the type * to use as a loop cursor. Loading
include/net/netfilter/nf_conntrack.h +2 −0 Original line number Diff line number Diff line Loading @@ -201,6 +201,8 @@ extern struct nf_conntrack_tuple_hash * __nf_conntrack_find(struct net *net, const struct nf_conntrack_tuple *tuple); extern void nf_conntrack_hash_insert(struct nf_conn *ct); extern void nf_ct_delete_from_lists(struct nf_conn *ct); extern void nf_ct_insert_dying_list(struct nf_conn *ct); extern void nf_conntrack_flush_report(struct net *net, u32 pid, int report); Loading
include/net/netfilter/nf_conntrack_ecache.h +105 −70 Original line number Diff line number Diff line Loading @@ -6,61 +6,54 @@ #define _NF_CONNTRACK_ECACHE_H #include <net/netfilter/nf_conntrack.h> #include <linux/interrupt.h> #include <net/net_namespace.h> #include <net/netfilter/nf_conntrack_expect.h> #include <linux/netfilter/nf_conntrack_common.h> #include <linux/netfilter/nf_conntrack_tuple_common.h> #include <net/netfilter/nf_conntrack_extend.h> /* Connection tracking event bits */ /* Connection tracking event types */ enum ip_conntrack_events { /* New conntrack */ IPCT_NEW_BIT = 0, IPCT_NEW = (1 << IPCT_NEW_BIT), /* Expected connection */ IPCT_RELATED_BIT = 1, IPCT_RELATED = (1 << IPCT_RELATED_BIT), /* Destroyed conntrack */ IPCT_DESTROY_BIT = 2, IPCT_DESTROY = (1 << IPCT_DESTROY_BIT), /* Status has changed */ IPCT_STATUS_BIT = 3, IPCT_STATUS = (1 << IPCT_STATUS_BIT), IPCT_NEW = 0, /* new conntrack */ IPCT_RELATED = 1, /* related conntrack */ IPCT_DESTROY = 2, /* destroyed conntrack */ IPCT_STATUS = 3, /* status has changed */ IPCT_PROTOINFO = 4, /* protocol information has changed */ IPCT_HELPER = 5, /* new helper has been set */ IPCT_MARK = 6, /* new mark has been set */ IPCT_NATSEQADJ = 7, /* NAT is doing sequence adjustment */ IPCT_SECMARK = 8, /* new security mark has been set */ }; /* Update of protocol info */ IPCT_PROTOINFO_BIT = 4, IPCT_PROTOINFO = (1 << IPCT_PROTOINFO_BIT), enum ip_conntrack_expect_events { IPEXP_NEW = 0, /* new expectation */ }; /* New helper for conntrack */ IPCT_HELPER_BIT = 5, IPCT_HELPER = (1 << IPCT_HELPER_BIT), struct nf_conntrack_ecache { unsigned long cache; /* bitops want long */ unsigned long missed; /* missed events */ u32 pid; /* netlink pid of destroyer */ }; /* Mark is set */ IPCT_MARK_BIT = 6, IPCT_MARK = (1 << IPCT_MARK_BIT), static inline struct nf_conntrack_ecache * nf_ct_ecache_find(const struct nf_conn *ct) { return nf_ct_ext_find(ct, NF_CT_EXT_ECACHE); } /* NAT sequence adjustment */ IPCT_NATSEQADJ_BIT = 7, IPCT_NATSEQADJ = (1 << IPCT_NATSEQADJ_BIT), static inline struct nf_conntrack_ecache * nf_ct_ecache_ext_add(struct nf_conn *ct, gfp_t gfp) { struct net *net = nf_ct_net(ct); /* Secmark is set */ IPCT_SECMARK_BIT = 8, IPCT_SECMARK = (1 << IPCT_SECMARK_BIT), }; if (!net->ct.sysctl_events) return NULL; enum ip_conntrack_expect_events { IPEXP_NEW_BIT = 0, IPEXP_NEW = (1 << IPEXP_NEW_BIT), return nf_ct_ext_add(ct, NF_CT_EXT_ECACHE, gfp); }; #ifdef CONFIG_NF_CONNTRACK_EVENTS struct nf_conntrack_ecache { struct nf_conn *ct; unsigned int events; }; /* This structure is passed to event handler */ struct nf_ct_event { struct nf_conn *ct; Loading @@ -76,53 +69,88 @@ extern struct nf_ct_event_notifier *nf_conntrack_event_cb; extern int nf_conntrack_register_notifier(struct nf_ct_event_notifier *nb); extern void nf_conntrack_unregister_notifier(struct nf_ct_event_notifier *nb); extern void nf_ct_deliver_cached_events(const struct nf_conn *ct); extern void __nf_ct_event_cache_init(struct nf_conn *ct); extern void nf_ct_event_cache_flush(struct net *net); extern void nf_ct_deliver_cached_events(struct nf_conn *ct); static inline void nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct) { struct net *net = nf_ct_net(ct); struct nf_conntrack_ecache *ecache; local_bh_disable(); ecache = per_cpu_ptr(net->ct.ecache, raw_smp_processor_id()); if (ct != ecache->ct) __nf_ct_event_cache_init(ct); ecache->events |= event; local_bh_enable(); struct nf_conntrack_ecache *e; if (nf_conntrack_event_cb == NULL) return; e = nf_ct_ecache_find(ct); if (e == NULL) return; set_bit(event, &e->cache); } static inline void nf_conntrack_event_report(enum ip_conntrack_events event, static inline int nf_conntrack_eventmask_report(unsigned int eventmask, struct nf_conn *ct, u32 pid, 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(nf_conntrack_event_cb); if (notify == NULL) goto out_unlock; if (!net->ct.sysctl_events) 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, .pid = pid, .pid = e->pid ? e->pid : pid, .report = report }; notify->fcn(event, &item); /* This is a resent of a destroy event? If so, skip missed */ unsigned long missed = e->pid ? 0 : e->missed; 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 PID * to include it in the retransmission. */ if (eventmask & (1 << IPCT_DESTROY) && e->pid == 0 && pid != 0) e->pid = pid; else e->missed |= eventmask; } else e->missed &= ~missed; spin_unlock_bh(&ct->lock); } } out_unlock: rcu_read_unlock(); return ret; } static inline void static inline int nf_conntrack_event_report(enum ip_conntrack_events event, struct nf_conn *ct, u32 pid, int report) { return nf_conntrack_eventmask_report(1 << event, ct, pid, report); } static inline int nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct) { nf_conntrack_event_report(event, ct, 0, 0); return nf_conntrack_eventmask_report(1 << event, ct, 0, 0); } struct nf_exp_event { Loading @@ -145,6 +173,7 @@ nf_ct_expect_event_report(enum ip_conntrack_expect_events event, u32 pid, int report) { struct net *net = nf_ct_exp_net(exp); struct nf_exp_event_notifier *notify; rcu_read_lock(); Loading @@ -152,13 +181,16 @@ nf_ct_expect_event_report(enum ip_conntrack_expect_events event, if (notify == NULL) goto out_unlock; if (!net->ct.sysctl_events) goto out_unlock; { struct nf_exp_event item = { .exp = exp, .pid = pid, .report = report }; notify->fcn(event, &item); notify->fcn(1 << event, &item); } out_unlock: rcu_read_unlock(); Loading @@ -178,12 +210,16 @@ extern void nf_conntrack_ecache_fini(struct net *net); static inline void nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct) {} static inline void nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct) {} static inline void nf_conntrack_event_report(enum ip_conntrack_events event, static inline int nf_conntrack_eventmask_report(unsigned int eventmask, struct nf_conn *ct, u32 pid, int report) {} int report) { return 0; } static inline int nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct) { return 0; } static inline int nf_conntrack_event_report(enum ip_conntrack_events event, struct nf_conn *ct, u32 pid, int report) { return 0; } static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) {} static inline void nf_ct_expect_event(enum ip_conntrack_expect_events event, struct nf_conntrack_expect *exp) {} Loading @@ -191,7 +227,6 @@ static inline void nf_ct_expect_event_report(enum ip_conntrack_expect_events e, struct nf_conntrack_expect *exp, u32 pid, int report) {} static inline void nf_ct_event_cache_flush(struct net *net) {} static inline int nf_conntrack_ecache_init(struct net *net) { Loading
include/net/netfilter/nf_conntrack_extend.h +2 −0 Original line number Diff line number Diff line Loading @@ -8,12 +8,14 @@ enum nf_ct_ext_id NF_CT_EXT_HELPER, NF_CT_EXT_NAT, NF_CT_EXT_ACCT, NF_CT_EXT_ECACHE, NF_CT_EXT_NUM, }; #define NF_CT_EXT_HELPER_TYPE struct nf_conn_help #define NF_CT_EXT_NAT_TYPE struct nf_conn_nat #define NF_CT_EXT_ACCT_TYPE struct nf_conn_counter #define NF_CT_EXT_ECACHE_TYPE struct nf_conntrack_ecache /* Extensions: optional stuff which isn't permanently in struct. */ struct nf_ct_ext { Loading
include/net/netfilter/nf_conntrack_helper.h +2 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,8 @@ extern struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp); extern int __nf_ct_try_assign_helper(struct nf_conn *ct, gfp_t flags); extern void nf_ct_helper_destroy(struct nf_conn *ct); static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct) { return nf_ct_ext_find(ct, NF_CT_EXT_HELPER); Loading