Blame view

net/netfilter/nf_conntrack_netlink.c 75.7 KB
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1
2
3
4
  /* Connection tracking via netlink socket. Allows for user space
   * protocol helpers and general trouble making from userspace.
   *
   * (C) 2001 by Jay Schulist <jschlst@samba.org>
dc808fe28   Harald Welte   [NETFILTER] nf_co...
5
   * (C) 2002-2006 by Harald Welte <laforge@gnumonks.org>
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
6
   * (C) 2003 by Patrick Mchardy <kaber@trash.net>
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
7
   * (C) 2005-2012 by Pablo Neira Ayuso <pablo@netfilter.org>
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
8
   *
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
9
   * Initial connection tracking via netlink development funded and
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
10
11
12
13
14
15
   * generally made possible by Network Robots, Inc. (www.networkrobots.com)
   *
   * Further development of this code funded by Astaro AG (http://www.astaro.com)
   *
   * This software may be used and distributed according to the terms
   * of the GNU General Public License, incorporated herein by reference.
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
16
17
18
19
20
   */
  
  #include <linux/init.h>
  #include <linux/module.h>
  #include <linux/kernel.h>
711bbdd65   Ingo Molnar   rculist.h: fix in...
21
  #include <linux/rculist.h>
ea781f197   Eric Dumazet   netfilter: nf_con...
22
  #include <linux/rculist_nulls.h>
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
23
24
  #include <linux/types.h>
  #include <linux/timer.h>
1cc63249a   Eric Paris   conntrack: export...
25
  #include <linux/security.h>
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
26
27
28
29
  #include <linux/skbuff.h>
  #include <linux/errno.h>
  #include <linux/netlink.h>
  #include <linux/spinlock.h>
40a839fdb   Yasuyuki Kozakai   [NETFILTER]: nf_c...
30
  #include <linux/interrupt.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
31
  #include <linux/slab.h>
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
32
33
  
  #include <linux/netfilter.h>
dc5fc579b   Arnaldo Carvalho de Melo   [NETLINK]: Use nl...
34
  #include <net/netlink.h>
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
35
  #include <net/sock.h>
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
36
37
  #include <net/netfilter/nf_conntrack.h>
  #include <net/netfilter/nf_conntrack_core.h>
77ab9cff0   Martin Josefsson   [NETFILTER]: nf_c...
38
  #include <net/netfilter/nf_conntrack_expect.h>
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
39
40
  #include <net/netfilter/nf_conntrack_helper.h>
  #include <net/netfilter/nf_conntrack_l3proto.h>
605dcad6c   Martin Josefsson   [NETFILTER]: nf_c...
41
  #include <net/netfilter/nf_conntrack_l4proto.h>
5b1158e90   Jozsef Kadlecsik   [NETFILTER]: Add ...
42
  #include <net/netfilter/nf_conntrack_tuple.h>
584015727   Krzysztof Piotr Oledzki   netfilter: accoun...
43
  #include <net/netfilter/nf_conntrack_acct.h>
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
44
  #include <net/netfilter/nf_conntrack_zones.h>
a992ca2a0   Pablo Neira Ayuso   netfilter: nf_con...
45
  #include <net/netfilter/nf_conntrack_timestamp.h>
c539f0171   Florian Westphal   netfilter: add co...
46
  #include <net/netfilter/nf_conntrack_labels.h>
5b1158e90   Jozsef Kadlecsik   [NETFILTER]: Add ...
47
48
  #ifdef CONFIG_NF_NAT_NEEDED
  #include <net/netfilter/nf_nat_core.h>
c7232c997   Patrick McHardy   netfilter: add pr...
49
  #include <net/netfilter/nf_nat_l4proto.h>
8c88f87cb   Pablo Neira Ayuso   netfilter: nfnetl...
50
  #include <net/netfilter/nf_nat_helper.h>
5b1158e90   Jozsef Kadlecsik   [NETFILTER]: Add ...
51
  #endif
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
52
53
54
55
56
  
  #include <linux/netfilter/nfnetlink.h>
  #include <linux/netfilter/nfnetlink_conntrack.h>
  
  MODULE_LICENSE("GPL");
dc808fe28   Harald Welte   [NETFILTER] nf_co...
57
  static char __initdata version[] = "0.93";
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
58

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
59
  static inline int
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
60
  ctnetlink_dump_tuples_proto(struct sk_buff *skb,
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
61
  			    const struct nf_conntrack_tuple *tuple,
605dcad6c   Martin Josefsson   [NETFILTER]: nf_c...
62
  			    struct nf_conntrack_l4proto *l4proto)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
63
  {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
64
  	int ret = 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
65
  	struct nlattr *nest_parms;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
66

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
67
68
69
  	nest_parms = nla_nest_start(skb, CTA_TUPLE_PROTO | NLA_F_NESTED);
  	if (!nest_parms)
  		goto nla_put_failure;
cc1eb4313   David S. Miller   nf_conntrack_netl...
70
71
  	if (nla_put_u8(skb, CTA_PROTO_NUM, tuple->dst.protonum))
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
72

fdf708322   Patrick McHardy   [NETFILTER]: nfne...
73
74
  	if (likely(l4proto->tuple_to_nlattr))
  		ret = l4proto->tuple_to_nlattr(skb, tuple);
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
75

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
76
  	nla_nest_end(skb, nest_parms);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
77
78
  
  	return ret;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
79
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
80
81
82
83
  	return -1;
  }
  
  static inline int
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
84
85
86
  ctnetlink_dump_tuples_ip(struct sk_buff *skb,
  			 const struct nf_conntrack_tuple *tuple,
  			 struct nf_conntrack_l3proto *l3proto)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
87
  {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
88
  	int ret = 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
89
90
91
92
93
  	struct nlattr *nest_parms;
  
  	nest_parms = nla_nest_start(skb, CTA_TUPLE_IP | NLA_F_NESTED);
  	if (!nest_parms)
  		goto nla_put_failure;
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
94

fdf708322   Patrick McHardy   [NETFILTER]: nfne...
95
96
  	if (likely(l3proto->tuple_to_nlattr))
  		ret = l3proto->tuple_to_nlattr(skb, tuple);
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
97

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
98
  	nla_nest_end(skb, nest_parms);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
99

1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
100
  	return ret;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
101
  nla_put_failure:
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
102
103
  	return -1;
  }
bb5cf80e9   Ilpo Järvinen   [NETFILTER]: Kill...
104
  static int
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
105
106
107
108
109
  ctnetlink_dump_tuples(struct sk_buff *skb,
  		      const struct nf_conntrack_tuple *tuple)
  {
  	int ret;
  	struct nf_conntrack_l3proto *l3proto;
605dcad6c   Martin Josefsson   [NETFILTER]: nf_c...
110
  	struct nf_conntrack_l4proto *l4proto;
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
111

3b988ece9   Hans Schillstrom   netfilter: ctnetl...
112
  	rcu_read_lock();
528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
113
  	l3proto = __nf_ct_l3proto_find(tuple->src.l3num);
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
114
  	ret = ctnetlink_dump_tuples_ip(skb, tuple, l3proto);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
115

3b988ece9   Hans Schillstrom   netfilter: ctnetl...
116
117
118
119
120
121
  	if (ret >= 0) {
  		l4proto = __nf_ct_l4proto_find(tuple->src.l3num,
  					       tuple->dst.protonum);
  		ret = ctnetlink_dump_tuples_proto(skb, tuple, l4proto);
  	}
  	rcu_read_unlock();
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
122
  	return ret;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
123
124
125
126
127
  }
  
  static inline int
  ctnetlink_dump_status(struct sk_buff *skb, const struct nf_conn *ct)
  {
cc1eb4313   David S. Miller   nf_conntrack_netl...
128
129
  	if (nla_put_be32(skb, CTA_STATUS, htonl(ct->status)))
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
130
  	return 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
131
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
132
133
134
135
136
137
  	return -1;
  }
  
  static inline int
  ctnetlink_dump_timeout(struct sk_buff *skb, const struct nf_conn *ct)
  {
c12163827   Xi Wang   netfilter: ctnetl...
138
  	long timeout = ((long)ct->timeout.expires - (long)jiffies) / HZ;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
139

77236b6e3   Patrick McHardy   [NETFILTER]: ctne...
140
  	if (timeout < 0)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
141
  		timeout = 0;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
142

cc1eb4313   David S. Miller   nf_conntrack_netl...
143
144
  	if (nla_put_be32(skb, CTA_TIMEOUT, htonl(timeout)))
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
145
  	return 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
146
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
147
148
149
150
  	return -1;
  }
  
  static inline int
440f0d588   Patrick McHardy   netfilter: nf_con...
151
  ctnetlink_dump_protoinfo(struct sk_buff *skb, struct nf_conn *ct)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
152
  {
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
153
  	struct nf_conntrack_l4proto *l4proto;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
154
  	struct nlattr *nest_proto;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
155
  	int ret;
528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
156
157
  	l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct));
  	if (!l4proto->to_nlattr)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
158
  		return 0;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
159

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
160
161
162
  	nest_proto = nla_nest_start(skb, CTA_PROTOINFO | NLA_F_NESTED);
  	if (!nest_proto)
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
163

fdf708322   Patrick McHardy   [NETFILTER]: nfne...
164
  	ret = l4proto->to_nlattr(skb, nest_proto, ct);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
165

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
166
  	nla_nest_end(skb, nest_proto);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
167
168
  
  	return ret;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
169
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
170
171
172
173
174
175
  	return -1;
  }
  
  static inline int
  ctnetlink_dump_helpinfo(struct sk_buff *skb, const struct nf_conn *ct)
  {
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
176
  	struct nlattr *nest_helper;
dc808fe28   Harald Welte   [NETFILTER] nf_co...
177
  	const struct nf_conn_help *help = nfct_help(ct);
3c158f7f5   Patrick McHarrdy   [NETFILTER]: nf_c...
178
  	struct nf_conntrack_helper *helper;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
179

3c158f7f5   Patrick McHarrdy   [NETFILTER]: nf_c...
180
  	if (!help)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
181
  		return 0;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
182

3c158f7f5   Patrick McHarrdy   [NETFILTER]: nf_c...
183
184
185
  	helper = rcu_dereference(help->helper);
  	if (!helper)
  		goto out;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
186
187
188
  	nest_helper = nla_nest_start(skb, CTA_HELP | NLA_F_NESTED);
  	if (!nest_helper)
  		goto nla_put_failure;
cc1eb4313   David S. Miller   nf_conntrack_netl...
189
190
  	if (nla_put_string(skb, CTA_HELP_NAME, helper->name))
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
191

fdf708322   Patrick McHardy   [NETFILTER]: nfne...
192
193
  	if (helper->to_nlattr)
  		helper->to_nlattr(skb, ct);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
194

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
195
  	nla_nest_end(skb, nest_helper);
3c158f7f5   Patrick McHarrdy   [NETFILTER]: nf_c...
196
  out:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
197
  	return 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
198
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
199
200
  	return -1;
  }
bb5cf80e9   Ilpo Järvinen   [NETFILTER]: Kill...
201
  static int
80e60e67b   Pablo Neira Ayuso   netfilter: ctnetl...
202
203
  dump_counters(struct sk_buff *skb, u64 pkts, u64 bytes,
  	      enum ip_conntrack_dir dir)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
204
205
  {
  	enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
206
  	struct nlattr *nest_count;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
207

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
208
209
210
  	nest_count = nla_nest_start(skb, type | NLA_F_NESTED);
  	if (!nest_count)
  		goto nla_put_failure;
cc1eb4313   David S. Miller   nf_conntrack_netl...
211
212
213
  	if (nla_put_be64(skb, CTA_COUNTERS_PACKETS, cpu_to_be64(pkts)) ||
  	    nla_put_be64(skb, CTA_COUNTERS_BYTES, cpu_to_be64(bytes)))
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
214

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
215
  	nla_nest_end(skb, nest_count);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
216
217
  
  	return 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
218
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
219
220
  	return -1;
  }
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
221

a992ca2a0   Pablo Neira Ayuso   netfilter: nf_con...
222
  static int
80e60e67b   Pablo Neira Ayuso   netfilter: ctnetl...
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
  ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct,
  			enum ip_conntrack_dir dir, int type)
  {
  	struct nf_conn_counter *acct;
  	u64 pkts, bytes;
  
  	acct = nf_conn_acct_find(ct);
  	if (!acct)
  		return 0;
  
  	if (type == IPCTNL_MSG_CT_GET_CTRZERO) {
  		pkts = atomic64_xchg(&acct[dir].packets, 0);
  		bytes = atomic64_xchg(&acct[dir].bytes, 0);
  	} else {
  		pkts = atomic64_read(&acct[dir].packets);
  		bytes = atomic64_read(&acct[dir].bytes);
  	}
  	return dump_counters(skb, pkts, bytes, dir);
  }
  
  static int
a992ca2a0   Pablo Neira Ayuso   netfilter: nf_con...
244
245
246
247
248
249
250
251
252
253
254
255
  ctnetlink_dump_timestamp(struct sk_buff *skb, const struct nf_conn *ct)
  {
  	struct nlattr *nest_count;
  	const struct nf_conn_tstamp *tstamp;
  
  	tstamp = nf_conn_tstamp_find(ct);
  	if (!tstamp)
  		return 0;
  
  	nest_count = nla_nest_start(skb, CTA_TIMESTAMP | NLA_F_NESTED);
  	if (!nest_count)
  		goto nla_put_failure;
cc1eb4313   David S. Miller   nf_conntrack_netl...
256
257
258
259
  	if (nla_put_be64(skb, CTA_TIMESTAMP_START, cpu_to_be64(tstamp->start)) ||
  	    (tstamp->stop != 0 && nla_put_be64(skb, CTA_TIMESTAMP_STOP,
  					       cpu_to_be64(tstamp->stop))))
  		goto nla_put_failure;
a992ca2a0   Pablo Neira Ayuso   netfilter: nf_con...
260
261
262
263
264
265
266
  	nla_nest_end(skb, nest_count);
  
  	return 0;
  
  nla_put_failure:
  	return -1;
  }
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
267
268
269
270
  #ifdef CONFIG_NF_CONNTRACK_MARK
  static inline int
  ctnetlink_dump_mark(struct sk_buff *skb, const struct nf_conn *ct)
  {
cc1eb4313   David S. Miller   nf_conntrack_netl...
271
272
  	if (nla_put_be32(skb, CTA_MARK, htonl(ct->mark)))
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
273
  	return 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
274
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
275
276
277
278
279
  	return -1;
  }
  #else
  #define ctnetlink_dump_mark(a, b) (0)
  #endif
37fccd857   Pablo Neira Ayuso   [NETFILTER]: ctne...
280
281
  #ifdef CONFIG_NF_CONNTRACK_SECMARK
  static inline int
1cc63249a   Eric Paris   conntrack: export...
282
  ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct)
37fccd857   Pablo Neira Ayuso   [NETFILTER]: ctne...
283
  {
1cc63249a   Eric Paris   conntrack: export...
284
285
286
287
288
289
  	struct nlattr *nest_secctx;
  	int len, ret;
  	char *secctx;
  
  	ret = security_secid_to_secctx(ct->secmark, &secctx, &len);
  	if (ret)
cba85b532   Pablo Neira Ayuso   netfilter: fix ex...
290
  		return 0;
1cc63249a   Eric Paris   conntrack: export...
291
292
293
294
295
  
  	ret = -1;
  	nest_secctx = nla_nest_start(skb, CTA_SECCTX | NLA_F_NESTED);
  	if (!nest_secctx)
  		goto nla_put_failure;
37fccd857   Pablo Neira Ayuso   [NETFILTER]: ctne...
296

cc1eb4313   David S. Miller   nf_conntrack_netl...
297
298
  	if (nla_put_string(skb, CTA_SECCTX_NAME, secctx))
  		goto nla_put_failure;
1cc63249a   Eric Paris   conntrack: export...
299
300
301
  	nla_nest_end(skb, nest_secctx);
  
  	ret = 0;
37fccd857   Pablo Neira Ayuso   [NETFILTER]: ctne...
302
  nla_put_failure:
1cc63249a   Eric Paris   conntrack: export...
303
304
  	security_release_secctx(secctx, len);
  	return ret;
37fccd857   Pablo Neira Ayuso   [NETFILTER]: ctne...
305
306
  }
  #else
1cc63249a   Eric Paris   conntrack: export...
307
  #define ctnetlink_dump_secctx(a, b) (0)
37fccd857   Pablo Neira Ayuso   [NETFILTER]: ctne...
308
  #endif
0ceabd838   Florian Westphal   netfilter: ctnetl...
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
  #ifdef CONFIG_NF_CONNTRACK_LABELS
  static int ctnetlink_label_size(const struct nf_conn *ct)
  {
  	struct nf_conn_labels *labels = nf_ct_labels_find(ct);
  
  	if (!labels)
  		return 0;
  	return nla_total_size(labels->words * sizeof(long));
  }
  
  static int
  ctnetlink_dump_labels(struct sk_buff *skb, const struct nf_conn *ct)
  {
  	struct nf_conn_labels *labels = nf_ct_labels_find(ct);
  	unsigned int len, i;
  
  	if (!labels)
  		return 0;
  
  	len = labels->words * sizeof(long);
  	i = 0;
  	do {
  		if (labels->bits[i] != 0)
  			return nla_put(skb, CTA_LABELS, len, labels->bits);
  		i++;
  	} while (i < labels->words);
  
  	return 0;
  }
  #else
  #define ctnetlink_dump_labels(a, b) (0)
  #define ctnetlink_label_size(a)	(0)
  #endif
0f417ce98   Pablo Neira Ayuso   [NETFILTER]: ctne...
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
  #define master_tuple(ct) &(ct->master->tuplehash[IP_CT_DIR_ORIGINAL].tuple)
  
  static inline int
  ctnetlink_dump_master(struct sk_buff *skb, const struct nf_conn *ct)
  {
  	struct nlattr *nest_parms;
  
  	if (!(ct->status & IPS_EXPECTED))
  		return 0;
  
  	nest_parms = nla_nest_start(skb, CTA_TUPLE_MASTER | NLA_F_NESTED);
  	if (!nest_parms)
  		goto nla_put_failure;
  	if (ctnetlink_dump_tuples(skb, master_tuple(ct)) < 0)
  		goto nla_put_failure;
  	nla_nest_end(skb, nest_parms);
  
  	return 0;
  
  nla_put_failure:
  	return -1;
  }
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
364
  #ifdef CONFIG_NF_NAT_NEEDED
bb5cf80e9   Ilpo Järvinen   [NETFILTER]: Kill...
365
  static int
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
366
367
  dump_nat_seq_adj(struct sk_buff *skb, const struct nf_nat_seq *natseq, int type)
  {
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
368
369
370
371
372
  	struct nlattr *nest_parms;
  
  	nest_parms = nla_nest_start(skb, type | NLA_F_NESTED);
  	if (!nest_parms)
  		goto nla_put_failure;
cc1eb4313   David S. Miller   nf_conntrack_netl...
373
374
375
376
377
378
379
  	if (nla_put_be32(skb, CTA_NAT_SEQ_CORRECTION_POS,
  			 htonl(natseq->correction_pos)) ||
  	    nla_put_be32(skb, CTA_NAT_SEQ_OFFSET_BEFORE,
  			 htonl(natseq->offset_before)) ||
  	    nla_put_be32(skb, CTA_NAT_SEQ_OFFSET_AFTER,
  			 htonl(natseq->offset_after)))
  		goto nla_put_failure;
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
  
  	nla_nest_end(skb, nest_parms);
  
  	return 0;
  
  nla_put_failure:
  	return -1;
  }
  
  static inline int
  ctnetlink_dump_nat_seq_adj(struct sk_buff *skb, const struct nf_conn *ct)
  {
  	struct nf_nat_seq *natseq;
  	struct nf_conn_nat *nat = nfct_nat(ct);
  
  	if (!(ct->status & IPS_SEQ_ADJUST) || !nat)
  		return 0;
  
  	natseq = &nat->seq[IP_CT_DIR_ORIGINAL];
  	if (dump_nat_seq_adj(skb, natseq, CTA_NAT_SEQ_ADJ_ORIG) == -1)
  		return -1;
  
  	natseq = &nat->seq[IP_CT_DIR_REPLY];
  	if (dump_nat_seq_adj(skb, natseq, CTA_NAT_SEQ_ADJ_REPLY) == -1)
  		return -1;
  
  	return 0;
  }
  #else
  #define ctnetlink_dump_nat_seq_adj(a, b) (0)
  #endif
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
411
412
413
  static inline int
  ctnetlink_dump_id(struct sk_buff *skb, const struct nf_conn *ct)
  {
cc1eb4313   David S. Miller   nf_conntrack_netl...
414
415
  	if (nla_put_be32(skb, CTA_ID, htonl((unsigned long)ct)))
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
416
  	return 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
417
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
418
419
420
421
422
423
  	return -1;
  }
  
  static inline int
  ctnetlink_dump_use(struct sk_buff *skb, const struct nf_conn *ct)
  {
cc1eb4313   David S. Miller   nf_conntrack_netl...
424
425
  	if (nla_put_be32(skb, CTA_USE, htonl(atomic_read(&ct->ct_general.use))))
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
426
  	return 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
427
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
428
429
  	return -1;
  }
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
430
  static int
