Blame view

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

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

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

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

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

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

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

1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
98
  	return ret;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
99
  nla_put_failure:
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
100
101
  	return -1;
  }
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
102
103
  static int ctnetlink_dump_tuples(struct sk_buff *skb,
  				 const struct nf_conntrack_tuple *tuple)
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
104
105
106
  {
  	int ret;
  	struct nf_conntrack_l3proto *l3proto;
605dcad6c   Martin Josefsson   [NETFILTER]: nf_c...
107
  	struct nf_conntrack_l4proto *l4proto;
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
108

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

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

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

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

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

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

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

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

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

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

4542fa472   Holger Eitzenberger   netfilter: ctnetl...
209
210
211
212
213
214
215
216
217
  	if (type == IPCTNL_MSG_CT_GET_CTRZERO) {
  		pkts = atomic64_xchg(&counter[dir].packets, 0);
  		bytes = atomic64_xchg(&counter[dir].bytes, 0);
  	} else {
  		pkts = atomic64_read(&counter[dir].packets);
  		bytes = atomic64_read(&counter[dir].bytes);
  	}
  
  	nest_count = nla_nest_start(skb, attr | NLA_F_NESTED);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
218
219
  	if (!nest_count)
  		goto nla_put_failure;
b46f6ded9   Nicolas Dichtel   libnl: nla_put_be...
220
221
222
223
  	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...
224
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
225

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

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

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

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

41d73ec05   Patrick McHardy   netfilter: nf_con...
395
  	if (!(ct->status & IPS_SEQ_ADJUST) || !seqadj)
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
396
  		return 0;
41d73ec05   Patrick McHardy   netfilter: nf_con...
397
398
  	seq = &seqadj->seq[IP_CT_DIR_ORIGINAL];
  	if (dump_ct_seq_adj(skb, seq, CTA_SEQ_ADJ_ORIG) == -1)
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
399
  		return -1;
41d73ec05   Patrick McHardy   netfilter: nf_con...
400
401
  	seq = &seqadj->seq[IP_CT_DIR_REPLY];
  	if (dump_ct_seq_adj(skb, seq, CTA_SEQ_ADJ_REPLY) == -1)
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
402
403
404
405
  		return -1;
  
  	return 0;
  }
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
406

4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
407
  static int ctnetlink_dump_id(struct sk_buff *skb, const struct nf_conn *ct)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
408
  {
cc1eb4313   David S. Miller   nf_conntrack_netl...
409
410
  	if (nla_put_be32(skb, CTA_ID, htonl((unsigned long)ct)))
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
411
  	return 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
412
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
413
414
  	return -1;
  }
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
415
  static int ctnetlink_dump_use(struct sk_buff *skb, const struct nf_conn *ct)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
416
  {
cc1eb4313   David S. Miller   nf_conntrack_netl...
417
418
  	if (nla_put_be32(skb, CTA_USE, htonl(atomic_read(&ct->ct_general.use))))
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
419
  	return 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
420
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
421
422
  	return -1;
  }
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
423
  static int
15e473046   Eric W. Biederman   netlink: Rename p...
424
  ctnetlink_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
80e60e67b   Pablo Neira Ayuso   netfilter: ctnetl...
425
  		    struct nf_conn *ct)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
426
  {
308ac9143   Daniel Borkmann   netfilter: nf_con...
427
  	const struct nf_conntrack_zone *zone;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
428
429
  	struct nlmsghdr *nlh;
  	struct nfgenmsg *nfmsg;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
430
  	struct nlattr *nest_parms;
15e473046   Eric W. Biederman   netlink: Rename p...
431
  	unsigned int flags = portid ? NLM_F_MULTI : 0, event;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
432

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

96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
438
  	nfmsg = nlmsg_data(nlh);
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
439
  	nfmsg->nfgen_family = nf_ct_l3num(ct);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
440
441
  	nfmsg->version      = NFNETLINK_V0;
  	nfmsg->res_id	    = 0;
deedb5903   Daniel Borkmann   netfilter: nf_con...
442
  	zone = nf_ct_zone(ct);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
443
444
445
  	nest_parms = nla_nest_start(skb, CTA_TUPLE_ORIG | NLA_F_NESTED);
  	if (!nest_parms)
  		goto nla_put_failure;
f2f3e38c6   Pablo Neira Ayuso   netfilter: ctnetl...
446
  	if (ctnetlink_dump_tuples(skb, nf_ct_tuple(ct, IP_CT_DIR_ORIGINAL)) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
447
  		goto nla_put_failure;
deedb5903   Daniel Borkmann   netfilter: nf_con...
448
449
450
  	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...
451
  	nla_nest_end(skb, nest_parms);
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
452

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
453
454
455
  	nest_parms = nla_nest_start(skb, CTA_TUPLE_REPLY | NLA_F_NESTED);
  	if (!nest_parms)
  		goto nla_put_failure;
f2f3e38c6   Pablo Neira Ayuso   netfilter: ctnetl...
456
  	if (ctnetlink_dump_tuples(skb, nf_ct_tuple(ct, IP_CT_DIR_REPLY)) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
457
  		goto nla_put_failure;
deedb5903   Daniel Borkmann   netfilter: nf_con...
458
459
460
  	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...
461
  	nla_nest_end(skb, nest_parms);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
462

deedb5903   Daniel Borkmann   netfilter: nf_con...
463
464
  	if (ctnetlink_dump_zone_id(skb, CTA_ZONE, zone,
  				   NF_CT_DEFAULT_ZONE_DIR) < 0)
cc1eb4313   David S. Miller   nf_conntrack_netl...
465
  		goto nla_put_failure;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
466

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

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

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

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

4a96300ce   Pablo Neira Ayuso   netfilter: ctnetl...
531
  static inline size_t ctnetlink_timestamp_size(const struct nf_conn *ct)
a992ca2a0   Pablo Neira Ayuso   netfilter: nf_con...
532
533
534
535
  {
  #ifdef CONFIG_NF_CONNTRACK_TIMESTAMP
  	if (!nf_ct_ext_exist(ct, NF_CT_EXT_TSTAMP))
  		return 0;
b46f6ded9   Nicolas Dichtel   libnl: nla_put_be...
536
  	return nla_total_size(0) + 2 * nla_total_size_64bit(sizeof(uint64_t));
a992ca2a0   Pablo Neira Ayuso   netfilter: nf_con...
537
538
539
540
  #else
  	return 0;
  #endif
  }
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
541
542
  #ifdef CONFIG_NF_CONNTRACK_EVENTS
  static size_t ctnetlink_nlmsg_size(const struct nf_conn *ct)
03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
543
544
545
546
547
548
549
550
  {
  	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...
551
  	       + ctnetlink_acct_size(ct)
a992ca2a0   Pablo Neira Ayuso   netfilter: nf_con...
552
  	       + ctnetlink_timestamp_size(ct)
03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
553
554
555
556
  	       + 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...
557
  	       + ctnetlink_secctx_size(ct)
d271e8bd8   Holger Eitzenberger   ctnetlink: comput...
558
  #ifdef CONFIG_NF_NAT_NEEDED
03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
559
560
  	       + 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...
561
562
  #endif
  #ifdef CONFIG_NF_CONNTRACK_MARK
03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
563
  	       + nla_total_size(sizeof(u_int32_t)) /* CTA_MARK */
d271e8bd8   Holger Eitzenberger   ctnetlink: comput...
564
  #endif
4a001068d   Ken-ichirou MATSUZAWA   netfilter: ctnetl...
565
  #ifdef CONFIG_NF_CONNTRACK_ZONES
deedb5903   Daniel Borkmann   netfilter: nf_con...
566
  	       + nla_total_size(sizeof(u_int16_t)) /* CTA_ZONE|CTA_TUPLE_ZONE */
4a001068d   Ken-ichirou MATSUZAWA   netfilter: ctnetl...
567
  #endif
03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
568
  	       + ctnetlink_proto_size(ct)
0ceabd838   Florian Westphal   netfilter: ctnetl...
569
  	       + ctnetlink_label_size(ct)
03b64f518   Pablo Neira Ayuso   netfilter: ctnetl...
570
  	       ;
2732c4e45   Holger Eitzenberger   netfilter: ctnetl...
571
  }
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
572
573
  static int
  ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
574
  {
308ac9143   Daniel Borkmann   netfilter: nf_con...
575
  	const struct nf_conntrack_zone *zone;
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
576
  	struct net *net;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
577
578
  	struct nlmsghdr *nlh;
  	struct nfgenmsg *nfmsg;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
579
  	struct nlattr *nest_parms;
19abb7b09   Pablo Neira Ayuso   netfilter: ctnetl...
580
  	struct nf_conn *ct = item->ct;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
581
582
  	struct sk_buff *skb;
  	unsigned int type;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
583
  	unsigned int flags = 0, group;
dd7669a92   Pablo Neira Ayuso   netfilter: conntr...
584
  	int err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
585
586
  
  	/* ignore our fake conntrack entry */
5bfddbd46   Eric Dumazet   netfilter: nf_con...
587
  	if (nf_ct_is_untracked(ct))
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
588
  		return 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
589

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

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

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

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

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

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
632
633
634
  	nest_parms = nla_nest_start(skb, CTA_TUPLE_REPLY | NLA_F_NESTED);
  	if (!nest_parms)
  		goto nla_put_failure;
f2f3e38c6   Pablo Neira Ayuso   netfilter: ctnetl...
635
  	if (ctnetlink_dump_tuples(skb, nf_ct_tuple(ct, IP_CT_DIR_REPLY)) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
636
  		goto nla_put_failure;
deedb5903   Daniel Borkmann   netfilter: nf_con...
637
638
639
  	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...
640
  	nla_nest_end(skb, nest_parms);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
641

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

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

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

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

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

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

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

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

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

3b988ece9   Hans Schillstrom   netfilter: ctnetl...
811
812
  			rcu_read_lock();
  			res =
15e473046   Eric W. Biederman   netlink: Rename p...
813
  			ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).portid,
3b988ece9   Hans Schillstrom   netfilter: ctnetl...
814
815
816
817
818
  					    cb->nlh->nlmsg_seq,
  					    NFNL_MSG_TYPE(cb->nlh->nlmsg_type),
  					    ct);
  			rcu_read_unlock();
  			if (res < 0) {
c71caf411   Pablo Neira Ayuso   netfilter: ctnetl...
819
  				nf_conntrack_get(&ct->ct_general);
89f2e2188   Patrick McHardy   [NETFILTER]: ctne...
820
  				cb->args[1] = (unsigned long)ct;
93bb0ceb7   Jesper Dangaard Brouer   netfilter: conntr...
821
  				spin_unlock(lockp);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
822
  				goto out;
89f2e2188   Patrick McHardy   [NETFILTER]: ctne...
823
824
  			}
  		}
93bb0ceb7   Jesper Dangaard Brouer   netfilter: conntr...
825
  		spin_unlock(lockp);
d205dc407   Patrick McHardy   [NETFILTER]: ctne...
826
  		if (cb->args[1]) {
89f2e2188   Patrick McHardy   [NETFILTER]: ctne...
827
828
  			cb->args[1] = 0;
  			goto restart;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
829
830
  		}
  	}
89f2e2188   Patrick McHardy   [NETFILTER]: ctne...
831
  out:
93bb0ceb7   Jesper Dangaard Brouer   netfilter: conntr...
832
  	local_bh_enable();
d205dc407   Patrick McHardy   [NETFILTER]: ctne...
833
834
  	if (last)
  		nf_ct_put(last);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
835

2344d64ec   Florian Westphal   netfilter: evict ...
836
837
838
839
840
841
  	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 ...
842
843
  	return skb->len;
  }
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
844
845
  static int ctnetlink_parse_tuple_ip(struct nlattr *attr,
  				    struct nf_conntrack_tuple *tuple)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
