Blame view

net/netfilter/nf_conntrack_netlink.c 95.2 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>
3c7910763   Florian Westphal   netfilter: ctnetl...
32
  #include <linux/siphash.h>
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
33
34
  
  #include <linux/netfilter.h>
dc5fc579b   Arnaldo Carvalho de Melo   [NETLINK]: Use nl...
35
  #include <net/netlink.h>
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
36
  #include <net/sock.h>
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
37
38
  #include <net/netfilter/nf_conntrack.h>
  #include <net/netfilter/nf_conntrack_core.h>
77ab9cff0   Martin Josefsson   [NETFILTER]: nf_c...
39
  #include <net/netfilter/nf_conntrack_expect.h>
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
40
  #include <net/netfilter/nf_conntrack_helper.h>
41d73ec05   Patrick McHardy   netfilter: nf_con...
41
  #include <net/netfilter/nf_conntrack_seqadj.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
  #include <net/netfilter/nf_conntrack_synproxy.h>
4806e9757   Florian Westphal   netfilter: replac...
49
  #if IS_ENABLED(CONFIG_NF_NAT)
d2c5c103b   Florian Westphal   netfilter: nat: r...
50
  #include <net/netfilter/nf_nat.h>
8c88f87cb   Pablo Neira Ayuso   netfilter: nfnetl...
51
  #include <net/netfilter/nf_nat_helper.h>
5b1158e90   Jozsef Kadlecsik   [NETFILTER]: Add ...
52
  #endif
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
53
54
55
  
  #include <linux/netfilter/nfnetlink.h>
  #include <linux/netfilter/nfnetlink_conntrack.h>
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
56
  #include "nf_internals.h"
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
57
  MODULE_LICENSE("GPL");
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
58
  static int ctnetlink_dump_tuples_proto(struct sk_buff *skb,
2a04aabf5   Julia Lawall   netfilter: consti...
59
60
  				const struct nf_conntrack_tuple *tuple,
  				const struct nf_conntrack_l4proto *l4proto)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
61
  {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
62
  	int ret = 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
63
  	struct nlattr *nest_parms;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
64

ae0be8de9   Michal Kubecek   netlink: make nla...
65
  	nest_parms = nla_nest_start(skb, CTA_TUPLE_PROTO);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
66
67
  	if (!nest_parms)
  		goto nla_put_failure;
cc1eb4313   David S. Miller   nf_conntrack_netl...
68
69
  	if (nla_put_u8(skb, CTA_PROTO_NUM, tuple->dst.protonum))
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
70

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

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
74
  	nla_nest_end(skb, nest_parms);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
75
76
  
  	return ret;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
77
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
78
79
  	return -1;
  }
f957be9d3   Florian Westphal   netfilter: conntr...
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
  static int ipv4_tuple_to_nlattr(struct sk_buff *skb,
  				const struct nf_conntrack_tuple *tuple)
  {
  	if (nla_put_in_addr(skb, CTA_IP_V4_SRC, tuple->src.u3.ip) ||
  	    nla_put_in_addr(skb, CTA_IP_V4_DST, tuple->dst.u3.ip))
  		return -EMSGSIZE;
  	return 0;
  }
  
  static int ipv6_tuple_to_nlattr(struct sk_buff *skb,
  				const struct nf_conntrack_tuple *tuple)
  {
  	if (nla_put_in6_addr(skb, CTA_IP_V6_SRC, &tuple->src.u3.in6) ||
  	    nla_put_in6_addr(skb, CTA_IP_V6_DST, &tuple->dst.u3.in6))
  		return -EMSGSIZE;
  	return 0;
  }
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
97
  static int ctnetlink_dump_tuples_ip(struct sk_buff *skb,
f957be9d3   Florian Westphal   netfilter: conntr...
98
  				    const struct nf_conntrack_tuple *tuple)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
99
  {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
100
  	int ret = 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
101
  	struct nlattr *nest_parms;
ae0be8de9   Michal Kubecek   netlink: make nla...
102
  	nest_parms = nla_nest_start(skb, CTA_TUPLE_IP);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
103
104
  	if (!nest_parms)
  		goto nla_put_failure;
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
105

f957be9d3   Florian Westphal   netfilter: conntr...
106
107
108
109
110
111
112
113
  	switch (tuple->src.l3num) {
  	case NFPROTO_IPV4:
  		ret = ipv4_tuple_to_nlattr(skb, tuple);
  		break;
  	case NFPROTO_IPV6:
  		ret = ipv6_tuple_to_nlattr(skb, tuple);
  		break;
  	}
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
114

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

1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
117
  	return ret;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
118
  nla_put_failure:
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
119
120
  	return -1;
  }
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
121
122
  static int ctnetlink_dump_tuples(struct sk_buff *skb,
  				 const struct nf_conntrack_tuple *tuple)
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
123
  {
b3480fe05   Florian Westphal   netfilter: conntr...
124
  	const struct nf_conntrack_l4proto *l4proto;
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
125
  	int ret;
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
126

3b988ece9   Hans Schillstrom   netfilter: ctnetl...
127
  	rcu_read_lock();
f957be9d3   Florian Westphal   netfilter: conntr...
128
  	ret = ctnetlink_dump_tuples_ip(skb, tuple);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
129

3b988ece9   Hans Schillstrom   netfilter: ctnetl...
130
  	if (ret >= 0) {
4a60dc748   Florian Westphal   netfilter: conntr...
131
  		l4proto = nf_ct_l4proto_find(tuple->dst.protonum);
3b988ece9   Hans Schillstrom   netfilter: ctnetl...
132
133
134
  		ret = ctnetlink_dump_tuples_proto(skb, tuple, l4proto);
  	}
  	rcu_read_unlock();
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
135
  	return ret;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
136
  }
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
137
138
  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...
139
140
141
142
143
144
145
146
147
148
  {
  	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...
149
  static int ctnetlink_dump_status(struct sk_buff *skb, const struct nf_conn *ct)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
150
  {
cc1eb4313   David S. Miller   nf_conntrack_netl...
151
152
  	if (nla_put_be32(skb, CTA_STATUS, htonl(ct->status)))
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
153
  	return 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
154
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
155
156
  	return -1;
  }
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
157
  static int ctnetlink_dump_timeout(struct sk_buff *skb, const struct nf_conn *ct)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
158
  {
d0b35b93d   Florian Westphal   netfilter: use_nf...
159
  	long timeout = nf_ct_expires(ct) / HZ;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
160

cc1eb4313   David S. Miller   nf_conntrack_netl...
161
162
  	if (nla_put_be32(skb, CTA_TIMEOUT, htonl(timeout)))
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
163
  	return 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
164
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
165
166
  	return -1;
  }
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
167
  static int ctnetlink_dump_protoinfo(struct sk_buff *skb, struct nf_conn *ct)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
168
  {
b3480fe05   Florian Westphal   netfilter: conntr...
169
  	const struct nf_conntrack_l4proto *l4proto;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
170
  	struct nlattr *nest_proto;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
171
  	int ret;
4a60dc748   Florian Westphal   netfilter: conntr...
172
  	l4proto = nf_ct_l4proto_find(nf_ct_protonum(ct));
528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
173
  	if (!l4proto->to_nlattr)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
174
  		return 0;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
175

ae0be8de9   Michal Kubecek   netlink: make nla...
176
  	nest_proto = nla_nest_start(skb, CTA_PROTOINFO);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
177
178
  	if (!nest_proto)
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
179

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

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
182
  	nla_nest_end(skb, nest_proto);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
183
184
  
  	return ret;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
185
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
186
187
  	return -1;
  }
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
188
189
  static int ctnetlink_dump_helpinfo(struct sk_buff *skb,
  				   const struct nf_conn *ct)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
190
  {
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
191
  	struct nlattr *nest_helper;
dc808fe28   Harald Welte   [NETFILTER] nf_co...
192
  	const struct nf_conn_help *help = nfct_help(ct);
3c158f7f5   Patrick McHarrdy   [NETFILTER]: nf_c...
193
  	struct nf_conntrack_helper *helper;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
194

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

3c158f7f5   Patrick McHarrdy   [NETFILTER]: nf_c...
198
199
200
  	helper = rcu_dereference(help->helper);
  	if (!helper)
  		goto out;
ae0be8de9   Michal Kubecek   netlink: make nla...
201
  	nest_helper = nla_nest_start(skb, CTA_HELP);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
202
203
  	if (!nest_helper)
  		goto nla_put_failure;
cc1eb4313   David S. Miller   nf_conntrack_netl...
204
205
  	if (nla_put_string(skb, CTA_HELP_NAME, helper->name))
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
206

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

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
210
  	nla_nest_end(skb, nest_helper);
3c158f7f5   Patrick McHarrdy   [NETFILTER]: nf_c...
211
  out:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
212
  	return 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
213
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
214
215
  	return -1;
  }
bb5cf80e9   Ilpo Järvinen   [NETFILTER]: Kill...
216
  static int
4542fa472   Holger Eitzenberger   netfilter: ctnetl...
217
218
  dump_counters(struct sk_buff *skb, struct nf_conn_acct *acct,
  	      enum ip_conntrack_dir dir, int type)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
219
  {
4542fa472   Holger Eitzenberger   netfilter: ctnetl...
220
221
  	enum ctattr_type attr = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG;
  	struct nf_conn_counter *counter = acct->counter;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
222
  	struct nlattr *nest_count;
4542fa472   Holger Eitzenberger   netfilter: ctnetl...
223
  	u64 pkts, bytes;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
224

4542fa472   Holger Eitzenberger   netfilter: ctnetl...
225
226
227
228
229
230
231
  	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);
  	}
ae0be8de9   Michal Kubecek   netlink: make nla...
232
  	nest_count = nla_nest_start(skb, attr);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
233
234
  	if (!nest_count)
  		goto nla_put_failure;
b46f6ded9   Nicolas Dichtel   libnl: nla_put_be...
235
236
237
238
  	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...
239
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
240

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
241
  	nla_nest_end(skb, nest_count);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
242
243
  
  	return 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
244
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
245
246
  	return -1;
  }
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
247

a992ca2a0   Pablo Neira Ayuso   netfilter: nf_con...
248
  static int
4542fa472   Holger Eitzenberger   netfilter: ctnetl...
249
  ctnetlink_dump_acct(struct sk_buff *skb, const struct nf_conn *ct, int type)
80e60e67b   Pablo Neira Ayuso   netfilter: ctnetl...
250
  {
4542fa472   Holger Eitzenberger   netfilter: ctnetl...
251
  	struct nf_conn_acct *acct = nf_conn_acct_find(ct);
80e60e67b   Pablo Neira Ayuso   netfilter: ctnetl...
252

80e60e67b   Pablo Neira Ayuso   netfilter: ctnetl...
253
254
  	if (!acct)
  		return 0;
4542fa472   Holger Eitzenberger   netfilter: ctnetl...
255
256
257
258
259
260
  	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...
261
262
263
  }
  
  static int
a992ca2a0   Pablo Neira Ayuso   netfilter: nf_con...
264
265
266
267
268
269
270
271
  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;
ae0be8de9   Michal Kubecek   netlink: make nla...
272
  	nest_count = nla_nest_start(skb, CTA_TIMESTAMP);
a992ca2a0   Pablo Neira Ayuso   netfilter: nf_con...
273
274
  	if (!nest_count)
  		goto nla_put_failure;
b46f6ded9   Nicolas Dichtel   libnl: nla_put_be...
275
276
  	if (nla_put_be64(skb, CTA_TIMESTAMP_START, cpu_to_be64(tstamp->start),
  			 CTA_TIMESTAMP_PAD) ||
cc1eb4313   David S. Miller   nf_conntrack_netl...
277
  	    (tstamp->stop != 0 && nla_put_be64(skb, CTA_TIMESTAMP_STOP,
b46f6ded9   Nicolas Dichtel   libnl: nla_put_be...
278
279
  					       cpu_to_be64(tstamp->stop),
  					       CTA_TIMESTAMP_PAD)))
cc1eb4313   David S. Miller   nf_conntrack_netl...
280
  		goto nla_put_failure;
a992ca2a0   Pablo Neira Ayuso   netfilter: nf_con...
281
282
283
284
285
286
287
  	nla_nest_end(skb, nest_count);
  
  	return 0;
  
  nla_put_failure:
  	return -1;
  }
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
288
  #ifdef CONFIG_NF_CONNTRACK_MARK
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
289
  static int ctnetlink_dump_mark(struct sk_buff *skb, const struct nf_conn *ct)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
290
  {
cc1eb4313   David S. Miller   nf_conntrack_netl...
291
292
  	if (nla_put_be32(skb, CTA_MARK, htonl(ct->mark)))
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
293
  	return 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
294
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
295
296
297
298
299
  	return -1;
  }
  #else
  #define ctnetlink_dump_mark(a, b) (0)
  #endif
37fccd857   Pablo Neira Ayuso   [NETFILTER]: ctne...
300
  #ifdef CONFIG_NF_CONNTRACK_SECMARK
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
301
  static int ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct)
37fccd857   Pablo Neira Ayuso   [NETFILTER]: ctne...
302
  {
1cc63249a   Eric Paris   conntrack: export...
303
304
305
306
307
308
  	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...
309
  		return 0;
1cc63249a   Eric Paris   conntrack: export...
310
311
  
  	ret = -1;
ae0be8de9   Michal Kubecek   netlink: make nla...
312
  	nest_secctx = nla_nest_start(skb, CTA_SECCTX);
1cc63249a   Eric Paris   conntrack: export...
313
314
  	if (!nest_secctx)
  		goto nla_put_failure;
37fccd857   Pablo Neira Ayuso   [NETFILTER]: ctne...
315

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

41d73ec05   Patrick McHardy   netfilter: nf_con...
406
  	if (!(ct->status & IPS_SEQ_ADJUST) || !seqadj)
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
407
  		return 0;
64f3967c7   Liping Zhang   netfilter: ctnetl...
408
  	spin_lock_bh(&ct->lock);
41d73ec05   Patrick McHardy   netfilter: nf_con...
409
410
  	seq = &seqadj->seq[IP_CT_DIR_ORIGINAL];
  	if (dump_ct_seq_adj(skb, seq, CTA_SEQ_ADJ_ORIG) == -1)
64f3967c7   Liping Zhang   netfilter: ctnetl...
411
  		goto err;
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
412

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

64f3967c7   Liping Zhang   netfilter: ctnetl...
417
  	spin_unlock_bh(&ct->lock);
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
418
  	return 0;
64f3967c7   Liping Zhang   netfilter: ctnetl...
419
420
421
  err:
  	spin_unlock_bh(&ct->lock);
  	return -1;
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
422
  }
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
423

20710b3b8   Pablo Neira Ayuso   netfilter: ctnetl...
424
425
426
427
428
429
430
  static int ctnetlink_dump_ct_synproxy(struct sk_buff *skb, struct nf_conn *ct)
  {
  	struct nf_conn_synproxy *synproxy = nfct_synproxy(ct);
  	struct nlattr *nest_parms;
  
  	if (!synproxy)
  		return 0;
ae0be8de9   Michal Kubecek   netlink: make nla...
431
  	nest_parms = nla_nest_start(skb, CTA_SYNPROXY);
20710b3b8   Pablo Neira Ayuso   netfilter: ctnetl...
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
  	if (!nest_parms)
  		goto nla_put_failure;
  
  	if (nla_put_be32(skb, CTA_SYNPROXY_ISN, htonl(synproxy->isn)) ||
  	    nla_put_be32(skb, CTA_SYNPROXY_ITS, htonl(synproxy->its)) ||
  	    nla_put_be32(skb, CTA_SYNPROXY_TSOFF, htonl(synproxy->tsoff)))
  		goto nla_put_failure;
  
  	nla_nest_end(skb, nest_parms);
  
  	return 0;
  
  nla_put_failure:
  	return -1;
  }
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
447
  static int ctnetlink_dump_id(struct sk_buff *skb, const struct nf_conn *ct)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
448
  {
3c7910763   Florian Westphal   netfilter: ctnetl...
449
450
451
  	__be32 id = (__force __be32)nf_ct_get_id(ct);
  
  	if (nla_put_be32(skb, CTA_ID, id))
cc1eb4313   David S. Miller   nf_conntrack_netl...
452
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
453
  	return 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
454
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
455
456
  	return -1;
  }
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
457
  static int ctnetlink_dump_use(struct sk_buff *skb, const struct nf_conn *ct)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
458
  {
cc1eb4313   David S. Miller   nf_conntrack_netl...
459
460
  	if (nla_put_be32(skb, CTA_USE, htonl(atomic_read(&ct->ct_general.use))))
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
461
  	return 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
462
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
463
464
  	return -1;
  }
49ca022bc   Florian Westphal   netfilter: ctnetl...
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
  /* all these functions access ct->ext. Caller must either hold a reference
   * on ct or prevent its deletion by holding either the bucket spinlock or
   * pcpu dying list lock.
   */
  static int ctnetlink_dump_extinfo(struct sk_buff *skb,
  				  struct nf_conn *ct, u32 type)
  {
  	if (ctnetlink_dump_acct(skb, ct, type) < 0 ||
  	    ctnetlink_dump_timestamp(skb, ct) < 0 ||
  	    ctnetlink_dump_helpinfo(skb, ct) < 0 ||
  	    ctnetlink_dump_labels(skb, ct) < 0 ||
  	    ctnetlink_dump_ct_seq_adj(skb, ct) < 0 ||
  	    ctnetlink_dump_ct_synproxy(skb, ct) < 0)
  		return -1;
  
  	return 0;
  }
  
  static int ctnetlink_dump_info(struct sk_buff *skb, struct nf_conn *ct)
  {
  	if (ctnetlink_dump_status(skb, ct) < 0 ||
  	    ctnetlink_dump_mark(skb, ct) < 0 ||
  	    ctnetlink_dump_secctx(skb, ct) < 0 ||
  	    ctnetlink_dump_id(skb, ct) < 0 ||
  	    ctnetlink_dump_use(skb, ct) < 0 ||
  	    ctnetlink_dump_master(skb, ct) < 0)
  		return -1;
  
  	if (!test_bit(IPS_OFFLOAD_BIT, &ct->status) &&
  	    (ctnetlink_dump_timeout(skb, ct) < 0 ||
  	     ctnetlink_dump_protoinfo(skb, ct) < 0))
  		return -1;
  
  	return 0;
  }
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
500
  static int
15e473046   Eric W. Biederman   netlink: Rename p...
501
  ctnetlink_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
502
  		    struct nf_conn *ct, bool extinfo, unsigned int flags)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
503
  {
308ac9143   Daniel Borkmann   netfilter: nf_con...
504
  	const struct nf_conntrack_zone *zone;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
505
506
  	struct nlmsghdr *nlh;
  	struct nfgenmsg *nfmsg;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
507
  	struct nlattr *nest_parms;
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
508
  	unsigned int event;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
509

cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
510
511
  	if (portid)
  		flags |= NLM_F_MULTI;
dedb67c4b   Pablo Neira Ayuso   netfilter: Add nf...
512
  	event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_NEW);
15e473046   Eric W. Biederman   netlink: Rename p...
513
  	nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
514
515
  	if (nlh == NULL)
  		goto nlmsg_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
516

96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
517
  	nfmsg = nlmsg_data(nlh);
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
518
  	nfmsg->nfgen_family = nf_ct_l3num(ct);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
519
520
  	nfmsg->version      = NFNETLINK_V0;
  	nfmsg->res_id	    = 0;
deedb5903   Daniel Borkmann   netfilter: nf_con...
521
  	zone = nf_ct_zone(ct);
ae0be8de9   Michal Kubecek   netlink: make nla...
522
  	nest_parms = nla_nest_start(skb, CTA_TUPLE_ORIG);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
523
524
  	if (!nest_parms)
  		goto nla_put_failure;
