Blame view

net/netfilter/nf_conntrack_netlink.c 83.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
  #include <net/netfilter/nf_conntrack_helper.h>
41d73ec05   Patrick McHardy   netfilter: nf_con...
40
  #include <net/netfilter/nf_conntrack_seqadj.h>
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
41
  #include <net/netfilter/nf_conntrack_l3proto.h>
605dcad6c   Martin Josefsson   [NETFILTER]: nf_c...
42
  #include <net/netfilter/nf_conntrack_l4proto.h>
5b1158e90   Jozsef Kadlecsik   [NETFILTER]: Add ...
43
  #include <net/netfilter/nf_conntrack_tuple.h>
584015727   Krzysztof Piotr Oledzki   netfilter: accoun...
44
  #include <net/netfilter/nf_conntrack_acct.h>
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
45
  #include <net/netfilter/nf_conntrack_zones.h>
a992ca2a0   Pablo Neira Ayuso   netfilter: nf_con...
46
  #include <net/netfilter/nf_conntrack_timestamp.h>
c539f0171   Florian Westphal   netfilter: add co...
47
  #include <net/netfilter/nf_conntrack_labels.h>
87e94dbc2   Eric Leblond   netfilter: synpro...
48
49
  #include <net/netfilter/nf_conntrack_seqadj.h>
  #include <net/netfilter/nf_conntrack_synproxy.h>
5b1158e90   Jozsef Kadlecsik   [NETFILTER]: Add ...
50
51
  #ifdef CONFIG_NF_NAT_NEEDED
  #include <net/netfilter/nf_nat_core.h>
c7232c997   Patrick McHardy   netfilter: add pr...
52
  #include <net/netfilter/nf_nat_l4proto.h>
8c88f87cb   Pablo Neira Ayuso   netfilter: nfnetl...
53
  #include <net/netfilter/nf_nat_helper.h>
5b1158e90   Jozsef Kadlecsik   [NETFILTER]: Add ...
54
  #endif
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
55
56
57
58
59
  
  #include <linux/netfilter/nfnetlink.h>
  #include <linux/netfilter/nfnetlink_conntrack.h>
  
  MODULE_LICENSE("GPL");
dc808fe28   Harald Welte   [NETFILTER] nf_co...
60
  static char __initdata version[] = "0.93";
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
61

4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
62
  static int ctnetlink_dump_tuples_proto(struct sk_buff *skb,
2a04aabf5   Julia Lawall   netfilter: consti...
63
64
  				const struct nf_conntrack_tuple *tuple,
  				const struct nf_conntrack_l4proto *l4proto)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
65
  {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
66
  	int ret = 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
67
  	struct nlattr *nest_parms;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
68

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
69
70
71
  	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...
72
73
  	if (nla_put_u8(skb, CTA_PROTO_NUM, tuple->dst.protonum))
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
74

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

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
78
  	nla_nest_end(skb, nest_parms);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
79
80
  
  	return ret;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
81
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
82
83
  	return -1;
  }
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
84
85
  static int ctnetlink_dump_tuples_ip(struct sk_buff *skb,
  				    const struct nf_conntrack_tuple *tuple,
2a04aabf5   Julia Lawall   netfilter: consti...
86
  				    const 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;
  }
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
104
105
  static int ctnetlink_dump_tuples(struct sk_buff *skb,
  				 const struct nf_conntrack_tuple *tuple)
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
106
  {
b3480fe05   Florian Westphal   netfilter: conntr...
107
108
  	const struct nf_conntrack_l3proto *l3proto;
  	const struct nf_conntrack_l4proto *l4proto;
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
109
  	int ret;
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
110

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

3b988ece9   Hans Schillstrom   netfilter: ctnetl...
115
116
117
118
119
120
  	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 ...
121
  	return ret;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
122
  }
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
123
124
  static int ctnetlink_dump_zone_id(struct sk_buff *skb, int attrtype,
  				  const struct nf_conntrack_zone *zone, int dir)
deedb5903   Daniel Borkmann   netfilter: nf_con...
125
126
127
128
129
130
131
132
133
134
  {
  	if (zone->id == NF_CT_DEFAULT_ZONE_ID || zone->dir != dir)
  		return 0;
  	if (nla_put_be16(skb, attrtype, htons(zone->id)))
  		goto nla_put_failure;
  	return 0;
  
  nla_put_failure:
  	return -1;
  }
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
135
  static int ctnetlink_dump_status(struct sk_buff *skb, const struct nf_conn *ct)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
136
  {
cc1eb4313   David S. Miller   nf_conntrack_netl...
137
138
  	if (nla_put_be32(skb, CTA_STATUS, htonl(ct->status)))
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
139
  	return 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
140
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
141
142
  	return -1;
  }
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
143
  static int ctnetlink_dump_timeout(struct sk_buff *skb, const struct nf_conn *ct)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
144
  {
d0b35b93d   Florian Westphal   netfilter: use_nf...
145
  	long timeout = nf_ct_expires(ct) / HZ;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
146

cc1eb4313   David S. Miller   nf_conntrack_netl...
147
148
  	if (nla_put_be32(skb, CTA_TIMEOUT, htonl(timeout)))
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
149
  	return 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
150
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
151
152
  	return -1;
  }
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
153
  static int ctnetlink_dump_protoinfo(struct sk_buff *skb, struct nf_conn *ct)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
154
  {
b3480fe05   Florian Westphal   netfilter: conntr...
155
  	const struct nf_conntrack_l4proto *l4proto;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
156
  	struct nlattr *nest_proto;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
157
  	int ret;
528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
158
159
  	l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct));
  	if (!l4proto->to_nlattr)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
160
  		return 0;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
161

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

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

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

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

3c158f7f5   Patrick McHarrdy   [NETFILTER]: nf_c...
184
185
186
  	helper = rcu_dereference(help->helper);
  	if (!helper)
  		goto out;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
187
188
189
  	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...
190
191
  	if (nla_put_string(skb, CTA_HELP_NAME, helper->name))
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
192

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

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

4542fa472   Holger Eitzenberger   netfilter: ctnetl...
211
212
213
214
215
216
217
218
219
  	if (type == IPCTNL_MSG_CT_GET_CTRZERO) {
  		pkts = atomic64_xchg(&counter[dir].packets, 0);
  		bytes = atomic64_xchg(&counter[dir].bytes, 0);
  	} else {
  		pkts = atomic64_read(&counter[dir].packets);
  		bytes = atomic64_read(&counter[dir].bytes);
  	}
  
  	nest_count = nla_nest_start(skb, attr | NLA_F_NESTED);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
220
221
  	if (!nest_count)
  		goto nla_put_failure;
b46f6ded9   Nicolas Dichtel   libnl: nla_put_be...
222
223
224
225
  	if (nla_put_be64(skb, CTA_COUNTERS_PACKETS, cpu_to_be64(pkts),
  			 CTA_COUNTERS_PAD) ||
  	    nla_put_be64(skb, CTA_COUNTERS_BYTES, cpu_to_be64(bytes),
  			 CTA_COUNTERS_PAD))
cc1eb4313   David S. Miller   nf_conntrack_netl...
226
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
227

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
228
  	nla_nest_end(skb, nest_count);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
229
230
  
  	return 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
231
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
232
233
  	return -1;
  }
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
234

a992ca2a0   Pablo Neira Ayuso   netfilter: nf_con...
235
  static int
4542fa472   Holger Eitzenberger   netfilter: ctnetl...
236
  ctnetlink_dump_acct(struct sk_buff *skb, const struct nf_conn *ct, int type)
80e60e67b   Pablo Neira Ayuso   netfilter: ctnetl...
237
  {
4542fa472   Holger Eitzenberger   netfilter: ctnetl...
238
  	struct nf_conn_acct *acct = nf_conn_acct_find(ct);
80e60e67b   Pablo Neira Ayuso   netfilter: ctnetl...
239

80e60e67b   Pablo Neira Ayuso   netfilter: ctnetl...
240
241
  	if (!acct)
  		return 0;
4542fa472   Holger Eitzenberger   netfilter: ctnetl...
242
243
244
245
246
247
  	if (dump_counters(skb, acct, IP_CT_DIR_ORIGINAL, type) < 0)
  		return -1;
  	if (dump_counters(skb, acct, IP_CT_DIR_REPLY, type) < 0)
  		return -1;
  
  	return 0;
80e60e67b   Pablo Neira Ayuso   netfilter: ctnetl...
248
249
250
  }
  
  static int
a992ca2a0   Pablo Neira Ayuso   netfilter: nf_con...
251
252
253
254
255
256
257
258
259
260
261
262
  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;
b46f6ded9   Nicolas Dichtel   libnl: nla_put_be...
263
264
  	if (nla_put_be64(skb, CTA_TIMESTAMP_START, cpu_to_be64(tstamp->start),
  			 CTA_TIMESTAMP_PAD) ||
cc1eb4313   David S. Miller   nf_conntrack_netl...
265
  	    (tstamp->stop != 0 && nla_put_be64(skb, CTA_TIMESTAMP_STOP,
b46f6ded9   Nicolas Dichtel   libnl: nla_put_be...
266
267
  					       cpu_to_be64(tstamp->stop),
  					       CTA_TIMESTAMP_PAD)))
cc1eb4313   David S. Miller   nf_conntrack_netl...
268
  		goto nla_put_failure;
a992ca2a0   Pablo Neira Ayuso   netfilter: nf_con...
269
270
271
272
273
274
275
  	nla_nest_end(skb, nest_count);
  
  	return 0;
  
  nla_put_failure:
  	return -1;
  }
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
276
  #ifdef CONFIG_NF_CONNTRACK_MARK
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
277
  static int ctnetlink_dump_mark(struct sk_buff *skb, const struct nf_conn *ct)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
278
  {
cc1eb4313   David S. Miller   nf_conntrack_netl...
279
280
  	if (nla_put_be32(skb, CTA_MARK, htonl(ct->mark)))
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
281
  	return 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
282
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
283
284
285
286
287
  	return -1;
  }
  #else
  #define ctnetlink_dump_mark(a, b) (0)
  #endif
37fccd857   Pablo Neira Ayuso   [NETFILTER]: ctne...
288
  #ifdef CONFIG_NF_CONNTRACK_SECMARK
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
289
  static int ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct)
37fccd857   Pablo Neira Ayuso   [NETFILTER]: ctne...
290
  {
1cc63249a   Eric Paris   conntrack: export...
291
292
293
294
295
296
  	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...
297
  		return 0;
1cc63249a   Eric Paris   conntrack: export...
298
299
300
301
302
  
  	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...
303

cc1eb4313   David S. Miller   nf_conntrack_netl...
304
305
  	if (nla_put_string(skb, CTA_SECCTX_NAME, secctx))
  		goto nla_put_failure;
1cc63249a   Eric Paris   conntrack: export...
306
307
308
  	nla_nest_end(skb, nest_secctx);
  
  	ret = 0;
37fccd857   Pablo Neira Ayuso   [NETFILTER]: ctne...
309
  nla_put_failure:
1cc63249a   Eric Paris   conntrack: export...
310
311
  	security_release_secctx(secctx, len);
  	return ret;
37fccd857   Pablo Neira Ayuso   [NETFILTER]: ctne...
312
313
  }
  #else
1cc63249a   Eric Paris   conntrack: export...
314
  #define ctnetlink_dump_secctx(a, b) (0)
37fccd857   Pablo Neira Ayuso   [NETFILTER]: ctne...
315
  #endif
0ceabd838   Florian Westphal   netfilter: ctnetl...
316
  #ifdef CONFIG_NF_CONNTRACK_LABELS
4a96300ce   Pablo Neira Ayuso   netfilter: ctnetl...
317
  static inline int ctnetlink_label_size(const struct nf_conn *ct)
0ceabd838   Florian Westphal   netfilter: ctnetl...
318
319
320
321
322
  {
  	struct nf_conn_labels *labels = nf_ct_labels_find(ct);
  
  	if (!labels)
  		return 0;
23014011b   Florian Westphal   netfilter: conntr...
323
  	return nla_total_size(sizeof(labels->bits));
0ceabd838   Florian Westphal   netfilter: ctnetl...
324
325
326
327
328
329
  }
  
  static int
  ctnetlink_dump_labels(struct sk_buff *skb, const struct nf_conn *ct)
  {
  	struct nf_conn_labels *labels = nf_ct_labels_find(ct);
23014011b   Florian Westphal   netfilter: conntr...
330
  	unsigned int i;
0ceabd838   Florian Westphal   netfilter: ctnetl...
331
332
333
  
  	if (!labels)
  		return 0;
0ceabd838   Florian Westphal   netfilter: ctnetl...
334
335
336
  	i = 0;
  	do {
  		if (labels->bits[i] != 0)
23014011b   Florian Westphal   netfilter: conntr...
337
338
  			return nla_put(skb, CTA_LABELS, sizeof(labels->bits),
  				       labels->bits);
0ceabd838   Florian Westphal   netfilter: ctnetl...
339
  		i++;
23014011b   Florian Westphal   netfilter: conntr...
340
  	} while (i < ARRAY_SIZE(labels->bits));
0ceabd838   Florian Westphal   netfilter: ctnetl...
341
342
343
344
345
346
347
  
  	return 0;
  }
  #else
  #define ctnetlink_dump_labels(a, b) (0)
  #define ctnetlink_label_size(a)	(0)
  #endif
0f417ce98   Pablo Neira Ayuso   [NETFILTER]: ctne...
348
  #define master_tuple(ct) &(ct->master->tuplehash[IP_CT_DIR_ORIGINAL].tuple)
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
349
  static int ctnetlink_dump_master(struct sk_buff *skb, const struct nf_conn *ct)
0f417ce98   Pablo Neira Ayuso   [NETFILTER]: ctne...
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
  {
  	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;
  }
bb5cf80e9   Ilpo Järvinen   [NETFILTER]: Kill...
368
  static int
41d73ec05   Patrick McHardy   netfilter: nf_con...
369
  dump_ct_seq_adj(struct sk_buff *skb, const struct nf_ct_seqadj *seq, int type)
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
370
  {
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
371
372
373
374
375
  	struct nlattr *nest_parms;
  
  	nest_parms = nla_nest_start(skb, type | NLA_F_NESTED);
  	if (!nest_parms)
  		goto nla_put_failure;
41d73ec05   Patrick McHardy   netfilter: nf_con...
376
377
378
379
380
381
  	if (nla_put_be32(skb, CTA_SEQADJ_CORRECTION_POS,
  			 htonl(seq->correction_pos)) ||
  	    nla_put_be32(skb, CTA_SEQADJ_OFFSET_BEFORE,
  			 htonl(seq->offset_before)) ||
  	    nla_put_be32(skb, CTA_SEQADJ_OFFSET_AFTER,
  			 htonl(seq->offset_after)))
cc1eb4313   David S. Miller   nf_conntrack_netl...
382
  		goto nla_put_failure;
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
383
384
385
386
387
388
389
390
  
  	nla_nest_end(skb, nest_parms);
  
  	return 0;
  
  nla_put_failure:
  	return -1;
  }
64f3967c7   Liping Zhang   netfilter: ctnetl...
391
  static int ctnetlink_dump_ct_seq_adj(struct sk_buff *skb, struct nf_conn *ct)
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
392
  {
41d73ec05   Patrick McHardy   netfilter: nf_con...
393
394
  	struct nf_conn_seqadj *seqadj = nfct_seqadj(ct);
  	struct nf_ct_seqadj *seq;
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
395

41d73ec05   Patrick McHardy   netfilter: nf_con...
396
  	if (!(ct->status & IPS_SEQ_ADJUST) || !seqadj)
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
397
  		return 0;
64f3967c7   Liping Zhang   netfilter: ctnetl...
398
  	spin_lock_bh(&ct->lock);
41d73ec05   Patrick McHardy   netfilter: nf_con...
399
400
  	seq = &seqadj->seq[IP_CT_DIR_ORIGINAL];
  	if (dump_ct_seq_adj(skb, seq, CTA_SEQ_ADJ_ORIG) == -1)
64f3967c7   Liping Zhang   netfilter: ctnetl...
401
  		goto err;
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
402

41d73ec05   Patrick McHardy   netfilter: nf_con...
403
404
  	seq = &seqadj->seq[IP_CT_DIR_REPLY];
  	if (dump_ct_seq_adj(skb, seq, CTA_SEQ_ADJ_REPLY) == -1)
64f3967c7   Liping Zhang   netfilter: ctnetl...
405
  		goto err;
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
406

64f3967c7   Liping Zhang   netfilter: ctnetl...
407
  	spin_unlock_bh(&ct->lock);
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
408
  	return 0;
64f3967c7   Liping Zhang   netfilter: ctnetl...
409
410
411
  err:
  	spin_unlock_bh(&ct->lock);
  	return -1;
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
412
  }
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
413

4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
414
  static int ctnetlink_dump_id(struct sk_buff *skb, const struct nf_conn *ct)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
415
  {
cc1eb4313   David S. Miller   nf_conntrack_netl...
416
417
  	if (nla_put_be32(skb, CTA_ID, htonl((unsigned long)ct)))
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
418
  	return 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
419
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
420
421
  	return -1;
  }
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
422
  static int ctnetlink_dump_use(struct sk_buff *skb, const struct nf_conn *ct)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
