Blame view
net/netfilter/nf_conntrack_netlink.c
95.2 KB
c1d10adb4 [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 [NETFILTER] nf_co... |
5 |
* (C) 2002-2006 by Harald Welte <laforge@gnumonks.org> |
c1d10adb4 [NETFILTER]: Add ... |
6 |
* (C) 2003 by Patrick Mchardy <kaber@trash.net> |
392025f87 netfilter: ctnetl... |
7 |
* (C) 2005-2012 by Pablo Neira Ayuso <pablo@netfilter.org> |
c1d10adb4 [NETFILTER]: Add ... |
8 |
* |
601e68e10 [NETFILTER]: Fix ... |
9 |
* Initial connection tracking via netlink development funded and |
c1d10adb4 [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 [NETFILTER]: Add ... |
16 17 18 19 20 |
*/ #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> |
711bbdd65 rculist.h: fix in... |
21 |
#include <linux/rculist.h> |
ea781f197 netfilter: nf_con... |
22 |
#include <linux/rculist_nulls.h> |
c1d10adb4 [NETFILTER]: Add ... |
23 24 |
#include <linux/types.h> #include <linux/timer.h> |
1cc63249a conntrack: export... |
25 |
#include <linux/security.h> |
c1d10adb4 [NETFILTER]: Add ... |
26 27 28 29 |
#include <linux/skbuff.h> #include <linux/errno.h> #include <linux/netlink.h> #include <linux/spinlock.h> |
40a839fdb [NETFILTER]: nf_c... |
30 |
#include <linux/interrupt.h> |
5a0e3ad6a include cleanup: ... |
31 |
#include <linux/slab.h> |
3c7910763 netfilter: ctnetl... |
32 |
#include <linux/siphash.h> |
c1d10adb4 [NETFILTER]: Add ... |
33 34 |
#include <linux/netfilter.h> |
dc5fc579b [NETLINK]: Use nl... |
35 |
#include <net/netlink.h> |
9592a5c01 netfilter: ctnetl... |
36 |
#include <net/sock.h> |
c1d10adb4 [NETFILTER]: Add ... |
37 38 |
#include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack_core.h> |
77ab9cff0 [NETFILTER]: nf_c... |
39 |
#include <net/netfilter/nf_conntrack_expect.h> |
c1d10adb4 [NETFILTER]: Add ... |
40 |
#include <net/netfilter/nf_conntrack_helper.h> |
41d73ec05 netfilter: nf_con... |
41 |
#include <net/netfilter/nf_conntrack_seqadj.h> |
605dcad6c [NETFILTER]: nf_c... |
42 |
#include <net/netfilter/nf_conntrack_l4proto.h> |
5b1158e90 [NETFILTER]: Add ... |
43 |
#include <net/netfilter/nf_conntrack_tuple.h> |
584015727 netfilter: accoun... |
44 |
#include <net/netfilter/nf_conntrack_acct.h> |
ef00f89f1 netfilter: ctnetl... |
45 |
#include <net/netfilter/nf_conntrack_zones.h> |
a992ca2a0 netfilter: nf_con... |
46 |
#include <net/netfilter/nf_conntrack_timestamp.h> |
c539f0171 netfilter: add co... |
47 |
#include <net/netfilter/nf_conntrack_labels.h> |
87e94dbc2 netfilter: synpro... |
48 |
#include <net/netfilter/nf_conntrack_synproxy.h> |
4806e9757 netfilter: replac... |
49 |
#if IS_ENABLED(CONFIG_NF_NAT) |
d2c5c103b netfilter: nat: r... |
50 |
#include <net/netfilter/nf_nat.h> |
8c88f87cb netfilter: nfnetl... |
51 |
#include <net/netfilter/nf_nat_helper.h> |
5b1158e90 [NETFILTER]: Add ... |
52 |
#endif |
c1d10adb4 [NETFILTER]: Add ... |
53 54 55 |
#include <linux/netfilter/nfnetlink.h> #include <linux/netfilter/nfnetlink_conntrack.h> |
cb8aa9a3a netfilter: ctnetl... |
56 |
#include "nf_internals.h" |
c1d10adb4 [NETFILTER]: Add ... |
57 |
MODULE_LICENSE("GPL"); |
4054ff454 netfilter: ctnetl... |
58 |
static int ctnetlink_dump_tuples_proto(struct sk_buff *skb, |
2a04aabf5 netfilter: consti... |
59 60 |
const struct nf_conntrack_tuple *tuple, const struct nf_conntrack_l4proto *l4proto) |
c1d10adb4 [NETFILTER]: Add ... |
61 |
{ |
c1d10adb4 [NETFILTER]: Add ... |
62 |
int ret = 0; |
df6fb868d [NETFILTER]: nfne... |
63 |
struct nlattr *nest_parms; |
c1d10adb4 [NETFILTER]: Add ... |
64 |
|
ae0be8de9 netlink: make nla... |
65 |
nest_parms = nla_nest_start(skb, CTA_TUPLE_PROTO); |
df6fb868d [NETFILTER]: nfne... |
66 67 |
if (!nest_parms) goto nla_put_failure; |
cc1eb4313 nf_conntrack_netl... |
68 69 |
if (nla_put_u8(skb, CTA_PROTO_NUM, tuple->dst.protonum)) goto nla_put_failure; |
c1d10adb4 [NETFILTER]: Add ... |
70 |
|
fdf708322 [NETFILTER]: nfne... |
71 72 |
if (likely(l4proto->tuple_to_nlattr)) ret = l4proto->tuple_to_nlattr(skb, tuple); |
601e68e10 [NETFILTER]: Fix ... |
73 |
|
df6fb868d [NETFILTER]: nfne... |
74 |
nla_nest_end(skb, nest_parms); |
c1d10adb4 [NETFILTER]: Add ... |
75 76 |
return ret; |
df6fb868d [NETFILTER]: nfne... |
77 |
nla_put_failure: |
c1d10adb4 [NETFILTER]: Add ... |
78 79 |
return -1; } |
f957be9d3 netfilter: conntr... |
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
static int ipv4_tuple_to_nlattr(struct sk_buff *skb, const struct nf_conntrack_tuple *tuple) { if (nla_put_in_addr(skb, CTA_IP_V4_SRC, tuple->src.u3.ip) || nla_put_in_addr(skb, CTA_IP_V4_DST, tuple->dst.u3.ip)) return -EMSGSIZE; return 0; } static int ipv6_tuple_to_nlattr(struct sk_buff *skb, const struct nf_conntrack_tuple *tuple) { if (nla_put_in6_addr(skb, CTA_IP_V6_SRC, &tuple->src.u3.in6) || nla_put_in6_addr(skb, CTA_IP_V6_DST, &tuple->dst.u3.in6)) return -EMSGSIZE; return 0; } |
4054ff454 netfilter: ctnetl... |
97 |
static int ctnetlink_dump_tuples_ip(struct sk_buff *skb, |
f957be9d3 netfilter: conntr... |
98 |
const struct nf_conntrack_tuple *tuple) |
c1d10adb4 [NETFILTER]: Add ... |
99 |
{ |
c1d10adb4 [NETFILTER]: Add ... |
100 |
int ret = 0; |
df6fb868d [NETFILTER]: nfne... |
101 |
struct nlattr *nest_parms; |
ae0be8de9 netlink: make nla... |
102 |
nest_parms = nla_nest_start(skb, CTA_TUPLE_IP); |
df6fb868d [NETFILTER]: nfne... |
103 104 |
if (!nest_parms) goto nla_put_failure; |
1cde64365 [NETFILTER]: ctne... |
105 |
|
f957be9d3 netfilter: conntr... |
106 107 108 109 110 111 112 113 |
switch (tuple->src.l3num) { case NFPROTO_IPV4: ret = ipv4_tuple_to_nlattr(skb, tuple); break; case NFPROTO_IPV6: ret = ipv6_tuple_to_nlattr(skb, tuple); break; } |
1cde64365 [NETFILTER]: ctne... |
114 |
|
df6fb868d [NETFILTER]: nfne... |
115 |
nla_nest_end(skb, nest_parms); |
c1d10adb4 [NETFILTER]: Add ... |
116 |
|
1cde64365 [NETFILTER]: ctne... |
117 |
return ret; |
df6fb868d [NETFILTER]: nfne... |
118 |
nla_put_failure: |
1cde64365 [NETFILTER]: ctne... |
119 120 |
return -1; } |
4054ff454 netfilter: ctnetl... |
121 122 |
static int ctnetlink_dump_tuples(struct sk_buff *skb, const struct nf_conntrack_tuple *tuple) |
1cde64365 [NETFILTER]: ctne... |
123 |
{ |
b3480fe05 netfilter: conntr... |
124 |
const struct nf_conntrack_l4proto *l4proto; |
1cde64365 [NETFILTER]: ctne... |
125 |
int ret; |
1cde64365 [NETFILTER]: ctne... |
126 |
|
3b988ece9 netfilter: ctnetl... |
127 |
rcu_read_lock(); |
f957be9d3 netfilter: conntr... |
128 |
ret = ctnetlink_dump_tuples_ip(skb, tuple); |
c1d10adb4 [NETFILTER]: Add ... |
129 |
|
3b988ece9 netfilter: ctnetl... |
130 |
if (ret >= 0) { |
4a60dc748 netfilter: conntr... |
131 |
l4proto = nf_ct_l4proto_find(tuple->dst.protonum); |
3b988ece9 netfilter: ctnetl... |
132 133 134 |
ret = ctnetlink_dump_tuples_proto(skb, tuple, l4proto); } rcu_read_unlock(); |
c1d10adb4 [NETFILTER]: Add ... |
135 |
return ret; |
c1d10adb4 [NETFILTER]: Add ... |
136 |
} |
4054ff454 netfilter: ctnetl... |
137 138 |
static int ctnetlink_dump_zone_id(struct sk_buff *skb, int attrtype, const struct nf_conntrack_zone *zone, int dir) |
deedb5903 netfilter: nf_con... |
139 140 141 142 143 144 145 146 147 148 |
{ if (zone->id == NF_CT_DEFAULT_ZONE_ID || zone->dir != dir) return 0; if (nla_put_be16(skb, attrtype, htons(zone->id))) goto nla_put_failure; return 0; nla_put_failure: return -1; } |
4054ff454 netfilter: ctnetl... |
149 |
static int ctnetlink_dump_status(struct sk_buff *skb, const struct nf_conn *ct) |
c1d10adb4 [NETFILTER]: Add ... |
150 |
{ |
cc1eb4313 nf_conntrack_netl... |
151 152 |
if (nla_put_be32(skb, CTA_STATUS, htonl(ct->status))) goto nla_put_failure; |
c1d10adb4 [NETFILTER]: Add ... |
153 |
return 0; |
df6fb868d [NETFILTER]: nfne... |
154 |
nla_put_failure: |
c1d10adb4 [NETFILTER]: Add ... |
155 156 |
return -1; } |
4054ff454 netfilter: ctnetl... |
157 |
static int ctnetlink_dump_timeout(struct sk_buff *skb, const struct nf_conn *ct) |
c1d10adb4 [NETFILTER]: Add ... |
158 |
{ |
d0b35b93d netfilter: use_nf... |
159 |
long timeout = nf_ct_expires(ct) / HZ; |
601e68e10 [NETFILTER]: Fix ... |
160 |
|
cc1eb4313 nf_conntrack_netl... |
161 162 |
if (nla_put_be32(skb, CTA_TIMEOUT, htonl(timeout))) goto nla_put_failure; |
c1d10adb4 [NETFILTER]: Add ... |
163 |
return 0; |
df6fb868d [NETFILTER]: nfne... |
164 |
nla_put_failure: |
c1d10adb4 [NETFILTER]: Add ... |
165 166 |
return -1; } |
4054ff454 netfilter: ctnetl... |
167 |
static int ctnetlink_dump_protoinfo(struct sk_buff *skb, struct nf_conn *ct) |
c1d10adb4 [NETFILTER]: Add ... |
168 |
{ |
b3480fe05 netfilter: conntr... |
169 |
const struct nf_conntrack_l4proto *l4proto; |
df6fb868d [NETFILTER]: nfne... |
170 |
struct nlattr *nest_proto; |
c1d10adb4 [NETFILTER]: Add ... |
171 |
int ret; |
4a60dc748 netfilter: conntr... |
172 |
l4proto = nf_ct_l4proto_find(nf_ct_protonum(ct)); |
528a3a6f6 netfilter: ctnetl... |
173 |
if (!l4proto->to_nlattr) |
c1d10adb4 [NETFILTER]: Add ... |
174 |
return 0; |
601e68e10 [NETFILTER]: Fix ... |
175 |
|
ae0be8de9 netlink: make nla... |
176 |
nest_proto = nla_nest_start(skb, CTA_PROTOINFO); |
df6fb868d [NETFILTER]: nfne... |
177 178 |
if (!nest_proto) goto nla_put_failure; |
c1d10adb4 [NETFILTER]: Add ... |
179 |
|
fdf708322 [NETFILTER]: nfne... |
180 |
ret = l4proto->to_nlattr(skb, nest_proto, ct); |
c1d10adb4 [NETFILTER]: Add ... |
181 |
|
df6fb868d [NETFILTER]: nfne... |
182 |
nla_nest_end(skb, nest_proto); |
c1d10adb4 [NETFILTER]: Add ... |
183 184 |
return ret; |
df6fb868d [NETFILTER]: nfne... |
185 |
nla_put_failure: |
c1d10adb4 [NETFILTER]: Add ... |
186 187 |
return -1; } |
4054ff454 netfilter: ctnetl... |
188 189 |
static int ctnetlink_dump_helpinfo(struct sk_buff *skb, const struct nf_conn *ct) |
c1d10adb4 [NETFILTER]: Add ... |
190 |
{ |
df6fb868d [NETFILTER]: nfne... |
191 |
struct nlattr *nest_helper; |
dc808fe28 [NETFILTER] nf_co... |
192 |
const struct nf_conn_help *help = nfct_help(ct); |
3c158f7f5 [NETFILTER]: nf_c... |
193 |
struct nf_conntrack_helper *helper; |
c1d10adb4 [NETFILTER]: Add ... |
194 |
|
3c158f7f5 [NETFILTER]: nf_c... |
195 |
if (!help) |
c1d10adb4 [NETFILTER]: Add ... |
196 |
return 0; |
601e68e10 [NETFILTER]: Fix ... |
197 |
|
3c158f7f5 [NETFILTER]: nf_c... |
198 199 200 |
helper = rcu_dereference(help->helper); if (!helper) goto out; |
ae0be8de9 netlink: make nla... |
201 |
nest_helper = nla_nest_start(skb, CTA_HELP); |
df6fb868d [NETFILTER]: nfne... |
202 203 |
if (!nest_helper) goto nla_put_failure; |
cc1eb4313 nf_conntrack_netl... |
204 205 |
if (nla_put_string(skb, CTA_HELP_NAME, helper->name)) goto nla_put_failure; |
c1d10adb4 [NETFILTER]: Add ... |
206 |
|
fdf708322 [NETFILTER]: nfne... |
207 208 |
if (helper->to_nlattr) helper->to_nlattr(skb, ct); |
c1d10adb4 [NETFILTER]: Add ... |
209 |
|
df6fb868d [NETFILTER]: nfne... |
210 |
nla_nest_end(skb, nest_helper); |
3c158f7f5 [NETFILTER]: nf_c... |
211 |
out: |
c1d10adb4 [NETFILTER]: Add ... |
212 |
return 0; |
df6fb868d [NETFILTER]: nfne... |
213 |
nla_put_failure: |
c1d10adb4 [NETFILTER]: Add ... |
214 215 |
return -1; } |
bb5cf80e9 [NETFILTER]: Kill... |
216 |
static int |
4542fa472 netfilter: ctnetl... |
217 218 |
dump_counters(struct sk_buff *skb, struct nf_conn_acct *acct, enum ip_conntrack_dir dir, int type) |
c1d10adb4 [NETFILTER]: Add ... |
219 |
{ |
4542fa472 netfilter: ctnetl... |
220 221 |
enum ctattr_type attr = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG; struct nf_conn_counter *counter = acct->counter; |
df6fb868d [NETFILTER]: nfne... |
222 |
struct nlattr *nest_count; |
4542fa472 netfilter: ctnetl... |
223 |
u64 pkts, bytes; |
c1d10adb4 [NETFILTER]: Add ... |
224 |
|
4542fa472 netfilter: ctnetl... |
225 226 227 228 229 230 231 |
if (type == IPCTNL_MSG_CT_GET_CTRZERO) { pkts = atomic64_xchg(&counter[dir].packets, 0); bytes = atomic64_xchg(&counter[dir].bytes, 0); } else { pkts = atomic64_read(&counter[dir].packets); bytes = atomic64_read(&counter[dir].bytes); } |
ae0be8de9 netlink: make nla... |
232 |
nest_count = nla_nest_start(skb, attr); |
df6fb868d [NETFILTER]: nfne... |
233 234 |
if (!nest_count) goto nla_put_failure; |
b46f6ded9 libnl: nla_put_be... |
235 236 237 238 |
if (nla_put_be64(skb, CTA_COUNTERS_PACKETS, cpu_to_be64(pkts), CTA_COUNTERS_PAD) || nla_put_be64(skb, CTA_COUNTERS_BYTES, cpu_to_be64(bytes), CTA_COUNTERS_PAD)) |
cc1eb4313 nf_conntrack_netl... |
239 |
goto nla_put_failure; |
c1d10adb4 [NETFILTER]: Add ... |
240 |
|
df6fb868d [NETFILTER]: nfne... |
241 |
nla_nest_end(skb, nest_count); |
c1d10adb4 [NETFILTER]: Add ... |
242 243 |
return 0; |
df6fb868d [NETFILTER]: nfne... |
244 |
nla_put_failure: |
c1d10adb4 [NETFILTER]: Add ... |
245 246 |
return -1; } |
c1d10adb4 [NETFILTER]: Add ... |
247 |
|
a992ca2a0 netfilter: nf_con... |
248 |
static int |
4542fa472 netfilter: ctnetl... |
249 |
ctnetlink_dump_acct(struct sk_buff *skb, const struct nf_conn *ct, int type) |
80e60e67b netfilter: ctnetl... |
250 |
{ |
4542fa472 netfilter: ctnetl... |
251 |
struct nf_conn_acct *acct = nf_conn_acct_find(ct); |
80e60e67b netfilter: ctnetl... |
252 |
|
80e60e67b netfilter: ctnetl... |
253 254 |
if (!acct) return 0; |
4542fa472 netfilter: ctnetl... |
255 256 257 258 259 260 |
if (dump_counters(skb, acct, IP_CT_DIR_ORIGINAL, type) < 0) return -1; if (dump_counters(skb, acct, IP_CT_DIR_REPLY, type) < 0) return -1; return 0; |
80e60e67b netfilter: ctnetl... |
261 262 263 |
} static int |
a992ca2a0 netfilter: nf_con... |
264 265 266 267 268 269 270 271 |
ctnetlink_dump_timestamp(struct sk_buff *skb, const struct nf_conn *ct) { struct nlattr *nest_count; const struct nf_conn_tstamp *tstamp; tstamp = nf_conn_tstamp_find(ct); if (!tstamp) return 0; |
ae0be8de9 netlink: make nla... |
272 |
nest_count = nla_nest_start(skb, CTA_TIMESTAMP); |
a992ca2a0 netfilter: nf_con... |
273 274 |
if (!nest_count) goto nla_put_failure; |
b46f6ded9 libnl: nla_put_be... |
275 276 |
if (nla_put_be64(skb, CTA_TIMESTAMP_START, cpu_to_be64(tstamp->start), CTA_TIMESTAMP_PAD) || |
cc1eb4313 nf_conntrack_netl... |
277 |
(tstamp->stop != 0 && nla_put_be64(skb, CTA_TIMESTAMP_STOP, |
b46f6ded9 libnl: nla_put_be... |
278 279 |
cpu_to_be64(tstamp->stop), CTA_TIMESTAMP_PAD))) |
cc1eb4313 nf_conntrack_netl... |
280 |
goto nla_put_failure; |
a992ca2a0 netfilter: nf_con... |
281 282 283 284 285 286 287 |
nla_nest_end(skb, nest_count); return 0; nla_put_failure: return -1; } |
c1d10adb4 [NETFILTER]: Add ... |
288 |
#ifdef CONFIG_NF_CONNTRACK_MARK |
4054ff454 netfilter: ctnetl... |
289 |
static int ctnetlink_dump_mark(struct sk_buff *skb, const struct nf_conn *ct) |
c1d10adb4 [NETFILTER]: Add ... |
290 |
{ |
cc1eb4313 nf_conntrack_netl... |
291 292 |
if (nla_put_be32(skb, CTA_MARK, htonl(ct->mark))) goto nla_put_failure; |
c1d10adb4 [NETFILTER]: Add ... |
293 |
return 0; |
df6fb868d [NETFILTER]: nfne... |
294 |
nla_put_failure: |
c1d10adb4 [NETFILTER]: Add ... |
295 296 297 298 299 |
return -1; } #else #define ctnetlink_dump_mark(a, b) (0) #endif |
37fccd857 [NETFILTER]: ctne... |
300 |
#ifdef CONFIG_NF_CONNTRACK_SECMARK |
4054ff454 netfilter: ctnetl... |
301 |
static int ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct) |
37fccd857 [NETFILTER]: ctne... |
302 |
{ |
1cc63249a conntrack: export... |
303 304 305 306 307 308 |
struct nlattr *nest_secctx; int len, ret; char *secctx; ret = security_secid_to_secctx(ct->secmark, &secctx, &len); if (ret) |
cba85b532 netfilter: fix ex... |
309 |
return 0; |
1cc63249a conntrack: export... |
310 311 |
ret = -1; |
ae0be8de9 netlink: make nla... |
312 |
nest_secctx = nla_nest_start(skb, CTA_SECCTX); |
1cc63249a conntrack: export... |
313 314 |
if (!nest_secctx) goto nla_put_failure; |
37fccd857 [NETFILTER]: ctne... |
315 |
|
cc1eb4313 nf_conntrack_netl... |
316 317 |
if (nla_put_string(skb, CTA_SECCTX_NAME, secctx)) goto nla_put_failure; |
1cc63249a conntrack: export... |
318 319 320 |
nla_nest_end(skb, nest_secctx); ret = 0; |
37fccd857 [NETFILTER]: ctne... |
321 |
nla_put_failure: |
1cc63249a conntrack: export... |
322 323 |
security_release_secctx(secctx, len); return ret; |
37fccd857 [NETFILTER]: ctne... |
324 325 |
} #else |
1cc63249a conntrack: export... |
326 |
#define ctnetlink_dump_secctx(a, b) (0) |
37fccd857 [NETFILTER]: ctne... |
327 |
#endif |
0ceabd838 netfilter: ctnetl... |
328 |
#ifdef CONFIG_NF_CONNTRACK_LABELS |
4a96300ce netfilter: ctnetl... |
329 |
static inline int ctnetlink_label_size(const struct nf_conn *ct) |
0ceabd838 netfilter: ctnetl... |
330 331 332 333 334 |
{ struct nf_conn_labels *labels = nf_ct_labels_find(ct); if (!labels) return 0; |
23014011b netfilter: conntr... |
335 |
return nla_total_size(sizeof(labels->bits)); |
0ceabd838 netfilter: ctnetl... |
336 337 338 339 340 341 |
} static int ctnetlink_dump_labels(struct sk_buff *skb, const struct nf_conn *ct) { struct nf_conn_labels *labels = nf_ct_labels_find(ct); |
23014011b netfilter: conntr... |
342 |
unsigned int i; |
0ceabd838 netfilter: ctnetl... |
343 344 345 |
if (!labels) return 0; |
0ceabd838 netfilter: ctnetl... |
346 347 348 |
i = 0; do { if (labels->bits[i] != 0) |
23014011b netfilter: conntr... |
349 350 |
return nla_put(skb, CTA_LABELS, sizeof(labels->bits), labels->bits); |
0ceabd838 netfilter: ctnetl... |
351 |
i++; |
23014011b netfilter: conntr... |
352 |
} while (i < ARRAY_SIZE(labels->bits)); |
0ceabd838 netfilter: ctnetl... |
353 354 355 356 357 358 359 |
return 0; } #else #define ctnetlink_dump_labels(a, b) (0) #define ctnetlink_label_size(a) (0) #endif |
0f417ce98 [NETFILTER]: ctne... |
360 |
#define master_tuple(ct) &(ct->master->tuplehash[IP_CT_DIR_ORIGINAL].tuple) |
4054ff454 netfilter: ctnetl... |
361 |
static int ctnetlink_dump_master(struct sk_buff *skb, const struct nf_conn *ct) |
0f417ce98 [NETFILTER]: ctne... |
362 363 364 365 366 |
{ struct nlattr *nest_parms; if (!(ct->status & IPS_EXPECTED)) return 0; |
ae0be8de9 netlink: make nla... |
367 |
nest_parms = nla_nest_start(skb, CTA_TUPLE_MASTER); |
0f417ce98 [NETFILTER]: ctne... |
368 369 370 371 372 373 374 375 376 377 378 |
if (!nest_parms) goto nla_put_failure; if (ctnetlink_dump_tuples(skb, master_tuple(ct)) < 0) goto nla_put_failure; nla_nest_end(skb, nest_parms); return 0; nla_put_failure: return -1; } |
bb5cf80e9 [NETFILTER]: Kill... |
379 |
static int |
41d73ec05 netfilter: nf_con... |
380 |
dump_ct_seq_adj(struct sk_buff *skb, const struct nf_ct_seqadj *seq, int type) |
13eae15a2 [NETFILTER]: ctne... |
381 |
{ |
13eae15a2 [NETFILTER]: ctne... |
382 |
struct nlattr *nest_parms; |
ae0be8de9 netlink: make nla... |
383 |
nest_parms = nla_nest_start(skb, type); |
13eae15a2 [NETFILTER]: ctne... |
384 385 |
if (!nest_parms) goto nla_put_failure; |
41d73ec05 netfilter: nf_con... |
386 387 388 389 390 391 |
if (nla_put_be32(skb, CTA_SEQADJ_CORRECTION_POS, htonl(seq->correction_pos)) || nla_put_be32(skb, CTA_SEQADJ_OFFSET_BEFORE, htonl(seq->offset_before)) || nla_put_be32(skb, CTA_SEQADJ_OFFSET_AFTER, htonl(seq->offset_after))) |
cc1eb4313 nf_conntrack_netl... |
392 |
goto nla_put_failure; |
13eae15a2 [NETFILTER]: ctne... |
393 394 395 396 397 398 399 400 |
nla_nest_end(skb, nest_parms); return 0; nla_put_failure: return -1; } |
64f3967c7 netfilter: ctnetl... |
401 |
static int ctnetlink_dump_ct_seq_adj(struct sk_buff *skb, struct nf_conn *ct) |
13eae15a2 [NETFILTER]: ctne... |
402 |
{ |
41d73ec05 netfilter: nf_con... |
403 404 |
struct nf_conn_seqadj *seqadj = nfct_seqadj(ct); struct nf_ct_seqadj *seq; |
13eae15a2 [NETFILTER]: ctne... |
405 |
|
41d73ec05 netfilter: nf_con... |
406 |
if (!(ct->status & IPS_SEQ_ADJUST) || !seqadj) |
13eae15a2 [NETFILTER]: ctne... |
407 |
return 0; |
64f3967c7 netfilter: ctnetl... |
408 |
spin_lock_bh(&ct->lock); |
41d73ec05 netfilter: nf_con... |
409 410 |
seq = &seqadj->seq[IP_CT_DIR_ORIGINAL]; if (dump_ct_seq_adj(skb, seq, CTA_SEQ_ADJ_ORIG) == -1) |
64f3967c7 netfilter: ctnetl... |
411 |
goto err; |
13eae15a2 [NETFILTER]: ctne... |
412 |
|
41d73ec05 netfilter: nf_con... |
413 414 |
seq = &seqadj->seq[IP_CT_DIR_REPLY]; if (dump_ct_seq_adj(skb, seq, CTA_SEQ_ADJ_REPLY) == -1) |
64f3967c7 netfilter: ctnetl... |
415 |
goto err; |
13eae15a2 [NETFILTER]: ctne... |
416 |
|
64f3967c7 netfilter: ctnetl... |
417 |
spin_unlock_bh(&ct->lock); |
13eae15a2 [NETFILTER]: ctne... |
418 |
return 0; |
64f3967c7 netfilter: ctnetl... |
419 420 421 |
err: spin_unlock_bh(&ct->lock); return -1; |
13eae15a2 [NETFILTER]: ctne... |
422 |
} |
13eae15a2 [NETFILTER]: ctne... |
423 |
|
20710b3b8 netfilter: ctnetl... |
424 425 426 427 428 429 430 |
static int ctnetlink_dump_ct_synproxy(struct sk_buff *skb, struct nf_conn *ct) { struct nf_conn_synproxy *synproxy = nfct_synproxy(ct); struct nlattr *nest_parms; if (!synproxy) return 0; |
ae0be8de9 netlink: make nla... |
431 |
nest_parms = nla_nest_start(skb, CTA_SYNPROXY); |
20710b3b8 netfilter: ctnetl... |
432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 |
if (!nest_parms) goto nla_put_failure; if (nla_put_be32(skb, CTA_SYNPROXY_ISN, htonl(synproxy->isn)) || nla_put_be32(skb, CTA_SYNPROXY_ITS, htonl(synproxy->its)) || nla_put_be32(skb, CTA_SYNPROXY_TSOFF, htonl(synproxy->tsoff))) goto nla_put_failure; nla_nest_end(skb, nest_parms); return 0; nla_put_failure: return -1; } |
4054ff454 netfilter: ctnetl... |
447 |
static int ctnetlink_dump_id(struct sk_buff *skb, const struct nf_conn *ct) |
c1d10adb4 [NETFILTER]: Add ... |
448 |
{ |
3c7910763 netfilter: ctnetl... |
449 450 451 |
__be32 id = (__force __be32)nf_ct_get_id(ct); if (nla_put_be32(skb, CTA_ID, id)) |
cc1eb4313 nf_conntrack_netl... |
452 |
goto nla_put_failure; |
c1d10adb4 [NETFILTER]: Add ... |
453 |
return 0; |
df6fb868d [NETFILTER]: nfne... |
454 |
nla_put_failure: |
c1d10adb4 [NETFILTER]: Add ... |
455 456 |
return -1; } |
4054ff454 netfilter: ctnetl... |
457 |
static int ctnetlink_dump_use(struct sk_buff *skb, const struct nf_conn *ct) |
c1d10adb4 [NETFILTER]: Add ... |
458 |
{ |
cc1eb4313 nf_conntrack_netl... |
459 460 |
if (nla_put_be32(skb, CTA_USE, htonl(atomic_read(&ct->ct_general.use)))) goto nla_put_failure; |
c1d10adb4 [NETFILTER]: Add ... |
461 |
return 0; |
df6fb868d [NETFILTER]: nfne... |
462 |
nla_put_failure: |
c1d10adb4 [NETFILTER]: Add ... |
463 464 |
return -1; } |
49ca022bc netfilter: ctnetl... |
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 |
/* all these functions access ct->ext. Caller must either hold a reference * on ct or prevent its deletion by holding either the bucket spinlock or * pcpu dying list lock. */ static int ctnetlink_dump_extinfo(struct sk_buff *skb, struct nf_conn *ct, u32 type) { if (ctnetlink_dump_acct(skb, ct, type) < 0 || ctnetlink_dump_timestamp(skb, ct) < 0 || ctnetlink_dump_helpinfo(skb, ct) < 0 || ctnetlink_dump_labels(skb, ct) < 0 || ctnetlink_dump_ct_seq_adj(skb, ct) < 0 || ctnetlink_dump_ct_synproxy(skb, ct) < 0) return -1; return 0; } static int ctnetlink_dump_info(struct sk_buff *skb, struct nf_conn *ct) { if (ctnetlink_dump_status(skb, ct) < 0 || ctnetlink_dump_mark(skb, ct) < 0 || ctnetlink_dump_secctx(skb, ct) < 0 || ctnetlink_dump_id(skb, ct) < 0 || ctnetlink_dump_use(skb, ct) < 0 || ctnetlink_dump_master(skb, ct) < 0) return -1; if (!test_bit(IPS_OFFLOAD_BIT, &ct->status) && (ctnetlink_dump_timeout(skb, ct) < 0 || ctnetlink_dump_protoinfo(skb, ct) < 0)) return -1; return 0; } |
c1d10adb4 [NETFILTER]: Add ... |
500 |
static int |
15e473046 netlink: Rename p... |
501 |
ctnetlink_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type, |
cb8aa9a3a netfilter: ctnetl... |
502 |
struct nf_conn *ct, bool extinfo, unsigned int flags) |
c1d10adb4 [NETFILTER]: Add ... |
503 |
{ |
308ac9143 netfilter: nf_con... |
504 |
const struct nf_conntrack_zone *zone; |
c1d10adb4 [NETFILTER]: Add ... |
505 506 |
struct nlmsghdr *nlh; struct nfgenmsg *nfmsg; |
df6fb868d [NETFILTER]: nfne... |
507 |
struct nlattr *nest_parms; |
cb8aa9a3a netfilter: ctnetl... |
508 |
unsigned int event; |
c1d10adb4 [NETFILTER]: Add ... |
509 |
|
cb8aa9a3a netfilter: ctnetl... |
510 511 |
if (portid) flags |= NLM_F_MULTI; |
dedb67c4b netfilter: Add nf... |
512 |
event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_NEW); |
15e473046 netlink: Rename p... |
513 |
nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags); |
96bcf938d netfilter: ctnetl... |
514 515 |
if (nlh == NULL) goto nlmsg_failure; |
c1d10adb4 [NETFILTER]: Add ... |
516 |
|
96bcf938d netfilter: ctnetl... |
517 |
nfmsg = nlmsg_data(nlh); |
5e8fbe2ac [NETFILTER]: nf_c... |
518 |
nfmsg->nfgen_family = nf_ct_l3num(ct); |
c1d10adb4 [NETFILTER]: Add ... |
519 520 |
nfmsg->version = NFNETLINK_V0; nfmsg->res_id = 0; |
deedb5903 netfilter: nf_con... |
521 |
zone = nf_ct_zone(ct); |
ae0be8de9 netlink: make nla... |
522 |
nest_parms = nla_nest_start(skb, CTA_TUPLE_ORIG); |
df6fb868d [NETFILTER]: nfne... |
523 524 |
if (!nest_parms) goto nla_put_failure; |
f2f3e38c6 netfilter: ctnetl... |
525 |
if (ctnetlink_dump_tuples(skb, nf_ct_tuple(ct, IP_CT_DIR_ORIGINAL)) < 0) |
df6fb868d [NETFILTER]: nfne... |
526 |
goto nla_put_failure; |
deedb5903 netfilter: nf_con... |
527 528 529 |
if (ctnetlink_dump_zone_id(skb, CTA_TUPLE_ZONE, zone, NF_CT_ZONE_DIR_ORIG) < 0) goto nla_put_failure; |
df6fb868d [NETFILTER]: nfne... |
530 |
nla_nest_end(skb, nest_parms); |
601e68e10 [NETFILTER]: Fix ... |
531 |
|
ae0be8de9 netlink: make nla... |
532 |
nest_parms = nla_nest_start(skb, CTA_TUPLE_REPLY); |
df6fb868d [NETFILTER]: nfne... |
533 534 |
if (!nest_parms) goto nla_put_failure; |
f2f3e38c6 netfilter: ctnetl... |
535 |
if (ctnetlink_dump_tuples(skb, nf_ct_tuple(ct, IP_CT_DIR_REPLY)) < 0) |
df6fb868d [NETFILTER]: nfne... |
536 |
goto nla_put_failure; |
deedb5903 netfilter: nf_con... |
537 538 539 |
if (ctnetlink_dump_zone_id(skb, CTA_TUPLE_ZONE, zone, NF_CT_ZONE_DIR_REPL) < 0) goto nla_put_failure; |
df6fb868d [NETFILTER]: nfne... |
540 |
nla_nest_end(skb, nest_parms); |
c1d10adb4 [NETFILTER]: Add ... |
541 |
|
deedb5903 netfilter: nf_con... |
542 543 |
if (ctnetlink_dump_zone_id(skb, CTA_ZONE, zone, NF_CT_DEFAULT_ZONE_DIR) < 0) |
cc1eb4313 nf_conntrack_netl... |
544 |
goto nla_put_failure; |
ef00f89f1 netfilter: ctnetl... |
545 |
|
49ca022bc netfilter: ctnetl... |
546 |
if (ctnetlink_dump_info(skb, ct) < 0) |
df6fb868d [NETFILTER]: nfne... |
547 |
goto nla_put_failure; |
49ca022bc netfilter: ctnetl... |
548 |
if (extinfo && ctnetlink_dump_extinfo(skb, ct, type) < 0) |
b067fa009 netfilter: ctnetl... |
549 |
goto nla_put_failure; |
96bcf938d netfilter: ctnetl... |
550 |
nlmsg_end(skb, nlh); |
c1d10adb4 [NETFILTER]: Add ... |
551 552 553 |
return skb->len; nlmsg_failure: |
df6fb868d [NETFILTER]: nfne... |
554 |
nla_put_failure: |
96bcf938d netfilter: ctnetl... |
555 |
nlmsg_cancel(skb, nlh); |
c1d10adb4 [NETFILTER]: Add ... |
556 557 |
return -1; } |
f957be9d3 netfilter: conntr... |
558 559 560 561 562 563 |
static const struct nla_policy cta_ip_nla_policy[CTA_IP_MAX + 1] = { [CTA_IP_V4_SRC] = { .type = NLA_U32 }, [CTA_IP_V4_DST] = { .type = NLA_U32 }, [CTA_IP_V6_SRC] = { .len = sizeof(__be32) * 4 }, [CTA_IP_V6_DST] = { .len = sizeof(__be32) * 4 }, }; |
8252fceac netfilter: add if... |
564 |
#if defined(CONFIG_NETFILTER_NETLINK_GLUE_CT) || defined(CONFIG_NF_CONNTRACK_EVENTS) |
5caaed151 netfilter: conntr... |
565 |
static size_t ctnetlink_proto_size(const struct nf_conn *ct) |
2732c4e45 netfilter: ctnetl... |
566 |
{ |
b3480fe05 netfilter: conntr... |
567 |
const struct nf_conntrack_l4proto *l4proto; |
5caaed151 netfilter: conntr... |
568 |
size_t len, len4 = 0; |
03b64f518 netfilter: ctnetl... |
569 |
|
f957be9d3 netfilter: conntr... |
570 |
len = nla_policy_len(cta_ip_nla_policy, CTA_IP_MAX + 1); |
0d0351003 netfilter: conntr... |
571 |
len *= 3u; /* ORIG, REPLY, MASTER */ |
03b64f518 netfilter: ctnetl... |
572 |
|
4a60dc748 netfilter: conntr... |
573 |
l4proto = nf_ct_l4proto_find(nf_ct_protonum(ct)); |
392158467 netfilter: conntr... |
574 |
len += l4proto->nlattr_size; |
5caaed151 netfilter: conntr... |
575 576 577 578 |
if (l4proto->nlattr_tuple_size) { len4 = l4proto->nlattr_tuple_size(); len4 *= 3u; /* ORIG, REPLY, MASTER */ } |
03b64f518 netfilter: ctnetl... |
579 |
|
5caaed151 netfilter: conntr... |
580 |
return len + len4; |
03b64f518 netfilter: ctnetl... |
581 |
} |
8252fceac netfilter: add if... |
582 |
#endif |
03b64f518 netfilter: ctnetl... |
583 |
|
4a96300ce netfilter: ctnetl... |
584 |
static inline size_t ctnetlink_acct_size(const struct nf_conn *ct) |
d26e6a028 netfilter: ctnetl... |
585 586 587 588 |
{ if (!nf_ct_ext_exist(ct, NF_CT_EXT_ACCT)) return 0; return 2 * nla_total_size(0) /* CTA_COUNTERS_ORIG|REPL */ |
b46f6ded9 libnl: nla_put_be... |
589 590 |
+ 2 * nla_total_size_64bit(sizeof(uint64_t)) /* CTA_COUNTERS_PACKETS */ + 2 * nla_total_size_64bit(sizeof(uint64_t)) /* CTA_COUNTERS_BYTES */ |
d26e6a028 netfilter: ctnetl... |
591 592 |
; } |
4a96300ce netfilter: ctnetl... |
593 |
static inline int ctnetlink_secctx_size(const struct nf_conn *ct) |
1cc63249a conntrack: export... |
594 |
{ |
cba85b532 netfilter: fix ex... |
595 596 |
#ifdef CONFIG_NF_CONNTRACK_SECMARK int len, ret; |
1cc63249a conntrack: export... |
597 |
|
cba85b532 netfilter: fix ex... |
598 599 600 |
ret = security_secid_to_secctx(ct->secmark, NULL, &len); if (ret) return 0; |
1cc63249a conntrack: export... |
601 |
|
cba85b532 netfilter: fix ex... |
602 603 604 605 |
return nla_total_size(0) /* CTA_SECCTX */ + nla_total_size(sizeof(char) * len); /* CTA_SECCTX_NAME */ #else return 0; |
1cc63249a conntrack: export... |
606 |
#endif |
cba85b532 netfilter: fix ex... |
607 |
} |
1cc63249a conntrack: export... |
608 |
|
4a96300ce netfilter: ctnetl... |
609 |
static inline size_t ctnetlink_timestamp_size(const struct nf_conn *ct) |
a992ca2a0 netfilter: nf_con... |
610 611 612 613 |
{ #ifdef CONFIG_NF_CONNTRACK_TIMESTAMP if (!nf_ct_ext_exist(ct, NF_CT_EXT_TSTAMP)) return 0; |
b46f6ded9 libnl: nla_put_be... |
614 |
return nla_total_size(0) + 2 * nla_total_size_64bit(sizeof(uint64_t)); |
a992ca2a0 netfilter: nf_con... |
615 616 617 618 |
#else return 0; #endif } |
4054ff454 netfilter: ctnetl... |
619 620 |
#ifdef CONFIG_NF_CONNTRACK_EVENTS static size_t ctnetlink_nlmsg_size(const struct nf_conn *ct) |
03b64f518 netfilter: ctnetl... |
621 622 623 624 625 626 627 628 |
{ return NLMSG_ALIGN(sizeof(struct nfgenmsg)) + 3 * nla_total_size(0) /* CTA_TUPLE_ORIG|REPL|MASTER */ + 3 * nla_total_size(0) /* CTA_TUPLE_IP */ + 3 * nla_total_size(0) /* CTA_TUPLE_PROTO */ + 3 * nla_total_size(sizeof(u_int8_t)) /* CTA_PROTO_NUM */ + nla_total_size(sizeof(u_int32_t)) /* CTA_ID */ + nla_total_size(sizeof(u_int32_t)) /* CTA_STATUS */ |
f7b13e433 netfilter: introd... |
629 |
+ ctnetlink_acct_size(ct) |
a992ca2a0 netfilter: nf_con... |
630 |
+ ctnetlink_timestamp_size(ct) |
03b64f518 netfilter: ctnetl... |
631 632 633 634 |
+ nla_total_size(sizeof(u_int32_t)) /* CTA_TIMEOUT */ + nla_total_size(0) /* CTA_PROTOINFO */ + nla_total_size(0) /* CTA_HELP */ + nla_total_size(NF_CT_HELPER_NAME_LEN) /* CTA_HELP_NAME */ |
cba85b532 netfilter: fix ex... |
635 |
+ ctnetlink_secctx_size(ct) |
4806e9757 netfilter: replac... |
636 |
#if IS_ENABLED(CONFIG_NF_NAT) |
03b64f518 netfilter: ctnetl... |
637 638 |
+ 2 * nla_total_size(0) /* CTA_NAT_SEQ_ADJ_ORIG|REPL */ + 6 * nla_total_size(sizeof(u_int32_t)) /* CTA_NAT_SEQ_OFFSET */ |
d271e8bd8 ctnetlink: comput... |
639 640 |
#endif #ifdef CONFIG_NF_CONNTRACK_MARK |
03b64f518 netfilter: ctnetl... |
641 |
+ nla_total_size(sizeof(u_int32_t)) /* CTA_MARK */ |
d271e8bd8 ctnetlink: comput... |
642 |
#endif |
4a001068d netfilter: ctnetl... |
643 |
#ifdef CONFIG_NF_CONNTRACK_ZONES |
deedb5903 netfilter: nf_con... |
644 |
+ nla_total_size(sizeof(u_int16_t)) /* CTA_ZONE|CTA_TUPLE_ZONE */ |
4a001068d netfilter: ctnetl... |
645 |
#endif |
03b64f518 netfilter: ctnetl... |
646 |
+ ctnetlink_proto_size(ct) |
0ceabd838 netfilter: ctnetl... |
647 |
+ ctnetlink_label_size(ct) |
03b64f518 netfilter: ctnetl... |
648 |
; |
2732c4e45 netfilter: ctnetl... |
649 |
} |
e34d5c1a4 netfilter: conntr... |
650 651 |
static int ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item) |
c1d10adb4 [NETFILTER]: Add ... |
652 |
{ |
308ac9143 netfilter: nf_con... |
653 |
const struct nf_conntrack_zone *zone; |
9592a5c01 netfilter: ctnetl... |
654 |
struct net *net; |
c1d10adb4 [NETFILTER]: Add ... |
655 656 |
struct nlmsghdr *nlh; struct nfgenmsg *nfmsg; |
df6fb868d [NETFILTER]: nfne... |
657 |
struct nlattr *nest_parms; |
19abb7b09 netfilter: ctnetl... |
658 |
struct nf_conn *ct = item->ct; |
c1d10adb4 [NETFILTER]: Add ... |
659 660 |
struct sk_buff *skb; unsigned int type; |
c1d10adb4 [NETFILTER]: Add ... |
661 |
unsigned int flags = 0, group; |
dd7669a92 netfilter: conntr... |
662 |
int err; |
c1d10adb4 [NETFILTER]: Add ... |
663 |
|
a0891aa6a netfilter: conntr... |
664 |
if (events & (1 << IPCT_DESTROY)) { |
c1d10adb4 [NETFILTER]: Add ... |
665 666 |
type = IPCTNL_MSG_CT_DELETE; group = NFNLGRP_CONNTRACK_DESTROY; |
04b80cead netfilter: ctnetl... |
667 |
} else if (events & ((1 << IPCT_NEW) | (1 << IPCT_RELATED))) { |
c1d10adb4 [NETFILTER]: Add ... |
668 669 |
type = IPCTNL_MSG_CT_NEW; flags = NLM_F_CREATE|NLM_F_EXCL; |
c1d10adb4 [NETFILTER]: Add ... |
670 |
group = NFNLGRP_CONNTRACK_NEW; |
04b80cead netfilter: ctnetl... |
671 |
} else if (events) { |
c1d10adb4 [NETFILTER]: Add ... |
672 673 674 |
type = IPCTNL_MSG_CT_NEW; group = NFNLGRP_CONNTRACK_UPDATE; } else |
e34d5c1a4 netfilter: conntr... |
675 |
return 0; |
a24276924 [NETFILTER]: ctne... |
676 |
|
9592a5c01 netfilter: ctnetl... |
677 678 |
net = nf_ct_net(ct); if (!item->report && !nfnetlink_has_listeners(net, group)) |
e34d5c1a4 netfilter: conntr... |
679 |
return 0; |
a24276924 [NETFILTER]: ctne... |
680 |
|
03b64f518 netfilter: ctnetl... |
681 682 |
skb = nlmsg_new(ctnetlink_nlmsg_size(ct), GFP_ATOMIC); if (skb == NULL) |
150ace0db netfilter: ctnetl... |
683 |
goto errout; |
c1d10adb4 [NETFILTER]: Add ... |
684 |
|
dedb67c4b netfilter: Add nf... |
685 |
type = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK, type); |
15e473046 netlink: Rename p... |
686 |
nlh = nlmsg_put(skb, item->portid, 0, type, sizeof(*nfmsg), flags); |
96bcf938d netfilter: ctnetl... |
687 688 |
if (nlh == NULL) goto nlmsg_failure; |
c1d10adb4 [NETFILTER]: Add ... |
689 |
|
96bcf938d netfilter: ctnetl... |
690 |
nfmsg = nlmsg_data(nlh); |
5e8fbe2ac [NETFILTER]: nf_c... |
691 |
nfmsg->nfgen_family = nf_ct_l3num(ct); |
c1d10adb4 [NETFILTER]: Add ... |
692 693 |
nfmsg->version = NFNETLINK_V0; nfmsg->res_id = 0; |
deedb5903 netfilter: nf_con... |
694 |
zone = nf_ct_zone(ct); |
ae0be8de9 netlink: make nla... |
695 |
nest_parms = nla_nest_start(skb, CTA_TUPLE_ORIG); |
df6fb868d [NETFILTER]: nfne... |
696 697 |
if (!nest_parms) goto nla_put_failure; |
f2f3e38c6 netfilter: ctnetl... |
698 |
if (ctnetlink_dump_tuples(skb, nf_ct_tuple(ct, IP_CT_DIR_ORIGINAL)) < 0) |
df6fb868d [NETFILTER]: nfne... |
699 |
goto nla_put_failure; |
deedb5903 netfilter: nf_con... |
700 701 702 |
if (ctnetlink_dump_zone_id(skb, CTA_TUPLE_ZONE, zone, NF_CT_ZONE_DIR_ORIG) < 0) goto nla_put_failure; |
df6fb868d [NETFILTER]: nfne... |
703 |
nla_nest_end(skb, nest_parms); |
601e68e10 [NETFILTER]: Fix ... |
704 |
|
ae0be8de9 netlink: make nla... |
705 |
nest_parms = nla_nest_start(skb, CTA_TUPLE_REPLY); |
df6fb868d [NETFILTER]: nfne... |
706 707 |
if (!nest_parms) goto nla_put_failure; |
f2f3e38c6 netfilter: ctnetl... |
708 |
if (ctnetlink_dump_tuples(skb, nf_ct_tuple(ct, IP_CT_DIR_REPLY)) < 0) |
df6fb868d [NETFILTER]: nfne... |
709 |
goto nla_put_failure; |
deedb5903 netfilter: nf_con... |
710 711 712 |
if (ctnetlink_dump_zone_id(skb, CTA_TUPLE_ZONE, zone, NF_CT_ZONE_DIR_REPL) < 0) goto nla_put_failure; |
df6fb868d [NETFILTER]: nfne... |
713 |
nla_nest_end(skb, nest_parms); |
c1d10adb4 [NETFILTER]: Add ... |
714 |
|
deedb5903 netfilter: nf_con... |
715 716 |
if (ctnetlink_dump_zone_id(skb, CTA_ZONE, zone, NF_CT_DEFAULT_ZONE_DIR) < 0) |
cc1eb4313 nf_conntrack_netl... |
717 |
goto nla_put_failure; |
ef00f89f1 netfilter: ctnetl... |
718 |
|
1eedf6999 netfilter: ctnetl... |
719 720 |
if (ctnetlink_dump_id(skb, ct) < 0) goto nla_put_failure; |
e57dce60c netfilter: ctnetl... |
721 722 |
if (ctnetlink_dump_status(skb, ct) < 0) goto nla_put_failure; |
a0891aa6a netfilter: conntr... |
723 |
if (events & (1 << IPCT_DESTROY)) { |
4542fa472 netfilter: ctnetl... |
724 |
if (ctnetlink_dump_acct(skb, ct, type) < 0 || |
a992ca2a0 netfilter: nf_con... |
725 |
ctnetlink_dump_timestamp(skb, ct) < 0) |
df6fb868d [NETFILTER]: nfne... |
726 |
goto nla_put_failure; |
7b621c1ea [NETFILTER]: ctne... |
727 |
} else { |
7b621c1ea [NETFILTER]: ctne... |
728 |
if (ctnetlink_dump_timeout(skb, ct) < 0) |
df6fb868d [NETFILTER]: nfne... |
729 |
goto nla_put_failure; |
7b621c1ea [NETFILTER]: ctne... |
730 |
|
a0891aa6a netfilter: conntr... |
731 |
if (events & (1 << IPCT_PROTOINFO) |
7b621c1ea [NETFILTER]: ctne... |
732 |
&& ctnetlink_dump_protoinfo(skb, ct) < 0) |
df6fb868d [NETFILTER]: nfne... |
733 |
goto nla_put_failure; |
7b621c1ea [NETFILTER]: ctne... |
734 |
|
a0891aa6a netfilter: conntr... |
735 |
if ((events & (1 << IPCT_HELPER) || nfct_help(ct)) |
7b621c1ea [NETFILTER]: ctne... |
736 |
&& ctnetlink_dump_helpinfo(skb, ct) < 0) |
df6fb868d [NETFILTER]: nfne... |
737 |
goto nla_put_failure; |
7b621c1ea [NETFILTER]: ctne... |
738 |
|
ff660c80d secmark: fix conf... |
739 |
#ifdef CONFIG_NF_CONNTRACK_SECMARK |
a0891aa6a netfilter: conntr... |
740 |
if ((events & (1 << IPCT_SECMARK) || ct->secmark) |
1cc63249a conntrack: export... |
741 |
&& ctnetlink_dump_secctx(skb, ct) < 0) |
37fccd857 [NETFILTER]: ctne... |
742 |
goto nla_put_failure; |
ff660c80d secmark: fix conf... |
743 |
#endif |
0ceabd838 netfilter: ctnetl... |
744 745 746 |
if (events & (1 << IPCT_LABEL) && ctnetlink_dump_labels(skb, ct) < 0) goto nla_put_failure; |
7b621c1ea [NETFILTER]: ctne... |
747 |
|
a0891aa6a netfilter: conntr... |
748 |
if (events & (1 << IPCT_RELATED) && |
0f417ce98 [NETFILTER]: ctne... |
749 750 |
ctnetlink_dump_master(skb, ct) < 0) goto nla_put_failure; |
41d73ec05 netfilter: nf_con... |
751 752 |
if (events & (1 << IPCT_SEQADJ) && ctnetlink_dump_ct_seq_adj(skb, ct) < 0) |
13eae15a2 [NETFILTER]: ctne... |
753 |
goto nla_put_failure; |
20710b3b8 netfilter: ctnetl... |
754 755 756 757 |
if (events & (1 << IPCT_SYNPROXY) && ctnetlink_dump_ct_synproxy(skb, ct) < 0) goto nla_put_failure; |
7b621c1ea [NETFILTER]: ctne... |
758 |
} |
b9a37e0c8 [NETFILTER]: ctne... |
759 |
|
a83099a60 [NETFILTER]: nf_c... |
760 |
#ifdef CONFIG_NF_CONNTRACK_MARK |
a0891aa6a netfilter: conntr... |
761 |
if ((events & (1 << IPCT_MARK) || ct->mark) |
a83099a60 [NETFILTER]: nf_c... |
762 763 764 |
&& ctnetlink_dump_mark(skb, ct) < 0) goto nla_put_failure; #endif |
96bcf938d netfilter: ctnetl... |
765 |
nlmsg_end(skb, nlh); |
15e473046 netlink: Rename p... |
766 |
err = nfnetlink_send(skb, net, item->portid, group, item->report, |
cd8c20b65 netfilter: nfnetl... |
767 |
GFP_ATOMIC); |
dd7669a92 netfilter: conntr... |
768 769 |
if (err == -ENOBUFS || err == -EAGAIN) return -ENOBUFS; |
e34d5c1a4 netfilter: conntr... |
770 |
return 0; |
c1d10adb4 [NETFILTER]: Add ... |
771 |
|
df6fb868d [NETFILTER]: nfne... |
772 |
nla_put_failure: |
96bcf938d netfilter: ctnetl... |
773 |
nlmsg_cancel(skb, nlh); |
528a3a6f6 netfilter: ctnetl... |
774 |
nlmsg_failure: |
c1d10adb4 [NETFILTER]: Add ... |
775 |
kfree_skb(skb); |
150ace0db netfilter: ctnetl... |
776 |
errout: |
37b7ef720 netfilter: ctnetl... |
777 778 |
if (nfnetlink_set_err(net, 0, group, -ENOBUFS) > 0) return -ENOBUFS; |
e34d5c1a4 netfilter: conntr... |
779 |
return 0; |
c1d10adb4 [NETFILTER]: Add ... |
780 781 782 783 784 |
} #endif /* CONFIG_NF_CONNTRACK_EVENTS */ static int ctnetlink_done(struct netlink_callback *cb) { |
89f2e2188 [NETFILTER]: ctne... |
785 786 |
if (cb->args[1]) nf_ct_put((struct nf_conn *)cb->args[1]); |
397304b52 netfilter: ctnetl... |
787 |
kfree(cb->data); |
c1d10adb4 [NETFILTER]: Add ... |
788 789 |
return 0; } |
866476f32 netfilter: conntr... |
790 |
struct ctnetlink_filter { |
59c08c69c netfilter: ctnetl... |
791 |
u8 family; |
cb8aa9a3a netfilter: ctnetl... |
792 793 794 795 796 797 798 |
u_int32_t orig_flags; u_int32_t reply_flags; struct nf_conntrack_tuple orig; struct nf_conntrack_tuple reply; struct nf_conntrack_zone zone; |
0f298a285 netfilter: ctnetl... |
799 800 801 802 803 |
struct { u_int32_t val; u_int32_t mask; } mark; }; |
cb8aa9a3a netfilter: ctnetl... |
804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 |
static const struct nla_policy cta_filter_nla_policy[CTA_FILTER_MAX + 1] = { [CTA_FILTER_ORIG_FLAGS] = { .type = NLA_U32 }, [CTA_FILTER_REPLY_FLAGS] = { .type = NLA_U32 }, }; static int ctnetlink_parse_filter(const struct nlattr *attr, struct ctnetlink_filter *filter) { struct nlattr *tb[CTA_FILTER_MAX + 1]; int ret = 0; ret = nla_parse_nested(tb, CTA_FILTER_MAX, attr, cta_filter_nla_policy, NULL); if (ret) return ret; if (tb[CTA_FILTER_ORIG_FLAGS]) { filter->orig_flags = nla_get_u32(tb[CTA_FILTER_ORIG_FLAGS]); if (filter->orig_flags & ~CTA_FILTER_F_ALL) return -EOPNOTSUPP; } if (tb[CTA_FILTER_REPLY_FLAGS]) { filter->reply_flags = nla_get_u32(tb[CTA_FILTER_REPLY_FLAGS]); if (filter->reply_flags & ~CTA_FILTER_F_ALL) return -EOPNOTSUPP; } return 0; } static int ctnetlink_parse_zone(const struct nlattr *attr, struct nf_conntrack_zone *zone); static int ctnetlink_parse_tuple_filter(const struct nlattr * const cda[], struct nf_conntrack_tuple *tuple, u32 type, u_int8_t l3num, struct nf_conntrack_zone *zone, u_int32_t flags); |
866476f32 netfilter: conntr... |
842 |
static struct ctnetlink_filter * |
59c08c69c netfilter: ctnetl... |
843 |
ctnetlink_alloc_filter(const struct nlattr * const cda[], u8 family) |
866476f32 netfilter: conntr... |
844 |
{ |
866476f32 netfilter: conntr... |
845 |
struct ctnetlink_filter *filter; |
cb8aa9a3a netfilter: ctnetl... |
846 |
int err; |
866476f32 netfilter: conntr... |
847 |
|
9306425b7 netfilter: ctnetl... |
848 |
#ifndef CONFIG_NF_CONNTRACK_MARK |
7c6b41216 netfilter: ctnetl... |
849 |
if (cda[CTA_MARK] || cda[CTA_MARK_MASK]) |
9306425b7 netfilter: ctnetl... |
850 851 |
return ERR_PTR(-EOPNOTSUPP); #endif |
866476f32 netfilter: conntr... |
852 853 854 |
filter = kzalloc(sizeof(*filter), GFP_KERNEL); if (filter == NULL) return ERR_PTR(-ENOMEM); |
59c08c69c netfilter: ctnetl... |
855 856 857 |
filter->family = family; #ifdef CONFIG_NF_CONNTRACK_MARK |
cb8aa9a3a netfilter: ctnetl... |
858 |
if (cda[CTA_MARK]) { |
9306425b7 netfilter: ctnetl... |
859 |
filter->mark.val = ntohl(nla_get_be32(cda[CTA_MARK])); |
6c0d95d12 netfilter: ctnetl... |
860 |
if (cda[CTA_MARK_MASK]) |
cb8aa9a3a netfilter: ctnetl... |
861 |
filter->mark.mask = ntohl(nla_get_be32(cda[CTA_MARK_MASK])); |
6c0d95d12 netfilter: ctnetl... |
862 |
else |
cb8aa9a3a netfilter: ctnetl... |
863 |
filter->mark.mask = 0xffffffff; |
cb8aa9a3a netfilter: ctnetl... |
864 |
} else if (cda[CTA_MARK_MASK]) { |
6c2d2176a netfilter: ctnetl... |
865 866 |
err = -EINVAL; goto err_filter; |
9306425b7 netfilter: ctnetl... |
867 |
} |
866476f32 netfilter: conntr... |
868 |
#endif |
cb8aa9a3a netfilter: ctnetl... |
869 870 871 872 873 |
if (!cda[CTA_FILTER]) return filter; err = ctnetlink_parse_zone(cda[CTA_ZONE], &filter->zone); if (err < 0) |
6c2d2176a netfilter: ctnetl... |
874 |
goto err_filter; |
cb8aa9a3a netfilter: ctnetl... |
875 876 877 |
err = ctnetlink_parse_filter(cda[CTA_FILTER], filter); if (err < 0) |
6c2d2176a netfilter: ctnetl... |
878 |
goto err_filter; |
cb8aa9a3a netfilter: ctnetl... |
879 880 |
if (filter->orig_flags) { |
6c2d2176a netfilter: ctnetl... |
881 882 883 884 |
if (!cda[CTA_TUPLE_ORIG]) { err = -EINVAL; goto err_filter; } |
cb8aa9a3a netfilter: ctnetl... |
885 886 887 888 889 890 891 |
err = ctnetlink_parse_tuple_filter(cda, &filter->orig, CTA_TUPLE_ORIG, filter->family, &filter->zone, filter->orig_flags); if (err < 0) |
6c2d2176a netfilter: ctnetl... |
892 |
goto err_filter; |
cb8aa9a3a netfilter: ctnetl... |
893 894 895 |
} if (filter->reply_flags) { |
6c2d2176a netfilter: ctnetl... |
896 897 898 899 |
if (!cda[CTA_TUPLE_REPLY]) { err = -EINVAL; goto err_filter; } |
cb8aa9a3a netfilter: ctnetl... |
900 901 902 903 904 905 |
err = ctnetlink_parse_tuple_filter(cda, &filter->reply, CTA_TUPLE_REPLY, filter->family, &filter->zone, filter->orig_flags); |
6c2d2176a netfilter: ctnetl... |
906 907 908 909 |
if (err < 0) { err = -EINVAL; goto err_filter; } |
cb8aa9a3a netfilter: ctnetl... |
910 |
} |
59c08c69c netfilter: ctnetl... |
911 |
return filter; |
6c2d2176a netfilter: ctnetl... |
912 913 914 915 916 |
err_filter: kfree(filter); return ERR_PTR(err); |
866476f32 netfilter: conntr... |
917 |
} |
cb8aa9a3a netfilter: ctnetl... |
918 919 920 921 |
static bool ctnetlink_needs_filter(u8 family, const struct nlattr * const *cda) { return family || cda[CTA_MARK] || cda[CTA_FILTER]; } |
3e673b23b netfilter: fix me... |
922 923 924 925 |
static int ctnetlink_start(struct netlink_callback *cb) { const struct nlattr * const *cda = cb->data; struct ctnetlink_filter *filter = NULL; |
59c08c69c netfilter: ctnetl... |
926 927 |
struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); u8 family = nfmsg->nfgen_family; |
3e673b23b netfilter: fix me... |
928 |
|
cb8aa9a3a netfilter: ctnetl... |
929 |
if (ctnetlink_needs_filter(family, cda)) { |
59c08c69c netfilter: ctnetl... |
930 |
filter = ctnetlink_alloc_filter(cda, family); |
3e673b23b netfilter: fix me... |
931 932 933 934 935 936 937 |
if (IS_ERR(filter)) return PTR_ERR(filter); } cb->data = filter; return 0; } |
cb8aa9a3a netfilter: ctnetl... |
938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 |
static int ctnetlink_filter_match_tuple(struct nf_conntrack_tuple *filter_tuple, struct nf_conntrack_tuple *ct_tuple, u_int32_t flags, int family) { switch (family) { case NFPROTO_IPV4: if ((flags & CTA_FILTER_FLAG(CTA_IP_SRC)) && filter_tuple->src.u3.ip != ct_tuple->src.u3.ip) return 0; if ((flags & CTA_FILTER_FLAG(CTA_IP_DST)) && filter_tuple->dst.u3.ip != ct_tuple->dst.u3.ip) return 0; break; case NFPROTO_IPV6: if ((flags & CTA_FILTER_FLAG(CTA_IP_SRC)) && !ipv6_addr_cmp(&filter_tuple->src.u3.in6, &ct_tuple->src.u3.in6)) return 0; if ((flags & CTA_FILTER_FLAG(CTA_IP_DST)) && !ipv6_addr_cmp(&filter_tuple->dst.u3.in6, &ct_tuple->dst.u3.in6)) return 0; break; } if ((flags & CTA_FILTER_FLAG(CTA_PROTO_NUM)) && filter_tuple->dst.protonum != ct_tuple->dst.protonum) return 0; switch (ct_tuple->dst.protonum) { case IPPROTO_TCP: case IPPROTO_UDP: if ((flags & CTA_FILTER_FLAG(CTA_PROTO_SRC_PORT)) && filter_tuple->src.u.tcp.port != ct_tuple->src.u.tcp.port) return 0; if ((flags & CTA_FILTER_FLAG(CTA_PROTO_DST_PORT)) && filter_tuple->dst.u.tcp.port != ct_tuple->dst.u.tcp.port) return 0; break; case IPPROTO_ICMP: if ((flags & CTA_FILTER_FLAG(CTA_PROTO_ICMP_TYPE)) && filter_tuple->dst.u.icmp.type != ct_tuple->dst.u.icmp.type) return 0; if ((flags & CTA_FILTER_FLAG(CTA_PROTO_ICMP_CODE)) && filter_tuple->dst.u.icmp.code != ct_tuple->dst.u.icmp.code) return 0; if ((flags & CTA_FILTER_FLAG(CTA_PROTO_ICMP_ID)) && filter_tuple->src.u.icmp.id != ct_tuple->src.u.icmp.id) return 0; break; case IPPROTO_ICMPV6: if ((flags & CTA_FILTER_FLAG(CTA_PROTO_ICMPV6_TYPE)) && filter_tuple->dst.u.icmp.type != ct_tuple->dst.u.icmp.type) return 0; if ((flags & CTA_FILTER_FLAG(CTA_PROTO_ICMPV6_CODE)) && filter_tuple->dst.u.icmp.code != ct_tuple->dst.u.icmp.code) return 0; if ((flags & CTA_FILTER_FLAG(CTA_PROTO_ICMPV6_ID)) && filter_tuple->src.u.icmp.id != ct_tuple->src.u.icmp.id) return 0; break; } return 1; } |
866476f32 netfilter: conntr... |
1006 1007 1008 |
static int ctnetlink_filter_match(struct nf_conn *ct, void *data) { struct ctnetlink_filter *filter = data; |
cb8aa9a3a netfilter: ctnetl... |
1009 |
struct nf_conntrack_tuple *tuple; |
866476f32 netfilter: conntr... |
1010 1011 |
if (filter == NULL) |
59c08c69c netfilter: ctnetl... |
1012 1013 1014 1015 1016 1017 1018 1019 |
goto out; /* Match entries of a given L3 protocol number. * If it is not specified, ie. l3proto == 0, * then match everything. */ if (filter->family && nf_ct_l3num(ct) != filter->family) goto ignore_entry; |
866476f32 netfilter: conntr... |
1020 |
|
cb8aa9a3a netfilter: ctnetl... |
1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 |
if (filter->orig_flags) { tuple = nf_ct_tuple(ct, IP_CT_DIR_ORIGINAL); if (!ctnetlink_filter_match_tuple(&filter->orig, tuple, filter->orig_flags, filter->family)) goto ignore_entry; } if (filter->reply_flags) { tuple = nf_ct_tuple(ct, IP_CT_DIR_REPLY); if (!ctnetlink_filter_match_tuple(&filter->reply, tuple, filter->reply_flags, filter->family)) goto ignore_entry; } |
866476f32 netfilter: conntr... |
1036 |
#ifdef CONFIG_NF_CONNTRACK_MARK |
6c0d95d12 netfilter: ctnetl... |
1037 |
if ((ct->mark & filter->mark.mask) != filter->mark.val) |
59c08c69c netfilter: ctnetl... |
1038 |
goto ignore_entry; |
866476f32 netfilter: conntr... |
1039 |
#endif |
59c08c69c netfilter: ctnetl... |
1040 1041 1042 1043 |
out: return 1; ignore_entry: |
866476f32 netfilter: conntr... |
1044 1045 |
return 0; } |
c1d10adb4 [NETFILTER]: Add ... |
1046 1047 1048 |
static int ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) { |
cb8aa9a3a netfilter: ctnetl... |
1049 |
unsigned int flags = cb->data ? NLM_F_DUMP_FILTERED : 0; |
9592a5c01 netfilter: ctnetl... |
1050 |
struct net *net = sock_net(skb->sk); |
89f2e2188 [NETFILTER]: ctne... |
1051 |
struct nf_conn *ct, *last; |
c1d10adb4 [NETFILTER]: Add ... |
1052 |
struct nf_conntrack_tuple_hash *h; |
ea781f197 netfilter: nf_con... |
1053 |
struct hlist_nulls_node *n; |
2344d64ec netfilter: evict ... |
1054 1055 |
struct nf_conn *nf_ct_evict[8]; int res, i; |
93bb0ceb7 netfilter: conntr... |
1056 |
spinlock_t *lockp; |
d205dc407 [NETFILTER]: ctne... |
1057 |
last = (struct nf_conn *)cb->args[1]; |
2344d64ec netfilter: evict ... |
1058 |
i = 0; |
93bb0ceb7 netfilter: conntr... |
1059 1060 |
local_bh_disable(); |
56d52d489 netfilter: conntr... |
1061 |
for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++) { |
89f2e2188 [NETFILTER]: ctne... |
1062 |
restart: |
2344d64ec netfilter: evict ... |
1063 1064 1065 1066 1067 1068 |
while (i) { i--; if (nf_ct_should_gc(nf_ct_evict[i])) nf_ct_kill(nf_ct_evict[i]); nf_ct_put(nf_ct_evict[i]); } |
93bb0ceb7 netfilter: conntr... |
1069 |
lockp = &nf_conntrack_locks[cb->args[0] % CONNTRACK_LOCKS]; |
b16c29191 netfilter: nf_con... |
1070 |
nf_conntrack_lock(lockp); |
56d52d489 netfilter: conntr... |
1071 |
if (cb->args[0] >= nf_conntrack_htable_size) { |
93bb0ceb7 netfilter: conntr... |
1072 1073 1074 |
spin_unlock(lockp); goto out; } |
56d52d489 netfilter: conntr... |
1075 1076 |
hlist_nulls_for_each_entry(h, n, &nf_conntrack_hash[cb->args[0]], hnnode) { |
5b1158e90 [NETFILTER]: Add ... |
1077 |
if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL) |
c1d10adb4 [NETFILTER]: Add ... |
1078 1079 |
continue; ct = nf_ct_tuplehash_to_ctrack(h); |
2344d64ec netfilter: evict ... |
1080 1081 1082 1083 1084 1085 |
if (nf_ct_is_expired(ct)) { if (i < ARRAY_SIZE(nf_ct_evict) && atomic_inc_not_zero(&ct->ct_general.use)) nf_ct_evict[i++] = ct; continue; } |
e0c7d4722 netfilter: conntr... |
1086 1087 |
if (!net_eq(net, nf_ct_net(ct))) continue; |
d205dc407 [NETFILTER]: ctne... |
1088 1089 |
if (cb->args[1]) { if (ct != last) |
13ee6ac57 netfilter: fix ra... |
1090 |
continue; |
d205dc407 [NETFILTER]: ctne... |
1091 |
cb->args[1] = 0; |
89f2e2188 [NETFILTER]: ctne... |
1092 |
} |
866476f32 netfilter: conntr... |
1093 |
if (!ctnetlink_filter_match(ct, cb->data)) |
0f298a285 netfilter: ctnetl... |
1094 |
continue; |
866476f32 netfilter: conntr... |
1095 |
|
3b988ece9 netfilter: ctnetl... |
1096 |
res = |
15e473046 netlink: Rename p... |
1097 |
ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).portid, |
3b988ece9 netfilter: ctnetl... |
1098 1099 |
cb->nlh->nlmsg_seq, NFNL_MSG_TYPE(cb->nlh->nlmsg_type), |
cb8aa9a3a netfilter: ctnetl... |
1100 |
ct, true, flags); |
3b988ece9 netfilter: ctnetl... |
1101 |
if (res < 0) { |
c71caf411 netfilter: ctnetl... |
1102 |
nf_conntrack_get(&ct->ct_general); |
89f2e2188 [NETFILTER]: ctne... |
1103 |
cb->args[1] = (unsigned long)ct; |
93bb0ceb7 netfilter: conntr... |
1104 |
spin_unlock(lockp); |
c1d10adb4 [NETFILTER]: Add ... |
1105 |
goto out; |
89f2e2188 [NETFILTER]: ctne... |
1106 1107 |
} } |
93bb0ceb7 netfilter: conntr... |
1108 |
spin_unlock(lockp); |
d205dc407 [NETFILTER]: ctne... |
1109 |
if (cb->args[1]) { |
89f2e2188 [NETFILTER]: ctne... |
1110 1111 |
cb->args[1] = 0; goto restart; |
c1d10adb4 [NETFILTER]: Add ... |
1112 1113 |
} } |
89f2e2188 [NETFILTER]: ctne... |
1114 |
out: |
93bb0ceb7 netfilter: conntr... |
1115 |
local_bh_enable(); |
fefa92679 netfilter: ctnetl... |
1116 1117 1118 1119 |
if (last) { /* nf ct hash resize happened, now clear the leftover. */ if ((struct nf_conn *)cb->args[1] == last) cb->args[1] = 0; |
d205dc407 [NETFILTER]: ctne... |
1120 |
nf_ct_put(last); |
fefa92679 netfilter: ctnetl... |
1121 |
} |
c1d10adb4 [NETFILTER]: Add ... |
1122 |
|
2344d64ec netfilter: evict ... |
1123 1124 1125 1126 1127 1128 |
while (i) { i--; if (nf_ct_should_gc(nf_ct_evict[i])) nf_ct_kill(nf_ct_evict[i]); nf_ct_put(nf_ct_evict[i]); } |
c1d10adb4 [NETFILTER]: Add ... |
1129 1130 |
return skb->len; } |
f957be9d3 netfilter: conntr... |
1131 |
static int ipv4_nlattr_to_tuple(struct nlattr *tb[], |
cb8aa9a3a netfilter: ctnetl... |
1132 1133 |
struct nf_conntrack_tuple *t, u_int32_t flags) |
f957be9d3 netfilter: conntr... |
1134 |
{ |
cb8aa9a3a netfilter: ctnetl... |
1135 1136 1137 1138 1139 1140 |
if (flags & CTA_FILTER_FLAG(CTA_IP_SRC)) { if (!tb[CTA_IP_V4_SRC]) return -EINVAL; t->src.u3.ip = nla_get_in_addr(tb[CTA_IP_V4_SRC]); } |
f957be9d3 netfilter: conntr... |
1141 |
|
cb8aa9a3a netfilter: ctnetl... |
1142 1143 1144 1145 1146 1147 |
if (flags & CTA_FILTER_FLAG(CTA_IP_DST)) { if (!tb[CTA_IP_V4_DST]) return -EINVAL; t->dst.u3.ip = nla_get_in_addr(tb[CTA_IP_V4_DST]); } |
f957be9d3 netfilter: conntr... |
1148 1149 1150 1151 1152 |
return 0; } static int ipv6_nlattr_to_tuple(struct nlattr *tb[], |
cb8aa9a3a netfilter: ctnetl... |
1153 1154 |
struct nf_conntrack_tuple *t, u_int32_t flags) |
f957be9d3 netfilter: conntr... |
1155 |
{ |
cb8aa9a3a netfilter: ctnetl... |
1156 1157 1158 1159 1160 1161 |
if (flags & CTA_FILTER_FLAG(CTA_IP_SRC)) { if (!tb[CTA_IP_V6_SRC]) return -EINVAL; t->src.u3.in6 = nla_get_in6_addr(tb[CTA_IP_V6_SRC]); } |
f957be9d3 netfilter: conntr... |
1162 |
|
cb8aa9a3a netfilter: ctnetl... |
1163 1164 1165 1166 1167 1168 |
if (flags & CTA_FILTER_FLAG(CTA_IP_DST)) { if (!tb[CTA_IP_V6_DST]) return -EINVAL; t->dst.u3.in6 = nla_get_in6_addr(tb[CTA_IP_V6_DST]); } |
f957be9d3 netfilter: conntr... |
1169 1170 1171 |
return 0; } |
4054ff454 netfilter: ctnetl... |
1172 |
static int ctnetlink_parse_tuple_ip(struct nlattr *attr, |
cb8aa9a3a netfilter: ctnetl... |
1173 1174 |
struct nf_conntrack_tuple *tuple, u_int32_t flags) |
c1d10adb4 [NETFILTER]: Add ... |
1175 |
{ |
df6fb868d [NETFILTER]: nfne... |
1176 |
struct nlattr *tb[CTA_IP_MAX+1]; |
c1d10adb4 [NETFILTER]: Add ... |
1177 |
int ret = 0; |
8cb081746 netlink: make val... |
1178 |
ret = nla_parse_nested_deprecated(tb, CTA_IP_MAX, attr, NULL, NULL); |
130ffbc26 netfilter: check ... |
1179 1180 |
if (ret < 0) return ret; |
c1d10adb4 [NETFILTER]: Add ... |
1181 |
|
8cb081746 netlink: make val... |
1182 1183 |
ret = nla_validate_nested_deprecated(attr, CTA_IP_MAX, cta_ip_nla_policy, NULL); |
f957be9d3 netfilter: conntr... |
1184 1185 |
if (ret) return ret; |
c1d10adb4 [NETFILTER]: Add ... |
1186 |
|
f957be9d3 netfilter: conntr... |
1187 1188 |
switch (tuple->src.l3num) { case NFPROTO_IPV4: |
cb8aa9a3a netfilter: ctnetl... |
1189 |
ret = ipv4_nlattr_to_tuple(tb, tuple, flags); |
f957be9d3 netfilter: conntr... |
1190 1191 |
break; case NFPROTO_IPV6: |
cb8aa9a3a netfilter: ctnetl... |
1192 |
ret = ipv6_nlattr_to_tuple(tb, tuple, flags); |
f957be9d3 netfilter: conntr... |
1193 |
break; |
f73e924cd [NETFILTER]: ctne... |
1194 |
} |
c1d10adb4 [NETFILTER]: Add ... |
1195 |
|
c1d10adb4 [NETFILTER]: Add ... |
1196 1197 |
return ret; } |
f73e924cd [NETFILTER]: ctne... |
1198 1199 |
static const struct nla_policy proto_nla_policy[CTA_PROTO_MAX+1] = { [CTA_PROTO_NUM] = { .type = NLA_U8 }, |
c1d10adb4 [NETFILTER]: Add ... |
1200 |
}; |
4054ff454 netfilter: ctnetl... |
1201 |
static int ctnetlink_parse_tuple_proto(struct nlattr *attr, |
cb8aa9a3a netfilter: ctnetl... |
1202 1203 |
struct nf_conntrack_tuple *tuple, u_int32_t flags) |
c1d10adb4 [NETFILTER]: Add ... |
1204 |
{ |
b3480fe05 netfilter: conntr... |
1205 |
const struct nf_conntrack_l4proto *l4proto; |
df6fb868d [NETFILTER]: nfne... |
1206 |
struct nlattr *tb[CTA_PROTO_MAX+1]; |
c1d10adb4 [NETFILTER]: Add ... |
1207 |
int ret = 0; |
8cb081746 netlink: make val... |
1208 1209 |
ret = nla_parse_nested_deprecated(tb, CTA_PROTO_MAX, attr, proto_nla_policy, NULL); |
f73e924cd [NETFILTER]: ctne... |
1210 1211 |
if (ret < 0) return ret; |
c1d10adb4 [NETFILTER]: Add ... |
1212 |
|
cb8aa9a3a netfilter: ctnetl... |
1213 1214 |
if (!(flags & CTA_FILTER_FLAG(CTA_PROTO_NUM))) return 0; |
df6fb868d [NETFILTER]: nfne... |
1215 |
if (!tb[CTA_PROTO_NUM]) |
c1d10adb4 [NETFILTER]: Add ... |
1216 |
return -EINVAL; |
cb8aa9a3a netfilter: ctnetl... |
1217 |
|
77236b6e3 [NETFILTER]: ctne... |
1218 |
tuple->dst.protonum = nla_get_u8(tb[CTA_PROTO_NUM]); |
c1d10adb4 [NETFILTER]: Add ... |
1219 |
|
cd91566e4 netfilter: ctnetl... |
1220 |
rcu_read_lock(); |
4a60dc748 netfilter: conntr... |
1221 |
l4proto = nf_ct_l4proto_find(tuple->dst.protonum); |
c1d10adb4 [NETFILTER]: Add ... |
1222 |
|
f73e924cd [NETFILTER]: ctne... |
1223 |
if (likely(l4proto->nlattr_to_tuple)) { |
8cb081746 netlink: make val... |
1224 1225 1226 |
ret = nla_validate_nested_deprecated(attr, CTA_PROTO_MAX, l4proto->nla_policy, NULL); |
f73e924cd [NETFILTER]: ctne... |
1227 |
if (ret == 0) |
cb8aa9a3a netfilter: ctnetl... |
1228 |
ret = l4proto->nlattr_to_tuple(tb, tuple, flags); |
f73e924cd [NETFILTER]: ctne... |
1229 |
} |
c1d10adb4 [NETFILTER]: Add ... |
1230 |
|
cd91566e4 netfilter: ctnetl... |
1231 |
rcu_read_unlock(); |
601e68e10 [NETFILTER]: Fix ... |
1232 |
|
c1d10adb4 [NETFILTER]: Add ... |
1233 1234 |
return ret; } |
deedb5903 netfilter: nf_con... |
1235 1236 1237 1238 |
static int ctnetlink_parse_zone(const struct nlattr *attr, struct nf_conntrack_zone *zone) { |
5e8018fc6 netfilter: nf_con... |
1239 1240 |
nf_ct_zone_init(zone, NF_CT_DEFAULT_ZONE_ID, NF_CT_DEFAULT_ZONE_DIR, 0); |
deedb5903 netfilter: nf_con... |
1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 |
#ifdef CONFIG_NF_CONNTRACK_ZONES if (attr) zone->id = ntohs(nla_get_be16(attr)); #else if (attr) return -EOPNOTSUPP; #endif return 0; } static int ctnetlink_parse_tuple_zone(struct nlattr *attr, enum ctattr_type type, struct nf_conntrack_zone *zone) { int ret; if (zone->id != NF_CT_DEFAULT_ZONE_ID) return -EINVAL; ret = ctnetlink_parse_zone(attr, zone); if (ret < 0) return ret; if (type == CTA_TUPLE_REPLY) zone->dir = NF_CT_ZONE_DIR_REPL; else zone->dir = NF_CT_ZONE_DIR_ORIG; return 0; } |
d0b0268fd netfilter: ctnetl... |
1271 1272 1273 |
static const struct nla_policy tuple_nla_policy[CTA_TUPLE_MAX+1] = { [CTA_TUPLE_IP] = { .type = NLA_NESTED }, [CTA_TUPLE_PROTO] = { .type = NLA_NESTED }, |
deedb5903 netfilter: nf_con... |
1274 |
[CTA_TUPLE_ZONE] = { .type = NLA_U16 }, |
d0b0268fd netfilter: ctnetl... |
1275 |
}; |
cb8aa9a3a netfilter: ctnetl... |
1276 1277 1278 1279 1280 1281 1282 1283 1284 |
#define CTA_FILTER_F_ALL_CTA_PROTO \ (CTA_FILTER_F_CTA_PROTO_SRC_PORT | \ CTA_FILTER_F_CTA_PROTO_DST_PORT | \ CTA_FILTER_F_CTA_PROTO_ICMP_TYPE | \ CTA_FILTER_F_CTA_PROTO_ICMP_CODE | \ CTA_FILTER_F_CTA_PROTO_ICMP_ID | \ CTA_FILTER_F_CTA_PROTO_ICMPV6_TYPE | \ CTA_FILTER_F_CTA_PROTO_ICMPV6_CODE | \ CTA_FILTER_F_CTA_PROTO_ICMPV6_ID) |
bb5cf80e9 [NETFILTER]: Kill... |
1285 |
static int |
cb8aa9a3a netfilter: ctnetl... |
1286 1287 1288 1289 |
ctnetlink_parse_tuple_filter(const struct nlattr * const cda[], struct nf_conntrack_tuple *tuple, u32 type, u_int8_t l3num, struct nf_conntrack_zone *zone, u_int32_t flags) |
c1d10adb4 [NETFILTER]: Add ... |
1290 |
{ |
df6fb868d [NETFILTER]: nfne... |
1291 |
struct nlattr *tb[CTA_TUPLE_MAX+1]; |
c1d10adb4 [NETFILTER]: Add ... |
1292 |
int err; |
c1d10adb4 [NETFILTER]: Add ... |
1293 |
memset(tuple, 0, sizeof(*tuple)); |
8cb081746 netlink: make val... |
1294 1295 |
err = nla_parse_nested_deprecated(tb, CTA_TUPLE_MAX, cda[type], tuple_nla_policy, NULL); |
130ffbc26 netfilter: check ... |
1296 1297 |
if (err < 0) return err; |
c1d10adb4 [NETFILTER]: Add ... |
1298 |
|
1cc5ef91d netfilter: ctnetl... |
1299 1300 |
if (l3num != NFPROTO_IPV4 && l3num != NFPROTO_IPV6) return -EOPNOTSUPP; |
c1d10adb4 [NETFILTER]: Add ... |
1301 |
tuple->src.l3num = l3num; |
cb8aa9a3a netfilter: ctnetl... |
1302 1303 1304 1305 |
if (flags & CTA_FILTER_FLAG(CTA_IP_DST) || flags & CTA_FILTER_FLAG(CTA_IP_SRC)) { if (!tb[CTA_TUPLE_IP]) return -EINVAL; |
c1d10adb4 [NETFILTER]: Add ... |
1306 |
|
cb8aa9a3a netfilter: ctnetl... |
1307 1308 1309 1310 |
err = ctnetlink_parse_tuple_ip(tb[CTA_TUPLE_IP], tuple, flags); if (err < 0) return err; } |
c1d10adb4 [NETFILTER]: Add ... |
1311 |
|
cb8aa9a3a netfilter: ctnetl... |
1312 1313 1314 |
if (flags & CTA_FILTER_FLAG(CTA_PROTO_NUM)) { if (!tb[CTA_TUPLE_PROTO]) return -EINVAL; |
c1d10adb4 [NETFILTER]: Add ... |
1315 |
|
cb8aa9a3a netfilter: ctnetl... |
1316 1317 1318 1319 1320 1321 1322 1323 1324 |
err = ctnetlink_parse_tuple_proto(tb[CTA_TUPLE_PROTO], tuple, flags); if (err < 0) return err; } else if (flags & CTA_FILTER_FLAG(ALL_CTA_PROTO)) { /* Can't manage proto flags without a protonum */ return -EINVAL; } if ((flags & CTA_FILTER_FLAG(CTA_TUPLE_ZONE)) && tb[CTA_TUPLE_ZONE]) { |
deedb5903 netfilter: nf_con... |
1325 1326 1327 1328 1329 1330 1331 1332 |
if (!zone) return -EINVAL; err = ctnetlink_parse_tuple_zone(tb[CTA_TUPLE_ZONE], type, zone); if (err < 0) return err; } |
c1d10adb4 [NETFILTER]: Add ... |
1333 1334 1335 1336 1337 |
/* orig and expect tuples get DIR_ORIGINAL */ if (type == CTA_TUPLE_REPLY) tuple->dst.dir = IP_CT_DIR_REPLY; else tuple->dst.dir = IP_CT_DIR_ORIGINAL; |
c1d10adb4 [NETFILTER]: Add ... |
1338 1339 |
return 0; } |
cb8aa9a3a netfilter: ctnetl... |
1340 1341 1342 1343 1344 1345 1346 1347 |
static int ctnetlink_parse_tuple(const struct nlattr * const cda[], struct nf_conntrack_tuple *tuple, u32 type, u_int8_t l3num, struct nf_conntrack_zone *zone) { return ctnetlink_parse_tuple_filter(cda, tuple, type, l3num, zone, CTA_FILTER_FLAG(ALL)); } |
d0b0268fd netfilter: ctnetl... |
1348 |
static const struct nla_policy help_nla_policy[CTA_HELP_MAX+1] = { |
6d1fafcae netfilter: ctnetl... |
1349 1350 |
[CTA_HELP_NAME] = { .type = NLA_NUL_STRING, .len = NF_CT_HELPER_NAME_LEN - 1 }, |
d0b0268fd netfilter: ctnetl... |
1351 |
}; |
4054ff454 netfilter: ctnetl... |
1352 1353 |
static int ctnetlink_parse_help(const struct nlattr *attr, char **helper_name, struct nlattr **helpinfo) |
c1d10adb4 [NETFILTER]: Add ... |
1354 |
{ |
130ffbc26 netfilter: check ... |
1355 |
int err; |
df6fb868d [NETFILTER]: nfne... |
1356 |
struct nlattr *tb[CTA_HELP_MAX+1]; |
c1d10adb4 [NETFILTER]: Add ... |
1357 |
|
8cb081746 netlink: make val... |
1358 1359 |
err = nla_parse_nested_deprecated(tb, CTA_HELP_MAX, attr, help_nla_policy, NULL); |
130ffbc26 netfilter: check ... |
1360 1361 |
if (err < 0) return err; |
c1d10adb4 [NETFILTER]: Add ... |
1362 |
|
df6fb868d [NETFILTER]: nfne... |
1363 |
if (!tb[CTA_HELP_NAME]) |
c1d10adb4 [NETFILTER]: Add ... |
1364 |
return -EINVAL; |
df6fb868d [NETFILTER]: nfne... |
1365 |
*helper_name = nla_data(tb[CTA_HELP_NAME]); |
c1d10adb4 [NETFILTER]: Add ... |
1366 |
|
ae243bee3 netfilter: ctnetl... |
1367 1368 |
if (tb[CTA_HELP_INFO]) *helpinfo = tb[CTA_HELP_INFO]; |
c1d10adb4 [NETFILTER]: Add ... |
1369 1370 |
return 0; } |
f73e924cd [NETFILTER]: ctne... |
1371 |
static const struct nla_policy ct_nla_policy[CTA_MAX+1] = { |
d0b0268fd netfilter: ctnetl... |
1372 1373 |
[CTA_TUPLE_ORIG] = { .type = NLA_NESTED }, [CTA_TUPLE_REPLY] = { .type = NLA_NESTED }, |
f73e924cd [NETFILTER]: ctne... |
1374 |
[CTA_STATUS] = { .type = NLA_U32 }, |
d0b0268fd netfilter: ctnetl... |
1375 1376 1377 |
[CTA_PROTOINFO] = { .type = NLA_NESTED }, [CTA_HELP] = { .type = NLA_NESTED }, [CTA_NAT_SRC] = { .type = NLA_NESTED }, |
f73e924cd [NETFILTER]: ctne... |
1378 1379 |
[CTA_TIMEOUT] = { .type = NLA_U32 }, [CTA_MARK] = { .type = NLA_U32 }, |
f73e924cd [NETFILTER]: ctne... |
1380 |
[CTA_ID] = { .type = NLA_U32 }, |
d0b0268fd netfilter: ctnetl... |
1381 1382 |
[CTA_NAT_DST] = { .type = NLA_NESTED }, [CTA_TUPLE_MASTER] = { .type = NLA_NESTED }, |
6d1fafcae netfilter: ctnetl... |
1383 1384 |
[CTA_NAT_SEQ_ADJ_ORIG] = { .type = NLA_NESTED }, [CTA_NAT_SEQ_ADJ_REPLY] = { .type = NLA_NESTED }, |
ef00f89f1 netfilter: ctnetl... |
1385 |
[CTA_ZONE] = { .type = NLA_U16 }, |
0f298a285 netfilter: ctnetl... |
1386 |
[CTA_MARK_MASK] = { .type = NLA_U32 }, |
9b21f6a90 netfilter: ctnetl... |
1387 |
[CTA_LABELS] = { .type = NLA_BINARY, |
d2bf2f34c netfilter: nft_ct... |
1388 |
.len = NF_CT_LABELS_MAX_SIZE }, |
9b21f6a90 netfilter: ctnetl... |
1389 |
[CTA_LABELS_MASK] = { .type = NLA_BINARY, |
d2bf2f34c netfilter: nft_ct... |
1390 |
.len = NF_CT_LABELS_MAX_SIZE }, |
cb8aa9a3a netfilter: ctnetl... |
1391 |
[CTA_FILTER] = { .type = NLA_NESTED }, |
c1d10adb4 [NETFILTER]: Add ... |
1392 |
}; |
90964016e netfilter: nf_con... |
1393 1394 1395 1396 1397 1398 1399 |
static int ctnetlink_flush_iterate(struct nf_conn *ct, void *data) { if (test_bit(IPS_OFFLOAD_BIT, &ct->status)) return 0; return ctnetlink_filter_match(ct, data); } |
866476f32 netfilter: conntr... |
1400 1401 |
static int ctnetlink_flush_conntrack(struct net *net, const struct nlattr * const cda[], |
59c08c69c netfilter: ctnetl... |
1402 |
u32 portid, int report, u8 family) |
866476f32 netfilter: conntr... |
1403 1404 |
{ struct ctnetlink_filter *filter = NULL; |
cb8aa9a3a netfilter: ctnetl... |
1405 1406 1407 |
if (ctnetlink_needs_filter(family, cda)) { if (cda[CTA_FILTER]) return -EOPNOTSUPP; |
59c08c69c netfilter: ctnetl... |
1408 |
filter = ctnetlink_alloc_filter(cda, family); |
866476f32 netfilter: conntr... |
1409 1410 1411 |
if (IS_ERR(filter)) return PTR_ERR(filter); } |
90964016e netfilter: nf_con... |
1412 |
nf_ct_iterate_cleanup_net(net, ctnetlink_flush_iterate, filter, |
9fd6452d6 netfilter: conntr... |
1413 |
portid, report); |
866476f32 netfilter: conntr... |
1414 1415 1416 1417 |
kfree(filter); return 0; } |
7b8002a15 netfilter: nfnetl... |
1418 1419 1420 |
static int ctnetlink_del_conntrack(struct net *net, struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, |
04ba724b6 netfilter: nfnetl... |
1421 1422 |
const struct nlattr * const cda[], struct netlink_ext_ack *extack) |
c1d10adb4 [NETFILTER]: Add ... |
1423 1424 1425 1426 |
{ struct nf_conntrack_tuple_hash *h; struct nf_conntrack_tuple tuple; struct nf_conn *ct; |
96bcf938d netfilter: ctnetl... |
1427 |
struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
308ac9143 netfilter: nf_con... |
1428 |
struct nf_conntrack_zone zone; |
ef00f89f1 netfilter: ctnetl... |
1429 1430 1431 1432 1433 |
int err; err = ctnetlink_parse_zone(cda[CTA_ZONE], &zone); if (err < 0) return err; |
c1d10adb4 [NETFILTER]: Add ... |
1434 |
|
df6fb868d [NETFILTER]: nfne... |
1435 |
if (cda[CTA_TUPLE_ORIG]) |
deedb5903 netfilter: nf_con... |
1436 |
err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG, |
e7600865d netfilter: ctnetl... |
1437 |
nfmsg->nfgen_family, &zone); |
df6fb868d [NETFILTER]: nfne... |
1438 |
else if (cda[CTA_TUPLE_REPLY]) |
deedb5903 netfilter: nf_con... |
1439 |
err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY, |
e7600865d netfilter: ctnetl... |
1440 |
nfmsg->nfgen_family, &zone); |
c1d10adb4 [NETFILTER]: Add ... |
1441 |
else { |
e7600865d netfilter: ctnetl... |
1442 |
u_int8_t u3 = nfmsg->version ? nfmsg->nfgen_family : AF_UNSPEC; |
866476f32 netfilter: conntr... |
1443 1444 |
return ctnetlink_flush_conntrack(net, cda, NETLINK_CB(skb).portid, |
59c08c69c netfilter: ctnetl... |
1445 |
nlmsg_report(nlh), u3); |
c1d10adb4 [NETFILTER]: Add ... |
1446 1447 1448 1449 |
} if (err < 0) return err; |
308ac9143 netfilter: nf_con... |
1450 |
h = nf_conntrack_find_get(net, &zone, &tuple); |
9ea8cfd6a [NETFILTER]: ctne... |
1451 |
if (!h) |
c1d10adb4 [NETFILTER]: Add ... |
1452 |
return -ENOENT; |
c1d10adb4 [NETFILTER]: Add ... |
1453 1454 |
ct = nf_ct_tuplehash_to_ctrack(h); |
601e68e10 [NETFILTER]: Fix ... |
1455 |
|
90964016e netfilter: nf_con... |
1456 1457 1458 1459 |
if (test_bit(IPS_OFFLOAD_BIT, &ct->status)) { nf_ct_put(ct); return -EBUSY; } |
df6fb868d [NETFILTER]: nfne... |
1460 |
if (cda[CTA_ID]) { |
3c7910763 netfilter: ctnetl... |
1461 1462 1463 |
__be32 id = nla_get_be32(cda[CTA_ID]); if (id != (__force __be32)nf_ct_get_id(ct)) { |
c1d10adb4 [NETFILTER]: Add ... |
1464 1465 1466 |
nf_ct_put(ct); return -ENOENT; } |
601e68e10 [NETFILTER]: Fix ... |
1467 |
} |
c1d10adb4 [NETFILTER]: Add ... |
1468 |
|
f330a7fdb netfilter: conntr... |
1469 |
nf_ct_delete(ct, NETLINK_CB(skb).portid, nlmsg_report(nlh)); |
c1d10adb4 [NETFILTER]: Add ... |
1470 |
nf_ct_put(ct); |
c1d10adb4 [NETFILTER]: Add ... |
1471 1472 1473 |
return 0; } |
7b8002a15 netfilter: nfnetl... |
1474 1475 1476 |
static int ctnetlink_get_conntrack(struct net *net, struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, |
04ba724b6 netfilter: nfnetl... |
1477 1478 |
const struct nlattr * const cda[], struct netlink_ext_ack *extack) |
c1d10adb4 [NETFILTER]: Add ... |
1479 1480 1481 1482 1483 |
{ struct nf_conntrack_tuple_hash *h; struct nf_conntrack_tuple tuple; struct nf_conn *ct; struct sk_buff *skb2 = NULL; |
96bcf938d netfilter: ctnetl... |
1484 |
struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
c1d10adb4 [NETFILTER]: Add ... |
1485 |
u_int8_t u3 = nfmsg->nfgen_family; |
308ac9143 netfilter: nf_con... |
1486 |
struct nf_conntrack_zone zone; |
ef00f89f1 netfilter: ctnetl... |
1487 |
int err; |
c1d10adb4 [NETFILTER]: Add ... |
1488 |
|
80d326fab netlink: add netl... |
1489 1490 |
if (nlh->nlmsg_flags & NLM_F_DUMP) { struct netlink_dump_control c = { |
3e673b23b netfilter: fix me... |
1491 |
.start = ctnetlink_start, |
80d326fab netlink: add netl... |
1492 1493 |
.dump = ctnetlink_dump_table, .done = ctnetlink_done, |
3e673b23b netfilter: fix me... |
1494 |
.data = (void *)cda, |
80d326fab netlink: add netl... |
1495 |
}; |
866476f32 netfilter: conntr... |
1496 |
|
80d326fab netlink: add netl... |
1497 1498 |
return netlink_dump_start(ctnl, skb, nlh, &c); } |
c1d10adb4 [NETFILTER]: Add ... |
1499 |
|
ef00f89f1 netfilter: ctnetl... |
1500 1501 1502 |
err = ctnetlink_parse_zone(cda[CTA_ZONE], &zone); if (err < 0) return err; |
df6fb868d [NETFILTER]: nfne... |
1503 |
if (cda[CTA_TUPLE_ORIG]) |
deedb5903 netfilter: nf_con... |
1504 1505 |
err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG, u3, &zone); |
df6fb868d [NETFILTER]: nfne... |
1506 |
else if (cda[CTA_TUPLE_REPLY]) |
deedb5903 netfilter: nf_con... |
1507 1508 |
err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY, u3, &zone); |
c1d10adb4 [NETFILTER]: Add ... |
1509 1510 1511 1512 1513 |
else return -EINVAL; if (err < 0) return err; |
308ac9143 netfilter: nf_con... |
1514 |
h = nf_conntrack_find_get(net, &zone, &tuple); |
9ea8cfd6a [NETFILTER]: ctne... |
1515 |
if (!h) |
c1d10adb4 [NETFILTER]: Add ... |
1516 |
return -ENOENT; |
9ea8cfd6a [NETFILTER]: ctne... |
1517 |
|
c1d10adb4 [NETFILTER]: Add ... |
1518 1519 1520 |
ct = nf_ct_tuplehash_to_ctrack(h); err = -ENOMEM; |
96bcf938d netfilter: ctnetl... |
1521 1522 |
skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (skb2 == NULL) { |
c1d10adb4 [NETFILTER]: Add ... |
1523 1524 1525 |
nf_ct_put(ct); return -ENOMEM; } |
c1d10adb4 [NETFILTER]: Add ... |
1526 |
|
15e473046 netlink: Rename p... |
1527 |
err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).portid, nlh->nlmsg_seq, |
cb8aa9a3a netfilter: ctnetl... |
1528 |
NFNL_MSG_TYPE(nlh->nlmsg_type), ct, true, 0); |
c1d10adb4 [NETFILTER]: Add ... |
1529 1530 1531 |
nf_ct_put(ct); if (err <= 0) goto free; |
15e473046 netlink: Rename p... |
1532 |
err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT); |
c1d10adb4 [NETFILTER]: Add ... |
1533 1534 |
if (err < 0) goto out; |
c1d10adb4 [NETFILTER]: Add ... |
1535 1536 1537 1538 1539 |
return 0; free: kfree_skb(skb2); out: |
f31e8d498 netfilter: ctnetl... |
1540 1541 |
/* this avoids a loop in nfnetlink. */ return err == -EAGAIN ? -ENOBUFS : err; |
c1d10adb4 [NETFILTER]: Add ... |
1542 |
} |
d871befe3 netfilter: ctnetl... |
1543 1544 1545 1546 1547 1548 1549 1550 |
static int ctnetlink_done_list(struct netlink_callback *cb) { if (cb->args[1]) nf_ct_put((struct nf_conn *)cb->args[1]); return 0; } static int |
b7779d06f netfilter: conntr... |
1551 |
ctnetlink_dump_list(struct sk_buff *skb, struct netlink_callback *cb, bool dying) |
d871befe3 netfilter: ctnetl... |
1552 |
{ |
cd5f336f1 netfilter: ctnetl... |
1553 |
struct nf_conn *ct, *last; |
d871befe3 netfilter: ctnetl... |
1554 1555 1556 1557 1558 |
struct nf_conntrack_tuple_hash *h; struct hlist_nulls_node *n; struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); u_int8_t l3proto = nfmsg->nfgen_family; int res; |
b7779d06f netfilter: conntr... |
1559 1560 1561 |
int cpu; struct hlist_nulls_head *list; struct net *net = sock_net(skb->sk); |
d871befe3 netfilter: ctnetl... |
1562 1563 1564 |
if (cb->args[2]) return 0; |
cd5f336f1 netfilter: ctnetl... |
1565 |
last = (struct nf_conn *)cb->args[1]; |
b7779d06f netfilter: conntr... |
1566 1567 1568 1569 |
for (cpu = cb->args[0]; cpu < nr_cpu_ids; cpu++) { struct ct_pcpu *pcpu; if (!cpu_possible(cpu)) |
d871befe3 netfilter: ctnetl... |
1570 |
continue; |
b7779d06f netfilter: conntr... |
1571 1572 1573 |
pcpu = per_cpu_ptr(net->ct.pcpu_lists, cpu); spin_lock_bh(&pcpu->lock); |
b7779d06f netfilter: conntr... |
1574 1575 1576 1577 1578 |
list = dying ? &pcpu->dying : &pcpu->unconfirmed; restart: hlist_nulls_for_each_entry(h, n, list, hnnode) { ct = nf_ct_tuplehash_to_ctrack(h); if (l3proto && nf_ct_l3num(ct) != l3proto) |
d871befe3 netfilter: ctnetl... |
1579 |
continue; |
b7779d06f netfilter: conntr... |
1580 1581 1582 1583 1584 |
if (cb->args[1]) { if (ct != last) continue; cb->args[1] = 0; } |
49ca022bc netfilter: ctnetl... |
1585 1586 1587 1588 1589 1590 1591 1592 |
/* We can't dump extension info for the unconfirmed * list because unconfirmed conntracks can have * ct->ext reallocated (and thus freed). * * In the dying list case ct->ext can't be free'd * until after we drop pcpu->lock. */ |
b7779d06f netfilter: conntr... |
1593 1594 1595 |
res = ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, NFNL_MSG_TYPE(cb->nlh->nlmsg_type), |
cb8aa9a3a netfilter: ctnetl... |
1596 |
ct, dying ? true : false, 0); |
b7779d06f netfilter: conntr... |
1597 |
if (res < 0) { |
cd5f336f1 netfilter: ctnetl... |
1598 1599 |
if (!atomic_inc_not_zero(&ct->ct_general.use)) continue; |
266155b2d netfilter: ctnetl... |
1600 |
cb->args[0] = cpu; |
b7779d06f netfilter: conntr... |
1601 1602 1603 1604 |
cb->args[1] = (unsigned long)ct; spin_unlock_bh(&pcpu->lock); goto out; } |
d871befe3 netfilter: ctnetl... |
1605 |
} |
b7779d06f netfilter: conntr... |
1606 1607 1608 |
if (cb->args[1]) { cb->args[1] = 0; goto restart; |
266155b2d netfilter: ctnetl... |
1609 |
} |
b7779d06f netfilter: conntr... |
1610 |
spin_unlock_bh(&pcpu->lock); |
d871befe3 netfilter: ctnetl... |
1611 |
} |
266155b2d netfilter: ctnetl... |
1612 |
cb->args[2] = 1; |
d871befe3 netfilter: ctnetl... |
1613 |
out: |
d871befe3 netfilter: ctnetl... |
1614 1615 1616 1617 1618 1619 1620 1621 1622 |
if (last) nf_ct_put(last); return skb->len; } static int ctnetlink_dump_dying(struct sk_buff *skb, struct netlink_callback *cb) { |
b7779d06f netfilter: conntr... |
1623 |
return ctnetlink_dump_list(skb, cb, true); |
d871befe3 netfilter: ctnetl... |
1624 |
} |
7b8002a15 netfilter: nfnetl... |
1625 1626 1627 |
static int ctnetlink_get_ct_dying(struct net *net, struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, |
04ba724b6 netfilter: nfnetl... |
1628 1629 |
const struct nlattr * const cda[], struct netlink_ext_ack *extack) |
d871befe3 netfilter: ctnetl... |
1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 |
{ if (nlh->nlmsg_flags & NLM_F_DUMP) { struct netlink_dump_control c = { .dump = ctnetlink_dump_dying, .done = ctnetlink_done_list, }; return netlink_dump_start(ctnl, skb, nlh, &c); } return -EOPNOTSUPP; } static int ctnetlink_dump_unconfirmed(struct sk_buff *skb, struct netlink_callback *cb) { |
b7779d06f netfilter: conntr... |
1645 |
return ctnetlink_dump_list(skb, cb, false); |
d871befe3 netfilter: ctnetl... |
1646 |
} |
7b8002a15 netfilter: nfnetl... |
1647 1648 1649 |
static int ctnetlink_get_ct_unconfirmed(struct net *net, struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, |
04ba724b6 netfilter: nfnetl... |
1650 1651 |
const struct nlattr * const cda[], struct netlink_ext_ack *extack) |
d871befe3 netfilter: ctnetl... |
1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 |
{ if (nlh->nlmsg_flags & NLM_F_DUMP) { struct netlink_dump_control c = { .dump = ctnetlink_dump_unconfirmed, .done = ctnetlink_done_list, }; return netlink_dump_start(ctnl, skb, nlh, &c); } return -EOPNOTSUPP; } |
4806e9757 netfilter: replac... |
1663 |
#if IS_ENABLED(CONFIG_NF_NAT) |
bb5cf80e9 [NETFILTER]: Kill... |
1664 |
static int |
e6a7d3c04 netfilter: ctnetl... |
1665 1666 |
ctnetlink_parse_nat_setup(struct nf_conn *ct, enum nf_nat_manip_type manip, |
399383246 netfilter: nfnetl... |
1667 |
const struct nlattr *attr) |
19f8f717f netfilter: ctnetl... |
1668 |
__must_hold(RCU) |
e6a7d3c04 netfilter: ctnetl... |
1669 |
{ |
2c205dd39 netfilter: add st... |
1670 |
struct nf_nat_hook *nat_hook; |
c7232c997 netfilter: add pr... |
1671 |
int err; |
e6a7d3c04 netfilter: ctnetl... |
1672 |
|
2c205dd39 netfilter: add st... |
1673 1674 |
nat_hook = rcu_dereference(nf_nat_hook); if (!nat_hook) { |
95a5afca4 net: Remove CONFI... |
1675 |
#ifdef CONFIG_MODULES |
e6a7d3c04 netfilter: ctnetl... |
1676 |
rcu_read_unlock(); |
c14b78e7d netfilter: nfnetl... |
1677 |
nfnl_unlock(NFNL_SUBSYS_CTNETLINK); |
c7232c997 netfilter: add pr... |
1678 |
if (request_module("nf-nat") < 0) { |
c14b78e7d netfilter: nfnetl... |
1679 |
nfnl_lock(NFNL_SUBSYS_CTNETLINK); |
e6a7d3c04 netfilter: ctnetl... |
1680 1681 1682 |
rcu_read_lock(); return -EOPNOTSUPP; } |
c14b78e7d netfilter: nfnetl... |
1683 |
nfnl_lock(NFNL_SUBSYS_CTNETLINK); |
e6a7d3c04 netfilter: ctnetl... |
1684 |
rcu_read_lock(); |
c05a45c08 netfilter: ctnetl... |
1685 1686 |
nat_hook = rcu_dereference(nf_nat_hook); if (nat_hook) |
e6a7d3c04 netfilter: ctnetl... |
1687 1688 1689 1690 |
return -EAGAIN; #endif return -EOPNOTSUPP; } |
2c205dd39 netfilter: add st... |
1691 |
err = nat_hook->parse_nat_setup(ct, manip, attr); |
c7232c997 netfilter: add pr... |
1692 1693 1694 |
if (err == -EAGAIN) { #ifdef CONFIG_MODULES rcu_read_unlock(); |
c14b78e7d netfilter: nfnetl... |
1695 |
nfnl_unlock(NFNL_SUBSYS_CTNETLINK); |
c7232c997 netfilter: add pr... |
1696 |
if (request_module("nf-nat-%u", nf_ct_l3num(ct)) < 0) { |
c14b78e7d netfilter: nfnetl... |
1697 |
nfnl_lock(NFNL_SUBSYS_CTNETLINK); |
c7232c997 netfilter: add pr... |
1698 1699 1700 |
rcu_read_lock(); return -EOPNOTSUPP; } |
c14b78e7d netfilter: nfnetl... |
1701 |
nfnl_lock(NFNL_SUBSYS_CTNETLINK); |
c7232c997 netfilter: add pr... |
1702 1703 1704 1705 1706 1707 |
rcu_read_lock(); #else err = -EOPNOTSUPP; #endif } return err; |
e6a7d3c04 netfilter: ctnetl... |
1708 |
} |
67671841d netfilter: fix co... |
1709 |
#endif |
e6a7d3c04 netfilter: ctnetl... |
1710 |
|
53b56da83 netfilter: ctnetl... |
1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 |
static void __ctnetlink_change_status(struct nf_conn *ct, unsigned long on, unsigned long off) { unsigned int bit; /* Ignore these unchangable bits */ on &= ~IPS_UNCHANGEABLE_MASK; off &= ~IPS_UNCHANGEABLE_MASK; for (bit = 0; bit < __IPS_MAX_BIT; bit++) { if (on & (1 << bit)) set_bit(bit, &ct->status); else if (off & (1 << bit)) clear_bit(bit, &ct->status); } } |
e6a7d3c04 netfilter: ctnetl... |
1728 |
static int |
399383246 netfilter: nfnetl... |
1729 |
ctnetlink_change_status(struct nf_conn *ct, const struct nlattr * const cda[]) |
c1d10adb4 [NETFILTER]: Add ... |
1730 1731 |
{ unsigned long d; |
77236b6e3 [NETFILTER]: ctne... |
1732 |
unsigned int status = ntohl(nla_get_be32(cda[CTA_STATUS])); |
c1d10adb4 [NETFILTER]: Add ... |
1733 1734 1735 1736 |
d = ct->status ^ status; if (d & (IPS_EXPECTED|IPS_CONFIRMED|IPS_DYING)) /* unchangeable */ |
0adf9d674 netfilter: ctnetl... |
1737 |
return -EBUSY; |
601e68e10 [NETFILTER]: Fix ... |
1738 |
|
c1d10adb4 [NETFILTER]: Add ... |
1739 1740 |
if (d & IPS_SEEN_REPLY && !(status & IPS_SEEN_REPLY)) /* SEEN_REPLY bit can only be set */ |
0adf9d674 netfilter: ctnetl... |
1741 |
return -EBUSY; |
601e68e10 [NETFILTER]: Fix ... |
1742 |
|
c1d10adb4 [NETFILTER]: Add ... |
1743 1744 |
if (d & IPS_ASSURED && !(status & IPS_ASSURED)) /* ASSURED bit can only be set */ |
0adf9d674 netfilter: ctnetl... |
1745 |
return -EBUSY; |
c1d10adb4 [NETFILTER]: Add ... |
1746 |
|
53b56da83 netfilter: ctnetl... |
1747 |
__ctnetlink_change_status(ct, status, 0); |
c1d10adb4 [NETFILTER]: Add ... |
1748 1749 |
return 0; } |
e6a7d3c04 netfilter: ctnetl... |
1750 |
static int |
0eba801b6 netfilter: ctnetl... |
1751 |
ctnetlink_setup_nat(struct nf_conn *ct, const struct nlattr * const cda[]) |
e6a7d3c04 netfilter: ctnetl... |
1752 |
{ |
4806e9757 netfilter: replac... |
1753 |
#if IS_ENABLED(CONFIG_NF_NAT) |
e6a7d3c04 netfilter: ctnetl... |
1754 |
int ret; |
fe337ac28 netfilter: ctnetl... |
1755 1756 |
if (!cda[CTA_NAT_DST] && !cda[CTA_NAT_SRC]) return 0; |
0eba801b6 netfilter: ctnetl... |
1757 1758 1759 1760 |
ret = ctnetlink_parse_nat_setup(ct, NF_NAT_MANIP_DST, cda[CTA_NAT_DST]); if (ret < 0) return ret; |
c47d36b38 netfilter: Merge ... |
1761 1762 |
return ctnetlink_parse_nat_setup(ct, NF_NAT_MANIP_SRC, cda[CTA_NAT_SRC]); |
e6a7d3c04 netfilter: ctnetl... |
1763 |
#else |
0eba801b6 netfilter: ctnetl... |
1764 1765 |
if (!cda[CTA_NAT_DST] && !cda[CTA_NAT_SRC]) return 0; |
e6a7d3c04 netfilter: ctnetl... |
1766 1767 1768 |
return -EOPNOTSUPP; #endif } |
c1d10adb4 [NETFILTER]: Add ... |
1769 |
|
4054ff454 netfilter: ctnetl... |
1770 1771 |
static int ctnetlink_change_helper(struct nf_conn *ct, const struct nlattr * const cda[]) |
c1d10adb4 [NETFILTER]: Add ... |
1772 1773 |
{ struct nf_conntrack_helper *helper; |
dc808fe28 [NETFILTER] nf_co... |
1774 |
struct nf_conn_help *help = nfct_help(ct); |
29fe1b481 netfilter: ctnetl... |
1775 |
char *helpname = NULL; |
ae243bee3 netfilter: ctnetl... |
1776 |
struct nlattr *helpinfo = NULL; |
c1d10adb4 [NETFILTER]: Add ... |
1777 |
int err; |
ae243bee3 netfilter: ctnetl... |
1778 |
err = ctnetlink_parse_help(cda[CTA_HELP], &helpname, &helpinfo); |
c1d10adb4 [NETFILTER]: Add ... |
1779 1780 |
if (err < 0) return err; |
f95d7a46b netfilter: ctnetl... |
1781 1782 1783 1784 1785 1786 |
/* don't change helper of sibling connections */ if (ct->master) { /* If we try to change the helper to the same thing twice, * treat the second attempt as a no-op instead of returning * an error. */ |
3173d5b8c netfilter: ctnetl... |
1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 |
err = -EBUSY; if (help) { rcu_read_lock(); helper = rcu_dereference(help->helper); if (helper && !strcmp(helper->name, helpname)) err = 0; rcu_read_unlock(); } return err; |
f95d7a46b netfilter: ctnetl... |
1797 |
} |
df293bbb6 [NETFILTER]: ctne... |
1798 1799 |
if (!strcmp(helpname, "")) { if (help && help->helper) { |
c1d10adb4 [NETFILTER]: Add ... |
1800 1801 |
/* we had a helper before ... */ nf_ct_remove_expectations(ct); |
a9b3cd7f3 rcu: convert uses... |
1802 |
RCU_INIT_POINTER(help->helper, NULL); |
c1d10adb4 [NETFILTER]: Add ... |
1803 |
} |
df293bbb6 [NETFILTER]: ctne... |
1804 1805 |
return 0; |
c1d10adb4 [NETFILTER]: Add ... |
1806 |
} |
601e68e10 [NETFILTER]: Fix ... |
1807 |
|
88be4c09d netfilter: ctnetl... |
1808 |
rcu_read_lock(); |
794e68716 netfilter: ctnetl... |
1809 1810 |
helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct), nf_ct_protonum(ct)); |
226c0c0ef netfilter: ctnetl... |
1811 |
if (helper == NULL) { |
88be4c09d netfilter: ctnetl... |
1812 |
rcu_read_unlock(); |
0adf9d674 netfilter: ctnetl... |
1813 |
return -EOPNOTSUPP; |
226c0c0ef netfilter: ctnetl... |
1814 |
} |
df293bbb6 [NETFILTER]: ctne... |
1815 |
|
ceceae1b1 [NETFILTER]: nf_c... |
1816 |
if (help) { |
ae243bee3 netfilter: ctnetl... |
1817 1818 |
if (help->helper == helper) { /* update private helper data if allowed. */ |
7be54ca47 netfilter: nf_ct_... |
1819 |
if (helper->from_nlattr) |
ae243bee3 netfilter: ctnetl... |
1820 |
helper->from_nlattr(helpinfo, ct); |
88be4c09d netfilter: ctnetl... |
1821 |
err = 0; |
fd7462de4 netfilter: ctnetl... |
1822 |
} else |
88be4c09d netfilter: ctnetl... |
1823 1824 1825 1826 |
err = -EBUSY; } else { /* we cannot set a helper for an existing conntrack */ err = -EOPNOTSUPP; |
ceceae1b1 [NETFILTER]: nf_c... |
1827 |
} |
df293bbb6 [NETFILTER]: ctne... |
1828 |
|
88be4c09d netfilter: ctnetl... |
1829 1830 |
rcu_read_unlock(); return err; |
c1d10adb4 [NETFILTER]: Add ... |
1831 |
} |
4054ff454 netfilter: ctnetl... |
1832 1833 |
static int ctnetlink_change_timeout(struct nf_conn *ct, const struct nlattr * const cda[]) |
c1d10adb4 [NETFILTER]: Add ... |
1834 |
{ |
8b1836c4b netfilter: conntr... |
1835 |
u64 timeout = (u64)ntohl(nla_get_be32(cda[CTA_TIMEOUT])) * HZ; |
601e68e10 [NETFILTER]: Fix ... |
1836 |
|
8b1836c4b netfilter: conntr... |
1837 1838 1839 |
if (timeout > INT_MAX) timeout = INT_MAX; ct->timeout = nfct_time_stamp + (u32)timeout; |
c1d10adb4 [NETFILTER]: Add ... |
1840 |
|
f330a7fdb netfilter: conntr... |
1841 1842 |
if (test_bit(IPS_DYING_BIT, &ct->status)) return -ETIME; |
c1d10adb4 [NETFILTER]: Add ... |
1843 1844 1845 |
return 0; } |
58fc419be netfilter: ctnetl... |
1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 |
#if defined(CONFIG_NF_CONNTRACK_MARK) static void ctnetlink_change_mark(struct nf_conn *ct, const struct nlattr * const cda[]) { u32 mark, newmark, mask = 0; if (cda[CTA_MARK_MASK]) mask = ~ntohl(nla_get_be32(cda[CTA_MARK_MASK])); mark = ntohl(nla_get_be32(cda[CTA_MARK])); newmark = (ct->mark & mask) ^ mark; if (newmark != ct->mark) ct->mark = newmark; } #endif |
d0b0268fd netfilter: ctnetl... |
1861 1862 1863 1864 1865 |
static const struct nla_policy protoinfo_policy[CTA_PROTOINFO_MAX+1] = { [CTA_PROTOINFO_TCP] = { .type = NLA_NESTED }, [CTA_PROTOINFO_DCCP] = { .type = NLA_NESTED }, [CTA_PROTOINFO_SCTP] = { .type = NLA_NESTED }, }; |
4054ff454 netfilter: ctnetl... |
1866 1867 |
static int ctnetlink_change_protoinfo(struct nf_conn *ct, const struct nlattr * const cda[]) |
c1d10adb4 [NETFILTER]: Add ... |
1868 |
{ |
399383246 netfilter: nfnetl... |
1869 |
const struct nlattr *attr = cda[CTA_PROTOINFO]; |
b3480fe05 netfilter: conntr... |
1870 |
const struct nf_conntrack_l4proto *l4proto; |
399383246 netfilter: nfnetl... |
1871 |
struct nlattr *tb[CTA_PROTOINFO_MAX+1]; |
c1d10adb4 [NETFILTER]: Add ... |
1872 |
int err = 0; |
8cb081746 netlink: make val... |
1873 1874 |
err = nla_parse_nested_deprecated(tb, CTA_PROTOINFO_MAX, attr, protoinfo_policy, NULL); |
130ffbc26 netfilter: check ... |
1875 1876 |
if (err < 0) return err; |
c1d10adb4 [NETFILTER]: Add ... |
1877 |
|
4a60dc748 netfilter: conntr... |
1878 |
l4proto = nf_ct_l4proto_find(nf_ct_protonum(ct)); |
fdf708322 [NETFILTER]: nfne... |
1879 1880 |
if (l4proto->from_nlattr) err = l4proto->from_nlattr(tb, ct); |
c1d10adb4 [NETFILTER]: Add ... |
1881 1882 1883 |
return err; } |
41d73ec05 netfilter: nf_con... |
1884 1885 1886 1887 |
static const struct nla_policy seqadj_policy[CTA_SEQADJ_MAX+1] = { [CTA_SEQADJ_CORRECTION_POS] = { .type = NLA_U32 }, [CTA_SEQADJ_OFFSET_BEFORE] = { .type = NLA_U32 }, [CTA_SEQADJ_OFFSET_AFTER] = { .type = NLA_U32 }, |
d0b0268fd netfilter: ctnetl... |
1888 |
}; |
4054ff454 netfilter: ctnetl... |
1889 1890 |
static int change_seq_adj(struct nf_ct_seqadj *seq, const struct nlattr * const attr) |
13eae15a2 [NETFILTER]: ctne... |
1891 |
{ |
130ffbc26 netfilter: check ... |
1892 |
int err; |
41d73ec05 netfilter: nf_con... |
1893 |
struct nlattr *cda[CTA_SEQADJ_MAX+1]; |
13eae15a2 [NETFILTER]: ctne... |
1894 |
|
8cb081746 netlink: make val... |
1895 1896 |
err = nla_parse_nested_deprecated(cda, CTA_SEQADJ_MAX, attr, seqadj_policy, NULL); |
130ffbc26 netfilter: check ... |
1897 1898 |
if (err < 0) return err; |
13eae15a2 [NETFILTER]: ctne... |
1899 |
|
41d73ec05 netfilter: nf_con... |
1900 |
if (!cda[CTA_SEQADJ_CORRECTION_POS]) |
13eae15a2 [NETFILTER]: ctne... |
1901 |
return -EINVAL; |
41d73ec05 netfilter: nf_con... |
1902 1903 |
seq->correction_pos = ntohl(nla_get_be32(cda[CTA_SEQADJ_CORRECTION_POS])); |
13eae15a2 [NETFILTER]: ctne... |
1904 |
|
41d73ec05 netfilter: nf_con... |
1905 |
if (!cda[CTA_SEQADJ_OFFSET_BEFORE]) |
13eae15a2 [NETFILTER]: ctne... |
1906 |
return -EINVAL; |
41d73ec05 netfilter: nf_con... |
1907 1908 |
seq->offset_before = ntohl(nla_get_be32(cda[CTA_SEQADJ_OFFSET_BEFORE])); |
13eae15a2 [NETFILTER]: ctne... |
1909 |
|
41d73ec05 netfilter: nf_con... |
1910 |
if (!cda[CTA_SEQADJ_OFFSET_AFTER]) |
13eae15a2 [NETFILTER]: ctne... |
1911 |
return -EINVAL; |
41d73ec05 netfilter: nf_con... |
1912 1913 |
seq->offset_after = ntohl(nla_get_be32(cda[CTA_SEQADJ_OFFSET_AFTER])); |
13eae15a2 [NETFILTER]: ctne... |
1914 1915 1916 1917 1918 |
return 0; } static int |
41d73ec05 netfilter: nf_con... |
1919 1920 |
ctnetlink_change_seq_adj(struct nf_conn *ct, const struct nlattr * const cda[]) |
13eae15a2 [NETFILTER]: ctne... |
1921 |
{ |
41d73ec05 netfilter: nf_con... |
1922 |
struct nf_conn_seqadj *seqadj = nfct_seqadj(ct); |
13eae15a2 [NETFILTER]: ctne... |
1923 |
int ret = 0; |
13eae15a2 [NETFILTER]: ctne... |
1924 |
|
41d73ec05 netfilter: nf_con... |
1925 |
if (!seqadj) |
13eae15a2 [NETFILTER]: ctne... |
1926 |
return 0; |
64f3967c7 netfilter: ctnetl... |
1927 |
spin_lock_bh(&ct->lock); |
41d73ec05 netfilter: nf_con... |
1928 1929 1930 |
if (cda[CTA_SEQ_ADJ_ORIG]) { ret = change_seq_adj(&seqadj->seq[IP_CT_DIR_ORIGINAL], cda[CTA_SEQ_ADJ_ORIG]); |
13eae15a2 [NETFILTER]: ctne... |
1931 |
if (ret < 0) |
64f3967c7 netfilter: ctnetl... |
1932 |
goto err; |
13eae15a2 [NETFILTER]: ctne... |
1933 |
|
53b56da83 netfilter: ctnetl... |
1934 |
set_bit(IPS_SEQ_ADJUST_BIT, &ct->status); |
13eae15a2 [NETFILTER]: ctne... |
1935 |
} |
41d73ec05 netfilter: nf_con... |
1936 1937 1938 |
if (cda[CTA_SEQ_ADJ_REPLY]) { ret = change_seq_adj(&seqadj->seq[IP_CT_DIR_REPLY], cda[CTA_SEQ_ADJ_REPLY]); |
13eae15a2 [NETFILTER]: ctne... |
1939 |
if (ret < 0) |
64f3967c7 netfilter: ctnetl... |
1940 |
goto err; |
13eae15a2 [NETFILTER]: ctne... |
1941 |
|
53b56da83 netfilter: ctnetl... |
1942 |
set_bit(IPS_SEQ_ADJUST_BIT, &ct->status); |
13eae15a2 [NETFILTER]: ctne... |
1943 |
} |
64f3967c7 netfilter: ctnetl... |
1944 |
spin_unlock_bh(&ct->lock); |
13eae15a2 [NETFILTER]: ctne... |
1945 |
return 0; |
64f3967c7 netfilter: ctnetl... |
1946 1947 1948 |
err: spin_unlock_bh(&ct->lock); return ret; |
13eae15a2 [NETFILTER]: ctne... |
1949 |
} |
13eae15a2 [NETFILTER]: ctne... |
1950 |
|
20710b3b8 netfilter: ctnetl... |
1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 |
static const struct nla_policy synproxy_policy[CTA_SYNPROXY_MAX + 1] = { [CTA_SYNPROXY_ISN] = { .type = NLA_U32 }, [CTA_SYNPROXY_ITS] = { .type = NLA_U32 }, [CTA_SYNPROXY_TSOFF] = { .type = NLA_U32 }, }; static int ctnetlink_change_synproxy(struct nf_conn *ct, const struct nlattr * const cda[]) { struct nf_conn_synproxy *synproxy = nfct_synproxy(ct); struct nlattr *tb[CTA_SYNPROXY_MAX + 1]; int err; if (!synproxy) return 0; |
8cb081746 netlink: make val... |
1966 1967 1968 |
err = nla_parse_nested_deprecated(tb, CTA_SYNPROXY_MAX, cda[CTA_SYNPROXY], synproxy_policy, NULL); |
20710b3b8 netfilter: ctnetl... |
1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 |
if (err < 0) return err; if (!tb[CTA_SYNPROXY_ISN] || !tb[CTA_SYNPROXY_ITS] || !tb[CTA_SYNPROXY_TSOFF]) return -EINVAL; synproxy->isn = ntohl(nla_get_be32(tb[CTA_SYNPROXY_ISN])); synproxy->its = ntohl(nla_get_be32(tb[CTA_SYNPROXY_ITS])); synproxy->tsoff = ntohl(nla_get_be32(tb[CTA_SYNPROXY_TSOFF])); return 0; } |
c1d10adb4 [NETFILTER]: Add ... |
1983 |
static int |
9b21f6a90 netfilter: ctnetl... |
1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 |
ctnetlink_attach_labels(struct nf_conn *ct, const struct nlattr * const cda[]) { #ifdef CONFIG_NF_CONNTRACK_LABELS size_t len = nla_len(cda[CTA_LABELS]); const void *mask = cda[CTA_LABELS_MASK]; if (len & (sizeof(u32)-1)) /* must be multiple of u32 */ return -EINVAL; if (mask) { if (nla_len(cda[CTA_LABELS_MASK]) == 0 || nla_len(cda[CTA_LABELS_MASK]) != len) return -EINVAL; mask = nla_data(cda[CTA_LABELS_MASK]); } len /= sizeof(u32); return nf_connlabels_replace(ct, nla_data(cda[CTA_LABELS]), mask, len); #else return -EOPNOTSUPP; #endif } static int |
399383246 netfilter: nfnetl... |
2009 2010 |
ctnetlink_change_conntrack(struct nf_conn *ct, const struct nlattr * const cda[]) |
c1d10adb4 [NETFILTER]: Add ... |
2011 2012 |
{ int err; |
e098360f1 netfilter: ctnetl... |
2013 2014 2015 |
/* only allow NAT changes and master assignation for new conntracks */ if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST] || cda[CTA_TUPLE_MASTER]) return -EOPNOTSUPP; |
df6fb868d [NETFILTER]: nfne... |
2016 |
if (cda[CTA_HELP]) { |
c1d10adb4 [NETFILTER]: Add ... |
2017 2018 2019 2020 |
err = ctnetlink_change_helper(ct, cda); if (err < 0) return err; } |
df6fb868d [NETFILTER]: nfne... |
2021 |
if (cda[CTA_TIMEOUT]) { |
c1d10adb4 [NETFILTER]: Add ... |
2022 2023 2024 2025 |
err = ctnetlink_change_timeout(ct, cda); if (err < 0) return err; } |
df6fb868d [NETFILTER]: nfne... |
2026 |
if (cda[CTA_STATUS]) { |
c1d10adb4 [NETFILTER]: Add ... |
2027 2028 2029 2030 |
err = ctnetlink_change_status(ct, cda); if (err < 0) return err; } |
df6fb868d [NETFILTER]: nfne... |
2031 |
if (cda[CTA_PROTOINFO]) { |
c1d10adb4 [NETFILTER]: Add ... |
2032 2033 2034 2035 |
err = ctnetlink_change_protoinfo(ct, cda); if (err < 0) return err; } |
bcd1e830a [NETFILTER]: fix ... |
2036 |
#if defined(CONFIG_NF_CONNTRACK_MARK) |
df6fb868d [NETFILTER]: nfne... |
2037 |
if (cda[CTA_MARK]) |
58fc419be netfilter: ctnetl... |
2038 |
ctnetlink_change_mark(ct, cda); |
c1d10adb4 [NETFILTER]: Add ... |
2039 |
#endif |
41d73ec05 netfilter: nf_con... |
2040 2041 |
if (cda[CTA_SEQ_ADJ_ORIG] || cda[CTA_SEQ_ADJ_REPLY]) { err = ctnetlink_change_seq_adj(ct, cda); |
13eae15a2 [NETFILTER]: ctne... |
2042 2043 2044 |
if (err < 0) return err; } |
41d73ec05 netfilter: nf_con... |
2045 |
|
20710b3b8 netfilter: ctnetl... |
2046 2047 2048 2049 2050 |
if (cda[CTA_SYNPROXY]) { err = ctnetlink_change_synproxy(ct, cda); if (err < 0) return err; } |
9b21f6a90 netfilter: ctnetl... |
2051 2052 2053 2054 2055 |
if (cda[CTA_LABELS]) { err = ctnetlink_attach_labels(ct, cda); if (err < 0) return err; } |
13eae15a2 [NETFILTER]: ctne... |
2056 |
|
c1d10adb4 [NETFILTER]: Add ... |
2057 2058 |
return 0; } |
f0a3c0869 netfilter: ctnetl... |
2059 |
static struct nf_conn * |
308ac9143 netfilter: nf_con... |
2060 2061 |
ctnetlink_create_conntrack(struct net *net, const struct nf_conntrack_zone *zone, |
9592a5c01 netfilter: ctnetl... |
2062 |
const struct nlattr * const cda[], |
c1d10adb4 [NETFILTER]: Add ... |
2063 |
struct nf_conntrack_tuple *otuple, |
5faa1f4cb [NETFILTER]: nf_c... |
2064 |
struct nf_conntrack_tuple *rtuple, |
7ec474967 netfilter: ctnetl... |
2065 |
u8 u3) |
c1d10adb4 [NETFILTER]: Add ... |
2066 2067 2068 |
{ struct nf_conn *ct; int err = -EINVAL; |
ceceae1b1 [NETFILTER]: nf_c... |
2069 |
struct nf_conntrack_helper *helper; |
315c34dae netfilter: ctnetl... |
2070 |
struct nf_conn_tstamp *tstamp; |
8b1836c4b netfilter: conntr... |
2071 |
u64 timeout; |
c1d10adb4 [NETFILTER]: Add ... |
2072 |
|
ef00f89f1 netfilter: ctnetl... |
2073 |
ct = nf_conntrack_alloc(net, zone, otuple, rtuple, GFP_ATOMIC); |
cd7fcbf1c netfilter 07/09: ... |
2074 |
if (IS_ERR(ct)) |
f0a3c0869 netfilter: ctnetl... |
2075 |
return ERR_PTR(-ENOMEM); |
c1d10adb4 [NETFILTER]: Add ... |
2076 |
|
df6fb868d [NETFILTER]: nfne... |
2077 |
if (!cda[CTA_TIMEOUT]) |
0f5b3e85a netfilter: ctnetl... |
2078 |
goto err1; |
c1d10adb4 [NETFILTER]: Add ... |
2079 |
|
8b1836c4b netfilter: conntr... |
2080 2081 2082 2083 |
timeout = (u64)ntohl(nla_get_be32(cda[CTA_TIMEOUT])) * HZ; if (timeout > INT_MAX) timeout = INT_MAX; ct->timeout = (u32)timeout + nfct_time_stamp; |
c1d10adb4 [NETFILTER]: Add ... |
2084 |
|
1575e7ea0 netfilter: ctnetl... |
2085 |
rcu_read_lock(); |
226c0c0ef netfilter: ctnetl... |
2086 |
if (cda[CTA_HELP]) { |
29fe1b481 netfilter: ctnetl... |
2087 |
char *helpname = NULL; |
ae243bee3 netfilter: ctnetl... |
2088 2089 2090 |
struct nlattr *helpinfo = NULL; err = ctnetlink_parse_help(cda[CTA_HELP], &helpname, &helpinfo); |
0f5b3e85a netfilter: ctnetl... |
2091 2092 |
if (err < 0) goto err2; |
226c0c0ef netfilter: ctnetl... |
2093 |
|
794e68716 netfilter: ctnetl... |
2094 2095 |
helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct), nf_ct_protonum(ct)); |
226c0c0ef netfilter: ctnetl... |
2096 2097 2098 2099 2100 |
if (helper == NULL) { rcu_read_unlock(); #ifdef CONFIG_MODULES if (request_module("nfct-helper-%s", helpname) < 0) { err = -EOPNOTSUPP; |
0f5b3e85a netfilter: ctnetl... |
2101 |
goto err1; |
226c0c0ef netfilter: ctnetl... |
2102 2103 2104 |
} rcu_read_lock(); |
794e68716 netfilter: ctnetl... |
2105 2106 2107 |
helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct), nf_ct_protonum(ct)); |
226c0c0ef netfilter: ctnetl... |
2108 |
if (helper) { |
226c0c0ef netfilter: ctnetl... |
2109 |
err = -EAGAIN; |
0f5b3e85a netfilter: ctnetl... |
2110 |
goto err2; |
226c0c0ef netfilter: ctnetl... |
2111 2112 2113 2114 |
} rcu_read_unlock(); #endif err = -EOPNOTSUPP; |
0f5b3e85a netfilter: ctnetl... |
2115 |
goto err1; |
226c0c0ef netfilter: ctnetl... |
2116 2117 |
} else { struct nf_conn_help *help; |
440534d3c netfilter: Remove... |
2118 |
help = nf_ct_helper_ext_add(ct, GFP_ATOMIC); |
226c0c0ef netfilter: ctnetl... |
2119 |
if (help == NULL) { |
226c0c0ef netfilter: ctnetl... |
2120 |
err = -ENOMEM; |
0f5b3e85a netfilter: ctnetl... |
2121 |
goto err2; |
226c0c0ef netfilter: ctnetl... |
2122 |
} |
ae243bee3 netfilter: ctnetl... |
2123 |
/* set private helper data if allowed. */ |
7be54ca47 netfilter: nf_ct_... |
2124 |
if (helper->from_nlattr) |
ae243bee3 netfilter: ctnetl... |
2125 |
helper->from_nlattr(helpinfo, ct); |
226c0c0ef netfilter: ctnetl... |
2126 2127 |
/* not in hash table yet so not strictly necessary */ |
a9b3cd7f3 rcu: convert uses... |
2128 |
RCU_INIT_POINTER(help->helper, helper); |
226c0c0ef netfilter: ctnetl... |
2129 2130 2131 |
} } else { /* try an implicit helper assignation */ |
b2a15a604 netfilter: nf_con... |
2132 |
err = __nf_ct_try_assign_helper(ct, NULL, GFP_ATOMIC); |
0f5b3e85a netfilter: ctnetl... |
2133 2134 |
if (err < 0) goto err2; |
1575e7ea0 netfilter: ctnetl... |
2135 |
} |
0eba801b6 netfilter: ctnetl... |
2136 2137 2138 |
err = ctnetlink_setup_nat(ct, cda); if (err < 0) goto err2; |
e6a7d3c04 netfilter: ctnetl... |
2139 |
|
a88e22adf netfilter: ctnetl... |
2140 |
nf_ct_acct_ext_add(ct, GFP_ATOMIC); |
a992ca2a0 netfilter: nf_con... |
2141 |
nf_ct_tstamp_ext_add(ct, GFP_ATOMIC); |
a88e22adf netfilter: ctnetl... |
2142 |
nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC); |
c539f0171 netfilter: add co... |
2143 |
nf_ct_labels_ext_add(ct); |
87e94dbc2 netfilter: synpro... |
2144 2145 |
nfct_seqadj_ext_add(ct); nfct_synproxy_ext_add(ct); |
c539f0171 netfilter: add co... |
2146 |
|
a88e22adf netfilter: ctnetl... |
2147 2148 2149 2150 2151 |
/* we must add conntrack extensions before confirmation. */ ct->status |= IPS_CONFIRMED; if (cda[CTA_STATUS]) { err = ctnetlink_change_status(ct, cda); |
0f5b3e85a netfilter: ctnetl... |
2152 2153 |
if (err < 0) goto err2; |
bbb3357d1 [NETFILTER]: ctne... |
2154 |
} |
c1d10adb4 [NETFILTER]: Add ... |
2155 |
|
41d73ec05 netfilter: nf_con... |
2156 2157 |
if (cda[CTA_SEQ_ADJ_ORIG] || cda[CTA_SEQ_ADJ_REPLY]) { err = ctnetlink_change_seq_adj(ct, cda); |
0f5b3e85a netfilter: ctnetl... |
2158 2159 |
if (err < 0) goto err2; |
c969aa7d2 netfilter: ctnetl... |
2160 |
} |
c969aa7d2 netfilter: ctnetl... |
2161 |
|
e5fc9e7a6 netfilter: nf_con... |
2162 |
memset(&ct->proto, 0, sizeof(ct->proto)); |
df6fb868d [NETFILTER]: nfne... |
2163 |
if (cda[CTA_PROTOINFO]) { |
c1d10adb4 [NETFILTER]: Add ... |
2164 |
err = ctnetlink_change_protoinfo(ct, cda); |
0f5b3e85a netfilter: ctnetl... |
2165 2166 |
if (err < 0) goto err2; |
c1d10adb4 [NETFILTER]: Add ... |
2167 |
} |
20710b3b8 netfilter: ctnetl... |
2168 2169 2170 2171 2172 |
if (cda[CTA_SYNPROXY]) { err = ctnetlink_change_synproxy(ct, cda); if (err < 0) goto err2; } |
bcd1e830a [NETFILTER]: fix ... |
2173 |
#if defined(CONFIG_NF_CONNTRACK_MARK) |
df6fb868d [NETFILTER]: nfne... |
2174 |
if (cda[CTA_MARK]) |
58fc419be netfilter: ctnetl... |
2175 |
ctnetlink_change_mark(ct, cda); |
c1d10adb4 [NETFILTER]: Add ... |
2176 |
#endif |
5faa1f4cb [NETFILTER]: nf_c... |
2177 |
/* setup master conntrack: this is a confirmed expectation */ |
7ec474967 netfilter: ctnetl... |
2178 2179 2180 2181 |
if (cda[CTA_TUPLE_MASTER]) { struct nf_conntrack_tuple master; struct nf_conntrack_tuple_hash *master_h; struct nf_conn *master_ct; |
deedb5903 netfilter: nf_con... |
2182 2183 |
err = ctnetlink_parse_tuple(cda, &master, CTA_TUPLE_MASTER, u3, NULL); |
7ec474967 netfilter: ctnetl... |
2184 |
if (err < 0) |
0f5b3e85a netfilter: ctnetl... |
2185 |
goto err2; |
7ec474967 netfilter: ctnetl... |
2186 |
|
ef00f89f1 netfilter: ctnetl... |
2187 |
master_h = nf_conntrack_find_get(net, zone, &master); |
7ec474967 netfilter: ctnetl... |
2188 2189 |
if (master_h == NULL) { err = -ENOENT; |
0f5b3e85a netfilter: ctnetl... |
2190 |
goto err2; |
7ec474967 netfilter: ctnetl... |
2191 2192 |
} master_ct = nf_ct_tuplehash_to_ctrack(master_h); |
f2a89004d [NETFILTER]: ctne... |
2193 |
__set_bit(IPS_EXPECTED_BIT, &ct->status); |
5faa1f4cb [NETFILTER]: nf_c... |
2194 |
ct->master = master_ct; |
f2a89004d [NETFILTER]: ctne... |
2195 |
} |
315c34dae netfilter: ctnetl... |
2196 2197 |
tstamp = nf_conn_tstamp_find(ct); if (tstamp) |
d2de875c6 net: use ktime_ge... |
2198 |
tstamp->start = ktime_get_real_ns(); |
5faa1f4cb [NETFILTER]: nf_c... |
2199 |
|
7d367e066 netfilter: ctnetl... |
2200 2201 2202 |
err = nf_conntrack_hash_check_insert(ct); if (err < 0) goto err2; |
58a3c9bb0 [NETFILTER]: nf_c... |
2203 |
rcu_read_unlock(); |
dafc741cf [NETFILTER]: nfct... |
2204 |
|
f0a3c0869 netfilter: ctnetl... |
2205 |
return ct; |
c1d10adb4 [NETFILTER]: Add ... |
2206 |
|
0f5b3e85a netfilter: ctnetl... |
2207 2208 2209 |
err2: rcu_read_unlock(); err1: |
c1d10adb4 [NETFILTER]: Add ... |
2210 |
nf_conntrack_free(ct); |
f0a3c0869 netfilter: ctnetl... |
2211 |
return ERR_PTR(err); |
c1d10adb4 [NETFILTER]: Add ... |
2212 |
} |
7b8002a15 netfilter: nfnetl... |
2213 2214 2215 |
static int ctnetlink_new_conntrack(struct net *net, struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, |
04ba724b6 netfilter: nfnetl... |
2216 2217 |
const struct nlattr * const cda[], struct netlink_ext_ack *extack) |
c1d10adb4 [NETFILTER]: Add ... |
2218 2219 2220 |
{ struct nf_conntrack_tuple otuple, rtuple; struct nf_conntrack_tuple_hash *h = NULL; |
96bcf938d netfilter: ctnetl... |
2221 |
struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
7d367e066 netfilter: ctnetl... |
2222 |
struct nf_conn *ct; |
c1d10adb4 [NETFILTER]: Add ... |
2223 |
u_int8_t u3 = nfmsg->nfgen_family; |
308ac9143 netfilter: nf_con... |
2224 |
struct nf_conntrack_zone zone; |
ef00f89f1 netfilter: ctnetl... |
2225 2226 2227 2228 2229 |
int err; err = ctnetlink_parse_zone(cda[CTA_ZONE], &zone); if (err < 0) return err; |
c1d10adb4 [NETFILTER]: Add ... |
2230 |
|
df6fb868d [NETFILTER]: nfne... |
2231 |
if (cda[CTA_TUPLE_ORIG]) { |
deedb5903 netfilter: nf_con... |
2232 2233 |
err = ctnetlink_parse_tuple(cda, &otuple, CTA_TUPLE_ORIG, u3, &zone); |
c1d10adb4 [NETFILTER]: Add ... |
2234 2235 2236 |
if (err < 0) return err; } |
df6fb868d [NETFILTER]: nfne... |
2237 |
if (cda[CTA_TUPLE_REPLY]) { |
deedb5903 netfilter: nf_con... |
2238 2239 |
err = ctnetlink_parse_tuple(cda, &rtuple, CTA_TUPLE_REPLY, u3, &zone); |
c1d10adb4 [NETFILTER]: Add ... |
2240 2241 2242 |
if (err < 0) return err; } |
df6fb868d [NETFILTER]: nfne... |
2243 |
if (cda[CTA_TUPLE_ORIG]) |
308ac9143 netfilter: nf_con... |
2244 |
h = nf_conntrack_find_get(net, &zone, &otuple); |
df6fb868d [NETFILTER]: nfne... |
2245 |
else if (cda[CTA_TUPLE_REPLY]) |
308ac9143 netfilter: nf_con... |
2246 |
h = nf_conntrack_find_get(net, &zone, &rtuple); |
c1d10adb4 [NETFILTER]: Add ... |
2247 2248 |
if (h == NULL) { |
c1d10adb4 [NETFILTER]: Add ... |
2249 |
err = -ENOENT; |
f0a3c0869 netfilter: ctnetl... |
2250 |
if (nlh->nlmsg_flags & NLM_F_CREATE) { |
fecc1133b netfilter: ctnetl... |
2251 |
enum ip_conntrack_events events; |
5faa1f4cb [NETFILTER]: nf_c... |
2252 |
|
442fad942 netfilter: ctnetl... |
2253 2254 |
if (!cda[CTA_TUPLE_ORIG] || !cda[CTA_TUPLE_REPLY]) return -EINVAL; |
aa0c2c68a netfilter: ctnetl... |
2255 2256 |
if (otuple.dst.protonum != rtuple.dst.protonum) return -EINVAL; |
442fad942 netfilter: ctnetl... |
2257 |
|
308ac9143 netfilter: nf_con... |
2258 |
ct = ctnetlink_create_conntrack(net, &zone, cda, &otuple, |
f0a3c0869 netfilter: ctnetl... |
2259 |
&rtuple, u3); |
7d367e066 netfilter: ctnetl... |
2260 2261 |
if (IS_ERR(ct)) return PTR_ERR(ct); |
f0a3c0869 netfilter: ctnetl... |
2262 |
err = 0; |
fecc1133b netfilter: ctnetl... |
2263 |
if (test_bit(IPS_EXPECTED_BIT, &ct->status)) |
97aae0df1 netfilter: ctnetl... |
2264 |
events = 1 << IPCT_RELATED; |
fecc1133b netfilter: ctnetl... |
2265 |
else |
97aae0df1 netfilter: ctnetl... |
2266 |
events = 1 << IPCT_NEW; |
fecc1133b netfilter: ctnetl... |
2267 |
|
9b21f6a90 netfilter: ctnetl... |
2268 2269 2270 |
if (cda[CTA_LABELS] && ctnetlink_attach_labels(ct, cda) == 0) events |= (1 << IPCT_LABEL); |
858b31330 netfilter: nf_con... |
2271 2272 |
nf_conntrack_eventmask_report((1 << IPCT_REPLY) | (1 << IPCT_ASSURED) | |
a0891aa6a netfilter: conntr... |
2273 2274 |
(1 << IPCT_HELPER) | (1 << IPCT_PROTOINFO) | |
41d73ec05 netfilter: nf_con... |
2275 |
(1 << IPCT_SEQADJ) | |
20710b3b8 netfilter: ctnetl... |
2276 2277 2278 |
(1 << IPCT_MARK) | (1 << IPCT_SYNPROXY) | events, |
15e473046 netlink: Rename p... |
2279 |
ct, NETLINK_CB(skb).portid, |
a0891aa6a netfilter: conntr... |
2280 |
nlmsg_report(nlh)); |
f0a3c0869 netfilter: ctnetl... |
2281 |
nf_ct_put(ct); |
7d367e066 netfilter: ctnetl... |
2282 |
} |
5faa1f4cb [NETFILTER]: nf_c... |
2283 |
|
c1d10adb4 [NETFILTER]: Add ... |
2284 2285 2286 |
return err; } /* implicit 'else' */ |
c1d10adb4 [NETFILTER]: Add ... |
2287 |
err = -EEXIST; |
7d367e066 netfilter: ctnetl... |
2288 |
ct = nf_ct_tuplehash_to_ctrack(h); |
ff4ca8273 [NETFILTER]: ctne... |
2289 |
if (!(nlh->nlmsg_flags & NLM_F_EXCL)) { |
19abb7b09 netfilter: ctnetl... |
2290 2291 |
err = ctnetlink_change_conntrack(ct, cda); if (err == 0) { |
858b31330 netfilter: nf_con... |
2292 2293 |
nf_conntrack_eventmask_report((1 << IPCT_REPLY) | (1 << IPCT_ASSURED) | |
a0891aa6a netfilter: conntr... |
2294 |
(1 << IPCT_HELPER) | |
797a7d66d netfilter: ctnetl... |
2295 |
(1 << IPCT_LABEL) | |
a0891aa6a netfilter: conntr... |
2296 |
(1 << IPCT_PROTOINFO) | |
41d73ec05 netfilter: nf_con... |
2297 |
(1 << IPCT_SEQADJ) | |
20710b3b8 netfilter: ctnetl... |
2298 2299 |
(1 << IPCT_MARK) | (1 << IPCT_SYNPROXY), |
15e473046 netlink: Rename p... |
2300 |
ct, NETLINK_CB(skb).portid, |
a0891aa6a netfilter: conntr... |
2301 |
nlmsg_report(nlh)); |
7d367e066 netfilter: ctnetl... |
2302 |
} |
ff4ca8273 [NETFILTER]: ctne... |
2303 |
} |
c1d10adb4 [NETFILTER]: Add ... |
2304 |
|
7d367e066 netfilter: ctnetl... |
2305 |
nf_ct_put(ct); |
c1d10adb4 [NETFILTER]: Add ... |
2306 2307 |
return err; } |
392025f87 netfilter: ctnetl... |
2308 |
static int |
15e473046 netlink: Rename p... |
2309 |
ctnetlink_ct_stat_cpu_fill_info(struct sk_buff *skb, u32 portid, u32 seq, |
392025f87 netfilter: ctnetl... |
2310 2311 2312 2313 |
__u16 cpu, const struct ip_conntrack_stat *st) { struct nlmsghdr *nlh; struct nfgenmsg *nfmsg; |
15e473046 netlink: Rename p... |
2314 |
unsigned int flags = portid ? NLM_F_MULTI : 0, event; |
392025f87 netfilter: ctnetl... |
2315 |
|
dedb67c4b netfilter: Add nf... |
2316 2317 |
event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET_STATS_CPU); |
15e473046 netlink: Rename p... |
2318 |
nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags); |
392025f87 netfilter: ctnetl... |
2319 2320 2321 2322 2323 2324 2325 |
if (nlh == NULL) goto nlmsg_failure; nfmsg = nlmsg_data(nlh); nfmsg->nfgen_family = AF_UNSPEC; nfmsg->version = NFNETLINK_V0; nfmsg->res_id = htons(cpu); |
8e8118f89 netfilter: conntr... |
2326 |
if (nla_put_be32(skb, CTA_STATS_FOUND, htonl(st->found)) || |
392025f87 netfilter: ctnetl... |
2327 |
nla_put_be32(skb, CTA_STATS_INVALID, htonl(st->invalid)) || |
392025f87 netfilter: ctnetl... |
2328 2329 2330 2331 2332 2333 2334 |
nla_put_be32(skb, CTA_STATS_INSERT, htonl(st->insert)) || nla_put_be32(skb, CTA_STATS_INSERT_FAILED, htonl(st->insert_failed)) || nla_put_be32(skb, CTA_STATS_DROP, htonl(st->drop)) || nla_put_be32(skb, CTA_STATS_EARLY_DROP, htonl(st->early_drop)) || nla_put_be32(skb, CTA_STATS_ERROR, htonl(st->error)) || nla_put_be32(skb, CTA_STATS_SEARCH_RESTART, |
bc9247041 netfilter: conntr... |
2335 2336 2337 |
htonl(st->search_restart)) || nla_put_be32(skb, CTA_STATS_CLASH_RESOLVE, htonl(st->clash_resolve))) |
392025f87 netfilter: ctnetl... |
2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 |
goto nla_put_failure; nlmsg_end(skb, nlh); return skb->len; nla_put_failure: nlmsg_failure: nlmsg_cancel(skb, nlh); return -1; } static int ctnetlink_ct_stat_cpu_dump(struct sk_buff *skb, struct netlink_callback *cb) { int cpu; struct net *net = sock_net(skb->sk); if (cb->args[0] == nr_cpu_ids) return 0; for (cpu = cb->args[0]; cpu < nr_cpu_ids; cpu++) { const struct ip_conntrack_stat *st; if (!cpu_possible(cpu)) continue; st = per_cpu_ptr(net->ct.stat, cpu); if (ctnetlink_ct_stat_cpu_fill_info(skb, |
15e473046 netlink: Rename p... |
2366 |
NETLINK_CB(cb->skb).portid, |
392025f87 netfilter: ctnetl... |
2367 2368 2369 2370 2371 2372 2373 2374 |
cb->nlh->nlmsg_seq, cpu, st) < 0) break; } cb->args[0] = cpu; return skb->len; } |
7b8002a15 netfilter: nfnetl... |
2375 2376 2377 |
static int ctnetlink_stat_ct_cpu(struct net *net, struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, |
04ba724b6 netfilter: nfnetl... |
2378 2379 |
const struct nlattr * const cda[], struct netlink_ext_ack *extack) |
392025f87 netfilter: ctnetl... |
2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 |
{ if (nlh->nlmsg_flags & NLM_F_DUMP) { struct netlink_dump_control c = { .dump = ctnetlink_ct_stat_cpu_dump, }; return netlink_dump_start(ctnl, skb, nlh, &c); } return 0; } static int |
15e473046 netlink: Rename p... |
2392 |
ctnetlink_stat_ct_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type, |
392025f87 netfilter: ctnetl... |
2393 2394 2395 2396 |
struct net *net) { struct nlmsghdr *nlh; struct nfgenmsg *nfmsg; |
15e473046 netlink: Rename p... |
2397 |
unsigned int flags = portid ? NLM_F_MULTI : 0, event; |
392025f87 netfilter: ctnetl... |
2398 |
unsigned int nr_conntracks = atomic_read(&net->ct.count); |
dedb67c4b netfilter: Add nf... |
2399 |
event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET_STATS); |
15e473046 netlink: Rename p... |
2400 |
nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags); |
392025f87 netfilter: ctnetl... |
2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 |
if (nlh == NULL) goto nlmsg_failure; nfmsg = nlmsg_data(nlh); nfmsg->nfgen_family = AF_UNSPEC; nfmsg->version = NFNETLINK_V0; nfmsg->res_id = 0; if (nla_put_be32(skb, CTA_STATS_GLOBAL_ENTRIES, htonl(nr_conntracks))) goto nla_put_failure; |
538c5672b netfilter: ctnetl... |
2411 2412 |
if (nla_put_be32(skb, CTA_STATS_GLOBAL_MAX_ENTRIES, htonl(nf_conntrack_max))) goto nla_put_failure; |
392025f87 netfilter: ctnetl... |
2413 2414 2415 2416 2417 2418 2419 2420 |
nlmsg_end(skb, nlh); return skb->len; nla_put_failure: nlmsg_failure: nlmsg_cancel(skb, nlh); return -1; } |
7b8002a15 netfilter: nfnetl... |
2421 2422 |
static int ctnetlink_stat_ct(struct net *net, struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, |
04ba724b6 netfilter: nfnetl... |
2423 2424 |
const struct nlattr * const cda[], struct netlink_ext_ack *extack) |
392025f87 netfilter: ctnetl... |
2425 2426 2427 2428 2429 2430 2431 |
{ struct sk_buff *skb2; int err; skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (skb2 == NULL) return -ENOMEM; |
15e473046 netlink: Rename p... |
2432 |
err = ctnetlink_stat_ct_fill_info(skb2, NETLINK_CB(skb).portid, |
392025f87 netfilter: ctnetl... |
2433 2434 2435 2436 2437 |
nlh->nlmsg_seq, NFNL_MSG_TYPE(nlh->nlmsg_type), sock_net(skb->sk)); if (err <= 0) goto free; |
15e473046 netlink: Rename p... |
2438 |
err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT); |
392025f87 netfilter: ctnetl... |
2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 |
if (err < 0) goto out; return 0; free: kfree_skb(skb2); out: /* this avoids a loop in nfnetlink. */ return err == -EAGAIN ? -ENOBUFS : err; } |
bd0779370 netfilter: nfnetl... |
2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 |
static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = { [CTA_EXPECT_MASTER] = { .type = NLA_NESTED }, [CTA_EXPECT_TUPLE] = { .type = NLA_NESTED }, [CTA_EXPECT_MASK] = { .type = NLA_NESTED }, [CTA_EXPECT_TIMEOUT] = { .type = NLA_U32 }, [CTA_EXPECT_ID] = { .type = NLA_U32 }, [CTA_EXPECT_HELP_NAME] = { .type = NLA_NUL_STRING, .len = NF_CT_HELPER_NAME_LEN - 1 }, [CTA_EXPECT_ZONE] = { .type = NLA_U16 }, [CTA_EXPECT_FLAGS] = { .type = NLA_U32 }, [CTA_EXPECT_CLASS] = { .type = NLA_U32 }, [CTA_EXPECT_NAT] = { .type = NLA_NESTED }, [CTA_EXPECT_FN] = { .type = NLA_NUL_STRING }, }; static struct nf_conntrack_expect * ctnetlink_alloc_expect(const struct nlattr *const cda[], struct nf_conn *ct, struct nf_conntrack_helper *helper, struct nf_conntrack_tuple *tuple, struct nf_conntrack_tuple *mask); |
83f3e94d3 netfilter: Kconfi... |
2470 |
#ifdef CONFIG_NETFILTER_NETLINK_GLUE_CT |
9cb017665 netfilter: add gl... |
2471 |
static size_t |
a4b4766c3 netfilter: nfnetl... |
2472 |
ctnetlink_glue_build_size(const struct nf_conn *ct) |
9cb017665 netfilter: add gl... |
2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 |
{ return 3 * nla_total_size(0) /* CTA_TUPLE_ORIG|REPL|MASTER */ + 3 * nla_total_size(0) /* CTA_TUPLE_IP */ + 3 * nla_total_size(0) /* CTA_TUPLE_PROTO */ + 3 * nla_total_size(sizeof(u_int8_t)) /* CTA_PROTO_NUM */ + nla_total_size(sizeof(u_int32_t)) /* CTA_ID */ + nla_total_size(sizeof(u_int32_t)) /* CTA_STATUS */ + nla_total_size(sizeof(u_int32_t)) /* CTA_TIMEOUT */ + nla_total_size(0) /* CTA_PROTOINFO */ + nla_total_size(0) /* CTA_HELP */ + nla_total_size(NF_CT_HELPER_NAME_LEN) /* CTA_HELP_NAME */ + ctnetlink_secctx_size(ct) |
4806e9757 netfilter: replac... |
2485 |
#if IS_ENABLED(CONFIG_NF_NAT) |
9cb017665 netfilter: add gl... |
2486 2487 2488 2489 2490 2491 |
+ 2 * nla_total_size(0) /* CTA_NAT_SEQ_ADJ_ORIG|REPL */ + 6 * nla_total_size(sizeof(u_int32_t)) /* CTA_NAT_SEQ_OFFSET */ #endif #ifdef CONFIG_NF_CONNTRACK_MARK + nla_total_size(sizeof(u_int32_t)) /* CTA_MARK */ #endif |
4a001068d netfilter: ctnetl... |
2492 |
#ifdef CONFIG_NF_CONNTRACK_ZONES |
deedb5903 netfilter: nf_con... |
2493 |
+ nla_total_size(sizeof(u_int16_t)) /* CTA_ZONE|CTA_TUPLE_ZONE */ |
4a001068d netfilter: ctnetl... |
2494 |
#endif |
9cb017665 netfilter: add gl... |
2495 2496 2497 |
+ ctnetlink_proto_size(ct) ; } |
224a05975 netfilter: ctnetl... |
2498 |
static struct nf_conn *ctnetlink_glue_get_ct(const struct sk_buff *skb, |
a4b4766c3 netfilter: nfnetl... |
2499 |
enum ip_conntrack_info *ctinfo) |
b7bd1809e netfilter: nfnetl... |
2500 |
{ |
ab8bc7ed8 netfilter: remove... |
2501 |
return nf_ct_get(skb, ctinfo); |
b7bd1809e netfilter: nfnetl... |
2502 |
} |
a4b4766c3 netfilter: nfnetl... |
2503 |
static int __ctnetlink_glue_build(struct sk_buff *skb, struct nf_conn *ct) |
9cb017665 netfilter: add gl... |
2504 |
{ |
308ac9143 netfilter: nf_con... |
2505 |
const struct nf_conntrack_zone *zone; |
9cb017665 netfilter: add gl... |
2506 |
struct nlattr *nest_parms; |
deedb5903 netfilter: nf_con... |
2507 |
zone = nf_ct_zone(ct); |
ae0be8de9 netlink: make nla... |
2508 |
nest_parms = nla_nest_start(skb, CTA_TUPLE_ORIG); |
9cb017665 netfilter: add gl... |
2509 2510 2511 2512 |
if (!nest_parms) goto nla_put_failure; if (ctnetlink_dump_tuples(skb, nf_ct_tuple(ct, IP_CT_DIR_ORIGINAL)) < 0) goto nla_put_failure; |
deedb5903 netfilter: nf_con... |
2513 2514 2515 |
if (ctnetlink_dump_zone_id(skb, CTA_TUPLE_ZONE, zone, NF_CT_ZONE_DIR_ORIG) < 0) goto nla_put_failure; |
9cb017665 netfilter: add gl... |
2516 |
nla_nest_end(skb, nest_parms); |
ae0be8de9 netlink: make nla... |
2517 |
nest_parms = nla_nest_start(skb, CTA_TUPLE_REPLY); |
9cb017665 netfilter: add gl... |
2518 2519 2520 2521 |
if (!nest_parms) goto nla_put_failure; if (ctnetlink_dump_tuples(skb, nf_ct_tuple(ct, IP_CT_DIR_REPLY)) < 0) goto nla_put_failure; |
deedb5903 netfilter: nf_con... |
2522 2523 2524 |
if (ctnetlink_dump_zone_id(skb, CTA_TUPLE_ZONE, zone, NF_CT_ZONE_DIR_REPL) < 0) goto nla_put_failure; |
9cb017665 netfilter: add gl... |
2525 |
nla_nest_end(skb, nest_parms); |
deedb5903 netfilter: nf_con... |
2526 2527 |
if (ctnetlink_dump_zone_id(skb, CTA_ZONE, zone, NF_CT_DEFAULT_ZONE_DIR) < 0) |
308ac9143 netfilter: nf_con... |
2528 |
goto nla_put_failure; |
9cb017665 netfilter: add gl... |
2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 |
if (ctnetlink_dump_id(skb, ct) < 0) goto nla_put_failure; if (ctnetlink_dump_status(skb, ct) < 0) goto nla_put_failure; if (ctnetlink_dump_timeout(skb, ct) < 0) goto nla_put_failure; if (ctnetlink_dump_protoinfo(skb, ct) < 0) goto nla_put_failure; if (ctnetlink_dump_helpinfo(skb, ct) < 0) goto nla_put_failure; #ifdef CONFIG_NF_CONNTRACK_SECMARK if (ct->secmark && ctnetlink_dump_secctx(skb, ct) < 0) goto nla_put_failure; #endif if (ct->master && ctnetlink_dump_master(skb, ct) < 0) goto nla_put_failure; if ((ct->status & IPS_SEQ_ADJUST) && |
41d73ec05 netfilter: nf_con... |
2553 |
ctnetlink_dump_ct_seq_adj(skb, ct) < 0) |
9cb017665 netfilter: add gl... |
2554 |
goto nla_put_failure; |
20710b3b8 netfilter: ctnetl... |
2555 2556 |
if (ctnetlink_dump_ct_synproxy(skb, ct) < 0) goto nla_put_failure; |
9cb017665 netfilter: add gl... |
2557 2558 2559 2560 |
#ifdef CONFIG_NF_CONNTRACK_MARK if (ct->mark && ctnetlink_dump_mark(skb, ct) < 0) goto nla_put_failure; #endif |
0ceabd838 netfilter: ctnetl... |
2561 2562 |
if (ctnetlink_dump_labels(skb, ct) < 0) goto nla_put_failure; |
9cb017665 netfilter: add gl... |
2563 2564 2565 |
return 0; nla_put_failure: |
9cb017665 netfilter: add gl... |
2566 2567 2568 2569 |
return -ENOSPC; } static int |
a4b4766c3 netfilter: nfnetl... |
2570 2571 2572 |
ctnetlink_glue_build(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info ctinfo, u_int16_t ct_attr, u_int16_t ct_info_attr) |
b7bd1809e netfilter: nfnetl... |
2573 2574 |
{ struct nlattr *nest_parms; |
ae0be8de9 netlink: make nla... |
2575 |
nest_parms = nla_nest_start(skb, ct_attr); |
b7bd1809e netfilter: nfnetl... |
2576 2577 |
if (!nest_parms) goto nla_put_failure; |
a4b4766c3 netfilter: nfnetl... |
2578 |
if (__ctnetlink_glue_build(skb, ct) < 0) |
b7bd1809e netfilter: nfnetl... |
2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 |
goto nla_put_failure; nla_nest_end(skb, nest_parms); if (nla_put_be32(skb, ct_info_attr, htonl(ctinfo))) goto nla_put_failure; return 0; nla_put_failure: return -ENOSPC; } static int |
a963d710f netfilter: ctnetl... |
2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 |
ctnetlink_update_status(struct nf_conn *ct, const struct nlattr * const cda[]) { unsigned int status = ntohl(nla_get_be32(cda[CTA_STATUS])); unsigned long d = ct->status ^ status; if (d & IPS_SEEN_REPLY && !(status & IPS_SEEN_REPLY)) /* SEEN_REPLY bit can only be set */ return -EBUSY; if (d & IPS_ASSURED && !(status & IPS_ASSURED)) /* ASSURED bit can only be set */ return -EBUSY; /* This check is less strict than ctnetlink_change_status() * because callers often flip IPS_EXPECTED bits when sending * an NFQA_CT attribute to the kernel. So ignore the |
53b56da83 netfilter: ctnetl... |
2609 2610 |
* unchangeable bits but do not error out. Also user programs * are allowed to clear the bits that they are allowed to change. |
a963d710f netfilter: ctnetl... |
2611 |
*/ |
53b56da83 netfilter: ctnetl... |
2612 |
__ctnetlink_change_status(ct, status, ~status); |
a963d710f netfilter: ctnetl... |
2613 2614 2615 2616 |
return 0; } static int |
a4b4766c3 netfilter: nfnetl... |
2617 |
ctnetlink_glue_parse_ct(const struct nlattr *cda[], struct nf_conn *ct) |
9cb017665 netfilter: add gl... |
2618 2619 2620 2621 2622 2623 2624 2625 2626 |
{ int err; if (cda[CTA_TIMEOUT]) { err = ctnetlink_change_timeout(ct, cda); if (err < 0) return err; } if (cda[CTA_STATUS]) { |
a963d710f netfilter: ctnetl... |
2627 |
err = ctnetlink_update_status(ct, cda); |
9cb017665 netfilter: add gl... |
2628 2629 2630 2631 2632 2633 2634 2635 |
if (err < 0) return err; } if (cda[CTA_HELP]) { err = ctnetlink_change_helper(ct, cda); if (err < 0) return err; } |
9b21f6a90 netfilter: ctnetl... |
2636 2637 2638 2639 2640 |
if (cda[CTA_LABELS]) { err = ctnetlink_attach_labels(ct, cda); if (err < 0) return err; } |
9cb017665 netfilter: add gl... |
2641 |
#if defined(CONFIG_NF_CONNTRACK_MARK) |
534473c60 netfilter: ctnetl... |
2642 |
if (cda[CTA_MARK]) { |
58fc419be netfilter: ctnetl... |
2643 |
ctnetlink_change_mark(ct, cda); |
534473c60 netfilter: ctnetl... |
2644 |
} |
9cb017665 netfilter: add gl... |
2645 2646 2647 2648 2649 |
#endif return 0; } static int |
a4b4766c3 netfilter: nfnetl... |
2650 |
ctnetlink_glue_parse(const struct nlattr *attr, struct nf_conn *ct) |
9cb017665 netfilter: add gl... |
2651 2652 |
{ struct nlattr *cda[CTA_MAX+1]; |
68e035c95 netfilter: ctnetl... |
2653 |
int ret; |
9cb017665 netfilter: add gl... |
2654 |
|
8cb081746 netlink: make val... |
2655 2656 |
ret = nla_parse_nested_deprecated(cda, CTA_MAX, attr, ct_nla_policy, NULL); |
130ffbc26 netfilter: check ... |
2657 2658 |
if (ret < 0) return ret; |
9cb017665 netfilter: add gl... |
2659 |
|
88be4c09d netfilter: ctnetl... |
2660 |
return ctnetlink_glue_parse_ct((const struct nlattr **)cda, ct); |
9cb017665 netfilter: add gl... |
2661 |
} |
a4b4766c3 netfilter: nfnetl... |
2662 2663 2664 2665 |
static int ctnetlink_glue_exp_parse(const struct nlattr * const *cda, const struct nf_conn *ct, struct nf_conntrack_tuple *tuple, struct nf_conntrack_tuple *mask) |
bd0779370 netfilter: nfnetl... |
2666 2667 2668 2669 |
{ int err; err = ctnetlink_parse_tuple(cda, tuple, CTA_EXPECT_TUPLE, |
deedb5903 netfilter: nf_con... |
2670 |
nf_ct_l3num(ct), NULL); |
bd0779370 netfilter: nfnetl... |
2671 2672 2673 2674 |
if (err < 0) return err; return ctnetlink_parse_tuple(cda, mask, CTA_EXPECT_MASK, |
deedb5903 netfilter: nf_con... |
2675 |
nf_ct_l3num(ct), NULL); |
bd0779370 netfilter: nfnetl... |
2676 2677 2678 |
} static int |
a4b4766c3 netfilter: nfnetl... |
2679 2680 |
ctnetlink_glue_attach_expect(const struct nlattr *attr, struct nf_conn *ct, u32 portid, u32 report) |
bd0779370 netfilter: nfnetl... |
2681 2682 2683 |
{ struct nlattr *cda[CTA_EXPECT_MAX+1]; struct nf_conntrack_tuple tuple, mask; |
b7e092c05 netfilter: ctnetl... |
2684 |
struct nf_conntrack_helper *helper = NULL; |
bd0779370 netfilter: nfnetl... |
2685 2686 |
struct nf_conntrack_expect *exp; int err; |
8cb081746 netlink: make val... |
2687 2688 |
err = nla_parse_nested_deprecated(cda, CTA_EXPECT_MAX, attr, exp_nla_policy, NULL); |
bd0779370 netfilter: nfnetl... |
2689 2690 |
if (err < 0) return err; |
a4b4766c3 netfilter: nfnetl... |
2691 2692 |
err = ctnetlink_glue_exp_parse((const struct nlattr * const *)cda, ct, &tuple, &mask); |
bd0779370 netfilter: nfnetl... |
2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 |
if (err < 0) return err; if (cda[CTA_EXPECT_HELP_NAME]) { const char *helpname = nla_data(cda[CTA_EXPECT_HELP_NAME]); helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct), nf_ct_protonum(ct)); if (helper == NULL) return -EOPNOTSUPP; } exp = ctnetlink_alloc_expect((const struct nlattr * const *)cda, ct, helper, &tuple, &mask); if (IS_ERR(exp)) return PTR_ERR(exp); |
3c00fb0bf netfilter: nf_con... |
2709 |
err = nf_ct_expect_related_report(exp, portid, report, 0); |
b18bcb001 netfilter: nfnetl... |
2710 2711 |
nf_ct_expect_put(exp); return err; |
bd0779370 netfilter: nfnetl... |
2712 |
} |
a4b4766c3 netfilter: nfnetl... |
2713 2714 |
static void ctnetlink_glue_seqadj(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info ctinfo, int diff) |
b7bd1809e netfilter: nfnetl... |
2715 2716 2717 2718 2719 2720 |
{ if (!(ct->status & IPS_NAT_MASK)) return; nf_ct_tcp_seqadj_set(skb, ct, ctinfo, diff); } |
a4b4766c3 netfilter: nfnetl... |
2721 2722 2723 2724 2725 2726 2727 |
static struct nfnl_ct_hook ctnetlink_glue_hook = { .get_ct = ctnetlink_glue_get_ct, .build_size = ctnetlink_glue_build_size, .build = ctnetlink_glue_build, .parse = ctnetlink_glue_parse, .attach_expect = ctnetlink_glue_attach_expect, .seq_adjust = ctnetlink_glue_seqadj, |
9cb017665 netfilter: add gl... |
2728 |
}; |
83f3e94d3 netfilter: Kconfi... |
2729 |
#endif /* CONFIG_NETFILTER_NETLINK_GLUE_CT */ |
9cb017665 netfilter: add gl... |
2730 |
|
601e68e10 [NETFILTER]: Fix ... |
2731 2732 2733 |
/*********************************************************************** * EXPECT ***********************************************************************/ |
c1d10adb4 [NETFILTER]: Add ... |
2734 |
|
4054ff454 netfilter: ctnetl... |
2735 2736 |
static int ctnetlink_exp_dump_tuple(struct sk_buff *skb, const struct nf_conntrack_tuple *tuple, |
a2b7cbdd2 netfilter: ctnetl... |
2737 |
u32 type) |
c1d10adb4 [NETFILTER]: Add ... |
2738 |
{ |
df6fb868d [NETFILTER]: nfne... |
2739 |
struct nlattr *nest_parms; |
601e68e10 [NETFILTER]: Fix ... |
2740 |
|
ae0be8de9 netlink: make nla... |
2741 |
nest_parms = nla_nest_start(skb, type); |
df6fb868d [NETFILTER]: nfne... |
2742 2743 |
if (!nest_parms) goto nla_put_failure; |
c1d10adb4 [NETFILTER]: Add ... |
2744 |
if (ctnetlink_dump_tuples(skb, tuple) < 0) |
df6fb868d [NETFILTER]: nfne... |
2745 2746 |
goto nla_put_failure; nla_nest_end(skb, nest_parms); |
c1d10adb4 [NETFILTER]: Add ... |
2747 2748 |
return 0; |
df6fb868d [NETFILTER]: nfne... |
2749 |
nla_put_failure: |
c1d10adb4 [NETFILTER]: Add ... |
2750 |
return -1; |
601e68e10 [NETFILTER]: Fix ... |
2751 |
} |
c1d10adb4 [NETFILTER]: Add ... |
2752 |
|
4054ff454 netfilter: ctnetl... |
2753 2754 2755 |
static int ctnetlink_exp_dump_mask(struct sk_buff *skb, const struct nf_conntrack_tuple *tuple, const struct nf_conntrack_tuple_mask *mask) |
1cde64365 [NETFILTER]: ctne... |
2756 |
{ |
b3480fe05 netfilter: conntr... |
2757 |
const struct nf_conntrack_l4proto *l4proto; |
d4156e8cd [NETFILTER]: nf_c... |
2758 |
struct nf_conntrack_tuple m; |
df6fb868d [NETFILTER]: nfne... |
2759 |
struct nlattr *nest_parms; |
b3480fe05 netfilter: conntr... |
2760 |
int ret; |
d4156e8cd [NETFILTER]: nf_c... |
2761 2762 |
memset(&m, 0xFF, sizeof(m)); |
d4156e8cd [NETFILTER]: nf_c... |
2763 |
memcpy(&m.src.u3, &mask->src.u3, sizeof(m.src.u3)); |
e578756c3 netfilter: ctnetl... |
2764 2765 |
m.src.u.all = mask->src.u.all; m.dst.protonum = tuple->dst.protonum; |
d4156e8cd [NETFILTER]: nf_c... |
2766 |
|
ae0be8de9 netlink: make nla... |
2767 |
nest_parms = nla_nest_start(skb, CTA_EXPECT_MASK); |
df6fb868d [NETFILTER]: nfne... |
2768 2769 |
if (!nest_parms) goto nla_put_failure; |
1cde64365 [NETFILTER]: ctne... |
2770 |
|
3b988ece9 netfilter: ctnetl... |
2771 |
rcu_read_lock(); |
f957be9d3 netfilter: conntr... |
2772 |
ret = ctnetlink_dump_tuples_ip(skb, &m); |
3b988ece9 netfilter: ctnetl... |
2773 |
if (ret >= 0) { |
4a60dc748 netfilter: conntr... |
2774 |
l4proto = nf_ct_l4proto_find(tuple->dst.protonum); |
48ab807c7 netfilter: conntr... |
2775 |
ret = ctnetlink_dump_tuples_proto(skb, &m, l4proto); |
3b988ece9 netfilter: ctnetl... |
2776 2777 |
} rcu_read_unlock(); |
1cde64365 [NETFILTER]: ctne... |
2778 |
if (unlikely(ret < 0)) |
df6fb868d [NETFILTER]: nfne... |
2779 |
goto nla_put_failure; |
1cde64365 [NETFILTER]: ctne... |
2780 |
|
df6fb868d [NETFILTER]: nfne... |
2781 |
nla_nest_end(skb, nest_parms); |
1cde64365 [NETFILTER]: ctne... |
2782 2783 |
return 0; |
df6fb868d [NETFILTER]: nfne... |
2784 |
nla_put_failure: |
1cde64365 [NETFILTER]: ctne... |
2785 2786 |
return -1; } |
c7232c997 netfilter: add pr... |
2787 |
static const union nf_inet_addr any_addr; |
3c7910763 netfilter: ctnetl... |
2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 |
static __be32 nf_expect_get_id(const struct nf_conntrack_expect *exp) { static __read_mostly siphash_key_t exp_id_seed; unsigned long a, b, c, d; net_get_random_once(&exp_id_seed, sizeof(exp_id_seed)); a = (unsigned long)exp; b = (unsigned long)exp->helper; c = (unsigned long)exp->master; d = (unsigned long)siphash(&exp->tuple, sizeof(exp->tuple), &exp_id_seed); #ifdef CONFIG_64BIT return (__force __be32)siphash_4u64((u64)a, (u64)b, (u64)c, (u64)d, &exp_id_seed); #else return (__force __be32)siphash_4u32((u32)a, (u32)b, (u32)c, (u32)d, &exp_id_seed); #endif } |
bb5cf80e9 [NETFILTER]: Kill... |
2806 |
static int |
c1d10adb4 [NETFILTER]: Add ... |
2807 |
ctnetlink_exp_dump_expect(struct sk_buff *skb, |
601e68e10 [NETFILTER]: Fix ... |
2808 |
const struct nf_conntrack_expect *exp) |
c1d10adb4 [NETFILTER]: Add ... |
2809 2810 |
{ struct nf_conn *master = exp->master; |
c12163827 netfilter: ctnetl... |
2811 |
long timeout = ((long)exp->timeout.expires - (long)jiffies) / HZ; |
bc01befdc netfilter: ctnetl... |
2812 |
struct nf_conn_help *help; |
4806e9757 netfilter: replac... |
2813 |
#if IS_ENABLED(CONFIG_NF_NAT) |
076a0ca02 netfilter: ctnetl... |
2814 2815 2816 |
struct nlattr *nest_parms; struct nf_conntrack_tuple nat_tuple = {}; #endif |
544d5c7d9 netfilter: ctnetl... |
2817 |
struct nf_ct_helper_expectfn *expfn; |
d978e5dae [NETFILTER]: ctne... |
2818 2819 |
if (timeout < 0) timeout = 0; |
c1d10adb4 [NETFILTER]: Add ... |
2820 2821 |
if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0) |
df6fb868d [NETFILTER]: nfne... |
2822 |
goto nla_put_failure; |
1cde64365 [NETFILTER]: ctne... |
2823 |
if (ctnetlink_exp_dump_mask(skb, &exp->tuple, &exp->mask) < 0) |
df6fb868d [NETFILTER]: nfne... |
2824 |
goto nla_put_failure; |
c1d10adb4 [NETFILTER]: Add ... |
2825 2826 2827 |
if (ctnetlink_exp_dump_tuple(skb, &master->tuplehash[IP_CT_DIR_ORIGINAL].tuple, CTA_EXPECT_MASTER) < 0) |
df6fb868d [NETFILTER]: nfne... |
2828 |
goto nla_put_failure; |
601e68e10 [NETFILTER]: Fix ... |
2829 |
|
4806e9757 netfilter: replac... |
2830 |
#if IS_ENABLED(CONFIG_NF_NAT) |
c7232c997 netfilter: add pr... |
2831 2832 |
if (!nf_inet_addr_cmp(&exp->saved_addr, &any_addr) || exp->saved_proto.all) { |
ae0be8de9 netlink: make nla... |
2833 |
nest_parms = nla_nest_start(skb, CTA_EXPECT_NAT); |
076a0ca02 netfilter: ctnetl... |
2834 2835 |
if (!nest_parms) goto nla_put_failure; |
cc1eb4313 nf_conntrack_netl... |
2836 2837 |
if (nla_put_be32(skb, CTA_EXPECT_NAT_DIR, htonl(exp->dir))) goto nla_put_failure; |
076a0ca02 netfilter: ctnetl... |
2838 2839 |
nat_tuple.src.l3num = nf_ct_l3num(master); |
c7232c997 netfilter: add pr... |
2840 |
nat_tuple.src.u3 = exp->saved_addr; |
076a0ca02 netfilter: ctnetl... |
2841 2842 2843 2844 2845 2846 2847 2848 2849 |
nat_tuple.dst.protonum = nf_ct_protonum(master); nat_tuple.src.u = exp->saved_proto; if (ctnetlink_exp_dump_tuple(skb, &nat_tuple, CTA_EXPECT_NAT_TUPLE) < 0) goto nla_put_failure; nla_nest_end(skb, nest_parms); } #endif |
cc1eb4313 nf_conntrack_netl... |
2850 |
if (nla_put_be32(skb, CTA_EXPECT_TIMEOUT, htonl(timeout)) || |
3c7910763 netfilter: ctnetl... |
2851 |
nla_put_be32(skb, CTA_EXPECT_ID, nf_expect_get_id(exp)) || |
cc1eb4313 nf_conntrack_netl... |
2852 2853 2854 |
nla_put_be32(skb, CTA_EXPECT_FLAGS, htonl(exp->flags)) || nla_put_be32(skb, CTA_EXPECT_CLASS, htonl(exp->class))) goto nla_put_failure; |
bc01befdc netfilter: ctnetl... |
2855 2856 2857 2858 2859 |
help = nfct_help(master); if (help) { struct nf_conntrack_helper *helper; helper = rcu_dereference(help->helper); |
cc1eb4313 nf_conntrack_netl... |
2860 2861 2862 |
if (helper && nla_put_string(skb, CTA_EXPECT_HELP_NAME, helper->name)) goto nla_put_failure; |
bc01befdc netfilter: ctnetl... |
2863 |
} |
544d5c7d9 netfilter: ctnetl... |
2864 |
expfn = nf_ct_helper_expectfn_find_by_symbol(exp->expectfn); |
cc1eb4313 nf_conntrack_netl... |
2865 2866 2867 |
if (expfn != NULL && nla_put_string(skb, CTA_EXPECT_FN, expfn->name)) goto nla_put_failure; |
c1d10adb4 [NETFILTER]: Add ... |
2868 2869 |
return 0; |
601e68e10 [NETFILTER]: Fix ... |
2870 |
|
df6fb868d [NETFILTER]: nfne... |
2871 |
nla_put_failure: |
c1d10adb4 [NETFILTER]: Add ... |
2872 2873 2874 2875 |
return -1; } static int |
15e473046 netlink: Rename p... |
2876 |
ctnetlink_exp_fill_info(struct sk_buff *skb, u32 portid, u32 seq, |
8b0a231d4 netfilter: ctnetl... |
2877 |
int event, const struct nf_conntrack_expect *exp) |
c1d10adb4 [NETFILTER]: Add ... |
2878 2879 2880 |
{ struct nlmsghdr *nlh; struct nfgenmsg *nfmsg; |
15e473046 netlink: Rename p... |
2881 |
unsigned int flags = portid ? NLM_F_MULTI : 0; |
c1d10adb4 [NETFILTER]: Add ... |
2882 |
|
dedb67c4b netfilter: Add nf... |
2883 |
event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK_EXP, event); |
15e473046 netlink: Rename p... |
2884 |
nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags); |
96bcf938d netfilter: ctnetl... |
2885 2886 |
if (nlh == NULL) goto nlmsg_failure; |
c1d10adb4 [NETFILTER]: Add ... |
2887 |
|
96bcf938d netfilter: ctnetl... |
2888 |
nfmsg = nlmsg_data(nlh); |
c1d10adb4 [NETFILTER]: Add ... |
2889 2890 2891 2892 2893 |
nfmsg->nfgen_family = exp->tuple.src.l3num; nfmsg->version = NFNETLINK_V0; nfmsg->res_id = 0; if (ctnetlink_exp_dump_expect(skb, exp) < 0) |
df6fb868d [NETFILTER]: nfne... |
2894 |
goto nla_put_failure; |
c1d10adb4 [NETFILTER]: Add ... |
2895 |
|
96bcf938d netfilter: ctnetl... |
2896 |
nlmsg_end(skb, nlh); |
c1d10adb4 [NETFILTER]: Add ... |
2897 2898 2899 |
return skb->len; nlmsg_failure: |
df6fb868d [NETFILTER]: nfne... |
2900 |
nla_put_failure: |
96bcf938d netfilter: ctnetl... |
2901 |
nlmsg_cancel(skb, nlh); |
c1d10adb4 [NETFILTER]: Add ... |
2902 2903 2904 2905 |
return -1; } #ifdef CONFIG_NF_CONNTRACK_EVENTS |
e34d5c1a4 netfilter: conntr... |
2906 2907 |
static int ctnetlink_expect_event(unsigned int events, struct nf_exp_event *item) |
c1d10adb4 [NETFILTER]: Add ... |
2908 |
{ |
9592a5c01 netfilter: ctnetl... |
2909 2910 |
struct nf_conntrack_expect *exp = item->exp; struct net *net = nf_ct_exp_net(exp); |
c1d10adb4 [NETFILTER]: Add ... |
2911 2912 |
struct nlmsghdr *nlh; struct nfgenmsg *nfmsg; |
c1d10adb4 [NETFILTER]: Add ... |
2913 |
struct sk_buff *skb; |
ebbf41df4 netfilter: ctnetl... |
2914 |
unsigned int type, group; |
c1d10adb4 [NETFILTER]: Add ... |
2915 |
int flags = 0; |
ebbf41df4 netfilter: ctnetl... |
2916 2917 2918 2919 |
if (events & (1 << IPEXP_DESTROY)) { type = IPCTNL_MSG_EXP_DELETE; group = NFNLGRP_CONNTRACK_EXP_DESTROY; } else if (events & (1 << IPEXP_NEW)) { |
c1d10adb4 [NETFILTER]: Add ... |
2920 2921 |
type = IPCTNL_MSG_EXP_NEW; flags = NLM_F_CREATE|NLM_F_EXCL; |
ebbf41df4 netfilter: ctnetl... |
2922 |
group = NFNLGRP_CONNTRACK_EXP_NEW; |
c1d10adb4 [NETFILTER]: Add ... |
2923 |
} else |
e34d5c1a4 netfilter: conntr... |
2924 |
return 0; |
c1d10adb4 [NETFILTER]: Add ... |
2925 |
|
ebbf41df4 netfilter: ctnetl... |
2926 |
if (!item->report && !nfnetlink_has_listeners(net, group)) |
e34d5c1a4 netfilter: conntr... |
2927 |
return 0; |
b3a27bfba [NETFILTER]: ctne... |
2928 |
|
96bcf938d netfilter: ctnetl... |
2929 2930 |
skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); if (skb == NULL) |
150ace0db netfilter: ctnetl... |
2931 |
goto errout; |
c1d10adb4 [NETFILTER]: Add ... |
2932 |
|
dedb67c4b netfilter: Add nf... |
2933 |
type = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK_EXP, type); |
15e473046 netlink: Rename p... |
2934 |
nlh = nlmsg_put(skb, item->portid, 0, type, sizeof(*nfmsg), flags); |
96bcf938d netfilter: ctnetl... |
2935 2936 |
if (nlh == NULL) goto nlmsg_failure; |
c1d10adb4 [NETFILTER]: Add ... |
2937 |
|
96bcf938d netfilter: ctnetl... |
2938 |
nfmsg = nlmsg_data(nlh); |
c1d10adb4 [NETFILTER]: Add ... |
2939 2940 2941 2942 2943 |
nfmsg->nfgen_family = exp->tuple.src.l3num; nfmsg->version = NFNETLINK_V0; nfmsg->res_id = 0; if (ctnetlink_exp_dump_expect(skb, exp) < 0) |
df6fb868d [NETFILTER]: nfne... |
2944 |
goto nla_put_failure; |
c1d10adb4 [NETFILTER]: Add ... |
2945 |
|
96bcf938d netfilter: ctnetl... |
2946 |
nlmsg_end(skb, nlh); |
15e473046 netlink: Rename p... |
2947 |
nfnetlink_send(skb, net, item->portid, group, item->report, GFP_ATOMIC); |
e34d5c1a4 netfilter: conntr... |
2948 |
return 0; |
c1d10adb4 [NETFILTER]: Add ... |
2949 |
|
df6fb868d [NETFILTER]: nfne... |
2950 |
nla_put_failure: |
96bcf938d netfilter: ctnetl... |
2951 |
nlmsg_cancel(skb, nlh); |
528a3a6f6 netfilter: ctnetl... |
2952 |
nlmsg_failure: |
c1d10adb4 [NETFILTER]: Add ... |
2953 |
kfree_skb(skb); |
150ace0db netfilter: ctnetl... |
2954 |
errout: |
9592a5c01 netfilter: ctnetl... |
2955 |
nfnetlink_set_err(net, 0, 0, -ENOBUFS); |
e34d5c1a4 netfilter: conntr... |
2956 |
return 0; |
c1d10adb4 [NETFILTER]: Add ... |
2957 2958 |
} #endif |
cf6994c2b [NETFILTER]: nf_c... |
2959 2960 |
static int ctnetlink_exp_done(struct netlink_callback *cb) { |
31f15875c [NETFILTER]: nf_c... |
2961 2962 |
if (cb->args[1]) nf_ct_expect_put((struct nf_conntrack_expect *)cb->args[1]); |
cf6994c2b [NETFILTER]: nf_c... |
2963 2964 |
return 0; } |
c1d10adb4 [NETFILTER]: Add ... |
2965 2966 2967 2968 |
static int ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb) { |
9592a5c01 netfilter: ctnetl... |
2969 |
struct net *net = sock_net(skb->sk); |
cf6994c2b [NETFILTER]: nf_c... |
2970 |
struct nf_conntrack_expect *exp, *last; |
96bcf938d netfilter: ctnetl... |
2971 |
struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); |
87711cb81 [NETFILTER]: Filt... |
2972 |
u_int8_t l3proto = nfmsg->nfgen_family; |
c1d10adb4 [NETFILTER]: Add ... |
2973 |
|
7d0742da1 [NETFILTER]: nf_c... |
2974 |
rcu_read_lock(); |
31f15875c [NETFILTER]: nf_c... |
2975 2976 |
last = (struct nf_conntrack_expect *)cb->args[1]; for (; cb->args[0] < nf_ct_expect_hsize; cb->args[0]++) { |
cf6994c2b [NETFILTER]: nf_c... |
2977 |
restart: |
7cddd967b netfilter: nf_ct_... |
2978 2979 |
hlist_for_each_entry_rcu(exp, &nf_ct_expect_hash[cb->args[0]], hnode) { |
31f15875c [NETFILTER]: nf_c... |
2980 |
if (l3proto && exp->tuple.src.l3num != l3proto) |
cf6994c2b [NETFILTER]: nf_c... |
2981 |
continue; |
03d7dc5cd netfilter: conntr... |
2982 2983 2984 |
if (!net_eq(nf_ct_net(exp->master), net)) continue; |
31f15875c [NETFILTER]: nf_c... |
2985 2986 2987 2988 2989 |
if (cb->args[1]) { if (exp != last) continue; cb->args[1] = 0; } |
8b0a231d4 netfilter: ctnetl... |
2990 |
if (ctnetlink_exp_fill_info(skb, |
15e473046 netlink: Rename p... |
2991 |
NETLINK_CB(cb->skb).portid, |
31f15875c [NETFILTER]: nf_c... |
2992 2993 |
cb->nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW, |
8b0a231d4 netfilter: ctnetl... |
2994 |
exp) < 0) { |
b54ab92b8 netfilter: refcou... |
2995 |
if (!refcount_inc_not_zero(&exp->use)) |
7d0742da1 [NETFILTER]: nf_c... |
2996 |
continue; |
31f15875c [NETFILTER]: nf_c... |
2997 2998 2999 |
cb->args[1] = (unsigned long)exp; goto out; } |
cf6994c2b [NETFILTER]: nf_c... |
3000 |
} |
31f15875c [NETFILTER]: nf_c... |
3001 3002 3003 |
if (cb->args[1]) { cb->args[1] = 0; goto restart; |
cf6994c2b [NETFILTER]: nf_c... |
3004 3005 |
} } |
601e68e10 [NETFILTER]: Fix ... |
3006 |
out: |
7d0742da1 [NETFILTER]: nf_c... |
3007 |
rcu_read_unlock(); |
cf6994c2b [NETFILTER]: nf_c... |
3008 3009 |
if (last) nf_ct_expect_put(last); |
c1d10adb4 [NETFILTER]: Add ... |
3010 |
|
c1d10adb4 [NETFILTER]: Add ... |
3011 3012 |
return skb->len; } |
e844a9284 netfilter: ctnetl... |
3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 |
static int ctnetlink_exp_ct_dump_table(struct sk_buff *skb, struct netlink_callback *cb) { struct nf_conntrack_expect *exp, *last; struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); struct nf_conn *ct = cb->data; struct nf_conn_help *help = nfct_help(ct); u_int8_t l3proto = nfmsg->nfgen_family; if (cb->args[0]) return 0; rcu_read_lock(); last = (struct nf_conntrack_expect *)cb->args[1]; restart: |
7cddd967b netfilter: nf_ct_... |
3028 |
hlist_for_each_entry_rcu(exp, &help->expectations, lnode) { |
e844a9284 netfilter: ctnetl... |
3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 |
if (l3proto && exp->tuple.src.l3num != l3proto) continue; if (cb->args[1]) { if (exp != last) continue; cb->args[1] = 0; } if (ctnetlink_exp_fill_info(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW, exp) < 0) { |
b54ab92b8 netfilter: refcou... |
3040 |
if (!refcount_inc_not_zero(&exp->use)) |
e844a9284 netfilter: ctnetl... |
3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 |
continue; cb->args[1] = (unsigned long)exp; goto out; } } if (cb->args[1]) { cb->args[1] = 0; goto restart; } cb->args[0] = 1; out: rcu_read_unlock(); if (last) nf_ct_expect_put(last); return skb->len; } |
7b8002a15 netfilter: nfnetl... |
3058 3059 |
static int ctnetlink_dump_exp_ct(struct net *net, struct sock *ctnl, struct sk_buff *skb, |
e844a9284 netfilter: ctnetl... |
3060 |
const struct nlmsghdr *nlh, |
04ba724b6 netfilter: nfnetl... |
3061 3062 |
const struct nlattr * const cda[], struct netlink_ext_ack *extack) |
e844a9284 netfilter: ctnetl... |
3063 3064 |
{ int err; |
e844a9284 netfilter: ctnetl... |
3065 3066 3067 3068 3069 |
struct nfgenmsg *nfmsg = nlmsg_data(nlh); u_int8_t u3 = nfmsg->nfgen_family; struct nf_conntrack_tuple tuple; struct nf_conntrack_tuple_hash *h; struct nf_conn *ct; |
308ac9143 netfilter: nf_con... |
3070 |
struct nf_conntrack_zone zone; |
e844a9284 netfilter: ctnetl... |
3071 3072 3073 3074 |
struct netlink_dump_control c = { .dump = ctnetlink_exp_ct_dump_table, .done = ctnetlink_exp_done, }; |
deedb5903 netfilter: nf_con... |
3075 3076 |
err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER, u3, NULL); |
e844a9284 netfilter: ctnetl... |
3077 3078 |
if (err < 0) return err; |
308ac9143 netfilter: nf_con... |
3079 3080 3081 |
err = ctnetlink_parse_zone(cda[CTA_EXPECT_ZONE], &zone); if (err < 0) return err; |
e844a9284 netfilter: ctnetl... |
3082 |
|
308ac9143 netfilter: nf_con... |
3083 |
h = nf_conntrack_find_get(net, &zone, &tuple); |
e844a9284 netfilter: ctnetl... |
3084 3085 3086 3087 |
if (!h) return -ENOENT; ct = nf_ct_tuplehash_to_ctrack(h); |
207df8150 netfilter: ctnetl... |
3088 3089 3090 3091 3092 |
/* No expectation linked to this connection tracking. */ if (!nfct_help(ct)) { nf_ct_put(ct); return 0; } |
e844a9284 netfilter: ctnetl... |
3093 3094 3095 3096 3097 3098 3099 |
c.data = ct; err = netlink_dump_start(ctnl, skb, nlh, &c); nf_ct_put(ct); return err; } |
7b8002a15 netfilter: nfnetl... |
3100 3101 |
static int ctnetlink_get_expect(struct net *net, struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, |
04ba724b6 netfilter: nfnetl... |
3102 3103 |
const struct nlattr * const cda[], struct netlink_ext_ack *extack) |
c1d10adb4 [NETFILTER]: Add ... |
3104 3105 3106 3107 |
{ struct nf_conntrack_tuple tuple; struct nf_conntrack_expect *exp; struct sk_buff *skb2; |
96bcf938d netfilter: ctnetl... |
3108 |
struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
c1d10adb4 [NETFILTER]: Add ... |
3109 |
u_int8_t u3 = nfmsg->nfgen_family; |
308ac9143 netfilter: nf_con... |
3110 |
struct nf_conntrack_zone zone; |
ef00f89f1 netfilter: ctnetl... |
3111 |
int err; |
c1d10adb4 [NETFILTER]: Add ... |
3112 |
|
b8f3ab429 Revert "netlink: ... |
3113 |
if (nlh->nlmsg_flags & NLM_F_DUMP) { |
e844a9284 netfilter: ctnetl... |
3114 |
if (cda[CTA_EXPECT_MASTER]) |
04ba724b6 netfilter: nfnetl... |
3115 3116 |
return ctnetlink_dump_exp_ct(net, ctnl, skb, nlh, cda, extack); |
e844a9284 netfilter: ctnetl... |
3117 3118 3119 3120 3121 3122 3123 |
else { struct netlink_dump_control c = { .dump = ctnetlink_exp_dump_table, .done = ctnetlink_exp_done, }; return netlink_dump_start(ctnl, skb, nlh, &c); } |
c1d10adb4 [NETFILTER]: Add ... |
3124 |
} |
ef00f89f1 netfilter: ctnetl... |
3125 3126 3127 |
err = ctnetlink_parse_zone(cda[CTA_EXPECT_ZONE], &zone); if (err < 0) return err; |
35dba1d7f netfilter: ctnetl... |
3128 |
if (cda[CTA_EXPECT_TUPLE]) |
deedb5903 netfilter: nf_con... |
3129 3130 |
err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE, u3, NULL); |
35dba1d7f netfilter: ctnetl... |
3131 |
else if (cda[CTA_EXPECT_MASTER]) |
deedb5903 netfilter: nf_con... |
3132 3133 |
err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER, u3, NULL); |
c1d10adb4 [NETFILTER]: Add ... |
3134 3135 3136 3137 3138 |
else return -EINVAL; if (err < 0) return err; |
308ac9143 netfilter: nf_con... |
3139 |
exp = nf_ct_expect_find_get(net, &zone, &tuple); |
c1d10adb4 [NETFILTER]: Add ... |
3140 3141 |
if (!exp) return -ENOENT; |
df6fb868d [NETFILTER]: nfne... |
3142 |
if (cda[CTA_EXPECT_ID]) { |
77236b6e3 [NETFILTER]: ctne... |
3143 |
__be32 id = nla_get_be32(cda[CTA_EXPECT_ID]); |
3c7910763 netfilter: ctnetl... |
3144 3145 |
if (id != nf_expect_get_id(exp)) { |
6823645d6 [NETFILTER]: nf_c... |
3146 |
nf_ct_expect_put(exp); |
c1d10adb4 [NETFILTER]: Add ... |
3147 3148 |
return -ENOENT; } |
601e68e10 [NETFILTER]: Fix ... |
3149 |
} |
c1d10adb4 [NETFILTER]: Add ... |
3150 3151 |
err = -ENOMEM; |
96bcf938d netfilter: ctnetl... |
3152 |
skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
81378f728 netfilter: ctnetl... |
3153 3154 |
if (skb2 == NULL) { nf_ct_expect_put(exp); |
c1d10adb4 [NETFILTER]: Add ... |
3155 |
goto out; |
81378f728 netfilter: ctnetl... |
3156 |
} |
4e9b82693 [NETLINK]: Remove... |
3157 |
|
528a3a6f6 netfilter: ctnetl... |
3158 |
rcu_read_lock(); |
15e473046 netlink: Rename p... |
3159 |
err = ctnetlink_exp_fill_info(skb2, NETLINK_CB(skb).portid, |
8b0a231d4 netfilter: ctnetl... |
3160 |
nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW, exp); |
528a3a6f6 netfilter: ctnetl... |
3161 |
rcu_read_unlock(); |
81378f728 netfilter: ctnetl... |
3162 |
nf_ct_expect_put(exp); |
c1d10adb4 [NETFILTER]: Add ... |
3163 3164 |
if (err <= 0) goto free; |
15e473046 netlink: Rename p... |
3165 |
err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT); |
81378f728 netfilter: ctnetl... |
3166 3167 |
if (err < 0) goto out; |
c1d10adb4 [NETFILTER]: Add ... |
3168 |
|
81378f728 netfilter: ctnetl... |
3169 |
return 0; |
c1d10adb4 [NETFILTER]: Add ... |
3170 3171 3172 3173 |
free: kfree_skb(skb2); out: |
81378f728 netfilter: ctnetl... |
3174 3175 |
/* this avoids a loop in nfnetlink. */ return err == -EAGAIN ? -ENOBUFS : err; |
c1d10adb4 [NETFILTER]: Add ... |
3176 |
} |
ac7b84839 netfilter: expect... |
3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 |
static bool expect_iter_name(struct nf_conntrack_expect *exp, void *data) { const struct nf_conn_help *m_help; const char *name = data; m_help = nfct_help(exp->master); return strcmp(m_help->helper->name, name) == 0; } static bool expect_iter_all(struct nf_conntrack_expect *exp, void *data) { return true; } |
7b8002a15 netfilter: nfnetl... |
3191 3192 |
static int ctnetlink_del_expect(struct net *net, struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, |
04ba724b6 netfilter: nfnetl... |
3193 3194 |
const struct nlattr * const cda[], struct netlink_ext_ack *extack) |
c1d10adb4 [NETFILTER]: Add ... |
3195 |
{ |
31f15875c [NETFILTER]: nf_c... |
3196 |
struct nf_conntrack_expect *exp; |
c1d10adb4 [NETFILTER]: Add ... |
3197 |
struct nf_conntrack_tuple tuple; |
96bcf938d netfilter: ctnetl... |
3198 |
struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
c1d10adb4 [NETFILTER]: Add ... |
3199 |
u_int8_t u3 = nfmsg->nfgen_family; |
308ac9143 netfilter: nf_con... |
3200 |
struct nf_conntrack_zone zone; |
c1d10adb4 [NETFILTER]: Add ... |
3201 |
int err; |
df6fb868d [NETFILTER]: nfne... |
3202 |
if (cda[CTA_EXPECT_TUPLE]) { |
c1d10adb4 [NETFILTER]: Add ... |
3203 |
/* delete a single expect by tuple */ |
ef00f89f1 netfilter: ctnetl... |
3204 3205 3206 |
err = ctnetlink_parse_zone(cda[CTA_EXPECT_ZONE], &zone); if (err < 0) return err; |
deedb5903 netfilter: nf_con... |
3207 3208 |
err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE, u3, NULL); |
c1d10adb4 [NETFILTER]: Add ... |
3209 3210 3211 3212 |
if (err < 0) return err; /* bump usage count to 2 */ |
308ac9143 netfilter: nf_con... |
3213 |
exp = nf_ct_expect_find_get(net, &zone, &tuple); |
c1d10adb4 [NETFILTER]: Add ... |
3214 3215 |
if (!exp) return -ENOENT; |
df6fb868d [NETFILTER]: nfne... |
3216 |
if (cda[CTA_EXPECT_ID]) { |
77236b6e3 [NETFILTER]: ctne... |
3217 |
__be32 id = nla_get_be32(cda[CTA_EXPECT_ID]); |
358324024 [NETFILTER]: nf_c... |
3218 |
if (ntohl(id) != (u32)(unsigned long)exp) { |
6823645d6 [NETFILTER]: nf_c... |
3219 |
nf_ct_expect_put(exp); |
c1d10adb4 [NETFILTER]: Add ... |
3220 3221 3222 3223 3224 |
return -ENOENT; } } /* after list removal, usage count == 1 */ |
ca7433df3 netfilter: conntr... |
3225 |
spin_lock_bh(&nf_conntrack_expect_lock); |
ebbf41df4 netfilter: ctnetl... |
3226 |
if (del_timer(&exp->timeout)) { |
15e473046 netlink: Rename p... |
3227 |
nf_ct_unlink_expect_report(exp, NETLINK_CB(skb).portid, |
ebbf41df4 netfilter: ctnetl... |
3228 3229 3230 |
nlmsg_report(nlh)); nf_ct_expect_put(exp); } |
ca7433df3 netfilter: conntr... |
3231 |
spin_unlock_bh(&nf_conntrack_expect_lock); |
601e68e10 [NETFILTER]: Fix ... |
3232 |
/* have to put what we 'get' above. |
c1d10adb4 [NETFILTER]: Add ... |
3233 |
* after this line usage count == 0 */ |
6823645d6 [NETFILTER]: nf_c... |
3234 |
nf_ct_expect_put(exp); |
df6fb868d [NETFILTER]: nfne... |
3235 3236 |
} else if (cda[CTA_EXPECT_HELP_NAME]) { char *name = nla_data(cda[CTA_EXPECT_HELP_NAME]); |
c1d10adb4 [NETFILTER]: Add ... |
3237 |
|
ac7b84839 netfilter: expect... |
3238 3239 3240 |
nf_ct_expect_iterate_net(net, expect_iter_name, name, NETLINK_CB(skb).portid, nlmsg_report(nlh)); |
c1d10adb4 [NETFILTER]: Add ... |
3241 3242 |
} else { /* This basically means we have to flush everything*/ |
ac7b84839 netfilter: expect... |
3243 3244 3245 |
nf_ct_expect_iterate_net(net, expect_iter_all, NULL, NETLINK_CB(skb).portid, nlmsg_report(nlh)); |
c1d10adb4 [NETFILTER]: Add ... |
3246 3247 3248 3249 3250 |
} return 0; } static int |
399383246 netfilter: nfnetl... |
3251 3252 |
ctnetlink_change_expect(struct nf_conntrack_expect *x, const struct nlattr * const cda[]) |
c1d10adb4 [NETFILTER]: Add ... |
3253 |
{ |
9768e1ace netfilter: nf_ct_... |
3254 3255 3256 3257 3258 3259 3260 3261 3262 |
if (cda[CTA_EXPECT_TIMEOUT]) { if (!del_timer(&x->timeout)) return -ETIME; x->timeout.expires = jiffies + ntohl(nla_get_be32(cda[CTA_EXPECT_TIMEOUT])) * HZ; add_timer(&x->timeout); } return 0; |
c1d10adb4 [NETFILTER]: Add ... |
3263 |
} |
076a0ca02 netfilter: ctnetl... |
3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 |
static const struct nla_policy exp_nat_nla_policy[CTA_EXPECT_NAT_MAX+1] = { [CTA_EXPECT_NAT_DIR] = { .type = NLA_U32 }, [CTA_EXPECT_NAT_TUPLE] = { .type = NLA_NESTED }, }; static int ctnetlink_parse_expect_nat(const struct nlattr *attr, struct nf_conntrack_expect *exp, u_int8_t u3) { |
4806e9757 netfilter: replac... |
3274 |
#if IS_ENABLED(CONFIG_NF_NAT) |
076a0ca02 netfilter: ctnetl... |
3275 3276 3277 |
struct nlattr *tb[CTA_EXPECT_NAT_MAX+1]; struct nf_conntrack_tuple nat_tuple = {}; int err; |
8cb081746 netlink: make val... |
3278 3279 |
err = nla_parse_nested_deprecated(tb, CTA_EXPECT_NAT_MAX, attr, exp_nat_nla_policy, NULL); |
130ffbc26 netfilter: check ... |
3280 3281 |
if (err < 0) return err; |
076a0ca02 netfilter: ctnetl... |
3282 3283 3284 3285 3286 |
if (!tb[CTA_EXPECT_NAT_DIR] || !tb[CTA_EXPECT_NAT_TUPLE]) return -EINVAL; err = ctnetlink_parse_tuple((const struct nlattr * const *)tb, |
deedb5903 netfilter: nf_con... |
3287 3288 |
&nat_tuple, CTA_EXPECT_NAT_TUPLE, u3, NULL); |
076a0ca02 netfilter: ctnetl... |
3289 3290 |
if (err < 0) return err; |
c7232c997 netfilter: add pr... |
3291 |
exp->saved_addr = nat_tuple.src.u3; |
076a0ca02 netfilter: ctnetl... |
3292 3293 3294 3295 3296 3297 3298 3299 |
exp->saved_proto = nat_tuple.src.u; exp->dir = ntohl(nla_get_be32(tb[CTA_EXPECT_NAT_DIR])); return 0; #else return -EOPNOTSUPP; #endif } |
0ef71ee1a netfilter: ctnetl... |
3300 3301 3302 3303 3304 |
static struct nf_conntrack_expect * ctnetlink_alloc_expect(const struct nlattr * const cda[], struct nf_conn *ct, struct nf_conntrack_helper *helper, struct nf_conntrack_tuple *tuple, struct nf_conntrack_tuple *mask) |
c1d10adb4 [NETFILTER]: Add ... |
3305 |
{ |
0ef71ee1a netfilter: ctnetl... |
3306 |
u_int32_t class = 0; |
c1d10adb4 [NETFILTER]: Add ... |
3307 |
struct nf_conntrack_expect *exp; |
dc808fe28 [NETFILTER] nf_co... |
3308 |
struct nf_conn_help *help; |
0ef71ee1a netfilter: ctnetl... |
3309 |
int err; |
660fdb2a0 netfilter: ctnetl... |
3310 |
|
2c62e0bc6 netfilter: ctnetl... |
3311 3312 3313 |
help = nfct_help(ct); if (!help) return ERR_PTR(-EOPNOTSUPP); |
b8c5e52c1 netfilter: ctnetl... |
3314 3315 |
if (cda[CTA_EXPECT_CLASS] && helper) { class = ntohl(nla_get_be32(cda[CTA_EXPECT_CLASS])); |
0ef71ee1a netfilter: ctnetl... |
3316 3317 |
if (class > helper->expect_class_max) return ERR_PTR(-EINVAL); |
b8c5e52c1 netfilter: ctnetl... |
3318 |
} |
6823645d6 [NETFILTER]: nf_c... |
3319 |
exp = nf_ct_expect_alloc(ct); |
0ef71ee1a netfilter: ctnetl... |
3320 3321 |
if (!exp) return ERR_PTR(-ENOMEM); |
2c62e0bc6 netfilter: ctnetl... |
3322 3323 3324 |
if (cda[CTA_EXPECT_FLAGS]) { exp->flags = ntohl(nla_get_be32(cda[CTA_EXPECT_FLAGS])); exp->flags &= ~NF_CT_EXPECT_USERSPACE; |
bc01befdc netfilter: ctnetl... |
3325 |
} else { |
2c62e0bc6 netfilter: ctnetl... |
3326 |
exp->flags = 0; |
bc01befdc netfilter: ctnetl... |
3327 |
} |
544d5c7d9 netfilter: ctnetl... |
3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 |
if (cda[CTA_EXPECT_FN]) { const char *name = nla_data(cda[CTA_EXPECT_FN]); struct nf_ct_helper_expectfn *expfn; expfn = nf_ct_helper_expectfn_find_by_name(name); if (expfn == NULL) { err = -EINVAL; goto err_out; } exp->expectfn = expfn->expectfn; } else exp->expectfn = NULL; |
601e68e10 [NETFILTER]: Fix ... |
3340 |
|
b8c5e52c1 netfilter: ctnetl... |
3341 |
exp->class = class; |
c1d10adb4 [NETFILTER]: Add ... |
3342 |
exp->master = ct; |
660fdb2a0 netfilter: ctnetl... |
3343 |
exp->helper = helper; |
0ef71ee1a netfilter: ctnetl... |
3344 3345 3346 |
exp->tuple = *tuple; exp->mask.src.u3 = mask->src.u3; exp->mask.src.u.all = mask->src.u.all; |
c1d10adb4 [NETFILTER]: Add ... |
3347 |
|
076a0ca02 netfilter: ctnetl... |
3348 3349 |
if (cda[CTA_EXPECT_NAT]) { err = ctnetlink_parse_expect_nat(cda[CTA_EXPECT_NAT], |
0ef71ee1a netfilter: ctnetl... |
3350 |
exp, nf_ct_l3num(ct)); |
076a0ca02 netfilter: ctnetl... |
3351 3352 3353 |
if (err < 0) goto err_out; } |
0ef71ee1a netfilter: ctnetl... |
3354 |
return exp; |
076a0ca02 netfilter: ctnetl... |
3355 |
err_out: |
6823645d6 [NETFILTER]: nf_c... |
3356 |
nf_ct_expect_put(exp); |
0ef71ee1a netfilter: ctnetl... |
3357 3358 3359 3360 |
return ERR_PTR(err); } static int |
308ac9143 netfilter: nf_con... |
3361 3362 |
ctnetlink_create_expect(struct net *net, const struct nf_conntrack_zone *zone, |
0ef71ee1a netfilter: ctnetl... |
3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 |
const struct nlattr * const cda[], u_int8_t u3, u32 portid, int report) { struct nf_conntrack_tuple tuple, mask, master_tuple; struct nf_conntrack_tuple_hash *h = NULL; struct nf_conntrack_helper *helper = NULL; struct nf_conntrack_expect *exp; struct nf_conn *ct; int err; /* caller guarantees that those three CTA_EXPECT_* exist */ |
deedb5903 netfilter: nf_con... |
3374 3375 |
err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE, u3, NULL); |
0ef71ee1a netfilter: ctnetl... |
3376 3377 |
if (err < 0) return err; |
deedb5903 netfilter: nf_con... |
3378 3379 |
err = ctnetlink_parse_tuple(cda, &mask, CTA_EXPECT_MASK, u3, NULL); |
0ef71ee1a netfilter: ctnetl... |
3380 3381 |
if (err < 0) return err; |
deedb5903 netfilter: nf_con... |
3382 3383 |
err = ctnetlink_parse_tuple(cda, &master_tuple, CTA_EXPECT_MASTER, u3, NULL); |
0ef71ee1a netfilter: ctnetl... |
3384 3385 3386 3387 3388 3389 3390 3391 |
if (err < 0) return err; /* Look for master conntrack of this expectation */ h = nf_conntrack_find_get(net, zone, &master_tuple); if (!h) return -ENOENT; ct = nf_ct_tuplehash_to_ctrack(h); |
8b5995d06 netfilter: helper... |
3392 |
rcu_read_lock(); |
0ef71ee1a netfilter: ctnetl... |
3393 3394 3395 3396 3397 3398 |
if (cda[CTA_EXPECT_HELP_NAME]) { const char *helpname = nla_data(cda[CTA_EXPECT_HELP_NAME]); helper = __nf_conntrack_helper_find(helpname, u3, nf_ct_protonum(ct)); if (helper == NULL) { |
8b5995d06 netfilter: helper... |
3399 |
rcu_read_unlock(); |
0ef71ee1a netfilter: ctnetl... |
3400 3401 3402 3403 3404 |
#ifdef CONFIG_MODULES if (request_module("nfct-helper-%s", helpname) < 0) { err = -EOPNOTSUPP; goto err_ct; } |
8b5995d06 netfilter: helper... |
3405 |
rcu_read_lock(); |
0ef71ee1a netfilter: ctnetl... |
3406 3407 3408 3409 |
helper = __nf_conntrack_helper_find(helpname, u3, nf_ct_protonum(ct)); if (helper) { err = -EAGAIN; |
8b5995d06 netfilter: helper... |
3410 |
goto err_rcu; |
0ef71ee1a netfilter: ctnetl... |
3411 |
} |
8b5995d06 netfilter: helper... |
3412 |
rcu_read_unlock(); |
0ef71ee1a netfilter: ctnetl... |
3413 3414 3415 3416 3417 3418 3419 3420 3421 |
#endif err = -EOPNOTSUPP; goto err_ct; } } exp = ctnetlink_alloc_expect(cda, ct, helper, &tuple, &mask); if (IS_ERR(exp)) { err = PTR_ERR(exp); |
8b5995d06 netfilter: helper... |
3422 |
goto err_rcu; |
0ef71ee1a netfilter: ctnetl... |
3423 |
} |
3c00fb0bf netfilter: nf_con... |
3424 |
err = nf_ct_expect_related_report(exp, portid, report, 0); |
0ef71ee1a netfilter: ctnetl... |
3425 |
nf_ct_expect_put(exp); |
8b5995d06 netfilter: helper... |
3426 3427 |
err_rcu: rcu_read_unlock(); |
0ef71ee1a netfilter: ctnetl... |
3428 3429 |
err_ct: nf_ct_put(ct); |
c1d10adb4 [NETFILTER]: Add ... |
3430 3431 |
return err; } |
7b8002a15 netfilter: nfnetl... |
3432 3433 |
static int ctnetlink_new_expect(struct net *net, struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, |
04ba724b6 netfilter: nfnetl... |
3434 3435 |
const struct nlattr * const cda[], struct netlink_ext_ack *extack) |
c1d10adb4 [NETFILTER]: Add ... |
3436 3437 3438 |
{ struct nf_conntrack_tuple tuple; struct nf_conntrack_expect *exp; |
96bcf938d netfilter: ctnetl... |
3439 |
struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
c1d10adb4 [NETFILTER]: Add ... |
3440 |
u_int8_t u3 = nfmsg->nfgen_family; |
308ac9143 netfilter: nf_con... |
3441 |
struct nf_conntrack_zone zone; |
ef00f89f1 netfilter: ctnetl... |
3442 |
int err; |
c1d10adb4 [NETFILTER]: Add ... |
3443 |
|
df6fb868d [NETFILTER]: nfne... |
3444 3445 3446 |
if (!cda[CTA_EXPECT_TUPLE] || !cda[CTA_EXPECT_MASK] || !cda[CTA_EXPECT_MASTER]) |
c1d10adb4 [NETFILTER]: Add ... |
3447 |
return -EINVAL; |
ef00f89f1 netfilter: ctnetl... |
3448 3449 3450 |
err = ctnetlink_parse_zone(cda[CTA_EXPECT_ZONE], &zone); if (err < 0) return err; |
deedb5903 netfilter: nf_con... |
3451 3452 |
err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE, u3, NULL); |
c1d10adb4 [NETFILTER]: Add ... |
3453 3454 |
if (err < 0) return err; |
ca7433df3 netfilter: conntr... |
3455 |
spin_lock_bh(&nf_conntrack_expect_lock); |
308ac9143 netfilter: nf_con... |
3456 |
exp = __nf_ct_expect_find(net, &zone, &tuple); |
c1d10adb4 [NETFILTER]: Add ... |
3457 |
if (!exp) { |
ca7433df3 netfilter: conntr... |
3458 |
spin_unlock_bh(&nf_conntrack_expect_lock); |
c1d10adb4 [NETFILTER]: Add ... |
3459 |
err = -ENOENT; |
19abb7b09 netfilter: ctnetl... |
3460 |
if (nlh->nlmsg_flags & NLM_F_CREATE) { |
308ac9143 netfilter: nf_con... |
3461 |
err = ctnetlink_create_expect(net, &zone, cda, u3, |
15e473046 netlink: Rename p... |
3462 |
NETLINK_CB(skb).portid, |
19abb7b09 netfilter: ctnetl... |
3463 3464 |
nlmsg_report(nlh)); } |
c1d10adb4 [NETFILTER]: Add ... |
3465 3466 3467 3468 3469 3470 |
return err; } err = -EEXIST; if (!(nlh->nlmsg_flags & NLM_F_EXCL)) err = ctnetlink_change_expect(exp, cda); |
ca7433df3 netfilter: conntr... |
3471 |
spin_unlock_bh(&nf_conntrack_expect_lock); |
c1d10adb4 [NETFILTER]: Add ... |
3472 |
|
c1d10adb4 [NETFILTER]: Add ... |
3473 3474 |
return err; } |
392025f87 netfilter: ctnetl... |
3475 |
static int |
15e473046 netlink: Rename p... |
3476 |
ctnetlink_exp_stat_fill_info(struct sk_buff *skb, u32 portid, u32 seq, int cpu, |
392025f87 netfilter: ctnetl... |
3477 3478 3479 3480 |
const struct ip_conntrack_stat *st) { struct nlmsghdr *nlh; struct nfgenmsg *nfmsg; |
15e473046 netlink: Rename p... |
3481 |
unsigned int flags = portid ? NLM_F_MULTI : 0, event; |
392025f87 netfilter: ctnetl... |
3482 |
|
dedb67c4b netfilter: Add nf... |
3483 3484 |
event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_EXP_GET_STATS_CPU); |
15e473046 netlink: Rename p... |
3485 |
nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags); |
392025f87 netfilter: ctnetl... |
3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 |
if (nlh == NULL) goto nlmsg_failure; nfmsg = nlmsg_data(nlh); nfmsg->nfgen_family = AF_UNSPEC; nfmsg->version = NFNETLINK_V0; nfmsg->res_id = htons(cpu); if (nla_put_be32(skb, CTA_STATS_EXP_NEW, htonl(st->expect_new)) || nla_put_be32(skb, CTA_STATS_EXP_CREATE, htonl(st->expect_create)) || nla_put_be32(skb, CTA_STATS_EXP_DELETE, htonl(st->expect_delete))) goto nla_put_failure; nlmsg_end(skb, nlh); return skb->len; nla_put_failure: nlmsg_failure: nlmsg_cancel(skb, nlh); return -1; } static int ctnetlink_exp_stat_cpu_dump(struct sk_buff *skb, struct netlink_callback *cb) { int cpu; struct net *net = sock_net(skb->sk); if (cb->args[0] == nr_cpu_ids) return 0; for (cpu = cb->args[0]; cpu < nr_cpu_ids; cpu++) { const struct ip_conntrack_stat *st; if (!cpu_possible(cpu)) continue; st = per_cpu_ptr(net->ct.stat, cpu); |
15e473046 netlink: Rename p... |
3524 |
if (ctnetlink_exp_stat_fill_info(skb, NETLINK_CB(cb->skb).portid, |
392025f87 netfilter: ctnetl... |
3525 3526 3527 3528 3529 3530 3531 3532 |
cb->nlh->nlmsg_seq, cpu, st) < 0) break; } cb->args[0] = cpu; return skb->len; } |
7b8002a15 netfilter: nfnetl... |
3533 3534 3535 |
static int ctnetlink_stat_exp_cpu(struct net *net, struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, |
04ba724b6 netfilter: nfnetl... |
3536 3537 |
const struct nlattr * const cda[], struct netlink_ext_ack *extack) |
392025f87 netfilter: ctnetl... |
3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 |
{ if (nlh->nlmsg_flags & NLM_F_DUMP) { struct netlink_dump_control c = { .dump = ctnetlink_exp_stat_cpu_dump, }; return netlink_dump_start(ctnl, skb, nlh, &c); } return 0; } |
c1d10adb4 [NETFILTER]: Add ... |
3548 |
#ifdef CONFIG_NF_CONNTRACK_EVENTS |
e34d5c1a4 netfilter: conntr... |
3549 3550 |
static struct nf_ct_event_notifier ctnl_notifier = { .fcn = ctnetlink_conntrack_event, |
c1d10adb4 [NETFILTER]: Add ... |
3551 |
}; |
e34d5c1a4 netfilter: conntr... |
3552 3553 |
static struct nf_exp_event_notifier ctnl_notifier_exp = { .fcn = ctnetlink_expect_event, |
c1d10adb4 [NETFILTER]: Add ... |
3554 3555 |
}; #endif |
7c8d4cb41 [NETFILTER]: nfne... |
3556 |
static const struct nfnl_callback ctnl_cb[IPCTNL_MSG_MAX] = { |
c1d10adb4 [NETFILTER]: Add ... |
3557 |
[IPCTNL_MSG_CT_NEW] = { .call = ctnetlink_new_conntrack, |
f73e924cd [NETFILTER]: ctne... |
3558 3559 |
.attr_count = CTA_MAX, .policy = ct_nla_policy }, |
c1d10adb4 [NETFILTER]: Add ... |
3560 |
[IPCTNL_MSG_CT_GET] = { .call = ctnetlink_get_conntrack, |
f73e924cd [NETFILTER]: ctne... |
3561 3562 |
.attr_count = CTA_MAX, .policy = ct_nla_policy }, |
c1d10adb4 [NETFILTER]: Add ... |
3563 |
[IPCTNL_MSG_CT_DELETE] = { .call = ctnetlink_del_conntrack, |
f73e924cd [NETFILTER]: ctne... |
3564 3565 |
.attr_count = CTA_MAX, .policy = ct_nla_policy }, |
c1d10adb4 [NETFILTER]: Add ... |
3566 |
[IPCTNL_MSG_CT_GET_CTRZERO] = { .call = ctnetlink_get_conntrack, |
f73e924cd [NETFILTER]: ctne... |
3567 3568 |
.attr_count = CTA_MAX, .policy = ct_nla_policy }, |
392025f87 netfilter: ctnetl... |
3569 3570 |
[IPCTNL_MSG_CT_GET_STATS_CPU] = { .call = ctnetlink_stat_ct_cpu }, [IPCTNL_MSG_CT_GET_STATS] = { .call = ctnetlink_stat_ct }, |
d871befe3 netfilter: ctnetl... |
3571 3572 |
[IPCTNL_MSG_CT_GET_DYING] = { .call = ctnetlink_get_ct_dying }, [IPCTNL_MSG_CT_GET_UNCONFIRMED] = { .call = ctnetlink_get_ct_unconfirmed }, |
c1d10adb4 [NETFILTER]: Add ... |
3573 |
}; |
7c8d4cb41 [NETFILTER]: nfne... |
3574 |
static const struct nfnl_callback ctnl_exp_cb[IPCTNL_MSG_EXP_MAX] = { |
c1d10adb4 [NETFILTER]: Add ... |
3575 |
[IPCTNL_MSG_EXP_GET] = { .call = ctnetlink_get_expect, |
f73e924cd [NETFILTER]: ctne... |
3576 3577 |
.attr_count = CTA_EXPECT_MAX, .policy = exp_nla_policy }, |
c1d10adb4 [NETFILTER]: Add ... |
3578 |
[IPCTNL_MSG_EXP_NEW] = { .call = ctnetlink_new_expect, |
f73e924cd [NETFILTER]: ctne... |
3579 3580 |
.attr_count = CTA_EXPECT_MAX, .policy = exp_nla_policy }, |
c1d10adb4 [NETFILTER]: Add ... |
3581 |
[IPCTNL_MSG_EXP_DELETE] = { .call = ctnetlink_del_expect, |
f73e924cd [NETFILTER]: ctne... |
3582 3583 |
.attr_count = CTA_EXPECT_MAX, .policy = exp_nla_policy }, |
392025f87 netfilter: ctnetl... |
3584 |
[IPCTNL_MSG_EXP_GET_STATS_CPU] = { .call = ctnetlink_stat_exp_cpu }, |
c1d10adb4 [NETFILTER]: Add ... |
3585 |
}; |
7c8d4cb41 [NETFILTER]: nfne... |
3586 |
static const struct nfnetlink_subsystem ctnl_subsys = { |
c1d10adb4 [NETFILTER]: Add ... |
3587 3588 3589 3590 3591 |
.name = "conntrack", .subsys_id = NFNL_SUBSYS_CTNETLINK, .cb_count = IPCTNL_MSG_MAX, .cb = ctnl_cb, }; |
7c8d4cb41 [NETFILTER]: nfne... |
3592 |
static const struct nfnetlink_subsystem ctnl_exp_subsys = { |
c1d10adb4 [NETFILTER]: Add ... |
3593 3594 3595 3596 3597 |
.name = "conntrack_expect", .subsys_id = NFNL_SUBSYS_CTNETLINK_EXP, .cb_count = IPCTNL_MSG_EXP_MAX, .cb = ctnl_exp_cb, }; |
d2483ddef [NETFILTER]: nf_c... |
3598 |
MODULE_ALIAS("ip_conntrack_netlink"); |
c1d10adb4 [NETFILTER]: Add ... |
3599 |
MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK); |
34f9a2e4d [NETFILTER]: ctne... |
3600 |
MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_EXP); |
c1d10adb4 [NETFILTER]: Add ... |
3601 |
|
70e9942f1 netfilter: nf_con... |
3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 |
static int __net_init ctnetlink_net_init(struct net *net) { #ifdef CONFIG_NF_CONNTRACK_EVENTS int ret; ret = nf_conntrack_register_notifier(net, &ctnl_notifier); if (ret < 0) { pr_err("ctnetlink_init: cannot register notifier. "); goto err_out; } ret = nf_ct_expect_register_notifier(net, &ctnl_notifier_exp); if (ret < 0) { pr_err("ctnetlink_init: cannot expect register notifier. "); goto err_unreg_notifier; } #endif return 0; #ifdef CONFIG_NF_CONNTRACK_EVENTS err_unreg_notifier: nf_conntrack_unregister_notifier(net, &ctnl_notifier); err_out: return ret; #endif } static void ctnetlink_net_exit(struct net *net) { #ifdef CONFIG_NF_CONNTRACK_EVENTS nf_ct_expect_unregister_notifier(net, &ctnl_notifier_exp); nf_conntrack_unregister_notifier(net, &ctnl_notifier); #endif } static void __net_exit ctnetlink_net_exit_batch(struct list_head *net_exit_list) { struct net *net; list_for_each_entry(net, net_exit_list, exit_list) ctnetlink_net_exit(net); |
18a110b02 netfilter: ctnetl... |
3645 3646 3647 |
/* wait for other cpus until they are done with ctnl_notifiers */ synchronize_rcu(); |
70e9942f1 netfilter: nf_con... |
3648 3649 3650 3651 3652 3653 |
} static struct pernet_operations ctnetlink_net_ops = { .init = ctnetlink_net_init, .exit_batch = ctnetlink_net_exit_batch, }; |
c1d10adb4 [NETFILTER]: Add ... |
3654 3655 3656 |
static int __init ctnetlink_init(void) { int ret; |
c1d10adb4 [NETFILTER]: Add ... |
3657 3658 |
ret = nfnetlink_subsys_register(&ctnl_subsys); if (ret < 0) { |
654d0fbdc netfilter: cleanu... |
3659 3660 |
pr_err("ctnetlink_init: cannot register with nfnetlink. "); |
c1d10adb4 [NETFILTER]: Add ... |
3661 3662 3663 3664 3665 |
goto err_out; } ret = nfnetlink_subsys_register(&ctnl_exp_subsys); if (ret < 0) { |
654d0fbdc netfilter: cleanu... |
3666 3667 |
pr_err("ctnetlink_init: cannot register exp with nfnetlink. "); |
c1d10adb4 [NETFILTER]: Add ... |
3668 3669 |
goto err_unreg_subsys; } |
ef6acf68c netfilter: ctnetl... |
3670 3671 |
ret = register_pernet_subsys(&ctnetlink_net_ops); if (ret < 0) { |
70e9942f1 netfilter: nf_con... |
3672 3673 |
pr_err("ctnetlink_init: cannot register pernet operations "); |
c1d10adb4 [NETFILTER]: Add ... |
3674 3675 |
goto err_unreg_exp_subsys; } |
83f3e94d3 netfilter: Kconfi... |
3676 |
#ifdef CONFIG_NETFILTER_NETLINK_GLUE_CT |
9cb017665 netfilter: add gl... |
3677 |
/* setup interaction between nf_queue and nf_conntrack_netlink. */ |
a4b4766c3 netfilter: nfnetl... |
3678 |
RCU_INIT_POINTER(nfnl_ct_hook, &ctnetlink_glue_hook); |
9cb017665 netfilter: add gl... |
3679 |
#endif |
c1d10adb4 [NETFILTER]: Add ... |
3680 |
return 0; |
c1d10adb4 [NETFILTER]: Add ... |
3681 3682 |
err_unreg_exp_subsys: nfnetlink_subsys_unregister(&ctnl_exp_subsys); |
c1d10adb4 [NETFILTER]: Add ... |
3683 3684 3685 3686 3687 3688 3689 3690 |
err_unreg_subsys: nfnetlink_subsys_unregister(&ctnl_subsys); err_out: return ret; } static void __exit ctnetlink_exit(void) { |
70e9942f1 netfilter: nf_con... |
3691 |
unregister_pernet_subsys(&ctnetlink_net_ops); |
c1d10adb4 [NETFILTER]: Add ... |
3692 3693 |
nfnetlink_subsys_unregister(&ctnl_exp_subsys); nfnetlink_subsys_unregister(&ctnl_subsys); |
83f3e94d3 netfilter: Kconfi... |
3694 |
#ifdef CONFIG_NETFILTER_NETLINK_GLUE_CT |
a4b4766c3 netfilter: nfnetl... |
3695 |
RCU_INIT_POINTER(nfnl_ct_hook, NULL); |
9cb017665 netfilter: add gl... |
3696 |
#endif |
3b7dabf02 netfilter: invoke... |
3697 |
synchronize_rcu(); |
c1d10adb4 [NETFILTER]: Add ... |
3698 3699 3700 3701 |
} module_init(ctnetlink_init); module_exit(ctnetlink_exit); |