f2f3e38c6   Pablo Neira Ayuso   netfilter: ctnetl...
525
  	if (ctnetlink_dump_tuples(skb, nf_ct_tuple(ct, IP_CT_DIR_ORIGINAL)) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
526
  		goto nla_put_failure;
deedb5903   Daniel Borkmann   netfilter: nf_con...
527
528
529
  	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...
530
  	nla_nest_end(skb, nest_parms);
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
531

ae0be8de9   Michal Kubecek   netlink: make nla...
532
  	nest_parms = nla_nest_start(skb, CTA_TUPLE_REPLY);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
533
534
  	if (!nest_parms)
  		goto nla_put_failure;
f2f3e38c6   Pablo Neira Ayuso   netfilter: ctnetl...
535
  	if (ctnetlink_dump_tuples(skb, nf_ct_tuple(ct, IP_CT_DIR_REPLY)) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
536
  		goto nla_put_failure;
deedb5903   Daniel Borkmann   netfilter: nf_con...
537
538
539
  	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...
540
  	nla_nest_end(skb, nest_parms);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
541

deedb5903   Daniel Borkmann   netfilter: nf_con...
542
543
  	if (ctnetlink_dump_zone_id(skb, CTA_ZONE, zone,
  				   NF_CT_DEFAULT_ZONE_DIR) < 0)
cc1eb4313   David S. Miller   nf_conntrack_netl...
544
  		goto nla_put_failure;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
545

49ca022bc   Florian Westphal   netfilter: ctnetl...
546
  	if (ctnetlink_dump_info(skb, ct) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
547
  		goto nla_put_failure;
49ca022bc   Florian Westphal   netfilter: ctnetl...
548
  	if (extinfo && ctnetlink_dump_extinfo(skb, ct, type) < 0)
b067fa009   Pablo Neira Ayuso   netfilter: ctnetl...
549
  		goto nla_put_failure;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
550
  	nlmsg_end(skb, nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
551
552
553
  	return skb->len;
  
  nlmsg_failure:
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
554
  nla_put_failure:
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
555
  	nlmsg_cancel(skb, nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
556
557
  	return -1;
  }
f957be9d3   Florian Westphal   netfilter: conntr...
558
559
560
561
562
563
  static const struct nla_policy cta_ip_nla_policy[CTA_IP_MAX + 1] = {
  	[CTA_IP_V4_SRC]	= { .type = NLA_U32 },
  	[CTA_IP_V4_DST]	= { .type = NLA_U32 },
  	[CTA_IP_V6_SRC]	= { .len = sizeof(__be32) * 4 },
  	[CTA_IP_V6_DST]	= { .len = sizeof(__be32) * 4 },
  };
8252fceac   Arnd Bergmann   netfilter: add if...
564
  #if defined(CONFIG_NETFILTER_NETLINK_GLUE_CT) || defined(CONFIG_NF_CONNTRACK_EVENTS)
5caaed151   Florian Westphal   netfilter: conntr...
565
  static size_t ctnetlink_proto_size(const struct nf_conn *ct)
2732c4e45   Holger Eitzenberger   netfilter: ctnetl...
566
  {
b3480fe05   Florian Westphal   netfilter: conntr...
567
  	const struct nf_conntrack_l4proto *l4proto;
5caaed151   Florian Westphal   netfilter: conntr...
568
  	size_t len, len4 = 0;
03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
569

f957be9d3   Florian Westphal   netfilter: conntr...
570
  	len = nla_policy_len(cta_ip_nla_policy, CTA_IP_MAX + 1);
0d0351003   Florian Westphal   netfilter: conntr...
571
  	len *= 3u; /* ORIG, REPLY, MASTER */
03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
572

4a60dc748   Florian Westphal   netfilter: conntr...
573
  	l4proto = nf_ct_l4proto_find(nf_ct_protonum(ct));
392158467   Florian Westphal   netfilter: conntr...
574
  	len += l4proto->nlattr_size;
5caaed151   Florian Westphal   netfilter: conntr...
575
576
577
578
  	if (l4proto->nlattr_tuple_size) {
  		len4 = l4proto->nlattr_tuple_size();
  		len4 *= 3u; /* ORIG, REPLY, MASTER */
  	}
03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
579

5caaed151   Florian Westphal   netfilter: conntr...
580
  	return len + len4;
03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
581
  }
8252fceac   Arnd Bergmann   netfilter: add if...
582
  #endif
03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
583

4a96300ce   Pablo Neira Ayuso   netfilter: ctnetl...
584
  static inline size_t ctnetlink_acct_size(const struct nf_conn *ct)
d26e6a028   Jiri Pirko   netfilter: ctnetl...
585
586
587
588
  {
  	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...
589
590
  	       + 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...
591
592
  	       ;
  }
4a96300ce   Pablo Neira Ayuso   netfilter: ctnetl...
593
  static inline int ctnetlink_secctx_size(const struct nf_conn *ct)
1cc63249a   Eric Paris   conntrack: export...
594
  {
cba85b532   Pablo Neira Ayuso   netfilter: fix ex...
595
596
  #ifdef CONFIG_NF_CONNTRACK_SECMARK
  	int len, ret;
1cc63249a   Eric Paris   conntrack: export...
597

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

cba85b532   Pablo Neira Ayuso   netfilter: fix ex...
602
603
604
605
  	return nla_total_size(0) /* CTA_SECCTX */
  	       + nla_total_size(sizeof(char) * len); /* CTA_SECCTX_NAME */
  #else
  	return 0;
1cc63249a   Eric Paris   conntrack: export...
606
  #endif
cba85b532   Pablo Neira Ayuso   netfilter: fix ex...
607
  }
1cc63249a   Eric Paris   conntrack: export...
608

4a96300ce   Pablo Neira Ayuso   netfilter: ctnetl...
609
  static inline size_t ctnetlink_timestamp_size(const struct nf_conn *ct)
a992ca2a0   Pablo Neira Ayuso   netfilter: nf_con...
610
611
612
613
  {
  #ifdef CONFIG_NF_CONNTRACK_TIMESTAMP
  	if (!nf_ct_ext_exist(ct, NF_CT_EXT_TSTAMP))
  		return 0;
b46f6ded9   Nicolas Dichtel   libnl: nla_put_be...
614
  	return nla_total_size(0) + 2 * nla_total_size_64bit(sizeof(uint64_t));
a992ca2a0   Pablo Neira Ayuso   netfilter: nf_con...
615
616
617
618
  #else
  	return 0;
  #endif
  }
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
619
620
  #ifdef CONFIG_NF_CONNTRACK_EVENTS
  static size_t ctnetlink_nlmsg_size(const struct nf_conn *ct)
03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
621
622
623
624
625
626
627
628
  {
  	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...
629
  	       + ctnetlink_acct_size(ct)
a992ca2a0   Pablo Neira Ayuso   netfilter: nf_con...
630
  	       + ctnetlink_timestamp_size(ct)
03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
631
632
633
634
  	       + 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...
635
  	       + ctnetlink_secctx_size(ct)
4806e9757   Florian Westphal   netfilter: replac...
636
  #if IS_ENABLED(CONFIG_NF_NAT)
03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
637
638
  	       + 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...
639
640
  #endif
  #ifdef CONFIG_NF_CONNTRACK_MARK
03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
641
  	       + nla_total_size(sizeof(u_int32_t)) /* CTA_MARK */
d271e8bd8   Holger Eitzenberger   ctnetlink: comput...
642
  #endif
4a001068d   Ken-ichirou MATSUZAWA   netfilter: ctnetl...
643
  #ifdef CONFIG_NF_CONNTRACK_ZONES
deedb5903   Daniel Borkmann   netfilter: nf_con...
644
  	       + nla_total_size(sizeof(u_int16_t)) /* CTA_ZONE|CTA_TUPLE_ZONE */
4a001068d   Ken-ichirou MATSUZAWA   netfilter: ctnetl...
645
  #endif
03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
646
  	       + ctnetlink_proto_size(ct)
0ceabd838   Florian Westphal   netfilter: ctnetl...
647
  	       + ctnetlink_label_size(ct)
03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
648
  	       ;
2732c4e45   Holger Eitzenberger   netfilter: ctnetl...
649
  }
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
650
651
  static int
  ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
652
  {
308ac9143   Daniel Borkmann   netfilter: nf_con...
653
  	const struct nf_conntrack_zone *zone;
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
654
  	struct net *net;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
655
656
  	struct nlmsghdr *nlh;
  	struct nfgenmsg *nfmsg;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
657
  	struct nlattr *nest_parms;
19abb7b09   Pablo Neira Ayuso   netfilter: ctnetl...
658
  	struct nf_conn *ct = item->ct;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
659
660
  	struct sk_buff *skb;
  	unsigned int type;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
661
  	unsigned int flags = 0, group;
dd7669a92   Pablo Neira Ayuso   netfilter: conntr...
662
  	int err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
663

a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
664
  	if (events & (1 << IPCT_DESTROY)) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
665
666
  		type = IPCTNL_MSG_CT_DELETE;
  		group = NFNLGRP_CONNTRACK_DESTROY;
04b80cead   linzhang   netfilter: ctnetl...
667
  	} else if (events & ((1 << IPCT_NEW) | (1 << IPCT_RELATED))) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
668
669
  		type = IPCTNL_MSG_CT_NEW;
  		flags = NLM_F_CREATE|NLM_F_EXCL;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
670
  		group = NFNLGRP_CONNTRACK_NEW;
04b80cead   linzhang   netfilter: ctnetl...
671
  	} else if (events) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
672
673
674
  		type = IPCTNL_MSG_CT_NEW;
  		group = NFNLGRP_CONNTRACK_UPDATE;
  	} else
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
675
  		return 0;
a24276924   Patrick McHardy   [NETFILTER]: ctne...
676

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

03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
681
682
  	skb = nlmsg_new(ctnetlink_nlmsg_size(ct), GFP_ATOMIC);
  	if (skb == NULL)
150ace0db   Pablo Neira Ayuso   netfilter: ctnetl...
683
  		goto errout;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
684

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

96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
690
  	nfmsg = nlmsg_data(nlh);
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
691
  	nfmsg->nfgen_family = nf_ct_l3num(ct);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
692
693
  	nfmsg->version	= NFNETLINK_V0;
  	nfmsg->res_id	= 0;
deedb5903   Daniel Borkmann   netfilter: nf_con...
694
  	zone = nf_ct_zone(ct);
ae0be8de9   Michal Kubecek   netlink: make nla...
695
  	nest_parms = nla_nest_start(skb, CTA_TUPLE_ORIG);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
696
697
  	if (!nest_parms)
  		goto nla_put_failure;
f2f3e38c6   Pablo Neira Ayuso   netfilter: ctnetl...
698
  	if (ctnetlink_dump_tuples(skb, nf_ct_tuple(ct, IP_CT_DIR_ORIGINAL)) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
699
  		goto nla_put_failure;
deedb5903   Daniel Borkmann   netfilter: nf_con...
700
701
702
  	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...
703
  	nla_nest_end(skb, nest_parms);
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
704

ae0be8de9   Michal Kubecek   netlink: make nla...
705
  	nest_parms = nla_nest_start(skb, CTA_TUPLE_REPLY);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
706
707
  	if (!nest_parms)
  		goto nla_put_failure;
f2f3e38c6   Pablo Neira Ayuso   netfilter: ctnetl...
708
  	if (ctnetlink_dump_tuples(skb, nf_ct_tuple(ct, IP_CT_DIR_REPLY)) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
709
  		goto nla_put_failure;
deedb5903   Daniel Borkmann   netfilter: nf_con...
710
711
712
  	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...
713
  	nla_nest_end(skb, nest_parms);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
714

deedb5903   Daniel Borkmann   netfilter: nf_con...
715
716
  	if (ctnetlink_dump_zone_id(skb, CTA_ZONE, zone,
  				   NF_CT_DEFAULT_ZONE_DIR) < 0)
cc1eb4313   David S. Miller   nf_conntrack_netl...
717
  		goto nla_put_failure;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
718

1eedf6999   Eric Leblond   netfilter: ctnetl...
719
720
  	if (ctnetlink_dump_id(skb, ct) < 0)
  		goto nla_put_failure;
e57dce60c   Fabian Hugelshofer   netfilter: ctnetl...
721
722
  	if (ctnetlink_dump_status(skb, ct) < 0)
  		goto nla_put_failure;
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
723
  	if (events & (1 << IPCT_DESTROY)) {
4542fa472   Holger Eitzenberger   netfilter: ctnetl...
724
  		if (ctnetlink_dump_acct(skb, ct, type) < 0 ||
a992ca2a0   Pablo Neira Ayuso   netfilter: nf_con...
725
  		    ctnetlink_dump_timestamp(skb, ct) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
726
  			goto nla_put_failure;
7b621c1ea   Pablo Neira Ayuso   [NETFILTER]: ctne...
727
  	} else {
7b621c1ea   Pablo Neira Ayuso   [NETFILTER]: ctne...
728
  		if (ctnetlink_dump_timeout(skb, ct) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
729
  			goto nla_put_failure;
7b621c1ea   Pablo Neira Ayuso   [NETFILTER]: ctne...
730

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

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

ff660c80d   Eric Paris   secmark: fix conf...
739
  #ifdef CONFIG_NF_CONNTRACK_SECMARK
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
740
  		if ((events & (1 << IPCT_SECMARK) || ct->secmark)
1cc63249a   Eric Paris   conntrack: export...
741
  		    && ctnetlink_dump_secctx(skb, ct) < 0)
37fccd857   Pablo Neira Ayuso   [NETFILTER]: ctne...
742
  			goto nla_put_failure;
ff660c80d   Eric Paris   secmark: fix conf...
743
  #endif
0ceabd838   Florian Westphal   netfilter: ctnetl...
744
745
746
  		if (events & (1 << IPCT_LABEL) &&
  		     ctnetlink_dump_labels(skb, ct) < 0)
  			goto nla_put_failure;
7b621c1ea   Pablo Neira Ayuso   [NETFILTER]: ctne...
747

a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
748
  		if (events & (1 << IPCT_RELATED) &&
0f417ce98   Pablo Neira Ayuso   [NETFILTER]: ctne...
749
750
  		    ctnetlink_dump_master(skb, ct) < 0)
  			goto nla_put_failure;
41d73ec05   Patrick McHardy   netfilter: nf_con...
751
752
  		if (events & (1 << IPCT_SEQADJ) &&
  		    ctnetlink_dump_ct_seq_adj(skb, ct) < 0)
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
753
  			goto nla_put_failure;
20710b3b8   Pablo Neira Ayuso   netfilter: ctnetl...
754
755
756
757
  
  		if (events & (1 << IPCT_SYNPROXY) &&
  		    ctnetlink_dump_ct_synproxy(skb, ct) < 0)
  			goto nla_put_failure;
7b621c1ea   Pablo Neira Ayuso   [NETFILTER]: ctne...
758
  	}
b9a37e0c8   Pablo Neira Ayuso   [NETFILTER]: ctne...
759

a83099a60   Eric Leblond   [NETFILTER]: nf_c...
760
  #ifdef CONFIG_NF_CONNTRACK_MARK
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
761
  	if ((events & (1 << IPCT_MARK) || ct->mark)
a83099a60   Eric Leblond   [NETFILTER]: nf_c...
762
763
764
  	    && ctnetlink_dump_mark(skb, ct) < 0)
  		goto nla_put_failure;
  #endif
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
765
  	nlmsg_end(skb, nlh);
15e473046   Eric W. Biederman   netlink: Rename p...
766
  	err = nfnetlink_send(skb, net, item->portid, group, item->report,
cd8c20b65   Alexey Dobriyan   netfilter: nfnetl...
767
  			     GFP_ATOMIC);
dd7669a92   Pablo Neira Ayuso   netfilter: conntr...
768
769
  	if (err == -ENOBUFS || err == -EAGAIN)
  		return -ENOBUFS;
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
770
  	return 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
771

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
772
  nla_put_failure:
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
773
  	nlmsg_cancel(skb, nlh);
528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
774
  nlmsg_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
775
  	kfree_skb(skb);
150ace0db   Pablo Neira Ayuso   netfilter: ctnetl...
776
  errout:
37b7ef720   Pablo Neira Ayuso   netfilter: ctnetl...
777
778
  	if (nfnetlink_set_err(net, 0, group, -ENOBUFS) > 0)
  		return -ENOBUFS;
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
779
  	return 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
780
781
782
783
784
  }
  #endif /* CONFIG_NF_CONNTRACK_EVENTS */
  
  static int ctnetlink_done(struct netlink_callback *cb)
  {
89f2e2188   Patrick McHardy   [NETFILTER]: ctne...
785
786
  	if (cb->args[1])
  		nf_ct_put((struct nf_conn *)cb->args[1]);
397304b52   Fabian Frederick   netfilter: ctnetl...
787
  	kfree(cb->data);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
788
789
  	return 0;
  }
866476f32   Kristian Evensen   netfilter: conntr...
790
  struct ctnetlink_filter {
59c08c69c   Kristian Evensen   netfilter: ctnetl...
791
  	u8 family;
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
792
793
794
795
796
797
798
  
  	u_int32_t orig_flags;
  	u_int32_t reply_flags;
  
  	struct nf_conntrack_tuple orig;
  	struct nf_conntrack_tuple reply;
  	struct nf_conntrack_zone zone;
0f298a285   Pablo Neira Ayuso   netfilter: ctnetl...
799
800
801
802
803
  	struct {
  		u_int32_t val;
  		u_int32_t mask;
  	} mark;
  };
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
  static const struct nla_policy cta_filter_nla_policy[CTA_FILTER_MAX + 1] = {
  	[CTA_FILTER_ORIG_FLAGS]		= { .type = NLA_U32 },
  	[CTA_FILTER_REPLY_FLAGS]	= { .type = NLA_U32 },
  };
  
  static int ctnetlink_parse_filter(const struct nlattr *attr,
  				  struct ctnetlink_filter *filter)
  {
  	struct nlattr *tb[CTA_FILTER_MAX + 1];
  	int ret = 0;
  
  	ret = nla_parse_nested(tb, CTA_FILTER_MAX, attr, cta_filter_nla_policy,
  			       NULL);
  	if (ret)
  		return ret;
  
  	if (tb[CTA_FILTER_ORIG_FLAGS]) {
  		filter->orig_flags = nla_get_u32(tb[CTA_FILTER_ORIG_FLAGS]);
  		if (filter->orig_flags & ~CTA_FILTER_F_ALL)
  			return -EOPNOTSUPP;
  	}
  
  	if (tb[CTA_FILTER_REPLY_FLAGS]) {
  		filter->reply_flags = nla_get_u32(tb[CTA_FILTER_REPLY_FLAGS]);
  		if (filter->reply_flags & ~CTA_FILTER_F_ALL)
  			return -EOPNOTSUPP;
  	}
  
  	return 0;
  }
  
  static int ctnetlink_parse_zone(const struct nlattr *attr,
  				struct nf_conntrack_zone *zone);
  static int ctnetlink_parse_tuple_filter(const struct nlattr * const cda[],
  					 struct nf_conntrack_tuple *tuple,
  					 u32 type, u_int8_t l3num,
  					 struct nf_conntrack_zone *zone,
  					 u_int32_t flags);
866476f32   Kristian Evensen   netfilter: conntr...
842
  static struct ctnetlink_filter *
59c08c69c   Kristian Evensen   netfilter: ctnetl...
843
  ctnetlink_alloc_filter(const struct nlattr * const cda[], u8 family)
866476f32   Kristian Evensen   netfilter: conntr...
844
  {
866476f32   Kristian Evensen   netfilter: conntr...
845
  	struct ctnetlink_filter *filter;
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
846
  	int err;
866476f32   Kristian Evensen   netfilter: conntr...
847

9306425b7   Florian Westphal   netfilter: ctnetl...
848
  #ifndef CONFIG_NF_CONNTRACK_MARK
7c6b41216   Romain Bellan   netfilter: ctnetl...
849
  	if (cda[CTA_MARK] || cda[CTA_MARK_MASK])
9306425b7   Florian Westphal   netfilter: ctnetl...
850
851
  		return ERR_PTR(-EOPNOTSUPP);
  #endif
866476f32   Kristian Evensen   netfilter: conntr...
852
853
854
  	filter = kzalloc(sizeof(*filter), GFP_KERNEL);
  	if (filter == NULL)
  		return ERR_PTR(-ENOMEM);
59c08c69c   Kristian Evensen   netfilter: ctnetl...
855
856
857
  	filter->family = family;
  
  #ifdef CONFIG_NF_CONNTRACK_MARK
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
858
  	if (cda[CTA_MARK]) {
9306425b7   Florian Westphal   netfilter: ctnetl...
859
  		filter->mark.val = ntohl(nla_get_be32(cda[CTA_MARK]));
6c0d95d12   Martin Willi   netfilter: ctnetl...
860
  		if (cda[CTA_MARK_MASK])
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
861
  			filter->mark.mask = ntohl(nla_get_be32(cda[CTA_MARK_MASK]));
6c0d95d12   Martin Willi   netfilter: ctnetl...
862
  		else
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
863
  			filter->mark.mask = 0xffffffff;
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
864
  	} else if (cda[CTA_MARK_MASK]) {
6c2d2176a   Pablo Neira Ayuso   netfilter: ctnetl...
865
866
  		err = -EINVAL;
  		goto err_filter;
9306425b7   Florian Westphal   netfilter: ctnetl...
867
  	}
866476f32   Kristian Evensen   netfilter: conntr...
868
  #endif
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
869
870
871
872
873
  	if (!cda[CTA_FILTER])
  		return filter;
  
  	err = ctnetlink_parse_zone(cda[CTA_ZONE], &filter->zone);
  	if (err < 0)
6c2d2176a   Pablo Neira Ayuso   netfilter: ctnetl...
874
  		goto err_filter;
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
875
876
877
  
  	err = ctnetlink_parse_filter(cda[CTA_FILTER], filter);
  	if (err < 0)
6c2d2176a   Pablo Neira Ayuso   netfilter: ctnetl...
878
  		goto err_filter;
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
879
880
  
  	if (filter->orig_flags) {
6c2d2176a   Pablo Neira Ayuso   netfilter: ctnetl...
881
882
883
884
  		if (!cda[CTA_TUPLE_ORIG]) {
  			err = -EINVAL;
  			goto err_filter;
  		}
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
885
886
887
888
889
890
891
  
  		err = ctnetlink_parse_tuple_filter(cda, &filter->orig,
  						   CTA_TUPLE_ORIG,
  						   filter->family,
  						   &filter->zone,
  						   filter->orig_flags);
  		if (err < 0)
6c2d2176a   Pablo Neira Ayuso   netfilter: ctnetl...
892
  			goto err_filter;
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
893
894
895
  	}
  
  	if (filter->reply_flags) {
6c2d2176a   Pablo Neira Ayuso   netfilter: ctnetl...
896
897
898
899
  		if (!cda[CTA_TUPLE_REPLY]) {
  			err = -EINVAL;
  			goto err_filter;
  		}
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
900
901
902
903
904
905
  
  		err = ctnetlink_parse_tuple_filter(cda, &filter->reply,
  						   CTA_TUPLE_REPLY,
  						   filter->family,
  						   &filter->zone,
  						   filter->orig_flags);
6c2d2176a   Pablo Neira Ayuso   netfilter: ctnetl...
906
907
908
909
  		if (err < 0) {
  			err = -EINVAL;
  			goto err_filter;
  		}
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
910
  	}
59c08c69c   Kristian Evensen   netfilter: ctnetl...
911
  	return filter;
6c2d2176a   Pablo Neira Ayuso   netfilter: ctnetl...
912
913
914
915
916
  
  err_filter:
  	kfree(filter);
  
  	return ERR_PTR(err);
866476f32   Kristian Evensen   netfilter: conntr...
917
  }
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
918
919
920
921
  static bool ctnetlink_needs_filter(u8 family, const struct nlattr * const *cda)
  {
  	return family || cda[CTA_MARK] || cda[CTA_FILTER];
  }
3e673b23b   Florian Westphal   netfilter: fix me...
922
923
924
925
  static int ctnetlink_start(struct netlink_callback *cb)
  {
  	const struct nlattr * const *cda = cb->data;
  	struct ctnetlink_filter *filter = NULL;
59c08c69c   Kristian Evensen   netfilter: ctnetl...
926
927
  	struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
  	u8 family = nfmsg->nfgen_family;
3e673b23b   Florian Westphal   netfilter: fix me...
928

cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
929
  	if (ctnetlink_needs_filter(family, cda)) {
59c08c69c   Kristian Evensen   netfilter: ctnetl...
930
  		filter = ctnetlink_alloc_filter(cda, family);
3e673b23b   Florian Westphal   netfilter: fix me...
931
932
933
934
935
936
937
  		if (IS_ERR(filter))
  			return PTR_ERR(filter);
  	}
  
  	cb->data = filter;
  	return 0;
  }
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
  static int ctnetlink_filter_match_tuple(struct nf_conntrack_tuple *filter_tuple,
  					struct nf_conntrack_tuple *ct_tuple,
  					u_int32_t flags, int family)
  {
  	switch (family) {
  	case NFPROTO_IPV4:
  		if ((flags & CTA_FILTER_FLAG(CTA_IP_SRC)) &&
  		    filter_tuple->src.u3.ip != ct_tuple->src.u3.ip)
  			return  0;
  
  		if ((flags & CTA_FILTER_FLAG(CTA_IP_DST)) &&
  		    filter_tuple->dst.u3.ip != ct_tuple->dst.u3.ip)
  			return  0;
  		break;
  	case NFPROTO_IPV6:
  		if ((flags & CTA_FILTER_FLAG(CTA_IP_SRC)) &&
  		    !ipv6_addr_cmp(&filter_tuple->src.u3.in6,
  				   &ct_tuple->src.u3.in6))
  			return 0;
  
  		if ((flags & CTA_FILTER_FLAG(CTA_IP_DST)) &&
  		    !ipv6_addr_cmp(&filter_tuple->dst.u3.in6,
  				   &ct_tuple->dst.u3.in6))
  			return 0;
  		break;
  	}
  
  	if ((flags & CTA_FILTER_FLAG(CTA_PROTO_NUM)) &&
  	    filter_tuple->dst.protonum != ct_tuple->dst.protonum)
  		return 0;
  
  	switch (ct_tuple->dst.protonum) {
  	case IPPROTO_TCP:
  	case IPPROTO_UDP:
  		if ((flags & CTA_FILTER_FLAG(CTA_PROTO_SRC_PORT)) &&
  		    filter_tuple->src.u.tcp.port != ct_tuple->src.u.tcp.port)
  			return 0;
  
  		if ((flags & CTA_FILTER_FLAG(CTA_PROTO_DST_PORT)) &&
  		    filter_tuple->dst.u.tcp.port != ct_tuple->dst.u.tcp.port)
  			return 0;
  		break;
  	case IPPROTO_ICMP:
  		if ((flags & CTA_FILTER_FLAG(CTA_PROTO_ICMP_TYPE)) &&
  		    filter_tuple->dst.u.icmp.type != ct_tuple->dst.u.icmp.type)
  			return 0;
  		if ((flags & CTA_FILTER_FLAG(CTA_PROTO_ICMP_CODE)) &&
  		    filter_tuple->dst.u.icmp.code != ct_tuple->dst.u.icmp.code)
  			return 0;
  		if ((flags & CTA_FILTER_FLAG(CTA_PROTO_ICMP_ID)) &&
  		    filter_tuple->src.u.icmp.id != ct_tuple->src.u.icmp.id)
  			return 0;
  		break;
  	case IPPROTO_ICMPV6:
  		if ((flags & CTA_FILTER_FLAG(CTA_PROTO_ICMPV6_TYPE)) &&
  		    filter_tuple->dst.u.icmp.type != ct_tuple->dst.u.icmp.type)
  			return 0;
  		if ((flags & CTA_FILTER_FLAG(CTA_PROTO_ICMPV6_CODE)) &&
  		    filter_tuple->dst.u.icmp.code != ct_tuple->dst.u.icmp.code)
  			return 0;
  		if ((flags & CTA_FILTER_FLAG(CTA_PROTO_ICMPV6_ID)) &&
  		    filter_tuple->src.u.icmp.id != ct_tuple->src.u.icmp.id)
  			return 0;
  		break;
  	}
  
  	return 1;
  }
866476f32   Kristian Evensen   netfilter: conntr...
1006
1007
1008
  static int ctnetlink_filter_match(struct nf_conn *ct, void *data)
  {
  	struct ctnetlink_filter *filter = data;
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
1009
  	struct nf_conntrack_tuple *tuple;
866476f32   Kristian Evensen   netfilter: conntr...
1010
1011
  
  	if (filter == NULL)
59c08c69c   Kristian Evensen   netfilter: ctnetl...
1012
1013
1014
1015
1016
1017
1018
1019
  		goto out;
  
  	/* Match entries of a given L3 protocol number.
  	 * If it is not specified, ie. l3proto == 0,
  	 * then match everything.
  	 */
  	if (filter->family && nf_ct_l3num(ct) != filter->family)
  		goto ignore_entry;
866476f32   Kristian Evensen   netfilter: conntr...
1020

cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
  	if (filter->orig_flags) {
  		tuple = nf_ct_tuple(ct, IP_CT_DIR_ORIGINAL);
  		if (!ctnetlink_filter_match_tuple(&filter->orig, tuple,
  						  filter->orig_flags,
  						  filter->family))
  			goto ignore_entry;
  	}
  
  	if (filter->reply_flags) {
  		tuple = nf_ct_tuple(ct, IP_CT_DIR_REPLY);
  		if (!ctnetlink_filter_match_tuple(&filter->reply, tuple,
  						  filter->reply_flags,
  						  filter->family))
  			goto ignore_entry;
  	}
866476f32   Kristian Evensen   netfilter: conntr...
1036
  #ifdef CONFIG_NF_CONNTRACK_MARK
6c0d95d12   Martin Willi   netfilter: ctnetl...
1037
  	if ((ct->mark & filter->mark.mask) != filter->mark.val)
59c08c69c   Kristian Evensen   netfilter: ctnetl...
1038
  		goto ignore_entry;
866476f32   Kristian Evensen   netfilter: conntr...
1039
  #endif
59c08c69c   Kristian Evensen   netfilter: ctnetl...
1040
1041
1042
1043
  out:
  	return 1;
  
  ignore_entry:
866476f32   Kristian Evensen   netfilter: conntr...
1044
1045
  	return 0;
  }
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1046
1047
1048
  static int
  ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
  {
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
1049
  	unsigned int flags = cb->data ? NLM_F_DUMP_FILTERED : 0;
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
1050
  	struct net *net = sock_net(skb->sk);
89f2e2188   Patrick McHardy   [NETFILTER]: ctne...
1051
  	struct nf_conn *ct, *last;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1052
  	struct nf_conntrack_tuple_hash *h;
ea781f197   Eric Dumazet   netfilter: nf_con...
1053
  	struct hlist_nulls_node *n;
2344d64ec   Florian Westphal   netfilter: evict ...
1054
1055
  	struct nf_conn *nf_ct_evict[8];
  	int res, i;
93bb0ceb7   Jesper Dangaard Brouer   netfilter: conntr...
1056
  	spinlock_t *lockp;
d205dc407   Patrick McHardy   [NETFILTER]: ctne...
1057
  	last = (struct nf_conn *)cb->args[1];
2344d64ec   Florian Westphal   netfilter: evict ...
1058
  	i = 0;
93bb0ceb7   Jesper Dangaard Brouer   netfilter: conntr...
1059
1060
  
  	local_bh_disable();
56d52d489   Florian Westphal   netfilter: conntr...
1061
  	for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++) {
89f2e2188   Patrick McHardy   [NETFILTER]: ctne...
1062
  restart:
2344d64ec   Florian Westphal   netfilter: evict ...
1063
1064
1065
1066
1067
1068
  		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...
1069
  		lockp = &nf_conntrack_locks[cb->args[0] % CONNTRACK_LOCKS];
b16c29191   Sasha Levin   netfilter: nf_con...
1070
  		nf_conntrack_lock(lockp);
56d52d489   Florian Westphal   netfilter: conntr...
1071
  		if (cb->args[0] >= nf_conntrack_htable_size) {
93bb0ceb7   Jesper Dangaard Brouer   netfilter: conntr...
1072
1073
1074
  			spin_unlock(lockp);
  			goto out;
  		}
56d52d489   Florian Westphal   netfilter: conntr...
1075
1076
  		hlist_nulls_for_each_entry(h, n, &nf_conntrack_hash[cb->args[0]],
  					   hnnode) {
5b1158e90   Jozsef Kadlecsik   [NETFILTER]: Add ...
1077
  			if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1078
1079
  				continue;
  			ct = nf_ct_tuplehash_to_ctrack(h);
2344d64ec   Florian Westphal   netfilter: evict ...
1080
1081
1082
1083
1084
1085
  			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...
1086
1087
  			if (!net_eq(net, nf_ct_net(ct)))
  				continue;
d205dc407   Patrick McHardy   [NETFILTER]: ctne...
1088
1089
  			if (cb->args[1]) {
  				if (ct != last)
13ee6ac57   Stephen Hemminger   netfilter: fix ra...
1090
  					continue;
d205dc407   Patrick McHardy   [NETFILTER]: ctne...
1091
  				cb->args[1] = 0;
89f2e2188   Patrick McHardy   [NETFILTER]: ctne...
1092
  			}
866476f32   Kristian Evensen   netfilter: conntr...
1093
  			if (!ctnetlink_filter_match(ct, cb->data))
0f298a285   Pablo Neira Ayuso   netfilter: ctnetl...
1094
  				continue;
866476f32   Kristian Evensen   netfilter: conntr...
1095

3b988ece9   Hans Schillstrom   netfilter: ctnetl...
1096
  			res =
15e473046   Eric W. Biederman   netlink: Rename p...
1097
  			ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).portid,
3b988ece9   Hans Schillstrom   netfilter: ctnetl...
1098
1099
  					    cb->nlh->nlmsg_seq,
  					    NFNL_MSG_TYPE(cb->nlh->nlmsg_type),
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
1100
  					    ct, true, flags);
3b988ece9   Hans Schillstrom   netfilter: ctnetl...
1101
  			if (res < 0) {
c71caf411   Pablo Neira Ayuso   netfilter: ctnetl...
1102
  				nf_conntrack_get(&ct->ct_general);
89f2e2188   Patrick McHardy   [NETFILTER]: ctne...
1103
  				cb->args[1] = (unsigned long)ct;
93bb0ceb7   Jesper Dangaard Brouer   netfilter: conntr...
1104
  				spin_unlock(lockp);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1105
  				goto out;
89f2e2188   Patrick McHardy   [NETFILTER]: ctne...
1106
1107
  			}
  		}
93bb0ceb7   Jesper Dangaard Brouer   netfilter: conntr...
1108
  		spin_unlock(lockp);
d205dc407   Patrick McHardy   [NETFILTER]: ctne...
1109
  		if (cb->args[1]) {
89f2e2188   Patrick McHardy   [NETFILTER]: ctne...
1110
1111
  			cb->args[1] = 0;
  			goto restart;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1112
1113
  		}
  	}
89f2e2188   Patrick McHardy   [NETFILTER]: ctne...
1114
  out:
93bb0ceb7   Jesper Dangaard Brouer   netfilter: conntr...
1115
  	local_bh_enable();
fefa92679   Liping Zhang   netfilter: ctnetl...
1116
1117
1118
1119
  	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...
1120
  		nf_ct_put(last);
fefa92679   Liping Zhang   netfilter: ctnetl...
1121
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1122

2344d64ec   Florian Westphal   netfilter: evict ...
1123
1124
1125
1126
1127
1128
  	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 ...
1129
1130
  	return skb->len;
  }
f957be9d3   Florian Westphal   netfilter: conntr...
1131
  static int ipv4_nlattr_to_tuple(struct nlattr *tb[],
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
1132
1133
  				struct nf_conntrack_tuple *t,
  				u_int32_t flags)
f957be9d3   Florian Westphal   netfilter: conntr...
1134
  {
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
1135
1136
1137
1138
1139
1140
  	if (flags & CTA_FILTER_FLAG(CTA_IP_SRC)) {
  		if (!tb[CTA_IP_V4_SRC])
  			return -EINVAL;
  
  		t->src.u3.ip = nla_get_in_addr(tb[CTA_IP_V4_SRC]);
  	}
f957be9d3   Florian Westphal   netfilter: conntr...
1141

cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
1142
1143
1144
1145
1146
1147
  	if (flags & CTA_FILTER_FLAG(CTA_IP_DST)) {
  		if (!tb[CTA_IP_V4_DST])
  			return -EINVAL;
  
  		t->dst.u3.ip = nla_get_in_addr(tb[CTA_IP_V4_DST]);
  	}
f957be9d3   Florian Westphal   netfilter: conntr...
1148
1149
1150
1151
1152
  
  	return 0;
  }
  
  static int ipv6_nlattr_to_tuple(struct nlattr *tb[],
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
1153
1154
  				struct nf_conntrack_tuple *t,
  				u_int32_t flags)
f957be9d3   Florian Westphal   netfilter: conntr...
1155
  {
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
1156
1157
1158
1159
1160
1161
  	if (flags & CTA_FILTER_FLAG(CTA_IP_SRC)) {
  		if (!tb[CTA_IP_V6_SRC])
  			return -EINVAL;
  
  		t->src.u3.in6 = nla_get_in6_addr(tb[CTA_IP_V6_SRC]);
  	}
f957be9d3   Florian Westphal   netfilter: conntr...
1162

cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
1163
1164
1165
1166
1167
1168
  	if (flags & CTA_FILTER_FLAG(CTA_IP_DST)) {
  		if (!tb[CTA_IP_V6_DST])
  			return -EINVAL;
  
  		t->dst.u3.in6 = nla_get_in6_addr(tb[CTA_IP_V6_DST]);
  	}
f957be9d3   Florian Westphal   netfilter: conntr...
1169
1170
1171
  
  	return 0;
  }
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
1172
  static int ctnetlink_parse_tuple_ip(struct nlattr *attr,
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
1173
1174
  				    struct nf_conntrack_tuple *tuple,
  				    u_int32_t flags)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1175
  {
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1176
  	struct nlattr *tb[CTA_IP_MAX+1];
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1177
  	int ret = 0;
8cb081746   Johannes Berg   netlink: make val...
1178
  	ret = nla_parse_nested_deprecated(tb, CTA_IP_MAX, attr, NULL, NULL);
130ffbc26   Daniel Borkmann   netfilter: check ...
1179
1180
  	if (ret < 0)
  		return ret;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1181

8cb081746   Johannes Berg   netlink: make val...
1182
1183
  	ret = nla_validate_nested_deprecated(attr, CTA_IP_MAX,
  					     cta_ip_nla_policy, NULL);
f957be9d3   Florian Westphal   netfilter: conntr...
1184
1185
  	if (ret)
  		return ret;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1186

f957be9d3   Florian Westphal   netfilter: conntr...
1187
1188
  	switch (tuple->src.l3num) {
  	case NFPROTO_IPV4:
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
1189
  		ret = ipv4_nlattr_to_tuple(tb, tuple, flags);
f957be9d3   Florian Westphal   netfilter: conntr...
1190
1191
  		break;
  	case NFPROTO_IPV6:
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
1192
  		ret = ipv6_nlattr_to_tuple(tb, tuple, flags);
f957be9d3   Florian Westphal   netfilter: conntr...
1193
  		break;
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
1194
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1195

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1196
1197
  	return ret;
  }
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
1198
1199
  static const struct nla_policy proto_nla_policy[CTA_PROTO_MAX+1] = {
  	[CTA_PROTO_NUM]	= { .type = NLA_U8 },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1200
  };
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
1201
  static int ctnetlink_parse_tuple_proto(struct nlattr *attr,
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
1202
1203
  				       struct nf_conntrack_tuple *tuple,
  				       u_int32_t flags)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1204
  {
b3480fe05   Florian Westphal   netfilter: conntr...
1205
  	const struct nf_conntrack_l4proto *l4proto;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1206
  	struct nlattr *tb[CTA_PROTO_MAX+1];
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1207
  	int ret = 0;
8cb081746   Johannes Berg   netlink: make val...
1208
1209
  	ret = nla_parse_nested_deprecated(tb, CTA_PROTO_MAX, attr,
  					  proto_nla_policy, NULL);
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
1210
1211
  	if (ret < 0)
  		return ret;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1212

cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
1213
1214
  	if (!(flags & CTA_FILTER_FLAG(CTA_PROTO_NUM)))
  		return 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1215
  	if (!tb[CTA_PROTO_NUM])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1216
  		return -EINVAL;
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
1217

77236b6e3   Patrick McHardy   [NETFILTER]: ctne...
1218
  	tuple->dst.protonum = nla_get_u8(tb[CTA_PROTO_NUM]);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1219

cd91566e4   Florian Westphal   netfilter: ctnetl...
1220
  	rcu_read_lock();
4a60dc748   Florian Westphal   netfilter: conntr...
1221
  	l4proto = nf_ct_l4proto_find(tuple->dst.protonum);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1222

f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
1223
  	if (likely(l4proto->nlattr_to_tuple)) {
8cb081746   Johannes Berg   netlink: make val...
1224
1225
1226
  		ret = nla_validate_nested_deprecated(attr, CTA_PROTO_MAX,
  						     l4proto->nla_policy,
  						     NULL);
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
1227
  		if (ret == 0)
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
1228
  			ret = l4proto->nlattr_to_tuple(tb, tuple, flags);
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
1229
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1230

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

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1233
1234
  	return ret;
  }
deedb5903   Daniel Borkmann   netfilter: nf_con...
1235
1236
1237
1238
  static int
  ctnetlink_parse_zone(const struct nlattr *attr,
  		     struct nf_conntrack_zone *zone)
  {
5e8018fc6   Daniel Borkmann   netfilter: nf_con...
1239
1240
  	nf_ct_zone_init(zone, NF_CT_DEFAULT_ZONE_ID,
  			NF_CT_DEFAULT_ZONE_DIR, 0);
deedb5903   Daniel Borkmann   netfilter: nf_con...
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
  #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...
1271
1272
1273
  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...
1274
  	[CTA_TUPLE_ZONE]	= { .type = NLA_U16 },
d0b0268fd   Patrick McHardy   netfilter: ctnetl...
1275
  };
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
1276
1277
1278
1279
1280
1281
1282
1283
1284
  #define CTA_FILTER_F_ALL_CTA_PROTO \
    (CTA_FILTER_F_CTA_PROTO_SRC_PORT | \
     CTA_FILTER_F_CTA_PROTO_DST_PORT | \
     CTA_FILTER_F_CTA_PROTO_ICMP_TYPE | \
     CTA_FILTER_F_CTA_PROTO_ICMP_CODE | \
     CTA_FILTER_F_CTA_PROTO_ICMP_ID | \
     CTA_FILTER_F_CTA_PROTO_ICMPV6_TYPE | \
     CTA_FILTER_F_CTA_PROTO_ICMPV6_CODE | \
     CTA_FILTER_F_CTA_PROTO_ICMPV6_ID)
bb5cf80e9   Ilpo Järvinen   [NETFILTER]: Kill...
1285
  static int
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
1286
1287
1288
1289
  ctnetlink_parse_tuple_filter(const struct nlattr * const cda[],
  			      struct nf_conntrack_tuple *tuple, u32 type,
  			      u_int8_t l3num, struct nf_conntrack_zone *zone,
  			      u_int32_t flags)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1290
  {
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1291
  	struct nlattr *tb[CTA_TUPLE_MAX+1];
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1292
  	int err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1293
  	memset(tuple, 0, sizeof(*tuple));
8cb081746   Johannes Berg   netlink: make val...
1294
1295
  	err = nla_parse_nested_deprecated(tb, CTA_TUPLE_MAX, cda[type],
  					  tuple_nla_policy, NULL);
130ffbc26   Daniel Borkmann   netfilter: check ...
1296
1297
  	if (err < 0)
  		return err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1298

1cc5ef91d   Will McVicker   netfilter: ctnetl...
1299
1300
  	if (l3num != NFPROTO_IPV4 && l3num != NFPROTO_IPV6)
  		return -EOPNOTSUPP;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1301
  	tuple->src.l3num = l3num;
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
1302
1303
1304
1305
  	if (flags & CTA_FILTER_FLAG(CTA_IP_DST) ||
  	    flags & CTA_FILTER_FLAG(CTA_IP_SRC)) {
  		if (!tb[CTA_TUPLE_IP])
  			return -EINVAL;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1306

cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
1307
1308
1309
1310
  		err = ctnetlink_parse_tuple_ip(tb[CTA_TUPLE_IP], tuple, flags);
  		if (err < 0)
  			return err;
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1311

cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
1312
1313
1314
  	if (flags & CTA_FILTER_FLAG(CTA_PROTO_NUM)) {
  		if (!tb[CTA_TUPLE_PROTO])
  			return -EINVAL;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1315

cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
1316
1317
1318
1319
1320
1321
1322
1323
1324
  		err = ctnetlink_parse_tuple_proto(tb[CTA_TUPLE_PROTO], tuple, flags);
  		if (err < 0)
  			return err;
  	} else if (flags & CTA_FILTER_FLAG(ALL_CTA_PROTO)) {
  		/* Can't manage proto flags without a protonum  */
  		return -EINVAL;
  	}
  
  	if ((flags & CTA_FILTER_FLAG(CTA_TUPLE_ZONE)) && tb[CTA_TUPLE_ZONE]) {
deedb5903   Daniel Borkmann   netfilter: nf_con...
1325
1326
1327
1328
1329
1330
1331
1332
  		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 ...
1333
1334
1335
1336
1337
  	/* 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 ...
1338
1339
  	return 0;
  }
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
1340
1341
1342
1343
1344
1345
1346
1347
  static int
  ctnetlink_parse_tuple(const struct nlattr * const cda[],
  		      struct nf_conntrack_tuple *tuple, u32 type,
  		      u_int8_t l3num, struct nf_conntrack_zone *zone)
  {
  	return ctnetlink_parse_tuple_filter(cda, tuple, type, l3num, zone,
  					    CTA_FILTER_FLAG(ALL));
  }
d0b0268fd   Patrick McHardy   netfilter: ctnetl...
1348
  static const struct nla_policy help_nla_policy[CTA_HELP_MAX+1] = {
6d1fafcae   Florian Westphal   netfilter: ctnetl...
1349
1350
  	[CTA_HELP_NAME]		= { .type = NLA_NUL_STRING,
  				    .len = NF_CT_HELPER_NAME_LEN - 1 },
d0b0268fd   Patrick McHardy   netfilter: ctnetl...
1351
  };
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
1352
1353
  static int ctnetlink_parse_help(const struct nlattr *attr, char **helper_name,
  				struct nlattr **helpinfo)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1354
  {
130ffbc26   Daniel Borkmann   netfilter: check ...
1355
  	int err;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1356
  	struct nlattr *tb[CTA_HELP_MAX+1];
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1357

8cb081746   Johannes Berg   netlink: make val...
1358
1359
  	err = nla_parse_nested_deprecated(tb, CTA_HELP_MAX, attr,
  					  help_nla_policy, NULL);
130ffbc26   Daniel Borkmann   netfilter: check ...
1360
1361
  	if (err < 0)
  		return err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1362

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1363
  	if (!tb[CTA_HELP_NAME])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1364
  		return -EINVAL;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1365
  	*helper_name = nla_data(tb[CTA_HELP_NAME]);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1366

ae243bee3   Pablo Neira Ayuso   netfilter: ctnetl...
1367
1368
  	if (tb[CTA_HELP_INFO])
  		*helpinfo = tb[CTA_HELP_INFO];
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1369
1370
  	return 0;
  }
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
1371
  static const struct nla_policy ct_nla_policy[CTA_MAX+1] = {
d0b0268fd   Patrick McHardy   netfilter: ctnetl...
1372
1373
  	[CTA_TUPLE_ORIG]	= { .type = NLA_NESTED },
  	[CTA_TUPLE_REPLY]	= { .type = NLA_NESTED },
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
1374
  	[CTA_STATUS] 		= { .type = NLA_U32 },
d0b0268fd   Patrick McHardy   netfilter: ctnetl...
1375
1376
1377
  	[CTA_PROTOINFO]		= { .type = NLA_NESTED },
  	[CTA_HELP]		= { .type = NLA_NESTED },
  	[CTA_NAT_SRC]		= { .type = NLA_NESTED },
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
1378
1379
  	[CTA_TIMEOUT] 		= { .type = NLA_U32 },
  	[CTA_MARK]		= { .type = NLA_U32 },
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
1380
  	[CTA_ID]		= { .type = NLA_U32 },
d0b0268fd   Patrick McHardy   netfilter: ctnetl...
1381
1382
  	[CTA_NAT_DST]		= { .type = NLA_NESTED },
  	[CTA_TUPLE_MASTER]	= { .type = NLA_NESTED },
6d1fafcae   Florian Westphal   netfilter: ctnetl...
1383
1384
  	[CTA_NAT_SEQ_ADJ_ORIG]  = { .type = NLA_NESTED },
  	[CTA_NAT_SEQ_ADJ_REPLY] = { .type = NLA_NESTED },
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
1385
  	[CTA_ZONE]		= { .type = NLA_U16 },
0f298a285   Pablo Neira Ayuso   netfilter: ctnetl...
1386
  	[CTA_MARK_MASK]		= { .type = NLA_U32 },
9b21f6a90   Florian Westphal   netfilter: ctnetl...
1387
  	[CTA_LABELS]		= { .type = NLA_BINARY,
d2bf2f34c   Florian Westphal   netfilter: nft_ct...
1388
  				    .len = NF_CT_LABELS_MAX_SIZE },
9b21f6a90   Florian Westphal   netfilter: ctnetl...
1389
  	[CTA_LABELS_MASK]	= { .type = NLA_BINARY,
d2bf2f34c   Florian Westphal   netfilter: nft_ct...
1390
  				    .len = NF_CT_LABELS_MAX_SIZE },
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
1391
  	[CTA_FILTER]		= { .type = NLA_NESTED },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1392
  };
90964016e   Pablo Neira Ayuso   netfilter: nf_con...
1393
1394
1395
1396
1397
1398
1399
  static int ctnetlink_flush_iterate(struct nf_conn *ct, void *data)
  {
  	if (test_bit(IPS_OFFLOAD_BIT, &ct->status))
  		return 0;
  
  	return ctnetlink_filter_match(ct, data);
  }
866476f32   Kristian Evensen   netfilter: conntr...
1400
1401
  static int ctnetlink_flush_conntrack(struct net *net,
  				     const struct nlattr * const cda[],
59c08c69c   Kristian Evensen   netfilter: ctnetl...
1402
  				     u32 portid, int report, u8 family)
866476f32   Kristian Evensen   netfilter: conntr...
1403
1404
  {
  	struct ctnetlink_filter *filter = NULL;
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
1405
1406
1407
  	if (ctnetlink_needs_filter(family, cda)) {
  		if (cda[CTA_FILTER])
  			return -EOPNOTSUPP;
59c08c69c   Kristian Evensen   netfilter: ctnetl...
1408
  		filter = ctnetlink_alloc_filter(cda, family);
866476f32   Kristian Evensen   netfilter: conntr...
1409
1410
1411
  		if (IS_ERR(filter))
  			return PTR_ERR(filter);
  	}
90964016e   Pablo Neira Ayuso   netfilter: nf_con...
1412
  	nf_ct_iterate_cleanup_net(net, ctnetlink_flush_iterate, filter,
9fd6452d6   Florian Westphal   netfilter: conntr...
1413
  				  portid, report);
866476f32   Kristian Evensen   netfilter: conntr...
1414
1415
1416
1417
  	kfree(filter);
  
  	return 0;
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
1418
1419
1420
  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...
1421
1422
  				   const struct nlattr * const cda[],
  				   struct netlink_ext_ack *extack)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1423
1424
1425
1426
  {
  	struct nf_conntrack_tuple_hash *h;
  	struct nf_conntrack_tuple tuple;
  	struct nf_conn *ct;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
1427
  	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
308ac9143   Daniel Borkmann   netfilter: nf_con...
1428
  	struct nf_conntrack_zone zone;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
1429
1430
1431
1432
1433
  	int err;
  
  	err = ctnetlink_parse_zone(cda[CTA_ZONE], &zone);
  	if (err < 0)
  		return err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1434

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1435
  	if (cda[CTA_TUPLE_ORIG])
deedb5903   Daniel Borkmann   netfilter: nf_con...
1436
  		err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG,
e7600865d   Felix Kaechele   netfilter: ctnetl...
1437
  					    nfmsg->nfgen_family, &zone);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1438
  	else if (cda[CTA_TUPLE_REPLY])
deedb5903   Daniel Borkmann   netfilter: nf_con...
1439
  		err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY,
e7600865d   Felix Kaechele   netfilter: ctnetl...
1440
  					    nfmsg->nfgen_family, &zone);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1441
  	else {
e7600865d   Felix Kaechele   netfilter: ctnetl...
1442
  		u_int8_t u3 = nfmsg->version ? nfmsg->nfgen_family : AF_UNSPEC;
866476f32   Kristian Evensen   netfilter: conntr...
1443
1444
  		return ctnetlink_flush_conntrack(net, cda,
  						 NETLINK_CB(skb).portid,
59c08c69c   Kristian Evensen   netfilter: ctnetl...
1445
  						 nlmsg_report(nlh), u3);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1446
1447
1448
1449
  	}
  
  	if (err < 0)
  		return err;
308ac9143   Daniel Borkmann   netfilter: nf_con...
1450
  	h = nf_conntrack_find_get(net, &zone, &tuple);
9ea8cfd6a   Pablo Neira Ayuso   [NETFILTER]: ctne...
1451
  	if (!h)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1452
  		return -ENOENT;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1453
1454
  
  	ct = nf_ct_tuplehash_to_ctrack(h);
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
1455

90964016e   Pablo Neira Ayuso   netfilter: nf_con...
1456
1457
1458
1459
  	if (test_bit(IPS_OFFLOAD_BIT, &ct->status)) {
  		nf_ct_put(ct);
  		return -EBUSY;
  	}
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1460
  	if (cda[CTA_ID]) {
3c7910763   Florian Westphal   netfilter: ctnetl...
1461
1462
1463
  		__be32 id = nla_get_be32(cda[CTA_ID]);
  
  		if (id != (__force __be32)nf_ct_get_id(ct)) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1464
1465
1466
  			nf_ct_put(ct);
  			return -ENOENT;
  		}
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
1467
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1468

f330a7fdb   Florian Westphal   netfilter: conntr...
1469
  	nf_ct_delete(ct, NETLINK_CB(skb).portid, nlmsg_report(nlh));
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1470
  	nf_ct_put(ct);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1471
1472
1473
  
  	return 0;
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
1474
1475
1476
  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...
1477
1478
  				   const struct nlattr * const cda[],
  				   struct netlink_ext_ack *extack)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1479
1480
1481
1482
1483
  {
  	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...
1484
  	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1485
  	u_int8_t u3 = nfmsg->nfgen_family;
308ac9143   Daniel Borkmann   netfilter: nf_con...
1486
  	struct nf_conntrack_zone zone;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
1487
  	int err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1488

80d326fab   Pablo Neira Ayuso   netlink: add netl...
1489
1490
  	if (nlh->nlmsg_flags & NLM_F_DUMP) {
  		struct netlink_dump_control c = {
3e673b23b   Florian Westphal   netfilter: fix me...
1491
  			.start = ctnetlink_start,
80d326fab   Pablo Neira Ayuso   netlink: add netl...
1492
1493
  			.dump = ctnetlink_dump_table,
  			.done = ctnetlink_done,
3e673b23b   Florian Westphal   netfilter: fix me...
1494
  			.data = (void *)cda,
80d326fab   Pablo Neira Ayuso   netlink: add netl...
1495
  		};
866476f32   Kristian Evensen   netfilter: conntr...
1496

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

ef00f89f1   Patrick McHardy   netfilter: ctnetl...
1500
1501
1502
  	err = ctnetlink_parse_zone(cda[CTA_ZONE], &zone);
  	if (err < 0)
  		return err;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1503
  	if (cda[CTA_TUPLE_ORIG])
deedb5903   Daniel Borkmann   netfilter: nf_con...
1504
1505
  		err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG,
  					    u3, &zone);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1506
  	else if (cda[CTA_TUPLE_REPLY])
deedb5903   Daniel Borkmann   netfilter: nf_con...
1507
1508
  		err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY,
  					    u3, &zone);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1509
1510
1511
1512
1513
  	else
  		return -EINVAL;
  
  	if (err < 0)
  		return err;
308ac9143   Daniel Borkmann   netfilter: nf_con...
1514
  	h = nf_conntrack_find_get(net, &zone, &tuple);
9ea8cfd6a   Pablo Neira Ayuso   [NETFILTER]: ctne...
1515
  	if (!h)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1516
  		return -ENOENT;
9ea8cfd6a   Pablo Neira Ayuso   [NETFILTER]: ctne...
1517

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1518
1519
1520
  	ct = nf_ct_tuplehash_to_ctrack(h);
  
  	err = -ENOMEM;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
1521
1522
  	skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
  	if (skb2 == NULL) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1523
1524
1525
  		nf_ct_put(ct);
  		return -ENOMEM;
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1526

15e473046   Eric W. Biederman   netlink: Rename p...
1527
  	err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).portid, nlh->nlmsg_seq,
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
1528
  				  NFNL_MSG_TYPE(nlh->nlmsg_type), ct, true, 0);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1529
1530
1531
  	nf_ct_put(ct);
  	if (err <= 0)
  		goto free;
15e473046   Eric W. Biederman   netlink: Rename p...
1532
  	err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1533
1534
  	if (err < 0)
  		goto out;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1535
1536
1537
1538
1539
  	return 0;
  
  free:
  	kfree_skb(skb2);
  out:
f31e8d498   Pablo Neira Ayuso   netfilter: ctnetl...
1540
1541
  	/* this avoids a loop in nfnetlink. */
  	return err == -EAGAIN ? -ENOBUFS : err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1542
  }
d871befe3   Pablo Neira Ayuso   netfilter: ctnetl...
1543
1544
1545
1546
1547
1548
1549
1550
  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...
1551
  ctnetlink_dump_list(struct sk_buff *skb, struct netlink_callback *cb, bool dying)
d871befe3   Pablo Neira Ayuso   netfilter: ctnetl...
1552
  {
cd5f336f1   Florian Westphal   netfilter: ctnetl...
1553
  	struct nf_conn *ct, *last;
d871befe3   Pablo Neira Ayuso   netfilter: ctnetl...
1554
1555
1556
1557
1558
  	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...
1559
1560
1561
  	int cpu;
  	struct hlist_nulls_head *list;
  	struct net *net = sock_net(skb->sk);
d871befe3   Pablo Neira Ayuso   netfilter: ctnetl...
1562
1563
1564
  
  	if (cb->args[2])
  		return 0;
cd5f336f1   Florian Westphal   netfilter: ctnetl...
1565
  	last = (struct nf_conn *)cb->args[1];
b7779d06f   Jesper Dangaard Brouer   netfilter: conntr...
1566
1567
1568
1569
  	for (cpu = cb->args[0]; cpu < nr_cpu_ids; cpu++) {
  		struct ct_pcpu *pcpu;
  
  		if (!cpu_possible(cpu))
d871befe3   Pablo Neira Ayuso   netfilter: ctnetl...
1570
  			continue;
b7779d06f   Jesper Dangaard Brouer   netfilter: conntr...
1571
1572
1573
  
  		pcpu = per_cpu_ptr(net->ct.pcpu_lists, cpu);
  		spin_lock_bh(&pcpu->lock);
b7779d06f   Jesper Dangaard Brouer   netfilter: conntr...
1574
1575
1576
1577
1578
  		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...
1579
  				continue;
b7779d06f   Jesper Dangaard Brouer   netfilter: conntr...
1580
1581
1582
1583
1584
  			if (cb->args[1]) {
  				if (ct != last)
  					continue;
  				cb->args[1] = 0;
  			}
49ca022bc   Florian Westphal   netfilter: ctnetl...
1585
1586
1587
1588
1589
1590
1591
1592
  
  			/* We can't dump extension info for the unconfirmed
  			 * list because unconfirmed conntracks can have
  			 * ct->ext reallocated (and thus freed).
  			 *
  			 * In the dying list case ct->ext can't be free'd
  			 * until after we drop pcpu->lock.
  			 */
b7779d06f   Jesper Dangaard Brouer   netfilter: conntr...
1593
1594
1595
  			res = ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).portid,
  						  cb->nlh->nlmsg_seq,
  						  NFNL_MSG_TYPE(cb->nlh->nlmsg_type),
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
1596
  						  ct, dying ? true : false, 0);
b7779d06f   Jesper Dangaard Brouer   netfilter: conntr...
1597
  			if (res < 0) {
cd5f336f1   Florian Westphal   netfilter: ctnetl...
1598
1599
  				if (!atomic_inc_not_zero(&ct->ct_general.use))
  					continue;
266155b2d   Pablo Neira Ayuso   netfilter: ctnetl...
1600
  				cb->args[0] = cpu;
b7779d06f   Jesper Dangaard Brouer   netfilter: conntr...
1601
1602
1603
1604
  				cb->args[1] = (unsigned long)ct;
  				spin_unlock_bh(&pcpu->lock);
  				goto out;
  			}
d871befe3   Pablo Neira Ayuso   netfilter: ctnetl...
1605
  		}
b7779d06f   Jesper Dangaard Brouer   netfilter: conntr...
1606
1607
1608
  		if (cb->args[1]) {
  			cb->args[1] = 0;
  			goto restart;
266155b2d   Pablo Neira Ayuso   netfilter: ctnetl...
1609
  		}
b7779d06f   Jesper Dangaard Brouer   netfilter: conntr...
1610
  		spin_unlock_bh(&pcpu->lock);
d871befe3   Pablo Neira Ayuso   netfilter: ctnetl...
1611
  	}
266155b2d   Pablo Neira Ayuso   netfilter: ctnetl...
1612
  	cb->args[2] = 1;
d871befe3   Pablo Neira Ayuso   netfilter: ctnetl...
1613
  out:
d871befe3   Pablo Neira Ayuso   netfilter: ctnetl...
1614
1615
1616
1617
1618
1619
1620
1621
1622
  	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...
1623
  	return ctnetlink_dump_list(skb, cb, true);
d871befe3   Pablo Neira Ayuso   netfilter: ctnetl...
1624
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
1625
1626
1627
  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...
1628
1629
  				  const struct nlattr * const cda[],
  				  struct netlink_ext_ack *extack)
d871befe3   Pablo Neira Ayuso   netfilter: ctnetl...
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
  {
  	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...
1645
  	return ctnetlink_dump_list(skb, cb, false);
d871befe3   Pablo Neira Ayuso   netfilter: ctnetl...
1646
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
1647
1648
1649
  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...
1650
1651
  					const struct nlattr * const cda[],
  					struct netlink_ext_ack *extack)
d871befe3   Pablo Neira Ayuso   netfilter: ctnetl...
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
  {
  	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;
  }
4806e9757   Florian Westphal   netfilter: replac...
1663
  #if IS_ENABLED(CONFIG_NF_NAT)
bb5cf80e9   Ilpo Järvinen   [NETFILTER]: Kill...
1664
  static int
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1665
1666
  ctnetlink_parse_nat_setup(struct nf_conn *ct,
  			  enum nf_nat_manip_type manip,
399383246   Patrick McHardy   netfilter: nfnetl...
1667
  			  const struct nlattr *attr)
19f8f717f   Jules Irenge   netfilter: ctnetl...
1668
  	__must_hold(RCU)
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1669
  {
2c205dd39   Pablo Neira Ayuso   netfilter: add st...
1670
  	struct nf_nat_hook *nat_hook;
c7232c997   Patrick McHardy   netfilter: add pr...
1671
  	int err;
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1672

2c205dd39   Pablo Neira Ayuso   netfilter: add st...
1673
1674
  	nat_hook = rcu_dereference(nf_nat_hook);
  	if (!nat_hook) {
95a5afca4   Johannes Berg   net: Remove CONFI...
1675
  #ifdef CONFIG_MODULES
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1676
  		rcu_read_unlock();
c14b78e7d   Pablo Neira Ayuso   netfilter: nfnetl...
1677
  		nfnl_unlock(NFNL_SUBSYS_CTNETLINK);
c7232c997   Patrick McHardy   netfilter: add pr...
1678
  		if (request_module("nf-nat") < 0) {
c14b78e7d   Pablo Neira Ayuso   netfilter: nfnetl...
1679
  			nfnl_lock(NFNL_SUBSYS_CTNETLINK);
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1680
1681
1682
  			rcu_read_lock();
  			return -EOPNOTSUPP;
  		}
c14b78e7d   Pablo Neira Ayuso   netfilter: nfnetl...
1683
  		nfnl_lock(NFNL_SUBSYS_CTNETLINK);
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1684
  		rcu_read_lock();
c05a45c08   Florian Westphal   netfilter: ctnetl...
1685
1686
  		nat_hook = rcu_dereference(nf_nat_hook);
  		if (nat_hook)
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1687
1688
1689
1690
  			return -EAGAIN;
  #endif
  		return -EOPNOTSUPP;
  	}
2c205dd39   Pablo Neira Ayuso   netfilter: add st...
1691
  	err = nat_hook->parse_nat_setup(ct, manip, attr);
c7232c997   Patrick McHardy   netfilter: add pr...
1692
1693
1694
  	if (err == -EAGAIN) {
  #ifdef CONFIG_MODULES
  		rcu_read_unlock();
c14b78e7d   Pablo Neira Ayuso   netfilter: nfnetl...
1695
  		nfnl_unlock(NFNL_SUBSYS_CTNETLINK);
c7232c997   Patrick McHardy   netfilter: add pr...
1696
  		if (request_module("nf-nat-%u", nf_ct_l3num(ct)) < 0) {
c14b78e7d   Pablo Neira Ayuso   netfilter: nfnetl...
1697
  			nfnl_lock(NFNL_SUBSYS_CTNETLINK);
c7232c997   Patrick McHardy   netfilter: add pr...
1698
1699
1700
  			rcu_read_lock();
  			return -EOPNOTSUPP;
  		}
c14b78e7d   Pablo Neira Ayuso   netfilter: nfnetl...
1701
  		nfnl_lock(NFNL_SUBSYS_CTNETLINK);
c7232c997   Patrick McHardy   netfilter: add pr...
1702
1703
1704
1705
1706
1707
  		rcu_read_lock();
  #else
  		err = -EOPNOTSUPP;
  #endif
  	}
  	return err;
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1708
  }
67671841d   Pablo Neira Ayuso   netfilter: fix co...
1709
  #endif
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1710

53b56da83   Liping Zhang   netfilter: ctnetl...
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
  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...
1728
  static int
399383246   Patrick McHardy   netfilter: nfnetl...
1729
  ctnetlink_change_status(struct nf_conn *ct, const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1730
1731
  {
  	unsigned long d;
77236b6e3   Patrick McHardy   [NETFILTER]: ctne...
1732
  	unsigned int status = ntohl(nla_get_be32(cda[CTA_STATUS]));
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1733
1734
1735
1736
  	d = ct->status ^ status;
  
  	if (d & (IPS_EXPECTED|IPS_CONFIRMED|IPS_DYING))
  		/* unchangeable */
0adf9d674   Pablo Neira Ayuso   netfilter: ctnetl...
1737
  		return -EBUSY;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
1738

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

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

53b56da83   Liping Zhang   netfilter: ctnetl...
1747
  	__ctnetlink_change_status(ct, status, 0);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1748
1749
  	return 0;
  }
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1750
  static int
0eba801b6   Pablo Neira Ayuso   netfilter: ctnetl...
1751
  ctnetlink_setup_nat(struct nf_conn *ct, const struct nlattr * const cda[])
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1752
  {
4806e9757   Florian Westphal   netfilter: replac...
1753
  #if IS_ENABLED(CONFIG_NF_NAT)
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1754
  	int ret;
fe337ac28   Florian Westphal   netfilter: ctnetl...
1755
1756
  	if (!cda[CTA_NAT_DST] && !cda[CTA_NAT_SRC])
  		return 0;
0eba801b6   Pablo Neira Ayuso   netfilter: ctnetl...
1757
1758
1759
1760
  	ret = ctnetlink_parse_nat_setup(ct, NF_NAT_MANIP_DST,
  					cda[CTA_NAT_DST]);
  	if (ret < 0)
  		return ret;
c47d36b38   Arushi Singhal   netfilter: Merge ...
1761
1762
  	return ctnetlink_parse_nat_setup(ct, NF_NAT_MANIP_SRC,
  					 cda[CTA_NAT_SRC]);
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1763
  #else
0eba801b6   Pablo Neira Ayuso   netfilter: ctnetl...
1764
1765
  	if (!cda[CTA_NAT_DST] && !cda[CTA_NAT_SRC])
  		return 0;
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1766
1767
1768
  	return -EOPNOTSUPP;
  #endif
  }
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1769

4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
1770
1771
  static int ctnetlink_change_helper(struct nf_conn *ct,
  				   const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1772
1773
  {
  	struct nf_conntrack_helper *helper;
dc808fe28   Harald Welte   [NETFILTER] nf_co...
1774
  	struct nf_conn_help *help = nfct_help(ct);
29fe1b481   Pablo Neira Ayuso   netfilter: ctnetl...
1775
  	char *helpname = NULL;
ae243bee3   Pablo Neira Ayuso   netfilter: ctnetl...
1776
  	struct nlattr *helpinfo = NULL;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1777
  	int err;
ae243bee3   Pablo Neira Ayuso   netfilter: ctnetl...
1778
  	err = ctnetlink_parse_help(cda[CTA_HELP], &helpname, &helpinfo);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1779
1780
  	if (err < 0)
  		return err;
f95d7a46b   Kevin Cernekee   netfilter: ctnetl...
1781
1782
1783
1784
1785
1786
  	/* 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...
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
  		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...
1797
  	}
df293bbb6   Yasuyuki Kozakai   [NETFILTER]: ctne...
1798
1799
  	if (!strcmp(helpname, "")) {
  		if (help && help->helper) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1800
1801
  			/* we had a helper before ... */
  			nf_ct_remove_expectations(ct);
a9b3cd7f3   Stephen Hemminger   rcu: convert uses...
1802
  			RCU_INIT_POINTER(help->helper, NULL);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1803
  		}
df293bbb6   Yasuyuki Kozakai   [NETFILTER]: ctne...
1804
1805
  
  		return 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1806
  	}
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
1807

88be4c09d   Liping Zhang   netfilter: ctnetl...
1808
  	rcu_read_lock();
794e68716   Patrick McHardy   netfilter: ctnetl...
1809
1810
  	helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct),
  					    nf_ct_protonum(ct));
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1811
  	if (helper == NULL) {
88be4c09d   Liping Zhang   netfilter: ctnetl...
1812
  		rcu_read_unlock();
0adf9d674   Pablo Neira Ayuso   netfilter: ctnetl...
1813
  		return -EOPNOTSUPP;
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1814
  	}
df293bbb6   Yasuyuki Kozakai   [NETFILTER]: ctne...
1815

ceceae1b1   Yasuyuki Kozakai   [NETFILTER]: nf_c...
1816
  	if (help) {
ae243bee3   Pablo Neira Ayuso   netfilter: ctnetl...
1817
1818
  		if (help->helper == helper) {
  			/* update private helper data if allowed. */
7be54ca47   Pablo Neira Ayuso   netfilter: nf_ct_...
1819
  			if (helper->from_nlattr)
ae243bee3   Pablo Neira Ayuso   netfilter: ctnetl...
1820
  				helper->from_nlattr(helpinfo, ct);
88be4c09d   Liping Zhang   netfilter: ctnetl...
1821
  			err = 0;
fd7462de4   Pablo Neira Ayuso   netfilter: ctnetl...
1822
  		} else
88be4c09d   Liping Zhang   netfilter: ctnetl...
1823
1824
1825
1826
  			err = -EBUSY;
  	} else {
  		/* we cannot set a helper for an existing conntrack */
  		err = -EOPNOTSUPP;
ceceae1b1   Yasuyuki Kozakai   [NETFILTER]: nf_c...
1827
  	}
df293bbb6   Yasuyuki Kozakai   [NETFILTER]: ctne...
1828

88be4c09d   Liping Zhang   netfilter: ctnetl...
1829
1830
  	rcu_read_unlock();
  	return err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1831
  }
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
1832
1833
  static int ctnetlink_change_timeout(struct nf_conn *ct,
  				    const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1834
  {
8b1836c4b   Jay Elliott   netfilter: conntr...
1835
  	u64 timeout = (u64)ntohl(nla_get_be32(cda[CTA_TIMEOUT])) * HZ;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
1836

8b1836c4b   Jay Elliott   netfilter: conntr...
1837
1838
1839
  	if (timeout > INT_MAX)
  		timeout = INT_MAX;
  	ct->timeout = nfct_time_stamp + (u32)timeout;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1840

f330a7fdb   Florian Westphal   netfilter: conntr...
1841
1842
  	if (test_bit(IPS_DYING_BIT, &ct->status))
  		return -ETIME;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1843
1844
1845
  
  	return 0;
  }
58fc419be   Andreas Jaggi   netfilter: ctnetl...
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
  #if defined(CONFIG_NF_CONNTRACK_MARK)
  static void ctnetlink_change_mark(struct nf_conn *ct,
  				    const struct nlattr * const cda[])
  {
  	u32 mark, newmark, mask = 0;
  
  	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;
  }
  #endif
d0b0268fd   Patrick McHardy   netfilter: ctnetl...
1861
1862
1863
1864
1865
  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...
1866
1867
  static int ctnetlink_change_protoinfo(struct nf_conn *ct,
  				      const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1868
  {
399383246   Patrick McHardy   netfilter: nfnetl...
1869
  	const struct nlattr *attr = cda[CTA_PROTOINFO];
b3480fe05   Florian Westphal   netfilter: conntr...
1870
  	const struct nf_conntrack_l4proto *l4proto;
399383246   Patrick McHardy   netfilter: nfnetl...
1871
  	struct nlattr *tb[CTA_PROTOINFO_MAX+1];
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1872
  	int err = 0;
8cb081746   Johannes Berg   netlink: make val...
1873
1874
  	err = nla_parse_nested_deprecated(tb, CTA_PROTOINFO_MAX, attr,
  					  protoinfo_policy, NULL);
130ffbc26   Daniel Borkmann   netfilter: check ...
1875
1876
  	if (err < 0)
  		return err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1877

4a60dc748   Florian Westphal   netfilter: conntr...
1878
  	l4proto = nf_ct_l4proto_find(nf_ct_protonum(ct));
fdf708322   Patrick McHardy   [NETFILTER]: nfne...
1879
1880
  	if (l4proto->from_nlattr)
  		err = l4proto->from_nlattr(tb, ct);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1881
1882
1883
  
  	return err;
  }
41d73ec05   Patrick McHardy   netfilter: nf_con...
1884
1885
1886
1887
  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...
1888
  };
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
1889
1890
  static int change_seq_adj(struct nf_ct_seqadj *seq,
  			  const struct nlattr * const attr)
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1891
  {
130ffbc26   Daniel Borkmann   netfilter: check ...
1892
  	int err;
41d73ec05   Patrick McHardy   netfilter: nf_con...
1893
  	struct nlattr *cda[CTA_SEQADJ_MAX+1];
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1894

8cb081746   Johannes Berg   netlink: make val...
1895
1896
  	err = nla_parse_nested_deprecated(cda, CTA_SEQADJ_MAX, attr,
  					  seqadj_policy, NULL);
130ffbc26   Daniel Borkmann   netfilter: check ...
1897
1898
  	if (err < 0)
  		return err;
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1899

41d73ec05   Patrick McHardy   netfilter: nf_con...
1900
  	if (!cda[CTA_SEQADJ_CORRECTION_POS])
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1901
  		return -EINVAL;
41d73ec05   Patrick McHardy   netfilter: nf_con...
1902
1903
  	seq->correction_pos =
  		ntohl(nla_get_be32(cda[CTA_SEQADJ_CORRECTION_POS]));
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1904

41d73ec05   Patrick McHardy   netfilter: nf_con...
1905
  	if (!cda[CTA_SEQADJ_OFFSET_BEFORE])
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1906
  		return -EINVAL;
41d73ec05   Patrick McHardy   netfilter: nf_con...
1907
1908
  	seq->offset_before =
  		ntohl(nla_get_be32(cda[CTA_SEQADJ_OFFSET_BEFORE]));
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1909

41d73ec05   Patrick McHardy   netfilter: nf_con...
1910
  	if (!cda[CTA_SEQADJ_OFFSET_AFTER])
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1911
  		return -EINVAL;
41d73ec05   Patrick McHardy   netfilter: nf_con...
1912
1913
  	seq->offset_after =
  		ntohl(nla_get_be32(cda[CTA_SEQADJ_OFFSET_AFTER]));
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1914
1915
1916
1917
1918
  
  	return 0;
  }
  
  static int
41d73ec05   Patrick McHardy   netfilter: nf_con...
1919
1920
  ctnetlink_change_seq_adj(struct nf_conn *ct,
  			 const struct nlattr * const cda[])
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1921
  {
41d73ec05   Patrick McHardy   netfilter: nf_con...
1922
  	struct nf_conn_seqadj *seqadj = nfct_seqadj(ct);
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1923
  	int ret = 0;
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1924

41d73ec05   Patrick McHardy   netfilter: nf_con...
1925
  	if (!seqadj)
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1926
  		return 0;
64f3967c7   Liping Zhang   netfilter: ctnetl...
1927
  	spin_lock_bh(&ct->lock);
41d73ec05   Patrick McHardy   netfilter: nf_con...
1928
1929
1930
  	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...
1931
  		if (ret < 0)
64f3967c7   Liping Zhang   netfilter: ctnetl...
1932
  			goto err;
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1933

53b56da83   Liping Zhang   netfilter: ctnetl...
1934
  		set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1935
  	}
41d73ec05   Patrick McHardy   netfilter: nf_con...
1936
1937
1938
  	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...
1939
  		if (ret < 0)
64f3967c7   Liping Zhang   netfilter: ctnetl...
1940
  			goto err;
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1941

53b56da83   Liping Zhang   netfilter: ctnetl...
1942
  		set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1943
  	}
64f3967c7   Liping Zhang   netfilter: ctnetl...
1944
  	spin_unlock_bh(&ct->lock);
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1945
  	return 0;
64f3967c7   Liping Zhang   netfilter: ctnetl...
1946
1947
1948
  err:
  	spin_unlock_bh(&ct->lock);
  	return ret;
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1949
  }
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1950