15e473046   Eric W. Biederman   netlink: Rename p...
431
  ctnetlink_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
80e60e67b   Pablo Neira Ayuso   netfilter: ctnetl...
432
  		    struct nf_conn *ct)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
433
434
435
  {
  	struct nlmsghdr *nlh;
  	struct nfgenmsg *nfmsg;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
436
  	struct nlattr *nest_parms;
15e473046   Eric W. Biederman   netlink: Rename p...
437
  	unsigned int flags = portid ? NLM_F_MULTI : 0, event;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
438

80e60e67b   Pablo Neira Ayuso   netfilter: ctnetl...
439
  	event = (NFNL_SUBSYS_CTNETLINK << 8 | IPCTNL_MSG_CT_NEW);
15e473046   Eric W. Biederman   netlink: Rename p...
440
  	nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
441
442
  	if (nlh == NULL)
  		goto nlmsg_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
443

96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
444
  	nfmsg = nlmsg_data(nlh);
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
445
  	nfmsg->nfgen_family = nf_ct_l3num(ct);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
446
447
  	nfmsg->version      = NFNETLINK_V0;
  	nfmsg->res_id	    = 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
448
449
450
  	nest_parms = nla_nest_start(skb, CTA_TUPLE_ORIG | NLA_F_NESTED);
  	if (!nest_parms)
  		goto nla_put_failure;
f2f3e38c6   Pablo Neira Ayuso   netfilter: ctnetl...
451
  	if (ctnetlink_dump_tuples(skb, nf_ct_tuple(ct, IP_CT_DIR_ORIGINAL)) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
452
453
  		goto nla_put_failure;
  	nla_nest_end(skb, nest_parms);
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
454

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
455
456
457
  	nest_parms = nla_nest_start(skb, CTA_TUPLE_REPLY | NLA_F_NESTED);
  	if (!nest_parms)
  		goto nla_put_failure;
f2f3e38c6   Pablo Neira Ayuso   netfilter: ctnetl...
458
  	if (ctnetlink_dump_tuples(skb, nf_ct_tuple(ct, IP_CT_DIR_REPLY)) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
459
460
  		goto nla_put_failure;
  	nla_nest_end(skb, nest_parms);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
461

cc1eb4313   David S. Miller   nf_conntrack_netl...
462
463
464
  	if (nf_ct_zone(ct) &&
  	    nla_put_be16(skb, CTA_ZONE, htons(nf_ct_zone(ct))))
  		goto nla_put_failure;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
465

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
466
467
  	if (ctnetlink_dump_status(skb, ct) < 0 ||
  	    ctnetlink_dump_timeout(skb, ct) < 0 ||
80e60e67b   Pablo Neira Ayuso   netfilter: ctnetl...
468
469
  	    ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL, type) < 0 ||
  	    ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY, type) < 0 ||
a992ca2a0   Pablo Neira Ayuso   netfilter: nf_con...
470
  	    ctnetlink_dump_timestamp(skb, ct) < 0 ||
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
471
472
473
  	    ctnetlink_dump_protoinfo(skb, ct) < 0 ||
  	    ctnetlink_dump_helpinfo(skb, ct) < 0 ||
  	    ctnetlink_dump_mark(skb, ct) < 0 ||
1cc63249a   Eric Paris   conntrack: export...
474
  	    ctnetlink_dump_secctx(skb, ct) < 0 ||
0ceabd838   Florian Westphal   netfilter: ctnetl...
475
  	    ctnetlink_dump_labels(skb, ct) < 0 ||
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
476
  	    ctnetlink_dump_id(skb, ct) < 0 ||
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
477
  	    ctnetlink_dump_use(skb, ct) < 0 ||
0f417ce98   Pablo Neira Ayuso   [NETFILTER]: ctne...
478
  	    ctnetlink_dump_master(skb, ct) < 0 ||
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
479
  	    ctnetlink_dump_nat_seq_adj(skb, ct) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
480
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
481

96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
482
  	nlmsg_end(skb, nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
483
484
485
  	return skb->len;
  
  nlmsg_failure:
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
486
  nla_put_failure:
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
487
  	nlmsg_cancel(skb, nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
488
489
  	return -1;
  }
03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
490
491
  static inline size_t
  ctnetlink_proto_size(const struct nf_conn *ct)
2732c4e45   Holger Eitzenberger   netfilter: ctnetl...
492
493
494
  {
  	struct nf_conntrack_l3proto *l3proto;
  	struct nf_conntrack_l4proto *l4proto;
03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
495
496
497
498
499
500
501
502
503
504
505
506
507
508
  	size_t len = 0;
  
  	rcu_read_lock();
  	l3proto = __nf_ct_l3proto_find(nf_ct_l3num(ct));
  	len += l3proto->nla_size;
  
  	l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct));
  	len += l4proto->nla_size;
  	rcu_read_unlock();
  
  	return len;
  }
  
  static inline size_t
d26e6a028   Jiri Pirko   netfilter: ctnetl...
509
510
511
512
513
514
515
516
517
  ctnetlink_counters_size(const struct nf_conn *ct)
  {
  	if (!nf_ct_ext_exist(ct, NF_CT_EXT_ACCT))
  		return 0;
  	return 2 * nla_total_size(0) /* CTA_COUNTERS_ORIG|REPL */
  	       + 2 * nla_total_size(sizeof(uint64_t)) /* CTA_COUNTERS_PACKETS */
  	       + 2 * nla_total_size(sizeof(uint64_t)) /* CTA_COUNTERS_BYTES */
  	       ;
  }
cba85b532   Pablo Neira Ayuso   netfilter: fix ex...
518
519
  static inline int
  ctnetlink_secctx_size(const struct nf_conn *ct)
1cc63249a   Eric Paris   conntrack: export...
520
  {
cba85b532   Pablo Neira Ayuso   netfilter: fix ex...
521
522
  #ifdef CONFIG_NF_CONNTRACK_SECMARK
  	int len, ret;
1cc63249a   Eric Paris   conntrack: export...
523

cba85b532   Pablo Neira Ayuso   netfilter: fix ex...
524
525
526
  	ret = security_secid_to_secctx(ct->secmark, NULL, &len);
  	if (ret)
  		return 0;
1cc63249a   Eric Paris   conntrack: export...
527

cba85b532   Pablo Neira Ayuso   netfilter: fix ex...
528
529
530
531
  	return nla_total_size(0) /* CTA_SECCTX */
  	       + nla_total_size(sizeof(char) * len); /* CTA_SECCTX_NAME */
  #else
  	return 0;
1cc63249a   Eric Paris   conntrack: export...
532
  #endif
cba85b532   Pablo Neira Ayuso   netfilter: fix ex...
533
  }
1cc63249a   Eric Paris   conntrack: export...
534

d26e6a028   Jiri Pirko   netfilter: ctnetl...
535
  static inline size_t
a992ca2a0   Pablo Neira Ayuso   netfilter: nf_con...
536
537
538
539
540
541
542
543
544
545
546
547
  ctnetlink_timestamp_size(const struct nf_conn *ct)
  {
  #ifdef CONFIG_NF_CONNTRACK_TIMESTAMP
  	if (!nf_ct_ext_exist(ct, NF_CT_EXT_TSTAMP))
  		return 0;
  	return nla_total_size(0) + 2 * nla_total_size(sizeof(uint64_t));
  #else
  	return 0;
  #endif
  }
  
  static inline size_t
03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
548
549
550
551
552
553
554
555
556
  ctnetlink_nlmsg_size(const struct nf_conn *ct)
  {
  	return NLMSG_ALIGN(sizeof(struct nfgenmsg))
  	       + 3 * nla_total_size(0) /* CTA_TUPLE_ORIG|REPL|MASTER */
  	       + 3 * nla_total_size(0) /* CTA_TUPLE_IP */
  	       + 3 * nla_total_size(0) /* CTA_TUPLE_PROTO */
  	       + 3 * nla_total_size(sizeof(u_int8_t)) /* CTA_PROTO_NUM */
  	       + nla_total_size(sizeof(u_int32_t)) /* CTA_ID */
  	       + nla_total_size(sizeof(u_int32_t)) /* CTA_STATUS */
d26e6a028   Jiri Pirko   netfilter: ctnetl...
557
  	       + ctnetlink_counters_size(ct)
a992ca2a0   Pablo Neira Ayuso   netfilter: nf_con...
558
  	       + ctnetlink_timestamp_size(ct)
03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
559
560
561
562
  	       + nla_total_size(sizeof(u_int32_t)) /* CTA_TIMEOUT */
  	       + nla_total_size(0) /* CTA_PROTOINFO */
  	       + nla_total_size(0) /* CTA_HELP */
  	       + nla_total_size(NF_CT_HELPER_NAME_LEN) /* CTA_HELP_NAME */
cba85b532   Pablo Neira Ayuso   netfilter: fix ex...
563
  	       + ctnetlink_secctx_size(ct)
d271e8bd8   Holger Eitzenberger   ctnetlink: comput...
564
  #ifdef CONFIG_NF_NAT_NEEDED
03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
565
566
  	       + 2 * nla_total_size(0) /* CTA_NAT_SEQ_ADJ_ORIG|REPL */
  	       + 6 * nla_total_size(sizeof(u_int32_t)) /* CTA_NAT_SEQ_OFFSET */
d271e8bd8   Holger Eitzenberger   ctnetlink: comput...
567
568
  #endif
  #ifdef CONFIG_NF_CONNTRACK_MARK
03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
569
  	       + nla_total_size(sizeof(u_int32_t)) /* CTA_MARK */
d271e8bd8   Holger Eitzenberger   ctnetlink: comput...
570
  #endif
03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
571
  	       + ctnetlink_proto_size(ct)
0ceabd838   Florian Westphal   netfilter: ctnetl...
572
  	       + ctnetlink_label_size(ct)
03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
573
  	       ;
2732c4e45   Holger Eitzenberger   netfilter: ctnetl...
574
  }
8e36c4b5b   Pablo Neira Ayuso   netfilter: ctnetl...
575
  #ifdef CONFIG_NF_CONNTRACK_EVENTS
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
576
577
  static int
  ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
578
  {
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
579
  	struct net *net;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
580
581
  	struct nlmsghdr *nlh;
  	struct nfgenmsg *nfmsg;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
582
  	struct nlattr *nest_parms;
19abb7b09   Pablo Neira Ayuso   netfilter: ctnetl...
583
  	struct nf_conn *ct = item->ct;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
584
585
  	struct sk_buff *skb;
  	unsigned int type;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
586
  	unsigned int flags = 0, group;
dd7669a92   Pablo Neira Ayuso   netfilter: conntr...
587
  	int err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
588
589
  
  	/* ignore our fake conntrack entry */
5bfddbd46   Eric Dumazet   netfilter: nf_con...
590
  	if (nf_ct_is_untracked(ct))
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
591
  		return 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
592

a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
593
  	if (events & (1 << IPCT_DESTROY)) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
594
595
  		type = IPCTNL_MSG_CT_DELETE;
  		group = NFNLGRP_CONNTRACK_DESTROY;
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
596
  	} else  if (events & ((1 << IPCT_NEW) | (1 << IPCT_RELATED))) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
597
598
  		type = IPCTNL_MSG_CT_NEW;
  		flags = NLM_F_CREATE|NLM_F_EXCL;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
599
  		group = NFNLGRP_CONNTRACK_NEW;
17e6e4eac   Pablo Neira Ayuso   netfilter: conntr...
600
  	} else  if (events) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
601
602
603
  		type = IPCTNL_MSG_CT_NEW;
  		group = NFNLGRP_CONNTRACK_UPDATE;
  	} else
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
604
  		return 0;
a24276924   Patrick McHardy   [NETFILTER]: ctne...
605

9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
606
607
  	net = nf_ct_net(ct);
  	if (!item->report && !nfnetlink_has_listeners(net, group))
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
608
  		return 0;
a24276924   Patrick McHardy   [NETFILTER]: ctne...
609

03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
610
611
  	skb = nlmsg_new(ctnetlink_nlmsg_size(ct), GFP_ATOMIC);
  	if (skb == NULL)
150ace0db   Pablo Neira Ayuso   netfilter: ctnetl...
612
  		goto errout;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
613

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
614
  	type |= NFNL_SUBSYS_CTNETLINK << 8;
15e473046   Eric W. Biederman   netlink: Rename p...
615
  	nlh = nlmsg_put(skb, item->portid, 0, type, sizeof(*nfmsg), flags);
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
616
617
  	if (nlh == NULL)
  		goto nlmsg_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
618

96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
619
  	nfmsg = nlmsg_data(nlh);
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
620
  	nfmsg->nfgen_family = nf_ct_l3num(ct);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
621
622
  	nfmsg->version	= NFNETLINK_V0;
  	nfmsg->res_id	= 0;
528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
623
  	rcu_read_lock();
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
624
625
626
  	nest_parms = nla_nest_start(skb, CTA_TUPLE_ORIG | NLA_F_NESTED);
  	if (!nest_parms)
  		goto nla_put_failure;