846
  {
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
847
  	struct nlattr *tb[CTA_IP_MAX+1];
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
848
849
  	struct nf_conntrack_l3proto *l3proto;
  	int ret = 0;
130ffbc26   Daniel Borkmann   netfilter: check ...
850
851
852
  	ret = nla_parse_nested(tb, CTA_IP_MAX, attr, NULL);
  	if (ret < 0)
  		return ret;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
853

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

f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
857
858
859
860
861
862
  	if (likely(l3proto->nlattr_to_tuple)) {
  		ret = nla_validate_nested(attr, CTA_IP_MAX,
  					  l3proto->nla_policy);
  		if (ret == 0)
  			ret = l3proto->nlattr_to_tuple(tb, tuple);
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
863

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

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
866
867
  	return ret;
  }
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
868
869
  static const struct nla_policy proto_nla_policy[CTA_PROTO_MAX+1] = {
  	[CTA_PROTO_NUM]	= { .type = NLA_U8 },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
870
  };
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
871
872
  static int ctnetlink_parse_tuple_proto(struct nlattr *attr,
  				       struct nf_conntrack_tuple *tuple)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
873
  {
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
874
  	struct nlattr *tb[CTA_PROTO_MAX+1];
605dcad6c   Martin Josefsson   [NETFILTER]: nf_c...
875
  	struct nf_conntrack_l4proto *l4proto;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
876
  	int ret = 0;
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
877
878
879
  	ret = nla_parse_nested(tb, CTA_PROTO_MAX, attr, proto_nla_policy);
  	if (ret < 0)
  		return ret;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
880

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

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

f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
888
889
890
891
892
893
  	if (likely(l4proto->nlattr_to_tuple)) {
  		ret = nla_validate_nested(attr, CTA_PROTO_MAX,
  					  l4proto->nla_policy);
  		if (ret == 0)
  			ret = l4proto->nlattr_to_tuple(tb, tuple);
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
894

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

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
897
898
  	return ret;
  }
deedb5903   Daniel Borkmann   netfilter: nf_con...
899
900
901
902
  static int
  ctnetlink_parse_zone(const struct nlattr *attr,
  		     struct nf_conntrack_zone *zone)
  {
5e8018fc6   Daniel Borkmann   netfilter: nf_con...
903
904
  	nf_ct_zone_init(zone, NF_CT_DEFAULT_ZONE_ID,
  			NF_CT_DEFAULT_ZONE_DIR, 0);
deedb5903   Daniel Borkmann   netfilter: nf_con...
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
  #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...
935
936
937
  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...
938
  	[CTA_TUPLE_ZONE]	= { .type = NLA_U16 },
d0b0268fd   Patrick McHardy   netfilter: ctnetl...
939
  };
bb5cf80e9   Ilpo Järvinen   [NETFILTER]: Kill...
940
  static int
399383246   Patrick McHardy   netfilter: nfnetl...
941
942
  ctnetlink_parse_tuple(const struct nlattr * const cda[],
  		      struct nf_conntrack_tuple *tuple,
deedb5903   Daniel Borkmann   netfilter: nf_con...
943
944
  		      enum ctattr_type type, u_int8_t l3num,
  		      struct nf_conntrack_zone *zone)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
945
  {
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
946
  	struct nlattr *tb[CTA_TUPLE_MAX+1];
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
947
  	int err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
948
  	memset(tuple, 0, sizeof(*tuple));
130ffbc26   Daniel Borkmann   netfilter: check ...
949
950
951
  	err = nla_parse_nested(tb, CTA_TUPLE_MAX, cda[type], tuple_nla_policy);
  	if (err < 0)
  		return err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
952

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
953
  	if (!tb[CTA_TUPLE_IP])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
954
955
956
  		return -EINVAL;
  
  	tuple->src.l3num = l3num;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
957
  	err = ctnetlink_parse_tuple_ip(tb[CTA_TUPLE_IP], tuple);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
958
959
  	if (err < 0)
  		return err;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
960
  	if (!tb[CTA_TUPLE_PROTO])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
961
  		return -EINVAL;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
962
  	err = ctnetlink_parse_tuple_proto(tb[CTA_TUPLE_PROTO], tuple);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
963
964
  	if (err < 0)
  		return err;
deedb5903   Daniel Borkmann   netfilter: nf_con...
965
966
967
968
969
970
971
972
973
  	if (tb[CTA_TUPLE_ZONE]) {
  		if (!zone)
  			return -EINVAL;
  
  		err = ctnetlink_parse_tuple_zone(tb[CTA_TUPLE_ZONE],
  						 type, zone);
  		if (err < 0)
  			return err;
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
974
975
976
977
978
  	/* 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 ...
979
980
  	return 0;
  }
d0b0268fd   Patrick McHardy   netfilter: ctnetl...
981
  static const struct nla_policy help_nla_policy[CTA_HELP_MAX+1] = {
6d1fafcae   Florian Westphal   netfilter: ctnetl...
982
983
  	[CTA_HELP_NAME]		= { .type = NLA_NUL_STRING,
  				    .len = NF_CT_HELPER_NAME_LEN - 1 },
d0b0268fd   Patrick McHardy   netfilter: ctnetl...
984
  };
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
985
986
  static int ctnetlink_parse_help(const struct nlattr *attr, char **helper_name,
  				struct nlattr **helpinfo)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
987
  {
130ffbc26   Daniel Borkmann   netfilter: check ...
988
  	int err;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
989
  	struct nlattr *tb[CTA_HELP_MAX+1];
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
990

130ffbc26   Daniel Borkmann   netfilter: check ...
991
992
993
  	err = nla_parse_nested(tb, CTA_HELP_MAX, attr, help_nla_policy);
  	if (err < 0)
  		return err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
994

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
995
  	if (!tb[CTA_HELP_NAME])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
996
  		return -EINVAL;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
997
  	*helper_name = nla_data(tb[CTA_HELP_NAME]);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
998

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

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1059
  	if (cda[CTA_TUPLE_ORIG])
deedb5903   Daniel Borkmann   netfilter: nf_con...
1060
1061
  		err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG,
  					    u3, &zone);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1062
  	else if (cda[CTA_TUPLE_REPLY])
deedb5903   Daniel Borkmann   netfilter: nf_con...
1063
1064
  		err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY,
  					    u3, &zone);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1065
  	else {
866476f32   Kristian Evensen   netfilter: conntr...
1066
1067
1068
  		return ctnetlink_flush_conntrack(net, cda,
  						 NETLINK_CB(skb).portid,
  						 nlmsg_report(nlh));
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1069
1070
1071
1072
  	}
  
  	if (err < 0)
  		return err;
308ac9143   Daniel Borkmann   netfilter: nf_con...
1073
  	h = nf_conntrack_find_get(net, &zone, &tuple);
9ea8cfd6a   Pablo Neira Ayuso   [NETFILTER]: ctne...
1074
  	if (!h)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1075
  		return -ENOENT;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1076
1077
  
  	ct = nf_ct_tuplehash_to_ctrack(h);
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
1078

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1079
  	if (cda[CTA_ID]) {
77236b6e3   Patrick McHardy   [NETFILTER]: ctne...
1080
  		u_int32_t id = ntohl(nla_get_be32(cda[CTA_ID]));
7f85f9147   Patrick McHardy   [NETFILTER]: nf_c...
1081
  		if (id != (u32)(unsigned long)ct) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1082
1083
1084
  			nf_ct_put(ct);
  			return -ENOENT;
  		}
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
1085
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1086

f330a7fdb   Florian Westphal   netfilter: conntr...
1087
  	nf_ct_delete(ct, NETLINK_CB(skb).portid, nlmsg_report(nlh));
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1088
  	nf_ct_put(ct);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1089
1090
1091
  
  	return 0;
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
1092
1093
1094
1095
  static int ctnetlink_get_conntrack(struct net *net, struct sock *ctnl,
  				   struct sk_buff *skb,
  				   const struct nlmsghdr *nlh,
  				   const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1096
1097
1098
1099
1100
  {
  	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...
1101
  	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1102
  	u_int8_t u3 = nfmsg->nfgen_family;
308ac9143   Daniel Borkmann   netfilter: nf_con...
1103
  	struct nf_conntrack_zone zone;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
1104
  	int err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1105

80d326fab   Pablo Neira Ayuso   netlink: add netl...
1106
1107
1108
1109
1110
  	if (nlh->nlmsg_flags & NLM_F_DUMP) {
  		struct netlink_dump_control c = {
  			.dump = ctnetlink_dump_table,
  			.done = ctnetlink_done,
  		};
866476f32   Kristian Evensen   netfilter: conntr...
1111

0f298a285   Pablo Neira Ayuso   netfilter: ctnetl...
1112
  		if (cda[CTA_MARK] && cda[CTA_MARK_MASK]) {
866476f32   Kristian Evensen   netfilter: conntr...
1113
  			struct ctnetlink_filter *filter;
0f298a285   Pablo Neira Ayuso   netfilter: ctnetl...
1114

866476f32   Kristian Evensen   netfilter: conntr...
1115
1116
1117
  			filter = ctnetlink_alloc_filter(cda);
  			if (IS_ERR(filter))
  				return PTR_ERR(filter);
0f298a285   Pablo Neira Ayuso   netfilter: ctnetl...
1118

0f298a285   Pablo Neira Ayuso   netfilter: ctnetl...
1119
1120
  			c.data = filter;
  		}
80d326fab   Pablo Neira Ayuso   netlink: add netl...
1121
1122
  		return netlink_dump_start(ctnl, skb, nlh, &c);
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1123

ef00f89f1   Patrick McHardy   netfilter: ctnetl...
1124
1125
1126
  	err = ctnetlink_parse_zone(cda[CTA_ZONE], &zone);
  	if (err < 0)
  		return err;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1127
  	if (cda[CTA_TUPLE_ORIG])
deedb5903   Daniel Borkmann   netfilter: nf_con...
1128
1129
  		err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG,
  					    u3, &zone);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1130
  	else if (cda[CTA_TUPLE_REPLY])
deedb5903   Daniel Borkmann   netfilter: nf_con...
1131
1132
  		err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY,
  					    u3, &zone);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1133
1134
1135
1136
1137
  	else
  		return -EINVAL;
  
  	if (err < 0)
  		return err;
308ac9143   Daniel Borkmann   netfilter: nf_con...
1138
  	h = nf_conntrack_find_get(net, &zone, &tuple);
9ea8cfd6a   Pablo Neira Ayuso   [NETFILTER]: ctne...
1139
  	if (!h)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1140
  		return -ENOENT;
9ea8cfd6a   Pablo Neira Ayuso   [NETFILTER]: ctne...
1141

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1142
1143
1144
  	ct = nf_ct_tuplehash_to_ctrack(h);
  
  	err = -ENOMEM;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
1145
1146
  	skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
  	if (skb2 == NULL) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1147
1148
1149
  		nf_ct_put(ct);
  		return -ENOMEM;
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1150

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

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

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

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1346
1347
  	/* Be careful here, modifying NAT bits can screw up things,
  	 * so don't let users modify them directly if they don't pass
5b1158e90   Jozsef Kadlecsik   [NETFILTER]: Add ...
1348
  	 * nf_nat_range. */
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1349
1350
1351
  	ct->status |= status & ~(IPS_NAT_DONE_MASK | IPS_NAT_MASK);
  	return 0;
  }
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1352
  static int
0eba801b6   Pablo Neira Ayuso   netfilter: ctnetl...
1353
  ctnetlink_setup_nat(struct nf_conn *ct, const struct nlattr * const cda[])
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1354
1355
1356
  {
  #ifdef CONFIG_NF_NAT_NEEDED
  	int ret;
fe337ac28   Florian Westphal   netfilter: ctnetl...
1357
1358
  	if (!cda[CTA_NAT_DST] && !cda[CTA_NAT_SRC])
  		return 0;
0eba801b6   Pablo Neira Ayuso   netfilter: ctnetl...
1359
1360
1361
1362
1363
1364
1365
1366
  	ret = ctnetlink_parse_nat_setup(ct, NF_NAT_MANIP_DST,
  					cda[CTA_NAT_DST]);
  	if (ret < 0)
  		return ret;
  
  	ret = ctnetlink_parse_nat_setup(ct, NF_NAT_MANIP_SRC,
  					cda[CTA_NAT_SRC]);
  	return ret;
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1367
  #else
0eba801b6   Pablo Neira Ayuso   netfilter: ctnetl...
1368
1369
  	if (!cda[CTA_NAT_DST] && !cda[CTA_NAT_SRC])
  		return 0;
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1370
1371
1372
  	return -EOPNOTSUPP;
  #endif
  }
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1373

4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
1374
1375
  static int ctnetlink_change_helper(struct nf_conn *ct,
  				   const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1376
1377
  {
  	struct nf_conntrack_helper *helper;
dc808fe28   Harald Welte   [NETFILTER] nf_co...
1378
  	struct nf_conn_help *help = nfct_help(ct);
29fe1b481   Pablo Neira Ayuso   netfilter: ctnetl...
1379
  	char *helpname = NULL;
ae243bee3   Pablo Neira Ayuso   netfilter: ctnetl...
1380
  	struct nlattr *helpinfo = NULL;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1381
  	int err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1382
1383
  	/* don't change helper of sibling connections */
  	if (ct->master)
0adf9d674   Pablo Neira Ayuso   netfilter: ctnetl...
1384
  		return -EBUSY;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1385

ae243bee3   Pablo Neira Ayuso   netfilter: ctnetl...
1386
  	err = ctnetlink_parse_help(cda[CTA_HELP], &helpname, &helpinfo);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1387
1388
  	if (err < 0)
  		return err;
df293bbb6   Yasuyuki Kozakai   [NETFILTER]: ctne...
1389
1390
  	if (!strcmp(helpname, "")) {
  		if (help && help->helper) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1391
1392
  			/* we had a helper before ... */
  			nf_ct_remove_expectations(ct);
a9b3cd7f3   Stephen Hemminger   rcu: convert uses...
1393
  			RCU_INIT_POINTER(help->helper, NULL);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1394
  		}
df293bbb6   Yasuyuki Kozakai   [NETFILTER]: ctne...
1395
1396
  
  		return 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1397
  	}
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
1398

794e68716   Patrick McHardy   netfilter: ctnetl...
1399
1400
  	helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct),
  					    nf_ct_protonum(ct));
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1401
1402
  	if (helper == NULL) {
  #ifdef CONFIG_MODULES
ca7433df3   Jesper Dangaard Brouer   netfilter: conntr...
1403
  		spin_unlock_bh(&nf_conntrack_expect_lock);
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1404
1405
  
  		if (request_module("nfct-helper-%s", helpname) < 0) {
ca7433df3   Jesper Dangaard Brouer   netfilter: conntr...
1406
  			spin_lock_bh(&nf_conntrack_expect_lock);
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1407
1408
  			return -EOPNOTSUPP;
  		}
ca7433df3   Jesper Dangaard Brouer   netfilter: conntr...
1409
  		spin_lock_bh(&nf_conntrack_expect_lock);
794e68716   Patrick McHardy   netfilter: ctnetl...
1410
1411
  		helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct),
  						    nf_ct_protonum(ct));
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1412
1413
1414
  		if (helper)
  			return -EAGAIN;
  #endif
0adf9d674   Pablo Neira Ayuso   netfilter: ctnetl...
1415
  		return -EOPNOTSUPP;
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1416
  	}
df293bbb6   Yasuyuki Kozakai   [NETFILTER]: ctne...
1417

ceceae1b1   Yasuyuki Kozakai   [NETFILTER]: nf_c...
1418
  	if (help) {
ae243bee3   Pablo Neira Ayuso   netfilter: ctnetl...
1419
1420
  		if (help->helper == helper) {
  			/* update private helper data if allowed. */
7be54ca47   Pablo Neira Ayuso   netfilter: nf_ct_...
1421
  			if (helper->from_nlattr)
ae243bee3   Pablo Neira Ayuso   netfilter: ctnetl...
1422
  				helper->from_nlattr(helpinfo, ct);
ceceae1b1   Yasuyuki Kozakai   [NETFILTER]: nf_c...
1423
  			return 0;
fd7462de4   Pablo Neira Ayuso   netfilter: ctnetl...
1424
  		} else
ceceae1b1   Yasuyuki Kozakai   [NETFILTER]: nf_c...
1425
  			return -EBUSY;
ceceae1b1   Yasuyuki Kozakai   [NETFILTER]: nf_c...
1426
  	}
df293bbb6   Yasuyuki Kozakai   [NETFILTER]: ctne...
1427