20710b3b8   Pablo Neira Ayuso   netfilter: ctnetl...
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
  static const struct nla_policy synproxy_policy[CTA_SYNPROXY_MAX + 1] = {
  	[CTA_SYNPROXY_ISN]	= { .type = NLA_U32 },
  	[CTA_SYNPROXY_ITS]	= { .type = NLA_U32 },
  	[CTA_SYNPROXY_TSOFF]	= { .type = NLA_U32 },
  };
  
  static int ctnetlink_change_synproxy(struct nf_conn *ct,
  				     const struct nlattr * const cda[])
  {
  	struct nf_conn_synproxy *synproxy = nfct_synproxy(ct);
  	struct nlattr *tb[CTA_SYNPROXY_MAX + 1];
  	int err;
  
  	if (!synproxy)
  		return 0;
8cb081746   Johannes Berg   netlink: make val...
1966
1967
1968
  	err = nla_parse_nested_deprecated(tb, CTA_SYNPROXY_MAX,
  					  cda[CTA_SYNPROXY], synproxy_policy,
  					  NULL);
20710b3b8   Pablo Neira Ayuso   netfilter: ctnetl...
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
  	if (err < 0)
  		return err;
  
  	if (!tb[CTA_SYNPROXY_ISN] ||
  	    !tb[CTA_SYNPROXY_ITS] ||
  	    !tb[CTA_SYNPROXY_TSOFF])
  		return -EINVAL;
  
  	synproxy->isn = ntohl(nla_get_be32(tb[CTA_SYNPROXY_ISN]));
  	synproxy->its = ntohl(nla_get_be32(tb[CTA_SYNPROXY_ITS]));
  	synproxy->tsoff = ntohl(nla_get_be32(tb[CTA_SYNPROXY_TSOFF]));
  
  	return 0;
  }
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1983
  static int