f2f3e38c6   Pablo Neira Ayuso   netfilter: ctnetl...
627
  	if (ctnetlink_dump_tuples(skb, nf_ct_tuple(ct, IP_CT_DIR_ORIGINAL)) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
628
629
  		goto nla_put_failure;
  	nla_nest_end(skb, nest_parms);
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
630

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
631
632
633
  	nest_parms = nla_nest_start(skb, CTA_TUPLE_REPLY | NLA_F_NESTED);
  	if (!nest_parms)
  		goto nla_put_failure;
f2f3e38c6   Pablo Neira Ayuso   netfilter: ctnetl...
634
  	if (ctnetlink_dump_tuples(skb, nf_ct_tuple(ct, IP_CT_DIR_REPLY)) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
635
636
  		goto nla_put_failure;
  	nla_nest_end(skb, nest_parms);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
637

cc1eb4313   David S. Miller   nf_conntrack_netl...
638
639
640
  	if (nf_ct_zone(ct) &&
  	    nla_put_be16(skb, CTA_ZONE, htons(nf_ct_zone(ct))))
  		goto nla_put_failure;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
641

1eedf6999   Eric Leblond   netfilter: ctnetl...
642
643
  	if (ctnetlink_dump_id(skb, ct) < 0)
  		goto nla_put_failure;
e57dce60c   Fabian Hugelshofer   netfilter: ctnetl...
644
645
  	if (ctnetlink_dump_status(skb, ct) < 0)
  		goto nla_put_failure;
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
646
  	if (events & (1 << IPCT_DESTROY)) {
80e60e67b   Pablo Neira Ayuso   netfilter: ctnetl...
647
648
649
650
  		if (ctnetlink_dump_counters(skb, ct,
  					    IP_CT_DIR_ORIGINAL, type) < 0 ||
  		    ctnetlink_dump_counters(skb, ct,
  					    IP_CT_DIR_REPLY, type) < 0 ||
a992ca2a0   Pablo Neira Ayuso   netfilter: nf_con...
651
  		    ctnetlink_dump_timestamp(skb, ct) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
652
  			goto nla_put_failure;
7b621c1ea   Pablo Neira Ayuso   [NETFILTER]: ctne...
653
  	} else {
7b621c1ea   Pablo Neira Ayuso   [NETFILTER]: ctne...
654
  		if (ctnetlink_dump_timeout(skb, ct) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
655
  			goto nla_put_failure;
7b621c1ea   Pablo Neira Ayuso   [NETFILTER]: ctne...
656

a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
657
  		if (events & (1 << IPCT_PROTOINFO)
7b621c1ea   Pablo Neira Ayuso   [NETFILTER]: ctne...
658
  		    && ctnetlink_dump_protoinfo(skb, ct) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
659
  			goto nla_put_failure;
7b621c1ea   Pablo Neira Ayuso   [NETFILTER]: ctne...
660

a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
661
  		if ((events & (1 << IPCT_HELPER) || nfct_help(ct))
7b621c1ea   Pablo Neira Ayuso   [NETFILTER]: ctne...
662
  		    && ctnetlink_dump_helpinfo(skb, ct) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
663
  			goto nla_put_failure;
7b621c1ea   Pablo Neira Ayuso   [NETFILTER]: ctne...
664

ff660c80d   Eric Paris   secmark: fix conf...
665
  #ifdef CONFIG_NF_CONNTRACK_SECMARK
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
666
  		if ((events & (1 << IPCT_SECMARK) || ct->secmark)
1cc63249a   Eric Paris   conntrack: export...
667
  		    && ctnetlink_dump_secctx(skb, ct) < 0)
37fccd857   Pablo Neira Ayuso   [NETFILTER]: ctne...
668
  			goto nla_put_failure;
ff660c80d   Eric Paris   secmark: fix conf...
669
  #endif
0ceabd838   Florian Westphal   netfilter: ctnetl...
670
671
672
  		if (events & (1 << IPCT_LABEL) &&
  		     ctnetlink_dump_labels(skb, ct) < 0)
  			goto nla_put_failure;
7b621c1ea   Pablo Neira Ayuso   [NETFILTER]: ctne...
673

a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
674
  		if (events & (1 << IPCT_RELATED) &&
0f417ce98   Pablo Neira Ayuso   [NETFILTER]: ctne...
675
676
  		    ctnetlink_dump_master(skb, ct) < 0)
  			goto nla_put_failure;
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
677
  		if (events & (1 << IPCT_NATSEQADJ) &&
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
678
679
  		    ctnetlink_dump_nat_seq_adj(skb, ct) < 0)
  			goto nla_put_failure;
7b621c1ea   Pablo Neira Ayuso   [NETFILTER]: ctne...
680
  	}
b9a37e0c8   Pablo Neira Ayuso   [NETFILTER]: ctne...
681

a83099a60   Eric Leblond   [NETFILTER]: nf_c...
682
  #ifdef CONFIG_NF_CONNTRACK_MARK
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
683
  	if ((events & (1 << IPCT_MARK) || ct->mark)
a83099a60   Eric Leblond   [NETFILTER]: nf_c...
684
685
686
  	    && ctnetlink_dump_mark(skb, ct) < 0)
  		goto nla_put_failure;
  #endif
528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
687
  	rcu_read_unlock();
a83099a60   Eric Leblond   [NETFILTER]: nf_c...
688

96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
689
  	nlmsg_end(skb, nlh);
15e473046   Eric W. Biederman   netlink: Rename p...
690
  	err = nfnetlink_send(skb, net, item->portid, group, item->report,
cd8c20b65   Alexey Dobriyan   netfilter: nfnetl...
691
  			     GFP_ATOMIC);
dd7669a92   Pablo Neira Ayuso   netfilter: conntr...
692
693
  	if (err == -ENOBUFS || err == -EAGAIN)
  		return -ENOBUFS;
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
694
  	return 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
695

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
696
  nla_put_failure:
528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
697
  	rcu_read_unlock();
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
698
  	nlmsg_cancel(skb, nlh);
528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
699
  nlmsg_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
700
  	kfree_skb(skb);
150ace0db   Pablo Neira Ayuso   netfilter: ctnetl...
701
  errout:
37b7ef720   Pablo Neira Ayuso   netfilter: ctnetl...
702
703
  	if (nfnetlink_set_err(net, 0, group, -ENOBUFS) > 0)
  		return -ENOBUFS;
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
704
  	return 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
705
706
707
708
709
  }
  #endif /* CONFIG_NF_CONNTRACK_EVENTS */
  
  static int ctnetlink_done(struct netlink_callback *cb)
  {
89f2e2188   Patrick McHardy   [NETFILTER]: ctne...
710
711
  	if (cb->args[1])
  		nf_ct_put((struct nf_conn *)cb->args[1]);
0f298a285   Pablo Neira Ayuso   netfilter: ctnetl...
712
713
  	if (cb->data)
  		kfree(cb->data);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
714
715
  	return 0;
  }
0f298a285   Pablo Neira Ayuso   netfilter: ctnetl...
716
717
718
719
720
721
  struct ctnetlink_dump_filter {
  	struct {
  		u_int32_t val;
  		u_int32_t mask;
  	} mark;
  };
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
722
723
724
  static int
  ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
  {
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
725
  	struct net *net = sock_net(skb->sk);
89f2e2188   Patrick McHardy   [NETFILTER]: ctne...
726
  	struct nf_conn *ct, *last;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
727
  	struct nf_conntrack_tuple_hash *h;
ea781f197   Eric Dumazet   netfilter: nf_con...
728
  	struct hlist_nulls_node *n;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
729
  	struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
87711cb81   Pablo Neira Ayuso   [NETFILTER]: Filt...
730
  	u_int8_t l3proto = nfmsg->nfgen_family;
3b988ece9   Hans Schillstrom   netfilter: ctnetl...
731
  	int res;
0f298a285   Pablo Neira Ayuso   netfilter: ctnetl...
732
733
734
  #ifdef CONFIG_NF_CONNTRACK_MARK
  	const struct ctnetlink_dump_filter *filter = cb->data;
  #endif
3b988ece9   Hans Schillstrom   netfilter: ctnetl...
735

13ee6ac57   Stephen Hemminger   netfilter: fix ra...
736
  	spin_lock_bh(&nf_conntrack_lock);
d205dc407   Patrick McHardy   [NETFILTER]: ctne...
737
  	last = (struct nf_conn *)cb->args[1];
9ab99d5a4   Patrick McHardy   Merge branch 'mas...
738
  	for (; cb->args[0] < net->ct.htable_size; cb->args[0]++) {
89f2e2188   Patrick McHardy   [NETFILTER]: ctne...
739
  restart:
13ee6ac57   Stephen Hemminger   netfilter: fix ra...
740
  		hlist_nulls_for_each_entry(h, n, &net->ct.hash[cb->args[0]],
ea781f197   Eric Dumazet   netfilter: nf_con...
741
  					 hnnode) {
5b1158e90   Jozsef Kadlecsik   [NETFILTER]: Add ...
742
  			if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
743
744
  				continue;
  			ct = nf_ct_tuplehash_to_ctrack(h);
87711cb81   Pablo Neira Ayuso   [NETFILTER]: Filt...
745
746
747
  			/* Dump entries of a given L3 protocol number.
  			 * If it is not specified, ie. l3proto == 0,
  			 * then dump everything. */
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
748
  			if (l3proto && nf_ct_l3num(ct) != l3proto)
13ee6ac57   Stephen Hemminger   netfilter: fix ra...
749
  				continue;
d205dc407   Patrick McHardy   [NETFILTER]: ctne...
750
751
  			if (cb->args[1]) {
  				if (ct != last)
13ee6ac57   Stephen Hemminger   netfilter: fix ra...
752
  					continue;
d205dc407   Patrick McHardy   [NETFILTER]: ctne...
753
  				cb->args[1] = 0;
89f2e2188   Patrick McHardy   [NETFILTER]: ctne...
754
  			}
0f298a285   Pablo Neira Ayuso   netfilter: ctnetl...
755
756
757
758
759
760
  #ifdef CONFIG_NF_CONNTRACK_MARK
  			if (filter && !((ct->mark & filter->mark.mask) ==
  					filter->mark.val)) {
  				continue;
  			}
  #endif
3b988ece9   Hans Schillstrom   netfilter: ctnetl...
761
762
  			rcu_read_lock();
  			res =
15e473046   Eric W. Biederman   netlink: Rename p...
763
  			ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).portid,
3b988ece9   Hans Schillstrom   netfilter: ctnetl...
764
765
766
767
768
  					    cb->nlh->nlmsg_seq,
  					    NFNL_MSG_TYPE(cb->nlh->nlmsg_type),
  					    ct);
  			rcu_read_unlock();
  			if (res < 0) {
c71caf411   Pablo Neira Ayuso   netfilter: ctnetl...
769
  				nf_conntrack_get(&ct->ct_general);
89f2e2188   Patrick McHardy   [NETFILTER]: ctne...
770
  				cb->args[1] = (unsigned long)ct;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
771
  				goto out;
89f2e2188   Patrick McHardy   [NETFILTER]: ctne...
772
773
  			}
  		}
d205dc407   Patrick McHardy   [NETFILTER]: ctne...
774
  		if (cb->args[1]) {
89f2e2188   Patrick McHardy   [NETFILTER]: ctne...
775
776
  			cb->args[1] = 0;
  			goto restart;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
777
778
  		}
  	}
89f2e2188   Patrick McHardy   [NETFILTER]: ctne...
779
  out:
13ee6ac57   Stephen Hemminger   netfilter: fix ra...
780
  	spin_unlock_bh(&nf_conntrack_lock);
d205dc407   Patrick McHardy   [NETFILTER]: ctne...
781
782
  	if (last)
  		nf_ct_put(last);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
783

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
784
785
  	return skb->len;
  }
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
786
  static inline int
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
787
  ctnetlink_parse_tuple_ip(struct nlattr *attr, struct nf_conntrack_tuple *tuple)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
788
  {
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
789
  	struct nlattr *tb[CTA_IP_MAX+1];
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
790
791
  	struct nf_conntrack_l3proto *l3proto;
  	int ret = 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
792
  	nla_parse_nested(tb, CTA_IP_MAX, attr, NULL);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
793

cd91566e4   Florian Westphal   netfilter: ctnetl...
794
795
  	rcu_read_lock();
  	l3proto = __nf_ct_l3proto_find(tuple->src.l3num);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
796

f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
797
798
799
800
801
802
  	if (likely(l3proto->nlattr_to_tuple)) {
  		ret = nla_validate_nested(attr, CTA_IP_MAX,
  					  l3proto->nla_policy);
  		if (ret == 0)
  			ret = l3proto->nlattr_to_tuple(tb, tuple);
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
803

cd91566e4   Florian Westphal   netfilter: ctnetl...
804
  	rcu_read_unlock();
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
805

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
806
807
  	return ret;
  }
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
808
809
  static const struct nla_policy proto_nla_policy[CTA_PROTO_MAX+1] = {
  	[CTA_PROTO_NUM]	= { .type = NLA_U8 },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
810
811
812
  };
  
  static inline int
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
813
  ctnetlink_parse_tuple_proto(struct nlattr *attr,
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
814
815
  			    struct nf_conntrack_tuple *tuple)
  {
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
816
  	struct nlattr *tb[CTA_PROTO_MAX+1];
605dcad6c   Martin Josefsson   [NETFILTER]: nf_c...
817
  	struct nf_conntrack_l4proto *l4proto;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
818
  	int ret = 0;
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
819
820
821
  	ret = nla_parse_nested(tb, CTA_PROTO_MAX, attr, proto_nla_policy);
  	if (ret < 0)
  		return ret;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
822

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
823
  	if (!tb[CTA_PROTO_NUM])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
824
  		return -EINVAL;
77236b6e3   Patrick McHardy   [NETFILTER]: ctne...
825
  	tuple->dst.protonum = nla_get_u8(tb[CTA_PROTO_NUM]);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
826

cd91566e4   Florian Westphal   netfilter: ctnetl...
827
828
  	rcu_read_lock();
  	l4proto = __nf_ct_l4proto_find(tuple->src.l3num, tuple->dst.protonum);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
829

f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
830
831
832
833
834
835
  	if (likely(l4proto->nlattr_to_tuple)) {
  		ret = nla_validate_nested(attr, CTA_PROTO_MAX,
  					  l4proto->nla_policy);
  		if (ret == 0)
  			ret = l4proto->nlattr_to_tuple(tb, tuple);
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
836

cd91566e4   Florian Westphal   netfilter: ctnetl...
837
  	rcu_read_unlock();
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
838

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
839
840
  	return ret;
  }
d0b0268fd   Patrick McHardy   netfilter: ctnetl...
841
842
843
844
  static const struct nla_policy tuple_nla_policy[CTA_TUPLE_MAX+1] = {
  	[CTA_TUPLE_IP]		= { .type = NLA_NESTED },
  	[CTA_TUPLE_PROTO]	= { .type = NLA_NESTED },
  };
bb5cf80e9   Ilpo Järvinen   [NETFILTER]: Kill...
845
  static int
399383246   Patrick McHardy   netfilter: nfnetl...
846
847
  ctnetlink_parse_tuple(const struct nlattr * const cda[],
  		      struct nf_conntrack_tuple *tuple,
a00f1f368   Patrick McHardy   netfilter: ctnetl...
848
  		      enum ctattr_type type, u_int8_t l3num)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
849
  {
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
850
  	struct nlattr *tb[CTA_TUPLE_MAX+1];
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
851
  	int err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
852
  	memset(tuple, 0, sizeof(*tuple));
d0b0268fd   Patrick McHardy   netfilter: ctnetl...
853
  	nla_parse_nested(tb, CTA_TUPLE_MAX, cda[type], tuple_nla_policy);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
854

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
855
  	if (!tb[CTA_TUPLE_IP])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
856
857
858
  		return -EINVAL;
  
  	tuple->src.l3num = l3num;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
859
  	err = ctnetlink_parse_tuple_ip(tb[CTA_TUPLE_IP], tuple);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
860
861
  	if (err < 0)
  		return err;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
862
  	if (!tb[CTA_TUPLE_PROTO])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
863
  		return -EINVAL;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
864
  	err = ctnetlink_parse_tuple_proto(tb[CTA_TUPLE_PROTO], tuple);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
865
866
867
868
869
870
871
872
  	if (err < 0)
  		return err;
  
  	/* orig and expect tuples get DIR_ORIGINAL */
  	if (type == CTA_TUPLE_REPLY)
  		tuple->dst.dir = IP_CT_DIR_REPLY;
  	else
  		tuple->dst.dir = IP_CT_DIR_ORIGINAL;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
873
874
  	return 0;
  }
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
875
876
877
878
879
880
881
882
883
884
885
886
887
888
  static int
  ctnetlink_parse_zone(const struct nlattr *attr, u16 *zone)
  {
  	if (attr)
  #ifdef CONFIG_NF_CONNTRACK_ZONES
  		*zone = ntohs(nla_get_be16(attr));
  #else
  		return -EOPNOTSUPP;
  #endif
  	else
  		*zone = 0;
  
  	return 0;
  }
d0b0268fd   Patrick McHardy   netfilter: ctnetl...
889
  static const struct nla_policy help_nla_policy[CTA_HELP_MAX+1] = {
6d1fafcae   Florian Westphal   netfilter: ctnetl...
890
891
  	[CTA_HELP_NAME]		= { .type = NLA_NUL_STRING,
  				    .len = NF_CT_HELPER_NAME_LEN - 1 },
d0b0268fd   Patrick McHardy   netfilter: ctnetl...
892
  };
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
893
  static inline int
ae243bee3   Pablo Neira Ayuso   netfilter: ctnetl...
894
895
  ctnetlink_parse_help(const struct nlattr *attr, char **helper_name,
  		     struct nlattr **helpinfo)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
896
  {
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
897
  	struct nlattr *tb[CTA_HELP_MAX+1];
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
898

d0b0268fd   Patrick McHardy   netfilter: ctnetl...
899
  	nla_parse_nested(tb, CTA_HELP_MAX, attr, help_nla_policy);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
900

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
901
  	if (!tb[CTA_HELP_NAME])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
902
  		return -EINVAL;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
903
  	*helper_name = nla_data(tb[CTA_HELP_NAME]);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
904

ae243bee3   Pablo Neira Ayuso   netfilter: ctnetl...
905
906
  	if (tb[CTA_HELP_INFO])
  		*helpinfo = tb[CTA_HELP_INFO];
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
907
908
  	return 0;
  }
9b21f6a90   Florian Westphal   netfilter: ctnetl...
909
  #define __CTA_LABELS_MAX_LENGTH ((XT_CONNLABEL_MAXBIT + 1) / BITS_PER_BYTE)
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
910
  static const struct nla_policy ct_nla_policy[CTA_MAX+1] = {
d0b0268fd   Patrick McHardy   netfilter: ctnetl...
911
912
  	[CTA_TUPLE_ORIG]	= { .type = NLA_NESTED },
  	[CTA_TUPLE_REPLY]	= { .type = NLA_NESTED },
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
913
  	[CTA_STATUS] 		= { .type = NLA_U32 },
d0b0268fd   Patrick McHardy   netfilter: ctnetl...
914
915
916
  	[CTA_PROTOINFO]		= { .type = NLA_NESTED },
  	[CTA_HELP]		= { .type = NLA_NESTED },
  	[CTA_NAT_SRC]		= { .type = NLA_NESTED },
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
917
918
  	[CTA_TIMEOUT] 		= { .type = NLA_U32 },
  	[CTA_MARK]		= { .type = NLA_U32 },
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
919
  	[CTA_ID]		= { .type = NLA_U32 },
d0b0268fd   Patrick McHardy   netfilter: ctnetl...
920
921
  	[CTA_NAT_DST]		= { .type = NLA_NESTED },
  	[CTA_TUPLE_MASTER]	= { .type = NLA_NESTED },
6d1fafcae   Florian Westphal   netfilter: ctnetl...
922
923
  	[CTA_NAT_SEQ_ADJ_ORIG]  = { .type = NLA_NESTED },
  	[CTA_NAT_SEQ_ADJ_REPLY] = { .type = NLA_NESTED },
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
924
  	[CTA_ZONE]		= { .type = NLA_U16 },
0f298a285   Pablo Neira Ayuso   netfilter: ctnetl...
925
  	[CTA_MARK_MASK]		= { .type = NLA_U32 },
9b21f6a90   Florian Westphal   netfilter: ctnetl...
926
927
928
929
  	[CTA_LABELS]		= { .type = NLA_BINARY,
  				    .len = __CTA_LABELS_MAX_LENGTH },
  	[CTA_LABELS_MASK]	= { .type = NLA_BINARY,
  				    .len = __CTA_LABELS_MAX_LENGTH },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
930
931
932
  };
  
  static int
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
933
  ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
399383246   Patrick McHardy   netfilter: nfnetl...
934
935
  			const struct nlmsghdr *nlh,
  			const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
936
  {
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
937
  	struct net *net = sock_net(ctnl);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
938
939
940
  	struct nf_conntrack_tuple_hash *h;
  	struct nf_conntrack_tuple tuple;
  	struct nf_conn *ct;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
941
  	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
942
  	u_int8_t u3 = nfmsg->nfgen_family;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
943
944
945
946
947
948
  	u16 zone;
  	int err;
  
  	err = ctnetlink_parse_zone(cda[CTA_ZONE], &zone);
  	if (err < 0)
  		return err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
949

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
950
  	if (cda[CTA_TUPLE_ORIG])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
951
  		err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG, u3);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
952
  	else if (cda[CTA_TUPLE_REPLY])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
953
954
955
  		err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY, u3);
  	else {
  		/* Flush the whole table */
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
956
  		nf_conntrack_flush_report(net,
15e473046   Eric W. Biederman   netlink: Rename p...
957
  					 NETLINK_CB(skb).portid,
274d383b9   Pablo Neira Ayuso   netfilter: conntr...
958
  					 nlmsg_report(nlh));
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
959
960
961
962
963
  		return 0;
  	}
  
  	if (err < 0)
  		return err;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
964
  	h = nf_conntrack_find_get(net, zone, &tuple);
9ea8cfd6a   Pablo Neira Ayuso   [NETFILTER]: ctne...
965
  	if (!h)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
966
  		return -ENOENT;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
967
968
  
  	ct = nf_ct_tuplehash_to_ctrack(h);
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
969

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
970
  	if (cda[CTA_ID]) {
77236b6e3   Patrick McHardy   [NETFILTER]: ctne...
971
  		u_int32_t id = ntohl(nla_get_be32(cda[CTA_ID]));
7f85f9147   Patrick McHardy   [NETFILTER]: nf_c...
972
  		if (id != (u32)(unsigned long)ct) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
973
974
975
  			nf_ct_put(ct);
  			return -ENOENT;
  		}
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
976
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
977

a16a1647f   Pablo Neira Ayuso   netfilter: ctnetl...
978
979
  	if (del_timer(&ct->timeout)) {
  		if (nf_conntrack_event_report(IPCT_DESTROY, ct,
15e473046   Eric W. Biederman   netlink: Rename p...
980
  					      NETLINK_CB(skb).portid,
a16a1647f   Pablo Neira Ayuso   netfilter: ctnetl...
981
982
983
  					      nlmsg_report(nlh)) < 0) {
  			nf_ct_delete_from_lists(ct);
  			/* we failed to report the event, try later */
04dac0111   Pablo Neira Ayuso   netfilter: nf_con...
984
  			nf_ct_dying_timeout(ct);
a16a1647f   Pablo Neira Ayuso   netfilter: ctnetl...
985
986
987
988
989
  			nf_ct_put(ct);
  			return 0;
  		}
  		/* death_by_timeout would report the event again */
  		set_bit(IPS_DYING_BIT, &ct->status);
dd7669a92   Pablo Neira Ayuso   netfilter: conntr...
990
  		nf_ct_delete_from_lists(ct);
dd7669a92   Pablo Neira Ayuso   netfilter: conntr...
991
  		nf_ct_put(ct);
dd7669a92   Pablo Neira Ayuso   netfilter: conntr...
992
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
993
  	nf_ct_put(ct);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
994
995
996
997
998
  
  	return 0;
  }
  
  static int
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
999
  ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
399383246   Patrick McHardy   netfilter: nfnetl...
1000
1001
  			const struct nlmsghdr *nlh,
  			const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1002
  {
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
1003
  	struct net *net = sock_net(ctnl);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1004
1005
1006
1007
  	struct nf_conntrack_tuple_hash *h;
  	struct nf_conntrack_tuple tuple;
  	struct nf_conn *ct;
  	struct sk_buff *skb2 = NULL;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
1008
  	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1009
  	u_int8_t u3 = nfmsg->nfgen_family;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
1010
1011
  	u16 zone;
  	int err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1012

80d326fab   Pablo Neira Ayuso   netlink: add netl...
1013
1014
1015
1016
1017
  	if (nlh->nlmsg_flags & NLM_F_DUMP) {
  		struct netlink_dump_control c = {
  			.dump = ctnetlink_dump_table,
  			.done = ctnetlink_done,
  		};
0f298a285   Pablo Neira Ayuso   netfilter: ctnetl...
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
  #ifdef CONFIG_NF_CONNTRACK_MARK
  		if (cda[CTA_MARK] && cda[CTA_MARK_MASK]) {
  			struct ctnetlink_dump_filter *filter;
  
  			filter = kzalloc(sizeof(struct ctnetlink_dump_filter),
  					 GFP_ATOMIC);
  			if (filter == NULL)
  				return -ENOMEM;
  
  			filter->mark.val = ntohl(nla_get_be32(cda[CTA_MARK]));
  			filter->mark.mask =
  				ntohl(nla_get_be32(cda[CTA_MARK_MASK]));
  			c.data = filter;
  		}
  #endif
80d326fab   Pablo Neira Ayuso   netlink: add netl...
1033
1034
  		return netlink_dump_start(ctnl, skb, nlh, &c);
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1035

ef00f89f1   Patrick McHardy   netfilter: ctnetl...
1036
1037
1038
  	err = ctnetlink_parse_zone(cda[CTA_ZONE], &zone);
  	if (err < 0)
  		return err;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1039
  	if (cda[CTA_TUPLE_ORIG])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1040
  		err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG, u3);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1041
  	else if (cda[CTA_TUPLE_REPLY])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1042
1043
1044
1045
1046
1047
  		err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY, u3);
  	else
  		return -EINVAL;
  
  	if (err < 0)
  		return err;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
1048
  	h = nf_conntrack_find_get(net, zone, &tuple);
9ea8cfd6a   Pablo Neira Ayuso   [NETFILTER]: ctne...
1049
  	if (!h)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1050
  		return -ENOENT;
9ea8cfd6a   Pablo Neira Ayuso   [NETFILTER]: ctne...
1051

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1052
1053
1054
  	ct = nf_ct_tuplehash_to_ctrack(h);
  
  	err = -ENOMEM;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
1055
1056
  	skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
  	if (skb2 == NULL) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1057
1058
1059
  		nf_ct_put(ct);
  		return -ENOMEM;
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1060

528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
1061
  	rcu_read_lock();
15e473046   Eric W. Biederman   netlink: Rename p...
1062
  	err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).portid, nlh->nlmsg_seq,
80e60e67b   Pablo Neira Ayuso   netfilter: ctnetl...
1063
  				  NFNL_MSG_TYPE(nlh->nlmsg_type), ct);
528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
1064
  	rcu_read_unlock();
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1065
1066
1067
  	nf_ct_put(ct);
  	if (err <= 0)
  		goto free;
15e473046   Eric W. Biederman   netlink: Rename p...
1068
  	err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1069
1070
  	if (err < 0)
  		goto out;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1071
1072
1073
1074
1075
  	return 0;
  
  free:
  	kfree_skb(skb2);
  out:
f31e8d498   Pablo Neira Ayuso   netfilter: ctnetl...
1076
1077
  	/* this avoids a loop in nfnetlink. */
  	return err == -EAGAIN ? -ENOBUFS : err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1078
  }
d871befe3   Pablo Neira Ayuso   netfilter: ctnetl...
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
  static int ctnetlink_done_list(struct netlink_callback *cb)
  {
  	if (cb->args[1])
  		nf_ct_put((struct nf_conn *)cb->args[1]);
  	return 0;
  }
  
  static int
  ctnetlink_dump_list(struct sk_buff *skb, struct netlink_callback *cb,
  		    struct hlist_nulls_head *list)
  {
  	struct nf_conn *ct, *last;
  	struct nf_conntrack_tuple_hash *h;
  	struct hlist_nulls_node *n;
  	struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
  	u_int8_t l3proto = nfmsg->nfgen_family;
  	int res;
  
  	if (cb->args[2])
  		return 0;
  
  	spin_lock_bh(&nf_conntrack_lock);
  	last = (struct nf_conn *)cb->args[1];
  restart:
  	hlist_nulls_for_each_entry(h, n, list, hnnode) {
  		ct = nf_ct_tuplehash_to_ctrack(h);
  		if (l3proto && nf_ct_l3num(ct) != l3proto)
  			continue;
  		if (cb->args[1]) {
  			if (ct != last)
  				continue;
  			cb->args[1] = 0;
  		}
  		rcu_read_lock();
  		res = ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).portid,
  					  cb->nlh->nlmsg_seq,
  					  NFNL_MSG_TYPE(cb->nlh->nlmsg_type),
  					  ct);
  		rcu_read_unlock();
  		if (res < 0) {
  			nf_conntrack_get(&ct->ct_general);
  			cb->args[1] = (unsigned long)ct;
  			goto out;
  		}
  	}
  	if (cb->args[1]) {
  		cb->args[1] = 0;
  		goto restart;
  	} else
  		cb->args[2] = 1;
  out:
  	spin_unlock_bh(&nf_conntrack_lock);
  	if (last)
  		nf_ct_put(last);
  
  	return skb->len;
  }
  
  static int
  ctnetlink_dump_dying(struct sk_buff *skb, struct netlink_callback *cb)
  {
  	struct net *net = sock_net(skb->sk);
  
  	return ctnetlink_dump_list(skb, cb, &net->ct.dying);
  }
  
  static int
  ctnetlink_get_ct_dying(struct sock *ctnl, struct sk_buff *skb,
  		       const struct nlmsghdr *nlh,
  		       const struct nlattr * const cda[])
  {
  	if (nlh->nlmsg_flags & NLM_F_DUMP) {
  		struct netlink_dump_control c = {
  			.dump = ctnetlink_dump_dying,
  			.done = ctnetlink_done_list,
  		};
  		return netlink_dump_start(ctnl, skb, nlh, &c);
  	}
  
  	return -EOPNOTSUPP;
  }
  
  static int
  ctnetlink_dump_unconfirmed(struct sk_buff *skb, struct netlink_callback *cb)
  {
  	struct net *net = sock_net(skb->sk);
  
  	return ctnetlink_dump_list(skb, cb, &net->ct.unconfirmed);
  }
  
  static int
  ctnetlink_get_ct_unconfirmed(struct sock *ctnl, struct sk_buff *skb,
  			     const struct nlmsghdr *nlh,
  			     const struct nlattr * const cda[])
  {
  	if (nlh->nlmsg_flags & NLM_F_DUMP) {
  		struct netlink_dump_control c = {
  			.dump = ctnetlink_dump_unconfirmed,
  			.done = ctnetlink_done_list,
  		};
  		return netlink_dump_start(ctnl, skb, nlh, &c);
  	}
  
  	return -EOPNOTSUPP;
  }