fd7462de4   Pablo Neira Ayuso   netfilter: ctnetl...
1428
1429
  	/* we cannot set a helper for an existing conntrack */
  	return -EOPNOTSUPP;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1430
  }
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
1431
1432
  static int ctnetlink_change_timeout(struct nf_conn *ct,
  				    const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1433
  {
77236b6e3   Patrick McHardy   [NETFILTER]: ctne...
1434
  	u_int32_t timeout = ntohl(nla_get_be32(cda[CTA_TIMEOUT]));
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
1435

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

f330a7fdb   Florian Westphal   netfilter: conntr...
1438
1439
  	if (test_bit(IPS_DYING_BIT, &ct->status))
  		return -ETIME;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1440
1441
1442
  
  	return 0;
  }
d0b0268fd   Patrick McHardy   netfilter: ctnetl...
1443
1444
1445
1446
1447
  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...
1448
1449
  static int ctnetlink_change_protoinfo(struct nf_conn *ct,
  				      const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1450
  {
399383246   Patrick McHardy   netfilter: nfnetl...
1451
1452
  	const struct nlattr *attr = cda[CTA_PROTOINFO];
  	struct nlattr *tb[CTA_PROTOINFO_MAX+1];
605dcad6c   Martin Josefsson   [NETFILTER]: nf_c...
1453
  	struct nf_conntrack_l4proto *l4proto;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1454
  	int err = 0;
130ffbc26   Daniel Borkmann   netfilter: check ...
1455
1456
1457
  	err = nla_parse_nested(tb, CTA_PROTOINFO_MAX, attr, protoinfo_policy);
  	if (err < 0)
  		return err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1458

cd91566e4   Florian Westphal   netfilter: ctnetl...
1459
1460
  	rcu_read_lock();
  	l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct));
fdf708322   Patrick McHardy   [NETFILTER]: nfne...
1461
1462
  	if (l4proto->from_nlattr)
  		err = l4proto->from_nlattr(tb, ct);
cd91566e4   Florian Westphal   netfilter: ctnetl...
1463
  	rcu_read_unlock();
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1464
1465
1466
  
  	return err;
  }
41d73ec05   Patrick McHardy   netfilter: nf_con...
1467
1468
1469
1470
  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...
1471
  };
4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
1472
1473
  static int change_seq_adj(struct nf_ct_seqadj *seq,
  			  const struct nlattr * const attr)
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1474
  {
130ffbc26   Daniel Borkmann   netfilter: check ...
1475
  	int err;
41d73ec05   Patrick McHardy   netfilter: nf_con...
1476
  	struct nlattr *cda[CTA_SEQADJ_MAX+1];
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1477

41d73ec05   Patrick McHardy   netfilter: nf_con...
1478
  	err = nla_parse_nested(cda, CTA_SEQADJ_MAX, attr, seqadj_policy);
130ffbc26   Daniel Borkmann   netfilter: check ...
1479
1480
  	if (err < 0)
  		return err;
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1481

41d73ec05   Patrick McHardy   netfilter: nf_con...
1482
  	if (!cda[CTA_SEQADJ_CORRECTION_POS])
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1483
  		return -EINVAL;
41d73ec05   Patrick McHardy   netfilter: nf_con...
1484
1485
  	seq->correction_pos =
  		ntohl(nla_get_be32(cda[CTA_SEQADJ_CORRECTION_POS]));
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1486

41d73ec05   Patrick McHardy   netfilter: nf_con...
1487
  	if (!cda[CTA_SEQADJ_OFFSET_BEFORE])
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1488
  		return -EINVAL;
41d73ec05   Patrick McHardy   netfilter: nf_con...
1489
1490
  	seq->offset_before =
  		ntohl(nla_get_be32(cda[CTA_SEQADJ_OFFSET_BEFORE]));
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1491

41d73ec05   Patrick McHardy   netfilter: nf_con...
1492
  	if (!cda[CTA_SEQADJ_OFFSET_AFTER])
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1493
  		return -EINVAL;
41d73ec05   Patrick McHardy   netfilter: nf_con...
1494
1495
  	seq->offset_after =
  		ntohl(nla_get_be32(cda[CTA_SEQADJ_OFFSET_AFTER]));
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1496
1497
1498
1499
1500
  
  	return 0;
  }
  
  static int
41d73ec05   Patrick McHardy   netfilter: nf_con...
1501
1502
  ctnetlink_change_seq_adj(struct nf_conn *ct,
  			 const struct nlattr * const cda[])
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1503
  {
41d73ec05   Patrick McHardy   netfilter: nf_con...
1504
  	struct nf_conn_seqadj *seqadj = nfct_seqadj(ct);
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1505
  	int ret = 0;
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1506

41d73ec05   Patrick McHardy   netfilter: nf_con...
1507
  	if (!seqadj)
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1508
  		return 0;
41d73ec05   Patrick McHardy   netfilter: nf_con...
1509
1510
1511
  	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...
1512
1513
1514
1515
1516
  		if (ret < 0)
  			return ret;
  
  		ct->status |= IPS_SEQ_ADJUST;
  	}
41d73ec05   Patrick McHardy   netfilter: nf_con...
1517
1518
1519
  	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...
1520
1521
1522
1523
1524
1525
1526
1527
  		if (ret < 0)
  			return ret;
  
  		ct->status |= IPS_SEQ_ADJUST;
  	}
  
  	return 0;
  }
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1528

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1529
  static int
9b21f6a90   Florian Westphal   netfilter: ctnetl...
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
  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...
1555
1556
  ctnetlink_change_conntrack(struct nf_conn *ct,
  			   const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1557
1558
  {
  	int err;
e098360f1   Pablo Neira Ayuso   netfilter: ctnetl...
1559
1560
1561
  	/* 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...
1562
  	if (cda[CTA_HELP]) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1563
1564
1565
1566
  		err = ctnetlink_change_helper(ct, cda);
  		if (err < 0)
  			return err;
  	}
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1567
  	if (cda[CTA_TIMEOUT]) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1568
1569
1570
1571
  		err = ctnetlink_change_timeout(ct, cda);
  		if (err < 0)
  			return err;
  	}
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1572
  	if (cda[CTA_STATUS]) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1573
1574
1575
1576
  		err = ctnetlink_change_status(ct, cda);
  		if (err < 0)
  			return err;
  	}
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1577
  	if (cda[CTA_PROTOINFO]) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1578
1579
1580
1581
  		err = ctnetlink_change_protoinfo(ct, cda);
  		if (err < 0)
  			return err;
  	}
bcd1e830a   Martin Josefsson   [NETFILTER]: fix ...
1582
  #if defined(CONFIG_NF_CONNTRACK_MARK)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1583
  	if (cda[CTA_MARK])
77236b6e3   Patrick McHardy   [NETFILTER]: ctne...
1584
  		ct->mark = ntohl(nla_get_be32(cda[CTA_MARK]));
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1585
  #endif
41d73ec05   Patrick McHardy   netfilter: nf_con...
1586
1587
  	if (cda[CTA_SEQ_ADJ_ORIG] || cda[CTA_SEQ_ADJ_REPLY]) {
  		err = ctnetlink_change_seq_adj(ct, cda);
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1588
1589
1590
  		if (err < 0)
  			return err;
  	}
41d73ec05   Patrick McHardy   netfilter: nf_con...
1591

9b21f6a90   Florian Westphal   netfilter: ctnetl...
1592
1593
1594
1595
1596
  	if (cda[CTA_LABELS]) {
  		err = ctnetlink_attach_labels(ct, cda);
  		if (err < 0)
  			return err;
  	}
13eae15a2   Pablo Neira Ayuso   [NETFILTER]: ctne...
1597

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1598
1599
  	return 0;
  }
f0a3c0869   Pablo Neira Ayuso   netfilter: ctnetl...
1600
  static struct nf_conn *
308ac9143   Daniel Borkmann   netfilter: nf_con...
1601
1602
  ctnetlink_create_conntrack(struct net *net,
  			   const struct nf_conntrack_zone *zone,
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
1603
  			   const struct nlattr * const cda[],
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1604
  			   struct nf_conntrack_tuple *otuple,
5faa1f4cb   Pablo Neira Ayuso   [NETFILTER]: nf_c...
1605
  			   struct nf_conntrack_tuple *rtuple,
7ec474967   Pablo Neira Ayuso   netfilter: ctnetl...
1606
  			   u8 u3)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1607
1608
1609
  {
  	struct nf_conn *ct;
  	int err = -EINVAL;
ceceae1b1   Yasuyuki Kozakai   [NETFILTER]: nf_c...
1610
  	struct nf_conntrack_helper *helper;
315c34dae   Pablo Neira Ayuso   netfilter: ctnetl...
1611
  	struct nf_conn_tstamp *tstamp;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1612

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

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

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

1575e7ea0   Pablo Neira Ayuso   netfilter: ctnetl...
1622
  	rcu_read_lock();
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1623
   	if (cda[CTA_HELP]) {
29fe1b481   Pablo Neira Ayuso   netfilter: ctnetl...
1624
  		char *helpname = NULL;
ae243bee3   Pablo Neira Ayuso   netfilter: ctnetl...
1625
1626
1627
  		struct nlattr *helpinfo = NULL;
  
  		err = ctnetlink_parse_help(cda[CTA_HELP], &helpname, &helpinfo);
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1628
1629
   		if (err < 0)
  			goto err2;
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1630

794e68716   Patrick McHardy   netfilter: ctnetl...
1631
1632
  		helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct),
  						    nf_ct_protonum(ct));
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1633
1634
1635
1636
1637
  		if (helper == NULL) {
  			rcu_read_unlock();
  #ifdef CONFIG_MODULES
  			if (request_module("nfct-helper-%s", helpname) < 0) {
  				err = -EOPNOTSUPP;
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1638
  				goto err1;
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1639
1640
1641
  			}
  
  			rcu_read_lock();
794e68716   Patrick McHardy   netfilter: ctnetl...
1642
1643
1644
  			helper = __nf_conntrack_helper_find(helpname,
  							    nf_ct_l3num(ct),
  							    nf_ct_protonum(ct));
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1645
  			if (helper) {
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1646
  				err = -EAGAIN;
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1647
  				goto err2;
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1648
1649
1650
1651
  			}
  			rcu_read_unlock();
  #endif
  			err = -EOPNOTSUPP;
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1652
  			goto err1;
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1653
1654
  		} else {
  			struct nf_conn_help *help;
1afc56794   Pablo Neira Ayuso   netfilter: nf_ct_...
1655
  			help = nf_ct_helper_ext_add(ct, helper, GFP_ATOMIC);
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1656
  			if (help == NULL) {
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1657
  				err = -ENOMEM;
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1658
  				goto err2;
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1659
  			}
ae243bee3   Pablo Neira Ayuso   netfilter: ctnetl...
1660
  			/* set private helper data if allowed. */
7be54ca47   Pablo Neira Ayuso   netfilter: nf_ct_...
1661
  			if (helper->from_nlattr)
ae243bee3   Pablo Neira Ayuso   netfilter: ctnetl...
1662
  				helper->from_nlattr(helpinfo, ct);
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1663
1664
  
  			/* not in hash table yet so not strictly necessary */
a9b3cd7f3   Stephen Hemminger   rcu: convert uses...
1665
  			RCU_INIT_POINTER(help->helper, helper);
226c0c0ef   Pablo Neira Ayuso   netfilter: ctnetl...
1666
1667
1668
  		}
  	} else {
  		/* try an implicit helper assignation */
b2a15a604   Patrick McHardy   netfilter: nf_con...
1669
  		err = __nf_ct_try_assign_helper(ct, NULL, GFP_ATOMIC);
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1670
1671
  		if (err < 0)
  			goto err2;
1575e7ea0   Pablo Neira Ayuso   netfilter: ctnetl...
1672
  	}
0eba801b6   Pablo Neira Ayuso   netfilter: ctnetl...
1673
1674
1675
  	err = ctnetlink_setup_nat(ct, cda);
  	if (err < 0)
  		goto err2;
e6a7d3c04   Pablo Neira Ayuso   netfilter: ctnetl...
1676

a88e22adf   Pablo Neira Ayuso   netfilter: ctnetl...
1677
  	nf_ct_acct_ext_add(ct, GFP_ATOMIC);
a992ca2a0   Pablo Neira Ayuso   netfilter: nf_con...
1678
  	nf_ct_tstamp_ext_add(ct, GFP_ATOMIC);
a88e22adf   Pablo Neira Ayuso   netfilter: ctnetl...
1679
  	nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC);
c539f0171   Florian Westphal   netfilter: add co...
1680
  	nf_ct_labels_ext_add(ct);
a88e22adf   Pablo Neira Ayuso   netfilter: ctnetl...
1681
1682
1683
1684
1685
  	/* 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...
1686
1687
  		if (err < 0)
  			goto err2;
bbb3357d1   Pablo Neira Ayuso   [NETFILTER]: ctne...
1688
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1689

41d73ec05   Patrick McHardy   netfilter: nf_con...
1690
1691
  	if (cda[CTA_SEQ_ADJ_ORIG] || cda[CTA_SEQ_ADJ_REPLY]) {
  		err = ctnetlink_change_seq_adj(ct, cda);
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1692
1693
  		if (err < 0)
  			goto err2;
c969aa7d2   Pablo Neira Ayuso   netfilter: ctnetl...
1694
  	}
c969aa7d2   Pablo Neira Ayuso   netfilter: ctnetl...
1695

e5fc9e7a6   Changli Gao   netfilter: nf_con...
1696
  	memset(&ct->proto, 0, sizeof(ct->proto));
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1697
  	if (cda[CTA_PROTOINFO]) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1698
  		err = ctnetlink_change_protoinfo(ct, cda);
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1699
1700
  		if (err < 0)
  			goto err2;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1701
  	}
bcd1e830a   Martin Josefsson   [NETFILTER]: fix ...
1702
  #if defined(CONFIG_NF_CONNTRACK_MARK)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1703
  	if (cda[CTA_MARK])
77236b6e3   Patrick McHardy   [NETFILTER]: ctne...
1704
  		ct->mark = ntohl(nla_get_be32(cda[CTA_MARK]));
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1705
  #endif
5faa1f4cb   Pablo Neira Ayuso   [NETFILTER]: nf_c...
1706
  	/* setup master conntrack: this is a confirmed expectation */
7ec474967   Pablo Neira Ayuso   netfilter: ctnetl...
1707
1708
1709
1710
  	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...
1711
1712
  		err = ctnetlink_parse_tuple(cda, &master, CTA_TUPLE_MASTER,
  					    u3, NULL);
7ec474967   Pablo Neira Ayuso   netfilter: ctnetl...
1713
  		if (err < 0)
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1714
  			goto err2;
7ec474967   Pablo Neira Ayuso   netfilter: ctnetl...
1715

ef00f89f1   Patrick McHardy   netfilter: ctnetl...
1716
  		master_h = nf_conntrack_find_get(net, zone, &master);
7ec474967   Pablo Neira Ayuso   netfilter: ctnetl...
1717
1718
  		if (master_h == NULL) {
  			err = -ENOENT;
0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1719
  			goto err2;
7ec474967   Pablo Neira Ayuso   netfilter: ctnetl...
1720
1721
  		}
  		master_ct = nf_ct_tuplehash_to_ctrack(master_h);