9b21f6a90   Florian Westphal   netfilter: ctnetl...
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
  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...
2009
2010
  ctnetlink_change_conntrack(struct nf_conn *ct,
  			   const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2011
2012
  {
  	int err;
e098360f1   Pablo Neira Ayuso   netfilter: ctnetl...
2013
2014
2015
  	/* 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...
2016
  	if (cda[CTA_HELP]) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2017
2018
2019
2020
  		err = ctnetlink_change_helper(ct, cda);
  		if (err < 0)
  			return err;
  	}
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2021
  	if (cda[CTA_TIMEOUT]) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2022
2023
2024
2025
  		err = ctnetlink_change_timeout(ct, cda);
  		if (err < 0)
  			return err;
  	}
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2026
  	if (cda[CTA_STATUS]) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2027
2028
2029
2030
  		err = ctnetlink_change_status(ct, cda);
  		if (err < 0)
  			return err;
  	}
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2031
  	if (cda[CTA_PROTOINFO]) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2032
2033
2034
2035
  		err = ctnetlink_change_protoinfo(ct, cda);
  		if (err < 0)
  			return err;
  	}
bcd1e830a   Martin Josefsson   [NETFILTER]: fix ...
2036
  #if defined(CONFIG_NF_CONNTRACK_MARK)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2037
  	if (cda[CTA_MARK])
58fc419be   Andreas Jaggi   netfilter: ctnetl...
2038
  		ctnetlink_change_mark(ct, cda);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2039
  #endif
41d73ec05   Patrick McHardy   netfilter: nf_con...
2040
2041
  	if (cda[CTA_SEQ_ADJ_ORIG] || cda[CTA_SEQ_ADJ_REPLY]) {
  		err = ctnetlink_change_seq_adj(ct, cda);
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
2042
2043
2044
  		if (err < 0)
  			return err;
  	}
41d73ec05   Patrick McHardy   netfilter: nf_con...
2045

20710b3b8   Pablo Neira Ayuso   netfilter: ctnetl...
2046
2047
2048
2049
2050
  	if (cda[CTA_SYNPROXY]) {
  		err = ctnetlink_change_synproxy(ct, cda);
  		if (err < 0)
  			return err;
  	}
9b21f6a90   Florian Westphal   netfilter: ctnetl...
2051
2052
2053
2054
2055
  	if (cda[CTA_LABELS]) {
  		err = ctnetlink_attach_labels(ct, cda);
  		if (err < 0)
  			return err;
  	}
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
2056

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2057
2058
  	return 0;
  }
f0a3c0869   Pablo Neira Ayuso   netfilter: ctnetl...
2059
  static struct nf_conn *
308ac9143   Daniel Borkmann   netfilter: nf_con...
2060
2061
  ctnetlink_create_conntrack(struct net *net,
  			   const struct nf_conntrack_zone *zone,
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
2062
  			   const struct nlattr * const cda[],
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2063
  			   struct nf_conntrack_tuple *otuple,
5faa1f4cb   Pablo Neira Ayuso   [NETFILTER]: nf_c...
2064
  			   struct nf_conntrack_tuple *rtuple,
7ec474967   Pablo Neira Ayuso   netfilter: ctnetl...
2065
  			   u8 u3)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2066
2067
2068
  {
  	struct nf_conn *ct;
  	int err = -EINVAL;
ceceae1b1   Yasuyuki Kozakai   [NETFILTER]: nf_c...
2069
  	struct nf_conntrack_helper *helper;
315c34dae   Pablo Neira Ayuso   netfilter: ctnetl...
2070
  	struct nf_conn_tstamp *tstamp;
8b1836c4b   Jay Elliott   netfilter: conntr...
2071
  	u64 timeout;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2072

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

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

8b1836c4b   Jay Elliott   netfilter: conntr...
2080
2081
2082
2083
  	timeout = (u64)ntohl(nla_get_be32(cda[CTA_TIMEOUT])) * HZ;
  	if (timeout > INT_MAX)
  		timeout = INT_MAX;
  	ct->timeout = (u32)timeout + nfct_time_stamp;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2084

1575e7ea0   Pablo Neira Ayuso   netfilter: ctnetl...
2085
  	rcu_read_lock();
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
2086
   	if (cda[CTA_HELP]) {
29fe1b481   Pablo Neira Ayuso   netfilter: ctnetl...
2087
  		char *helpname = NULL;
ae243bee3   Pablo Neira Ayuso   netfilter: ctnetl...
2088
2089
2090
  		struct nlattr *helpinfo = NULL;
  
  		err = ctnetlink_parse_help(cda[CTA_HELP], &helpname, &helpinfo);
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
2091
2092
   		if (err < 0)
  			goto err2;
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
2093

794e68716   Patrick McHardy   netfilter: ctnetl...
2094
2095
  		helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct),
  						    nf_ct_protonum(ct));
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
2096
2097
2098
2099
2100
  		if (helper == NULL) {
  			rcu_read_unlock();
  #ifdef CONFIG_MODULES
  			if (request_module("nfct-helper-%s", helpname) < 0) {
  				err = -EOPNOTSUPP;
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
2101
  				goto err1;
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
2102
2103
2104
  			}
  
  			rcu_read_lock();
794e68716   Patrick McHardy   netfilter: ctnetl...
2105
2106
2107
  			helper = __nf_conntrack_helper_find(helpname,
  							    nf_ct_l3num(ct),
  							    nf_ct_protonum(ct));
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
2108
  			if (helper) {
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
2109
  				err = -EAGAIN;
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
2110
  				goto err2;
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
2111
2112
2113
2114
  			}
  			rcu_read_unlock();
  #endif
  			err = -EOPNOTSUPP;
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
2115
  			goto err1;
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
2116
2117
  		} else {
  			struct nf_conn_help *help;
440534d3c   Gao Feng   netfilter: Remove...
2118
  			help = nf_ct_helper_ext_add(ct, GFP_ATOMIC);
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
2119
  			if (help == NULL) {
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
2120
  				err = -ENOMEM;
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
2121
  				goto err2;
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
2122
  			}
ae243bee3   Pablo Neira Ayuso   netfilter: ctnetl...
2123
  			/* set private helper data if allowed. */
7be54ca47   Pablo Neira Ayuso   netfilter: nf_ct_...
2124
  			if (helper->from_nlattr)
ae243bee3   Pablo Neira Ayuso   netfilter: ctnetl...
2125
  				helper->from_nlattr(helpinfo, ct);
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
2126
2127
  
  			/* not in hash table yet so not strictly necessary */
a9b3cd7f3   Stephen Hemminger   rcu: convert uses...
2128
  			RCU_INIT_POINTER(help->helper, helper);
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
2129
2130
2131
  		}
  	} else {
  		/* try an implicit helper assignation */
b2a15a604   Patrick McHardy   netfilter: nf_con...
2132
  		err = __nf_ct_try_assign_helper(ct, NULL, GFP_ATOMIC);
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
2133
2134
  		if (err < 0)
  			goto err2;
1575e7ea0   Pablo Neira Ayuso   netfilter: ctnetl...
2135
  	}
