diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/net/netfilter/nf_conntrack.h | 2 | ||||
-rw-r--r-- | include/net/netfilter/nf_conntrack_ecache.h | 61 | ||||
-rw-r--r-- | include/net/netns/conntrack.h | 2 |
3 files changed, 48 insertions, 17 deletions
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index ecc79f959076..a632689b61b4 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h | |||
@@ -201,6 +201,8 @@ extern struct nf_conntrack_tuple_hash * | |||
201 | __nf_conntrack_find(struct net *net, const struct nf_conntrack_tuple *tuple); | 201 | __nf_conntrack_find(struct net *net, const struct nf_conntrack_tuple *tuple); |
202 | 202 | ||
203 | extern void nf_conntrack_hash_insert(struct nf_conn *ct); | 203 | extern void nf_conntrack_hash_insert(struct nf_conn *ct); |
204 | extern void nf_ct_delete_from_lists(struct nf_conn *ct); | ||
205 | extern void nf_ct_insert_dying_list(struct nf_conn *ct); | ||
204 | 206 | ||
205 | extern void nf_conntrack_flush_report(struct net *net, u32 pid, int report); | 207 | extern void nf_conntrack_flush_report(struct net *net, u32 pid, int report); |
206 | 208 | ||
diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h index e7ae297ba383..4f20d58e2ab7 100644 --- a/include/net/netfilter/nf_conntrack_ecache.h +++ b/include/net/netfilter/nf_conntrack_ecache.h | |||
@@ -32,6 +32,8 @@ enum ip_conntrack_expect_events { | |||
32 | 32 | ||
33 | struct nf_conntrack_ecache { | 33 | struct nf_conntrack_ecache { |
34 | unsigned long cache; /* bitops want long */ | 34 | unsigned long cache; /* bitops want long */ |
35 | unsigned long missed; /* missed events */ | ||
36 | u32 pid; /* netlink pid of destroyer */ | ||
35 | }; | 37 | }; |
36 | 38 | ||
37 | static inline struct nf_conntrack_ecache * | 39 | static inline struct nf_conntrack_ecache * |
@@ -84,14 +86,16 @@ nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct) | |||
84 | set_bit(event, &e->cache); | 86 | set_bit(event, &e->cache); |
85 | } | 87 | } |
86 | 88 | ||
87 | static inline void | 89 | static inline int |
88 | nf_conntrack_eventmask_report(unsigned int eventmask, | 90 | nf_conntrack_eventmask_report(unsigned int eventmask, |
89 | struct nf_conn *ct, | 91 | struct nf_conn *ct, |
90 | u32 pid, | 92 | u32 pid, |
91 | int report) | 93 | int report) |
92 | { | 94 | { |
95 | int ret = 0; | ||
93 | struct net *net = nf_ct_net(ct); | 96 | struct net *net = nf_ct_net(ct); |
94 | struct nf_ct_event_notifier *notify; | 97 | struct nf_ct_event_notifier *notify; |
98 | struct nf_conntrack_ecache *e; | ||
95 | 99 | ||
96 | rcu_read_lock(); | 100 | rcu_read_lock(); |
97 | notify = rcu_dereference(nf_conntrack_event_cb); | 101 | notify = rcu_dereference(nf_conntrack_event_cb); |
@@ -101,29 +105,52 @@ nf_conntrack_eventmask_report(unsigned int eventmask, | |||
101 | if (!net->ct.sysctl_events) | 105 | if (!net->ct.sysctl_events) |
102 | goto out_unlock; | 106 | goto out_unlock; |
103 | 107 | ||
108 | e = nf_ct_ecache_find(ct); | ||
109 | if (e == NULL) | ||
110 | goto out_unlock; | ||
111 | |||
104 | if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) { | 112 | if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) { |
105 | struct nf_ct_event item = { | 113 | struct nf_ct_event item = { |
106 | .ct = ct, | 114 | .ct = ct, |
107 | .pid = pid, | 115 | .pid = e->pid ? e->pid : pid, |
108 | .report = report | 116 | .report = report |
109 | }; | 117 | }; |
110 | notify->fcn(eventmask, &item); | 118 | /* This is a resent of a destroy event? If so, skip missed */ |
119 | unsigned long missed = e->pid ? 0 : e->missed; | ||
120 | |||
121 | ret = notify->fcn(eventmask | missed, &item); | ||
122 | if (unlikely(ret < 0 || missed)) { | ||
123 | spin_lock_bh(&ct->lock); | ||
124 | if (ret < 0) { | ||
125 | /* This is a destroy event that has been | ||
126 | * triggered by a process, we store the PID | ||
127 | * to include it in the retransmission. */ | ||
128 | if (eventmask & (1 << IPCT_DESTROY) && | ||
129 | e->pid == 0 && pid != 0) | ||
130 | e->pid = pid; | ||
131 | else | ||
132 | e->missed |= eventmask; | ||
133 | } else | ||
134 | e->missed &= ~missed; | ||
135 | spin_unlock_bh(&ct->lock); | ||
136 | } | ||
111 | } | 137 | } |
112 | out_unlock: | 138 | out_unlock: |
113 | rcu_read_unlock(); | 139 | rcu_read_unlock(); |
140 | return ret; | ||
114 | } | 141 | } |
115 | 142 | ||
116 | static inline void | 143 | static inline int |
117 | nf_conntrack_event_report(enum ip_conntrack_events event, struct nf_conn *ct, | 144 | nf_conntrack_event_report(enum ip_conntrack_events event, struct nf_conn *ct, |
118 | u32 pid, int report) | 145 | u32 pid, int report) |
119 | { | 146 | { |
120 | nf_conntrack_eventmask_report(1 << event, ct, pid, report); | 147 | return nf_conntrack_eventmask_report(1 << event, ct, pid, report); |
121 | } | 148 | } |
122 | 149 | ||
123 | static inline void | 150 | static inline int |
124 | nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct) | 151 | nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct) |
125 | { | 152 | { |
126 | nf_conntrack_eventmask_report(1 << event, ct, 0, 0); | 153 | return nf_conntrack_eventmask_report(1 << event, ct, 0, 0); |
127 | } | 154 | } |
128 | 155 | ||
129 | struct nf_exp_event { | 156 | struct nf_exp_event { |
@@ -183,16 +210,16 @@ extern void nf_conntrack_ecache_fini(struct net *net); | |||
183 | 210 | ||
184 | static inline void nf_conntrack_event_cache(enum ip_conntrack_events event, | 211 | static inline void nf_conntrack_event_cache(enum ip_conntrack_events event, |
185 | struct nf_conn *ct) {} | 212 | struct nf_conn *ct) {} |
186 | static inline void nf_conntrack_eventmask_report(unsigned int eventmask, | 213 | static inline int nf_conntrack_eventmask_report(unsigned int eventmask, |
187 | struct nf_conn *ct, | 214 | struct nf_conn *ct, |
188 | u32 pid, | 215 | u32 pid, |
189 | int report) {} | 216 | int report) { return 0; } |
190 | static inline void nf_conntrack_event(enum ip_conntrack_events event, | 217 | static inline int nf_conntrack_event(enum ip_conntrack_events event, |
191 | struct nf_conn *ct) {} | 218 | struct nf_conn *ct) { return 0; } |
192 | static inline void nf_conntrack_event_report(enum ip_conntrack_events event, | 219 | static inline int nf_conntrack_event_report(enum ip_conntrack_events event, |
193 | struct nf_conn *ct, | 220 | struct nf_conn *ct, |
194 | u32 pid, | 221 | u32 pid, |
195 | int report) {} | 222 | int report) { return 0; } |
196 | static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) {} | 223 | static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) {} |
197 | static inline void nf_ct_expect_event(enum ip_conntrack_expect_events event, | 224 | static inline void nf_ct_expect_event(enum ip_conntrack_expect_events event, |
198 | struct nf_conntrack_expect *exp) {} | 225 | struct nf_conntrack_expect *exp) {} |
diff --git a/include/net/netns/conntrack.h b/include/net/netns/conntrack.h index 505a51cd8c63..ba1ba0c5efd1 100644 --- a/include/net/netns/conntrack.h +++ b/include/net/netns/conntrack.h | |||
@@ -14,8 +14,10 @@ struct netns_ct { | |||
14 | struct hlist_nulls_head *hash; | 14 | struct hlist_nulls_head *hash; |
15 | struct hlist_head *expect_hash; | 15 | struct hlist_head *expect_hash; |
16 | struct hlist_nulls_head unconfirmed; | 16 | struct hlist_nulls_head unconfirmed; |
17 | struct hlist_nulls_head dying; | ||
17 | struct ip_conntrack_stat *stat; | 18 | struct ip_conntrack_stat *stat; |
18 | int sysctl_events; | 19 | int sysctl_events; |
20 | unsigned int sysctl_events_retry_timeout; | ||
19 | int sysctl_acct; | 21 | int sysctl_acct; |
20 | int sysctl_checksum; | 22 | int sysctl_checksum; |
21 | unsigned int sysctl_log_invalid; /* Log invalid packets */ | 23 | unsigned int sysctl_log_invalid; /* Log invalid packets */ |