f2a89004d   Pablo Neira Ayuso   [NETFILTER]: ctne...
1722
  		__set_bit(IPS_EXPECTED_BIT, &ct->status);
5faa1f4cb   Pablo Neira Ayuso   [NETFILTER]: nf_c...
1723
  		ct->master = master_ct;
f2a89004d   Pablo Neira Ayuso   [NETFILTER]: ctne...
1724
  	}
315c34dae   Pablo Neira Ayuso   netfilter: ctnetl...
1725
1726
  	tstamp = nf_conn_tstamp_find(ct);
  	if (tstamp)
d2de875c6   Eric Dumazet   net: use ktime_ge...
1727
  		tstamp->start = ktime_get_real_ns();
5faa1f4cb   Pablo Neira Ayuso   [NETFILTER]: nf_c...
1728

7d367e066   Jozsef Kadlecsik   netfilter: ctnetl...
1729
1730
1731
  	err = nf_conntrack_hash_check_insert(ct);
  	if (err < 0)
  		goto err2;
58a3c9bb0   Patrick McHardy   [NETFILTER]: nf_c...
1732
  	rcu_read_unlock();
dafc741cf   Yasuyuki Kozakai   [NETFILTER]: nfct...
1733

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

0f5b3e85a   Patrick McHardy   netfilter: ctnetl...
1736
1737
1738
  err2:
  	rcu_read_unlock();
  err1:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1739
  	nf_conntrack_free(ct);