67671841d   Pablo Neira Ayuso   netfilter: fix co...
1184
  #ifdef CONFIG_NF_NAT_NEEDED
bb5cf80e9   Ilpo Järvinen   [NETFILTER]: Kill...
1185
  static int
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1186
1187
  ctnetlink_parse_nat_setup(struct nf_conn *ct,
  			  enum nf_nat_manip_type manip,
399383246   Patrick McHardy   netfilter: nfnetl...
1188
  			  const struct nlattr *attr)
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1189
1190
  {
  	typeof(nfnetlink_parse_nat_setup_hook) parse_nat_setup;
c7232c997   Patrick McHardy   netfilter: add pr...
1191
  	int err;
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1192
1193
1194
  
  	parse_nat_setup = rcu_dereference(nfnetlink_parse_nat_setup_hook);
  	if (!parse_nat_setup) {
95a5afca4   Johannes Berg   net: Remove CONFI...
1195
  #ifdef CONFIG_MODULES
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1196
  		rcu_read_unlock();
c14b78e7d   Pablo Neira Ayuso   netfilter: nfnetl...
1197
  		nfnl_unlock(NFNL_SUBSYS_CTNETLINK);
c7232c997   Patrick McHardy   netfilter: add pr...
1198
  		if (request_module("nf-nat") < 0) {
c14b78e7d   Pablo Neira Ayuso   netfilter: nfnetl...
1199
  			nfnl_lock(NFNL_SUBSYS_CTNETLINK);
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1200
1201
1202
  			rcu_read_lock();
  			return -EOPNOTSUPP;
  		}
c14b78e7d   Pablo Neira Ayuso   netfilter: nfnetl...
1203
  		nfnl_lock(NFNL_SUBSYS_CTNETLINK);
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1204
1205
1206
1207
1208
1209
  		rcu_read_lock();
  		if (nfnetlink_parse_nat_setup_hook)
  			return -EAGAIN;
  #endif
  		return -EOPNOTSUPP;
  	}
c7232c997   Patrick McHardy   netfilter: add pr...
1210
1211
1212
1213
  	err = parse_nat_setup(ct, manip, attr);
  	if (err == -EAGAIN) {
  #ifdef CONFIG_MODULES
  		rcu_read_unlock();
c14b78e7d   Pablo Neira Ayuso   netfilter: nfnetl...
1214
  		nfnl_unlock(NFNL_SUBSYS_CTNETLINK);
c7232c997   Patrick McHardy   netfilter: add pr...
1215
  		if (request_module("nf-nat-%u", nf_ct_l3num(ct)) < 0) {
c14b78e7d   Pablo Neira Ayuso   netfilter: nfnetl...
1216
  			nfnl_lock(NFNL_SUBSYS_CTNETLINK);
c7232c997   Patrick McHardy   netfilter: add pr...
1217
1218
1219
  			rcu_read_lock();
  			return -EOPNOTSUPP;
  		}
c14b78e7d   Pablo Neira Ayuso   netfilter: nfnetl...
1220
  		nfnl_lock(NFNL_SUBSYS_CTNETLINK);
c7232c997   Patrick McHardy   netfilter: add pr...
1221
1222
1223
1224
1225
1226
  		rcu_read_lock();
  #else
  		err = -EOPNOTSUPP;
  #endif
  	}
  	return err;
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1227
  }
67671841d   Pablo Neira Ayuso   netfilter: fix co...
1228
  #endif
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1229
1230
  
  static int
399383246   Patrick McHardy   netfilter: nfnetl...
1231
  ctnetlink_change_status(struct nf_conn *ct, const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1232
1233
  {
  	unsigned long d;
77236b6e3   Patrick McHardy   [NETFILTER]: ctne...
1234
  	unsigned int status = ntohl(nla_get_be32(cda[CTA_STATUS]));
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1235
1236
1237
1238
  	d = ct->status ^ status;
  
  	if (d & (IPS_EXPECTED|IPS_CONFIRMED|IPS_DYING))
  		/* unchangeable */
0adf9d674   Pablo Neira Ayuso   netfilter: ctnetl...
1239
  		return -EBUSY;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
1240

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1241
1242
  	if (d & IPS_SEEN_REPLY && !(status & IPS_SEEN_REPLY))
  		/* SEEN_REPLY bit can only be set */
0adf9d674   Pablo Neira Ayuso   netfilter: ctnetl...
1243
  		return -EBUSY;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
1244

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1245
1246
  	if (d & IPS_ASSURED && !(status & IPS_ASSURED))
  		/* ASSURED bit can only be set */
0adf9d674   Pablo Neira Ayuso   netfilter: ctnetl...
1247
  		return -EBUSY;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1248

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1249
1250
  	/* Be careful here, modifying NAT bits can screw up things,
  	 * so don't let users modify them directly if they don't pass
5b1158e90   Jozsef Kadlecsik   [NETFILTER]: Add ...
1251
  	 * nf_nat_range. */
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1252
1253
1254
  	ct->status |= status & ~(IPS_NAT_DONE_MASK | IPS_NAT_MASK);
  	return 0;
  }
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1255
  static int
399383246   Patrick McHardy   netfilter: nfnetl...
1256
  ctnetlink_change_nat(struct nf_conn *ct, const struct nlattr * const cda[])
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1257
1258
1259
1260
1261
1262
  {
  #ifdef CONFIG_NF_NAT_NEEDED
  	int ret;
  
  	if (cda[CTA_NAT_DST]) {
  		ret = ctnetlink_parse_nat_setup(ct,
cbc9f2f4f   Patrick McHardy   netfilter: nf_nat...
1263
  						NF_NAT_MANIP_DST,
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1264
1265
1266
1267
1268
1269
  						cda[CTA_NAT_DST]);
  		if (ret < 0)
  			return ret;
  	}
  	if (cda[CTA_NAT_SRC]) {
  		ret = ctnetlink_parse_nat_setup(ct,
cbc9f2f4f   Patrick McHardy   netfilter: nf_nat...
1270
  						NF_NAT_MANIP_SRC,
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1271
1272
1273
1274
1275
1276
1277
1278
1279
  						cda[CTA_NAT_SRC]);
  		if (ret < 0)
  			return ret;
  	}
  	return 0;
  #else
  	return -EOPNOTSUPP;
  #endif
  }
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1280
1281
  
  static inline int
399383246   Patrick McHardy   netfilter: nfnetl...
1282
  ctnetlink_change_helper(struct nf_conn *ct, const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1283
1284
  {
  	struct nf_conntrack_helper *helper;
dc808fe28   Harald Welte   [NETFILTER] nf_co...
1285
  	struct nf_conn_help *help = nfct_help(ct);
29fe1b481   Pablo Neira Ayuso   netfilter: ctnetl...
1286
  	char *helpname = NULL;
ae243bee3   Pablo Neira Ayuso   netfilter: ctnetl...
1287
  	struct nlattr *helpinfo = NULL;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1288
  	int err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1289
1290
  	/* don't change helper of sibling connections */
  	if (ct->master)
0adf9d674   Pablo Neira Ayuso   netfilter: ctnetl...
1291
  		return -EBUSY;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1292

ae243bee3   Pablo Neira Ayuso   netfilter: ctnetl...
1293
  	err = ctnetlink_parse_help(cda[CTA_HELP], &helpname, &helpinfo);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1294
1295
  	if (err < 0)
  		return err;
df293bbb6   Yasuyuki Kozakai   [NETFILTER]: ctne...
1296
1297
  	if (!strcmp(helpname, "")) {
  		if (help && help->helper) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1298
1299
  			/* we had a helper before ... */
  			nf_ct_remove_expectations(ct);
a9b3cd7f3   Stephen Hemminger   rcu: convert uses...
1300
  			RCU_INIT_POINTER(help->helper, NULL);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1301
  		}
df293bbb6   Yasuyuki Kozakai   [NETFILTER]: ctne...
1302
1303
  
  		return 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1304
  	}
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
1305

794e68716   Patrick McHardy   netfilter: ctnetl...
1306
1307
  	helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct),
  					    nf_ct_protonum(ct));
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
  	if (helper == NULL) {
  #ifdef CONFIG_MODULES
  		spin_unlock_bh(&nf_conntrack_lock);
  
  		if (request_module("nfct-helper-%s", helpname) < 0) {
  			spin_lock_bh(&nf_conntrack_lock);
  			return -EOPNOTSUPP;
  		}
  
  		spin_lock_bh(&nf_conntrack_lock);
794e68716   Patrick McHardy   netfilter: ctnetl...
1318
1319
  		helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct),
  						    nf_ct_protonum(ct));
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1320
1321
1322
  		if (helper)
  			return -EAGAIN;
  #endif
0adf9d674   Pablo Neira Ayuso   netfilter: ctnetl...
1323
  		return -EOPNOTSUPP;
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1324
  	}
df293bbb6   Yasuyuki Kozakai   [NETFILTER]: ctne...
1325

ceceae1b1   Yasuyuki Kozakai   [NETFILTER]: nf_c...
1326
  	if (help) {
ae243bee3   Pablo Neira Ayuso   netfilter: ctnetl...
1327
1328
  		if (help->helper == helper) {
  			/* update private helper data if allowed. */
7be54ca47   Pablo Neira Ayuso   netfilter: nf_ct_...
1329
  			if (helper->from_nlattr)
ae243bee3   Pablo Neira Ayuso   netfilter: ctnetl...
1330
  				helper->from_nlattr(helpinfo, ct);
ceceae1b1   Yasuyuki Kozakai   [NETFILTER]: nf_c...
1331
  			return 0;
fd7462de4   Pablo Neira Ayuso   netfilter: ctnetl...
1332
  		} else
ceceae1b1   Yasuyuki Kozakai   [NETFILTER]: nf_c...
1333
  			return -EBUSY;
ceceae1b1   Yasuyuki Kozakai   [NETFILTER]: nf_c...
1334
  	}
df293bbb6   Yasuyuki Kozakai   [NETFILTER]: ctne...
1335

fd7462de4   Pablo Neira Ayuso   netfilter: ctnetl...
1336
1337
  	/* we cannot set a helper for an existing conntrack */
  	return -EOPNOTSUPP;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1338
1339
1340
  }
  
  static inline int
399383246   Patrick McHardy   netfilter: nfnetl...
1341
  ctnetlink_change_timeout(struct nf_conn *ct, const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1342
  {
77236b6e3   Patrick McHardy   [NETFILTER]: ctne...
1343
  	u_int32_t timeout = ntohl(nla_get_be32(cda[CTA_TIMEOUT]));
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
1344

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1345
1346
1347
1348
1349
1350
1351
1352
  	if (!del_timer(&ct->timeout))
  		return -ETIME;
  
  	ct->timeout.expires = jiffies + timeout * HZ;
  	add_timer(&ct->timeout);
  
  	return 0;
  }
d0b0268fd   Patrick McHardy   netfilter: ctnetl...
1353
1354
1355
1356
1357
  static const struct nla_policy protoinfo_policy[CTA_PROTOINFO_MAX+1] = {
  	[CTA_PROTOINFO_TCP]	= { .type = NLA_NESTED },
  	[CTA_PROTOINFO_DCCP]	= { .type = NLA_NESTED },
  	[CTA_PROTOINFO_SCTP]	= { .type = NLA_NESTED },
  };
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1358
  static inline int
399383246   Patrick McHardy   netfilter: nfnetl...
1359
  ctnetlink_change_protoinfo(struct nf_conn *ct, const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1360
  {
399383246   Patrick McHardy   netfilter: nfnetl...
1361
1362
  	const struct nlattr *attr = cda[CTA_PROTOINFO];
  	struct nlattr *tb[CTA_PROTOINFO_MAX+1];
605dcad6c   Martin Josefsson   [NETFILTER]: nf_c...
1363
  	struct nf_conntrack_l4proto *l4proto;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1364
  	int err = 0;
d0b0268fd   Patrick McHardy   netfilter: ctnetl...
1365
  	nla_parse_nested(tb, CTA_PROTOINFO_MAX, attr, protoinfo_policy);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1366

cd91566e4   Florian Westphal   netfilter: ctnetl...
1367
1368
  	rcu_read_lock();
  	l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct));
fdf708322   Patrick McHardy   [NETFILTER]: nfne...
1369
1370
  	if (l4proto->from_nlattr)
  		err = l4proto->from_nlattr(tb, ct);
cd91566e4   Florian Westphal   netfilter: ctnetl...
1371
  	rcu_read_unlock();
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1372
1373
1374
  
  	return err;
  }
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1375
  #ifdef CONFIG_NF_NAT_NEEDED
d0b0268fd   Patrick McHardy   netfilter: ctnetl...
1376
1377
1378
1379
1380
  static const struct nla_policy nat_seq_policy[CTA_NAT_SEQ_MAX+1] = {
  	[CTA_NAT_SEQ_CORRECTION_POS]	= { .type = NLA_U32 },
  	[CTA_NAT_SEQ_OFFSET_BEFORE]	= { .type = NLA_U32 },
  	[CTA_NAT_SEQ_OFFSET_AFTER]	= { .type = NLA_U32 },
  };
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1381
  static inline int
399383246   Patrick McHardy   netfilter: nfnetl...
1382
  change_nat_seq_adj(struct nf_nat_seq *natseq, const struct nlattr * const attr)
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1383
1384
  {
  	struct nlattr *cda[CTA_NAT_SEQ_MAX+1];
d0b0268fd   Patrick McHardy   netfilter: ctnetl...
1385
  	nla_parse_nested(cda, CTA_NAT_SEQ_MAX, attr, nat_seq_policy);
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1386
1387
1388
1389
1390
  
  	if (!cda[CTA_NAT_SEQ_CORRECTION_POS])
  		return -EINVAL;
  
  	natseq->correction_pos =
77236b6e3   Patrick McHardy   [NETFILTER]: ctne...
1391
  		ntohl(nla_get_be32(cda[CTA_NAT_SEQ_CORRECTION_POS]));
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1392
1393
1394
1395
1396
  
  	if (!cda[CTA_NAT_SEQ_OFFSET_BEFORE])
  		return -EINVAL;
  
  	natseq->offset_before =
77236b6e3   Patrick McHardy   [NETFILTER]: ctne...
1397
  		ntohl(nla_get_be32(cda[CTA_NAT_SEQ_OFFSET_BEFORE]));
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1398
1399
1400
1401
1402
  
  	if (!cda[CTA_NAT_SEQ_OFFSET_AFTER])
  		return -EINVAL;
  
  	natseq->offset_after =
77236b6e3   Patrick McHardy   [NETFILTER]: ctne...
1403
  		ntohl(nla_get_be32(cda[CTA_NAT_SEQ_OFFSET_AFTER]));
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1404
1405
1406
1407
1408
  
  	return 0;
  }
  
  static int
399383246   Patrick McHardy   netfilter: nfnetl...
1409
1410
  ctnetlink_change_nat_seq_adj(struct nf_conn *ct,
  			     const struct nlattr * const cda[])
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
  {
  	int ret = 0;
  	struct nf_conn_nat *nat = nfct_nat(ct);
  
  	if (!nat)
  		return 0;
  
  	if (cda[CTA_NAT_SEQ_ADJ_ORIG]) {
  		ret = change_nat_seq_adj(&nat->seq[IP_CT_DIR_ORIGINAL],
  					 cda[CTA_NAT_SEQ_ADJ_ORIG]);
  		if (ret < 0)
  			return ret;
  
  		ct->status |= IPS_SEQ_ADJUST;
  	}
  
  	if (cda[CTA_NAT_SEQ_ADJ_REPLY]) {
  		ret = change_nat_seq_adj(&nat->seq[IP_CT_DIR_REPLY],
  					 cda[CTA_NAT_SEQ_ADJ_REPLY]);
  		if (ret < 0)
  			return ret;
  
  		ct->status |= IPS_SEQ_ADJUST;
  	}
  
  	return 0;
  }
  #endif
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1439
  static int
9b21f6a90   Florian Westphal   netfilter: ctnetl...
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
  ctnetlink_attach_labels(struct nf_conn *ct, const struct nlattr * const cda[])
  {
  #ifdef CONFIG_NF_CONNTRACK_LABELS
  	size_t len = nla_len(cda[CTA_LABELS]);
  	const void *mask = cda[CTA_LABELS_MASK];
  
  	if (len & (sizeof(u32)-1)) /* must be multiple of u32 */
  		return -EINVAL;
  
  	if (mask) {
  		if (nla_len(cda[CTA_LABELS_MASK]) == 0 ||
  		    nla_len(cda[CTA_LABELS_MASK]) != len)
  			return -EINVAL;
  		mask = nla_data(cda[CTA_LABELS_MASK]);
  	}
  
  	len /= sizeof(u32);
  
  	return nf_connlabels_replace(ct, nla_data(cda[CTA_LABELS]), mask, len);
  #else
  	return -EOPNOTSUPP;
  #endif
  }
  
  static int
399383246   Patrick McHardy   netfilter: nfnetl...
1465
1466
  ctnetlink_change_conntrack(struct nf_conn *ct,
  			   const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1467
1468
  {
  	int err;
e098360f1   Pablo Neira Ayuso   netfilter: ctnetl...
1469
1470
1471
  	/* only allow NAT changes and master assignation for new conntracks */
  	if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST] || cda[CTA_TUPLE_MASTER])
  		return -EOPNOTSUPP;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1472
  	if (cda[CTA_HELP]) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1473
1474
1475
1476
  		err = ctnetlink_change_helper(ct, cda);
  		if (err < 0)
  			return err;
  	}
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1477
  	if (cda[CTA_TIMEOUT]) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1478
1479
1480
1481
  		err = ctnetlink_change_timeout(ct, cda);
  		if (err < 0)
  			return err;
  	}
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1482
  	if (cda[CTA_STATUS]) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1483
1484
1485
1486
  		err = ctnetlink_change_status(ct, cda);
  		if (err < 0)
  			return err;
  	}
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1487
  	if (cda[CTA_PROTOINFO]) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1488