0eba801b6   Pablo Neira Ayuso   netfilter: ctnetl...
2136
2137
2138
  	err = ctnetlink_setup_nat(ct, cda);
  	if (err < 0)
  		goto err2;
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
2139

a88e22adf   Pablo Neira Ayuso   netfilter: ctnetl...
2140
  	nf_ct_acct_ext_add(ct, GFP_ATOMIC);
a992ca2a0   Pablo Neira Ayuso   netfilter: nf_con...
2141
  	nf_ct_tstamp_ext_add(ct, GFP_ATOMIC);
a88e22adf   Pablo Neira Ayuso   netfilter: ctnetl...
2142
  	nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC);
c539f0171   Florian Westphal   netfilter: add co...
2143
  	nf_ct_labels_ext_add(ct);
87e94dbc2   Eric Leblond   netfilter: synpro...
2144
2145
  	nfct_seqadj_ext_add(ct);
  	nfct_synproxy_ext_add(ct);
c539f0171   Florian Westphal   netfilter: add co...
2146

a88e22adf   Pablo Neira Ayuso   netfilter: ctnetl...
2147
2148
2149
2150
2151
  	/* 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...
2152
2153
  		if (err < 0)
  			goto err2;
bbb3357d1   Pablo Neira Ayuso   [NETFILTER]: ctne...
2154
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2155

41d73ec05   Patrick McHardy   netfilter: nf_con...
2156
2157
  	if (cda[CTA_SEQ_ADJ_ORIG] || cda[CTA_SEQ_ADJ_REPLY]) {
  		err = ctnetlink_change_seq_adj(ct, cda);
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
2158
2159
  		if (err < 0)
  			goto err2;
c969aa7d2   Pablo Neira Ayuso   netfilter: ctnetl...
2160
  	}
c969aa7d2   Pablo Neira Ayuso   netfilter: ctnetl...
2161

e5fc9e7a6   Changli Gao   netfilter: nf_con...
2162
  	memset(&ct->proto, 0, sizeof(ct->proto));
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2163
  	if (cda[CTA_PROTOINFO]) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2164
  		err = ctnetlink_change_protoinfo(ct, cda);
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
2165
2166
  		if (err < 0)
  			goto err2;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2167
  	}
20710b3b8   Pablo Neira Ayuso   netfilter: ctnetl...
2168
2169
2170
2171
2172
  	if (cda[CTA_SYNPROXY]) {
  		err = ctnetlink_change_synproxy(ct, cda);
  		if (err < 0)
  			goto err2;
  	}
bcd1e830a   Martin Josefsson   [NETFILTER]: fix ...
2173
  #if defined(CONFIG_NF_CONNTRACK_MARK)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2174
  	if (cda[CTA_MARK])
58fc419be   Andreas Jaggi   netfilter: ctnetl...
2175
  		ctnetlink_change_mark(ct, cda);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2176
  #endif
5faa1f4cb   Pablo Neira Ayuso   [NETFILTER]: nf_c...
2177
  	/* setup master conntrack: this is a confirmed expectation */