f0a3c0869   Pablo Neira Ayuso   netfilter: ctnetl...
1740
  	return ERR_PTR(err);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1741
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
1742
1743
1744
1745
  static int ctnetlink_new_conntrack(struct net *net, struct sock *ctnl,
  				   struct sk_buff *skb,
  				   const struct nlmsghdr *nlh,
  				   const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1746
1747
1748
  {
  	struct nf_conntrack_tuple otuple, rtuple;
  	struct nf_conntrack_tuple_hash *h = NULL;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
1749
  	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
7d367e066   Jozsef Kadlecsik   netfilter: ctnetl...
1750
  	struct nf_conn *ct;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1751
  	u_int8_t u3 = nfmsg->nfgen_family;
308ac9143   Daniel Borkmann   netfilter: nf_con...
1752
  	struct nf_conntrack_zone zone;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
1753
1754
1755
1756
1757
  	int err;
  
  	err = ctnetlink_parse_zone(cda[CTA_ZONE], &zone);
  	if (err < 0)
  		return err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1758

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1759
  	if (cda[CTA_TUPLE_ORIG]) {
deedb5903   Daniel Borkmann   netfilter: nf_con...
1760
1761
  		err = ctnetlink_parse_tuple(cda, &otuple, CTA_TUPLE_ORIG,
  					    u3, &zone);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1762
1763
1764
  		if (err < 0)
  			return err;
  	}
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1765
  	if (cda[CTA_TUPLE_REPLY]) {
deedb5903   Daniel Borkmann   netfilter: nf_con...
1766
1767
  		err = ctnetlink_parse_tuple(cda, &rtuple, CTA_TUPLE_REPLY,
  					    u3, &zone);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1768
1769
1770
  		if (err < 0)
  			return err;
  	}
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1771
  	if (cda[CTA_TUPLE_ORIG])
308ac9143   Daniel Borkmann   netfilter: nf_con...
1772
  		h = nf_conntrack_find_get(net, &zone, &otuple);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1773
  	else if (cda[CTA_TUPLE_REPLY])
308ac9143   Daniel Borkmann   netfilter: nf_con...
1774
  		h = nf_conntrack_find_get(net, &zone, &rtuple);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1775
1776
  
  	if (h == NULL) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1777
  		err = -ENOENT;
f0a3c0869   Pablo Neira Ayuso   netfilter: ctnetl...
1778
  		if (nlh->nlmsg_flags & NLM_F_CREATE) {
fecc1133b   Pablo Neira Ayuso   netfilter: ctnetl...
1779
  			enum ip_conntrack_events events;
5faa1f4cb   Pablo Neira Ayuso   [NETFILTER]: nf_c...
1780

442fad942   Florian Westphal   netfilter: ctnetl...
1781
1782
  			if (!cda[CTA_TUPLE_ORIG] || !cda[CTA_TUPLE_REPLY])
  				return -EINVAL;
aa0c2c68a   Liping Zhang   netfilter: ctnetl...
1783
1784
  			if (otuple.dst.protonum != rtuple.dst.protonum)
  				return -EINVAL;
442fad942   Florian Westphal   netfilter: ctnetl...
1785

308ac9143   Daniel Borkmann   netfilter: nf_con...
1786
  			ct = ctnetlink_create_conntrack(net, &zone, cda, &otuple,
f0a3c0869   Pablo Neira Ayuso   netfilter: ctnetl...
1787
  							&rtuple, u3);
7d367e066   Jozsef Kadlecsik   netfilter: ctnetl...
1788
1789
  			if (IS_ERR(ct))
  				return PTR_ERR(ct);
f0a3c0869   Pablo Neira Ayuso   netfilter: ctnetl...
1790
  			err = 0;
fecc1133b   Pablo Neira Ayuso   netfilter: ctnetl...
1791
1792
1793
1794
  			if (test_bit(IPS_EXPECTED_BIT, &ct->status))
  				events = IPCT_RELATED;
  			else
  				events = IPCT_NEW;
9b21f6a90   Florian Westphal   netfilter: ctnetl...
1795
1796
1797
  			if (cda[CTA_LABELS] &&
  			    ctnetlink_attach_labels(ct, cda) == 0)
  				events |= (1 << IPCT_LABEL);
858b31330   Patrick McHardy   netfilter: nf_con...
1798
1799
  			nf_conntrack_eventmask_report((1 << IPCT_REPLY) |
  						      (1 << IPCT_ASSURED) |
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
1800
1801
  						      (1 << IPCT_HELPER) |
  						      (1 << IPCT_PROTOINFO) |
41d73ec05   Patrick McHardy   netfilter: nf_con...
1802
  						      (1 << IPCT_SEQADJ) |
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
1803
  						      (1 << IPCT_MARK) | events,
15e473046   Eric W. Biederman   netlink: Rename p...
1804
  						      ct, NETLINK_CB(skb).portid,
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
1805
  						      nlmsg_report(nlh));
f0a3c0869   Pablo Neira Ayuso   netfilter: ctnetl...
1806
  			nf_ct_put(ct);
7d367e066   Jozsef Kadlecsik   netfilter: ctnetl...
1807
  		}
5faa1f4cb   Pablo Neira Ayuso   [NETFILTER]: nf_c...
1808

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1809
1810
1811
  		return err;
  	}
  	/* implicit 'else' */
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1812
  	err = -EEXIST;
7d367e066   Jozsef Kadlecsik   netfilter: ctnetl...
1813
  	ct = nf_ct_tuplehash_to_ctrack(h);
ff4ca8273   Pablo Neira Ayuso   [NETFILTER]: ctne...
1814
  	if (!(nlh->nlmsg_flags & NLM_F_EXCL)) {
ca7433df3   Jesper Dangaard Brouer   netfilter: conntr...
1815
  		spin_lock_bh(&nf_conntrack_expect_lock);
19abb7b09   Pablo Neira Ayuso   netfilter: ctnetl...
1816
  		err = ctnetlink_change_conntrack(ct, cda);
ca7433df3   Jesper Dangaard Brouer   netfilter: conntr...
1817
  		spin_unlock_bh(&nf_conntrack_expect_lock);
19abb7b09   Pablo Neira Ayuso   netfilter: ctnetl...
1818
  		if (err == 0) {
858b31330   Patrick McHardy   netfilter: nf_con...
1819
1820
  			nf_conntrack_eventmask_report((1 << IPCT_REPLY) |
  						      (1 << IPCT_ASSURED) |
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
1821
  						      (1 << IPCT_HELPER) |
797a7d66d   Florian Westphal   netfilter: ctnetl...
1822
  						      (1 << IPCT_LABEL) |
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
1823
  						      (1 << IPCT_PROTOINFO) |
41d73ec05   Patrick McHardy   netfilter: nf_con...
1824
  						      (1 << IPCT_SEQADJ) |
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
1825
  						      (1 << IPCT_MARK),
15e473046   Eric W. Biederman   netlink: Rename p...
1826
  						      ct, NETLINK_CB(skb).portid,
a0891aa6a   Pablo Neira Ayuso   netfilter: conntr...
1827
  						      nlmsg_report(nlh));
7d367e066   Jozsef Kadlecsik   netfilter: ctnetl...
1828
  		}
ff4ca8273   Pablo Neira Ayuso   [NETFILTER]: ctne...
1829
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1830

7d367e066   Jozsef Kadlecsik   netfilter: ctnetl...
1831
  	nf_ct_put(ct);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
1832
1833
  	return err;
  }
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1834
  static int
15e473046   Eric W. Biederman   netlink: Rename p...
1835
  ctnetlink_ct_stat_cpu_fill_info(struct sk_buff *skb, u32 portid, u32 seq,
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1836
1837
1838
1839
  				__u16 cpu, const struct ip_conntrack_stat *st)
  {
  	struct nlmsghdr *nlh;
  	struct nfgenmsg *nfmsg;
15e473046   Eric W. Biederman   netlink: Rename p...
1840
  	unsigned int flags = portid ? NLM_F_MULTI : 0, event;
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1841
1842
  
  	event = (NFNL_SUBSYS_CTNETLINK << 8 | IPCTNL_MSG_CT_GET_STATS_CPU);
15e473046   Eric W. Biederman   netlink: Rename p...
1843
  	nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1844
1845
1846
1847
1848
1849
1850
  	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...
1851
  	if (nla_put_be32(skb, CTA_STATS_FOUND, htonl(st->found)) ||
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1852
1853
  	    nla_put_be32(skb, CTA_STATS_INVALID, htonl(st->invalid)) ||
  	    nla_put_be32(skb, CTA_STATS_IGNORE, htonl(st->ignore)) ||
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
  	    nla_put_be32(skb, CTA_STATS_INSERT, htonl(st->insert)) ||
  	    nla_put_be32(skb, CTA_STATS_INSERT_FAILED,
  				htonl(st->insert_failed)) ||
  	    nla_put_be32(skb, CTA_STATS_DROP, htonl(st->drop)) ||
  	    nla_put_be32(skb, CTA_STATS_EARLY_DROP, htonl(st->early_drop)) ||
  	    nla_put_be32(skb, CTA_STATS_ERROR, htonl(st->error)) ||
  	    nla_put_be32(skb, CTA_STATS_SEARCH_RESTART,
  				htonl(st->search_restart)))
  		goto nla_put_failure;
  
  	nlmsg_end(skb, nlh);
  	return skb->len;
  
  nla_put_failure:
  nlmsg_failure:
  	nlmsg_cancel(skb, nlh);
  	return -1;
  }
  
  static int
  ctnetlink_ct_stat_cpu_dump(struct sk_buff *skb, struct netlink_callback *cb)
  {
  	int cpu;
  	struct net *net = sock_net(skb->sk);
  
  	if (cb->args[0] == nr_cpu_ids)
  		return 0;
  
  	for (cpu = cb->args[0]; cpu < nr_cpu_ids; cpu++) {
  		const struct ip_conntrack_stat *st;
  
  		if (!cpu_possible(cpu))
  			continue;
  
  		st = per_cpu_ptr(net->ct.stat, cpu);
  		if (ctnetlink_ct_stat_cpu_fill_info(skb,
15e473046   Eric W. Biederman   netlink: Rename p...
1890
  						    NETLINK_CB(cb->skb).portid,
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1891
1892
1893
1894
1895
1896
1897
1898
  						    cb->nlh->nlmsg_seq,
  						    cpu, st) < 0)
  				break;
  	}
  	cb->args[0] = cpu;
  
  	return skb->len;
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
1899
1900
1901
1902
  static int ctnetlink_stat_ct_cpu(struct net *net, struct sock *ctnl,
  				 struct sk_buff *skb,
  				 const struct nlmsghdr *nlh,
  				 const struct nlattr * const cda[])
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
  {
  	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...
1915
  ctnetlink_stat_ct_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1916
1917
1918
1919
  			    struct net *net)
  {
  	struct nlmsghdr *nlh;
  	struct nfgenmsg *nfmsg;
15e473046   Eric W. Biederman   netlink: Rename p...
1920
  	unsigned int flags = portid ? NLM_F_MULTI : 0, event;
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1921
1922
1923
  	unsigned int nr_conntracks = atomic_read(&net->ct.count);
  
  	event = (NFNL_SUBSYS_CTNETLINK << 8 | IPCTNL_MSG_CT_GET_STATS);
15e473046   Eric W. Biederman   netlink: Rename p...
1924
  	nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
  	if (nlh == NULL)
  		goto nlmsg_failure;
  
  	nfmsg = nlmsg_data(nlh);
  	nfmsg->nfgen_family = AF_UNSPEC;
  	nfmsg->version      = NFNETLINK_V0;
  	nfmsg->res_id	    = 0;
  
  	if (nla_put_be32(skb, CTA_STATS_GLOBAL_ENTRIES, htonl(nr_conntracks)))
  		goto nla_put_failure;
  
  	nlmsg_end(skb, nlh);
  	return skb->len;
  
  nla_put_failure:
  nlmsg_failure:
  	nlmsg_cancel(skb, nlh);
  	return -1;
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
1944
1945
1946
  static int ctnetlink_stat_ct(struct net *net, struct sock *ctnl,
  			     struct sk_buff *skb, const struct nlmsghdr *nlh,
  			     const struct nlattr * const cda[])
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1947
1948
1949
1950
1951
1952
1953
  {
  	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...
1954
  	err = ctnetlink_stat_ct_fill_info(skb2, NETLINK_CB(skb).portid,
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1955
1956
1957
1958
1959
  					  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...
1960
  	err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT);
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
  	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...
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
  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...
1992
  #ifdef CONFIG_NETFILTER_NETLINK_GLUE_CT
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
1993
  static size_t
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
1994
  ctnetlink_glue_build_size(const struct nf_conn *ct)
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
  {
  	return 3 * nla_total_size(0) /* CTA_TUPLE_ORIG|REPL|MASTER */
  	       + 3 * nla_total_size(0) /* CTA_TUPLE_IP */
  	       + 3 * nla_total_size(0) /* CTA_TUPLE_PROTO */
  	       + 3 * nla_total_size(sizeof(u_int8_t)) /* CTA_PROTO_NUM */
  	       + nla_total_size(sizeof(u_int32_t)) /* CTA_ID */
  	       + nla_total_size(sizeof(u_int32_t)) /* CTA_STATUS */
  	       + nla_total_size(sizeof(u_int32_t)) /* CTA_TIMEOUT */
  	       + nla_total_size(0) /* CTA_PROTOINFO */
  	       + nla_total_size(0) /* CTA_HELP */
  	       + nla_total_size(NF_CT_HELPER_NAME_LEN) /* CTA_HELP_NAME */
  	       + ctnetlink_secctx_size(ct)
  #ifdef CONFIG_NF_NAT_NEEDED
  	       + 2 * nla_total_size(0) /* CTA_NAT_SEQ_ADJ_ORIG|REPL */
  	       + 6 * nla_total_size(sizeof(u_int32_t)) /* CTA_NAT_SEQ_OFFSET */
  #endif
  #ifdef CONFIG_NF_CONNTRACK_MARK
  	       + nla_total_size(sizeof(u_int32_t)) /* CTA_MARK */
  #endif
4a001068d   Ken-ichirou MATSUZAWA   netfilter: ctnetl...
2014
  #ifdef CONFIG_NF_CONNTRACK_ZONES
deedb5903   Daniel Borkmann   netfilter: nf_con...
2015
  	       + nla_total_size(sizeof(u_int16_t)) /* CTA_ZONE|CTA_TUPLE_ZONE */
4a001068d   Ken-ichirou MATSUZAWA   netfilter: ctnetl...
2016
  #endif
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2017
2018
2019
  	       + ctnetlink_proto_size(ct)
  	       ;
  }
224a05975   Ken-ichirou MATSUZAWA   netfilter: ctnetl...
2020
  static struct nf_conn *ctnetlink_glue_get_ct(const struct sk_buff *skb,
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2021
  					     enum ip_conntrack_info *ctinfo)
b7bd1809e   Pablo Neira Ayuso   netfilter: nfnetl...
2022
2023
2024
2025
2026
2027
2028
2029
2030
  {
  	struct nf_conn *ct;
  
  	ct = nf_ct_get(skb, ctinfo);
  	if (ct && nf_ct_is_untracked(ct))
  		ct = NULL;
  
  	return ct;
  }
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2031
  static int __ctnetlink_glue_build(struct sk_buff *skb, struct nf_conn *ct)
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2032
  {
308ac9143   Daniel Borkmann   netfilter: nf_con...
2033
  	const struct nf_conntrack_zone *zone;
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2034
2035
2036
  	struct nlattr *nest_parms;
  
  	rcu_read_lock();
deedb5903   Daniel Borkmann   netfilter: nf_con...
2037
  	zone = nf_ct_zone(ct);
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2038
2039
2040
2041
2042
  	nest_parms = nla_nest_start(skb, CTA_TUPLE_ORIG | NLA_F_NESTED);
  	if (!nest_parms)
  		goto nla_put_failure;
  	if (ctnetlink_dump_tuples(skb, nf_ct_tuple(ct, IP_CT_DIR_ORIGINAL)) < 0)
  		goto nla_put_failure;
deedb5903   Daniel Borkmann   netfilter: nf_con...
2043
2044
2045
  	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...
2046
2047
2048
2049
2050
2051
2052
  	nla_nest_end(skb, nest_parms);
  
  	nest_parms = nla_nest_start(skb, CTA_TUPLE_REPLY | NLA_F_NESTED);
  	if (!nest_parms)
  		goto nla_put_failure;
  	if (ctnetlink_dump_tuples(skb, nf_ct_tuple(ct, IP_CT_DIR_REPLY)) < 0)
  		goto nla_put_failure;
deedb5903   Daniel Borkmann   netfilter: nf_con...
2053
2054
2055
  	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...
2056
  	nla_nest_end(skb, nest_parms);
deedb5903   Daniel Borkmann   netfilter: nf_con...
2057
2058
  	if (ctnetlink_dump_zone_id(skb, CTA_ZONE, zone,
  				   NF_CT_DEFAULT_ZONE_DIR) < 0)
308ac9143   Daniel Borkmann   netfilter: nf_con...
2059
  		goto nla_put_failure;
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
  
  	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...
2084
  	    ctnetlink_dump_ct_seq_adj(skb, ct) < 0)
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2085
2086
2087
2088
2089
2090
  		goto nla_put_failure;
  
  #ifdef CONFIG_NF_CONNTRACK_MARK
  	if (ct->mark && ctnetlink_dump_mark(skb, ct) < 0)
  		goto nla_put_failure;
  #endif
0ceabd838   Florian Westphal   netfilter: ctnetl...
2091
2092
  	if (ctnetlink_dump_labels(skb, ct) < 0)
  		goto nla_put_failure;
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2093
2094
2095
2096
2097
2098
2099
2100
2101
  	rcu_read_unlock();
  	return 0;
  
  nla_put_failure:
  	rcu_read_unlock();
  	return -ENOSPC;
  }
  
  static int
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2102
2103
2104
  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...
2105
2106
2107
2108
2109
2110
  {
  	struct nlattr *nest_parms;
  
  	nest_parms = nla_nest_start(skb, ct_attr | NLA_F_NESTED);
  	if (!nest_parms)
  		goto nla_put_failure;
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2111
  	if (__ctnetlink_glue_build(skb, ct) < 0)
b7bd1809e   Pablo Neira Ayuso   netfilter: nfnetl...
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
  		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
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2126
  ctnetlink_glue_parse_ct(const struct nlattr *cda[], struct nf_conn *ct)
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
  {
  	int err;
  
  	if (cda[CTA_TIMEOUT]) {
  		err = ctnetlink_change_timeout(ct, cda);
  		if (err < 0)
  			return err;
  	}
  	if (cda[CTA_STATUS]) {
  		err = ctnetlink_change_status(ct, cda);
  		if (err < 0)
  			return err;
  	}
  	if (cda[CTA_HELP]) {
  		err = ctnetlink_change_helper(ct, cda);
  		if (err < 0)
  			return err;
  	}
9b21f6a90   Florian Westphal   netfilter: ctnetl...
2145
2146
2147
2148
2149
  	if (cda[CTA_LABELS]) {
  		err = ctnetlink_attach_labels(ct, cda);
  		if (err < 0)
  			return err;
  	}
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2150
  #if defined(CONFIG_NF_CONNTRACK_MARK)
534473c60   Florian Westphal   netfilter: ctnetl...
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
  	if (cda[CTA_MARK]) {
  		u32 mask = 0, mark, newmark;
  		if (cda[CTA_MARK_MASK])
  			mask = ~ntohl(nla_get_be32(cda[CTA_MARK_MASK]));
  
  		mark = ntohl(nla_get_be32(cda[CTA_MARK]));
  		newmark = (ct->mark & mask) ^ mark;
  		if (newmark != ct->mark)
  			ct->mark = newmark;
  	}
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2161
2162
2163
2164
2165
  #endif
  	return 0;
  }
  
  static int
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2166
  ctnetlink_glue_parse(const struct nlattr *attr, struct nf_conn *ct)
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2167
2168
  {
  	struct nlattr *cda[CTA_MAX+1];
68e035c95   Pablo Neira Ayuso   netfilter: ctnetl...
2169
  	int ret;
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2170

130ffbc26   Daniel Borkmann   netfilter: check ...
2171
2172
2173
  	ret = nla_parse_nested(cda, CTA_MAX, attr, ct_nla_policy);
  	if (ret < 0)
  		return ret;
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2174

ca7433df3   Jesper Dangaard Brouer   netfilter: conntr...
2175
  	spin_lock_bh(&nf_conntrack_expect_lock);
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2176
  	ret = ctnetlink_glue_parse_ct((const struct nlattr **)cda, ct);
ca7433df3   Jesper Dangaard Brouer   netfilter: conntr...
2177
  	spin_unlock_bh(&nf_conntrack_expect_lock);
68e035c95   Pablo Neira Ayuso   netfilter: ctnetl...
2178
2179
  
  	return ret;
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2180
  }
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2181
2182
2183
2184
  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...
2185
2186
2187
2188
  {
  	int err;
  
  	err = ctnetlink_parse_tuple(cda, tuple, CTA_EXPECT_TUPLE,
deedb5903   Daniel Borkmann   netfilter: nf_con...
2189
  				    nf_ct_l3num(ct), NULL);
bd0779370   Pablo Neira Ayuso   netfilter: nfnetl...
2190
2191
2192
2193
  	if (err < 0)
  		return err;
  
  	return ctnetlink_parse_tuple(cda, mask, CTA_EXPECT_MASK,
deedb5903   Daniel Borkmann   netfilter: nf_con...
2194
  				     nf_ct_l3num(ct), NULL);
bd0779370   Pablo Neira Ayuso   netfilter: nfnetl...
2195
2196
2197
  }
  
  static int
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2198
2199
  ctnetlink_glue_attach_expect(const struct nlattr *attr, struct nf_conn *ct,
  			     u32 portid, u32 report)
bd0779370   Pablo Neira Ayuso   netfilter: nfnetl...
2200
2201
2202
  {
  	struct nlattr *cda[CTA_EXPECT_MAX+1];
  	struct nf_conntrack_tuple tuple, mask;
b7e092c05   Florian Westphal   netfilter: ctnetl...
2203
  	struct nf_conntrack_helper *helper = NULL;
bd0779370   Pablo Neira Ayuso   netfilter: nfnetl...
2204
2205
2206
2207
2208
2209
  	struct nf_conntrack_expect *exp;
  	int err;
  
  	err = nla_parse_nested(cda, CTA_EXPECT_MAX, attr, exp_nla_policy);
  	if (err < 0)
  		return err;
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2210
2211
  	err = ctnetlink_glue_exp_parse((const struct nlattr * const *)cda,
  				       ct, &tuple, &mask);
bd0779370   Pablo Neira Ayuso   netfilter: nfnetl...
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
  	if (err < 0)
  		return err;
  
  	if (cda[CTA_EXPECT_HELP_NAME]) {
  		const char *helpname = nla_data(cda[CTA_EXPECT_HELP_NAME]);
  
  		helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct),
  						    nf_ct_protonum(ct));
  		if (helper == NULL)
  			return -EOPNOTSUPP;
  	}
  
  	exp = ctnetlink_alloc_expect((const struct nlattr * const *)cda, ct,
  				     helper, &tuple, &mask);
  	if (IS_ERR(exp))
  		return PTR_ERR(exp);
  
  	err = nf_ct_expect_related_report(exp, portid, report);
b18bcb001   Liping Zhang   netfilter: nfnetl...
2230
2231
  	nf_ct_expect_put(exp);
  	return err;
bd0779370   Pablo Neira Ayuso   netfilter: nfnetl...
2232
  }
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2233
2234
  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...
2235
2236
2237
2238
2239
2240
  {
  	if (!(ct->status & IPS_NAT_MASK))
  		return;
  
  	nf_ct_tcp_seqadj_set(skb, ct, ctinfo, diff);
  }
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
2241
2242
2243
2244
2245
2246
2247
  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...
2248
  };
83f3e94d3   Ken-ichirou MATSUZAWA   netfilter: Kconfi...
2249
  #endif /* CONFIG_NETFILTER_NETLINK_GLUE_CT */
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
2250

601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2251
2252
2253
  /***********************************************************************
   * EXPECT
   ***********************************************************************/
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2254

4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
2255
2256
2257
  static int ctnetlink_exp_dump_tuple(struct sk_buff *skb,
  				    const struct nf_conntrack_tuple *tuple,
  				    enum ctattr_expect type)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2258
  {
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2259
  	struct nlattr *nest_parms;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2260

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2261
2262
2263
  	nest_parms = nla_nest_start(skb, type | NLA_F_NESTED);
  	if (!nest_parms)
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2264
  	if (ctnetlink_dump_tuples(skb, tuple) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2265
2266
  		goto nla_put_failure;
  	nla_nest_end(skb, nest_parms);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2267
2268
  
  	return 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2269
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2270
  	return -1;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2271
  }
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2272

4054ff454   Pablo Neira Ayuso   netfilter: ctnetl...
2273
2274
2275
  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...
2276
2277
2278
  {
  	int ret;
  	struct nf_conntrack_l3proto *l3proto;
605dcad6c   Martin Josefsson   [NETFILTER]: nf_c...
2279
  	struct nf_conntrack_l4proto *l4proto;
d4156e8cd   Patrick McHardy   [NETFILTER]: nf_c...
2280
  	struct nf_conntrack_tuple m;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2281
  	struct nlattr *nest_parms;
d4156e8cd   Patrick McHardy   [NETFILTER]: nf_c...
2282
2283
  
  	memset(&m, 0xFF, sizeof(m));
d4156e8cd   Patrick McHardy   [NETFILTER]: nf_c...
2284
  	memcpy(&m.src.u3, &mask->src.u3, sizeof(m.src.u3));
e578756c3   Patrick McHardy   netfilter: ctnetl...
2285
2286
  	m.src.u.all = mask->src.u.all;
  	m.dst.protonum = tuple->dst.protonum;
d4156e8cd   Patrick McHardy   [NETFILTER]: nf_c...
2287

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2288
2289
2290
  	nest_parms = nla_nest_start(skb, CTA_EXPECT_MASK | NLA_F_NESTED);
  	if (!nest_parms)
  		goto nla_put_failure;
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
2291

3b988ece9   Hans Schillstrom   netfilter: ctnetl...
2292
  	rcu_read_lock();
528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
2293
  	l3proto = __nf_ct_l3proto_find(tuple->src.l3num);
d4156e8cd   Patrick McHardy   [NETFILTER]: nf_c...
2294
  	ret = ctnetlink_dump_tuples_ip(skb, &m, l3proto);
3b988ece9   Hans Schillstrom   netfilter: ctnetl...
2295
2296
2297
  	if (ret >= 0) {
  		l4proto = __nf_ct_l4proto_find(tuple->src.l3num,
  					       tuple->dst.protonum);
d4156e8cd   Patrick McHardy   [NETFILTER]: nf_c...
2298
  	ret = ctnetlink_dump_tuples_proto(skb, &m, l4proto);
3b988ece9   Hans Schillstrom   netfilter: ctnetl...
2299
2300
  	}
  	rcu_read_unlock();
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
2301
  	if (unlikely(ret < 0))
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2302
  		goto nla_put_failure;
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
2303

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2304
  	nla_nest_end(skb, nest_parms);
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
2305
2306
  
  	return 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2307
  nla_put_failure:
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
2308
2309
  	return -1;
  }
c7232c997   Patrick McHardy   netfilter: add pr...
2310
  static const union nf_inet_addr any_addr;
bb5cf80e9   Ilpo Järvinen   [NETFILTER]: Kill...
2311
  static int
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2312
  ctnetlink_exp_dump_expect(struct sk_buff *skb,
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2313
  			  const struct nf_conntrack_expect *exp)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2314
2315
  {
  	struct nf_conn *master = exp->master;
c12163827   Xi Wang   netfilter: ctnetl...
2316
  	long timeout = ((long)exp->timeout.expires - (long)jiffies) / HZ;
bc01befdc   Pablo Neira Ayuso   netfilter: ctnetl...
2317
  	struct nf_conn_help *help;
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2318
2319
2320
2321
  #ifdef CONFIG_NF_NAT_NEEDED
  	struct nlattr *nest_parms;
  	struct nf_conntrack_tuple nat_tuple = {};
  #endif
544d5c7d9   Pablo Neira Ayuso   netfilter: ctnetl...
2322
  	struct nf_ct_helper_expectfn *expfn;
d978e5dae   Patrick McHardy   [NETFILTER]: ctne...
2323
2324
  	if (timeout < 0)
  		timeout = 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2325
2326
  
  	if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2327
  		goto nla_put_failure;
1cde64365   Pablo Neira Ayuso   [NETFILTER]: ctne...
2328
  	if (ctnetlink_exp_dump_mask(skb, &exp->tuple, &exp->mask) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2329
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2330
2331
2332
  	if (ctnetlink_exp_dump_tuple(skb,
  				 &master->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
  				 CTA_EXPECT_MASTER) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2333
  		goto nla_put_failure;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2334

076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2335
  #ifdef CONFIG_NF_NAT_NEEDED
c7232c997   Patrick McHardy   netfilter: add pr...
2336
2337
  	if (!nf_inet_addr_cmp(&exp->saved_addr, &any_addr) ||
  	    exp->saved_proto.all) {
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2338
2339
2340
  		nest_parms = nla_nest_start(skb, CTA_EXPECT_NAT | NLA_F_NESTED);
  		if (!nest_parms)
  			goto nla_put_failure;
cc1eb4313   David S. Miller   nf_conntrack_netl...
2341
2342
  		if (nla_put_be32(skb, CTA_EXPECT_NAT_DIR, htonl(exp->dir)))
  			goto nla_put_failure;
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2343
2344
  
  		nat_tuple.src.l3num = nf_ct_l3num(master);
c7232c997   Patrick McHardy   netfilter: add pr...
2345
  		nat_tuple.src.u3 = exp->saved_addr;
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2346
2347
2348
2349
2350
2351
2352
2353
2354
  		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...
2355
2356
2357
2358
2359
  	if (nla_put_be32(skb, CTA_EXPECT_TIMEOUT, htonl(timeout)) ||
  	    nla_put_be32(skb, CTA_EXPECT_ID, htonl((unsigned long)exp)) ||
  	    nla_put_be32(skb, CTA_EXPECT_FLAGS, htonl(exp->flags)) ||
  	    nla_put_be32(skb, CTA_EXPECT_CLASS, htonl(exp->class)))
  		goto nla_put_failure;
bc01befdc   Pablo Neira Ayuso   netfilter: ctnetl...
2360
2361
2362
2363
2364
  	help = nfct_help(master);
  	if (help) {
  		struct nf_conntrack_helper *helper;
  
  		helper = rcu_dereference(help->helper);
cc1eb4313   David S. Miller   nf_conntrack_netl...
2365
2366
2367
  		if (helper &&
  		    nla_put_string(skb, CTA_EXPECT_HELP_NAME, helper->name))
  			goto nla_put_failure;
bc01befdc   Pablo Neira Ayuso   netfilter: ctnetl...
2368
  	}
544d5c7d9   Pablo Neira Ayuso   netfilter: ctnetl...
2369
  	expfn = nf_ct_helper_expectfn_find_by_symbol(exp->expectfn);
cc1eb4313   David S. Miller   nf_conntrack_netl...
2370
2371
2372
  	if (expfn != NULL &&
  	    nla_put_string(skb, CTA_EXPECT_FN, expfn->name))
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2373
2374
  
  	return 0;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2375

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2376
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2377
2378
2379
2380
  	return -1;
  }
  
  static int
15e473046   Eric W. Biederman   netlink: Rename p...
2381
  ctnetlink_exp_fill_info(struct sk_buff *skb, u32 portid, u32 seq,
8b0a231d4   Pablo Neira Ayuso   netfilter: ctnetl...
2382
  			int event, const struct nf_conntrack_expect *exp)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2383
2384
2385
  {
  	struct nlmsghdr *nlh;
  	struct nfgenmsg *nfmsg;
15e473046   Eric W. Biederman   netlink: Rename p...
2386
  	unsigned int flags = portid ? NLM_F_MULTI : 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2387
2388
  
  	event |= NFNL_SUBSYS_CTNETLINK_EXP << 8;
15e473046   Eric W. Biederman   netlink: Rename p...
2389
  	nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2390
2391
  	if (nlh == NULL)
  		goto nlmsg_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2392

96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2393
  	nfmsg = nlmsg_data(nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2394
2395
2396
2397
2398
  	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...
2399
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2400

96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2401
  	nlmsg_end(skb, nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2402
2403
2404
  	return skb->len;
  
  nlmsg_failure:
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2405
  nla_put_failure:
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2406
  	nlmsg_cancel(skb, nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2407
2408
2409
2410
  	return -1;
  }
  
  #ifdef CONFIG_NF_CONNTRACK_EVENTS
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
2411
2412
  static int
  ctnetlink_expect_event(unsigned int events, struct nf_exp_event *item)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2413
  {
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
2414
2415
  	struct nf_conntrack_expect *exp = item->exp;
  	struct net *net = nf_ct_exp_net(exp);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2416
2417
  	struct nlmsghdr *nlh;
  	struct nfgenmsg *nfmsg;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2418
  	struct sk_buff *skb;
ebbf41df4   Pablo Neira Ayuso   netfilter: ctnetl...
2419
  	unsigned int type, group;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2420
  	int flags = 0;
ebbf41df4   Pablo Neira Ayuso   netfilter: ctnetl...
2421
2422
2423
2424
  	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 ...
2425
2426
  		type = IPCTNL_MSG_EXP_NEW;
  		flags = NLM_F_CREATE|NLM_F_EXCL;
ebbf41df4   Pablo Neira Ayuso   netfilter: ctnetl...
2427
  		group = NFNLGRP_CONNTRACK_EXP_NEW;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2428
  	} else
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
2429
  		return 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2430

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

96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2434
2435
  	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
  	if (skb == NULL)
150ace0db   Pablo Neira Ayuso   netfilter: ctnetl...
2436
  		goto errout;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2437

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

96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2443
  	nfmsg = nlmsg_data(nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2444
2445
2446
  	nfmsg->nfgen_family = exp->tuple.src.l3num;
  	nfmsg->version	    = NFNETLINK_V0;
  	nfmsg->res_id	    = 0;
528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
2447
  	rcu_read_lock();
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2448
  	if (ctnetlink_exp_dump_expect(skb, exp) < 0)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2449
  		goto nla_put_failure;
528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
2450
  	rcu_read_unlock();
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2451

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

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2456
  nla_put_failure:
528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
2457
  	rcu_read_unlock();
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2458
  	nlmsg_cancel(skb, nlh);
528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
2459
  nlmsg_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2460
  	kfree_skb(skb);
150ace0db   Pablo Neira Ayuso   netfilter: ctnetl...
2461
  errout:
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
2462
  	nfnetlink_set_err(net, 0, 0, -ENOBUFS);
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
2463
  	return 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2464
2465
  }
  #endif
cf6994c2b   Patrick McHardy   [NETFILTER]: nf_c...
2466
2467
  static int ctnetlink_exp_done(struct netlink_callback *cb)
  {
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2468
2469
  	if (cb->args[1])
  		nf_ct_expect_put((struct nf_conntrack_expect *)cb->args[1]);
cf6994c2b   Patrick McHardy   [NETFILTER]: nf_c...
2470
2471
  	return 0;
  }
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2472
2473
2474
2475
  
  static int
  ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
  {
9592a5c01   Alexey Dobriyan   netfilter: ctnetl...
2476
  	struct net *net = sock_net(skb->sk);
cf6994c2b   Patrick McHardy   [NETFILTER]: nf_c...
2477
  	struct nf_conntrack_expect *exp, *last;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2478
  	struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
87711cb81   Pablo Neira Ayuso   [NETFILTER]: Filt...
2479
  	u_int8_t l3proto = nfmsg->nfgen_family;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2480

7d0742da1   Patrick McHardy   [NETFILTER]: nf_c...
2481
  	rcu_read_lock();
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2482
2483
  	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...
2484
  restart:
0a93aaedc   Florian Westphal   netfilter: conntr...
2485
  		hlist_for_each_entry(exp, &nf_ct_expect_hash[cb->args[0]],
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2486
2487
  				     hnode) {
  			if (l3proto && exp->tuple.src.l3num != l3proto)
cf6994c2b   Patrick McHardy   [NETFILTER]: nf_c...
2488
  				continue;
03d7dc5cd   Florian Westphal   netfilter: conntr...
2489
2490
2491
  
  			if (!net_eq(nf_ct_net(exp->master), net))
  				continue;
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2492
2493
2494
2495
2496
  			if (cb->args[1]) {
  				if (exp != last)
  					continue;
  				cb->args[1] = 0;
  			}
8b0a231d4   Pablo Neira Ayuso   netfilter: ctnetl...
2497
  			if (ctnetlink_exp_fill_info(skb,
15e473046   Eric W. Biederman   netlink: Rename p...
2498
  						    NETLINK_CB(cb->skb).portid,
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2499
2500
  						    cb->nlh->nlmsg_seq,
  						    IPCTNL_MSG_EXP_NEW,
8b0a231d4   Pablo Neira Ayuso   netfilter: ctnetl...
2501
  						    exp) < 0) {
7d0742da1   Patrick McHardy   [NETFILTER]: nf_c...
2502
2503
  				if (!atomic_inc_not_zero(&exp->use))
  					continue;
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2504
2505
2506
  				cb->args[1] = (unsigned long)exp;
  				goto out;
  			}
cf6994c2b   Patrick McHardy   [NETFILTER]: nf_c...
2507
  		}
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2508
2509
2510
  		if (cb->args[1]) {
  			cb->args[1] = 0;
  			goto restart;
cf6994c2b   Patrick McHardy   [NETFILTER]: nf_c...
2511
2512
  		}
  	}
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2513
  out:
7d0742da1   Patrick McHardy   [NETFILTER]: nf_c...
2514
  	rcu_read_unlock();
cf6994c2b   Patrick McHardy   [NETFILTER]: nf_c...
2515
2516
  	if (last)
  		nf_ct_expect_put(last);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2517

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2518
2519
  	return skb->len;
  }
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
  static int
  ctnetlink_exp_ct_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
  {
  	struct nf_conntrack_expect *exp, *last;
  	struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
  	struct nf_conn *ct = cb->data;
  	struct nf_conn_help *help = nfct_help(ct);
  	u_int8_t l3proto = nfmsg->nfgen_family;
  
  	if (cb->args[0])
  		return 0;
  
  	rcu_read_lock();
  	last = (struct nf_conntrack_expect *)cb->args[1];
  restart:
  	hlist_for_each_entry(exp, &help->expectations, lnode) {
  		if (l3proto && exp->tuple.src.l3num != l3proto)
  			continue;
  		if (cb->args[1]) {
  			if (exp != last)
  				continue;
  			cb->args[1] = 0;
  		}
  		if (ctnetlink_exp_fill_info(skb, NETLINK_CB(cb->skb).portid,
  					    cb->nlh->nlmsg_seq,
  					    IPCTNL_MSG_EXP_NEW,
  					    exp) < 0) {
  			if (!atomic_inc_not_zero(&exp->use))
  				continue;
  			cb->args[1] = (unsigned long)exp;
  			goto out;
  		}
  	}
  	if (cb->args[1]) {
  		cb->args[1] = 0;
  		goto restart;
  	}
  	cb->args[0] = 1;
  out:
  	rcu_read_unlock();
  	if (last)
  		nf_ct_expect_put(last);
  
  	return skb->len;
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
2565
2566
  static int ctnetlink_dump_exp_ct(struct net *net, struct sock *ctnl,
  				 struct sk_buff *skb,
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
2567
2568
2569
2570
  				 const struct nlmsghdr *nlh,
  				 const struct nlattr * const cda[])
  {
  	int err;
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
2571
2572
2573
2574
2575
  	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...
2576
  	struct nf_conntrack_zone zone;
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
2577
2578
2579
2580
  	struct netlink_dump_control c = {
  		.dump = ctnetlink_exp_ct_dump_table,
  		.done = ctnetlink_exp_done,
  	};
deedb5903   Daniel Borkmann   netfilter: nf_con...
2581
2582
  	err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER,
  				    u3, NULL);
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
2583
2584
  	if (err < 0)
  		return err;
308ac9143   Daniel Borkmann   netfilter: nf_con...
2585
2586
2587
  	err = ctnetlink_parse_zone(cda[CTA_EXPECT_ZONE], &zone);
  	if (err < 0)
  		return err;
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
2588

308ac9143   Daniel Borkmann   netfilter: nf_con...
2589
  	h = nf_conntrack_find_get(net, &zone, &tuple);
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
  	if (!h)
  		return -ENOENT;
  
  	ct = nf_ct_tuplehash_to_ctrack(h);
  	c.data = ct;
  
  	err = netlink_dump_start(ctnl, skb, nlh, &c);
  	nf_ct_put(ct);
  
  	return err;
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
2601
2602
2603
  static int ctnetlink_get_expect(struct net *net, struct sock *ctnl,
  				struct sk_buff *skb, const struct nlmsghdr *nlh,
  				const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2604
2605
2606
2607
  {
  	struct nf_conntrack_tuple tuple;
  	struct nf_conntrack_expect *exp;
  	struct sk_buff *skb2;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2608
  	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2609
  	u_int8_t u3 = nfmsg->nfgen_family;
308ac9143   Daniel Borkmann   netfilter: nf_con...
2610
  	struct nf_conntrack_zone zone;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
2611
  	int err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2612

b8f3ab429   David S. Miller   Revert "netlink: ...
2613
  	if (nlh->nlmsg_flags & NLM_F_DUMP) {
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
2614
  		if (cda[CTA_EXPECT_MASTER])
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
2615
  			return ctnetlink_dump_exp_ct(net, ctnl, skb, nlh, cda);
e844a9284   Pablo Neira Ayuso   netfilter: ctnetl...
2616
2617
2618
2619
2620
2621
2622
  		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 ...
2623
  	}
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
2624
2625
2626
  	err = ctnetlink_parse_zone(cda[CTA_EXPECT_ZONE], &zone);
  	if (err < 0)
  		return err;
35dba1d7f   Pablo Neira Ayuso   netfilter: ctnetl...
2627
  	if (cda[CTA_EXPECT_TUPLE])
deedb5903   Daniel Borkmann   netfilter: nf_con...
2628
2629
  		err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE,
  					    u3, NULL);
35dba1d7f   Pablo Neira Ayuso   netfilter: ctnetl...
2630
  	else if (cda[CTA_EXPECT_MASTER])
deedb5903   Daniel Borkmann   netfilter: nf_con...
2631
2632
  		err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER,
  					    u3, NULL);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2633
2634
2635
2636
2637
  	else
  		return -EINVAL;
  
  	if (err < 0)
  		return err;
308ac9143   Daniel Borkmann   netfilter: nf_con...
2638
  	exp = nf_ct_expect_find_get(net, &zone, &tuple);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2639
2640
  	if (!exp)
  		return -ENOENT;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2641
  	if (cda[CTA_EXPECT_ID]) {
77236b6e3   Patrick McHardy   [NETFILTER]: ctne...
2642
  		__be32 id = nla_get_be32(cda[CTA_EXPECT_ID]);
358324024   Patrick McHardy   [NETFILTER]: nf_c...
2643
  		if (ntohl(id) != (u32)(unsigned long)exp) {
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
2644
  			nf_ct_expect_put(exp);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2645
2646
  			return -ENOENT;
  		}
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2647
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2648
2649
  
  	err = -ENOMEM;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2650
  	skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
81378f728   Pablo Neira Ayuso   netfilter: ctnetl...
2651
2652
  	if (skb2 == NULL) {
  		nf_ct_expect_put(exp);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2653
  		goto out;
81378f728   Pablo Neira Ayuso   netfilter: ctnetl...
2654
  	}
4e9b82693   Thomas Graf   [NETLINK]: Remove...
2655

528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
2656
  	rcu_read_lock();
15e473046   Eric W. Biederman   netlink: Rename p...
2657
  	err = ctnetlink_exp_fill_info(skb2, NETLINK_CB(skb).portid,
8b0a231d4   Pablo Neira Ayuso   netfilter: ctnetl...
2658
  				      nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW, exp);
528a3a6f6   Pablo Neira Ayuso   netfilter: ctnetl...
2659
  	rcu_read_unlock();
81378f728   Pablo Neira Ayuso   netfilter: ctnetl...
2660
  	nf_ct_expect_put(exp);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2661
2662
  	if (err <= 0)
  		goto free;
15e473046   Eric W. Biederman   netlink: Rename p...
2663
  	err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT);
81378f728   Pablo Neira Ayuso   netfilter: ctnetl...
2664
2665
  	if (err < 0)
  		goto out;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2666

81378f728   Pablo Neira Ayuso   netfilter: ctnetl...
2667
  	return 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2668
2669
2670
2671
  
  free:
  	kfree_skb(skb2);
  out:
81378f728   Pablo Neira Ayuso   netfilter: ctnetl...
2672
2673
  	/* this avoids a loop in nfnetlink. */
  	return err == -EAGAIN ? -ENOBUFS : err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2674
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
2675
2676
2677
  static int ctnetlink_del_expect(struct net *net, struct sock *ctnl,
  				struct sk_buff *skb, const struct nlmsghdr *nlh,
  				const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2678
  {
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2679
  	struct nf_conntrack_expect *exp;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2680
  	struct nf_conntrack_tuple tuple;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2681
  	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
b67bfe0d4   Sasha Levin   hlist: drop the n...
2682
  	struct hlist_node *next;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2683
  	u_int8_t u3 = nfmsg->nfgen_family;
308ac9143   Daniel Borkmann   netfilter: nf_con...
2684
  	struct nf_conntrack_zone zone;
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2685
  	unsigned int i;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2686
  	int err;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2687
  	if (cda[CTA_EXPECT_TUPLE]) {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2688
  		/* delete a single expect by tuple */
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
2689
2690
2691
  		err = ctnetlink_parse_zone(cda[CTA_EXPECT_ZONE], &zone);
  		if (err < 0)
  			return err;
deedb5903   Daniel Borkmann   netfilter: nf_con...
2692
2693
  		err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE,
  					    u3, NULL);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2694
2695
2696
2697
  		if (err < 0)
  			return err;
  
  		/* bump usage count to 2 */
308ac9143   Daniel Borkmann   netfilter: nf_con...
2698
  		exp = nf_ct_expect_find_get(net, &zone, &tuple);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2699
2700
  		if (!exp)
  			return -ENOENT;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2701
  		if (cda[CTA_EXPECT_ID]) {
77236b6e3   Patrick McHardy   [NETFILTER]: ctne...
2702
  			__be32 id = nla_get_be32(cda[CTA_EXPECT_ID]);
358324024   Patrick McHardy   [NETFILTER]: nf_c...
2703
  			if (ntohl(id) != (u32)(unsigned long)exp) {
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
2704
  				nf_ct_expect_put(exp);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2705
2706
2707
2708
2709
  				return -ENOENT;
  			}
  		}
  
  		/* after list removal, usage count == 1 */
ca7433df3   Jesper Dangaard Brouer   netfilter: conntr...
2710
  		spin_lock_bh(&nf_conntrack_expect_lock);
ebbf41df4   Pablo Neira Ayuso   netfilter: ctnetl...
2711
  		if (del_timer(&exp->timeout)) {
15e473046   Eric W. Biederman   netlink: Rename p...
2712
  			nf_ct_unlink_expect_report(exp, NETLINK_CB(skb).portid,
ebbf41df4   Pablo Neira Ayuso   netfilter: ctnetl...
2713
2714
2715
  						   nlmsg_report(nlh));
  			nf_ct_expect_put(exp);
  		}
ca7433df3   Jesper Dangaard Brouer   netfilter: conntr...
2716
  		spin_unlock_bh(&nf_conntrack_expect_lock);
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2717
  		/* have to put what we 'get' above.
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2718
  		 * after this line usage count == 0 */
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
2719
  		nf_ct_expect_put(exp);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2720
2721
  	} else if (cda[CTA_EXPECT_HELP_NAME]) {
  		char *name = nla_data(cda[CTA_EXPECT_HELP_NAME]);
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2722
  		struct nf_conn_help *m_help;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2723
2724
  
  		/* delete all expectations for this helper */
ca7433df3   Jesper Dangaard Brouer   netfilter: conntr...
2725
  		spin_lock_bh(&nf_conntrack_expect_lock);
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2726
  		for (i = 0; i < nf_ct_expect_hsize; i++) {
b67bfe0d4   Sasha Levin   hlist: drop the n...
2727
  			hlist_for_each_entry_safe(exp, next,
0a93aaedc   Florian Westphal   netfilter: conntr...
2728
  						  &nf_ct_expect_hash[i],
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2729
  						  hnode) {
03d7dc5cd   Florian Westphal   netfilter: conntr...
2730
2731
2732
  
  				if (!net_eq(nf_ct_exp_net(exp), net))
  					continue;
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2733
  				m_help = nfct_help(exp->master);
794e68716   Patrick McHardy   netfilter: ctnetl...
2734
2735
  				if (!strcmp(m_help->helper->name, name) &&
  				    del_timer(&exp->timeout)) {
ebbf41df4   Pablo Neira Ayuso   netfilter: ctnetl...
2736
  					nf_ct_unlink_expect_report(exp,
15e473046   Eric W. Biederman   netlink: Rename p...
2737
  							NETLINK_CB(skb).portid,
ebbf41df4   Pablo Neira Ayuso   netfilter: ctnetl...
2738
  							nlmsg_report(nlh));
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2739
2740
  					nf_ct_expect_put(exp);
  				}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2741
2742
  			}
  		}
ca7433df3   Jesper Dangaard Brouer   netfilter: conntr...
2743
  		spin_unlock_bh(&nf_conntrack_expect_lock);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2744
2745
  	} else {
  		/* This basically means we have to flush everything*/
ca7433df3   Jesper Dangaard Brouer   netfilter: conntr...
2746
  		spin_lock_bh(&nf_conntrack_expect_lock);
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2747
  		for (i = 0; i < nf_ct_expect_hsize; i++) {
b67bfe0d4   Sasha Levin   hlist: drop the n...
2748
  			hlist_for_each_entry_safe(exp, next,
0a93aaedc   Florian Westphal   netfilter: conntr...
2749
  						  &nf_ct_expect_hash[i],
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2750
  						  hnode) {
03d7dc5cd   Florian Westphal   netfilter: conntr...
2751
2752
2753
  
  				if (!net_eq(nf_ct_exp_net(exp), net))
  					continue;
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2754
  				if (del_timer(&exp->timeout)) {
ebbf41df4   Pablo Neira Ayuso   netfilter: ctnetl...
2755
  					nf_ct_unlink_expect_report(exp,
15e473046   Eric W. Biederman   netlink: Rename p...
2756
  							NETLINK_CB(skb).portid,
ebbf41df4   Pablo Neira Ayuso   netfilter: ctnetl...
2757
  							nlmsg_report(nlh));
31f15875c   Patrick McHardy   [NETFILTER]: nf_c...
2758
2759
  					nf_ct_expect_put(exp);
  				}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2760
2761
  			}
  		}
ca7433df3   Jesper Dangaard Brouer   netfilter: conntr...
2762
  		spin_unlock_bh(&nf_conntrack_expect_lock);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2763
2764
2765
2766
2767
  	}
  
  	return 0;
  }
  static int
399383246   Patrick McHardy   netfilter: nfnetl...
2768
2769
  ctnetlink_change_expect(struct nf_conntrack_expect *x,
  			const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2770
  {
9768e1ace   Kelvie Wong   netfilter: nf_ct_...
2771
2772
2773
2774
2775
2776
2777
2778
2779
  	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 ...
2780
  }
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
  static const struct nla_policy exp_nat_nla_policy[CTA_EXPECT_NAT_MAX+1] = {
  	[CTA_EXPECT_NAT_DIR]	= { .type = NLA_U32 },
  	[CTA_EXPECT_NAT_TUPLE]	= { .type = NLA_NESTED },
  };
  
  static int
  ctnetlink_parse_expect_nat(const struct nlattr *attr,
  			   struct nf_conntrack_expect *exp,
  			   u_int8_t u3)
  {
  #ifdef CONFIG_NF_NAT_NEEDED
  	struct nlattr *tb[CTA_EXPECT_NAT_MAX+1];
  	struct nf_conntrack_tuple nat_tuple = {};
  	int err;
130ffbc26   Daniel Borkmann   netfilter: check ...
2795
2796
2797
  	err = nla_parse_nested(tb, CTA_EXPECT_NAT_MAX, attr, exp_nat_nla_policy);
  	if (err < 0)
  		return err;
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2798
2799
2800
2801
2802
  
  	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...
2803
2804
  				    &nat_tuple, CTA_EXPECT_NAT_TUPLE,
  				    u3, NULL);
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2805
2806
  	if (err < 0)
  		return err;
c7232c997   Patrick McHardy   netfilter: add pr...
2807
  	exp->saved_addr = nat_tuple.src.u3;
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2808
2809
2810
2811
2812
2813
2814
2815
  	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...
2816
2817
2818
2819
2820
  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 ...
2821
  {
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2822
  	u_int32_t class = 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2823
  	struct nf_conntrack_expect *exp;
dc808fe28   Harald Welte   [NETFILTER] nf_co...
2824
  	struct nf_conn_help *help;
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2825
  	int err;
660fdb2a0   Pablo Neira Ayuso   netfilter: ctnetl...
2826

b8c5e52c1   Pablo Neira Ayuso   netfilter: ctnetl...
2827
2828
  	if (cda[CTA_EXPECT_CLASS] && helper) {
  		class = ntohl(nla_get_be32(cda[CTA_EXPECT_CLASS]));
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2829
2830
  		if (class > helper->expect_class_max)
  			return ERR_PTR(-EINVAL);
b8c5e52c1   Pablo Neira Ayuso   netfilter: ctnetl...
2831
  	}
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
2832
  	exp = nf_ct_expect_alloc(ct);
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2833
2834
  	if (!exp)
  		return ERR_PTR(-ENOMEM);
bc01befdc   Pablo Neira Ayuso   netfilter: ctnetl...
2835
2836
2837
2838
  	help = nfct_help(ct);
  	if (!help) {
  		if (!cda[CTA_EXPECT_TIMEOUT]) {
  			err = -EINVAL;
1310b955c   Jesper Juhl   netfilter: ctnetl...
2839
  			goto err_out;
bc01befdc   Pablo Neira Ayuso   netfilter: ctnetl...
2840
2841
2842
  		}
  		exp->timeout.expires =
  		  jiffies + ntohl(nla_get_be32(cda[CTA_EXPECT_TIMEOUT])) * HZ;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
2843

bc01befdc   Pablo Neira Ayuso   netfilter: ctnetl...
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
  		exp->flags = NF_CT_EXPECT_USERSPACE;
  		if (cda[CTA_EXPECT_FLAGS]) {
  			exp->flags |=
  				ntohl(nla_get_be32(cda[CTA_EXPECT_FLAGS]));
  		}
  	} else {
  		if (cda[CTA_EXPECT_FLAGS]) {
  			exp->flags = ntohl(nla_get_be32(cda[CTA_EXPECT_FLAGS]));
  			exp->flags &= ~NF_CT_EXPECT_USERSPACE;
  		} else
  			exp->flags = 0;
  	}
544d5c7d9   Pablo Neira Ayuso   netfilter: ctnetl...
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
  	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 ...
2868

b8c5e52c1   Pablo Neira Ayuso   netfilter: ctnetl...
2869
  	exp->class = class;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2870
  	exp->master = ct;
660fdb2a0   Pablo Neira Ayuso   netfilter: ctnetl...
2871
  	exp->helper = helper;
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2872
2873
2874
  	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 ...
2875

076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2876
2877
  	if (cda[CTA_EXPECT_NAT]) {
  		err = ctnetlink_parse_expect_nat(cda[CTA_EXPECT_NAT],
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2878
  						 exp, nf_ct_l3num(ct));
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2879
2880
2881
  		if (err < 0)
  			goto err_out;
  	}
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2882
  	return exp;
076a0ca02   Pablo Neira Ayuso   netfilter: ctnetl...
2883
  err_out:
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
2884
  	nf_ct_expect_put(exp);
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2885
2886
2887
2888
  	return ERR_PTR(err);
  }
  
  static int
308ac9143   Daniel Borkmann   netfilter: nf_con...
2889
2890
  ctnetlink_create_expect(struct net *net,
  			const struct nf_conntrack_zone *zone,
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
  			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...
2902
2903
  	err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE,
  				    u3, NULL);
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2904
2905
  	if (err < 0)
  		return err;
deedb5903   Daniel Borkmann   netfilter: nf_con...
2906
2907
  	err = ctnetlink_parse_tuple(cda, &mask, CTA_EXPECT_MASK,
  				    u3, NULL);
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2908
2909
  	if (err < 0)
  		return err;
deedb5903   Daniel Borkmann   netfilter: nf_con...
2910
2911
  	err = ctnetlink_parse_tuple(cda, &master_tuple, CTA_EXPECT_MASTER,
  				    u3, NULL);
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
  	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);
  
  	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) {
  #ifdef CONFIG_MODULES
  			if (request_module("nfct-helper-%s", helpname) < 0) {
  				err = -EOPNOTSUPP;
  				goto err_ct;
  			}
  			helper = __nf_conntrack_helper_find(helpname, u3,
  							    nf_ct_protonum(ct));
  			if (helper) {
  				err = -EAGAIN;
  				goto err_ct;
  			}
  #endif
  			err = -EOPNOTSUPP;
  			goto err_ct;
  		}
  	}
  
  	exp = ctnetlink_alloc_expect(cda, ct, helper, &tuple, &mask);
  	if (IS_ERR(exp)) {
  		err = PTR_ERR(exp);
  		goto err_ct;
  	}
  
  	err = nf_ct_expect_related_report(exp, portid, report);
0ef71ee1a   Pablo Neira Ayuso   netfilter: ctnetl...
2951
2952
2953
  	nf_ct_expect_put(exp);
  err_ct:
  	nf_ct_put(ct);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2954
2955
  	return err;
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
2956
2957
2958
  static int ctnetlink_new_expect(struct net *net, struct sock *ctnl,
  				struct sk_buff *skb, const struct nlmsghdr *nlh,
  				const struct nlattr * const cda[])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2959
2960
2961
  {
  	struct nf_conntrack_tuple tuple;
  	struct nf_conntrack_expect *exp;
96bcf938d   Pablo Neira Ayuso   netfilter: ctnetl...
2962
  	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2963
  	u_int8_t u3 = nfmsg->nfgen_family;
308ac9143   Daniel Borkmann   netfilter: nf_con...
2964
  	struct nf_conntrack_zone zone;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
2965
  	int err;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2966

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
2967
2968
2969
  	if (!cda[CTA_EXPECT_TUPLE]
  	    || !cda[CTA_EXPECT_MASK]
  	    || !cda[CTA_EXPECT_MASTER])
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2970
  		return -EINVAL;
ef00f89f1   Patrick McHardy   netfilter: ctnetl...
2971
2972
2973
  	err = ctnetlink_parse_zone(cda[CTA_EXPECT_ZONE], &zone);
  	if (err < 0)
  		return err;
deedb5903   Daniel Borkmann   netfilter: nf_con...
2974
2975
  	err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE,
  				    u3, NULL);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2976
2977
  	if (err < 0)
  		return err;
ca7433df3   Jesper Dangaard Brouer   netfilter: conntr...
2978
  	spin_lock_bh(&nf_conntrack_expect_lock);
308ac9143   Daniel Borkmann   netfilter: nf_con...
2979
  	exp = __nf_ct_expect_find(net, &zone, &tuple);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2980
  	if (!exp) {
ca7433df3   Jesper Dangaard Brouer   netfilter: conntr...
2981
  		spin_unlock_bh(&nf_conntrack_expect_lock);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2982
  		err = -ENOENT;
19abb7b09   Pablo Neira Ayuso   netfilter: ctnetl...
2983
  		if (nlh->nlmsg_flags & NLM_F_CREATE) {
308ac9143   Daniel Borkmann   netfilter: nf_con...
2984
  			err = ctnetlink_create_expect(net, &zone, cda, u3,
15e473046   Eric W. Biederman   netlink: Rename p...
2985
  						      NETLINK_CB(skb).portid,
19abb7b09   Pablo Neira Ayuso   netfilter: ctnetl...
2986
2987
  						      nlmsg_report(nlh));
  		}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2988
2989
2990
2991
2992
2993
  		return err;
  	}
  
  	err = -EEXIST;
  	if (!(nlh->nlmsg_flags & NLM_F_EXCL))
  		err = ctnetlink_change_expect(exp, cda);
ca7433df3   Jesper Dangaard Brouer   netfilter: conntr...
2994
  	spin_unlock_bh(&nf_conntrack_expect_lock);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2995

c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
2996
2997
  	return err;
  }
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
2998
  static int
15e473046   Eric W. Biederman   netlink: Rename p...
2999
  ctnetlink_exp_stat_fill_info(struct sk_buff *skb, u32 portid, u32 seq, int cpu,
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
3000
3001
3002
3003
  			     const struct ip_conntrack_stat *st)
  {
  	struct nlmsghdr *nlh;
  	struct nfgenmsg *nfmsg;
15e473046   Eric W. Biederman   netlink: Rename p...
3004
  	unsigned int flags = portid ? NLM_F_MULTI : 0, event;
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
3005
3006
  
  	event = (NFNL_SUBSYS_CTNETLINK << 8 | IPCTNL_MSG_EXP_GET_STATS_CPU);
15e473046   Eric W. Biederman   netlink: Rename p...
3007
  	nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
  	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...
3046
  		if (ctnetlink_exp_stat_fill_info(skb, NETLINK_CB(cb->skb).portid,
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
3047
3048
3049
3050
3051
3052
3053
3054
  						 cb->nlh->nlmsg_seq,
  						 cpu, st) < 0)
  			break;
  	}
  	cb->args[0] = cpu;
  
  	return skb->len;
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
3055
3056
3057
3058
  static int ctnetlink_stat_exp_cpu(struct net *net, struct sock *ctnl,
  				  struct sk_buff *skb,
  				  const struct nlmsghdr *nlh,
  				  const struct nlattr * const cda[])
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
  {
  	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 ...
3069
  #ifdef CONFIG_NF_CONNTRACK_EVENTS
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
3070
3071
  static struct nf_ct_event_notifier ctnl_notifier = {
  	.fcn = ctnetlink_conntrack_event,
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3072
  };
e34d5c1a4   Pablo Neira Ayuso   netfilter: conntr...
3073
3074
  static struct nf_exp_event_notifier ctnl_notifier_exp = {
  	.fcn = ctnetlink_expect_event,
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3075
3076
  };
  #endif
7c8d4cb41   Patrick McHardy   [NETFILTER]: nfne...
3077
  static const struct nfnl_callback ctnl_cb[IPCTNL_MSG_MAX] = {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3078
  	[IPCTNL_MSG_CT_NEW]		= { .call = ctnetlink_new_conntrack,
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
3079
3080
  					    .attr_count = CTA_MAX,
  					    .policy = ct_nla_policy },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3081
  	[IPCTNL_MSG_CT_GET] 		= { .call = ctnetlink_get_conntrack,
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
3082
3083
  					    .attr_count = CTA_MAX,
  					    .policy = ct_nla_policy },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3084
  	[IPCTNL_MSG_CT_DELETE]  	= { .call = ctnetlink_del_conntrack,
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
3085
3086
  					    .attr_count = CTA_MAX,
  					    .policy = ct_nla_policy },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3087
  	[IPCTNL_MSG_CT_GET_CTRZERO] 	= { .call = ctnetlink_get_conntrack,
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
3088
3089
  					    .attr_count = CTA_MAX,
  					    .policy = ct_nla_policy },
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
3090
3091
  	[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...
3092
3093
  	[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 ...
3094
  };
7c8d4cb41   Patrick McHardy   [NETFILTER]: nfne...
3095
  static const struct nfnl_callback ctnl_exp_cb[IPCTNL_MSG_EXP_MAX] = {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3096
  	[IPCTNL_MSG_EXP_GET]		= { .call = ctnetlink_get_expect,
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
3097
3098
  					    .attr_count = CTA_EXPECT_MAX,
  					    .policy = exp_nla_policy },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3099
  	[IPCTNL_MSG_EXP_NEW]		= { .call = ctnetlink_new_expect,
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
3100
3101
  					    .attr_count = CTA_EXPECT_MAX,
  					    .policy = exp_nla_policy },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3102
  	[IPCTNL_MSG_EXP_DELETE]		= { .call = ctnetlink_del_expect,
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
3103
3104
  					    .attr_count = CTA_EXPECT_MAX,
  					    .policy = exp_nla_policy },
392025f87   Pablo Neira Ayuso   netfilter: ctnetl...
3105
  	[IPCTNL_MSG_EXP_GET_STATS_CPU]	= { .call = ctnetlink_stat_exp_cpu },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3106
  };
7c8d4cb41   Patrick McHardy   [NETFILTER]: nfne...
3107
  static const struct nfnetlink_subsystem ctnl_subsys = {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3108
3109
3110
3111
3112
  	.name				= "conntrack",
  	.subsys_id			= NFNL_SUBSYS_CTNETLINK,
  	.cb_count			= IPCTNL_MSG_MAX,
  	.cb				= ctnl_cb,
  };
7c8d4cb41   Patrick McHardy   [NETFILTER]: nfne...
3113
  static const struct nfnetlink_subsystem ctnl_exp_subsys = {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3114
3115
3116
3117
3118
  	.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...
3119
  MODULE_ALIAS("ip_conntrack_netlink");
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3120
  MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK);
34f9a2e4d   Pablo Neira Ayuso   [NETFILTER]: ctne...
3121
  MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_EXP);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3122

70e9942f1   Pablo Neira Ayuso   netfilter: nf_con...
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
  static int __net_init ctnetlink_net_init(struct net *net)
  {
  #ifdef CONFIG_NF_CONNTRACK_EVENTS
  	int ret;
  
  	ret = nf_conntrack_register_notifier(net, &ctnl_notifier);
  	if (ret < 0) {
  		pr_err("ctnetlink_init: cannot register notifier.
  ");
  		goto err_out;
  	}
  
  	ret = nf_ct_expect_register_notifier(net, &ctnl_notifier_exp);
  	if (ret < 0) {
  		pr_err("ctnetlink_init: cannot expect register notifier.
  ");
  		goto err_unreg_notifier;
  	}
  #endif
  	return 0;
  
  #ifdef CONFIG_NF_CONNTRACK_EVENTS
  err_unreg_notifier:
  	nf_conntrack_unregister_notifier(net, &ctnl_notifier);
  err_out:
  	return ret;
  #endif
  }
  
  static void ctnetlink_net_exit(struct net *net)
  {
  #ifdef CONFIG_NF_CONNTRACK_EVENTS
  	nf_ct_expect_unregister_notifier(net, &ctnl_notifier_exp);
  	nf_conntrack_unregister_notifier(net, &ctnl_notifier);
  #endif
  }
  
  static void __net_exit ctnetlink_net_exit_batch(struct list_head *net_exit_list)
  {
  	struct net *net;
  
  	list_for_each_entry(net, net_exit_list, exit_list)
  		ctnetlink_net_exit(net);
  }
  
  static struct pernet_operations ctnetlink_net_ops = {
  	.init		= ctnetlink_net_init,
  	.exit_batch	= ctnetlink_net_exit_batch,
  };
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3172
3173
3174
  static int __init ctnetlink_init(void)
  {
  	int ret;
654d0fbdc   Stephen Hemminger   netfilter: cleanu...
3175
3176
  	pr_info("ctnetlink v%s: registering with nfnetlink.
  ", version);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3177
3178
  	ret = nfnetlink_subsys_register(&ctnl_subsys);
  	if (ret < 0) {
654d0fbdc   Stephen Hemminger   netfilter: cleanu...
3179
3180
  		pr_err("ctnetlink_init: cannot register with nfnetlink.
  ");
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3181
3182
3183
3184
3185
  		goto err_out;
  	}
  
  	ret = nfnetlink_subsys_register(&ctnl_exp_subsys);
  	if (ret < 0) {
654d0fbdc   Stephen Hemminger   netfilter: cleanu...
3186
3187
  		pr_err("ctnetlink_init: cannot register exp with nfnetlink.
  ");
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3188
3189
  		goto err_unreg_subsys;
  	}
ef6acf68c   Julia Lawall   netfilter: ctnetl...
3190
3191
  	ret = register_pernet_subsys(&ctnetlink_net_ops);
  	if (ret < 0) {
70e9942f1   Pablo Neira Ayuso   netfilter: nf_con...
3192
3193
  		pr_err("ctnetlink_init: cannot register pernet operations
  ");
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3194
3195
  		goto err_unreg_exp_subsys;
  	}
83f3e94d3   Ken-ichirou MATSUZAWA   netfilter: Kconfi...
3196
  #ifdef CONFIG_NETFILTER_NETLINK_GLUE_CT
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
3197
  	/* setup interaction between nf_queue and nf_conntrack_netlink. */
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
3198
  	RCU_INIT_POINTER(nfnl_ct_hook, &ctnetlink_glue_hook);
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
3199
  #endif
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3200
  	return 0;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3201
3202
  err_unreg_exp_subsys:
  	nfnetlink_subsys_unregister(&ctnl_exp_subsys);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3203
3204
3205
3206
3207
3208
3209
3210
  err_unreg_subsys:
  	nfnetlink_subsys_unregister(&ctnl_subsys);
  err_out:
  	return ret;
  }
  
  static void __exit ctnetlink_exit(void)
  {
654d0fbdc   Stephen Hemminger   netfilter: cleanu...
3211
3212
  	pr_info("ctnetlink: unregistering from nfnetlink.
  ");
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3213

70e9942f1   Pablo Neira Ayuso   netfilter: nf_con...
3214
  	unregister_pernet_subsys(&ctnetlink_net_ops);
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3215
3216
  	nfnetlink_subsys_unregister(&ctnl_exp_subsys);
  	nfnetlink_subsys_unregister(&ctnl_subsys);
83f3e94d3   Ken-ichirou MATSUZAWA   netfilter: Kconfi...
3217
  #ifdef CONFIG_NETFILTER_NETLINK_GLUE_CT
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
3218
  	RCU_INIT_POINTER(nfnl_ct_hook, NULL);
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
3219
  #endif
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
3220
3221
3222
3223
  }
  
  module_init(ctnetlink_init);
  module_exit(ctnetlink_exit);