1489
1490
1491
  		err = ctnetlink_change_protoinfo(ct, cda);
  		if (err < 0)
  			return err;
  	}
bcd1e830a   Martin Josefsson   [NETFILTER]: fix ...
1492
  #if defined(CONFIG_NF_CONNTRACK_MARK)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1493
  	if (cda[CTA_MARK])
77236b6e3   Patrick McHardy   [NETFILTER]: ctne...
1494
  		ct->mark = ntohl(nla_get_be32(cda[CTA_MARK]));
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1495
  #endif
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1496
1497
1498
1499
1500
1501
1502
  #ifdef CONFIG_NF_NAT_NEEDED
  	if (cda[CTA_NAT_SEQ_ADJ_ORIG] || cda[CTA_NAT_SEQ_ADJ_REPLY]) {
  		err = ctnetlink_change_nat_seq_adj(ct, cda);
  		if (err < 0)
  			return err;
  	}
  #endif
9b21f6a90   Florian Westphal   netfilter: ctnetl...
1503
1504
1505
1506
1507
  	if (cda[CTA_LABELS]) {
  		err = ctnetlink_attach_labels(ct, cda);
  		if (err < 0)
  			return err;
  	}
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1508

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1509
1510
  	return 0;
  }
f0a3c0869   Pablo Neira Ayuso   netfilter: ctnetl...
1511
  static struct nf_conn *
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
1512
  ctnetlink_create_conntrack(struct net *net, u16 zone,
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
1513
  			   const struct nlattr * const cda[],
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1514
  			   struct nf_conntrack_tuple *otuple,
5faa1f4cb   Pablo Neira Ayuso   [NETFILTER]: nf_c...
1515
  			   struct nf_conntrack_tuple *rtuple,
7ec474967   Pablo Neira Ayuso   netfilter: ctnetl...
1516
  			   u8 u3)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1517
1518
1519
  {
  	struct nf_conn *ct;
  	int err = -EINVAL;
ceceae1b1   Yasuyuki Kozakai   [NETFILTER]: nf_c...
1520
  	struct nf_conntrack_helper *helper;
315c34dae   Pablo Neira Ayuso   netfilter: ctnetl...
1521
  	struct nf_conn_tstamp *tstamp;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1522

ef00f89f1   Patrick McHardy   netfilter: ctnetl...
1523
  	ct = nf_conntrack_alloc(net, zone, otuple, rtuple, GFP_ATOMIC);
cd7fcbf1c   Julia Lawall   netfilter 07/09: ...
1524
  	if (IS_ERR(ct))
f0a3c0869   Pablo Neira Ayuso   netfilter: ctnetl...
1525
  		return ERR_PTR(-ENOMEM);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1526

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1527
  	if (!cda[CTA_TIMEOUT])
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1528
  		goto err1;
77236b6e3   Patrick McHardy   [NETFILTER]: ctne...
1529
  	ct->timeout.expires = ntohl(nla_get_be32(cda[CTA_TIMEOUT]));
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1530
1531
  
  	ct->timeout.expires = jiffies + ct->timeout.expires * HZ;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1532

1575e7ea0   Pablo Neira Ayuso   netfilter: ctnetl...
1533
  	rcu_read_lock();
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1534
   	if (cda[CTA_HELP]) {
29fe1b481   Pablo Neira Ayuso   netfilter: ctnetl...
1535
  		char *helpname = NULL;
ae243bee3   Pablo Neira Ayuso   netfilter: ctnetl...
1536
1537
1538
  		struct nlattr *helpinfo = NULL;
  
  		err = ctnetlink_parse_help(cda[CTA_HELP], &helpname, &helpinfo);
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1539
1540
   		if (err < 0)
  			goto err2;
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1541

794e68716   Patrick McHardy   netfilter: ctnetl...
1542
1543
  		helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct),
  						    nf_ct_protonum(ct));
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1544
1545
1546
1547
1548
  		if (helper == NULL) {
  			rcu_read_unlock();
  #ifdef CONFIG_MODULES
  			if (request_module("nfct-helper-%s", helpname) < 0) {
  				err = -EOPNOTSUPP;
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1549
  				goto err1;
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1550
1551
1552
  			}
  
  			rcu_read_lock();
794e68716   Patrick McHardy   netfilter: ctnetl...
1553
1554
1555
  			helper = __nf_conntrack_helper_find(helpname,
  							    nf_ct_l3num(ct),
  							    nf_ct_protonum(ct));
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1556
  			if (helper) {
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1557
  				err = -EAGAIN;
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1558
  				goto err2;
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1559
1560
1561
1562
  			}
  			rcu_read_unlock();
  #endif
  			err = -EOPNOTSUPP;
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1563
  			goto err1;
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1564
1565
  		} else {
  			struct nf_conn_help *help;
1afc56794   Pablo Neira Ayuso   netfilter: nf_ct_...
1566
  			help = nf_ct_helper_ext_add(ct, helper, GFP_ATOMIC);
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1567
  			if (help == NULL) {
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1568
  				err = -ENOMEM;
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1569
  				goto err2;
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1570
  			}
ae243bee3   Pablo Neira Ayuso   netfilter: ctnetl...
1571
  			/* set private helper data if allowed. */
7be54ca47   Pablo Neira Ayuso   netfilter: nf_ct_...
1572
  			if (helper->from_nlattr)
ae243bee3   Pablo Neira Ayuso   netfilter: ctnetl...
1573
  				helper->from_nlattr(helpinfo, ct);
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1574
1575
  
  			/* not in hash table yet so not strictly necessary */
a9b3cd7f3   Stephen Hemminger   rcu: convert uses...
1576
  			RCU_INIT_POINTER(help->helper, helper);
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1577
1578
1579
  		}
  	} else {
  		/* try an implicit helper assignation */
b2a15a604   Patrick McHardy   netfilter: nf_con...
1580
  		err = __nf_ct_try_assign_helper(ct, NULL, GFP_ATOMIC);
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1581
1582
  		if (err < 0)
  			goto err2;
1575e7ea0   Pablo Neira Ayuso   netfilter: ctnetl...
1583
  	}
a88e22adf   Pablo Neira Ayuso   netfilter: ctnetl...
1584
1585
  	if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) {
  		err = ctnetlink_change_nat(ct, cda);
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1586
1587
  		if (err < 0)
  			goto err2;
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1588
  	}
a88e22adf   Pablo Neira Ayuso   netfilter: ctnetl...
1589
  	nf_ct_acct_ext_add(ct, GFP_ATOMIC);
a992ca2a0   Pablo Neira Ayuso   netfilter: nf_con...
1590
  	nf_ct_tstamp_ext_add(ct, GFP_ATOMIC);
a88e22adf   Pablo Neira Ayuso   netfilter: ctnetl...
1591
  	nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC);
c539f0171   Florian Westphal   netfilter: add co...
1592
  	nf_ct_labels_ext_add(ct);
a88e22adf   Pablo Neira Ayuso   netfilter: ctnetl...
1593
1594
1595
1596
1597
  	/* we must add conntrack extensions before confirmation. */
  	ct->status |= IPS_CONFIRMED;
  
  	if (cda[CTA_STATUS]) {
  		err = ctnetlink_change_status(ct, cda);
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1598
1599
  		if (err < 0)
  			goto err2;
bbb3357d1   Pablo Neira Ayuso   [NETFILTER]: ctne...
1600
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1601

c969aa7d2   Pablo Neira Ayuso   netfilter: ctnetl...
1602
1603
1604
  #ifdef CONFIG_NF_NAT_NEEDED
  	if (cda[CTA_NAT_SEQ_ADJ_ORIG] || cda[CTA_NAT_SEQ_ADJ_REPLY]) {
  		err = ctnetlink_change_nat_seq_adj(ct, cda);
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1605
1606
  		if (err < 0)
  			goto err2;
c969aa7d2   Pablo Neira Ayuso   netfilter: ctnetl...
1607
1608
  	}
  #endif
e5fc9e7a6   Changli Gao   netfilter: nf_con...
1609
  	memset(&ct->proto, 0, sizeof(ct->proto));
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1610
  	if (cda[CTA_PROTOINFO]) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1611
  		err = ctnetlink_change_protoinfo(ct, cda);
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1612
1613
  		if (err < 0)
  			goto err2;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1614
  	}
bcd1e830a   Martin Josefsson   [NETFILTER]: fix ...
1615
  #if defined(CONFIG_NF_CONNTRACK_MARK)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1616
  	if (cda[CTA_MARK])
77236b6e3   Patrick McHardy   [NETFILTER]: ctne...
1617
  		ct->mark = ntohl(nla_get_be32(cda[CTA_MARK]));
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1618
  #endif
5faa1f4cb   Pablo Neira Ayuso   [NETFILTER]: nf_c...
1619
  	/* setup master conntrack: this is a confirmed expectation */
7ec474967   Pablo Neira Ayuso   netfilter: ctnetl...
1620
1621
1622
1623
1624
1625
1626
  	if (cda[CTA_TUPLE_MASTER]) {
  		struct nf_conntrack_tuple master;
  		struct nf_conntrack_tuple_hash *master_h;
  		struct nf_conn *master_ct;
  
  		err = ctnetlink_parse_tuple(cda, &master, CTA_TUPLE_MASTER, u3);
  		if (err < 0)
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1627
  			goto err2;
7ec474967   Pablo Neira Ayuso   netfilter: ctnetl...
1628

ef00f89f1   Patrick McHardy   netfilter: ctnetl...
1629
  		master_h = nf_conntrack_find_get(net, zone, &master);
7ec474967   Pablo Neira Ayuso   netfilter: ctnetl...
1630
1631
  		if (master_h == NULL) {
  			err = -ENOENT;
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1632
  			goto err2;
7ec474967   Pablo Neira Ayuso   netfilter: ctnetl...
1633
1634
  		}
  		master_ct = nf_ct_tuplehash_to_ctrack(master_h);
f2a89004d   Pablo Neira Ayuso   [NETFILTER]: ctne...
1635
  		__set_bit(IPS_EXPECTED_BIT, &ct->status);
5faa1f4cb   Pablo Neira Ayuso   [NETFILTER]: nf_c...
1636
  		ct->master = master_ct;
f2a89004d   Pablo Neira Ayuso   [NETFILTER]: ctne...
1637
  	}
315c34dae   Pablo Neira Ayuso   netfilter: ctnetl...
1638
1639
1640
  	tstamp = nf_conn_tstamp_find(ct);
  	if (tstamp)
  		tstamp->start = ktime_to_ns(ktime_get_real());
5faa1f4cb   Pablo Neira Ayuso   [NETFILTER]: nf_c...
1641

7d367e066   Jozsef Kadlecsik   netfilter: ctnetl...
1642
1643
1644
  	err = nf_conntrack_hash_check_insert(ct);
  	if (err < 0)
  		goto err2;
58a3c9bb0   Patrick McHardy   [NETFILTER]: nf_c...
1645
  	rcu_read_unlock();
dafc741cf   Yasuyuki Kozakai   [NETFILTER]: nfct...
1646

f0a3c0869   Pablo Neira Ayuso   netfilter: ctnetl...
1647
  	return ct;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1648

0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1649
1650
1651
  err2:
  	rcu_read_unlock();
  err1:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1652
  	nf_conntrack_free(ct);
f0a3c0869   Pablo Neira Ayuso   netfilter: ctnetl...
1653
  	return ERR_PTR(err);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1654
  }
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
1655
1656
  static int
  ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
399383246   Patrick McHardy   netfilter: nfnetl...
1657
1658
  			const struct nlmsghdr *nlh,
  			const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1659
  {
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
1660
  	struct net *net = sock_net(ctnl);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1661
1662
  	struct nf_conntrack_tuple otuple, rtuple;
  	struct nf_conntrack_tuple_hash *h = NULL;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
1663
  	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
7d367e066   Jozsef Kadlecsik   netfilter: ctnetl...
1664
  	struct nf_conn *ct;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1665
  	u_int8_t u3 = nfmsg->nfgen_family;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
1666
1667
1668
1669
1670
1671
  	u16 zone;
  	int err;
  
  	err = ctnetlink_parse_zone(cda[CTA_ZONE], &zone);
  	if (err < 0)
  		return err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1672

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1673
  	if (cda[CTA_TUPLE_ORIG]) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1674
1675
1676
1677
  		err = ctnetlink_parse_tuple(cda, &otuple, CTA_TUPLE_ORIG, u3);
  		if (err < 0)
  			return err;
  	}
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1678
  	if (cda[CTA_TUPLE_REPLY]) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1679
1680
1681
1682
  		err = ctnetlink_parse_tuple(cda, &rtuple, CTA_TUPLE_REPLY, u3);
  		if (err < 0)
  			return err;
  	}
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1683
  	if (cda[CTA_TUPLE_ORIG])
7d367e066   Jozsef Kadlecsik   netfilter: ctnetl...
1684
  		h = nf_conntrack_find_get(net, zone, &otuple);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1685
  	else if (cda[CTA_TUPLE_REPLY])
7d367e066   Jozsef Kadlecsik   netfilter: ctnetl...
1686
  		h = nf_conntrack_find_get(net, zone, &rtuple);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1687
1688
  
  	if (h == NULL) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1689
  		err = -ENOENT;
f0a3c0869   Pablo Neira Ayuso   netfilter: ctnetl...
1690
  		if (nlh->nlmsg_flags & NLM_F_CREATE) {
fecc1133b   Pablo Neira Ayuso   netfilter: ctnetl...
1691
  			enum ip_conntrack_events events;
5faa1f4cb   Pablo Neira Ayuso   [NETFILTER]: nf_c...
1692

442fad942   Florian Westphal   netfilter: ctnetl...
1693
1694
  			if (!cda[CTA_TUPLE_ORIG] || !cda[CTA_TUPLE_REPLY])
  				return -EINVAL;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
1695
  			ct = ctnetlink_create_conntrack(net, zone, cda, &otuple,
f0a3c0869   Pablo Neira Ayuso   netfilter: ctnetl...
1696
  							&rtuple, u3);
7d367e066   Jozsef Kadlecsik   netfilter: ctnetl...
1697
1698
  			if (IS_ERR(ct))
  				return PTR_ERR(ct);
f0a3c0869   Pablo Neira Ayuso   netfilter: ctnetl...
1699
  			err = 0;
fecc1133b   Pablo Neira Ayuso   netfilter: ctnetl...
1700
1701
1702
1703
  			if (test_bit(IPS_EXPECTED_BIT, &ct->status))
  				events = IPCT_RELATED;
  			else
  				events = IPCT_NEW;
9b21f6a90   Florian Westphal   netfilter: ctnetl...
1704
1705
1706
  			if (cda[CTA_LABELS] &&
  			    ctnetlink_attach_labels(ct, cda) == 0)
  				events |= (1 << IPCT_LABEL);
858b31330   Patrick McHardy   netfilter: nf_con...
1707
1708
  			nf_conntrack_eventmask_report((1 << IPCT_REPLY) |
  						      (1 << IPCT_ASSURED) |
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
1709
1710
1711
1712
  						      (1 << IPCT_HELPER) |
  						      (1 << IPCT_PROTOINFO) |
  						      (1 << IPCT_NATSEQADJ) |
  						      (1 << IPCT_MARK) | events,
15e473046   Eric W. Biederman   netlink: Rename p...
1713
  						      ct, NETLINK_CB(skb).portid,
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
1714
  						      nlmsg_report(nlh));
f0a3c0869   Pablo Neira Ayuso   netfilter: ctnetl...
1715
  			nf_ct_put(ct);
7d367e066   Jozsef Kadlecsik   netfilter: ctnetl...
1716
  		}
5faa1f4cb   Pablo Neira Ayuso   [NETFILTER]: nf_c...
1717

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1718
1719
1720
  		return err;
  	}
  	/* implicit 'else' */
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1721
  	err = -EEXIST;
7d367e066   Jozsef Kadlecsik   netfilter: ctnetl...
1722
  	ct = nf_ct_tuplehash_to_ctrack(h);
ff4ca8273   Pablo Neira Ayuso   [NETFILTER]: ctne...
1723
  	if (!(nlh->nlmsg_flags & NLM_F_EXCL)) {
7d367e066   Jozsef Kadlecsik   netfilter: ctnetl...
1724
  		spin_lock_bh(&nf_conntrack_lock);
19abb7b09   Pablo Neira Ayuso   netfilter: ctnetl...
1725
  		err = ctnetlink_change_conntrack(ct, cda);
7d367e066   Jozsef Kadlecsik   netfilter: ctnetl...
1726
  		spin_unlock_bh(&nf_conntrack_lock);
19abb7b09   Pablo Neira Ayuso   netfilter: ctnetl...
1727
  		if (err == 0) {
858b31330   Patrick McHardy   netfilter: nf_con...
1728
1729
  			nf_conntrack_eventmask_report((1 << IPCT_REPLY) |
  						      (1 << IPCT_ASSURED) |
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
1730
  						      (1 << IPCT_HELPER) |
797a7d66d   Florian Westphal   netfilter: ctnetl...
1731
  						      (1 << IPCT_LABEL) |
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
1732
1733
1734
  						      (1 << IPCT_PROTOINFO) |
  						      (1 << IPCT_NATSEQADJ) |
  						      (1 << IPCT_MARK),
15e473046   Eric W. Biederman   netlink: Rename p...
1735
  						      ct, NETLINK_CB(skb).portid,
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
1736
  						      nlmsg_report(nlh));
7d367e066   Jozsef Kadlecsik   netfilter: ctnetl...
1737
  		}
ff4ca8273   Pablo Neira Ayuso   [NETFILTER]: ctne...
1738
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1739

7d367e066   Jozsef Kadlecsik   netfilter: ctnetl...
1740
  	nf_ct_put(ct);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1741
1742
  	return err;
  }
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1743
  static int
15e473046   Eric W. Biederman   netlink: Rename p...
1744
  ctnetlink_ct_stat_cpu_fill_info(struct sk_buff *skb, u32 portid, u32 seq,
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1745
1746
1747
1748
  				__u16 cpu, const struct ip_conntrack_stat *st)
  {
  	struct nlmsghdr *nlh;
  	struct nfgenmsg *nfmsg;
15e473046   Eric W. Biederman   netlink: Rename p...
1749
  	unsigned int flags = portid ? NLM_F_MULTI : 0, event;
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1750
1751
  
  	event = (NFNL_SUBSYS_CTNETLINK << 8 | IPCTNL_MSG_CT_GET_STATS_CPU);
15e473046   Eric W. Biederman   netlink: Rename p...
1752
  	nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
  	if (nlh == NULL)
  		goto nlmsg_failure;
  
  	nfmsg = nlmsg_data(nlh);
  	nfmsg->nfgen_family = AF_UNSPEC;
  	nfmsg->version      = NFNETLINK_V0;
  	nfmsg->res_id	    = htons(cpu);
  
  	if (nla_put_be32(skb, CTA_STATS_SEARCHED, htonl(st->searched)) ||
  	    nla_put_be32(skb, CTA_STATS_FOUND, htonl(st->found)) ||
  	    nla_put_be32(skb, CTA_STATS_NEW, htonl(st->new)) ||
  	    nla_put_be32(skb, CTA_STATS_INVALID, htonl(st->invalid)) ||
  	    nla_put_be32(skb, CTA_STATS_IGNORE, htonl(st->ignore)) ||
  	    nla_put_be32(skb, CTA_STATS_DELETE, htonl(st->delete)) ||
  	    nla_put_be32(skb, CTA_STATS_DELETE_LIST, htonl(st->delete_list)) ||
  	    nla_put_be32(skb, CTA_STATS_INSERT, htonl(st->insert)) ||
  	    nla_put_be32(skb, CTA_STATS_INSERT_FAILED,
  				htonl(st->insert_failed)) ||
  	    nla_put_be32(skb, CTA_STATS_DROP, htonl(st->drop)) ||
  	    nla_put_be32(skb, CTA_STATS_EARLY_DROP, htonl(st->early_drop)) ||
  	    nla_put_be32(skb, CTA_STATS_ERROR, htonl(st->error)) ||
  	    nla_put_be32(skb, CTA_STATS_SEARCH_RESTART,
  				htonl(st->search_restart)))
  		goto nla_put_failure;
  
  	nlmsg_end(skb, nlh);
  	return skb->len;
  
  nla_put_failure:
  nlmsg_failure:
  	nlmsg_cancel(skb, nlh);
  	return -1;
  }
  
  static int
  ctnetlink_ct_stat_cpu_dump(struct sk_buff *skb, struct netlink_callback *cb)
  {
  	int cpu;
  	struct net *net = sock_net(skb->sk);
  
  	if (cb->args[0] == nr_cpu_ids)
  		return 0;
  
  	for (cpu = cb->args[0]; cpu < nr_cpu_ids; cpu++) {
  		const struct ip_conntrack_stat *st;
  
  		if (!cpu_possible(cpu))
  			continue;
  
  		st = per_cpu_ptr(net->ct.stat, cpu);
  		if (ctnetlink_ct_stat_cpu_fill_info(skb,
15e473046   Eric W. Biederman   netlink: Rename p...
1804
  						    NETLINK_CB(cb->skb).portid,
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
  						    cb->nlh->nlmsg_seq,
  						    cpu, st) < 0)
  				break;
  	}
  	cb->args[0] = cpu;
  
  	return skb->len;
  }
  
  static int
  ctnetlink_stat_ct_cpu(struct sock *ctnl, struct sk_buff *skb,
  		      const struct nlmsghdr *nlh,
  		      const struct nlattr * const cda[])
  {
  	if (nlh->nlmsg_flags & NLM_F_DUMP) {
  		struct netlink_dump_control c = {
  			.dump = ctnetlink_ct_stat_cpu_dump,
  		};
  		return netlink_dump_start(ctnl, skb, nlh, &c);
  	}
  
  	return 0;
  }
  
  static int