7ec474967   Pablo Neira Ayuso   netfilter: ctnetl...
2178
2179
2180
2181
  	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...
2182
2183
  		err = ctnetlink_parse_tuple(cda, &master, CTA_TUPLE_MASTER,
  					    u3, NULL);
7ec474967   Pablo Neira Ayuso   netfilter: ctnetl...
2184
  		if (err < 0)
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
2185
  			goto err2;
7ec474967   Pablo Neira Ayuso   netfilter: ctnetl...
2186

ef00f89f1   Patrick McHardy   netfilter: ctnetl...
2187
  		master_h = nf_conntrack_find_get(net, zone, &master);
7ec474967   Pablo Neira Ayuso   netfilter: ctnetl...
2188
2189
  		if (master_h == NULL) {
  			err = -ENOENT;
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
2190
  			goto err2;
7ec474967   Pablo Neira Ayuso   netfilter: ctnetl...
2191
2192
  		}
  		master_ct = nf_ct_tuplehash_to_ctrack(master_h);
f2a89004d   Pablo Neira Ayuso   [NETFILTER]: ctne...
2193
  		__set_bit(IPS_EXPECTED_BIT, &ct->status);
5faa1f4cb   Pablo Neira Ayuso   [NETFILTER]: nf_c...
2194
  		ct->master = master_ct;
f2a89004d   Pablo Neira Ayuso   [NETFILTER]: ctne...
2195
  	}
315c34dae   Pablo Neira Ayuso   netfilter: ctnetl...
2196
2197
  	tstamp = nf_conn_tstamp_find(ct);
  	if (tstamp)
d2de875c6   Eric Dumazet   net: use ktime_ge...
2198
  		tstamp->start = ktime_get_real_ns();
5faa1f4cb   Pablo Neira Ayuso   [NETFILTER]: nf_c...
2199

7d367e066   Jozsef Kadlecsik   netfilter: ctnetl...
2200
2201
2202
  	err = nf_conntrack_hash_check_insert(ct);
  	if (err < 0)
  		goto err2;
58a3c9bb0   Patrick McHardy   [NETFILTER]: nf_c...
2203
  	rcu_read_unlock();
dafc741cf   Yasuyuki Kozakai   [NETFILTER]: nfct...
2204

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

0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
2207
2208
2209
  err2:
  	rcu_read_unlock();
  err1:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2210
  	nf_conntrack_free(ct);
f0a3c0869   Pablo Neira Ayuso   netfilter: ctnetl...
2211
  	return ERR_PTR(err);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2212
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
2213
2214
2215
  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...
2216
2217
  				   const struct nlattr * const cda[],
  				   struct netlink_ext_ack *extack)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2218
2219
2220
  {
  	struct nf_conntrack_tuple otuple, rtuple;
  	struct nf_conntrack_tuple_hash *h = NULL;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2221
  	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
7d367e066   Jozsef Kadlecsik   netfilter: ctnetl...
2222
  	struct nf_conn *ct;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2223
  	u_int8_t u3 = nfmsg->nfgen_family;
308ac9143   Daniel Borkmann   netfilter: nf_con...
2224
  	struct nf_conntrack_zone zone;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
2225
2226
2227
2228
2229
  	int err;
  
  	err = ctnetlink_parse_zone(cda[CTA_ZONE], &zone);
  	if (err < 0)
  		return err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2230

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2231
  	if (cda[CTA_TUPLE_ORIG]) {
deedb5903   Daniel Borkmann   netfilter: nf_con...
2232
2233
  		err = ctnetlink_parse_tuple(cda, &otuple, CTA_TUPLE_ORIG,
  					    u3, &zone);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2234
2235
2236
  		if (err < 0)
  			return err;
  	}
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2237
  	if (cda[CTA_TUPLE_REPLY]) {
deedb5903   Daniel Borkmann   netfilter: nf_con...
2238
2239
  		err = ctnetlink_parse_tuple(cda, &rtuple, CTA_TUPLE_REPLY,
  					    u3, &zone);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2240
2241
2242
  		if (err < 0)
  			return err;
  	}
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2243
  	if (cda[CTA_TUPLE_ORIG])
308ac9143   Daniel Borkmann   netfilter: nf_con...
2244
  		h = nf_conntrack_find_get(net, &zone, &otuple);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2245
  	else if (cda[CTA_TUPLE_REPLY])
308ac9143   Daniel Borkmann   netfilter: nf_con...
2246
  		h = nf_conntrack_find_get(net, &zone, &rtuple);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2247
2248
  
  	if (h == NULL) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2249
  		err = -ENOENT;
f0a3c0869   Pablo Neira Ayuso   netfilter: ctnetl...
2250
  		if (nlh->nlmsg_flags & NLM_F_CREATE) {
fecc1133b   Pablo Neira Ayuso   netfilter: ctnetl...
2251
  			enum ip_conntrack_events events;
5faa1f4cb   Pablo Neira Ayuso   [NETFILTER]: nf_c...
2252

442fad942   Florian Westphal   netfilter: ctnetl...
2253
2254
  			if (!cda[CTA_TUPLE_ORIG] || !cda[CTA_TUPLE_REPLY])
  				return -EINVAL;
aa0c2c68a   Liping Zhang   netfilter: ctnetl...
2255
2256
  			if (otuple.dst.protonum != rtuple.dst.protonum)
  				return -EINVAL;
442fad942   Florian Westphal   netfilter: ctnetl...
2257

308ac9143   Daniel Borkmann   netfilter: nf_con...
2258
  			ct = ctnetlink_create_conntrack(net, &zone, cda, &otuple,
f0a3c0869   Pablo Neira Ayuso   netfilter: ctnetl...
2259
  							&rtuple, u3);
7d367e066   Jozsef Kadlecsik   netfilter: ctnetl...
2260
2261
  			if (IS_ERR(ct))
  				return PTR_ERR(ct);
f0a3c0869   Pablo Neira Ayuso   netfilter: ctnetl...
2262
  			err = 0;
fecc1133b   Pablo Neira Ayuso   netfilter: ctnetl...
2263
  			if (test_bit(IPS_EXPECTED_BIT, &ct->status))
97aae0df1   Liping Zhang   netfilter: ctnetl...
2264
  				events = 1 << IPCT_RELATED;
fecc1133b   Pablo Neira Ayuso   netfilter: ctnetl...
2265
  			else
97aae0df1   Liping Zhang   netfilter: ctnetl...
2266
  				events = 1 << IPCT_NEW;
fecc1133b   Pablo Neira Ayuso   netfilter: ctnetl...
2267

9b21f6a90   Florian Westphal   netfilter: ctnetl...
2268
2269
2270
  			if (cda[CTA_LABELS] &&
  			    ctnetlink_attach_labels(ct, cda) == 0)
  				events |= (1 << IPCT_LABEL);
858b31330   Patrick McHardy   netfilter: nf_con...
2271
2272
  			nf_conntrack_eventmask_report((1 << IPCT_REPLY) |
  						      (1 << IPCT_ASSURED) |
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
2273
2274
  						      (1 << IPCT_HELPER) |
  						      (1 << IPCT_PROTOINFO) |
41d73ec05   Patrick McHardy   netfilter: nf_con...
2275
  						      (1 << IPCT_SEQADJ) |
20710b3b8   Pablo Neira Ayuso   netfilter: ctnetl...
2276
2277
2278
  						      (1 << IPCT_MARK) |
  						      (1 << IPCT_SYNPROXY) |
  						      events,
15e473046   Eric W. Biederman   netlink: Rename p...
2279
  						      ct, NETLINK_CB(skb).portid,
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
2280
  						      nlmsg_report(nlh));
f0a3c0869   Pablo Neira Ayuso   netfilter: ctnetl...
2281
  			nf_ct_put(ct);
7d367e066   Jozsef Kadlecsik   netfilter: ctnetl...
2282
  		}
5faa1f4cb   Pablo Neira Ayuso   [NETFILTER]: nf_c...
2283

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2284
2285
2286
  		return err;
  	}
  	/* implicit 'else' */
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2287
  	err = -EEXIST;
7d367e066   Jozsef Kadlecsik   netfilter: ctnetl...
2288
  	ct = nf_ct_tuplehash_to_ctrack(h);
ff4ca8273   Pablo Neira Ayuso   [NETFILTER]: ctne...
2289
  	if (!(nlh->nlmsg_flags & NLM_F_EXCL)) {
19abb7b09   Pablo Neira Ayuso   netfilter: ctnetl...
2290
2291
  		err = ctnetlink_change_conntrack(ct, cda);
  		if (err == 0) {
858b31330   Patrick McHardy   netfilter: nf_con...
2292
2293
  			nf_conntrack_eventmask_report((1 << IPCT_REPLY) |
  						      (1 << IPCT_ASSURED) |
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
2294
  						      (1 << IPCT_HELPER) |
797a7d66d   Florian Westphal   netfilter: ctnetl...
2295
  						      (1 << IPCT_LABEL) |
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
2296
  						      (1 << IPCT_PROTOINFO) |
41d73ec05   Patrick McHardy   netfilter: nf_con...
2297
  						      (1 << IPCT_SEQADJ) |
20710b3b8   Pablo Neira Ayuso   netfilter: ctnetl...
2298
2299
  						      (1 << IPCT_MARK) |
  						      (1 << IPCT_SYNPROXY),
15e473046   Eric W. Biederman   netlink: Rename p...
2300
  						      ct, NETLINK_CB(skb).portid,
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
2301
  						      nlmsg_report(nlh));
7d367e066   Jozsef Kadlecsik   netfilter: ctnetl...
2302
  		}
ff4ca8273   Pablo Neira Ayuso   [NETFILTER]: ctne...
2303
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2304

7d367e066   Jozsef Kadlecsik   netfilter: ctnetl...
2305
  	nf_ct_put(ct);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2306
2307
  	return err;
  }
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
2308
  static int
15e473046   Eric W. Biederman   netlink: Rename p...
2309
  ctnetlink_ct_stat_cpu_fill_info(struct sk_buff *skb, u32 portid, u32 seq,
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
2310
2311
2312
2313
  				__u16 cpu, const struct ip_conntrack_stat *st)
  {
  	struct nlmsghdr *nlh;
  	struct nfgenmsg *nfmsg;
15e473046   Eric W. Biederman   netlink: Rename p...
2314
  	unsigned int flags = portid ? NLM_F_MULTI : 0, event;
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
2315

dedb67c4b   Pablo Neira Ayuso   netfilter: Add nf...
2316
2317
  	event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK,
  			      IPCTNL_MSG_CT_GET_STATS_CPU);
15e473046   Eric W. Biederman   netlink: Rename p...
2318
  	nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
2319
2320
2321
2322
2323
2324
2325
  	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...
2326
  	if (nla_put_be32(skb, CTA_STATS_FOUND, htonl(st->found)) ||
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
2327
  	    nla_put_be32(skb, CTA_STATS_INVALID, htonl(st->invalid)) ||
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
2328
2329
2330
2331
2332
2333
2334
  	    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,
bc9247041   Florian Westphal   netfilter: conntr...
2335
2336
2337
  				htonl(st->search_restart)) ||
  	    nla_put_be32(skb, CTA_STATS_CLASH_RESOLVE,
  				htonl(st->clash_resolve)))
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
  		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...
2366
  						    NETLINK_CB(cb->skb).portid,
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
2367
2368
2369
2370
2371
2372
2373
2374
  						    cb->nlh->nlmsg_seq,
  						    cpu, st) < 0)
  				break;
  	}
  	cb->args[0] = cpu;
  
  	return skb->len;
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
2375
2376
2377
  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...
2378
2379
  				 const struct nlattr * const cda[],
  				 struct netlink_ext_ack *extack)
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
  {
  	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...
2392
  ctnetlink_stat_ct_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
2393
2394
2395
2396
  			    struct net *net)
  {
  	struct nlmsghdr *nlh;
  	struct nfgenmsg *nfmsg;
15e473046   Eric W. Biederman   netlink: Rename p...
2397
  	unsigned int flags = portid ? NLM_F_MULTI : 0, event;
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
2398
  	unsigned int nr_conntracks = atomic_read(&net->ct.count);
dedb67c4b   Pablo Neira Ayuso   netfilter: Add nf...
2399
  	event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET_STATS);
15e473046   Eric W. Biederman   netlink: Rename p...
2400
  	nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
  	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;
538c5672b   Florent Fourcot   netfilter: ctnetl...
2411
2412
  	if (nla_put_be32(skb, CTA_STATS_GLOBAL_MAX_ENTRIES, htonl(nf_conntrack_max)))
  		goto nla_put_failure;
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
2413
2414
2415
2416
2417
2418
2419
2420
  	nlmsg_end(skb, nlh);
  	return skb->len;
  
  nla_put_failure:
  nlmsg_failure:
  	nlmsg_cancel(skb, nlh);
  	return -1;
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
2421
2422
  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...
2423
2424
  			     const struct nlattr * const cda[],
  			     struct netlink_ext_ack *extack)
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
2425
2426
2427
2428
2429
2430
2431
  {
  	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...
2432
  	err = ctnetlink_stat_ct_fill_info(skb2, NETLINK_CB(skb).portid,
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
2433
2434
2435
2436
2437
  					  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...
2438
  	err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT);
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
  	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...
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
  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...
2470
  #ifdef CONFIG_NETFILTER_NETLINK_GLUE_CT
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2471
  static size_t
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2472
  ctnetlink_glue_build_size(const struct nf_conn *ct)
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
  {
  	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)
4806e9757   Florian Westphal   netfilter: replac...
2485
  #if IS_ENABLED(CONFIG_NF_NAT)
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2486
2487
2488
2489
2490
2491
  	       + 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...
2492
  #ifdef CONFIG_NF_CONNTRACK_ZONES
deedb5903   Daniel Borkmann   netfilter: nf_con...
2493
  	       + nla_total_size(sizeof(u_int16_t)) /* CTA_ZONE|CTA_TUPLE_ZONE */
4a001068d   Ken-ichirou MATSUZAWA   netfilter: ctnetl...
2494
  #endif
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2495
2496
2497
  	       + ctnetlink_proto_size(ct)
  	       ;
  }
224a05975   Ken-ichirou MATSUZAWA   netfilter: ctnetl...
2498
  static struct nf_conn *ctnetlink_glue_get_ct(const struct sk_buff *skb,
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2499
  					     enum ip_conntrack_info *ctinfo)
b7bd1809e   Pablo Neira Ayuso   netfilter: nfnetl...
2500
  {
ab8bc7ed8   Florian Westphal   netfilter: remove...
2501
  	return nf_ct_get(skb, ctinfo);
b7bd1809e   Pablo Neira Ayuso   netfilter: nfnetl...
2502
  }
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2503
  static int __ctnetlink_glue_build(struct sk_buff *skb, struct nf_conn *ct)
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2504
  {
308ac9143   Daniel Borkmann   netfilter: nf_con...
2505
  	const struct nf_conntrack_zone *zone;
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2506
  	struct nlattr *nest_parms;
deedb5903   Daniel Borkmann   netfilter: nf_con...
2507
  	zone = nf_ct_zone(ct);
ae0be8de9   Michal Kubecek   netlink: make nla...
2508
  	nest_parms = nla_nest_start(skb, CTA_TUPLE_ORIG);
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2509
2510
2511
2512
  	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...
2513
2514
2515
  	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...
2516
  	nla_nest_end(skb, nest_parms);
ae0be8de9   Michal Kubecek   netlink: make nla...
2517
  	nest_parms = nla_nest_start(skb, CTA_TUPLE_REPLY);
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2518
2519
2520
2521
  	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...
2522
2523
2524
  	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...
2525
  	nla_nest_end(skb, nest_parms);
deedb5903   Daniel Borkmann   netfilter: nf_con...
2526
2527
  	if (ctnetlink_dump_zone_id(skb, CTA_ZONE, zone,
  				   NF_CT_DEFAULT_ZONE_DIR) < 0)
308ac9143   Daniel Borkmann   netfilter: nf_con...
2528
  		goto nla_put_failure;
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
  
  	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...
2553
  	    ctnetlink_dump_ct_seq_adj(skb, ct) < 0)
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2554
  		goto nla_put_failure;
20710b3b8   Pablo Neira Ayuso   netfilter: ctnetl...
2555
2556
  	if (ctnetlink_dump_ct_synproxy(skb, ct) < 0)
  		goto nla_put_failure;
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2557
2558
2559
2560
  #ifdef CONFIG_NF_CONNTRACK_MARK
  	if (ct->mark && ctnetlink_dump_mark(skb, ct) < 0)
  		goto nla_put_failure;
  #endif
0ceabd838   Florian Westphal   netfilter: ctnetl...
2561
2562
  	if (ctnetlink_dump_labels(skb, ct) < 0)
  		goto nla_put_failure;
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2563
2564
2565
  	return 0;
  
  nla_put_failure:
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2566
2567
2568
2569
  	return -ENOSPC;
  }
  
  static int
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2570
2571
2572
  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...
2573
2574
  {
  	struct nlattr *nest_parms;
ae0be8de9   Michal Kubecek   netlink: make nla...
2575
  	nest_parms = nla_nest_start(skb, ct_attr);
b7bd1809e   Pablo Neira Ayuso   netfilter: nfnetl...
2576
2577
  	if (!nest_parms)
  		goto nla_put_failure;
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2578
  	if (__ctnetlink_glue_build(skb, ct) < 0)
b7bd1809e   Pablo Neira Ayuso   netfilter: nfnetl...
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
  		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...
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
  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...
2609
2610
  	 * 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...
2611
  	 */
53b56da83   Liping Zhang   netfilter: ctnetl...
2612
  	__ctnetlink_change_status(ct, status, ~status);
a963d710f   Kevin Cernekee   netfilter: ctnetl...
2613
2614
2615
2616
  	return 0;
  }
  
  static int
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2617
  ctnetlink_glue_parse_ct(const struct nlattr *cda[], struct nf_conn *ct)
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2618
2619
2620
2621
2622
2623
2624
2625
2626
  {
  	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...
2627
  		err = ctnetlink_update_status(ct, cda);
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2628
2629
2630
2631
2632
2633
2634
2635
  		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...
2636
2637
2638
2639
2640
  	if (cda[CTA_LABELS]) {
  		err = ctnetlink_attach_labels(ct, cda);
  		if (err < 0)
  			return err;
  	}
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2641
  #if defined(CONFIG_NF_CONNTRACK_MARK)
534473c60   Florian Westphal   netfilter: ctnetl...
2642
  	if (cda[CTA_MARK]) {
58fc419be   Andreas Jaggi   netfilter: ctnetl...
2643
  		ctnetlink_change_mark(ct, cda);
534473c60   Florian Westphal   netfilter: ctnetl...
2644
  	}
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2645
2646
2647
2648
2649
  #endif
  	return 0;
  }
  
  static int
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2650
  ctnetlink_glue_parse(const struct nlattr *attr, struct nf_conn *ct)
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2651
2652
  {
  	struct nlattr *cda[CTA_MAX+1];
68e035c95   Pablo Neira Ayuso   netfilter: ctnetl...
2653
  	int ret;
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2654

8cb081746   Johannes Berg   netlink: make val...
2655
2656
  	ret = nla_parse_nested_deprecated(cda, CTA_MAX, attr, ct_nla_policy,
  					  NULL);
130ffbc26   Daniel Borkmann   netfilter: check ...
2657
2658
  	if (ret < 0)
  		return ret;
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2659

88be4c09d   Liping Zhang   netfilter: ctnetl...
2660
  	return ctnetlink_glue_parse_ct((const struct nlattr **)cda, ct);
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2661
  }
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2662
2663
2664
2665
  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...