423
  {
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
  {
308ac9143   Daniel Borkmann   netfilter: nf_con...
434
  	const struct nf_conntrack_zone *zone;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
435
436
  	struct nlmsghdr *nlh;
  	struct nfgenmsg *nfmsg;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
437
  	struct nlattr *nest_parms;
15e473046   Eric W. Biederman   netlink: Rename p...
438
  	unsigned int flags = portid ? NLM_F_MULTI : 0, event;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
439

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

96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
445
  	nfmsg = nlmsg_data(nlh);
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
446
  	nfmsg->nfgen_family = nf_ct_l3num(ct);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
447
448
  	nfmsg->version      = NFNETLINK_V0;
  	nfmsg->res_id	    = 0;
deedb5903   Daniel Borkmann   netfilter: nf_con...
449
  	zone = nf_ct_zone(ct);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
450
451
452
  	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...
453
  	if (ctnetlink_dump_tuples(skb, nf_ct_tuple(ct, IP_CT_DIR_ORIGINAL)) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
454
  		goto nla_put_failure;
deedb5903   Daniel Borkmann   netfilter: nf_con...
455
456
457
  	if (ctnetlink_dump_zone_id(skb, CTA_TUPLE_ZONE, zone,
  				   NF_CT_ZONE_DIR_ORIG) < 0)
  		goto nla_put_failure;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
458
  	nla_nest_end(skb, nest_parms);
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
459

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
460
461
462
  	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...
463
  	if (ctnetlink_dump_tuples(skb, nf_ct_tuple(ct, IP_CT_DIR_REPLY)) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
464
  		goto nla_put_failure;
deedb5903   Daniel Borkmann   netfilter: nf_con...
465
466
467
  	if (ctnetlink_dump_zone_id(skb, CTA_TUPLE_ZONE, zone,
  				   NF_CT_ZONE_DIR_REPL) < 0)
  		goto nla_put_failure;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
468
  	nla_nest_end(skb, nest_parms);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
469

deedb5903   Daniel Borkmann   netfilter: nf_con...
470
471
  	if (ctnetlink_dump_zone_id(skb, CTA_ZONE, zone,
  				   NF_CT_DEFAULT_ZONE_DIR) < 0)
cc1eb4313   David S. Miller   nf_conntrack_netl...
472
  		goto nla_put_failure;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
473

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
474
475
  	if (ctnetlink_dump_status(skb, ct) < 0 ||
  	    ctnetlink_dump_timeout(skb, ct) < 0 ||
4542fa472   Holger Eitzenberger   netfilter: ctnetl...
476
  	    ctnetlink_dump_acct(skb, ct, type) < 0 ||
a992ca2a0   Pablo Neira Ayuso   netfilter: nf_con...
477
  	    ctnetlink_dump_timestamp(skb, ct) < 0 ||
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
478
479
480
  	    ctnetlink_dump_protoinfo(skb, ct) < 0 ||
  	    ctnetlink_dump_helpinfo(skb, ct) < 0 ||
  	    ctnetlink_dump_mark(skb, ct) < 0 ||
1cc63249a   Eric Paris   conntrack: export...
481
  	    ctnetlink_dump_secctx(skb, ct) < 0 ||
0ceabd838   Florian Westphal   netfilter: ctnetl...
482
  	    ctnetlink_dump_labels(skb, ct) < 0 ||
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
483
  	    ctnetlink_dump_id(skb, ct) < 0 ||
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
484
  	    ctnetlink_dump_use(skb, ct) < 0 ||
0f417ce98   Pablo Neira Ayuso   [NETFILTER]: ctne...
485
  	    ctnetlink_dump_master(skb, ct) < 0 ||
41d73ec05   Patrick McHardy   netfilter: nf_con...
486
  	    ctnetlink_dump_ct_seq_adj(skb, ct) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
487
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
488

96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
489
  	nlmsg_end(skb, nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
490
491
492
  	return skb->len;
  
  nlmsg_failure:
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
493
  nla_put_failure:
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
494
  	nlmsg_cancel(skb, nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
495
496
  	return -1;
  }
4a96300ce   Pablo Neira Ayuso   netfilter: ctnetl...
497
  static inline size_t ctnetlink_proto_size(const struct nf_conn *ct)
2732c4e45   Holger Eitzenberger   netfilter: ctnetl...
498
  {
b3480fe05   Florian Westphal   netfilter: conntr...
499
500
501
  	const struct nf_conntrack_l3proto *l3proto;
  	const struct nf_conntrack_l4proto *l4proto;
  	size_t len;
03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
502

03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
503
  	l3proto = __nf_ct_l3proto_find(nf_ct_l3num(ct));
0d0351003   Florian Westphal   netfilter: conntr...
504
505
  	len = l3proto->nla_size;
  	len *= 3u; /* ORIG, REPLY, MASTER */
03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
506
507
508
  
  	l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct));
  	len += l4proto->nla_size;
03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
509
510
511
  
  	return len;
  }
4a96300ce   Pablo Neira Ayuso   netfilter: ctnetl...
512
  static inline size_t ctnetlink_acct_size(const struct nf_conn *ct)
d26e6a028   Jiri Pirko   netfilter: ctnetl...
513
514
515
516
  {
  	if (!nf_ct_ext_exist(ct, NF_CT_EXT_ACCT))
  		return 0;
  	return 2 * nla_total_size(0) /* CTA_COUNTERS_ORIG|REPL */
b46f6ded9   Nicolas Dichtel   libnl: nla_put_be...
517
518
  	       + 2 * nla_total_size_64bit(sizeof(uint64_t)) /* CTA_COUNTERS_PACKETS */
  	       + 2 * nla_total_size_64bit(sizeof(uint64_t)) /* CTA_COUNTERS_BYTES */
d26e6a028   Jiri Pirko   netfilter: ctnetl...
519
520
  	       ;
  }
4a96300ce   Pablo Neira Ayuso   netfilter: ctnetl...
521
  static inline int ctnetlink_secctx_size(const struct nf_conn *ct)
1cc63249a   Eric Paris   conntrack: export...
522
  {
cba85b532   Pablo Neira Ayuso   netfilter: fix ex...
523
524
  #ifdef CONFIG_NF_CONNTRACK_SECMARK
  	int len, ret;
1cc63249a   Eric Paris   conntrack: export...
525

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

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

4a96300ce   Pablo Neira Ayuso   netfilter: ctnetl...
537
  static inline size_t ctnetlink_timestamp_size(const struct nf_conn *ct)
a992ca2a0   Pablo Neira Ayuso   netfilter: nf_con...
538
539
540
541
  {
  #ifdef CONFIG_NF_CONNTRACK_TIMESTAMP
  	if (!nf_ct_ext_exist(ct, NF_CT_EXT_TSTAMP))
  		return 0;
b46f6ded9   Nicolas Dichtel   libnl: nla_put_be...
542
  	return nla_total_size(0) + 2 * nla_total_size_64bit(sizeof(uint64_t));
a992ca2a0   Pablo Neira Ayuso   netfilter: nf_con...
543
544
545
546
  #else
  	return 0;
  #endif
  }
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
547
548
  #ifdef CONFIG_NF_CONNTRACK_EVENTS
  static size_t ctnetlink_nlmsg_size(const struct nf_conn *ct)
03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
549
550
551
552
553
554
555
556
  {
  	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 */
f7b13e433   Holger Eitzenberger   netfilter: introd...
557
  	       + ctnetlink_acct_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
4a001068d   Ken-ichirou MATSUZAWA   netfilter: ctnetl...
571
  #ifdef CONFIG_NF_CONNTRACK_ZONES
deedb5903   Daniel Borkmann   netfilter: nf_con...
572
  	       + nla_total_size(sizeof(u_int16_t)) /* CTA_ZONE|CTA_TUPLE_ZONE */
4a001068d   Ken-ichirou MATSUZAWA   netfilter: ctnetl...
573
  #endif
03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
574
  	       + ctnetlink_proto_size(ct)
0ceabd838   Florian Westphal   netfilter: ctnetl...
575
  	       + ctnetlink_label_size(ct)
03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
576
  	       ;
2732c4e45   Holger Eitzenberger   netfilter: ctnetl...
577
  }
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
578
579
  static int
  ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
580
  {
308ac9143   Daniel Borkmann   netfilter: nf_con...
581
  	const struct nf_conntrack_zone *zone;
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
582
  	struct net *net;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
583
584
  	struct nlmsghdr *nlh;
  	struct nfgenmsg *nfmsg;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
585
  	struct nlattr *nest_parms;
19abb7b09   Pablo Neira Ayuso   netfilter: ctnetl...
586
  	struct nf_conn *ct = item->ct;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
587
588
  	struct sk_buff *skb;
  	unsigned int type;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
589
  	unsigned int flags = 0, group;
dd7669a92   Pablo Neira Ayuso   netfilter: conntr...
590
  	int err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
591

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

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

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

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

96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
618
  	nfmsg = nlmsg_data(nlh);
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
619
  	nfmsg->nfgen_family = nf_ct_l3num(ct);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
620
621
  	nfmsg->version	= NFNETLINK_V0;
  	nfmsg->res_id	= 0;
deedb5903   Daniel Borkmann   netfilter: nf_con...
622
  	zone = nf_ct_zone(ct);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
623
624
625
  	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...
626
  	if (ctnetlink_dump_tuples(skb, nf_ct_tuple(ct, IP_CT_DIR_ORIGINAL)) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
627
  		goto nla_put_failure;
deedb5903   Daniel Borkmann   netfilter: nf_con...
628
629
630
  	if (ctnetlink_dump_zone_id(skb, CTA_TUPLE_ZONE, zone,
  				   NF_CT_ZONE_DIR_ORIG) < 0)
  		goto nla_put_failure;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
631
  	nla_nest_end(skb, nest_parms);
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
632

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
633
634
635
  	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...
636
  	if (ctnetlink_dump_tuples(skb, nf_ct_tuple(ct, IP_CT_DIR_REPLY)) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
637
  		goto nla_put_failure;
deedb5903   Daniel Borkmann   netfilter: nf_con...
638
639
640
  	if (ctnetlink_dump_zone_id(skb, CTA_TUPLE_ZONE, zone,
  				   NF_CT_ZONE_DIR_REPL) < 0)
  		goto nla_put_failure;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
641
  	nla_nest_end(skb, nest_parms);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
642

deedb5903   Daniel Borkmann   netfilter: nf_con...
643
644
  	if (ctnetlink_dump_zone_id(skb, CTA_ZONE, zone,
  				   NF_CT_DEFAULT_ZONE_DIR) < 0)
cc1eb4313   David S. Miller   nf_conntrack_netl...
645
  		goto nla_put_failure;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
646

1eedf6999   Eric Leblond   netfilter: ctnetl...
647
648
  	if (ctnetlink_dump_id(skb, ct) < 0)
  		goto nla_put_failure;
e57dce60c   Fabian Hugelshofer   netfilter: ctnetl...
649
650
  	if (ctnetlink_dump_status(skb, ct) < 0)
  		goto nla_put_failure;
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
651
  	if (events & (1 << IPCT_DESTROY)) {
4542fa472   Holger Eitzenberger   netfilter: ctnetl...
652
  		if (ctnetlink_dump_acct(skb, ct, type) < 0 ||
a992ca2a0   Pablo Neira Ayuso   netfilter: nf_con...
653
  		    ctnetlink_dump_timestamp(skb, ct) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
654
  			goto nla_put_failure;
7b621c1ea   Pablo Neira Ayuso   [NETFILTER]: ctne...
655
  	} else {
7b621c1ea   Pablo Neira Ayuso   [NETFILTER]: ctne...
656
  		if (ctnetlink_dump_timeout(skb, ct) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
657
  			goto nla_put_failure;
7b621c1ea   Pablo Neira Ayuso   [NETFILTER]: ctne...
658

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

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

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

a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
676
  		if (events & (1 << IPCT_RELATED) &&
0f417ce98   Pablo Neira Ayuso   [NETFILTER]: ctne...
677
678
  		    ctnetlink_dump_master(skb, ct) < 0)
  			goto nla_put_failure;
41d73ec05   Patrick McHardy   netfilter: nf_con...
679
680
  		if (events & (1 << IPCT_SEQADJ) &&
  		    ctnetlink_dump_ct_seq_adj(skb, ct) < 0)
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
681
  			goto nla_put_failure;
7b621c1ea   Pablo Neira Ayuso   [NETFILTER]: ctne...
682
  	}
b9a37e0c8   Pablo Neira Ayuso   [NETFILTER]: ctne...
683

a83099a60   Eric Leblond   [NETFILTER]: nf_c...
684
  #ifdef CONFIG_NF_CONNTRACK_MARK
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
685
  	if ((events & (1 << IPCT_MARK) || ct->mark)
a83099a60   Eric Leblond   [NETFILTER]: nf_c...
686
687
688
  	    && ctnetlink_dump_mark(skb, ct) < 0)
  		goto nla_put_failure;
  #endif
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:
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
697
  	nlmsg_cancel(skb, nlh);
528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
698
  nlmsg_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
699
  	kfree_skb(skb);
150ace0db   Pablo Neira Ayuso   netfilter: ctnetl...
700
  errout:
37b7ef720   Pablo Neira Ayuso   netfilter: ctnetl...
701
702
  	if (nfnetlink_set_err(net, 0, group, -ENOBUFS) > 0)
  		return -ENOBUFS;
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
703
  	return 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
704
705
706
707
708
  }
  #endif /* CONFIG_NF_CONNTRACK_EVENTS */
  
  static int ctnetlink_done(struct netlink_callback *cb)
  {
89f2e2188   Patrick McHardy   [NETFILTER]: ctne...
709
710
  	if (cb->args[1])
  		nf_ct_put((struct nf_conn *)cb->args[1]);
397304b52   Fabian Frederick   netfilter: ctnetl...
711
  	kfree(cb->data);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
712
713
  	return 0;
  }
866476f32   Kristian Evensen   netfilter: conntr...
714
  struct ctnetlink_filter {
0f298a285   Pablo Neira Ayuso   netfilter: ctnetl...
715
716
717
718
719
  	struct {
  		u_int32_t val;
  		u_int32_t mask;
  	} mark;
  };
866476f32   Kristian Evensen   netfilter: conntr...
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
  static struct ctnetlink_filter *
  ctnetlink_alloc_filter(const struct nlattr * const cda[])
  {
  #ifdef CONFIG_NF_CONNTRACK_MARK
  	struct ctnetlink_filter *filter;
  
  	filter = kzalloc(sizeof(*filter), GFP_KERNEL);
  	if (filter == NULL)
  		return ERR_PTR(-ENOMEM);
  
  	filter->mark.val = ntohl(nla_get_be32(cda[CTA_MARK]));
  	filter->mark.mask = ntohl(nla_get_be32(cda[CTA_MARK_MASK]));
  
  	return filter;
  #else
  	return ERR_PTR(-EOPNOTSUPP);
  #endif
  }
58de2cef2   Florian Westphal   netfilter: fix me...
738
739
740
741
742
743
744
745
746
747
748
749
750
751
  static int ctnetlink_start(struct netlink_callback *cb)
  {
  	const struct nlattr * const *cda = cb->data;
  	struct ctnetlink_filter *filter = NULL;
  
  	if (cda[CTA_MARK] && cda[CTA_MARK_MASK]) {
  		filter = ctnetlink_alloc_filter(cda);
  		if (IS_ERR(filter))
  			return PTR_ERR(filter);
  	}
  
  	cb->data = filter;
  	return 0;
  }
866476f32   Kristian Evensen   netfilter: conntr...
752
753
754
755
756
757
758
759
760
761
762
763
764
765
  static int ctnetlink_filter_match(struct nf_conn *ct, void *data)
  {
  	struct ctnetlink_filter *filter = data;
  
  	if (filter == NULL)
  		return 1;
  
  #ifdef CONFIG_NF_CONNTRACK_MARK
  	if ((ct->mark & filter->mark.mask) == filter->mark.val)
  		return 1;
  #endif
  
  	return 0;
  }
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
766
767
768
  static int
  ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
  {
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
769
  	struct net *net = sock_net(skb->sk);
89f2e2188   Patrick McHardy   [NETFILTER]: ctne...
770
  	struct nf_conn *ct, *last;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
771
  	struct nf_conntrack_tuple_hash *h;
ea781f197   Eric Dumazet   netfilter: nf_con...
772
  	struct hlist_nulls_node *n;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
773
  	struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
87711cb81   Pablo Neira Ayuso   [NETFILTER]: Filt...
774
  	u_int8_t l3proto = nfmsg->nfgen_family;
2344d64ec   Florian Westphal   netfilter: evict ...
775
776
  	struct nf_conn *nf_ct_evict[8];
  	int res, i;
93bb0ceb7   Jesper Dangaard Brouer   netfilter: conntr...
777
  	spinlock_t *lockp;
d205dc407   Patrick McHardy   [NETFILTER]: ctne...
778
  	last = (struct nf_conn *)cb->args[1];
2344d64ec   Florian Westphal   netfilter: evict ...
779
  	i = 0;
93bb0ceb7   Jesper Dangaard Brouer   netfilter: conntr...
780
781
  
  	local_bh_disable();
56d52d489   Florian Westphal   netfilter: conntr...
782
  	for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++) {
89f2e2188   Patrick McHardy   [NETFILTER]: ctne...
783
  restart:
2344d64ec   Florian Westphal   netfilter: evict ...
784
785
786
787
788
789
  		while (i) {
  			i--;
  			if (nf_ct_should_gc(nf_ct_evict[i]))
  				nf_ct_kill(nf_ct_evict[i]);
  			nf_ct_put(nf_ct_evict[i]);
  		}
93bb0ceb7   Jesper Dangaard Brouer   netfilter: conntr...
790
  		lockp = &nf_conntrack_locks[cb->args[0] % CONNTRACK_LOCKS];
b16c29191   Sasha Levin   netfilter: nf_con...
791
  		nf_conntrack_lock(lockp);
56d52d489   Florian Westphal   netfilter: conntr...
792
  		if (cb->args[0] >= nf_conntrack_htable_size) {
93bb0ceb7   Jesper Dangaard Brouer   netfilter: conntr...
793
794
795
  			spin_unlock(lockp);
  			goto out;
  		}
56d52d489   Florian Westphal   netfilter: conntr...
796
797
  		hlist_nulls_for_each_entry(h, n, &nf_conntrack_hash[cb->args[0]],
  					   hnnode) {
5b1158e90   Jozsef Kadlecsik   [NETFILTER]: Add ...
798
  			if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
799
800
  				continue;
  			ct = nf_ct_tuplehash_to_ctrack(h);
2344d64ec   Florian Westphal   netfilter: evict ...
801
802
803
804
805
806
  			if (nf_ct_is_expired(ct)) {
  				if (i < ARRAY_SIZE(nf_ct_evict) &&
  				    atomic_inc_not_zero(&ct->ct_general.use))
  					nf_ct_evict[i++] = ct;
  				continue;
  			}
e0c7d4722   Florian Westphal   netfilter: conntr...
807
808
  			if (!net_eq(net, nf_ct_net(ct)))
  				continue;
87711cb81   Pablo Neira Ayuso   [NETFILTER]: Filt...
809
810
811
  			/* 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...
812
  			if (l3proto && nf_ct_l3num(ct) != l3proto)
13ee6ac57   Stephen Hemminger   netfilter: fix ra...
813
  				continue;
d205dc407   Patrick McHardy   [NETFILTER]: ctne...
814
815
  			if (cb->args[1]) {
  				if (ct != last)
13ee6ac57   Stephen Hemminger   netfilter: fix ra...
816
  					continue;
d205dc407   Patrick McHardy   [NETFILTER]: ctne...
817
  				cb->args[1] = 0;
89f2e2188   Patrick McHardy   [NETFILTER]: ctne...
818
  			}
866476f32   Kristian Evensen   netfilter: conntr...
819
  			if (!ctnetlink_filter_match(ct, cb->data))
0f298a285   Pablo Neira Ayuso   netfilter: ctnetl...
820
  				continue;
866476f32   Kristian Evensen   netfilter: conntr...
821

3b988ece9   Hans Schillstrom   netfilter: ctnetl...
822
823
  			rcu_read_lock();
  			res =
15e473046   Eric W. Biederman   netlink: Rename p...
824
  			ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).portid,
3b988ece9   Hans Schillstrom   netfilter: ctnetl...
825
826
827
828
829
  					    cb->nlh->nlmsg_seq,
  					    NFNL_MSG_TYPE(cb->nlh->nlmsg_type),
  					    ct);
  			rcu_read_unlock();
  			if (res < 0) {
c71caf411   Pablo Neira Ayuso   netfilter: ctnetl...
830
  				nf_conntrack_get(&ct->ct_general);
89f2e2188   Patrick McHardy   [NETFILTER]: ctne...
831
  				cb->args[1] = (unsigned long)ct;
93bb0ceb7   Jesper Dangaard Brouer   netfilter: conntr...
832
  				spin_unlock(lockp);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
833
  				goto out;
89f2e2188   Patrick McHardy   [NETFILTER]: ctne...
834
835
  			}
  		}
93bb0ceb7   Jesper Dangaard Brouer   netfilter: conntr...
836
  		spin_unlock(lockp);
d205dc407   Patrick McHardy   [NETFILTER]: ctne...
837
  		if (cb->args[1]) {
89f2e2188   Patrick McHardy   [NETFILTER]: ctne...
838
839
  			cb->args[1] = 0;
  			goto restart;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
840
841
  		}
  	}
89f2e2188   Patrick McHardy   [NETFILTER]: ctne...
842
  out:
93bb0ceb7   Jesper Dangaard Brouer   netfilter: conntr...
843
  	local_bh_enable();
fefa92679   Liping Zhang   netfilter: ctnetl...
844
845
846
847
  	if (last) {
  		/* nf ct hash resize happened, now clear the leftover. */
  		if ((struct nf_conn *)cb->args[1] == last)
  			cb->args[1] = 0;
d205dc407   Patrick McHardy   [NETFILTER]: ctne...
848
  		nf_ct_put(last);
fefa92679   Liping Zhang   netfilter: ctnetl...
849
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
850

2344d64ec   Florian Westphal   netfilter: evict ...
851
852
853
854
855
856
  	while (i) {
  		i--;
  		if (nf_ct_should_gc(nf_ct_evict[i]))
  			nf_ct_kill(nf_ct_evict[i]);
  		nf_ct_put(nf_ct_evict[i]);
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
857
858
  	return skb->len;
  }
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
859
860
  static int ctnetlink_parse_tuple_ip(struct nlattr *attr,
  				    struct nf_conntrack_tuple *tuple)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
861
  {
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
862
  	struct nlattr *tb[CTA_IP_MAX+1];
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
863
864
  	struct nf_conntrack_l3proto *l3proto;
  	int ret = 0;
fceb6435e   Johannes Berg   netlink: pass ext...
865
  	ret = nla_parse_nested(tb, CTA_IP_MAX, attr, NULL, NULL);
130ffbc26   Daniel Borkmann   netfilter: check ...
866
867
  	if (ret < 0)
  		return ret;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
868

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

f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
872
873
  	if (likely(l3proto->nlattr_to_tuple)) {
  		ret = nla_validate_nested(attr, CTA_IP_MAX,
fceb6435e   Johannes Berg   netlink: pass ext...
874
  					  l3proto->nla_policy, NULL);
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
875
876
877
  		if (ret == 0)
  			ret = l3proto->nlattr_to_tuple(tb, tuple);
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
878

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

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
881
882
  	return ret;
  }
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
883
884
  static const struct nla_policy proto_nla_policy[CTA_PROTO_MAX+1] = {
  	[CTA_PROTO_NUM]	= { .type = NLA_U8 },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
885
  };
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
886
887
  static int ctnetlink_parse_tuple_proto(struct nlattr *attr,
  				       struct nf_conntrack_tuple *tuple)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
888
  {
b3480fe05   Florian Westphal   netfilter: conntr...
889
  	const struct nf_conntrack_l4proto *l4proto;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
890
  	struct nlattr *tb[CTA_PROTO_MAX+1];
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
891
  	int ret = 0;
fceb6435e   Johannes Berg   netlink: pass ext...
892
893
  	ret = nla_parse_nested(tb, CTA_PROTO_MAX, attr, proto_nla_policy,
  			       NULL);
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
894
895
  	if (ret < 0)
  		return ret;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
896

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

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

f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
904
905
  	if (likely(l4proto->nlattr_to_tuple)) {
  		ret = nla_validate_nested(attr, CTA_PROTO_MAX,
fceb6435e   Johannes Berg   netlink: pass ext...
906
  					  l4proto->nla_policy, NULL);
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
907
908
909
  		if (ret == 0)
  			ret = l4proto->nlattr_to_tuple(tb, tuple);
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
910

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

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
913
914
  	return ret;
  }
deedb5903   Daniel Borkmann   netfilter: nf_con...
915
916
917
918
  static int
  ctnetlink_parse_zone(const struct nlattr *attr,
  		     struct nf_conntrack_zone *zone)
  {
5e8018fc6   Daniel Borkmann   netfilter: nf_con...
919
920
  	nf_ct_zone_init(zone, NF_CT_DEFAULT_ZONE_ID,
  			NF_CT_DEFAULT_ZONE_DIR, 0);
deedb5903   Daniel Borkmann   netfilter: nf_con...
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
  #ifdef CONFIG_NF_CONNTRACK_ZONES
  	if (attr)
  		zone->id = ntohs(nla_get_be16(attr));
  #else
  	if (attr)
  		return -EOPNOTSUPP;
  #endif
  	return 0;
  }
  
  static int
  ctnetlink_parse_tuple_zone(struct nlattr *attr, enum ctattr_type type,
  			   struct nf_conntrack_zone *zone)
  {
  	int ret;
  
  	if (zone->id != NF_CT_DEFAULT_ZONE_ID)
  		return -EINVAL;
  
  	ret = ctnetlink_parse_zone(attr, zone);
  	if (ret < 0)
  		return ret;
  
  	if (type == CTA_TUPLE_REPLY)
  		zone->dir = NF_CT_ZONE_DIR_REPL;
  	else
  		zone->dir = NF_CT_ZONE_DIR_ORIG;
  
  	return 0;
  }
d0b0268fd   Patrick McHardy   netfilter: ctnetl...
951
952
953
  static const struct nla_policy tuple_nla_policy[CTA_TUPLE_MAX+1] = {
  	[CTA_TUPLE_IP]		= { .type = NLA_NESTED },
  	[CTA_TUPLE_PROTO]	= { .type = NLA_NESTED },
deedb5903   Daniel Borkmann   netfilter: nf_con...
954
  	[CTA_TUPLE_ZONE]	= { .type = NLA_U16 },
d0b0268fd   Patrick McHardy   netfilter: ctnetl...
955
  };
bb5cf80e9   Ilpo Järvinen   [NETFILTER]: Kill...
956
  static int
399383246   Patrick McHardy   netfilter: nfnetl...
957
  ctnetlink_parse_tuple(const struct nlattr * const cda[],
a2b7cbdd2   Matthias Kaehlcke   netfilter: ctnetl...
958
959
  		      struct nf_conntrack_tuple *tuple, u32 type,
  		      u_int8_t l3num, struct nf_conntrack_zone *zone)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
960
  {
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
961
  	struct nlattr *tb[CTA_TUPLE_MAX+1];
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
962
  	int err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
963
  	memset(tuple, 0, sizeof(*tuple));
fceb6435e   Johannes Berg   netlink: pass ext...
964
965
  	err = nla_parse_nested(tb, CTA_TUPLE_MAX, cda[type], tuple_nla_policy,
  			       NULL);
130ffbc26   Daniel Borkmann   netfilter: check ...
966
967
  	if (err < 0)
  		return err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
968

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
969
  	if (!tb[CTA_TUPLE_IP])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
970
971
972
  		return -EINVAL;
  
  	tuple->src.l3num = l3num;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
973
  	err = ctnetlink_parse_tuple_ip(tb[CTA_TUPLE_IP], tuple);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
974
975
  	if (err < 0)
  		return err;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
976
  	if (!tb[CTA_TUPLE_PROTO])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
977
  		return -EINVAL;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
978
  	err = ctnetlink_parse_tuple_proto(tb[CTA_TUPLE_PROTO], tuple);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
979
980
  	if (err < 0)
  		return err;
deedb5903   Daniel Borkmann   netfilter: nf_con...
981
982
983
984
985
986
987
988
989
  	if (tb[CTA_TUPLE_ZONE]) {
  		if (!zone)
  			return -EINVAL;
  
  		err = ctnetlink_parse_tuple_zone(tb[CTA_TUPLE_ZONE],
  						 type, zone);
  		if (err < 0)
  			return err;
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
990
991
992
993
994
  	/* 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 ...
995
996
  	return 0;
  }
d0b0268fd   Patrick McHardy   netfilter: ctnetl...
997
  static const struct nla_policy help_nla_policy[CTA_HELP_MAX+1] = {
6d1fafcae   Florian Westphal   netfilter: ctnetl...
998
999
  	[CTA_HELP_NAME]		= { .type = NLA_NUL_STRING,
  				    .len = NF_CT_HELPER_NAME_LEN - 1 },
d0b0268fd   Patrick McHardy   netfilter: ctnetl...
1000
  };
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
1001
1002
  static int ctnetlink_parse_help(const struct nlattr *attr, char **helper_name,
  				struct nlattr **helpinfo)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1003
  {
130ffbc26   Daniel Borkmann   netfilter: check ...
1004
  	int err;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1005
  	struct nlattr *tb[CTA_HELP_MAX+1];
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1006

fceb6435e   Johannes Berg   netlink: pass ext...
1007
  	err = nla_parse_nested(tb, CTA_HELP_MAX, attr, help_nla_policy, NULL);
130ffbc26   Daniel Borkmann   netfilter: check ...
1008
1009
  	if (err < 0)
  		return err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1010

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1011
  	if (!tb[CTA_HELP_NAME])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1012
  		return -EINVAL;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1013
  	*helper_name = nla_data(tb[CTA_HELP_NAME]);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1014

ae243bee3   Pablo Neira Ayuso   netfilter: ctnetl...
1015
1016
  	if (tb[CTA_HELP_INFO])
  		*helpinfo = tb[CTA_HELP_INFO];
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1017
1018
  	return 0;
  }
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
1019
  static const struct nla_policy ct_nla_policy[CTA_MAX+1] = {
d0b0268fd   Patrick McHardy   netfilter: ctnetl...
1020
1021
  	[CTA_TUPLE_ORIG]	= { .type = NLA_NESTED },
  	[CTA_TUPLE_REPLY]	= { .type = NLA_NESTED },
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
1022
  	[CTA_STATUS] 		= { .type = NLA_U32 },
d0b0268fd   Patrick McHardy   netfilter: ctnetl...
1023
1024
1025
  	[CTA_PROTOINFO]		= { .type = NLA_NESTED },
  	[CTA_HELP]		= { .type = NLA_NESTED },
  	[CTA_NAT_SRC]		= { .type = NLA_NESTED },
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
1026
1027
  	[CTA_TIMEOUT] 		= { .type = NLA_U32 },
  	[CTA_MARK]		= { .type = NLA_U32 },
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
1028
  	[CTA_ID]		= { .type = NLA_U32 },
d0b0268fd   Patrick McHardy   netfilter: ctnetl...
1029
1030
  	[CTA_NAT_DST]		= { .type = NLA_NESTED },
  	[CTA_TUPLE_MASTER]	= { .type = NLA_NESTED },
6d1fafcae   Florian Westphal   netfilter: ctnetl...
1031
1032
  	[CTA_NAT_SEQ_ADJ_ORIG]  = { .type = NLA_NESTED },
  	[CTA_NAT_SEQ_ADJ_REPLY] = { .type = NLA_NESTED },
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
1033
  	[CTA_ZONE]		= { .type = NLA_U16 },
0f298a285   Pablo Neira Ayuso   netfilter: ctnetl...
1034
  	[CTA_MARK_MASK]		= { .type = NLA_U32 },
9b21f6a90   Florian Westphal   netfilter: ctnetl...
1035
  	[CTA_LABELS]		= { .type = NLA_BINARY,
d2bf2f34c   Florian Westphal   netfilter: nft_ct...
1036
  				    .len = NF_CT_LABELS_MAX_SIZE },
9b21f6a90   Florian Westphal   netfilter: ctnetl...
1037
  	[CTA_LABELS_MASK]	= { .type = NLA_BINARY,
d2bf2f34c   Florian Westphal   netfilter: nft_ct...
1038
  				    .len = NF_CT_LABELS_MAX_SIZE },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1039
  };
866476f32   Kristian Evensen   netfilter: conntr...
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
  static int ctnetlink_flush_conntrack(struct net *net,
  				     const struct nlattr * const cda[],
  				     u32 portid, int report)
  {
  	struct ctnetlink_filter *filter = NULL;
  
  	if (cda[CTA_MARK] && cda[CTA_MARK_MASK]) {
  		filter = ctnetlink_alloc_filter(cda);
  		if (IS_ERR(filter))
  			return PTR_ERR(filter);
  	}
9fd6452d6   Florian Westphal   netfilter: conntr...
1051
1052
  	nf_ct_iterate_cleanup_net(net, ctnetlink_filter_match, filter,
  				  portid, report);
866476f32   Kristian Evensen   netfilter: conntr...
1053
1054
1055
1056
  	kfree(filter);
  
  	return 0;
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
1057
1058
1059
  static int ctnetlink_del_conntrack(struct net *net, struct sock *ctnl,
  				   struct sk_buff *skb,
  				   const struct nlmsghdr *nlh,
04ba724b6   Pablo Neira Ayuso   netfilter: nfnetl...
1060
1061
  				   const struct nlattr * const cda[],
  				   struct netlink_ext_ack *extack)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1062
1063
1064
1065
  {
  	struct nf_conntrack_tuple_hash *h;
  	struct nf_conntrack_tuple tuple;
  	struct nf_conn *ct;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
1066
  	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1067
  	u_int8_t u3 = nfmsg->nfgen_family;
308ac9143   Daniel Borkmann   netfilter: nf_con...
1068
  	struct nf_conntrack_zone zone;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
1069
1070
1071
1072
1073
  	int err;
  
  	err = ctnetlink_parse_zone(cda[CTA_ZONE], &zone);
  	if (err < 0)
  		return err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1074

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1075
  	if (cda[CTA_TUPLE_ORIG])
deedb5903   Daniel Borkmann   netfilter: nf_con...
1076
1077
  		err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG,
  					    u3, &zone);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1078
  	else if (cda[CTA_TUPLE_REPLY])
deedb5903   Daniel Borkmann   netfilter: nf_con...
1079
1080
  		err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY,
  					    u3, &zone);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1081
  	else {
866476f32   Kristian Evensen   netfilter: conntr...
1082
1083
1084
  		return ctnetlink_flush_conntrack(net, cda,
  						 NETLINK_CB(skb).portid,
  						 nlmsg_report(nlh));
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1085
1086
1087
1088
  	}
  
  	if (err < 0)
  		return err;
308ac9143   Daniel Borkmann   netfilter: nf_con...
1089
  	h = nf_conntrack_find_get(net, &zone, &tuple);
9ea8cfd6a   Pablo Neira Ayuso   [NETFILTER]: ctne...
1090
  	if (!h)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1091
  		return -ENOENT;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1092
1093
  
  	ct = nf_ct_tuplehash_to_ctrack(h);
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
1094

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1095
  	if (cda[CTA_ID]) {
77236b6e3   Patrick McHardy   [NETFILTER]: ctne...
1096
  		u_int32_t id = ntohl(nla_get_be32(cda[CTA_ID]));
7f85f9147   Patrick McHardy   [NETFILTER]: nf_c...
1097
  		if (id != (u32)(unsigned long)ct) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1098
1099
1100
  			nf_ct_put(ct);
  			return -ENOENT;
  		}
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
1101
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1102

f330a7fdb   Florian Westphal   netfilter: conntr...
1103
  	nf_ct_delete(ct, NETLINK_CB(skb).portid, nlmsg_report(nlh));
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1104
  	nf_ct_put(ct);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1105
1106
1107
  
  	return 0;
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
1108
1109
1110
  static int ctnetlink_get_conntrack(struct net *net, struct sock *ctnl,
  				   struct sk_buff *skb,
  				   const struct nlmsghdr *nlh,
04ba724b6   Pablo Neira Ayuso   netfilter: nfnetl...
1111
1112
  				   const struct nlattr * const cda[],
  				   struct netlink_ext_ack *extack)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1113
1114
1115
1116
1117
  {
  	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...
1118
  	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1119
  	u_int8_t u3 = nfmsg->nfgen_family;
308ac9143   Daniel Borkmann   netfilter: nf_con...
1120
  	struct nf_conntrack_zone zone;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
1121
  	int err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1122

80d326fab   Pablo Neira Ayuso   netlink: add netl...
1123
1124
  	if (nlh->nlmsg_flags & NLM_F_DUMP) {
  		struct netlink_dump_control c = {
58de2cef2   Florian Westphal   netfilter: fix me...
1125
  			.start = ctnetlink_start,
80d326fab   Pablo Neira Ayuso   netlink: add netl...
1126
1127
  			.dump = ctnetlink_dump_table,
  			.done = ctnetlink_done,
58de2cef2   Florian Westphal   netfilter: fix me...
1128
  			.data = (void *)cda,
80d326fab   Pablo Neira Ayuso   netlink: add netl...
1129
  		};
866476f32   Kristian Evensen   netfilter: conntr...
1130

80d326fab   Pablo Neira Ayuso   netlink: add netl...
1131
1132
  		return netlink_dump_start(ctnl, skb, nlh, &c);
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1133

ef00f89f1   Patrick McHardy   netfilter: ctnetl...
1134
1135
1136
  	err = ctnetlink_parse_zone(cda[CTA_ZONE], &zone);
  	if (err < 0)
  		return err;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1137
  	if (cda[CTA_TUPLE_ORIG])
deedb5903   Daniel Borkmann   netfilter: nf_con...
1138
1139
  		err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG,
  					    u3, &zone);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1140
  	else if (cda[CTA_TUPLE_REPLY])
deedb5903   Daniel Borkmann   netfilter: nf_con...
1141
1142
  		err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY,
  					    u3, &zone);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1143
1144
1145
1146
1147
  	else
  		return -EINVAL;
  
  	if (err < 0)
  		return err;
308ac9143   Daniel Borkmann   netfilter: nf_con...
1148
  	h = nf_conntrack_find_get(net, &zone, &tuple);
9ea8cfd6a   Pablo Neira Ayuso   [NETFILTER]: ctne...
1149
  	if (!h)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1150
  		return -ENOENT;
9ea8cfd6a   Pablo Neira Ayuso   [NETFILTER]: ctne...
1151

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1152
1153
1154
  	ct = nf_ct_tuplehash_to_ctrack(h);
  
  	err = -ENOMEM;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
1155
1156
  	skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
  	if (skb2 == NULL) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1157
1158
1159
  		nf_ct_put(ct);
  		return -ENOMEM;
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1160

528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
1161
  	rcu_read_lock();
15e473046   Eric W. Biederman   netlink: Rename p...
1162
  	err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).portid, nlh->nlmsg_seq,
80e60e67b   Pablo Neira Ayuso   netfilter: ctnetl...
1163
  				  NFNL_MSG_TYPE(nlh->nlmsg_type), ct);
528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
1164
  	rcu_read_unlock();
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1165
1166
1167
  	nf_ct_put(ct);
  	if (err <= 0)
  		goto free;
15e473046   Eric W. Biederman   netlink: Rename p...
1168
  	err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1169
1170
  	if (err < 0)
  		goto out;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1171
1172
1173
1174
1175
  	return 0;
  
  free:
  	kfree_skb(skb2);
  out:
f31e8d498   Pablo Neira Ayuso   netfilter: ctnetl...
1176
1177
  	/* this avoids a loop in nfnetlink. */
  	return err == -EAGAIN ? -ENOBUFS : err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1178
  }
d871befe3   Pablo Neira Ayuso   netfilter: ctnetl...
1179
1180
1181
1182
1183
1184
1185
1186
  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
b7779d06f   Jesper Dangaard Brouer   netfilter: conntr...
1187
  ctnetlink_dump_list(struct sk_buff *skb, struct netlink_callback *cb, bool dying)
d871befe3   Pablo Neira Ayuso   netfilter: ctnetl...
1188
  {
cd5f336f1   Florian Westphal   netfilter: ctnetl...
1189
  	struct nf_conn *ct, *last;
d871befe3   Pablo Neira Ayuso   netfilter: ctnetl...
1190
1191
1192
1193
1194
  	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;
b7779d06f   Jesper Dangaard Brouer   netfilter: conntr...
1195
1196
1197
  	int cpu;
  	struct hlist_nulls_head *list;
  	struct net *net = sock_net(skb->sk);
d871befe3   Pablo Neira Ayuso   netfilter: ctnetl...
1198
1199
1200
  
  	if (cb->args[2])
  		return 0;
cd5f336f1   Florian Westphal   netfilter: ctnetl...
1201
  	last = (struct nf_conn *)cb->args[1];
b7779d06f   Jesper Dangaard Brouer   netfilter: conntr...
1202
1203
1204
1205
  	for (cpu = cb->args[0]; cpu < nr_cpu_ids; cpu++) {
  		struct ct_pcpu *pcpu;
  
  		if (!cpu_possible(cpu))
d871befe3   Pablo Neira Ayuso   netfilter: ctnetl...
1206
  			continue;
b7779d06f   Jesper Dangaard Brouer   netfilter: conntr...
1207
1208
1209
  
  		pcpu = per_cpu_ptr(net->ct.pcpu_lists, cpu);
  		spin_lock_bh(&pcpu->lock);
b7779d06f   Jesper Dangaard Brouer   netfilter: conntr...
1210
1211
1212
1213
1214
  		list = dying ? &pcpu->dying : &pcpu->unconfirmed;
  restart:
  		hlist_nulls_for_each_entry(h, n, list, hnnode) {
  			ct = nf_ct_tuplehash_to_ctrack(h);
  			if (l3proto && nf_ct_l3num(ct) != l3proto)
d871befe3   Pablo Neira Ayuso   netfilter: ctnetl...
1215
  				continue;
b7779d06f   Jesper Dangaard Brouer   netfilter: conntr...
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
  			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) {
cd5f336f1   Florian Westphal   netfilter: ctnetl...
1228
1229
  				if (!atomic_inc_not_zero(&ct->ct_general.use))
  					continue;
266155b2d   Pablo Neira Ayuso   netfilter: ctnetl...
1230
  				cb->args[0] = cpu;
b7779d06f   Jesper Dangaard Brouer   netfilter: conntr...
1231
1232
1233
1234
  				cb->args[1] = (unsigned long)ct;
  				spin_unlock_bh(&pcpu->lock);
  				goto out;
  			}
d871befe3   Pablo Neira Ayuso   netfilter: ctnetl...
1235
  		}
b7779d06f   Jesper Dangaard Brouer   netfilter: conntr...
1236
1237
1238
  		if (cb->args[1]) {
  			cb->args[1] = 0;
  			goto restart;
266155b2d   Pablo Neira Ayuso   netfilter: ctnetl...
1239
  		}
b7779d06f   Jesper Dangaard Brouer   netfilter: conntr...
1240
  		spin_unlock_bh(&pcpu->lock);
d871befe3   Pablo Neira Ayuso   netfilter: ctnetl...
1241
  	}
266155b2d   Pablo Neira Ayuso   netfilter: ctnetl...
1242
  	cb->args[2] = 1;
d871befe3   Pablo Neira Ayuso   netfilter: ctnetl...
1243
  out:
d871befe3   Pablo Neira Ayuso   netfilter: ctnetl...
1244
1245
1246
1247
1248
1249
1250
1251
1252
  	if (last)
  		nf_ct_put(last);
  
  	return skb->len;
  }
  
  static int
  ctnetlink_dump_dying(struct sk_buff *skb, struct netlink_callback *cb)
  {
b7779d06f   Jesper Dangaard Brouer   netfilter: conntr...
1253
  	return ctnetlink_dump_list(skb, cb, true);
d871befe3   Pablo Neira Ayuso   netfilter: ctnetl...
1254
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
1255
1256
1257
  static int ctnetlink_get_ct_dying(struct net *net, struct sock *ctnl,
  				  struct sk_buff *skb,
  				  const struct nlmsghdr *nlh,
04ba724b6   Pablo Neira Ayuso   netfilter: nfnetl...
1258
1259
  				  const struct nlattr * const cda[],
  				  struct netlink_ext_ack *extack)
d871befe3   Pablo Neira Ayuso   netfilter: ctnetl...
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
  {
  	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)
  {
b7779d06f   Jesper Dangaard Brouer   netfilter: conntr...
1275
  	return ctnetlink_dump_list(skb, cb, false);
d871befe3   Pablo Neira Ayuso   netfilter: ctnetl...
1276
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
1277
1278
1279
  static int ctnetlink_get_ct_unconfirmed(struct net *net, struct sock *ctnl,
  					struct sk_buff *skb,
  					const struct nlmsghdr *nlh,
04ba724b6   Pablo Neira Ayuso   netfilter: nfnetl...
1280
1281
  					const struct nlattr * const cda[],
  					struct netlink_ext_ack *extack)
d871befe3   Pablo Neira Ayuso   netfilter: ctnetl...
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
  {
  	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...
1293
  #ifdef CONFIG_NF_NAT_NEEDED
bb5cf80e9   Ilpo Järvinen   [NETFILTER]: Kill...
1294
  static int
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1295
1296
  ctnetlink_parse_nat_setup(struct nf_conn *ct,
  			  enum nf_nat_manip_type manip,
399383246   Patrick McHardy   netfilter: nfnetl...
1297
  			  const struct nlattr *attr)
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1298
1299
  {
  	typeof(nfnetlink_parse_nat_setup_hook) parse_nat_setup;
c7232c997   Patrick McHardy   netfilter: add pr...
1300
  	int err;
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1301
1302
1303
  
  	parse_nat_setup = rcu_dereference(nfnetlink_parse_nat_setup_hook);
  	if (!parse_nat_setup) {
95a5afca4   Johannes Berg   net: Remove CONFI...
1304
  #ifdef CONFIG_MODULES
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1305
  		rcu_read_unlock();
c14b78e7d   Pablo Neira Ayuso   netfilter: nfnetl...
1306
  		nfnl_unlock(NFNL_SUBSYS_CTNETLINK);
c7232c997   Patrick McHardy   netfilter: add pr...
1307
  		if (request_module("nf-nat") < 0) {
c14b78e7d   Pablo Neira Ayuso   netfilter: nfnetl...
1308
  			nfnl_lock(NFNL_SUBSYS_CTNETLINK);
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1309
1310
1311
  			rcu_read_lock();
  			return -EOPNOTSUPP;
  		}
c14b78e7d   Pablo Neira Ayuso   netfilter: nfnetl...
1312
  		nfnl_lock(NFNL_SUBSYS_CTNETLINK);
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1313
1314
1315
1316
1317
1318
  		rcu_read_lock();
  		if (nfnetlink_parse_nat_setup_hook)
  			return -EAGAIN;
  #endif
  		return -EOPNOTSUPP;
  	}
c7232c997   Patrick McHardy   netfilter: add pr...
1319
1320
1321
1322
  	err = parse_nat_setup(ct, manip, attr);
  	if (err == -EAGAIN) {
  #ifdef CONFIG_MODULES
  		rcu_read_unlock();
c14b78e7d   Pablo Neira Ayuso   netfilter: nfnetl...
1323
  		nfnl_unlock(NFNL_SUBSYS_CTNETLINK);
c7232c997   Patrick McHardy   netfilter: add pr...
1324
  		if (request_module("nf-nat-%u", nf_ct_l3num(ct)) < 0) {
c14b78e7d   Pablo Neira Ayuso   netfilter: nfnetl...
1325
  			nfnl_lock(NFNL_SUBSYS_CTNETLINK);
c7232c997   Patrick McHardy   netfilter: add pr...
1326
1327
1328
  			rcu_read_lock();
  			return -EOPNOTSUPP;
  		}
c14b78e7d   Pablo Neira Ayuso   netfilter: nfnetl...
1329
  		nfnl_lock(NFNL_SUBSYS_CTNETLINK);
c7232c997   Patrick McHardy   netfilter: add pr...
1330
1331
1332
1333
1334
1335
  		rcu_read_lock();
  #else
  		err = -EOPNOTSUPP;
  #endif
  	}
  	return err;
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1336
  }
67671841d   Pablo Neira Ayuso   netfilter: fix co...
1337
  #endif
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1338

53b56da83   Liping Zhang   netfilter: ctnetl...
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
  static void
  __ctnetlink_change_status(struct nf_conn *ct, unsigned long on,
  			  unsigned long off)
  {
  	unsigned int bit;
  
  	/* Ignore these unchangable bits */
  	on &= ~IPS_UNCHANGEABLE_MASK;
  	off &= ~IPS_UNCHANGEABLE_MASK;
  
  	for (bit = 0; bit < __IPS_MAX_BIT; bit++) {
  		if (on & (1 << bit))
  			set_bit(bit, &ct->status);
  		else if (off & (1 << bit))
  			clear_bit(bit, &ct->status);
  	}
  }
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1356
  static int
399383246   Patrick McHardy   netfilter: nfnetl...
1357
  ctnetlink_change_status(struct nf_conn *ct, const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1358
1359
  {
  	unsigned long d;
77236b6e3   Patrick McHardy   [NETFILTER]: ctne...
1360
  	unsigned int status = ntohl(nla_get_be32(cda[CTA_STATUS]));
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1361
1362
1363
1364
  	d = ct->status ^ status;
  
  	if (d & (IPS_EXPECTED|IPS_CONFIRMED|IPS_DYING))
  		/* unchangeable */
0adf9d674   Pablo Neira Ayuso   netfilter: ctnetl...
1365
  		return -EBUSY;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
1366

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

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

53b56da83   Liping Zhang   netfilter: ctnetl...
1375
  	__ctnetlink_change_status(ct, status, 0);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1376
1377
  	return 0;
  }
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1378
  static int
0eba801b6   Pablo Neira Ayuso   netfilter: ctnetl...
1379
  ctnetlink_setup_nat(struct nf_conn *ct, const struct nlattr * const cda[])
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1380
1381
1382
  {
  #ifdef CONFIG_NF_NAT_NEEDED
  	int ret;
fe337ac28   Florian Westphal   netfilter: ctnetl...
1383
1384
  	if (!cda[CTA_NAT_DST] && !cda[CTA_NAT_SRC])
  		return 0;
0eba801b6   Pablo Neira Ayuso   netfilter: ctnetl...
1385
1386
1387
1388
1389
1390
1391
1392
  	ret = ctnetlink_parse_nat_setup(ct, NF_NAT_MANIP_DST,
  					cda[CTA_NAT_DST]);
  	if (ret < 0)
  		return ret;
  
  	ret = ctnetlink_parse_nat_setup(ct, NF_NAT_MANIP_SRC,
  					cda[CTA_NAT_SRC]);
  	return ret;
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1393
  #else
0eba801b6   Pablo Neira Ayuso   netfilter: ctnetl...
1394
1395
  	if (!cda[CTA_NAT_DST] && !cda[CTA_NAT_SRC])
  		return 0;
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1396
1397
1398
  	return -EOPNOTSUPP;
  #endif
  }
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1399

4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
1400
1401
  static int ctnetlink_change_helper(struct nf_conn *ct,
  				   const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1402
1403
  {
  	struct nf_conntrack_helper *helper;
dc808fe28   Harald Welte   [NETFILTER] nf_co...
1404
  	struct nf_conn_help *help = nfct_help(ct);
29fe1b481   Pablo Neira Ayuso   netfilter: ctnetl...
1405
  	char *helpname = NULL;
ae243bee3   Pablo Neira Ayuso   netfilter: ctnetl...
1406
  	struct nlattr *helpinfo = NULL;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1407
  	int err;
ae243bee3   Pablo Neira Ayuso   netfilter: ctnetl...
1408
  	err = ctnetlink_parse_help(cda[CTA_HELP], &helpname, &helpinfo);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1409
1410
  	if (err < 0)
  		return err;
f95d7a46b   Kevin Cernekee   netfilter: ctnetl...
1411
1412
1413
1414
1415
1416
  	/* don't change helper of sibling connections */
  	if (ct->master) {
  		/* If we try to change the helper to the same thing twice,
  		 * treat the second attempt as a no-op instead of returning
  		 * an error.
  		 */
3173d5b8c   Liping Zhang   netfilter: ctnetl...
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
  		err = -EBUSY;
  		if (help) {
  			rcu_read_lock();
  			helper = rcu_dereference(help->helper);
  			if (helper && !strcmp(helper->name, helpname))
  				err = 0;
  			rcu_read_unlock();
  		}
  
  		return err;
f95d7a46b   Kevin Cernekee   netfilter: ctnetl...
1427
  	}
df293bbb6   Yasuyuki Kozakai   [NETFILTER]: ctne...
1428
1429
  	if (!strcmp(helpname, "")) {
  		if (help && help->helper) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1430
1431
  			/* we had a helper before ... */
  			nf_ct_remove_expectations(ct);
a9b3cd7f3   Stephen Hemminger   rcu: convert uses...
1432
  			RCU_INIT_POINTER(help->helper, NULL);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1433
  		}
df293bbb6   Yasuyuki Kozakai   [NETFILTER]: ctne...
1434
1435
  
  		return 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1436
  	}
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
1437

88be4c09d   Liping Zhang   netfilter: ctnetl...
1438
  	rcu_read_lock();
794e68716   Patrick McHardy   netfilter: ctnetl...
1439
1440
  	helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct),
  					    nf_ct_protonum(ct));
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1441
  	if (helper == NULL) {
88be4c09d   Liping Zhang   netfilter: ctnetl...
1442
  		rcu_read_unlock();
0adf9d674   Pablo Neira Ayuso   netfilter: ctnetl...
1443
  		return -EOPNOTSUPP;
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1444
  	}
df293bbb6   Yasuyuki Kozakai   [NETFILTER]: ctne...
1445

ceceae1b1   Yasuyuki Kozakai   [NETFILTER]: nf_c...
1446
  	if (help) {
ae243bee3   Pablo Neira Ayuso   netfilter: ctnetl...
1447
1448
  		if (help->helper == helper) {
  			/* update private helper data if allowed. */
7be54ca47   Pablo Neira Ayuso   netfilter: nf_ct_...
1449
  			if (helper->from_nlattr)
ae243bee3   Pablo Neira Ayuso   netfilter: ctnetl...
1450
  				helper->from_nlattr(helpinfo, ct);
88be4c09d   Liping Zhang   netfilter: ctnetl...
1451
  			err = 0;
fd7462de4   Pablo Neira Ayuso   netfilter: ctnetl...
1452
  		} else
88be4c09d   Liping Zhang   netfilter: ctnetl...
1453
1454
1455
1456
  			err = -EBUSY;
  	} else {
  		/* we cannot set a helper for an existing conntrack */
  		err = -EOPNOTSUPP;
ceceae1b1   Yasuyuki Kozakai   [NETFILTER]: nf_c...
1457
  	}
df293bbb6   Yasuyuki Kozakai   [NETFILTER]: ctne...
1458

88be4c09d   Liping Zhang   netfilter: ctnetl...
1459
1460
  	rcu_read_unlock();
  	return err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1461
  }
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
1462
1463
  static int ctnetlink_change_timeout(struct nf_conn *ct,
  				    const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1464
  {
77236b6e3   Patrick McHardy   [NETFILTER]: ctne...
1465
  	u_int32_t timeout = ntohl(nla_get_be32(cda[CTA_TIMEOUT]));
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
1466

f330a7fdb   Florian Westphal   netfilter: conntr...
1467
  	ct->timeout = nfct_time_stamp + timeout * HZ;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1468

f330a7fdb   Florian Westphal   netfilter: conntr...
1469
1470
  	if (test_bit(IPS_DYING_BIT, &ct->status))
  		return -ETIME;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1471
1472
1473
  
  	return 0;
  }
d0b0268fd   Patrick McHardy   netfilter: ctnetl...
1474
1475
1476
1477
1478
  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 },
  };
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
1479
1480
  static int ctnetlink_change_protoinfo(struct nf_conn *ct,
  				      const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1481
  {
399383246   Patrick McHardy   netfilter: nfnetl...
1482
  	const struct nlattr *attr = cda[CTA_PROTOINFO];
b3480fe05   Florian Westphal   netfilter: conntr...
1483
  	const struct nf_conntrack_l4proto *l4proto;
399383246   Patrick McHardy   netfilter: nfnetl...
1484
  	struct nlattr *tb[CTA_PROTOINFO_MAX+1];
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1485
  	int err = 0;
fceb6435e   Johannes Berg   netlink: pass ext...
1486
1487
  	err = nla_parse_nested(tb, CTA_PROTOINFO_MAX, attr, protoinfo_policy,
  			       NULL);
130ffbc26   Daniel Borkmann   netfilter: check ...
1488
1489
  	if (err < 0)
  		return err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1490

cd91566e4   Florian Westphal   netfilter: ctnetl...
1491
1492
  	rcu_read_lock();
  	l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct));
fdf708322   Patrick McHardy   [NETFILTER]: nfne...
1493
1494
  	if (l4proto->from_nlattr)
  		err = l4proto->from_nlattr(tb, ct);
cd91566e4   Florian Westphal   netfilter: ctnetl...
1495
  	rcu_read_unlock();
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1496
1497
1498
  
  	return err;
  }
41d73ec05   Patrick McHardy   netfilter: nf_con...
1499
1500
1501
1502
  static const struct nla_policy seqadj_policy[CTA_SEQADJ_MAX+1] = {
  	[CTA_SEQADJ_CORRECTION_POS]	= { .type = NLA_U32 },
  	[CTA_SEQADJ_OFFSET_BEFORE]	= { .type = NLA_U32 },
  	[CTA_SEQADJ_OFFSET_AFTER]	= { .type = NLA_U32 },
d0b0268fd   Patrick McHardy   netfilter: ctnetl...
1503
  };
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
1504
1505
  static int change_seq_adj(struct nf_ct_seqadj *seq,
  			  const struct nlattr * const attr)
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1506
  {
130ffbc26   Daniel Borkmann   netfilter: check ...
1507
  	int err;
41d73ec05   Patrick McHardy   netfilter: nf_con...
1508
  	struct nlattr *cda[CTA_SEQADJ_MAX+1];
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1509

fceb6435e   Johannes Berg   netlink: pass ext...
1510
  	err = nla_parse_nested(cda, CTA_SEQADJ_MAX, attr, seqadj_policy, NULL);
130ffbc26   Daniel Borkmann   netfilter: check ...
1511
1512
  	if (err < 0)
  		return err;
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1513

41d73ec05   Patrick McHardy   netfilter: nf_con...
1514
  	if (!cda[CTA_SEQADJ_CORRECTION_POS])
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1515
  		return -EINVAL;
41d73ec05   Patrick McHardy   netfilter: nf_con...
1516
1517
  	seq->correction_pos =
  		ntohl(nla_get_be32(cda[CTA_SEQADJ_CORRECTION_POS]));
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1518

41d73ec05   Patrick McHardy   netfilter: nf_con...
1519
  	if (!cda[CTA_SEQADJ_OFFSET_BEFORE])
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1520
  		return -EINVAL;
41d73ec05   Patrick McHardy   netfilter: nf_con...
1521
1522
  	seq->offset_before =
  		ntohl(nla_get_be32(cda[CTA_SEQADJ_OFFSET_BEFORE]));
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1523

41d73ec05   Patrick McHardy   netfilter: nf_con...
1524
  	if (!cda[CTA_SEQADJ_OFFSET_AFTER])
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1525
  		return -EINVAL;
41d73ec05   Patrick McHardy   netfilter: nf_con...
1526
1527
  	seq->offset_after =
  		ntohl(nla_get_be32(cda[CTA_SEQADJ_OFFSET_AFTER]));
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1528
1529
1530
1531
1532
  
  	return 0;
  }
  
  static int
41d73ec05   Patrick McHardy   netfilter: nf_con...
1533
1534
  ctnetlink_change_seq_adj(struct nf_conn *ct,
  			 const struct nlattr * const cda[])
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1535
  {
41d73ec05   Patrick McHardy   netfilter: nf_con...
1536
  	struct nf_conn_seqadj *seqadj = nfct_seqadj(ct);
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1537
  	int ret = 0;
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1538

41d73ec05   Patrick McHardy   netfilter: nf_con...
1539
  	if (!seqadj)
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1540
  		return 0;
64f3967c7   Liping Zhang   netfilter: ctnetl...
1541
  	spin_lock_bh(&ct->lock);
41d73ec05   Patrick McHardy   netfilter: nf_con...
1542
1543
1544
  	if (cda[CTA_SEQ_ADJ_ORIG]) {
  		ret = change_seq_adj(&seqadj->seq[IP_CT_DIR_ORIGINAL],
  				     cda[CTA_SEQ_ADJ_ORIG]);
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1545
  		if (ret < 0)
64f3967c7   Liping Zhang   netfilter: ctnetl...
1546
  			goto err;
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1547

53b56da83   Liping Zhang   netfilter: ctnetl...
1548
  		set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1549
  	}
41d73ec05   Patrick McHardy   netfilter: nf_con...
1550
1551
1552
  	if (cda[CTA_SEQ_ADJ_REPLY]) {
  		ret = change_seq_adj(&seqadj->seq[IP_CT_DIR_REPLY],
  				     cda[CTA_SEQ_ADJ_REPLY]);
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1553
  		if (ret < 0)
64f3967c7   Liping Zhang   netfilter: ctnetl...
1554
  			goto err;
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1555

53b56da83   Liping Zhang   netfilter: ctnetl...
1556
  		set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1557
  	}
64f3967c7   Liping Zhang   netfilter: ctnetl...
1558
  	spin_unlock_bh(&ct->lock);
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1559
  	return 0;
64f3967c7   Liping Zhang   netfilter: ctnetl...
1560
1561
1562
  err:
  	spin_unlock_bh(&ct->lock);
  	return ret;
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1563
  }
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1564

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1565
  static int
9b21f6a90   Florian Westphal   netfilter: ctnetl...
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
  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...
1591
1592
  ctnetlink_change_conntrack(struct nf_conn *ct,
  			   const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1593
1594
  {
  	int err;
e098360f1   Pablo Neira Ayuso   netfilter: ctnetl...
1595
1596
1597
  	/* 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...
1598
  	if (cda[CTA_HELP]) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1599
1600
1601
1602
  		err = ctnetlink_change_helper(ct, cda);
  		if (err < 0)
  			return err;
  	}
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1603
  	if (cda[CTA_TIMEOUT]) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1604
1605
1606
1607
  		err = ctnetlink_change_timeout(ct, cda);
  		if (err < 0)
  			return err;
  	}
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1608
  	if (cda[CTA_STATUS]) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1609
1610
1611
1612
  		err = ctnetlink_change_status(ct, cda);
  		if (err < 0)
  			return err;
  	}
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1613
  	if (cda[CTA_PROTOINFO]) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1614
1615
1616
1617
  		err = ctnetlink_change_protoinfo(ct, cda);
  		if (err < 0)
  			return err;
  	}
bcd1e830a   Martin Josefsson   [NETFILTER]: fix ...
1618
  #if defined(CONFIG_NF_CONNTRACK_MARK)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1619
  	if (cda[CTA_MARK])
77236b6e3   Patrick McHardy   [NETFILTER]: ctne...
1620
  		ct->mark = ntohl(nla_get_be32(cda[CTA_MARK]));
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1621
  #endif
41d73ec05   Patrick McHardy   netfilter: nf_con...
1622
1623
  	if (cda[CTA_SEQ_ADJ_ORIG] || cda[CTA_SEQ_ADJ_REPLY]) {
  		err = ctnetlink_change_seq_adj(ct, cda);
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1624
1625
1626
  		if (err < 0)
  			return err;
  	}
41d73ec05   Patrick McHardy   netfilter: nf_con...
1627

9b21f6a90   Florian Westphal   netfilter: ctnetl...
1628
1629
1630
1631
1632
  	if (cda[CTA_LABELS]) {
  		err = ctnetlink_attach_labels(ct, cda);
  		if (err < 0)
  			return err;
  	}
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1633

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1634
1635
  	return 0;
  }
f0a3c0869   Pablo Neira Ayuso   netfilter: ctnetl...
1636
  static struct nf_conn *
308ac9143   Daniel Borkmann   netfilter: nf_con...
1637
1638
  ctnetlink_create_conntrack(struct net *net,
  			   const struct nf_conntrack_zone *zone,
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
1639
  			   const struct nlattr * const cda[],
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1640
  			   struct nf_conntrack_tuple *otuple,
5faa1f4cb   Pablo Neira Ayuso   [NETFILTER]: nf_c...
1641
  			   struct nf_conntrack_tuple *rtuple,
7ec474967   Pablo Neira Ayuso   netfilter: ctnetl...
1642
  			   u8 u3)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1643
1644
1645
  {
  	struct nf_conn *ct;
  	int err = -EINVAL;
ceceae1b1   Yasuyuki Kozakai   [NETFILTER]: nf_c...
1646
  	struct nf_conntrack_helper *helper;
315c34dae   Pablo Neira Ayuso   netfilter: ctnetl...
1647
  	struct nf_conn_tstamp *tstamp;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1648

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

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1653
  	if (!cda[CTA_TIMEOUT])
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1654
  		goto err1;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1655

f330a7fdb   Florian Westphal   netfilter: conntr...
1656
  	ct->timeout = nfct_time_stamp + ntohl(nla_get_be32(cda[CTA_TIMEOUT])) * HZ;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1657

1575e7ea0   Pablo Neira Ayuso   netfilter: ctnetl...
1658
  	rcu_read_lock();
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1659
   	if (cda[CTA_HELP]) {
29fe1b481   Pablo Neira Ayuso   netfilter: ctnetl...
1660
  		char *helpname = NULL;
ae243bee3   Pablo Neira Ayuso   netfilter: ctnetl...
1661
1662
1663
  		struct nlattr *helpinfo = NULL;
  
  		err = ctnetlink_parse_help(cda[CTA_HELP], &helpname, &helpinfo);
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1664
1665
   		if (err < 0)
  			goto err2;
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1666

794e68716   Patrick McHardy   netfilter: ctnetl...
1667
1668
  		helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct),
  						    nf_ct_protonum(ct));
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1669
1670
1671
1672
1673
  		if (helper == NULL) {
  			rcu_read_unlock();
  #ifdef CONFIG_MODULES
  			if (request_module("nfct-helper-%s", helpname) < 0) {
  				err = -EOPNOTSUPP;
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1674
  				goto err1;
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1675
1676
1677
  			}
  
  			rcu_read_lock();
794e68716   Patrick McHardy   netfilter: ctnetl...
1678
1679
1680
  			helper = __nf_conntrack_helper_find(helpname,
  							    nf_ct_l3num(ct),
  							    nf_ct_protonum(ct));
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1681
  			if (helper) {
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1682
  				err = -EAGAIN;
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1683
  				goto err2;
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1684
1685
1686
1687
  			}
  			rcu_read_unlock();
  #endif
  			err = -EOPNOTSUPP;
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1688
  			goto err1;
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1689
1690
  		} else {
  			struct nf_conn_help *help;
1afc56794   Pablo Neira Ayuso   netfilter: nf_ct_...
1691
  			help = nf_ct_helper_ext_add(ct, helper, GFP_ATOMIC);
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1692
  			if (help == NULL) {
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1693
  				err = -ENOMEM;
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1694
  				goto err2;
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1695
  			}
ae243bee3   Pablo Neira Ayuso   netfilter: ctnetl...
1696
  			/* set private helper data if allowed. */
7be54ca47   Pablo Neira Ayuso   netfilter: nf_ct_...
1697
  			if (helper->from_nlattr)
ae243bee3   Pablo Neira Ayuso   netfilter: ctnetl...
1698
  				helper->from_nlattr(helpinfo, ct);
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1699
1700
  
  			/* not in hash table yet so not strictly necessary */
a9b3cd7f3   Stephen Hemminger   rcu: convert uses...
1701
  			RCU_INIT_POINTER(help->helper, helper);
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1702
1703
1704
  		}
  	} else {
  		/* try an implicit helper assignation */
b2a15a604   Patrick McHardy   netfilter: nf_con...
1705
  		err = __nf_ct_try_assign_helper(ct, NULL, GFP_ATOMIC);
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1706
1707
  		if (err < 0)
  			goto err2;
1575e7ea0   Pablo Neira Ayuso   netfilter: ctnetl...
1708
  	}
0eba801b6   Pablo Neira Ayuso   netfilter: ctnetl...
1709
1710
1711
  	err = ctnetlink_setup_nat(ct, cda);
  	if (err < 0)
  		goto err2;
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1712

a88e22adf   Pablo Neira Ayuso   netfilter: ctnetl...
1713
  	nf_ct_acct_ext_add(ct, GFP_ATOMIC);
a992ca2a0   Pablo Neira Ayuso   netfilter: nf_con...
1714
  	nf_ct_tstamp_ext_add(ct, GFP_ATOMIC);
a88e22adf   Pablo Neira Ayuso   netfilter: ctnetl...
1715
  	nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC);
c539f0171   Florian Westphal   netfilter: add co...
1716
  	nf_ct_labels_ext_add(ct);
87e94dbc2   Eric Leblond   netfilter: synpro...
1717
1718
  	nfct_seqadj_ext_add(ct);
  	nfct_synproxy_ext_add(ct);
c539f0171   Florian Westphal   netfilter: add co...
1719

a88e22adf   Pablo Neira Ayuso   netfilter: ctnetl...
1720
1721
1722
1723
1724
  	/* 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...
1725
1726
  		if (err < 0)
  			goto err2;
bbb3357d1   Pablo Neira Ayuso   [NETFILTER]: ctne...
1727
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1728

41d73ec05   Patrick McHardy   netfilter: nf_con...
1729
1730
  	if (cda[CTA_SEQ_ADJ_ORIG] || cda[CTA_SEQ_ADJ_REPLY]) {
  		err = ctnetlink_change_seq_adj(ct, cda);
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1731
1732
  		if (err < 0)
  			goto err2;
c969aa7d2   Pablo Neira Ayuso   netfilter: ctnetl...
1733
  	}
c969aa7d2   Pablo Neira Ayuso   netfilter: ctnetl...
1734

e5fc9e7a6   Changli Gao   netfilter: nf_con...
1735
  	memset(&ct->proto, 0, sizeof(ct->proto));
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1736
  	if (cda[CTA_PROTOINFO]) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1737
  		err = ctnetlink_change_protoinfo(ct, cda);
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1738
1739
  		if (err < 0)
  			goto err2;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1740
  	}
bcd1e830a   Martin Josefsson   [NETFILTER]: fix ...
1741
  #if defined(CONFIG_NF_CONNTRACK_MARK)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1742
  	if (cda[CTA_MARK])
77236b6e3   Patrick McHardy   [NETFILTER]: ctne...
1743
  		ct->mark = ntohl(nla_get_be32(cda[CTA_MARK]));
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1744
  #endif
5faa1f4cb   Pablo Neira Ayuso   [NETFILTER]: nf_c...
1745
  	/* setup master conntrack: this is a confirmed expectation */
7ec474967   Pablo Neira Ayuso   netfilter: ctnetl...
1746
1747
1748
1749
  	if (cda[CTA_TUPLE_MASTER]) {
  		struct nf_conntrack_tuple master;
  		struct nf_conntrack_tuple_hash *master_h;
  		struct nf_conn *master_ct;
deedb5903   Daniel Borkmann   netfilter: nf_con...
1750
1751
  		err = ctnetlink_parse_tuple(cda, &master, CTA_TUPLE_MASTER,
  					    u3, NULL);
7ec474967   Pablo Neira Ayuso   netfilter: ctnetl...
1752
  		if (err < 0)
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1753
  			goto err2;
7ec474967   Pablo Neira Ayuso   netfilter: ctnetl...
1754

ef00f89f1   Patrick McHardy   netfilter: ctnetl...
1755
  		master_h = nf_conntrack_find_get(net, zone, &master);
7ec474967   Pablo Neira Ayuso   netfilter: ctnetl...
1756
1757
  		if (master_h == NULL) {
  			err = -ENOENT;
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1758
  			goto err2;
7ec474967   Pablo Neira Ayuso   netfilter: ctnetl...
1759
1760
  		}
  		master_ct = nf_ct_tuplehash_to_ctrack(master_h);
f2a89004d   Pablo Neira Ayuso   [NETFILTER]: ctne...
1761
  		__set_bit(IPS_EXPECTED_BIT, &ct->status);
5faa1f4cb   Pablo Neira Ayuso   [NETFILTER]: nf_c...
1762
  		ct->master = master_ct;
f2a89004d   Pablo Neira Ayuso   [NETFILTER]: ctne...
1763
  	}
315c34dae   Pablo Neira Ayuso   netfilter: ctnetl...
1764
1765
  	tstamp = nf_conn_tstamp_find(ct);
  	if (tstamp)
d2de875c6   Eric Dumazet   net: use ktime_ge...
1766
  		tstamp->start = ktime_get_real_ns();
5faa1f4cb   Pablo Neira Ayuso   [NETFILTER]: nf_c...
1767

7d367e066   Jozsef Kadlecsik   netfilter: ctnetl...
1768
1769
1770
  	err = nf_conntrack_hash_check_insert(ct);
  	if (err < 0)
  		goto err2;
58a3c9bb0   Patrick McHardy   [NETFILTER]: nf_c...
1771
  	rcu_read_unlock();
dafc741cf   Yasuyuki Kozakai   [NETFILTER]: nfct...
1772

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

0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1775
1776
1777
  err2:
  	rcu_read_unlock();
  err1:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1778
  	nf_conntrack_free(ct);
f0a3c0869   Pablo Neira Ayuso   netfilter: ctnetl...
1779
  	return ERR_PTR(err);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1780
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
1781
1782
1783
  static int ctnetlink_new_conntrack(struct net *net, struct sock *ctnl,
  				   struct sk_buff *skb,
  				   const struct nlmsghdr *nlh,
04ba724b6   Pablo Neira Ayuso   netfilter: nfnetl...
1784
1785
  				   const struct nlattr * const cda[],
  				   struct netlink_ext_ack *extack)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1786
1787
1788
  {
  	struct nf_conntrack_tuple otuple, rtuple;
  	struct nf_conntrack_tuple_hash *h = NULL;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
1789
  	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
7d367e066   Jozsef Kadlecsik   netfilter: ctnetl...
1790
  	struct nf_conn *ct;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1791
  	u_int8_t u3 = nfmsg->nfgen_family;
308ac9143   Daniel Borkmann   netfilter: nf_con...
1792
  	struct nf_conntrack_zone zone;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
1793
1794
1795
1796
1797
  	int err;
  
  	err = ctnetlink_parse_zone(cda[CTA_ZONE], &zone);
  	if (err < 0)
  		return err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1798

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1799
  	if (cda[CTA_TUPLE_ORIG]) {
deedb5903   Daniel Borkmann   netfilter: nf_con...
1800
1801
  		err = ctnetlink_parse_tuple(cda, &otuple, CTA_TUPLE_ORIG,
  					    u3, &zone);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1802
1803
1804
  		if (err < 0)
  			return err;
  	}
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1805
  	if (cda[CTA_TUPLE_REPLY]) {
deedb5903   Daniel Borkmann   netfilter: nf_con...
1806
1807
  		err = ctnetlink_parse_tuple(cda, &rtuple, CTA_TUPLE_REPLY,
  					    u3, &zone);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1808
1809
1810
  		if (err < 0)
  			return err;
  	}
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1811
  	if (cda[CTA_TUPLE_ORIG])
308ac9143   Daniel Borkmann   netfilter: nf_con...
1812
  		h = nf_conntrack_find_get(net, &zone, &otuple);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1813
  	else if (cda[CTA_TUPLE_REPLY])
308ac9143   Daniel Borkmann   netfilter: nf_con...
1814
  		h = nf_conntrack_find_get(net, &zone, &rtuple);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1815
1816
  
  	if (h == NULL) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1817
  		err = -ENOENT;
f0a3c0869   Pablo Neira Ayuso   netfilter: ctnetl...
1818
  		if (nlh->nlmsg_flags & NLM_F_CREATE) {
fecc1133b   Pablo Neira Ayuso   netfilter: ctnetl...
1819
  			enum ip_conntrack_events events;
5faa1f4cb   Pablo Neira Ayuso   [NETFILTER]: nf_c...
1820

442fad942   Florian Westphal   netfilter: ctnetl...
1821
1822
  			if (!cda[CTA_TUPLE_ORIG] || !cda[CTA_TUPLE_REPLY])
  				return -EINVAL;
aa0c2c68a   Liping Zhang   netfilter: ctnetl...
1823
1824
  			if (otuple.dst.protonum != rtuple.dst.protonum)
  				return -EINVAL;
442fad942   Florian Westphal   netfilter: ctnetl...
1825

308ac9143   Daniel Borkmann   netfilter: nf_con...
1826
  			ct = ctnetlink_create_conntrack(net, &zone, cda, &otuple,
f0a3c0869   Pablo Neira Ayuso   netfilter: ctnetl...
1827
  							&rtuple, u3);
7d367e066   Jozsef Kadlecsik   netfilter: ctnetl...
1828
1829
  			if (IS_ERR(ct))
  				return PTR_ERR(ct);
f0a3c0869   Pablo Neira Ayuso   netfilter: ctnetl...
1830
  			err = 0;
fecc1133b   Pablo Neira Ayuso   netfilter: ctnetl...
1831
  			if (test_bit(IPS_EXPECTED_BIT, &ct->status))
97aae0df1   Liping Zhang   netfilter: ctnetl...
1832
  				events = 1 << IPCT_RELATED;
fecc1133b   Pablo Neira Ayuso   netfilter: ctnetl...
1833
  			else
97aae0df1   Liping Zhang   netfilter: ctnetl...
1834
  				events = 1 << IPCT_NEW;
fecc1133b   Pablo Neira Ayuso   netfilter: ctnetl...
1835

9b21f6a90   Florian Westphal   netfilter: ctnetl...
1836
1837
1838
  			if (cda[CTA_LABELS] &&
  			    ctnetlink_attach_labels(ct, cda) == 0)
  				events |= (1 << IPCT_LABEL);
858b31330   Patrick McHardy   netfilter: nf_con...
1839
1840
  			nf_conntrack_eventmask_report((1 << IPCT_REPLY) |
  						      (1 << IPCT_ASSURED) |
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
1841
1842
  						      (1 << IPCT_HELPER) |
  						      (1 << IPCT_PROTOINFO) |
41d73ec05   Patrick McHardy   netfilter: nf_con...
1843
  						      (1 << IPCT_SEQADJ) |
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
1844
  						      (1 << IPCT_MARK) | events,
15e473046   Eric W. Biederman   netlink: Rename p...
1845
  						      ct, NETLINK_CB(skb).portid,
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
1846
  						      nlmsg_report(nlh));
f0a3c0869   Pablo Neira Ayuso   netfilter: ctnetl...
1847
  			nf_ct_put(ct);
7d367e066   Jozsef Kadlecsik   netfilter: ctnetl...
1848
  		}
5faa1f4cb   Pablo Neira Ayuso   [NETFILTER]: nf_c...
1849

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1850
1851
1852
  		return err;
  	}
  	/* implicit 'else' */
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1853
  	err = -EEXIST;
7d367e066   Jozsef Kadlecsik   netfilter: ctnetl...
1854
  	ct = nf_ct_tuplehash_to_ctrack(h);
ff4ca8273   Pablo Neira Ayuso   [NETFILTER]: ctne...
1855
  	if (!(nlh->nlmsg_flags & NLM_F_EXCL)) {
19abb7b09   Pablo Neira Ayuso   netfilter: ctnetl...
1856
1857
  		err = ctnetlink_change_conntrack(ct, cda);
  		if (err == 0) {
858b31330   Patrick McHardy   netfilter: nf_con...
1858
1859
  			nf_conntrack_eventmask_report((1 << IPCT_REPLY) |
  						      (1 << IPCT_ASSURED) |
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
1860
  						      (1 << IPCT_HELPER) |
797a7d66d   Florian Westphal   netfilter: ctnetl...
1861
  						      (1 << IPCT_LABEL) |
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
1862
  						      (1 << IPCT_PROTOINFO) |
41d73ec05   Patrick McHardy   netfilter: nf_con...
1863
  						      (1 << IPCT_SEQADJ) |
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
1864
  						      (1 << IPCT_MARK),
15e473046   Eric W. Biederman   netlink: Rename p...
1865
  						      ct, NETLINK_CB(skb).portid,
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
1866
  						      nlmsg_report(nlh));
7d367e066   Jozsef Kadlecsik   netfilter: ctnetl...
1867
  		}
ff4ca8273   Pablo Neira Ayuso   [NETFILTER]: ctne...
1868
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1869

7d367e066   Jozsef Kadlecsik   netfilter: ctnetl...
1870
  	nf_ct_put(ct);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1871
1872
  	return err;
  }
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1873
  static int
15e473046   Eric W. Biederman   netlink: Rename p...
1874
  ctnetlink_ct_stat_cpu_fill_info(struct sk_buff *skb, u32 portid, u32 seq,
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1875
1876
1877
1878
  				__u16 cpu, const struct ip_conntrack_stat *st)
  {
  	struct nlmsghdr *nlh;
  	struct nfgenmsg *nfmsg;
15e473046   Eric W. Biederman   netlink: Rename p...
1879
  	unsigned int flags = portid ? NLM_F_MULTI : 0, event;
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1880

dedb67c4b   Pablo Neira Ayuso   netfilter: Add nf...
1881
1882
  	event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK,
  			      IPCTNL_MSG_CT_GET_STATS_CPU);
15e473046   Eric W. Biederman   netlink: Rename p...
1883
  	nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1884
1885
1886
1887
1888
1889
1890
  	if (nlh == NULL)
  		goto nlmsg_failure;
  
  	nfmsg = nlmsg_data(nlh);
  	nfmsg->nfgen_family = AF_UNSPEC;
  	nfmsg->version      = NFNETLINK_V0;
  	nfmsg->res_id	    = htons(cpu);
8e8118f89   Florian Westphal   netfilter: conntr...
1891
  	if (nla_put_be32(skb, CTA_STATS_FOUND, htonl(st->found)) ||
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1892
1893
  	    nla_put_be32(skb, CTA_STATS_INVALID, htonl(st->invalid)) ||
  	    nla_put_be32(skb, CTA_STATS_IGNORE, htonl(st->ignore)) ||
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
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
  	    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...
1930
  						    NETLINK_CB(cb->skb).portid,
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1931
1932
1933
1934
1935
1936
1937
1938
  						    cb->nlh->nlmsg_seq,
  						    cpu, st) < 0)
  				break;
  	}
  	cb->args[0] = cpu;
  
  	return skb->len;
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
1939
1940
1941
  static int ctnetlink_stat_ct_cpu(struct net *net, struct sock *ctnl,
  				 struct sk_buff *skb,
  				 const struct nlmsghdr *nlh,
04ba724b6   Pablo Neira Ayuso   netfilter: nfnetl...
1942
1943
  				 const struct nlattr * const cda[],
  				 struct netlink_ext_ack *extack)
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
  {
  	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...
1956
  ctnetlink_stat_ct_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1957
1958
1959
1960
  			    struct net *net)
  {
  	struct nlmsghdr *nlh;
  	struct nfgenmsg *nfmsg;
15e473046   Eric W. Biederman   netlink: Rename p...
1961
  	unsigned int flags = portid ? NLM_F_MULTI : 0, event;
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1962
  	unsigned int nr_conntracks = atomic_read(&net->ct.count);
dedb67c4b   Pablo Neira Ayuso   netfilter: Add nf...
1963
  	event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET_STATS);
15e473046   Eric W. Biederman   netlink: Rename p...
1964
  	nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
  	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;
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
1984
1985
  static int ctnetlink_stat_ct(struct net *net, struct sock *ctnl,
  			     struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b6   Pablo Neira Ayuso   netfilter: nfnetl...
1986
1987
  			     const struct nlattr * const cda[],
  			     struct netlink_ext_ack *extack)
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1988
1989
1990
1991
1992
1993
1994
  {
  	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...
1995
  	err = ctnetlink_stat_ct_fill_info(skb2, NETLINK_CB(skb).portid,
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1996
1997
1998
1999
2000
  					  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...
2001
  	err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT);
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
  	if (err < 0)
  		goto out;
  
  	return 0;
  
  free:
  	kfree_skb(skb2);
  out:
  	/* this avoids a loop in nfnetlink. */
  	return err == -EAGAIN ? -ENOBUFS : err;
  }
bd0779370   Pablo Neira Ayuso   netfilter: nfnetl...
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
  static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = {
  	[CTA_EXPECT_MASTER]	= { .type = NLA_NESTED },
  	[CTA_EXPECT_TUPLE]	= { .type = NLA_NESTED },
  	[CTA_EXPECT_MASK]	= { .type = NLA_NESTED },
  	[CTA_EXPECT_TIMEOUT]	= { .type = NLA_U32 },
  	[CTA_EXPECT_ID]		= { .type = NLA_U32 },
  	[CTA_EXPECT_HELP_NAME]	= { .type = NLA_NUL_STRING,
  				    .len = NF_CT_HELPER_NAME_LEN - 1 },
  	[CTA_EXPECT_ZONE]	= { .type = NLA_U16 },
  	[CTA_EXPECT_FLAGS]	= { .type = NLA_U32 },
  	[CTA_EXPECT_CLASS]	= { .type = NLA_U32 },
  	[CTA_EXPECT_NAT]	= { .type = NLA_NESTED },
  	[CTA_EXPECT_FN]		= { .type = NLA_NUL_STRING },
  };
  
  static struct nf_conntrack_expect *
  ctnetlink_alloc_expect(const struct nlattr *const cda[], struct nf_conn *ct,
  		       struct nf_conntrack_helper *helper,
  		       struct nf_conntrack_tuple *tuple,
  		       struct nf_conntrack_tuple *mask);
83f3e94d3   Ken-ichirou MATSUZAWA   netfilter: Kconfi...
2033
  #ifdef CONFIG_NETFILTER_NETLINK_GLUE_CT
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2034
  static size_t
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2035
  ctnetlink_glue_build_size(const struct nf_conn *ct)
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
  {
  	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
4a001068d   Ken-ichirou MATSUZAWA   netfilter: ctnetl...
2055
  #ifdef CONFIG_NF_CONNTRACK_ZONES
deedb5903   Daniel Borkmann   netfilter: nf_con...
2056
  	       + nla_total_size(sizeof(u_int16_t)) /* CTA_ZONE|CTA_TUPLE_ZONE */
4a001068d   Ken-ichirou MATSUZAWA   netfilter: ctnetl...
2057
  #endif
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2058
2059
2060
  	       + ctnetlink_proto_size(ct)
  	       ;
  }
224a05975   Ken-ichirou MATSUZAWA   netfilter: ctnetl...
2061
  static struct nf_conn *ctnetlink_glue_get_ct(const struct sk_buff *skb,
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2062
  					     enum ip_conntrack_info *ctinfo)
b7bd1809e   Pablo Neira Ayuso   netfilter: nfnetl...
2063
  {
ab8bc7ed8   Florian Westphal   netfilter: remove...
2064
  	return nf_ct_get(skb, ctinfo);
b7bd1809e   Pablo Neira Ayuso   netfilter: nfnetl...
2065
  }
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2066
  static int __ctnetlink_glue_build(struct sk_buff *skb, struct nf_conn *ct)
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2067
  {
308ac9143   Daniel Borkmann   netfilter: nf_con...
2068
  	const struct nf_conntrack_zone *zone;
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2069
  	struct nlattr *nest_parms;
deedb5903   Daniel Borkmann   netfilter: nf_con...
2070
  	zone = nf_ct_zone(ct);
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2071
2072
2073
2074
2075
  	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;
deedb5903   Daniel Borkmann   netfilter: nf_con...
2076
2077
2078
  	if (ctnetlink_dump_zone_id(skb, CTA_TUPLE_ZONE, zone,
  				   NF_CT_ZONE_DIR_ORIG) < 0)
  		goto nla_put_failure;
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2079
2080
2081
2082
2083
2084
2085
  	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;
deedb5903   Daniel Borkmann   netfilter: nf_con...
2086
2087
2088
  	if (ctnetlink_dump_zone_id(skb, CTA_TUPLE_ZONE, zone,
  				   NF_CT_ZONE_DIR_REPL) < 0)
  		goto nla_put_failure;
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2089
  	nla_nest_end(skb, nest_parms);
deedb5903   Daniel Borkmann   netfilter: nf_con...
2090
2091
  	if (ctnetlink_dump_zone_id(skb, CTA_ZONE, zone,
  				   NF_CT_DEFAULT_ZONE_DIR) < 0)
308ac9143   Daniel Borkmann   netfilter: nf_con...
2092
  		goto nla_put_failure;
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
  
  	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) &&
41d73ec05   Patrick McHardy   netfilter: nf_con...
2117
  	    ctnetlink_dump_ct_seq_adj(skb, ct) < 0)
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2118
2119
2120
2121
2122
2123
  		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...
2124
2125
  	if (ctnetlink_dump_labels(skb, ct) < 0)
  		goto nla_put_failure;
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2126
2127
2128
  	return 0;
  
  nla_put_failure:
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2129
2130
2131
2132
  	return -ENOSPC;
  }
  
  static int
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2133
2134
2135
  ctnetlink_glue_build(struct sk_buff *skb, struct nf_conn *ct,
  		     enum ip_conntrack_info ctinfo,
  		     u_int16_t ct_attr, u_int16_t ct_info_attr)
b7bd1809e   Pablo Neira Ayuso   netfilter: nfnetl...
2136
2137
2138
2139
2140
2141
  {
  	struct nlattr *nest_parms;
  
  	nest_parms = nla_nest_start(skb, ct_attr | NLA_F_NESTED);
  	if (!nest_parms)
  		goto nla_put_failure;
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2142
  	if (__ctnetlink_glue_build(skb, ct) < 0)
b7bd1809e   Pablo Neira Ayuso   netfilter: nfnetl...
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
  		goto nla_put_failure;
  
  	nla_nest_end(skb, nest_parms);
  
  	if (nla_put_be32(skb, ct_info_attr, htonl(ctinfo)))
  		goto nla_put_failure;
  
  	return 0;
  
  nla_put_failure:
  	return -ENOSPC;
  }
  
  static int
a963d710f   Kevin Cernekee   netfilter: ctnetl...
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
  ctnetlink_update_status(struct nf_conn *ct, const struct nlattr * const cda[])
  {
  	unsigned int status = ntohl(nla_get_be32(cda[CTA_STATUS]));
  	unsigned long d = ct->status ^ status;
  
  	if (d & IPS_SEEN_REPLY && !(status & IPS_SEEN_REPLY))
  		/* SEEN_REPLY bit can only be set */
  		return -EBUSY;
  
  	if (d & IPS_ASSURED && !(status & IPS_ASSURED))
  		/* ASSURED bit can only be set */
  		return -EBUSY;
  
  	/* This check is less strict than ctnetlink_change_status()
  	 * because callers often flip IPS_EXPECTED bits when sending
  	 * an NFQA_CT attribute to the kernel.  So ignore the
53b56da83   Liping Zhang   netfilter: ctnetl...
2173
2174
  	 * unchangeable bits but do not error out. Also user programs
  	 * are allowed to clear the bits that they are allowed to change.
a963d710f   Kevin Cernekee   netfilter: ctnetl...
2175
  	 */
53b56da83   Liping Zhang   netfilter: ctnetl...
2176
  	__ctnetlink_change_status(ct, status, ~status);
a963d710f   Kevin Cernekee   netfilter: ctnetl...
2177
2178
2179
2180
  	return 0;
  }
  
  static int
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2181
  ctnetlink_glue_parse_ct(const struct nlattr *cda[], struct nf_conn *ct)
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2182
2183
2184
2185
2186
2187
2188
2189
2190
  {
  	int err;
  
  	if (cda[CTA_TIMEOUT]) {
  		err = ctnetlink_change_timeout(ct, cda);
  		if (err < 0)
  			return err;
  	}
  	if (cda[CTA_STATUS]) {
a963d710f   Kevin Cernekee   netfilter: ctnetl...
2191
  		err = ctnetlink_update_status(ct, cda);
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2192
2193
2194
2195
2196
2197
2198
2199
  		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...
2200
2201
2202
2203
2204
  	if (cda[CTA_LABELS]) {
  		err = ctnetlink_attach_labels(ct, cda);
  		if (err < 0)
  			return err;
  	}
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2205
  #if defined(CONFIG_NF_CONNTRACK_MARK)
534473c60   Florian Westphal   netfilter: ctnetl...
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
  	if (cda[CTA_MARK]) {
  		u32 mask = 0, mark, newmark;
  		if (cda[CTA_MARK_MASK])
  			mask = ~ntohl(nla_get_be32(cda[CTA_MARK_MASK]));
  
  		mark = ntohl(nla_get_be32(cda[CTA_MARK]));
  		newmark = (ct->mark & mask) ^ mark;
  		if (newmark != ct->mark)
  			ct->mark = newmark;
  	}
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2216
2217
2218
2219
2220
  #endif
  	return 0;
  }
  
  static int
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2221
  ctnetlink_glue_parse(const struct nlattr *attr, struct nf_conn *ct)
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2222
2223
  {
  	struct nlattr *cda[CTA_MAX+1];
68e035c95   Pablo Neira Ayuso   netfilter: ctnetl...
2224
  	int ret;
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2225

fceb6435e   Johannes Berg   netlink: pass ext...
2226
  	ret = nla_parse_nested(cda, CTA_MAX, attr, ct_nla_policy, NULL);
130ffbc26   Daniel Borkmann   netfilter: check ...
2227
2228
  	if (ret < 0)
  		return ret;
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2229

88be4c09d   Liping Zhang   netfilter: ctnetl...
2230
  	return ctnetlink_glue_parse_ct((const struct nlattr **)cda, ct);
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2231
  }
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2232
2233
2234
2235
  static int ctnetlink_glue_exp_parse(const struct nlattr * const *cda,
  				    const struct nf_conn *ct,
  				    struct nf_conntrack_tuple *tuple,
  				    struct nf_conntrack_tuple *mask)
bd0779370   Pablo Neira Ayuso   netfilter: nfnetl...
2236
2237
2238
2239
  {
  	int err;
  
  	err = ctnetlink_parse_tuple(cda, tuple, CTA_EXPECT_TUPLE,
deedb5903   Daniel Borkmann   netfilter: nf_con...
2240
  				    nf_ct_l3num(ct), NULL);
bd0779370   Pablo Neira Ayuso   netfilter: nfnetl...
2241
2242
2243
2244
  	if (err < 0)
  		return err;
  
  	return ctnetlink_parse_tuple(cda, mask, CTA_EXPECT_MASK,
deedb5903   Daniel Borkmann   netfilter: nf_con...
2245
  				     nf_ct_l3num(ct), NULL);
bd0779370   Pablo Neira Ayuso   netfilter: nfnetl...
2246
2247
2248
  }
  
  static int
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2249
2250
  ctnetlink_glue_attach_expect(const struct nlattr *attr, struct nf_conn *ct,
  			     u32 portid, u32 report)
bd0779370   Pablo Neira Ayuso   netfilter: nfnetl...
2251
2252
2253
  {
  	struct nlattr *cda[CTA_EXPECT_MAX+1];
  	struct nf_conntrack_tuple tuple, mask;
b7e092c05   Florian Westphal   netfilter: ctnetl...
2254
  	struct nf_conntrack_helper *helper = NULL;
bd0779370   Pablo Neira Ayuso   netfilter: nfnetl...
2255
2256
  	struct nf_conntrack_expect *exp;
  	int err;
fceb6435e   Johannes Berg   netlink: pass ext...
2257
2258
  	err = nla_parse_nested(cda, CTA_EXPECT_MAX, attr, exp_nla_policy,
  			       NULL);
bd0779370   Pablo Neira Ayuso   netfilter: nfnetl...
2259
2260
  	if (err < 0)
  		return err;
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2261
2262
  	err = ctnetlink_glue_exp_parse((const struct nlattr * const *)cda,
  				       ct, &tuple, &mask);
bd0779370   Pablo Neira Ayuso   netfilter: nfnetl...
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
  	if (err < 0)
  		return err;
  
  	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)
  			return -EOPNOTSUPP;
  	}
  
  	exp = ctnetlink_alloc_expect((const struct nlattr * const *)cda, ct,
  				     helper, &tuple, &mask);
  	if (IS_ERR(exp))
  		return PTR_ERR(exp);
  
  	err = nf_ct_expect_related_report(exp, portid, report);
b18bcb001   Liping Zhang   netfilter: nfnetl...
2281
2282
  	nf_ct_expect_put(exp);
  	return err;
bd0779370   Pablo Neira Ayuso   netfilter: nfnetl...
2283
  }
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2284
2285
  static void ctnetlink_glue_seqadj(struct sk_buff *skb, struct nf_conn *ct,
  				  enum ip_conntrack_info ctinfo, int diff)
b7bd1809e   Pablo Neira Ayuso   netfilter: nfnetl...
2286
2287
2288
2289
2290
2291
  {
  	if (!(ct->status & IPS_NAT_MASK))
  		return;
  
  	nf_ct_tcp_seqadj_set(skb, ct, ctinfo, diff);
  }
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2292
2293
2294
2295
2296
2297
2298
  static struct nfnl_ct_hook ctnetlink_glue_hook = {
  	.get_ct		= ctnetlink_glue_get_ct,
  	.build_size	= ctnetlink_glue_build_size,
  	.build		= ctnetlink_glue_build,
  	.parse		= ctnetlink_glue_parse,
  	.attach_expect	= ctnetlink_glue_attach_expect,
  	.seq_adjust	= ctnetlink_glue_seqadj,
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2299
  };
83f3e94d3   Ken-ichirou MATSUZAWA   netfilter: Kconfi...
2300
  #endif /* CONFIG_NETFILTER_NETLINK_GLUE_CT */
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2301

601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2302
2303
2304
  /***********************************************************************
   * EXPECT
   ***********************************************************************/
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2305

4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
2306
2307
  static int ctnetlink_exp_dump_tuple(struct sk_buff *skb,
  				    const struct nf_conntrack_tuple *tuple,
a2b7cbdd2   Matthias Kaehlcke   netfilter: ctnetl...
2308
  				    u32 type)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2309
  {
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2310
  	struct nlattr *nest_parms;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2311

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2312
2313
2314
  	nest_parms = nla_nest_start(skb, type | NLA_F_NESTED);
  	if (!nest_parms)
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2315
  	if (ctnetlink_dump_tuples(skb, tuple) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2316
2317
  		goto nla_put_failure;
  	nla_nest_end(skb, nest_parms);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2318
2319
  
  	return 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2320
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2321
  	return -1;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2322
  }
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2323

4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
2324
2325
2326
  static int ctnetlink_exp_dump_mask(struct sk_buff *skb,
  				   const struct nf_conntrack_tuple *tuple,
  				   const struct nf_conntrack_tuple_mask *mask)
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
2327
  {
b3480fe05   Florian Westphal   netfilter: conntr...
2328
2329
  	const struct nf_conntrack_l3proto *l3proto;
  	const struct nf_conntrack_l4proto *l4proto;
d4156e8cd   Patrick McHardy   [NETFILTER]: nf_c...
2330
  	struct nf_conntrack_tuple m;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2331
  	struct nlattr *nest_parms;
b3480fe05   Florian Westphal   netfilter: conntr...
2332
  	int ret;
d4156e8cd   Patrick McHardy   [NETFILTER]: nf_c...
2333
2334
  
  	memset(&m, 0xFF, sizeof(m));
d4156e8cd   Patrick McHardy   [NETFILTER]: nf_c...
2335
  	memcpy(&m.src.u3, &mask->src.u3, sizeof(m.src.u3));
e578756c3   Patrick McHardy   netfilter: ctnetl...
2336
2337
  	m.src.u.all = mask->src.u.all;
  	m.dst.protonum = tuple->dst.protonum;
d4156e8cd   Patrick McHardy   [NETFILTER]: nf_c...
2338

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2339
2340
2341
  	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...
2342

3b988ece9   Hans Schillstrom   netfilter: ctnetl...
2343
  	rcu_read_lock();
528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
2344
  	l3proto = __nf_ct_l3proto_find(tuple->src.l3num);
d4156e8cd   Patrick McHardy   [NETFILTER]: nf_c...
2345
  	ret = ctnetlink_dump_tuples_ip(skb, &m, l3proto);
3b988ece9   Hans Schillstrom   netfilter: ctnetl...
2346
2347
2348
  	if (ret >= 0) {
  		l4proto = __nf_ct_l4proto_find(tuple->src.l3num,
  					       tuple->dst.protonum);
d4156e8cd   Patrick McHardy   [NETFILTER]: nf_c...
2349
  	ret = ctnetlink_dump_tuples_proto(skb, &m, l4proto);
3b988ece9   Hans Schillstrom   netfilter: ctnetl...
2350
2351
  	}
  	rcu_read_unlock();
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
2352
  	if (unlikely(ret < 0))
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2353
  		goto nla_put_failure;
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
2354

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2355
  	nla_nest_end(skb, nest_parms);
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
2356
2357
  
  	return 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2358
  nla_put_failure:
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
2359
2360
  	return -1;
  }
c7232c997   Patrick McHardy   netfilter: add pr...
2361
  static const union nf_inet_addr any_addr;
bb5cf80e9   Ilpo Järvinen   [NETFILTER]: Kill...
2362
  static int
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2363
  ctnetlink_exp_dump_expect(struct sk_buff *skb,
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2364
  			  const struct nf_conntrack_expect *exp)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2365
2366
  {
  	struct nf_conn *master = exp->master;
c12163827   Xi Wang   netfilter: ctnetl...
2367
  	long timeout = ((long)exp->timeout.expires - (long)jiffies) / HZ;
bc01befdc   Pablo Neira Ayuso   netfilter: ctnetl...
2368
  	struct nf_conn_help *help;
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2369
2370
2371
2372
  #ifdef CONFIG_NF_NAT_NEEDED
  	struct nlattr *nest_parms;
  	struct nf_conntrack_tuple nat_tuple = {};
  #endif
544d5c7d9   Pablo Neira Ayuso   netfilter: ctnetl...
2373
  	struct nf_ct_helper_expectfn *expfn;
d978e5dae   Patrick McHardy   [NETFILTER]: ctne...
2374
2375
  	if (timeout < 0)
  		timeout = 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2376
2377
  
  	if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2378
  		goto nla_put_failure;
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
2379
  	if (ctnetlink_exp_dump_mask(skb, &exp->tuple, &exp->mask) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2380
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2381
2382
2383
  	if (ctnetlink_exp_dump_tuple(skb,
  				 &master->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
  				 CTA_EXPECT_MASTER) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2384
  		goto nla_put_failure;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2385

076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2386
  #ifdef CONFIG_NF_NAT_NEEDED
c7232c997   Patrick McHardy   netfilter: add pr...
2387
2388
  	if (!nf_inet_addr_cmp(&exp->saved_addr, &any_addr) ||
  	    exp->saved_proto.all) {
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2389
2390
2391
  		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...
2392
2393
  		if (nla_put_be32(skb, CTA_EXPECT_NAT_DIR, htonl(exp->dir)))
  			goto nla_put_failure;
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2394
2395
  
  		nat_tuple.src.l3num = nf_ct_l3num(master);
c7232c997   Patrick McHardy   netfilter: add pr...
2396
  		nat_tuple.src.u3 = exp->saved_addr;
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2397
2398
2399
2400
2401
2402
2403
2404
2405
  		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...
2406
2407
2408
2409
2410
  	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...
2411
2412
2413
2414
2415
  	help = nfct_help(master);
  	if (help) {
  		struct nf_conntrack_helper *helper;
  
  		helper = rcu_dereference(help->helper);
cc1eb4313   David S. Miller   nf_conntrack_netl...
2416
2417
2418
  		if (helper &&
  		    nla_put_string(skb, CTA_EXPECT_HELP_NAME, helper->name))
  			goto nla_put_failure;
bc01befdc   Pablo Neira Ayuso   netfilter: ctnetl...
2419
  	}
544d5c7d9   Pablo Neira Ayuso   netfilter: ctnetl...
2420
  	expfn = nf_ct_helper_expectfn_find_by_symbol(exp->expectfn);
cc1eb4313   David S. Miller   nf_conntrack_netl...
2421
2422
2423
  	if (expfn != NULL &&
  	    nla_put_string(skb, CTA_EXPECT_FN, expfn->name))
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2424
2425
  
  	return 0;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2426

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2427
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2428
2429
2430
2431
  	return -1;
  }
  
  static int
15e473046   Eric W. Biederman   netlink: Rename p...
2432
  ctnetlink_exp_fill_info(struct sk_buff *skb, u32 portid, u32 seq,
8b0a231d4   Pablo Neira Ayuso   netfilter: ctnetl...
2433
  			int event, const struct nf_conntrack_expect *exp)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2434
2435
2436
  {
  	struct nlmsghdr *nlh;
  	struct nfgenmsg *nfmsg;
15e473046   Eric W. Biederman   netlink: Rename p...
2437
  	unsigned int flags = portid ? NLM_F_MULTI : 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2438

dedb67c4b   Pablo Neira Ayuso   netfilter: Add nf...
2439
  	event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK_EXP, event);
15e473046   Eric W. Biederman   netlink: Rename p...
2440
  	nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2441
2442
  	if (nlh == NULL)
  		goto nlmsg_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2443

96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2444
  	nfmsg = nlmsg_data(nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2445
2446
2447
2448
2449
  	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...
2450
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2451

96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2452
  	nlmsg_end(skb, nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2453
2454
2455
  	return skb->len;
  
  nlmsg_failure:
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2456
  nla_put_failure:
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2457
  	nlmsg_cancel(skb, nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2458
2459
2460
2461
  	return -1;
  }
  
  #ifdef CONFIG_NF_CONNTRACK_EVENTS
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
2462
2463
  static int
  ctnetlink_expect_event(unsigned int events, struct nf_exp_event *item)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2464
  {
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
2465
2466
  	struct nf_conntrack_expect *exp = item->exp;
  	struct net *net = nf_ct_exp_net(exp);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2467
2468
  	struct nlmsghdr *nlh;
  	struct nfgenmsg *nfmsg;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2469
  	struct sk_buff *skb;
ebbf41df4   Pablo Neira Ayuso   netfilter: ctnetl...
2470
  	unsigned int type, group;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2471
  	int flags = 0;
ebbf41df4   Pablo Neira Ayuso   netfilter: ctnetl...
2472
2473
2474
2475
  	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 ...
2476
2477
  		type = IPCTNL_MSG_EXP_NEW;
  		flags = NLM_F_CREATE|NLM_F_EXCL;
ebbf41df4   Pablo Neira Ayuso   netfilter: ctnetl...
2478
  		group = NFNLGRP_CONNTRACK_EXP_NEW;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2479
  	} else
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
2480
  		return 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2481

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

96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2485
2486
  	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
  	if (skb == NULL)
150ace0db   Pablo Neira Ayuso   netfilter: ctnetl...
2487
  		goto errout;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2488

dedb67c4b   Pablo Neira Ayuso   netfilter: Add nf...
2489
  	type = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK_EXP, type);
15e473046   Eric W. Biederman   netlink: Rename p...
2490
  	nlh = nlmsg_put(skb, item->portid, 0, type, sizeof(*nfmsg), flags);
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2491
2492
  	if (nlh == NULL)
  		goto nlmsg_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2493

96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2494
  	nfmsg = nlmsg_data(nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2495
2496
2497
2498
2499
  	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...
2500
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2501

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

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2506
  nla_put_failure:
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2507
  	nlmsg_cancel(skb, nlh);
528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
2508
  nlmsg_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2509
  	kfree_skb(skb);
150ace0db   Pablo Neira Ayuso   netfilter: ctnetl...
2510
  errout:
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
2511
  	nfnetlink_set_err(net, 0, 0, -ENOBUFS);
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
2512
  	return 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2513
2514
  }
  #endif
cf6994c2b   Patrick McHardy   [NETFILTER]: nf_c...
2515
2516
  static int ctnetlink_exp_done(struct netlink_callback *cb)
  {
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2517
2518
  	if (cb->args[1])
  		nf_ct_expect_put((struct nf_conntrack_expect *)cb->args[1]);
cf6994c2b   Patrick McHardy   [NETFILTER]: nf_c...
2519
2520
  	return 0;
  }
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2521
2522
2523
2524
  
  static int
  ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
  {
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
2525
  	struct net *net = sock_net(skb->sk);
cf6994c2b   Patrick McHardy   [NETFILTER]: nf_c...
2526
  	struct nf_conntrack_expect *exp, *last;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2527
  	struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
87711cb81   Pablo Neira Ayuso   [NETFILTER]: Filt...
2528
  	u_int8_t l3proto = nfmsg->nfgen_family;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2529

7d0742da1   Patrick McHardy   [NETFILTER]: nf_c...
2530
  	rcu_read_lock();
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2531
2532
  	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...
2533
  restart:
7cddd967b   Liping Zhang   netfilter: nf_ct_...
2534
2535
  		hlist_for_each_entry_rcu(exp, &nf_ct_expect_hash[cb->args[0]],
  					 hnode) {
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2536
  			if (l3proto && exp->tuple.src.l3num != l3proto)
cf6994c2b   Patrick McHardy   [NETFILTER]: nf_c...
2537
  				continue;
03d7dc5cd   Florian Westphal   netfilter: conntr...
2538
2539
2540
  
  			if (!net_eq(nf_ct_net(exp->master), net))
  				continue;
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2541
2542
2543
2544
2545
  			if (cb->args[1]) {
  				if (exp != last)
  					continue;
  				cb->args[1] = 0;
  			}
8b0a231d4   Pablo Neira Ayuso   netfilter: ctnetl...
2546
  			if (ctnetlink_exp_fill_info(skb,
15e473046   Eric W. Biederman   netlink: Rename p...
2547
  						    NETLINK_CB(cb->skb).portid,
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2548
2549
  						    cb->nlh->nlmsg_seq,
  						    IPCTNL_MSG_EXP_NEW,
8b0a231d4   Pablo Neira Ayuso   netfilter: ctnetl...
2550
  						    exp) < 0) {
b54ab92b8   Reshetova, Elena   netfilter: refcou...
2551
  				if (!refcount_inc_not_zero(&exp->use))
7d0742da1   Patrick McHardy   [NETFILTER]: nf_c...
2552
  					continue;
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2553
2554
2555
  				cb->args[1] = (unsigned long)exp;
  				goto out;
  			}
cf6994c2b   Patrick McHardy   [NETFILTER]: nf_c...
2556
  		}
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2557
2558
2559
  		if (cb->args[1]) {
  			cb->args[1] = 0;
  			goto restart;
cf6994c2b   Patrick McHardy   [NETFILTER]: nf_c...
2560
2561
  		}
  	}
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2562
  out:
7d0742da1   Patrick McHardy   [NETFILTER]: nf_c...
2563
  	rcu_read_unlock();
cf6994c2b   Patrick McHardy   [NETFILTER]: nf_c...
2564
2565
  	if (last)
  		nf_ct_expect_put(last);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2566

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2567
2568
  	return skb->len;
  }
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
  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:
7cddd967b   Liping Zhang   netfilter: nf_ct_...
2584
  	hlist_for_each_entry_rcu(exp, &help->expectations, lnode) {
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
  		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) {
b54ab92b8   Reshetova, Elena   netfilter: refcou...
2596
  			if (!refcount_inc_not_zero(&exp->use))
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
  				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;
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
2614
2615
  static int ctnetlink_dump_exp_ct(struct net *net, struct sock *ctnl,
  				 struct sk_buff *skb,
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
2616
  				 const struct nlmsghdr *nlh,
04ba724b6   Pablo Neira Ayuso   netfilter: nfnetl...
2617
2618
  				 const struct nlattr * const cda[],
  				 struct netlink_ext_ack *extack)
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
2619
2620
  {
  	int err;
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
2621
2622
2623
2624
2625
  	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;
308ac9143   Daniel Borkmann   netfilter: nf_con...
2626
  	struct nf_conntrack_zone zone;
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
2627
2628
2629
2630
  	struct netlink_dump_control c = {
  		.dump = ctnetlink_exp_ct_dump_table,
  		.done = ctnetlink_exp_done,
  	};
deedb5903   Daniel Borkmann   netfilter: nf_con...
2631
2632
  	err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER,
  				    u3, NULL);
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
2633
2634
  	if (err < 0)
  		return err;
308ac9143   Daniel Borkmann   netfilter: nf_con...
2635
2636
2637
  	err = ctnetlink_parse_zone(cda[CTA_EXPECT_ZONE], &zone);
  	if (err < 0)
  		return err;
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
2638

308ac9143   Daniel Borkmann   netfilter: nf_con...
2639
  	h = nf_conntrack_find_get(net, &zone, &tuple);
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
2640
2641
2642
2643
  	if (!h)
  		return -ENOENT;
  
  	ct = nf_ct_tuplehash_to_ctrack(h);
207df8150   Liping Zhang   netfilter: ctnetl...
2644
2645
2646
2647
2648
  	/* No expectation linked to this connection tracking. */
  	if (!nfct_help(ct)) {
  		nf_ct_put(ct);
  		return 0;
  	}
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
2649
2650
2651
2652
2653
2654
2655
  	c.data = ct;
  
  	err = netlink_dump_start(ctnl, skb, nlh, &c);
  	nf_ct_put(ct);
  
  	return err;
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
2656
2657
  static int ctnetlink_get_expect(struct net *net, struct sock *ctnl,
  				struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b6   Pablo Neira Ayuso   netfilter: nfnetl...
2658
2659
  				const struct nlattr * const cda[],
  				struct netlink_ext_ack *extack)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2660
2661
2662
2663
  {
  	struct nf_conntrack_tuple tuple;
  	struct nf_conntrack_expect *exp;
  	struct sk_buff *skb2;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2664
  	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2665
  	u_int8_t u3 = nfmsg->nfgen_family;
308ac9143   Daniel Borkmann   netfilter: nf_con...
2666
  	struct nf_conntrack_zone zone;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
2667
  	int err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2668

b8f3ab429   David S. Miller   Revert "netlink: ...
2669
  	if (nlh->nlmsg_flags & NLM_F_DUMP) {
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
2670
  		if (cda[CTA_EXPECT_MASTER])
04ba724b6   Pablo Neira Ayuso   netfilter: nfnetl...
2671
2672
  			return ctnetlink_dump_exp_ct(net, ctnl, skb, nlh, cda,
  						     extack);
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
2673
2674
2675
2676
2677
2678
2679
  		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 ...
2680
  	}
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
2681
2682
2683
  	err = ctnetlink_parse_zone(cda[CTA_EXPECT_ZONE], &zone);
  	if (err < 0)
  		return err;
35dba1d7f   Pablo Neira Ayuso   netfilter: ctnetl...
2684
  	if (cda[CTA_EXPECT_TUPLE])
deedb5903   Daniel Borkmann   netfilter: nf_con...
2685
2686
  		err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE,
  					    u3, NULL);
35dba1d7f   Pablo Neira Ayuso   netfilter: ctnetl...
2687
  	else if (cda[CTA_EXPECT_MASTER])
deedb5903   Daniel Borkmann   netfilter: nf_con...
2688
2689
  		err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER,
  					    u3, NULL);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2690
2691
2692
2693
2694
  	else
  		return -EINVAL;
  
  	if (err < 0)
  		return err;
308ac9143   Daniel Borkmann   netfilter: nf_con...
2695
  	exp = nf_ct_expect_find_get(net, &zone, &tuple);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2696
2697
  	if (!exp)
  		return -ENOENT;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2698
  	if (cda[CTA_EXPECT_ID]) {
77236b6e3   Patrick McHardy   [NETFILTER]: ctne...
2699
  		__be32 id = nla_get_be32(cda[CTA_EXPECT_ID]);
358324024   Patrick McHardy   [NETFILTER]: nf_c...
2700
  		if (ntohl(id) != (u32)(unsigned long)exp) {
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
2701
  			nf_ct_expect_put(exp);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2702
2703
  			return -ENOENT;
  		}
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2704
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2705
2706
  
  	err = -ENOMEM;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2707
  	skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
81378f728   Pablo Neira Ayuso   netfilter: ctnetl...
2708
2709
  	if (skb2 == NULL) {
  		nf_ct_expect_put(exp);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2710
  		goto out;
81378f728   Pablo Neira Ayuso   netfilter: ctnetl...
2711
  	}
4e9b82693   Thomas Graf   [NETLINK]: Remove...
2712

528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
2713
  	rcu_read_lock();
15e473046   Eric W. Biederman   netlink: Rename p...
2714
  	err = ctnetlink_exp_fill_info(skb2, NETLINK_CB(skb).portid,
8b0a231d4   Pablo Neira Ayuso   netfilter: ctnetl...
2715
  				      nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW, exp);
528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
2716
  	rcu_read_unlock();
81378f728   Pablo Neira Ayuso   netfilter: ctnetl...
2717
  	nf_ct_expect_put(exp);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2718
2719
  	if (err <= 0)
  		goto free;
15e473046   Eric W. Biederman   netlink: Rename p...
2720
  	err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT);
81378f728   Pablo Neira Ayuso   netfilter: ctnetl...
2721
2722
  	if (err < 0)
  		goto out;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2723

81378f728   Pablo Neira Ayuso   netfilter: ctnetl...
2724
  	return 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2725
2726
2727
2728
  
  free:
  	kfree_skb(skb2);
  out:
81378f728   Pablo Neira Ayuso   netfilter: ctnetl...
2729
2730
  	/* this avoids a loop in nfnetlink. */
  	return err == -EAGAIN ? -ENOBUFS : err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2731
  }
ac7b84839   Florian Westphal   netfilter: expect...
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
  static bool expect_iter_name(struct nf_conntrack_expect *exp, void *data)
  {
  	const struct nf_conn_help *m_help;
  	const char *name = data;
  
  	m_help = nfct_help(exp->master);
  
  	return strcmp(m_help->helper->name, name) == 0;
  }
  
  static bool expect_iter_all(struct nf_conntrack_expect *exp, void *data)
  {
  	return true;
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
2746
2747
  static int ctnetlink_del_expect(struct net *net, struct sock *ctnl,
  				struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b6   Pablo Neira Ayuso   netfilter: nfnetl...
2748
2749
  				const struct nlattr * const cda[],
  				struct netlink_ext_ack *extack)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2750
  {
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2751
  	struct nf_conntrack_expect *exp;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2752
  	struct nf_conntrack_tuple tuple;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2753
  	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2754
  	u_int8_t u3 = nfmsg->nfgen_family;
308ac9143   Daniel Borkmann   netfilter: nf_con...
2755
  	struct nf_conntrack_zone zone;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2756
  	int err;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2757
  	if (cda[CTA_EXPECT_TUPLE]) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2758
  		/* delete a single expect by tuple */
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
2759
2760
2761
  		err = ctnetlink_parse_zone(cda[CTA_EXPECT_ZONE], &zone);
  		if (err < 0)
  			return err;
deedb5903   Daniel Borkmann   netfilter: nf_con...
2762
2763
  		err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE,
  					    u3, NULL);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2764
2765
2766
2767
  		if (err < 0)
  			return err;
  
  		/* bump usage count to 2 */
308ac9143   Daniel Borkmann   netfilter: nf_con...
2768
  		exp = nf_ct_expect_find_get(net, &zone, &tuple);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2769
2770
  		if (!exp)
  			return -ENOENT;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2771
  		if (cda[CTA_EXPECT_ID]) {
77236b6e3   Patrick McHardy   [NETFILTER]: ctne...
2772
  			__be32 id = nla_get_be32(cda[CTA_EXPECT_ID]);
358324024   Patrick McHardy   [NETFILTER]: nf_c...
2773
  			if (ntohl(id) != (u32)(unsigned long)exp) {
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
2774
  				nf_ct_expect_put(exp);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2775
2776
2777
2778
2779
  				return -ENOENT;
  			}
  		}
  
  		/* after list removal, usage count == 1 */
ca7433df3   Jesper Dangaard Brouer   netfilter: conntr...
2780
  		spin_lock_bh(&nf_conntrack_expect_lock);
ebbf41df4   Pablo Neira Ayuso   netfilter: ctnetl...
2781
  		if (del_timer(&exp->timeout)) {
15e473046   Eric W. Biederman   netlink: Rename p...
2782
  			nf_ct_unlink_expect_report(exp, NETLINK_CB(skb).portid,
ebbf41df4   Pablo Neira Ayuso   netfilter: ctnetl...
2783
2784
2785
  						   nlmsg_report(nlh));
  			nf_ct_expect_put(exp);
  		}
ca7433df3   Jesper Dangaard Brouer   netfilter: conntr...
2786
  		spin_unlock_bh(&nf_conntrack_expect_lock);
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2787
  		/* have to put what we 'get' above.
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2788
  		 * after this line usage count == 0 */
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
2789
  		nf_ct_expect_put(exp);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2790
2791
  	} else if (cda[CTA_EXPECT_HELP_NAME]) {
  		char *name = nla_data(cda[CTA_EXPECT_HELP_NAME]);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2792

ac7b84839   Florian Westphal   netfilter: expect...
2793
2794
2795
  		nf_ct_expect_iterate_net(net, expect_iter_name, name,
  					 NETLINK_CB(skb).portid,
  					 nlmsg_report(nlh));
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2796
2797
  	} else {
  		/* This basically means we have to flush everything*/
ac7b84839   Florian Westphal   netfilter: expect...
2798
2799
2800
  		nf_ct_expect_iterate_net(net, expect_iter_all, NULL,
  					 NETLINK_CB(skb).portid,
  					 nlmsg_report(nlh));
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2801
2802
2803
2804
2805
  	}
  
  	return 0;
  }
  static int
399383246   Patrick McHardy   netfilter: nfnetl...
2806
2807
  ctnetlink_change_expect(struct nf_conntrack_expect *x,
  			const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2808
  {
9768e1ace   Kelvie Wong   netfilter: nf_ct_...
2809
2810
2811
2812
2813
2814
2815
2816
2817
  	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 ...
2818
  }
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
  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;
fceb6435e   Johannes Berg   netlink: pass ext...
2833
2834
  	err = nla_parse_nested(tb, CTA_EXPECT_NAT_MAX, attr,
  			       exp_nat_nla_policy, NULL);
130ffbc26   Daniel Borkmann   netfilter: check ...
2835
2836
  	if (err < 0)
  		return err;
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2837
2838
2839
2840
2841
  
  	if (!tb[CTA_EXPECT_NAT_DIR] || !tb[CTA_EXPECT_NAT_TUPLE])
  		return -EINVAL;
  
  	err = ctnetlink_parse_tuple((const struct nlattr * const *)tb,
deedb5903   Daniel Borkmann   netfilter: nf_con...
2842
2843
  				    &nat_tuple, CTA_EXPECT_NAT_TUPLE,
  				    u3, NULL);
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2844
2845
  	if (err < 0)
  		return err;
c7232c997   Patrick McHardy   netfilter: add pr...
2846
  	exp->saved_addr = nat_tuple.src.u3;
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2847
2848
2849
2850
2851
2852
2853
2854
  	exp->saved_proto = nat_tuple.src.u;
  	exp->dir = ntohl(nla_get_be32(tb[CTA_EXPECT_NAT_DIR]));
  
  	return 0;
  #else
  	return -EOPNOTSUPP;
  #endif
  }
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2855
2856
2857
2858
2859
  static struct nf_conntrack_expect *
  ctnetlink_alloc_expect(const struct nlattr * const cda[], struct nf_conn *ct,
  		       struct nf_conntrack_helper *helper,
  		       struct nf_conntrack_tuple *tuple,
  		       struct nf_conntrack_tuple *mask)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2860
  {
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2861
  	u_int32_t class = 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2862
  	struct nf_conntrack_expect *exp;
dc808fe28   Harald Welte   [NETFILTER] nf_co...
2863
  	struct nf_conn_help *help;
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2864
  	int err;
660fdb2a0   Pablo Neira Ayuso   netfilter: ctnetl...
2865

2c62e0bc6   Gao Feng   netfilter: ctnetl...
2866
2867
2868
  	help = nfct_help(ct);
  	if (!help)
  		return ERR_PTR(-EOPNOTSUPP);
b8c5e52c1   Pablo Neira Ayuso   netfilter: ctnetl...
2869
2870
  	if (cda[CTA_EXPECT_CLASS] && helper) {
  		class = ntohl(nla_get_be32(cda[CTA_EXPECT_CLASS]));
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2871
2872
  		if (class > helper->expect_class_max)
  			return ERR_PTR(-EINVAL);
b8c5e52c1   Pablo Neira Ayuso   netfilter: ctnetl...
2873
  	}
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
2874
  	exp = nf_ct_expect_alloc(ct);
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2875
2876
  	if (!exp)
  		return ERR_PTR(-ENOMEM);
2c62e0bc6   Gao Feng   netfilter: ctnetl...
2877
2878
2879
  	if (cda[CTA_EXPECT_FLAGS]) {
  		exp->flags = ntohl(nla_get_be32(cda[CTA_EXPECT_FLAGS]));
  		exp->flags &= ~NF_CT_EXPECT_USERSPACE;
bc01befdc   Pablo Neira Ayuso   netfilter: ctnetl...
2880
  	} else {
2c62e0bc6   Gao Feng   netfilter: ctnetl...
2881
  		exp->flags = 0;
bc01befdc   Pablo Neira Ayuso   netfilter: ctnetl...
2882
  	}
544d5c7d9   Pablo Neira Ayuso   netfilter: ctnetl...
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
  	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 ...
2895

b8c5e52c1   Pablo Neira Ayuso   netfilter: ctnetl...
2896
  	exp->class = class;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2897
  	exp->master = ct;
660fdb2a0   Pablo Neira Ayuso   netfilter: ctnetl...
2898
  	exp->helper = helper;
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2899
2900
2901
  	exp->tuple = *tuple;
  	exp->mask.src.u3 = mask->src.u3;
  	exp->mask.src.u.all = mask->src.u.all;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2902

076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2903
2904
  	if (cda[CTA_EXPECT_NAT]) {
  		err = ctnetlink_parse_expect_nat(cda[CTA_EXPECT_NAT],
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2905
  						 exp, nf_ct_l3num(ct));
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2906
2907
2908
  		if (err < 0)
  			goto err_out;
  	}
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2909
  	return exp;
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2910
  err_out:
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
2911
  	nf_ct_expect_put(exp);
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2912
2913
2914
2915
  	return ERR_PTR(err);
  }
  
  static int
308ac9143   Daniel Borkmann   netfilter: nf_con...
2916
2917
  ctnetlink_create_expect(struct net *net,
  			const struct nf_conntrack_zone *zone,
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
  			const struct nlattr * const cda[],
  			u_int8_t u3, u32 portid, int report)
  {
  	struct nf_conntrack_tuple tuple, mask, master_tuple;
  	struct nf_conntrack_tuple_hash *h = NULL;
  	struct nf_conntrack_helper *helper = NULL;
  	struct nf_conntrack_expect *exp;
  	struct nf_conn *ct;
  	int err;
  
  	/* caller guarantees that those three CTA_EXPECT_* exist */
deedb5903   Daniel Borkmann   netfilter: nf_con...
2929
2930
  	err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE,
  				    u3, NULL);
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2931
2932
  	if (err < 0)
  		return err;
deedb5903   Daniel Borkmann   netfilter: nf_con...
2933
2934
  	err = ctnetlink_parse_tuple(cda, &mask, CTA_EXPECT_MASK,
  				    u3, NULL);
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2935
2936
  	if (err < 0)
  		return err;
deedb5903   Daniel Borkmann   netfilter: nf_con...
2937
2938
  	err = ctnetlink_parse_tuple(cda, &master_tuple, CTA_EXPECT_MASTER,
  				    u3, NULL);
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2939
2940
2941
2942
2943
2944
2945
2946
  	if (err < 0)
  		return err;
  
  	/* Look for master conntrack of this expectation */
  	h = nf_conntrack_find_get(net, zone, &master_tuple);
  	if (!h)
  		return -ENOENT;
  	ct = nf_ct_tuplehash_to_ctrack(h);
8b5995d06   Gao Feng   netfilter: helper...
2947
  	rcu_read_lock();
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2948
2949
2950
2951
2952
2953
  	if (cda[CTA_EXPECT_HELP_NAME]) {
  		const char *helpname = nla_data(cda[CTA_EXPECT_HELP_NAME]);
  
  		helper = __nf_conntrack_helper_find(helpname, u3,
  						    nf_ct_protonum(ct));
  		if (helper == NULL) {
8b5995d06   Gao Feng   netfilter: helper...
2954
  			rcu_read_unlock();
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2955
2956
2957
2958
2959
  #ifdef CONFIG_MODULES
  			if (request_module("nfct-helper-%s", helpname) < 0) {
  				err = -EOPNOTSUPP;
  				goto err_ct;
  			}
8b5995d06   Gao Feng   netfilter: helper...
2960
  			rcu_read_lock();
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2961
2962
2963
2964
  			helper = __nf_conntrack_helper_find(helpname, u3,
  							    nf_ct_protonum(ct));
  			if (helper) {
  				err = -EAGAIN;
8b5995d06   Gao Feng   netfilter: helper...
2965
  				goto err_rcu;
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2966
  			}
8b5995d06   Gao Feng   netfilter: helper...
2967
  			rcu_read_unlock();
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2968
2969
2970
2971
2972
2973
2974
2975
2976
  #endif
  			err = -EOPNOTSUPP;
  			goto err_ct;
  		}
  	}
  
  	exp = ctnetlink_alloc_expect(cda, ct, helper, &tuple, &mask);
  	if (IS_ERR(exp)) {
  		err = PTR_ERR(exp);
8b5995d06   Gao Feng   netfilter: helper...
2977
  		goto err_rcu;
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2978
2979
2980
  	}
  
  	err = nf_ct_expect_related_report(exp, portid, report);
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2981
  	nf_ct_expect_put(exp);
8b5995d06   Gao Feng   netfilter: helper...
2982
2983
  err_rcu:
  	rcu_read_unlock();
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2984
2985
  err_ct:
  	nf_ct_put(ct);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2986
2987
  	return err;
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
2988
2989
  static int ctnetlink_new_expect(struct net *net, struct sock *ctnl,
  				struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b6   Pablo Neira Ayuso   netfilter: nfnetl...
2990
2991
  				const struct nlattr * const cda[],
  				struct netlink_ext_ack *extack)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2992
2993
2994
  {
  	struct nf_conntrack_tuple tuple;
  	struct nf_conntrack_expect *exp;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2995
  	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2996
  	u_int8_t u3 = nfmsg->nfgen_family;
308ac9143   Daniel Borkmann   netfilter: nf_con...
2997
  	struct nf_conntrack_zone zone;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
2998
  	int err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2999

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
3000
3001
3002
  	if (!cda[CTA_EXPECT_TUPLE]
  	    || !cda[CTA_EXPECT_MASK]
  	    || !cda[CTA_EXPECT_MASTER])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3003
  		return -EINVAL;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
3004
3005
3006
  	err = ctnetlink_parse_zone(cda[CTA_EXPECT_ZONE], &zone);
  	if (err < 0)
  		return err;
deedb5903   Daniel Borkmann   netfilter: nf_con...
3007
3008
  	err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE,
  				    u3, NULL);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3009
3010
  	if (err < 0)
  		return err;
ca7433df3   Jesper Dangaard Brouer   netfilter: conntr...
3011
  	spin_lock_bh(&nf_conntrack_expect_lock);
308ac9143   Daniel Borkmann   netfilter: nf_con...
3012
  	exp = __nf_ct_expect_find(net, &zone, &tuple);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3013
  	if (!exp) {
ca7433df3   Jesper Dangaard Brouer   netfilter: conntr...
3014
  		spin_unlock_bh(&nf_conntrack_expect_lock);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3015
  		err = -ENOENT;
19abb7b09   Pablo Neira Ayuso   netfilter: ctnetl...
3016
  		if (nlh->nlmsg_flags & NLM_F_CREATE) {
308ac9143   Daniel Borkmann   netfilter: nf_con...
3017
  			err = ctnetlink_create_expect(net, &zone, cda, u3,
15e473046   Eric W. Biederman   netlink: Rename p...
3018
  						      NETLINK_CB(skb).portid,
19abb7b09   Pablo Neira Ayuso   netfilter: ctnetl...
3019
3020
  						      nlmsg_report(nlh));
  		}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3021
3022
3023
3024
3025
3026
  		return err;
  	}
  
  	err = -EEXIST;
  	if (!(nlh->nlmsg_flags & NLM_F_EXCL))
  		err = ctnetlink_change_expect(exp, cda);
ca7433df3   Jesper Dangaard Brouer   netfilter: conntr...
3027
  	spin_unlock_bh(&nf_conntrack_expect_lock);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3028

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3029
3030
  	return err;
  }
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
3031
  static int
15e473046   Eric W. Biederman   netlink: Rename p...
3032
  ctnetlink_exp_stat_fill_info(struct sk_buff *skb, u32 portid, u32 seq, int cpu,
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
3033
3034
3035
3036
  			     const struct ip_conntrack_stat *st)
  {
  	struct nlmsghdr *nlh;
  	struct nfgenmsg *nfmsg;
15e473046   Eric W. Biederman   netlink: Rename p...
3037
  	unsigned int flags = portid ? NLM_F_MULTI : 0, event;
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
3038

dedb67c4b   Pablo Neira Ayuso   netfilter: Add nf...
3039
3040
  	event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK,
  			      IPCTNL_MSG_EXP_GET_STATS_CPU);
15e473046   Eric W. Biederman   netlink: Rename p...
3041
  	nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
  	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...
3080
  		if (ctnetlink_exp_stat_fill_info(skb, NETLINK_CB(cb->skb).portid,
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
3081
3082
3083
3084
3085
3086
3087
3088
  						 cb->nlh->nlmsg_seq,
  						 cpu, st) < 0)
  			break;
  	}
  	cb->args[0] = cpu;
  
  	return skb->len;
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
3089
3090
3091
  static int ctnetlink_stat_exp_cpu(struct net *net, struct sock *ctnl,
  				  struct sk_buff *skb,
  				  const struct nlmsghdr *nlh,
04ba724b6   Pablo Neira Ayuso   netfilter: nfnetl...
3092
3093
  				  const struct nlattr * const cda[],
  				  struct netlink_ext_ack *extack)
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
  {
  	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 ...
3104
  #ifdef CONFIG_NF_CONNTRACK_EVENTS
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
3105
3106
  static struct nf_ct_event_notifier ctnl_notifier = {
  	.fcn = ctnetlink_conntrack_event,
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3107
  };
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
3108
3109
  static struct nf_exp_event_notifier ctnl_notifier_exp = {
  	.fcn = ctnetlink_expect_event,
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3110
3111
  };
  #endif
7c8d4cb41   Patrick McHardy   [NETFILTER]: nfne...
3112
  static const struct nfnl_callback ctnl_cb[IPCTNL_MSG_MAX] = {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3113
  	[IPCTNL_MSG_CT_NEW]		= { .call = ctnetlink_new_conntrack,
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
3114
3115
  					    .attr_count = CTA_MAX,
  					    .policy = ct_nla_policy },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3116
  	[IPCTNL_MSG_CT_GET] 		= { .call = ctnetlink_get_conntrack,
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
3117
3118
  					    .attr_count = CTA_MAX,
  					    .policy = ct_nla_policy },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3119
  	[IPCTNL_MSG_CT_DELETE]  	= { .call = ctnetlink_del_conntrack,
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
3120
3121
  					    .attr_count = CTA_MAX,
  					    .policy = ct_nla_policy },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3122
  	[IPCTNL_MSG_CT_GET_CTRZERO] 	= { .call = ctnetlink_get_conntrack,
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
3123
3124
  					    .attr_count = CTA_MAX,
  					    .policy = ct_nla_policy },
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
3125
3126
  	[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...
3127
3128
  	[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 ...
3129
  };
7c8d4cb41   Patrick McHardy   [NETFILTER]: nfne...
3130
  static const struct nfnl_callback ctnl_exp_cb[IPCTNL_MSG_EXP_MAX] = {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3131
  	[IPCTNL_MSG_EXP_GET]		= { .call = ctnetlink_get_expect,
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
3132
3133
  					    .attr_count = CTA_EXPECT_MAX,
  					    .policy = exp_nla_policy },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3134
  	[IPCTNL_MSG_EXP_NEW]		= { .call = ctnetlink_new_expect,
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
3135
3136
  					    .attr_count = CTA_EXPECT_MAX,
  					    .policy = exp_nla_policy },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3137
  	[IPCTNL_MSG_EXP_DELETE]		= { .call = ctnetlink_del_expect,
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
3138
3139
  					    .attr_count = CTA_EXPECT_MAX,
  					    .policy = exp_nla_policy },
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
3140
  	[IPCTNL_MSG_EXP_GET_STATS_CPU]	= { .call = ctnetlink_stat_exp_cpu },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3141
  };
7c8d4cb41   Patrick McHardy   [NETFILTER]: nfne...
3142
  static const struct nfnetlink_subsystem ctnl_subsys = {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3143
3144
3145
3146
3147
  	.name				= "conntrack",
  	.subsys_id			= NFNL_SUBSYS_CTNETLINK,
  	.cb_count			= IPCTNL_MSG_MAX,
  	.cb				= ctnl_cb,
  };
7c8d4cb41   Patrick McHardy   [NETFILTER]: nfne...
3148
  static const struct nfnetlink_subsystem ctnl_exp_subsys = {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3149
3150
3151
3152
3153
  	.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...
3154
  MODULE_ALIAS("ip_conntrack_netlink");
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3155
  MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK);
34f9a2e4d   Pablo Neira Ayuso   [NETFILTER]: ctne...
3156
  MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_EXP);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3157

70e9942f1   Pablo Neira Ayuso   netfilter: nf_con...
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
  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 ...
3207
3208
3209
  static int __init ctnetlink_init(void)
  {
  	int ret;
654d0fbdc   Stephen Hemminger   netfilter: cleanu...
3210
3211
  	pr_info("ctnetlink v%s: registering with nfnetlink.
  ", version);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3212
3213
  	ret = nfnetlink_subsys_register(&ctnl_subsys);
  	if (ret < 0) {
654d0fbdc   Stephen Hemminger   netfilter: cleanu...
3214
3215
  		pr_err("ctnetlink_init: cannot register with nfnetlink.
  ");
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3216
3217
3218
3219
3220
  		goto err_out;
  	}
  
  	ret = nfnetlink_subsys_register(&ctnl_exp_subsys);
  	if (ret < 0) {
654d0fbdc   Stephen Hemminger   netfilter: cleanu...
3221
3222
  		pr_err("ctnetlink_init: cannot register exp with nfnetlink.
  ");
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3223
3224
  		goto err_unreg_subsys;
  	}
ef6acf68c   Julia Lawall   netfilter: ctnetl...
3225
3226
  	ret = register_pernet_subsys(&ctnetlink_net_ops);
  	if (ret < 0) {
70e9942f1   Pablo Neira Ayuso   netfilter: nf_con...
3227
3228
  		pr_err("ctnetlink_init: cannot register pernet operations
  ");
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3229
3230
  		goto err_unreg_exp_subsys;
  	}
83f3e94d3   Ken-ichirou MATSUZAWA   netfilter: Kconfi...
3231
  #ifdef CONFIG_NETFILTER_NETLINK_GLUE_CT
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
3232
  	/* setup interaction between nf_queue and nf_conntrack_netlink. */
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
3233
  	RCU_INIT_POINTER(nfnl_ct_hook, &ctnetlink_glue_hook);
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
3234
  #endif
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3235
  	return 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3236
3237
  err_unreg_exp_subsys:
  	nfnetlink_subsys_unregister(&ctnl_exp_subsys);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3238
3239
3240
3241
3242
3243
3244
3245
  err_unreg_subsys:
  	nfnetlink_subsys_unregister(&ctnl_subsys);
  err_out:
  	return ret;
  }
  
  static void __exit ctnetlink_exit(void)
  {
654d0fbdc   Stephen Hemminger   netfilter: cleanu...
3246
3247
  	pr_info("ctnetlink: unregistering from nfnetlink.
  ");
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3248

70e9942f1   Pablo Neira Ayuso   netfilter: nf_con...
3249
  	unregister_pernet_subsys(&ctnetlink_net_ops);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3250
3251
  	nfnetlink_subsys_unregister(&ctnl_exp_subsys);
  	nfnetlink_subsys_unregister(&ctnl_subsys);
83f3e94d3   Ken-ichirou MATSUZAWA   netfilter: Kconfi...
3252
  #ifdef CONFIG_NETFILTER_NETLINK_GLUE_CT
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
3253
  	RCU_INIT_POINTER(nfnl_ct_hook, NULL);
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
3254
  #endif
3b7dabf02   Liping Zhang   netfilter: invoke...
3255
  	synchronize_rcu();
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3256
3257
3258
3259
  }
  
  module_init(ctnetlink_init);
  module_exit(ctnetlink_exit);