15e473046   Eric W. Biederman   netlink: Rename p...
1830
  ctnetlink_stat_ct_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1831
1832
1833
1834
  			    struct net *net)
  {
  	struct nlmsghdr *nlh;
  	struct nfgenmsg *nfmsg;
15e473046   Eric W. Biederman   netlink: Rename p...
1835
  	unsigned int flags = portid ? NLM_F_MULTI : 0, event;
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1836
1837
1838
  	unsigned int nr_conntracks = atomic_read(&net->ct.count);
  
  	event = (NFNL_SUBSYS_CTNETLINK << 8 | IPCTNL_MSG_CT_GET_STATS);
15e473046   Eric W. Biederman   netlink: Rename p...
1839
  	nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
  	if (nlh == NULL)
  		goto nlmsg_failure;
  
  	nfmsg = nlmsg_data(nlh);
  	nfmsg->nfgen_family = AF_UNSPEC;
  	nfmsg->version      = NFNETLINK_V0;
  	nfmsg->res_id	    = 0;
  
  	if (nla_put_be32(skb, CTA_STATS_GLOBAL_ENTRIES, htonl(nr_conntracks)))
  		goto nla_put_failure;
  
  	nlmsg_end(skb, nlh);
  	return skb->len;
  
  nla_put_failure:
  nlmsg_failure:
  	nlmsg_cancel(skb, nlh);
  	return -1;
  }
  
  static int
  ctnetlink_stat_ct(struct sock *ctnl, struct sk_buff *skb,
  		  const struct nlmsghdr *nlh,
  		  const struct nlattr * const cda[])
  {
  	struct sk_buff *skb2;
  	int err;
  
  	skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
  	if (skb2 == NULL)
  		return -ENOMEM;
15e473046   Eric W. Biederman   netlink: Rename p...
1871
  	err = ctnetlink_stat_ct_fill_info(skb2, NETLINK_CB(skb).portid,
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1872
1873
1874
1875
1876
  					  nlh->nlmsg_seq,
  					  NFNL_MSG_TYPE(nlh->nlmsg_type),
  					  sock_net(skb->sk));
  	if (err <= 0)
  		goto free;
15e473046   Eric W. Biederman   netlink: Rename p...
1877
  	err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT);
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
  	if (err < 0)
  		goto out;
  
  	return 0;
  
  free:
  	kfree_skb(skb2);
  out:
  	/* this avoids a loop in nfnetlink. */
  	return err == -EAGAIN ? -ENOBUFS : err;
  }
7c6223454   Pablo Neira Ayuso   netfilter: nfnetl...
1889
  #ifdef CONFIG_NETFILTER_NETLINK_QUEUE_CT
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
  static size_t
  ctnetlink_nfqueue_build_size(const struct nf_conn *ct)
  {
  	return 3 * nla_total_size(0) /* CTA_TUPLE_ORIG|REPL|MASTER */
  	       + 3 * nla_total_size(0) /* CTA_TUPLE_IP */
  	       + 3 * nla_total_size(0) /* CTA_TUPLE_PROTO */
  	       + 3 * nla_total_size(sizeof(u_int8_t)) /* CTA_PROTO_NUM */
  	       + nla_total_size(sizeof(u_int32_t)) /* CTA_ID */
  	       + nla_total_size(sizeof(u_int32_t)) /* CTA_STATUS */
  	       + nla_total_size(sizeof(u_int32_t)) /* CTA_TIMEOUT */
  	       + nla_total_size(0) /* CTA_PROTOINFO */
  	       + nla_total_size(0) /* CTA_HELP */
  	       + nla_total_size(NF_CT_HELPER_NAME_LEN) /* CTA_HELP_NAME */
  	       + ctnetlink_secctx_size(ct)
  #ifdef CONFIG_NF_NAT_NEEDED
  	       + 2 * nla_total_size(0) /* CTA_NAT_SEQ_ADJ_ORIG|REPL */
  	       + 6 * nla_total_size(sizeof(u_int32_t)) /* CTA_NAT_SEQ_OFFSET */
  #endif
  #ifdef CONFIG_NF_CONNTRACK_MARK
  	       + nla_total_size(sizeof(u_int32_t)) /* CTA_MARK */
  #endif
  	       + ctnetlink_proto_size(ct)
  	       ;
  }
  
  static int
  ctnetlink_nfqueue_build(struct sk_buff *skb, struct nf_conn *ct)
  {
  	struct nlattr *nest_parms;
  
  	rcu_read_lock();
  	nest_parms = nla_nest_start(skb, CTA_TUPLE_ORIG | NLA_F_NESTED);
  	if (!nest_parms)
  		goto nla_put_failure;
  	if (ctnetlink_dump_tuples(skb, nf_ct_tuple(ct, IP_CT_DIR_ORIGINAL)) < 0)
  		goto nla_put_failure;
  	nla_nest_end(skb, nest_parms);
  
  	nest_parms = nla_nest_start(skb, CTA_TUPLE_REPLY | NLA_F_NESTED);
  	if (!nest_parms)
  		goto nla_put_failure;
  	if (ctnetlink_dump_tuples(skb, nf_ct_tuple(ct, IP_CT_DIR_REPLY)) < 0)
  		goto nla_put_failure;
  	nla_nest_end(skb, nest_parms);
  
  	if (nf_ct_zone(ct)) {
  		if (nla_put_be16(skb, CTA_ZONE, htons(nf_ct_zone(ct))))
  			goto nla_put_failure;
  	}
  
  	if (ctnetlink_dump_id(skb, ct) < 0)
  		goto nla_put_failure;
  
  	if (ctnetlink_dump_status(skb, ct) < 0)
  		goto nla_put_failure;
  
  	if (ctnetlink_dump_timeout(skb, ct) < 0)
  		goto nla_put_failure;
  
  	if (ctnetlink_dump_protoinfo(skb, ct) < 0)
  		goto nla_put_failure;
  
  	if (ctnetlink_dump_helpinfo(skb, ct) < 0)
  		goto nla_put_failure;
  
  #ifdef CONFIG_NF_CONNTRACK_SECMARK
  	if (ct->secmark && ctnetlink_dump_secctx(skb, ct) < 0)
  		goto nla_put_failure;
  #endif
  	if (ct->master && ctnetlink_dump_master(skb, ct) < 0)
  		goto nla_put_failure;
  
  	if ((ct->status & IPS_SEQ_ADJUST) &&
  	    ctnetlink_dump_nat_seq_adj(skb, ct) < 0)
  		goto nla_put_failure;
  
  #ifdef CONFIG_NF_CONNTRACK_MARK
  	if (ct->mark && ctnetlink_dump_mark(skb, ct) < 0)
  		goto nla_put_failure;
  #endif
0ceabd838   Florian Westphal   netfilter: ctnetl...
1970
1971
  	if (ctnetlink_dump_labels(skb, ct) < 0)
  		goto nla_put_failure;
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
  	rcu_read_unlock();
  	return 0;
  
  nla_put_failure:
  	rcu_read_unlock();
  	return -ENOSPC;
  }
  
  static int
  ctnetlink_nfqueue_parse_ct(const struct nlattr *cda[], struct nf_conn *ct)
  {
  	int err;
  
  	if (cda[CTA_TIMEOUT]) {
  		err = ctnetlink_change_timeout(ct, cda);
  		if (err < 0)
  			return err;
  	}
  	if (cda[CTA_STATUS]) {
  		err = ctnetlink_change_status(ct, cda);
  		if (err < 0)
  			return err;
  	}
  	if (cda[CTA_HELP]) {
  		err = ctnetlink_change_helper(ct, cda);
  		if (err < 0)
  			return err;
  	}
9b21f6a90   Florian Westphal   netfilter: ctnetl...
2000
2001
2002
2003
2004
  	if (cda[CTA_LABELS]) {
  		err = ctnetlink_attach_labels(ct, cda);
  		if (err < 0)
  			return err;
  	}
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
  #if defined(CONFIG_NF_CONNTRACK_MARK)
  	if (cda[CTA_MARK])
  		ct->mark = ntohl(nla_get_be32(cda[CTA_MARK]));
  #endif
  	return 0;
  }
  
  static int
  ctnetlink_nfqueue_parse(const struct nlattr *attr, struct nf_conn *ct)
  {
  	struct nlattr *cda[CTA_MAX+1];
68e035c95   Pablo Neira Ayuso   netfilter: ctnetl...
2016
  	int ret;
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2017
2018
  
  	nla_parse_nested(cda, CTA_MAX, attr, ct_nla_policy);
68e035c95   Pablo Neira Ayuso   netfilter: ctnetl...
2019
2020
2021
2022
2023
  	spin_lock_bh(&nf_conntrack_lock);
  	ret = ctnetlink_nfqueue_parse_ct((const struct nlattr **)cda, ct);
  	spin_unlock_bh(&nf_conntrack_lock);
  
  	return ret;
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2024
2025
2026
2027
2028
2029
2030
  }
  
  static struct nfq_ct_hook ctnetlink_nfqueue_hook = {
  	.build_size	= ctnetlink_nfqueue_build_size,
  	.build		= ctnetlink_nfqueue_build,
  	.parse		= ctnetlink_nfqueue_parse,
  };
7c6223454   Pablo Neira Ayuso   netfilter: nfnetl...
2031
  #endif /* CONFIG_NETFILTER_NETLINK_QUEUE_CT */
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2032