2666
2667
2668
2669
  {
  	int err;
  
  	err = ctnetlink_parse_tuple(cda, tuple, CTA_EXPECT_TUPLE,
deedb5903   Daniel Borkmann   netfilter: nf_con...
2670
  				    nf_ct_l3num(ct), NULL);
bd0779370   Pablo Neira Ayuso   netfilter: nfnetl...
2671
2672
2673
2674
  	if (err < 0)
  		return err;
  
  	return ctnetlink_parse_tuple(cda, mask, CTA_EXPECT_MASK,
deedb5903   Daniel Borkmann   netfilter: nf_con...
2675
  				     nf_ct_l3num(ct), NULL);
bd0779370   Pablo Neira Ayuso   netfilter: nfnetl...
2676
2677
2678
  }
  
  static int
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2679
2680
  ctnetlink_glue_attach_expect(const struct nlattr *attr, struct nf_conn *ct,
  			     u32 portid, u32 report)
bd0779370   Pablo Neira Ayuso   netfilter: nfnetl...
2681
2682
2683
  {
  	struct nlattr *cda[CTA_EXPECT_MAX+1];
  	struct nf_conntrack_tuple tuple, mask;
b7e092c05   Florian Westphal   netfilter: ctnetl...
2684
  	struct nf_conntrack_helper *helper = NULL;
bd0779370   Pablo Neira Ayuso   netfilter: nfnetl...
2685
2686
  	struct nf_conntrack_expect *exp;
  	int err;
8cb081746   Johannes Berg   netlink: make val...
2687
2688
  	err = nla_parse_nested_deprecated(cda, CTA_EXPECT_MAX, attr,
  					  exp_nla_policy, NULL);
bd0779370   Pablo Neira Ayuso   netfilter: nfnetl...
2689
2690
  	if (err < 0)
  		return err;
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2691
2692
  	err = ctnetlink_glue_exp_parse((const struct nlattr * const *)cda,
  				       ct, &tuple, &mask);
bd0779370   Pablo Neira Ayuso   netfilter: nfnetl...
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
  	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);
3c00fb0bf   xiao ruizhu   netfilter: nf_con...
2709
  	err = nf_ct_expect_related_report(exp, portid, report, 0);
b18bcb001   Liping Zhang   netfilter: nfnetl...
2710
2711
  	nf_ct_expect_put(exp);
  	return err;
bd0779370   Pablo Neira Ayuso   netfilter: nfnetl...
2712
  }
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2713
2714
  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...
2715
2716
2717
2718
2719
2720
  {
  	if (!(ct->status & IPS_NAT_MASK))
  		return;
  
  	nf_ct_tcp_seqadj_set(skb, ct, ctinfo, diff);
  }
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2721
2722
2723
2724
2725
2726
2727
  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...
2728
  };
83f3e94d3   Ken-ichirou MATSUZAWA   netfilter: Kconfi...
2729
  #endif /* CONFIG_NETFILTER_NETLINK_GLUE_CT */
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2730

601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2731
2732
2733
  /***********************************************************************
   * EXPECT
   ***********************************************************************/
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2734

4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
2735
2736
  static int ctnetlink_exp_dump_tuple(struct sk_buff *skb,
  				    const struct nf_conntrack_tuple *tuple,
a2b7cbdd2   Matthias Kaehlcke   netfilter: ctnetl...
2737
  				    u32 type)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2738
  {
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2739
  	struct nlattr *nest_parms;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2740

ae0be8de9   Michal Kubecek   netlink: make nla...
2741
  	nest_parms = nla_nest_start(skb, type);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2742
2743
  	if (!nest_parms)
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2744
  	if (ctnetlink_dump_tuples(skb, tuple) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2745
2746
  		goto nla_put_failure;
  	nla_nest_end(skb, nest_parms);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2747
2748
  
  	return 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2749
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2750
  	return -1;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2751
  }
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2752

4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
2753
2754
2755
  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...
2756
  {
b3480fe05   Florian Westphal   netfilter: conntr...
2757
  	const struct nf_conntrack_l4proto *l4proto;
d4156e8cd   Patrick McHardy   [NETFILTER]: nf_c...
2758
  	struct nf_conntrack_tuple m;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2759
  	struct nlattr *nest_parms;
b3480fe05   Florian Westphal   netfilter: conntr...
2760
  	int ret;
d4156e8cd   Patrick McHardy   [NETFILTER]: nf_c...
2761
2762
  
  	memset(&m, 0xFF, sizeof(m));
d4156e8cd   Patrick McHardy   [NETFILTER]: nf_c...
2763
  	memcpy(&m.src.u3, &mask->src.u3, sizeof(m.src.u3));
e578756c3   Patrick McHardy   netfilter: ctnetl...
2764
2765
  	m.src.u.all = mask->src.u.all;
  	m.dst.protonum = tuple->dst.protonum;
d4156e8cd   Patrick McHardy   [NETFILTER]: nf_c...
2766

ae0be8de9   Michal Kubecek   netlink: make nla...
2767
  	nest_parms = nla_nest_start(skb, CTA_EXPECT_MASK);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2768
2769
  	if (!nest_parms)
  		goto nla_put_failure;
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
2770

3b988ece9   Hans Schillstrom   netfilter: ctnetl...
2771
  	rcu_read_lock();
f957be9d3   Florian Westphal   netfilter: conntr...
2772
  	ret = ctnetlink_dump_tuples_ip(skb, &m);
3b988ece9   Hans Schillstrom   netfilter: ctnetl...
2773
  	if (ret >= 0) {
4a60dc748   Florian Westphal   netfilter: conntr...
2774
  		l4proto = nf_ct_l4proto_find(tuple->dst.protonum);
48ab807c7   Colin Ian King   netfilter: conntr...
2775
  		ret = ctnetlink_dump_tuples_proto(skb, &m, l4proto);
3b988ece9   Hans Schillstrom   netfilter: ctnetl...
2776
2777
  	}
  	rcu_read_unlock();
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
2778
  	if (unlikely(ret < 0))
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2779
  		goto nla_put_failure;
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
2780

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2781
  	nla_nest_end(skb, nest_parms);
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
2782
2783
  
  	return 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2784
  nla_put_failure:
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
2785
2786
  	return -1;
  }
c7232c997   Patrick McHardy   netfilter: add pr...
2787
  static const union nf_inet_addr any_addr;
3c7910763   Florian Westphal   netfilter: ctnetl...
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
  static __be32 nf_expect_get_id(const struct nf_conntrack_expect *exp)
  {
  	static __read_mostly siphash_key_t exp_id_seed;
  	unsigned long a, b, c, d;
  
  	net_get_random_once(&exp_id_seed, sizeof(exp_id_seed));
  
  	a = (unsigned long)exp;
  	b = (unsigned long)exp->helper;
  	c = (unsigned long)exp->master;
  	d = (unsigned long)siphash(&exp->tuple, sizeof(exp->tuple), &exp_id_seed);
  
  #ifdef CONFIG_64BIT
  	return (__force __be32)siphash_4u64((u64)a, (u64)b, (u64)c, (u64)d, &exp_id_seed);
  #else
  	return (__force __be32)siphash_4u32((u32)a, (u32)b, (u32)c, (u32)d, &exp_id_seed);
  #endif
  }
bb5cf80e9   Ilpo Järvinen   [NETFILTER]: Kill...
2806
  static int
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2807
  ctnetlink_exp_dump_expect(struct sk_buff *skb,
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2808
  			  const struct nf_conntrack_expect *exp)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2809
2810
  {
  	struct nf_conn *master = exp->master;
c12163827   Xi Wang   netfilter: ctnetl...
2811
  	long timeout = ((long)exp->timeout.expires - (long)jiffies) / HZ;
bc01befdc   Pablo Neira Ayuso   netfilter: ctnetl...
2812
  	struct nf_conn_help *help;
4806e9757   Florian Westphal   netfilter: replac...
2813
  #if IS_ENABLED(CONFIG_NF_NAT)
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2814
2815
2816
  	struct nlattr *nest_parms;
  	struct nf_conntrack_tuple nat_tuple = {};
  #endif
544d5c7d9   Pablo Neira Ayuso   netfilter: ctnetl...
2817
  	struct nf_ct_helper_expectfn *expfn;
d978e5dae   Patrick McHardy   [NETFILTER]: ctne...
2818
2819
  	if (timeout < 0)
  		timeout = 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2820
2821
  
  	if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2822
  		goto nla_put_failure;
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
2823
  	if (ctnetlink_exp_dump_mask(skb, &exp->tuple, &exp->mask) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2824
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2825
2826
2827
  	if (ctnetlink_exp_dump_tuple(skb,
  				 &master->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
  				 CTA_EXPECT_MASTER) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2828
  		goto nla_put_failure;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2829

4806e9757   Florian Westphal   netfilter: replac...
2830
  #if IS_ENABLED(CONFIG_NF_NAT)
c7232c997   Patrick McHardy   netfilter: add pr...
2831
2832
  	if (!nf_inet_addr_cmp(&exp->saved_addr, &any_addr) ||
  	    exp->saved_proto.all) {
ae0be8de9   Michal Kubecek   netlink: make nla...
2833
  		nest_parms = nla_nest_start(skb, CTA_EXPECT_NAT);
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2834
2835
  		if (!nest_parms)
  			goto nla_put_failure;
cc1eb4313   David S. Miller   nf_conntrack_netl...
2836
2837
  		if (nla_put_be32(skb, CTA_EXPECT_NAT_DIR, htonl(exp->dir)))
  			goto nla_put_failure;
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2838
2839
  
  		nat_tuple.src.l3num = nf_ct_l3num(master);
c7232c997   Patrick McHardy   netfilter: add pr...
2840
  		nat_tuple.src.u3 = exp->saved_addr;
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2841
2842
2843
2844
2845
2846
2847
2848
2849
  		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...
2850
  	if (nla_put_be32(skb, CTA_EXPECT_TIMEOUT, htonl(timeout)) ||
3c7910763   Florian Westphal   netfilter: ctnetl...
2851
  	    nla_put_be32(skb, CTA_EXPECT_ID, nf_expect_get_id(exp)) ||
cc1eb4313   David S. Miller   nf_conntrack_netl...
2852
2853
2854
  	    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...
2855
2856
2857
2858
2859
  	help = nfct_help(master);
  	if (help) {
  		struct nf_conntrack_helper *helper;
  
  		helper = rcu_dereference(help->helper);
cc1eb4313   David S. Miller   nf_conntrack_netl...
2860
2861
2862
  		if (helper &&
  		    nla_put_string(skb, CTA_EXPECT_HELP_NAME, helper->name))
  			goto nla_put_failure;
bc01befdc   Pablo Neira Ayuso   netfilter: ctnetl...
2863
  	}
544d5c7d9   Pablo Neira Ayuso   netfilter: ctnetl...
2864
  	expfn = nf_ct_helper_expectfn_find_by_symbol(exp->expectfn);
cc1eb4313   David S. Miller   nf_conntrack_netl...
2865
2866
2867
  	if (expfn != NULL &&
  	    nla_put_string(skb, CTA_EXPECT_FN, expfn->name))
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2868
2869
  
  	return 0;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2870

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2871
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2872
2873
2874
2875
  	return -1;
  }
  
  static int
15e473046   Eric W. Biederman   netlink: Rename p...
2876
  ctnetlink_exp_fill_info(struct sk_buff *skb, u32 portid, u32 seq,
8b0a231d4   Pablo Neira Ayuso   netfilter: ctnetl...
2877
  			int event, const struct nf_conntrack_expect *exp)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2878
2879
2880
  {
  	struct nlmsghdr *nlh;
  	struct nfgenmsg *nfmsg;
15e473046   Eric W. Biederman   netlink: Rename p...
2881
  	unsigned int flags = portid ? NLM_F_MULTI : 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2882

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

96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2888
  	nfmsg = nlmsg_data(nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2889
2890
2891
2892
2893
  	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...
2894
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2895

96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2896
  	nlmsg_end(skb, nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2897
2898
2899
  	return skb->len;
  
  nlmsg_failure:
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2900
  nla_put_failure:
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2901
  	nlmsg_cancel(skb, nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2902
2903
2904
2905
  	return -1;
  }
  
  #ifdef CONFIG_NF_CONNTRACK_EVENTS
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
2906
2907
  static int
  ctnetlink_expect_event(unsigned int events, struct nf_exp_event *item)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2908
  {
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
2909
2910
  	struct nf_conntrack_expect *exp = item->exp;
  	struct net *net = nf_ct_exp_net(exp);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2911
2912
  	struct nlmsghdr *nlh;
  	struct nfgenmsg *nfmsg;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2913
  	struct sk_buff *skb;
ebbf41df4   Pablo Neira Ayuso   netfilter: ctnetl...
2914
  	unsigned int type, group;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2915
  	int flags = 0;
ebbf41df4   Pablo Neira Ayuso   netfilter: ctnetl...
2916
2917
2918
2919
  	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 ...
2920
2921
  		type = IPCTNL_MSG_EXP_NEW;
  		flags = NLM_F_CREATE|NLM_F_EXCL;
ebbf41df4   Pablo Neira Ayuso   netfilter: ctnetl...
2922
  		group = NFNLGRP_CONNTRACK_EXP_NEW;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2923
  	} else
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
2924
  		return 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2925

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

96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2929
2930
  	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
  	if (skb == NULL)
150ace0db   Pablo Neira Ayuso   netfilter: ctnetl...
2931
  		goto errout;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2932

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

96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2938
  	nfmsg = nlmsg_data(nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2939
2940
2941
2942
2943
  	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...
2944
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2945

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

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2950
  nla_put_failure:
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2951
  	nlmsg_cancel(skb, nlh);
528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
2952
  nlmsg_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2953
  	kfree_skb(skb);
150ace0db   Pablo Neira Ayuso   netfilter: ctnetl...
2954
  errout:
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
2955
  	nfnetlink_set_err(net, 0, 0, -ENOBUFS);
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
2956
  	return 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2957
2958
  }
  #endif
cf6994c2b   Patrick McHardy   [NETFILTER]: nf_c...
2959
2960
  static int ctnetlink_exp_done(struct netlink_callback *cb)
  {
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2961
2962
  	if (cb->args[1])
  		nf_ct_expect_put((struct nf_conntrack_expect *)cb->args[1]);
cf6994c2b   Patrick McHardy   [NETFILTER]: nf_c...
2963
2964
  	return 0;
  }
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2965
2966
2967
2968
  
  static int
  ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
  {
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
2969
  	struct net *net = sock_net(skb->sk);
cf6994c2b   Patrick McHardy   [NETFILTER]: nf_c...
2970
  	struct nf_conntrack_expect *exp, *last;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2971
  	struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
87711cb81   Pablo Neira Ayuso   [NETFILTER]: Filt...
2972
  	u_int8_t l3proto = nfmsg->nfgen_family;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2973

7d0742da1   Patrick McHardy   [NETFILTER]: nf_c...
2974
  	rcu_read_lock();
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2975
2976
  	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...
2977
  restart:
7cddd967b   Liping Zhang   netfilter: nf_ct_...
2978
2979
  		hlist_for_each_entry_rcu(exp, &nf_ct_expect_hash[cb->args[0]],
  					 hnode) {
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2980
  			if (l3proto && exp->tuple.src.l3num != l3proto)
cf6994c2b   Patrick McHardy   [NETFILTER]: nf_c...
2981
  				continue;
03d7dc5cd   Florian Westphal   netfilter: conntr...
2982
2983
2984
  
  			if (!net_eq(nf_ct_net(exp->master), net))
  				continue;
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2985
2986
2987
2988
2989
  			if (cb->args[1]) {
  				if (exp != last)
  					continue;
  				cb->args[1] = 0;
  			}
8b0a231d4   Pablo Neira Ayuso   netfilter: ctnetl...
2990
  			if (ctnetlink_exp_fill_info(skb,
15e473046   Eric W. Biederman   netlink: Rename p...
2991
  						    NETLINK_CB(cb->skb).portid,
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2992
2993
  						    cb->nlh->nlmsg_seq,
  						    IPCTNL_MSG_EXP_NEW,
8b0a231d4   Pablo Neira Ayuso   netfilter: ctnetl...
2994
  						    exp) < 0) {
b54ab92b8   Reshetova, Elena   netfilter: refcou...
2995
  				if (!refcount_inc_not_zero(&exp->use))
7d0742da1   Patrick McHardy   [NETFILTER]: nf_c...
2996
  					continue;
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2997
2998
2999
  				cb->args[1] = (unsigned long)exp;
  				goto out;
  			}
cf6994c2b   Patrick McHardy   [NETFILTER]: nf_c...
3000
  		}
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
3001
3002
3003
  		if (cb->args[1]) {
  			cb->args[1] = 0;
  			goto restart;
cf6994c2b   Patrick McHardy   [NETFILTER]: nf_c...
3004
3005
  		}
  	}
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
3006
  out:
7d0742da1   Patrick McHardy   [NETFILTER]: nf_c...
3007
  	rcu_read_unlock();
cf6994c2b   Patrick McHardy   [NETFILTER]: nf_c...
3008
3009
  	if (last)
  		nf_ct_expect_put(last);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3010

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3011
3012
  	return skb->len;
  }
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
  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_...
3028
  	hlist_for_each_entry_rcu(exp, &help->expectations, lnode) {
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
  		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...
3040
  			if (!refcount_inc_not_zero(&exp->use))
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
  				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...
3058
3059
  static int ctnetlink_dump_exp_ct(struct net *net, struct sock *ctnl,
  				 struct sk_buff *skb,
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
3060
  				 const struct nlmsghdr *nlh,
04ba724b6   Pablo Neira Ayuso   netfilter: nfnetl...
3061
3062
  				 const struct nlattr * const cda[],
  				 struct netlink_ext_ack *extack)
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
3063
3064
  {
  	int err;
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
3065
3066
3067
3068
3069
  	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...
3070
  	struct nf_conntrack_zone zone;
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
3071
3072
3073
3074
  	struct netlink_dump_control c = {
  		.dump = ctnetlink_exp_ct_dump_table,
  		.done = ctnetlink_exp_done,
  	};
deedb5903   Daniel Borkmann   netfilter: nf_con...
3075
3076
  	err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER,
  				    u3, NULL);
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
3077
3078
  	if (err < 0)
  		return err;
308ac9143   Daniel Borkmann   netfilter: nf_con...
3079
3080
3081
  	err = ctnetlink_parse_zone(cda[CTA_EXPECT_ZONE], &zone);
  	if (err < 0)
  		return err;
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
3082

308ac9143   Daniel Borkmann   netfilter: nf_con...
3083
  	h = nf_conntrack_find_get(net, &zone, &tuple);
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
3084
3085
3086
3087
  	if (!h)
  		return -ENOENT;
  
  	ct = nf_ct_tuplehash_to_ctrack(h);
207df8150   Liping Zhang   netfilter: ctnetl...
3088
3089
3090
3091
3092
  	/* No expectation linked to this connection tracking. */
  	if (!nfct_help(ct)) {
  		nf_ct_put(ct);
  		return 0;
  	}
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
3093
3094
3095
3096
3097
3098
3099
  	c.data = ct;
  
  	err = netlink_dump_start(ctnl, skb, nlh, &c);
  	nf_ct_put(ct);
  
  	return err;
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
3100
3101
  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...
3102
3103
  				const struct nlattr * const cda[],
  				struct netlink_ext_ack *extack)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3104
3105
3106
3107
  {
  	struct nf_conntrack_tuple tuple;
  	struct nf_conntrack_expect *exp;
  	struct sk_buff *skb2;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
3108
  	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3109
  	u_int8_t u3 = nfmsg->nfgen_family;
308ac9143   Daniel Borkmann   netfilter: nf_con...
3110
  	struct nf_conntrack_zone zone;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
3111
  	int err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3112

b8f3ab429   David S. Miller   Revert "netlink: ...
3113
  	if (nlh->nlmsg_flags & NLM_F_DUMP) {
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
3114
  		if (cda[CTA_EXPECT_MASTER])
04ba724b6   Pablo Neira Ayuso   netfilter: nfnetl...
3115
3116
  			return ctnetlink_dump_exp_ct(net, ctnl, skb, nlh, cda,
  						     extack);
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
3117
3118
3119
3120
3121
3122
3123
  		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 ...
3124
  	}
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
3125
3126
3127
  	err = ctnetlink_parse_zone(cda[CTA_EXPECT_ZONE], &zone);
  	if (err < 0)
  		return err;
35dba1d7f   Pablo Neira Ayuso   netfilter: ctnetl...
3128
  	if (cda[CTA_EXPECT_TUPLE])
deedb5903   Daniel Borkmann   netfilter: nf_con...
3129
3130
  		err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE,
  					    u3, NULL);
35dba1d7f   Pablo Neira Ayuso   netfilter: ctnetl...
3131
  	else if (cda[CTA_EXPECT_MASTER])
deedb5903   Daniel Borkmann   netfilter: nf_con...
3132
3133
  		err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER,
  					    u3, NULL);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3134
3135
3136
3137
3138
  	else
  		return -EINVAL;
  
  	if (err < 0)
  		return err;
308ac9143   Daniel Borkmann   netfilter: nf_con...
3139
  	exp = nf_ct_expect_find_get(net, &zone, &tuple);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3140
3141
  	if (!exp)
  		return -ENOENT;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
3142
  	if (cda[CTA_EXPECT_ID]) {
77236b6e3   Patrick McHardy   [NETFILTER]: ctne...
3143
  		__be32 id = nla_get_be32(cda[CTA_EXPECT_ID]);
3c7910763   Florian Westphal   netfilter: ctnetl...
3144
3145
  
  		if (id != nf_expect_get_id(exp)) {
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
3146
  			nf_ct_expect_put(exp);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3147
3148
  			return -ENOENT;
  		}
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
3149
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3150
3151
  
  	err = -ENOMEM;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
3152
  	skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
81378f728   Pablo Neira Ayuso   netfilter: ctnetl...
3153
3154
  	if (skb2 == NULL) {
  		nf_ct_expect_put(exp);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3155
  		goto out;
81378f728   Pablo Neira Ayuso   netfilter: ctnetl...
3156
  	}
4e9b82693   Thomas Graf   [NETLINK]: Remove...
3157

528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
3158
  	rcu_read_lock();
15e473046   Eric W. Biederman   netlink: Rename p...
3159
  	err = ctnetlink_exp_fill_info(skb2, NETLINK_CB(skb).portid,
8b0a231d4   Pablo Neira Ayuso   netfilter: ctnetl...
3160
  				      nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW, exp);
528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
3161
  	rcu_read_unlock();
81378f728   Pablo Neira Ayuso   netfilter: ctnetl...
3162
  	nf_ct_expect_put(exp);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3163
3164
  	if (err <= 0)
  		goto free;
15e473046   Eric W. Biederman   netlink: Rename p...
3165
  	err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT);
81378f728   Pablo Neira Ayuso   netfilter: ctnetl...
3166
3167
  	if (err < 0)
  		goto out;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3168

81378f728   Pablo Neira Ayuso   netfilter: ctnetl...
3169
  	return 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3170
3171
3172
3173
  
  free:
  	kfree_skb(skb2);
  out:
81378f728   Pablo Neira Ayuso   netfilter: ctnetl...
3174
3175
  	/* this avoids a loop in nfnetlink. */
  	return err == -EAGAIN ? -ENOBUFS : err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3176
  }
ac7b84839   Florian Westphal   netfilter: expect...
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
  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...
3191
3192
  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...
3193
3194
  				const struct nlattr * const cda[],
  				struct netlink_ext_ack *extack)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3195
  {
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
3196
  	struct nf_conntrack_expect *exp;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3197
  	struct nf_conntrack_tuple tuple;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
3198
  	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3199
  	u_int8_t u3 = nfmsg->nfgen_family;
308ac9143   Daniel Borkmann   netfilter: nf_con...
3200
  	struct nf_conntrack_zone zone;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3201
  	int err;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
3202
  	if (cda[CTA_EXPECT_TUPLE]) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3203
  		/* delete a single expect by tuple */
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
3204
3205
3206
  		err = ctnetlink_parse_zone(cda[CTA_EXPECT_ZONE], &zone);
  		if (err < 0)
  			return err;
deedb5903   Daniel Borkmann   netfilter: nf_con...
3207
3208
  		err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE,
  					    u3, NULL);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3209
3210
3211
3212
  		if (err < 0)
  			return err;
  
  		/* bump usage count to 2 */
308ac9143   Daniel Borkmann   netfilter: nf_con...
3213
  		exp = nf_ct_expect_find_get(net, &zone, &tuple);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3214
3215
  		if (!exp)
  			return -ENOENT;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
3216
  		if (cda[CTA_EXPECT_ID]) {
77236b6e3   Patrick McHardy   [NETFILTER]: ctne...
3217
  			__be32 id = nla_get_be32(cda[CTA_EXPECT_ID]);
358324024   Patrick McHardy   [NETFILTER]: nf_c...
3218
  			if (ntohl(id) != (u32)(unsigned long)exp) {
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
3219
  				nf_ct_expect_put(exp);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3220
3221
3222
3223
3224
  				return -ENOENT;
  			}
  		}
  
  		/* after list removal, usage count == 1 */
ca7433df3   Jesper Dangaard Brouer   netfilter: conntr...
3225
  		spin_lock_bh(&nf_conntrack_expect_lock);
ebbf41df4   Pablo Neira Ayuso   netfilter: ctnetl...
3226
  		if (del_timer(&exp->timeout)) {
15e473046   Eric W. Biederman   netlink: Rename p...
3227
  			nf_ct_unlink_expect_report(exp, NETLINK_CB(skb).portid,
ebbf41df4   Pablo Neira Ayuso   netfilter: ctnetl...
3228
3229
3230
  						   nlmsg_report(nlh));
  			nf_ct_expect_put(exp);
  		}
ca7433df3   Jesper Dangaard Brouer   netfilter: conntr...
3231
  		spin_unlock_bh(&nf_conntrack_expect_lock);
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
3232
  		/* have to put what we 'get' above.
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3233
  		 * after this line usage count == 0 */
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
3234
  		nf_ct_expect_put(exp);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
3235
3236
  	} else if (cda[CTA_EXPECT_HELP_NAME]) {
  		char *name = nla_data(cda[CTA_EXPECT_HELP_NAME]);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3237

ac7b84839   Florian Westphal   netfilter: expect...
3238
3239
3240
  		nf_ct_expect_iterate_net(net, expect_iter_name, name,
  					 NETLINK_CB(skb).portid,
  					 nlmsg_report(nlh));
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3241
3242
  	} else {
  		/* This basically means we have to flush everything*/
ac7b84839   Florian Westphal   netfilter: expect...
3243
3244
3245
  		nf_ct_expect_iterate_net(net, expect_iter_all, NULL,
  					 NETLINK_CB(skb).portid,
  					 nlmsg_report(nlh));
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3246
3247
3248
3249
3250
  	}
  
  	return 0;
  }
  static int
399383246   Patrick McHardy   netfilter: nfnetl...
3251
3252
  ctnetlink_change_expect(struct nf_conntrack_expect *x,
  			const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3253
  {
9768e1ace   Kelvie Wong   netfilter: nf_ct_...
3254
3255
3256
3257
3258
3259
3260
3261
3262
  	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 ...
3263
  }
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
  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)
  {
4806e9757   Florian Westphal   netfilter: replac...
3274
  #if IS_ENABLED(CONFIG_NF_NAT)
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
3275
3276
3277
  	struct nlattr *tb[CTA_EXPECT_NAT_MAX+1];
  	struct nf_conntrack_tuple nat_tuple = {};
  	int err;
8cb081746   Johannes Berg   netlink: make val...
3278
3279
  	err = nla_parse_nested_deprecated(tb, CTA_EXPECT_NAT_MAX, attr,
  					  exp_nat_nla_policy, NULL);
130ffbc26   Daniel Borkmann   netfilter: check ...
3280
3281
  	if (err < 0)
  		return err;
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
3282
3283
3284
3285
3286
  
  	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...
3287
3288
  				    &nat_tuple, CTA_EXPECT_NAT_TUPLE,
  				    u3, NULL);
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
3289
3290
  	if (err < 0)
  		return err;
c7232c997   Patrick McHardy   netfilter: add pr...
3291
  	exp->saved_addr = nat_tuple.src.u3;
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
3292
3293
3294
3295
3296
3297
3298
3299
  	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...
3300
3301
3302
3303
3304
  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 ...
3305
  {
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
3306
  	u_int32_t class = 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3307
  	struct nf_conntrack_expect *exp;
dc808fe28   Harald Welte   [NETFILTER] nf_co...
3308
  	struct nf_conn_help *help;
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
3309
  	int err;
660fdb2a0   Pablo Neira Ayuso   netfilter: ctnetl...
3310

2c62e0bc6   Gao Feng   netfilter: ctnetl...
3311
3312
3313
  	help = nfct_help(ct);
  	if (!help)
  		return ERR_PTR(-EOPNOTSUPP);
b8c5e52c1   Pablo Neira Ayuso   netfilter: ctnetl...
3314
3315
  	if (cda[CTA_EXPECT_CLASS] && helper) {
  		class = ntohl(nla_get_be32(cda[CTA_EXPECT_CLASS]));
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
3316
3317
  		if (class > helper->expect_class_max)
  			return ERR_PTR(-EINVAL);
b8c5e52c1   Pablo Neira Ayuso   netfilter: ctnetl...
3318
  	}
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
3319
  	exp = nf_ct_expect_alloc(ct);
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
3320
3321
  	if (!exp)
  		return ERR_PTR(-ENOMEM);
2c62e0bc6   Gao Feng   netfilter: ctnetl...
3322
3323
3324
  	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...
3325
  	} else {
2c62e0bc6   Gao Feng   netfilter: ctnetl...
3326
  		exp->flags = 0;
bc01befdc   Pablo Neira Ayuso   netfilter: ctnetl...
3327
  	}
544d5c7d9   Pablo Neira Ayuso   netfilter: ctnetl...
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
  	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 ...
3340

b8c5e52c1   Pablo Neira Ayuso   netfilter: ctnetl...
3341
  	exp->class = class;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3342
  	exp->master = ct;
660fdb2a0   Pablo Neira Ayuso   netfilter: ctnetl...
3343
  	exp->helper = helper;
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
3344
3345
3346
  	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 ...
3347

076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
3348
3349
  	if (cda[CTA_EXPECT_NAT]) {
  		err = ctnetlink_parse_expect_nat(cda[CTA_EXPECT_NAT],
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
3350
  						 exp, nf_ct_l3num(ct));
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
3351
3352
3353
  		if (err < 0)
  			goto err_out;
  	}
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
3354
  	return exp;
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
3355
  err_out:
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
3356
  	nf_ct_expect_put(exp);
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
3357
3358
3359
3360
  	return ERR_PTR(err);
  }
  
  static int
308ac9143   Daniel Borkmann   netfilter: nf_con...
3361
3362
  ctnetlink_create_expect(struct net *net,
  			const struct nf_conntrack_zone *zone,
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
  			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...
3374
3375
  	err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE,
  				    u3, NULL);
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
3376
3377
  	if (err < 0)
  		return err;
deedb5903   Daniel Borkmann   netfilter: nf_con...
3378
3379
  	err = ctnetlink_parse_tuple(cda, &mask, CTA_EXPECT_MASK,
  				    u3, NULL);
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
3380
3381
  	if (err < 0)
  		return err;
deedb5903   Daniel Borkmann   netfilter: nf_con...
3382
3383
  	err = ctnetlink_parse_tuple(cda, &master_tuple, CTA_EXPECT_MASTER,
  				    u3, NULL);
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
3384
3385
3386
3387
3388
3389
3390
3391
  	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...
3392
  	rcu_read_lock();
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
3393
3394
3395
3396
3397
3398
  	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...
3399
  			rcu_read_unlock();
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
3400
3401
3402
3403
3404
  #ifdef CONFIG_MODULES
  			if (request_module("nfct-helper-%s", helpname) < 0) {
  				err = -EOPNOTSUPP;
  				goto err_ct;
  			}
8b5995d06   Gao Feng   netfilter: helper...
3405
  			rcu_read_lock();
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
3406
3407
3408
3409
  			helper = __nf_conntrack_helper_find(helpname, u3,
  							    nf_ct_protonum(ct));
  			if (helper) {
  				err = -EAGAIN;
8b5995d06   Gao Feng   netfilter: helper...
3410
  				goto err_rcu;
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
3411
  			}
8b5995d06   Gao Feng   netfilter: helper...
3412
  			rcu_read_unlock();
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
3413
3414
3415
3416
3417
3418
3419
3420
3421
  #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...
3422
  		goto err_rcu;
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
3423
  	}