601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2033
2034
2035
  /***********************************************************************
   * EXPECT
   ***********************************************************************/
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2036
2037
2038
2039
2040
2041
  
  static inline int
  ctnetlink_exp_dump_tuple(struct sk_buff *skb,
  			 const struct nf_conntrack_tuple *tuple,
  			 enum ctattr_expect type)
  {
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2042
  	struct nlattr *nest_parms;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2043

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2044
2045
2046
  	nest_parms = nla_nest_start(skb, type | NLA_F_NESTED);
  	if (!nest_parms)
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2047
  	if (ctnetlink_dump_tuples(skb, tuple) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2048
2049
  		goto nla_put_failure;
  	nla_nest_end(skb, nest_parms);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2050
2051
  
  	return 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2052
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2053
  	return -1;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2054
  }
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2055
2056
  
  static inline int
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
2057
2058
  ctnetlink_exp_dump_mask(struct sk_buff *skb,
  			const struct nf_conntrack_tuple *tuple,
d4156e8cd   Patrick McHardy   [NETFILTER]: nf_c...
2059
  			const struct nf_conntrack_tuple_mask *mask)
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
2060
2061
2062
  {
  	int ret;
  	struct nf_conntrack_l3proto *l3proto;
605dcad6c   Martin Josefsson   [NETFILTER]: nf_c...
2063
  	struct nf_conntrack_l4proto *l4proto;
d4156e8cd   Patrick McHardy   [NETFILTER]: nf_c...
2064
  	struct nf_conntrack_tuple m;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2065
  	struct nlattr *nest_parms;
d4156e8cd   Patrick McHardy   [NETFILTER]: nf_c...
2066
2067
  
  	memset(&m, 0xFF, sizeof(m));
d4156e8cd   Patrick McHardy   [NETFILTER]: nf_c...
2068
  	memcpy(&m.src.u3, &mask->src.u3, sizeof(m.src.u3));
e578756c3   Patrick McHardy   netfilter: ctnetl...
2069
2070
  	m.src.u.all = mask->src.u.all;
  	m.dst.protonum = tuple->dst.protonum;
d4156e8cd   Patrick McHardy   [NETFILTER]: nf_c...
2071

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2072
2073
2074
  	nest_parms = nla_nest_start(skb, CTA_EXPECT_MASK | NLA_F_NESTED);
  	if (!nest_parms)
  		goto nla_put_failure;
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
2075

3b988ece9   Hans Schillstrom   netfilter: ctnetl...
2076
  	rcu_read_lock();
528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
2077
  	l3proto = __nf_ct_l3proto_find(tuple->src.l3num);
d4156e8cd   Patrick McHardy   [NETFILTER]: nf_c...
2078
  	ret = ctnetlink_dump_tuples_ip(skb, &m, l3proto);
3b988ece9   Hans Schillstrom   netfilter: ctnetl...
2079
2080
2081
  	if (ret >= 0) {
  		l4proto = __nf_ct_l4proto_find(tuple->src.l3num,
  					       tuple->dst.protonum);
d4156e8cd   Patrick McHardy   [NETFILTER]: nf_c...
2082
  	ret = ctnetlink_dump_tuples_proto(skb, &m, l4proto);
3b988ece9   Hans Schillstrom   netfilter: ctnetl...
2083
2084
  	}
  	rcu_read_unlock();
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
2085
  	if (unlikely(ret < 0))
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2086
  		goto nla_put_failure;
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
2087

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2088
  	nla_nest_end(skb, nest_parms);
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
2089
2090
  
  	return 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2091
  nla_put_failure:
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
2092
2093
  	return -1;
  }
c7232c997   Patrick McHardy   netfilter: add pr...
2094
  static const union nf_inet_addr any_addr;
bb5cf80e9   Ilpo Järvinen   [NETFILTER]: Kill...
2095
  static int
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2096
  ctnetlink_exp_dump_expect(struct sk_buff *skb,
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2097
  			  const struct nf_conntrack_expect *exp)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2098
2099
  {
  	struct nf_conn *master = exp->master;
c12163827   Xi Wang   netfilter: ctnetl...
2100
  	long timeout = ((long)exp->timeout.expires - (long)jiffies) / HZ;
bc01befdc   Pablo Neira Ayuso   netfilter: ctnetl...
2101
  	struct nf_conn_help *help;
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2102
2103
2104
2105
  #ifdef CONFIG_NF_NAT_NEEDED
  	struct nlattr *nest_parms;
  	struct nf_conntrack_tuple nat_tuple = {};
  #endif
544d5c7d9   Pablo Neira Ayuso   netfilter: ctnetl...
2106
  	struct nf_ct_helper_expectfn *expfn;
d978e5dae   Patrick McHardy   [NETFILTER]: ctne...
2107
2108
  	if (timeout < 0)
  		timeout = 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2109
2110
  
  	if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2111
  		goto nla_put_failure;
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
2112
  	if (ctnetlink_exp_dump_mask(skb, &exp->tuple, &exp->mask) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2113
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2114
2115
2116
  	if (ctnetlink_exp_dump_tuple(skb,
  				 &master->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
  				 CTA_EXPECT_MASTER) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2117
  		goto nla_put_failure;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2118

076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2119
  #ifdef CONFIG_NF_NAT_NEEDED
c7232c997   Patrick McHardy   netfilter: add pr...
2120
2121
  	if (!nf_inet_addr_cmp(&exp->saved_addr, &any_addr) ||
  	    exp->saved_proto.all) {
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2122
2123
2124
  		nest_parms = nla_nest_start(skb, CTA_EXPECT_NAT | NLA_F_NESTED);
  		if (!nest_parms)
  			goto nla_put_failure;
cc1eb4313   David S. Miller   nf_conntrack_netl...
2125
2126
  		if (nla_put_be32(skb, CTA_EXPECT_NAT_DIR, htonl(exp->dir)))
  			goto nla_put_failure;
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2127
2128
  
  		nat_tuple.src.l3num = nf_ct_l3num(master);
c7232c997   Patrick McHardy   netfilter: add pr...
2129
  		nat_tuple.src.u3 = exp->saved_addr;
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2130
2131
2132
2133
2134
2135
2136
2137
2138
  		nat_tuple.dst.protonum = nf_ct_protonum(master);
  		nat_tuple.src.u = exp->saved_proto;
  
  		if (ctnetlink_exp_dump_tuple(skb, &nat_tuple,
  						CTA_EXPECT_NAT_TUPLE) < 0)
  	                goto nla_put_failure;
  	        nla_nest_end(skb, nest_parms);
  	}
  #endif
cc1eb4313   David S. Miller   nf_conntrack_netl...
2139
2140
2141
2142
2143
  	if (nla_put_be32(skb, CTA_EXPECT_TIMEOUT, htonl(timeout)) ||
  	    nla_put_be32(skb, CTA_EXPECT_ID, htonl((unsigned long)exp)) ||
  	    nla_put_be32(skb, CTA_EXPECT_FLAGS, htonl(exp->flags)) ||
  	    nla_put_be32(skb, CTA_EXPECT_CLASS, htonl(exp->class)))
  		goto nla_put_failure;
bc01befdc   Pablo Neira Ayuso   netfilter: ctnetl...
2144
2145
2146
2147
2148
  	help = nfct_help(master);
  	if (help) {
  		struct nf_conntrack_helper *helper;
  
  		helper = rcu_dereference(help->helper);
cc1eb4313   David S. Miller   nf_conntrack_netl...
2149
2150
2151
  		if (helper &&
  		    nla_put_string(skb, CTA_EXPECT_HELP_NAME, helper->name))
  			goto nla_put_failure;
bc01befdc   Pablo Neira Ayuso   netfilter: ctnetl...
2152
  	}
544d5c7d9   Pablo Neira Ayuso   netfilter: ctnetl...
2153
  	expfn = nf_ct_helper_expectfn_find_by_symbol(exp->expectfn);
cc1eb4313   David S. Miller   nf_conntrack_netl...
2154
2155
2156
  	if (expfn != NULL &&
  	    nla_put_string(skb, CTA_EXPECT_FN, expfn->name))
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2157
2158
  
  	return 0;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2159

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2160
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2161
2162
2163
2164
  	return -1;
  }
  
  static int
15e473046   Eric W. Biederman   netlink: Rename p...
2165
  ctnetlink_exp_fill_info(struct sk_buff *skb, u32 portid, u32 seq,
8b0a231d4   Pablo Neira Ayuso   netfilter: ctnetl...
2166
  			int event, const struct nf_conntrack_expect *exp)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2167
2168
2169
  {
  	struct nlmsghdr *nlh;
  	struct nfgenmsg *nfmsg;
15e473046   Eric W. Biederman   netlink: Rename p...
2170
  	unsigned int flags = portid ? NLM_F_MULTI : 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2171
2172
  
  	event |= NFNL_SUBSYS_CTNETLINK_EXP << 8;
15e473046   Eric W. Biederman   netlink: Rename p...
2173
  	nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2174
2175
  	if (nlh == NULL)
  		goto nlmsg_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2176

96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2177
  	nfmsg = nlmsg_data(nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2178
2179
2180
2181
2182
  	nfmsg->nfgen_family = exp->tuple.src.l3num;
  	nfmsg->version	    = NFNETLINK_V0;
  	nfmsg->res_id	    = 0;
  
  	if (ctnetlink_exp_dump_expect(skb, exp) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2183
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2184

96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2185
  	nlmsg_end(skb, nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2186
2187
2188
  	return skb->len;
  
  nlmsg_failure:
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2189
  nla_put_failure:
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2190
  	nlmsg_cancel(skb, nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2191
2192
2193
2194
  	return -1;
  }
  
  #ifdef CONFIG_NF_CONNTRACK_EVENTS
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
2195
2196
  static int
  ctnetlink_expect_event(unsigned int events, struct nf_exp_event *item)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2197
  {
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
2198
2199
  	struct nf_conntrack_expect *exp = item->exp;
  	struct net *net = nf_ct_exp_net(exp);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2200
2201
  	struct nlmsghdr *nlh;
  	struct nfgenmsg *nfmsg;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2202
  	struct sk_buff *skb;
ebbf41df4   Pablo Neira Ayuso   netfilter: ctnetl...
2203
  	unsigned int type, group;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2204
  	int flags = 0;
ebbf41df4   Pablo Neira Ayuso   netfilter: ctnetl...
2205
2206
2207
2208
  	if (events & (1 << IPEXP_DESTROY)) {
  		type = IPCTNL_MSG_EXP_DELETE;
  		group = NFNLGRP_CONNTRACK_EXP_DESTROY;
  	} else if (events & (1 << IPEXP_NEW)) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2209
2210
  		type = IPCTNL_MSG_EXP_NEW;
  		flags = NLM_F_CREATE|NLM_F_EXCL;
ebbf41df4   Pablo Neira Ayuso   netfilter: ctnetl...
2211
  		group = NFNLGRP_CONNTRACK_EXP_NEW;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2212
  	} else
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
2213
  		return 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2214

ebbf41df4   Pablo Neira Ayuso   netfilter: ctnetl...
2215
  	if (!item->report && !nfnetlink_has_listeners(net, group))
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
2216
  		return 0;
b3a27bfba   Pablo Neira Ayuso   [NETFILTER]: ctne...
2217

96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2218
2219
  	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
  	if (skb == NULL)
150ace0db   Pablo Neira Ayuso   netfilter: ctnetl...
2220
  		goto errout;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2221

b633ad5fb   Marcus Sundberg   [NETFILTER]: ctne...
2222
  	type |= NFNL_SUBSYS_CTNETLINK_EXP << 8;
15e473046   Eric W. Biederman   netlink: Rename p...
2223
  	nlh = nlmsg_put(skb, item->portid, 0, type, sizeof(*nfmsg), flags);
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2224
2225
  	if (nlh == NULL)
  		goto nlmsg_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2226

96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2227
  	nfmsg = nlmsg_data(nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2228
2229
2230
  	nfmsg->nfgen_family = exp->tuple.src.l3num;
  	nfmsg->version	    = NFNETLINK_V0;
  	nfmsg->res_id	    = 0;
528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
2231
  	rcu_read_lock();
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2232
  	if (ctnetlink_exp_dump_expect(skb, exp) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2233
  		goto nla_put_failure;
528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
2234
  	rcu_read_unlock();
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2235

96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2236
  	nlmsg_end(skb, nlh);
15e473046   Eric W. Biederman   netlink: Rename p...
2237
  	nfnetlink_send(skb, net, item->portid, group, item->report, GFP_ATOMIC);
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
2238
  	return 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2239

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2240
  nla_put_failure:
528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
2241
  	rcu_read_unlock();
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2242
  	nlmsg_cancel(skb, nlh);
528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
2243
  nlmsg_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2244
  	kfree_skb(skb);
150ace0db   Pablo Neira Ayuso   netfilter: ctnetl...
2245
  errout:
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
2246
  	nfnetlink_set_err(net, 0, 0, -ENOBUFS);
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
2247
  	return 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2248
2249
  }
  #endif
cf6994c2b   Patrick McHardy   [NETFILTER]: nf_c...
2250
2251
  static int ctnetlink_exp_done(struct netlink_callback *cb)
  {
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2252
2253
  	if (cb->args[1])
  		nf_ct_expect_put((struct nf_conntrack_expect *)cb->args[1]);
cf6994c2b   Patrick McHardy   [NETFILTER]: nf_c...
2254
2255
  	return 0;
  }
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2256
2257
2258
2259
  
  static int
  ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
  {
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
2260
  	struct net *net = sock_net(skb->sk);
cf6994c2b   Patrick McHardy   [NETFILTER]: nf_c...
2261
  	struct nf_conntrack_expect *exp, *last;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2262
  	struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
87711cb81   Pablo Neira Ayuso   [NETFILTER]: Filt...
2263
  	u_int8_t l3proto = nfmsg->nfgen_family;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2264

7d0742da1   Patrick McHardy   [NETFILTER]: nf_c...
2265
  	rcu_read_lock();
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2266
2267
  	last = (struct nf_conntrack_expect *)cb->args[1];
  	for (; cb->args[0] < nf_ct_expect_hsize; cb->args[0]++) {
cf6994c2b   Patrick McHardy   [NETFILTER]: nf_c...
2268
  restart:
b67bfe0d4   Sasha Levin   hlist: drop the n...
2269
  		hlist_for_each_entry(exp, &net->ct.expect_hash[cb->args[0]],
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2270
2271
  				     hnode) {
  			if (l3proto && exp->tuple.src.l3num != l3proto)
cf6994c2b   Patrick McHardy   [NETFILTER]: nf_c...
2272
  				continue;
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2273
2274
2275
2276
2277
  			if (cb->args[1]) {
  				if (exp != last)
  					continue;
  				cb->args[1] = 0;
  			}
8b0a231d4   Pablo Neira Ayuso   netfilter: ctnetl...
2278
  			if (ctnetlink_exp_fill_info(skb,
15e473046   Eric W. Biederman   netlink: Rename p...
2279
  						    NETLINK_CB(cb->skb).portid,
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2280
2281
  						    cb->nlh->nlmsg_seq,
  						    IPCTNL_MSG_EXP_NEW,
8b0a231d4   Pablo Neira Ayuso   netfilter: ctnetl...
2282
  						    exp) < 0) {
7d0742da1   Patrick McHardy   [NETFILTER]: nf_c...
2283
2284
  				if (!atomic_inc_not_zero(&exp->use))
  					continue;
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2285
2286
2287
  				cb->args[1] = (unsigned long)exp;
  				goto out;
  			}
cf6994c2b   Patrick McHardy   [NETFILTER]: nf_c...
2288
  		}
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2289
2290
2291
  		if (cb->args[1]) {
  			cb->args[1] = 0;
  			goto restart;
cf6994c2b   Patrick McHardy   [NETFILTER]: nf_c...
2292
2293
  		}
  	}
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2294
  out:
7d0742da1   Patrick McHardy   [NETFILTER]: nf_c...
2295
  	rcu_read_unlock();
cf6994c2b   Patrick McHardy   [NETFILTER]: nf_c...
2296
2297
  	if (last)
  		nf_ct_expect_put(last);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2298

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2299
2300
  	return skb->len;
  }
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
  static int
  ctnetlink_exp_ct_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
  {
  	struct nf_conntrack_expect *exp, *last;
  	struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
  	struct nf_conn *ct = cb->data;
  	struct nf_conn_help *help = nfct_help(ct);
  	u_int8_t l3proto = nfmsg->nfgen_family;
  
  	if (cb->args[0])
  		return 0;
  
  	rcu_read_lock();
  	last = (struct nf_conntrack_expect *)cb->args[1];
  restart:
  	hlist_for_each_entry(exp, &help->expectations, lnode) {
  		if (l3proto && exp->tuple.src.l3num != l3proto)
  			continue;
  		if (cb->args[1]) {
  			if (exp != last)
  				continue;
  			cb->args[1] = 0;
  		}
  		if (ctnetlink_exp_fill_info(skb, NETLINK_CB(cb->skb).portid,
  					    cb->nlh->nlmsg_seq,
  					    IPCTNL_MSG_EXP_NEW,
  					    exp) < 0) {
  			if (!atomic_inc_not_zero(&exp->use))
  				continue;
  			cb->args[1] = (unsigned long)exp;
  			goto out;
  		}
  	}
  	if (cb->args[1]) {
  		cb->args[1] = 0;
  		goto restart;
  	}
  	cb->args[0] = 1;
  out:
  	rcu_read_unlock();
  	if (last)
  		nf_ct_expect_put(last);
  
  	return skb->len;
  }
  
  static int ctnetlink_dump_exp_ct(struct sock *ctnl, struct sk_buff *skb,
  				 const struct nlmsghdr *nlh,
  				 const struct nlattr * const cda[])
  {
  	int err;
  	struct net *net = sock_net(ctnl);
  	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
  	u_int8_t u3 = nfmsg->nfgen_family;
  	struct nf_conntrack_tuple tuple;
  	struct nf_conntrack_tuple_hash *h;
  	struct nf_conn *ct;
  	u16 zone = 0;
  	struct netlink_dump_control c = {
  		.dump = ctnetlink_exp_ct_dump_table,
  		.done = ctnetlink_exp_done,
  	};
  
  	err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER, u3);
  	if (err < 0)
  		return err;
  
  	if (cda[CTA_EXPECT_ZONE]) {
  		err = ctnetlink_parse_zone(cda[CTA_EXPECT_ZONE], &zone);
  		if (err < 0)
  			return err;
  	}
  
  	h = nf_conntrack_find_get(net, zone, &tuple);
  	if (!h)
  		return -ENOENT;
  
  	ct = nf_ct_tuplehash_to_ctrack(h);
  	c.data = ct;
  
  	err = netlink_dump_start(ctnl, skb, nlh, &c);
  	nf_ct_put(ct);
  
  	return err;
  }
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
2386
  static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = {
d0b0268fd   Patrick McHardy   netfilter: ctnetl...
2387
2388
2389
  	[CTA_EXPECT_MASTER]	= { .type = NLA_NESTED },
  	[CTA_EXPECT_TUPLE]	= { .type = NLA_NESTED },
  	[CTA_EXPECT_MASK]	= { .type = NLA_NESTED },
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
2390
2391
  	[CTA_EXPECT_TIMEOUT]	= { .type = NLA_U32 },
  	[CTA_EXPECT_ID]		= { .type = NLA_U32 },
6d1fafcae   Florian Westphal   netfilter: ctnetl...
2392
2393
  	[CTA_EXPECT_HELP_NAME]	= { .type = NLA_NUL_STRING,
  				    .len = NF_CT_HELPER_NAME_LEN - 1 },
bcac0dfab   Pablo Neira Ayuso   netfilter: ctnetl...
2394
  	[CTA_EXPECT_ZONE]	= { .type = NLA_U16 },
8b008faf9   Pablo Neira Ayuso   netfilter: ctnetl...
2395
  	[CTA_EXPECT_FLAGS]	= { .type = NLA_U32 },
b8c5e52c1   Pablo Neira Ayuso   netfilter: ctnetl...
2396
  	[CTA_EXPECT_CLASS]	= { .type = NLA_U32 },
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2397
  	[CTA_EXPECT_NAT]	= { .type = NLA_NESTED },
544d5c7d9   Pablo Neira Ayuso   netfilter: ctnetl...
2398
  	[CTA_EXPECT_FN]		= { .type = NLA_NUL_STRING },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2399
2400
2401
  };
  
  static int
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2402
  ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
399383246   Patrick McHardy   netfilter: nfnetl...
2403
2404
  		     const struct nlmsghdr *nlh,
  		     const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2405
  {
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
2406
  	struct net *net = sock_net(ctnl);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2407
2408
2409
  	struct nf_conntrack_tuple tuple;
  	struct nf_conntrack_expect *exp;
  	struct sk_buff *skb2;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2410
  	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2411
  	u_int8_t u3 = nfmsg->nfgen_family;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
2412
2413
  	u16 zone;
  	int err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2414

b8f3ab429   David S. Miller   Revert "netlink: ...
2415
  	if (nlh->nlmsg_flags & NLM_F_DUMP) {
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
2416
2417
2418
2419
2420
2421
2422
2423
2424
  		if (cda[CTA_EXPECT_MASTER])
  			return ctnetlink_dump_exp_ct(ctnl, skb, nlh, cda);
  		else {
  			struct netlink_dump_control c = {
  				.dump = ctnetlink_exp_dump_table,
  				.done = ctnetlink_exp_done,
  			};
  			return netlink_dump_start(ctnl, skb, nlh, &c);
  		}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2425
  	}
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
2426
2427
2428
  	err = ctnetlink_parse_zone(cda[CTA_EXPECT_ZONE], &zone);
  	if (err < 0)
  		return err;
35dba1d7f   Pablo Neira Ayuso   netfilter: ctnetl...
2429
2430
2431
  	if (cda[CTA_EXPECT_TUPLE])
  		err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE, u3);
  	else if (cda[CTA_EXPECT_MASTER])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2432
2433
2434
2435
2436
2437
  		err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER, u3);
  	else
  		return -EINVAL;
  
  	if (err < 0)
  		return err;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
2438
  	exp = nf_ct_expect_find_get(net, zone, &tuple);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2439
2440
  	if (!exp)
  		return -ENOENT;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2441
  	if (cda[CTA_EXPECT_ID]) {
77236b6e3   Patrick McHardy   [NETFILTER]: ctne...
2442
  		__be32 id = nla_get_be32(cda[CTA_EXPECT_ID]);
358324024   Patrick McHardy   [NETFILTER]: nf_c...
2443
  		if (ntohl(id) != (u32)(unsigned long)exp) {
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
2444
  			nf_ct_expect_put(exp);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2445
2446
  			return -ENOENT;
  		}
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2447
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2448
2449
  
  	err = -ENOMEM;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2450
  	skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
81378f728   Pablo Neira Ayuso   netfilter: ctnetl...
2451
2452
  	if (skb2 == NULL) {
  		nf_ct_expect_put(exp);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2453
  		goto out;
81378f728   Pablo Neira Ayuso   netfilter: ctnetl...
2454
  	}
4e9b82693   Thomas Graf   [NETLINK]: Remove...
2455

528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
2456
  	rcu_read_lock();
15e473046   Eric W. Biederman   netlink: Rename p...
2457
  	err = ctnetlink_exp_fill_info(skb2, NETLINK_CB(skb).portid,
8b0a231d4   Pablo Neira Ayuso   netfilter: ctnetl...
2458
  				      nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW, exp);
528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
2459
  	rcu_read_unlock();
81378f728   Pablo Neira Ayuso   netfilter: ctnetl...
2460
  	nf_ct_expect_put(exp);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2461
2462
  	if (err <= 0)
  		goto free;
15e473046   Eric W. Biederman   netlink: Rename p...
2463
  	err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT);
81378f728   Pablo Neira Ayuso   netfilter: ctnetl...
2464
2465
  	if (err < 0)
  		goto out;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2466

81378f728   Pablo Neira Ayuso   netfilter: ctnetl...
2467
  	return 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2468
2469
2470
2471
  
  free:
  	kfree_skb(skb2);
  out:
81378f728   Pablo Neira Ayuso   netfilter: ctnetl...
2472
2473
  	/* this avoids a loop in nfnetlink. */
  	return err == -EAGAIN ? -ENOBUFS : err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2474
2475
2476
  }
  
  static int
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2477
  ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
399383246   Patrick McHardy   netfilter: nfnetl...
2478
2479
  		     const struct nlmsghdr *nlh,
  		     const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2480
  {
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
2481
  	struct net *net = sock_net(ctnl);
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2482
  	struct nf_conntrack_expect *exp;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2483
  	struct nf_conntrack_tuple tuple;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2484
  	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
b67bfe0d4   Sasha Levin   hlist: drop the n...
2485
  	struct hlist_node *next;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2486
  	u_int8_t u3 = nfmsg->nfgen_family;
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2487
  	unsigned int i;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
2488
  	u16 zone;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2489
  	int err;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2490
  	if (cda[CTA_EXPECT_TUPLE]) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2491
  		/* delete a single expect by tuple */
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
2492
2493
2494
  		err = ctnetlink_parse_zone(cda[CTA_EXPECT_ZONE], &zone);
  		if (err < 0)
  			return err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2495
2496
2497
2498
2499
  		err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE, u3);
  		if (err < 0)
  			return err;
  
  		/* bump usage count to 2 */
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
2500
  		exp = nf_ct_expect_find_get(net, zone, &tuple);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2501
2502
  		if (!exp)
  			return -ENOENT;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2503
  		if (cda[CTA_EXPECT_ID]) {
77236b6e3   Patrick McHardy   [NETFILTER]: ctne...
2504
  			__be32 id = nla_get_be32(cda[CTA_EXPECT_ID]);
358324024   Patrick McHardy   [NETFILTER]: nf_c...
2505
  			if (ntohl(id) != (u32)(unsigned long)exp) {
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
2506
  				nf_ct_expect_put(exp);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2507
2508
2509
2510
2511
  				return -ENOENT;
  			}
  		}
  
  		/* after list removal, usage count == 1 */
ebbf41df4   Pablo Neira Ayuso   netfilter: ctnetl...
2512
2513
  		spin_lock_bh(&nf_conntrack_lock);
  		if (del_timer(&exp->timeout)) {
15e473046   Eric W. Biederman   netlink: Rename p...
2514
  			nf_ct_unlink_expect_report(exp, NETLINK_CB(skb).portid,
ebbf41df4   Pablo Neira Ayuso   netfilter: ctnetl...
2515
2516
2517
2518
  						   nlmsg_report(nlh));
  			nf_ct_expect_put(exp);
  		}
  		spin_unlock_bh(&nf_conntrack_lock);
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2519
  		/* have to put what we 'get' above.
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2520
  		 * after this line usage count == 0 */
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
2521
  		nf_ct_expect_put(exp);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2522
2523
  	} else if (cda[CTA_EXPECT_HELP_NAME]) {
  		char *name = nla_data(cda[CTA_EXPECT_HELP_NAME]);
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2524
  		struct nf_conn_help *m_help;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2525
2526
  
  		/* delete all expectations for this helper */
f8ba1affa   Patrick McHardy   [NETFILTER]: nf_c...
2527
  		spin_lock_bh(&nf_conntrack_lock);
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2528
  		for (i = 0; i < nf_ct_expect_hsize; i++) {
b67bfe0d4   Sasha Levin   hlist: drop the n...
2529
  			hlist_for_each_entry_safe(exp, next,
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
2530
  						  &net->ct.expect_hash[i],
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2531
2532
  						  hnode) {
  				m_help = nfct_help(exp->master);
794e68716   Patrick McHardy   netfilter: ctnetl...
2533
2534
  				if (!strcmp(m_help->helper->name, name) &&
  				    del_timer(&exp->timeout)) {
ebbf41df4   Pablo Neira Ayuso   netfilter: ctnetl...
2535
  					nf_ct_unlink_expect_report(exp,
15e473046   Eric W. Biederman   netlink: Rename p...
2536
  							NETLINK_CB(skb).portid,
ebbf41df4   Pablo Neira Ayuso   netfilter: ctnetl...
2537
  							nlmsg_report(nlh));
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2538
2539
  					nf_ct_expect_put(exp);
  				}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2540
2541
  			}
  		}
f8ba1affa   Patrick McHardy   [NETFILTER]: nf_c...
2542
  		spin_unlock_bh(&nf_conntrack_lock);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2543
2544
  	} else {
  		/* This basically means we have to flush everything*/
f8ba1affa   Patrick McHardy   [NETFILTER]: nf_c...
2545
  		spin_lock_bh(&nf_conntrack_lock);
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2546
  		for (i = 0; i < nf_ct_expect_hsize; i++) {
b67bfe0d4   Sasha Levin   hlist: drop the n...
2547
  			hlist_for_each_entry_safe(exp, next,
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
2548
  						  &net->ct.expect_hash[i],
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2549
2550
  						  hnode) {
  				if (del_timer(&exp->timeout)) {
ebbf41df4   Pablo Neira Ayuso   netfilter: ctnetl...
2551
  					nf_ct_unlink_expect_report(exp,
15e473046   Eric W. Biederman   netlink: Rename p...
2552
  							NETLINK_CB(skb).portid,
ebbf41df4   Pablo Neira Ayuso   netfilter: ctnetl...
2553
  							nlmsg_report(nlh));
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2554
2555
  					nf_ct_expect_put(exp);
  				}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2556
2557
  			}
  		}
f8ba1affa   Patrick McHardy   [NETFILTER]: nf_c...
2558
  		spin_unlock_bh(&nf_conntrack_lock);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2559
2560
2561
2562
2563
  	}
  
  	return 0;
  }
  static int
399383246   Patrick McHardy   netfilter: nfnetl...
2564
2565
  ctnetlink_change_expect(struct nf_conntrack_expect *x,
  			const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2566
  {
9768e1ace   Kelvie Wong   netfilter: nf_ct_...
2567
2568
2569
2570
2571
2572
2573
2574
2575
  	if (cda[CTA_EXPECT_TIMEOUT]) {
  		if (!del_timer(&x->timeout))
  			return -ETIME;
  
  		x->timeout.expires = jiffies +
  			ntohl(nla_get_be32(cda[CTA_EXPECT_TIMEOUT])) * HZ;
  		add_timer(&x->timeout);
  	}
  	return 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2576
  }
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
  static const struct nla_policy exp_nat_nla_policy[CTA_EXPECT_NAT_MAX+1] = {
  	[CTA_EXPECT_NAT_DIR]	= { .type = NLA_U32 },
  	[CTA_EXPECT_NAT_TUPLE]	= { .type = NLA_NESTED },
  };
  
  static int
  ctnetlink_parse_expect_nat(const struct nlattr *attr,
  			   struct nf_conntrack_expect *exp,
  			   u_int8_t u3)
  {
  #ifdef CONFIG_NF_NAT_NEEDED
  	struct nlattr *tb[CTA_EXPECT_NAT_MAX+1];
  	struct nf_conntrack_tuple nat_tuple = {};
  	int err;
  
  	nla_parse_nested(tb, CTA_EXPECT_NAT_MAX, attr, exp_nat_nla_policy);
  
  	if (!tb[CTA_EXPECT_NAT_DIR] || !tb[CTA_EXPECT_NAT_TUPLE])
  		return -EINVAL;
  
  	err = ctnetlink_parse_tuple((const struct nlattr * const *)tb,
  					&nat_tuple, CTA_EXPECT_NAT_TUPLE, u3);
  	if (err < 0)
  		return err;
c7232c997   Patrick McHardy   netfilter: add pr...
2601
  	exp->saved_addr = nat_tuple.src.u3;
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2602
2603
2604
2605
2606
2607
2608
2609
  	exp->saved_proto = nat_tuple.src.u;
  	exp->dir = ntohl(nla_get_be32(tb[CTA_EXPECT_NAT_DIR]));
  
  	return 0;
  #else
  	return -EOPNOTSUPP;
  #endif
  }
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2610
  static int
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
2611
2612
  ctnetlink_create_expect(struct net *net, u16 zone,
  			const struct nlattr * const cda[],
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
2613
  			u_int8_t u3,
15e473046   Eric W. Biederman   netlink: Rename p...
2614
  			u32 portid, int report)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2615
2616
2617
2618
2619
  {
  	struct nf_conntrack_tuple tuple, mask, master_tuple;
  	struct nf_conntrack_tuple_hash *h = NULL;
  	struct nf_conntrack_expect *exp;
  	struct nf_conn *ct;
dc808fe28   Harald Welte   [NETFILTER] nf_co...
2620
  	struct nf_conn_help *help;
660fdb2a0   Pablo Neira Ayuso   netfilter: ctnetl...
2621
  	struct nf_conntrack_helper *helper = NULL;
b8c5e52c1   Pablo Neira Ayuso   netfilter: ctnetl...
2622
  	u_int32_t class = 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2623
  	int err = 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
  	/* caller guarantees that those three CTA_EXPECT_* exist */
  	err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE, u3);
  	if (err < 0)
  		return err;
  	err = ctnetlink_parse_tuple(cda, &mask, CTA_EXPECT_MASK, u3);
  	if (err < 0)
  		return err;
  	err = ctnetlink_parse_tuple(cda, &master_tuple, CTA_EXPECT_MASTER, u3);
  	if (err < 0)
  		return err;
  
  	/* Look for master conntrack of this expectation */
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
2636
  	h = nf_conntrack_find_get(net, zone, &master_tuple);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2637
2638
2639
  	if (!h)
  		return -ENOENT;
  	ct = nf_ct_tuplehash_to_ctrack(h);
660fdb2a0   Pablo Neira Ayuso   netfilter: ctnetl...
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
  
  	/* Look for helper of this expectation */
  	if (cda[CTA_EXPECT_HELP_NAME]) {
  		const char *helpname = nla_data(cda[CTA_EXPECT_HELP_NAME]);
  
  		helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct),
  						    nf_ct_protonum(ct));
  		if (helper == NULL) {
  #ifdef CONFIG_MODULES
  			if (request_module("nfct-helper-%s", helpname) < 0) {
  				err = -EOPNOTSUPP;
  				goto out;
  			}
  
  			helper = __nf_conntrack_helper_find(helpname,
  							    nf_ct_l3num(ct),
  							    nf_ct_protonum(ct));
  			if (helper) {
  				err = -EAGAIN;
  				goto out;
  			}
  #endif
  			err = -EOPNOTSUPP;
  			goto out;
  		}
  	}
b8c5e52c1   Pablo Neira Ayuso   netfilter: ctnetl...
2666
2667
2668
2669
2670
2671
2672
  	if (cda[CTA_EXPECT_CLASS] && helper) {
  		class = ntohl(nla_get_be32(cda[CTA_EXPECT_CLASS]));
  		if (class > helper->expect_class_max) {
  			err = -EINVAL;
  			goto out;
  		}
  	}
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
2673
  	exp = nf_ct_expect_alloc(ct);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2674
2675
2676
2677
  	if (!exp) {
  		err = -ENOMEM;
  		goto out;
  	}
bc01befdc   Pablo Neira Ayuso   netfilter: ctnetl...
2678
2679
2680
2681
  	help = nfct_help(ct);
  	if (!help) {
  		if (!cda[CTA_EXPECT_TIMEOUT]) {
  			err = -EINVAL;
1310b955c   Jesper Juhl   netfilter: ctnetl...
2682
  			goto err_out;
bc01befdc   Pablo Neira Ayuso   netfilter: ctnetl...
2683
2684
2685
  		}
  		exp->timeout.expires =
  		  jiffies + ntohl(nla_get_be32(cda[CTA_EXPECT_TIMEOUT])) * HZ;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2686

bc01befdc   Pablo Neira Ayuso   netfilter: ctnetl...
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
  		exp->flags = NF_CT_EXPECT_USERSPACE;
  		if (cda[CTA_EXPECT_FLAGS]) {
  			exp->flags |=
  				ntohl(nla_get_be32(cda[CTA_EXPECT_FLAGS]));
  		}
  	} else {
  		if (cda[CTA_EXPECT_FLAGS]) {
  			exp->flags = ntohl(nla_get_be32(cda[CTA_EXPECT_FLAGS]));
  			exp->flags &= ~NF_CT_EXPECT_USERSPACE;
  		} else
  			exp->flags = 0;
  	}
544d5c7d9   Pablo Neira Ayuso   netfilter: ctnetl...
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
  	if (cda[CTA_EXPECT_FN]) {
  		const char *name = nla_data(cda[CTA_EXPECT_FN]);
  		struct nf_ct_helper_expectfn *expfn;
  
  		expfn = nf_ct_helper_expectfn_find_by_name(name);
  		if (expfn == NULL) {
  			err = -EINVAL;
  			goto err_out;
  		}
  		exp->expectfn = expfn->expectfn;
  	} else
  		exp->expectfn = NULL;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2711

b8c5e52c1   Pablo Neira Ayuso   netfilter: ctnetl...
2712
  	exp->class = class;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2713
  	exp->master = ct;
660fdb2a0   Pablo Neira Ayuso   netfilter: ctnetl...
2714
  	exp->helper = helper;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2715
  	memcpy(&exp->tuple, &tuple, sizeof(struct nf_conntrack_tuple));
d4156e8cd   Patrick McHardy   [NETFILTER]: nf_c...
2716
2717
  	memcpy(&exp->mask.src.u3, &mask.src.u3, sizeof(exp->mask.src.u3));
  	exp->mask.src.u.all = mask.src.u.all;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2718

076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2719
2720
2721
2722
2723
2724
  	if (cda[CTA_EXPECT_NAT]) {
  		err = ctnetlink_parse_expect_nat(cda[CTA_EXPECT_NAT],
  						 exp, u3);
  		if (err < 0)
  			goto err_out;
  	}
15e473046   Eric W. Biederman   netlink: Rename p...
2725
  	err = nf_ct_expect_related_report(exp, portid, report);
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2726
  err_out:
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
2727
  	nf_ct_expect_put(exp);
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2728
  out:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2729
2730
2731
2732
2733
2734
  	nf_ct_put(nf_ct_tuplehash_to_ctrack(h));
  	return err;
  }
  
  static int
  ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb,
399383246   Patrick McHardy   netfilter: nfnetl...
2735
2736
  		     const struct nlmsghdr *nlh,
  		     const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2737
  {
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
2738
  	struct net *net = sock_net(ctnl);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2739
2740
  	struct nf_conntrack_tuple tuple;
  	struct nf_conntrack_expect *exp;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2741
  	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2742
  	u_int8_t u3 = nfmsg->nfgen_family;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
2743
2744
  	u16 zone;
  	int err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2745

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2746
2747
2748
  	if (!cda[CTA_EXPECT_TUPLE]
  	    || !cda[CTA_EXPECT_MASK]
  	    || !cda[CTA_EXPECT_MASTER])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2749
  		return -EINVAL;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
2750
2751
2752
  	err = ctnetlink_parse_zone(cda[CTA_EXPECT_ZONE], &zone);
  	if (err < 0)
  		return err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2753
2754
2755
  	err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE, u3);
  	if (err < 0)
  		return err;
f8ba1affa   Patrick McHardy   [NETFILTER]: nf_c...
2756
  	spin_lock_bh(&nf_conntrack_lock);
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
2757
  	exp = __nf_ct_expect_find(net, zone, &tuple);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2758
2759
  
  	if (!exp) {
f8ba1affa   Patrick McHardy   [NETFILTER]: nf_c...
2760
  		spin_unlock_bh(&nf_conntrack_lock);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2761
  		err = -ENOENT;
19abb7b09   Pablo Neira Ayuso   netfilter: ctnetl...
2762
  		if (nlh->nlmsg_flags & NLM_F_CREATE) {
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
2763
  			err = ctnetlink_create_expect(net, zone, cda,
19abb7b09   Pablo Neira Ayuso   netfilter: ctnetl...
2764
  						      u3,
15e473046   Eric W. Biederman   netlink: Rename p...
2765
  						      NETLINK_CB(skb).portid,
19abb7b09   Pablo Neira Ayuso   netfilter: ctnetl...
2766
2767
  						      nlmsg_report(nlh));
  		}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2768
2769
2770
2771
2772
2773
  		return err;
  	}
  
  	err = -EEXIST;
  	if (!(nlh->nlmsg_flags & NLM_F_EXCL))
  		err = ctnetlink_change_expect(exp, cda);
f8ba1affa   Patrick McHardy   [NETFILTER]: nf_c...
2774
  	spin_unlock_bh(&nf_conntrack_lock);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2775

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2776
2777
  	return err;
  }
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
2778
  static int