3c00fb0bf   xiao ruizhu   netfilter: nf_con...
3424
  	err = nf_ct_expect_related_report(exp, portid, report, 0);
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
3425
  	nf_ct_expect_put(exp);
8b5995d06   Gao Feng   netfilter: helper...
3426
3427
  err_rcu:
  	rcu_read_unlock();
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
3428
3429
  err_ct:
  	nf_ct_put(ct);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3430
3431
  	return err;
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
3432
3433
  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...
3434
3435
  				const struct nlattr * const cda[],
  				struct netlink_ext_ack *extack)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3436
3437
3438
  {
  	struct nf_conntrack_tuple tuple;
  	struct nf_conntrack_expect *exp;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
3439
  	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3440
  	u_int8_t u3 = nfmsg->nfgen_family;
308ac9143   Daniel Borkmann   netfilter: nf_con...
3441
  	struct nf_conntrack_zone zone;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
3442
  	int err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3443

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
3444
3445
3446
  	if (!cda[CTA_EXPECT_TUPLE]
  	    || !cda[CTA_EXPECT_MASK]
  	    || !cda[CTA_EXPECT_MASTER])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3447
  		return -EINVAL;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
3448
3449
3450
  	err = ctnetlink_parse_zone(cda[CTA_EXPECT_ZONE], &zone);
  	if (err < 0)
  		return err;
deedb5903   Daniel Borkmann   netfilter: nf_con...
3451
3452
  	err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE,
  				    u3, NULL);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3453
3454
  	if (err < 0)
  		return err;
ca7433df3   Jesper Dangaard Brouer   netfilter: conntr...
3455
  	spin_lock_bh(&nf_conntrack_expect_lock);
308ac9143   Daniel Borkmann   netfilter: nf_con...
3456
  	exp = __nf_ct_expect_find(net, &zone, &tuple);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3457
  	if (!exp) {
ca7433df3   Jesper Dangaard Brouer   netfilter: conntr...
3458
  		spin_unlock_bh(&nf_conntrack_expect_lock);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3459
  		err = -ENOENT;
19abb7b09   Pablo Neira Ayuso   netfilter: ctnetl...
3460
  		if (nlh->nlmsg_flags & NLM_F_CREATE) {
308ac9143   Daniel Borkmann   netfilter: nf_con...
3461
  			err = ctnetlink_create_expect(net, &zone, cda, u3,
15e473046   Eric W. Biederman   netlink: Rename p...
3462
  						      NETLINK_CB(skb).portid,
19abb7b09   Pablo Neira Ayuso   netfilter: ctnetl...
3463
3464
  						      nlmsg_report(nlh));
  		}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3465
3466
3467
3468
3469
3470
  		return err;
  	}
  
  	err = -EEXIST;
  	if (!(nlh->nlmsg_flags & NLM_F_EXCL))
  		err = ctnetlink_change_expect(exp, cda);
ca7433df3   Jesper Dangaard Brouer   netfilter: conntr...
3471
  	spin_unlock_bh(&nf_conntrack_expect_lock);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3472

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3473
3474
  	return err;
  }
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
3475
  static int
15e473046   Eric W. Biederman   netlink: Rename p...
3476
  ctnetlink_exp_stat_fill_info(struct sk_buff *skb, u32 portid, u32 seq, int cpu,
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
3477
3478
3479
3480
  			     const struct ip_conntrack_stat *st)
  {
  	struct nlmsghdr *nlh;
  	struct nfgenmsg *nfmsg;
15e473046   Eric W. Biederman   netlink: Rename p...
3481
  	unsigned int flags = portid ? NLM_F_MULTI : 0, event;
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
3482

dedb67c4b   Pablo Neira Ayuso   netfilter: Add nf...
3483
3484
  	event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK,
  			      IPCTNL_MSG_EXP_GET_STATS_CPU);
15e473046   Eric W. Biederman   netlink: Rename p...
3485
  	nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
  	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...
3524
  		if (ctnetlink_exp_stat_fill_info(skb, NETLINK_CB(cb->skb).portid,
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
3525
3526
3527
3528
3529
3530
3531
3532
  						 cb->nlh->nlmsg_seq,
  						 cpu, st) < 0)
  			break;
  	}
  	cb->args[0] = cpu;
  
  	return skb->len;
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
3533
3534
3535
  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...
3536
3537
  				  const struct nlattr * const cda[],
  				  struct netlink_ext_ack *extack)
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
  {
  	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 ...
3548
  #ifdef CONFIG_NF_CONNTRACK_EVENTS
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
3549
3550
  static struct nf_ct_event_notifier ctnl_notifier = {
  	.fcn = ctnetlink_conntrack_event,
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3551
  };
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
3552
3553
  static struct nf_exp_event_notifier ctnl_notifier_exp = {
  	.fcn = ctnetlink_expect_event,
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3554
3555
  };
  #endif
7c8d4cb41   Patrick McHardy   [NETFILTER]: nfne...
3556
  static const struct nfnl_callback ctnl_cb[IPCTNL_MSG_MAX] = {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3557
  	[IPCTNL_MSG_CT_NEW]		= { .call = ctnetlink_new_conntrack,
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
3558
3559
  					    .attr_count = CTA_MAX,
  					    .policy = ct_nla_policy },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3560
  	[IPCTNL_MSG_CT_GET] 		= { .call = ctnetlink_get_conntrack,
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
3561
3562
  					    .attr_count = CTA_MAX,
  					    .policy = ct_nla_policy },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3563
  	[IPCTNL_MSG_CT_DELETE]  	= { .call = ctnetlink_del_conntrack,
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
3564
3565
  					    .attr_count = CTA_MAX,
  					    .policy = ct_nla_policy },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3566
  	[IPCTNL_MSG_CT_GET_CTRZERO] 	= { .call = ctnetlink_get_conntrack,
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
3567
3568
  					    .attr_count = CTA_MAX,
  					    .policy = ct_nla_policy },
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
3569
3570
  	[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...
3571
3572
  	[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 ...
3573
  };
7c8d4cb41   Patrick McHardy   [NETFILTER]: nfne...
3574
  static const struct nfnl_callback ctnl_exp_cb[IPCTNL_MSG_EXP_MAX] = {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3575
  	[IPCTNL_MSG_EXP_GET]		= { .call = ctnetlink_get_expect,
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
3576
3577
  					    .attr_count = CTA_EXPECT_MAX,
  					    .policy = exp_nla_policy },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3578
  	[IPCTNL_MSG_EXP_NEW]		= { .call = ctnetlink_new_expect,
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
3579
3580
  					    .attr_count = CTA_EXPECT_MAX,
  					    .policy = exp_nla_policy },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3581
  	[IPCTNL_MSG_EXP_DELETE]		= { .call = ctnetlink_del_expect,
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
3582
3583
  					    .attr_count = CTA_EXPECT_MAX,
  					    .policy = exp_nla_policy },
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
3584
  	[IPCTNL_MSG_EXP_GET_STATS_CPU]	= { .call = ctnetlink_stat_exp_cpu },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3585
  };
7c8d4cb41   Patrick McHardy   [NETFILTER]: nfne...
3586
  static const struct nfnetlink_subsystem ctnl_subsys = {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3587
3588
3589
3590
3591
  	.name				= "conntrack",
  	.subsys_id			= NFNL_SUBSYS_CTNETLINK,
  	.cb_count			= IPCTNL_MSG_MAX,
  	.cb				= ctnl_cb,
  };
7c8d4cb41   Patrick McHardy   [NETFILTER]: nfne...
3592
  static const struct nfnetlink_subsystem ctnl_exp_subsys = {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3593
3594
3595
3596
3597
  	.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...
3598
  MODULE_ALIAS("ip_conntrack_netlink");
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3599
  MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK);
34f9a2e4d   Pablo Neira Ayuso   [NETFILTER]: ctne...
3600
  MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_EXP);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3601

70e9942f1   Pablo Neira Ayuso   netfilter: nf_con...
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
  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);
18a110b02   Florian Westphal   netfilter: ctnetl...
3645
3646
3647
  
  	/* wait for other cpus until they are done with ctnl_notifiers */
  	synchronize_rcu();
70e9942f1   Pablo Neira Ayuso   netfilter: nf_con...
3648
3649
3650
3651
3652
3653
  }
  
  static struct pernet_operations ctnetlink_net_ops = {
  	.init		= ctnetlink_net_init,
  	.exit_batch	= ctnetlink_net_exit_batch,
  };
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3654
3655
3656
  static int __init ctnetlink_init(void)
  {
  	int ret;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3657
3658
  	ret = nfnetlink_subsys_register(&ctnl_subsys);
  	if (ret < 0) {
654d0fbdc   Stephen Hemminger   netfilter: cleanu...
3659
3660
  		pr_err("ctnetlink_init: cannot register with nfnetlink.
  ");
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3661
3662
3663
3664
3665
  		goto err_out;
  	}
  
  	ret = nfnetlink_subsys_register(&ctnl_exp_subsys);
  	if (ret < 0) {
654d0fbdc   Stephen Hemminger   netfilter: cleanu...
3666
3667
  		pr_err("ctnetlink_init: cannot register exp with nfnetlink.
  ");
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3668
3669
  		goto err_unreg_subsys;
  	}
ef6acf68c   Julia Lawall   netfilter: ctnetl...
3670
3671
  	ret = register_pernet_subsys(&ctnetlink_net_ops);
  	if (ret < 0) {
70e9942f1   Pablo Neira Ayuso   netfilter: nf_con...
3672
3673
  		pr_err("ctnetlink_init: cannot register pernet operations
  ");
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3674
3675
  		goto err_unreg_exp_subsys;
  	}
83f3e94d3   Ken-ichirou MATSUZAWA   netfilter: Kconfi...
3676
  #ifdef CONFIG_NETFILTER_NETLINK_GLUE_CT
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
3677
  	/* setup interaction between nf_queue and nf_conntrack_netlink. */
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
3678
  	RCU_INIT_POINTER(nfnl_ct_hook, &ctnetlink_glue_hook);
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
3679
  #endif
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3680
  	return 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3681
3682
  err_unreg_exp_subsys:
  	nfnetlink_subsys_unregister(&ctnl_exp_subsys);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3683
3684
3685
3686
3687
3688
3689
3690
  err_unreg_subsys:
  	nfnetlink_subsys_unregister(&ctnl_subsys);
  err_out:
  	return ret;
  }
  
  static void __exit ctnetlink_exit(void)
  {
70e9942f1   Pablo Neira Ayuso   netfilter: nf_con...
3691
  	unregister_pernet_subsys(&ctnetlink_net_ops);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3692
3693
  	nfnetlink_subsys_unregister(&ctnl_exp_subsys);
  	nfnetlink_subsys_unregister(&ctnl_subsys);
83f3e94d3   Ken-ichirou MATSUZAWA   netfilter: Kconfi...
3694
  #ifdef CONFIG_NETFILTER_NETLINK_GLUE_CT
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
3695
  	RCU_INIT_POINTER(nfnl_ct_hook, NULL);
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
3696
  #endif
3b7dabf02   Liping Zhang   netfilter: invoke...
3697
  	synchronize_rcu();
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3698
3699
3700
3701
  }
  
  module_init(ctnetlink_init);
  module_exit(ctnetlink_exit);