15e473046   Eric W. Biederman   netlink: Rename p...
2779
  ctnetlink_exp_stat_fill_info(struct sk_buff *skb, u32 portid, u32 seq, int cpu,
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
2780
2781
2782
2783
  			     const struct ip_conntrack_stat *st)
  {
  	struct nlmsghdr *nlh;
  	struct nfgenmsg *nfmsg;
15e473046   Eric W. Biederman   netlink: Rename p...
2784
  	unsigned int flags = portid ? NLM_F_MULTI : 0, event;
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
2785
2786
  
  	event = (NFNL_SUBSYS_CTNETLINK << 8 | IPCTNL_MSG_EXP_GET_STATS_CPU);
15e473046   Eric W. Biederman   netlink: Rename p...
2787
  	nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
  	if (nlh == NULL)
  		goto nlmsg_failure;
  
  	nfmsg = nlmsg_data(nlh);
  	nfmsg->nfgen_family = AF_UNSPEC;
  	nfmsg->version      = NFNETLINK_V0;
  	nfmsg->res_id	    = htons(cpu);
  
  	if (nla_put_be32(skb, CTA_STATS_EXP_NEW, htonl(st->expect_new)) ||
  	    nla_put_be32(skb, CTA_STATS_EXP_CREATE, htonl(st->expect_create)) ||
  	    nla_put_be32(skb, CTA_STATS_EXP_DELETE, htonl(st->expect_delete)))
  		goto nla_put_failure;
  
  	nlmsg_end(skb, nlh);
  	return skb->len;
  
  nla_put_failure:
  nlmsg_failure:
  	nlmsg_cancel(skb, nlh);
  	return -1;
  }
  
  static int
  ctnetlink_exp_stat_cpu_dump(struct sk_buff *skb, struct netlink_callback *cb)
  {
  	int cpu;
  	struct net *net = sock_net(skb->sk);
  
  	if (cb->args[0] == nr_cpu_ids)
  		return 0;
  
  	for (cpu = cb->args[0]; cpu < nr_cpu_ids; cpu++) {
  		const struct ip_conntrack_stat *st;
  
  		if (!cpu_possible(cpu))
  			continue;
  
  		st = per_cpu_ptr(net->ct.stat, cpu);
15e473046   Eric W. Biederman   netlink: Rename p...
2826
  		if (ctnetlink_exp_stat_fill_info(skb, NETLINK_CB(cb->skb).portid,
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
  						 cb->nlh->nlmsg_seq,
  						 cpu, st) < 0)
  			break;
  	}
  	cb->args[0] = cpu;
  
  	return skb->len;
  }
  
  static int
  ctnetlink_stat_exp_cpu(struct sock *ctnl, struct sk_buff *skb,
  		       const struct nlmsghdr *nlh,
  		       const struct nlattr * const cda[])
  {
  	if (nlh->nlmsg_flags & NLM_F_DUMP) {
  		struct netlink_dump_control c = {
  			.dump = ctnetlink_exp_stat_cpu_dump,
  		};
  		return netlink_dump_start(ctnl, skb, nlh, &c);
  	}
  
  	return 0;
  }
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2850
  #ifdef CONFIG_NF_CONNTRACK_EVENTS
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
2851
2852
  static struct nf_ct_event_notifier ctnl_notifier = {
  	.fcn = ctnetlink_conntrack_event,
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2853
  };
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
2854
2855
  static struct nf_exp_event_notifier ctnl_notifier_exp = {
  	.fcn = ctnetlink_expect_event,
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2856
2857
  };
  #endif
7c8d4cb41   Patrick McHardy   [NETFILTER]: nfne...
2858
  static const struct nfnl_callback ctnl_cb[IPCTNL_MSG_MAX] = {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2859
  	[IPCTNL_MSG_CT_NEW]		= { .call = ctnetlink_new_conntrack,
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
2860
2861
  					    .attr_count = CTA_MAX,
  					    .policy = ct_nla_policy },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2862
  	[IPCTNL_MSG_CT_GET] 		= { .call = ctnetlink_get_conntrack,
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
2863
2864
  					    .attr_count = CTA_MAX,
  					    .policy = ct_nla_policy },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2865
  	[IPCTNL_MSG_CT_DELETE]  	= { .call = ctnetlink_del_conntrack,
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
2866
2867
  					    .attr_count = CTA_MAX,
  					    .policy = ct_nla_policy },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2868
  	[IPCTNL_MSG_CT_GET_CTRZERO] 	= { .call = ctnetlink_get_conntrack,
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
2869
2870
  					    .attr_count = CTA_MAX,
  					    .policy = ct_nla_policy },
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
2871
2872
  	[IPCTNL_MSG_CT_GET_STATS_CPU]	= { .call = ctnetlink_stat_ct_cpu },
  	[IPCTNL_MSG_CT_GET_STATS]	= { .call = ctnetlink_stat_ct },
d871befe3   Pablo Neira Ayuso   netfilter: ctnetl...
2873
2874
  	[IPCTNL_MSG_CT_GET_DYING]	= { .call = ctnetlink_get_ct_dying },
  	[IPCTNL_MSG_CT_GET_UNCONFIRMED]	= { .call = ctnetlink_get_ct_unconfirmed },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2875
  };
7c8d4cb41   Patrick McHardy   [NETFILTER]: nfne...
2876
  static const struct nfnl_callback ctnl_exp_cb[IPCTNL_MSG_EXP_MAX] = {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2877
  	[IPCTNL_MSG_EXP_GET]		= { .call = ctnetlink_get_expect,
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
2878
2879
  					    .attr_count = CTA_EXPECT_MAX,
  					    .policy = exp_nla_policy },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2880
  	[IPCTNL_MSG_EXP_NEW]		= { .call = ctnetlink_new_expect,
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
2881
2882
  					    .attr_count = CTA_EXPECT_MAX,
  					    .policy = exp_nla_policy },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2883
  	[IPCTNL_MSG_EXP_DELETE]		= { .call = ctnetlink_del_expect,
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
2884
2885
  					    .attr_count = CTA_EXPECT_MAX,
  					    .policy = exp_nla_policy },
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
2886
  	[IPCTNL_MSG_EXP_GET_STATS_CPU]	= { .call = ctnetlink_stat_exp_cpu },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2887
  };
7c8d4cb41   Patrick McHardy   [NETFILTER]: nfne...
2888
  static const struct nfnetlink_subsystem ctnl_subsys = {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2889
2890
2891
2892
2893
  	.name				= "conntrack",
  	.subsys_id			= NFNL_SUBSYS_CTNETLINK,
  	.cb_count			= IPCTNL_MSG_MAX,
  	.cb				= ctnl_cb,
  };
7c8d4cb41   Patrick McHardy   [NETFILTER]: nfne...
2894
  static const struct nfnetlink_subsystem ctnl_exp_subsys = {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2895
2896
2897
2898
2899
  	.name				= "conntrack_expect",
  	.subsys_id			= NFNL_SUBSYS_CTNETLINK_EXP,
  	.cb_count			= IPCTNL_MSG_EXP_MAX,
  	.cb				= ctnl_exp_cb,
  };
d2483ddef   Patrick McHardy   [NETFILTER]: nf_c...
2900
  MODULE_ALIAS("ip_conntrack_netlink");
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2901
  MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK);
34f9a2e4d   Pablo Neira Ayuso   [NETFILTER]: ctne...
2902
  MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_EXP);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2903

70e9942f1   Pablo Neira Ayuso   netfilter: nf_con...
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
  static int __net_init ctnetlink_net_init(struct net *net)
  {
  #ifdef CONFIG_NF_CONNTRACK_EVENTS
  	int ret;
  
  	ret = nf_conntrack_register_notifier(net, &ctnl_notifier);
  	if (ret < 0) {
  		pr_err("ctnetlink_init: cannot register notifier.
  ");
  		goto err_out;
  	}
  
  	ret = nf_ct_expect_register_notifier(net, &ctnl_notifier_exp);
  	if (ret < 0) {
  		pr_err("ctnetlink_init: cannot expect register notifier.
  ");
  		goto err_unreg_notifier;
  	}
  #endif
  	return 0;
  
  #ifdef CONFIG_NF_CONNTRACK_EVENTS
  err_unreg_notifier:
  	nf_conntrack_unregister_notifier(net, &ctnl_notifier);
  err_out:
  	return ret;
  #endif
  }
  
  static void ctnetlink_net_exit(struct net *net)
  {
  #ifdef CONFIG_NF_CONNTRACK_EVENTS
  	nf_ct_expect_unregister_notifier(net, &ctnl_notifier_exp);
  	nf_conntrack_unregister_notifier(net, &ctnl_notifier);
  #endif
  }
  
  static void __net_exit ctnetlink_net_exit_batch(struct list_head *net_exit_list)
  {
  	struct net *net;
  
  	list_for_each_entry(net, net_exit_list, exit_list)
  		ctnetlink_net_exit(net);
  }
  
  static struct pernet_operations ctnetlink_net_ops = {
  	.init		= ctnetlink_net_init,
  	.exit_batch	= ctnetlink_net_exit_batch,
  };
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2953
2954
2955
  static int __init ctnetlink_init(void)
  {
  	int ret;
654d0fbdc   Stephen Hemminger   netfilter: cleanu...
2956
2957
  	pr_info("ctnetlink v%s: registering with nfnetlink.
  ", version);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2958
2959
  	ret = nfnetlink_subsys_register(&ctnl_subsys);
  	if (ret < 0) {
654d0fbdc   Stephen Hemminger   netfilter: cleanu...
2960
2961
  		pr_err("ctnetlink_init: cannot register with nfnetlink.
  ");
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2962
2963
2964
2965
2966
  		goto err_out;
  	}
  
  	ret = nfnetlink_subsys_register(&ctnl_exp_subsys);
  	if (ret < 0) {
654d0fbdc   Stephen Hemminger   netfilter: cleanu...
2967
2968
  		pr_err("ctnetlink_init: cannot register exp with nfnetlink.
  ");
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2969
2970
  		goto err_unreg_subsys;
  	}
ef6acf68c   Julia Lawall   netfilter: ctnetl...
2971
2972
  	ret = register_pernet_subsys(&ctnetlink_net_ops);
  	if (ret < 0) {
70e9942f1   Pablo Neira Ayuso   netfilter: nf_con...
2973
2974
  		pr_err("ctnetlink_init: cannot register pernet operations
  ");
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2975
2976
  		goto err_unreg_exp_subsys;
  	}
7c6223454   Pablo Neira Ayuso   netfilter: nfnetl...
2977
  #ifdef CONFIG_NETFILTER_NETLINK_QUEUE_CT
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2978
2979
2980
  	/* setup interaction between nf_queue and nf_conntrack_netlink. */
  	RCU_INIT_POINTER(nfq_ct_hook, &ctnetlink_nfqueue_hook);
  #endif
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2981
  	return 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2982
2983
  err_unreg_exp_subsys:
  	nfnetlink_subsys_unregister(&ctnl_exp_subsys);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2984
2985
2986
2987
2988
2989
2990
2991
  err_unreg_subsys:
  	nfnetlink_subsys_unregister(&ctnl_subsys);
  err_out:
  	return ret;
  }
  
  static void __exit ctnetlink_exit(void)
  {
654d0fbdc   Stephen Hemminger   netfilter: cleanu...
2992
2993
  	pr_info("ctnetlink: unregistering from nfnetlink.
  ");
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2994

70e9942f1   Pablo Neira Ayuso   netfilter: nf_con...
2995
  	unregister_pernet_subsys(&ctnetlink_net_ops);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2996
2997
  	nfnetlink_subsys_unregister(&ctnl_exp_subsys);
  	nfnetlink_subsys_unregister(&ctnl_subsys);
7c6223454   Pablo Neira Ayuso   netfilter: nfnetl...
2998
  #ifdef CONFIG_NETFILTER_NETLINK_QUEUE_CT
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2999
3000
  	RCU_INIT_POINTER(nfq_ct_hook, NULL);
  #endif
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3001
3002
3003
3004
  }
  
  module_init(ctnetlink_init);
  module_exit(ctnetlink_exit);