1 /* Connection tracking via netlink socket. Allows for user space
2 * protocol helpers and general trouble making from userspace.
4 * (C) 2001 by Jay Schulist <jschlst@samba.org>
5 * (C) 2002-2006 by Harald Welte <laforge@gnumonks.org>
6 * (C) 2003 by Patrick Mchardy <kaber@trash.net>
7 * (C) 2005-2006 by Pablo Neira Ayuso <pablo@eurodev.net>
9 * I've reworked this stuff to use attributes instead of conntrack
10 * structures. 5.44 am. I need more tea. --pablo 05/07/11.
12 * Initial connection tracking via netlink development funded and
13 * generally made possible by Network Robots, Inc. (www.networkrobots.com)
15 * Further development of this code funded by Astaro AG (http://www.astaro.com)
17 * This software may be used and distributed according to the terms
18 * of the GNU General Public License, incorporated herein by reference.
20 * Derived from ip_conntrack_netlink.c: Port by Pablo Neira Ayuso (05/11/14)
23 #include <linux/init.h>
24 #include <linux/module.h>
25 #include <linux/kernel.h>
26 #include <linux/types.h>
27 #include <linux/timer.h>
28 #include <linux/skbuff.h>
29 #include <linux/errno.h>
30 #include <linux/netlink.h>
31 #include <linux/spinlock.h>
32 #include <linux/interrupt.h>
33 #include <linux/notifier.h>
35 #include <linux/netfilter.h>
36 #include <net/netfilter/nf_conntrack.h>
37 #include <net/netfilter/nf_conntrack_core.h>
38 #include <net/netfilter/nf_conntrack_helper.h>
39 #include <net/netfilter/nf_conntrack_l3proto.h>
40 #include <net/netfilter/nf_conntrack_protocol.h>
41 #include <linux/netfilter_ipv4/ip_nat_protocol.h>
43 #include <linux/netfilter/nfnetlink.h>
44 #include <linux/netfilter/nfnetlink_conntrack.h>
46 MODULE_LICENSE("GPL");
48 static char __initdata version
[] = "0.93";
53 #define DEBUGP(format, args...)
58 ctnetlink_dump_tuples_proto(struct sk_buff
*skb
,
59 const struct nf_conntrack_tuple
*tuple
,
60 struct nf_conntrack_protocol
*proto
)
63 struct nfattr
*nest_parms
= NFA_NEST(skb
, CTA_TUPLE_PROTO
);
65 NFA_PUT(skb
, CTA_PROTO_NUM
, sizeof(u_int8_t
), &tuple
->dst
.protonum
);
67 if (likely(proto
->tuple_to_nfattr
))
68 ret
= proto
->tuple_to_nfattr(skb
, tuple
);
70 NFA_NEST_END(skb
, nest_parms
);
79 ctnetlink_dump_tuples_ip(struct sk_buff
*skb
,
80 const struct nf_conntrack_tuple
*tuple
,
81 struct nf_conntrack_l3proto
*l3proto
)
84 struct nfattr
*nest_parms
= NFA_NEST(skb
, CTA_TUPLE_IP
);
86 if (likely(l3proto
->tuple_to_nfattr
))
87 ret
= l3proto
->tuple_to_nfattr(skb
, tuple
);
89 NFA_NEST_END(skb
, nest_parms
);
98 ctnetlink_dump_tuples(struct sk_buff
*skb
,
99 const struct nf_conntrack_tuple
*tuple
)
102 struct nf_conntrack_l3proto
*l3proto
;
103 struct nf_conntrack_protocol
*proto
;
105 l3proto
= nf_ct_l3proto_find_get(tuple
->src
.l3num
);
106 ret
= ctnetlink_dump_tuples_ip(skb
, tuple
, l3proto
);
107 nf_ct_l3proto_put(l3proto
);
109 if (unlikely(ret
< 0))
112 proto
= nf_ct_proto_find_get(tuple
->src
.l3num
, tuple
->dst
.protonum
);
113 ret
= ctnetlink_dump_tuples_proto(skb
, tuple
, proto
);
114 nf_ct_proto_put(proto
);
120 ctnetlink_dump_status(struct sk_buff
*skb
, const struct nf_conn
*ct
)
122 u_int32_t status
= htonl((u_int32_t
) ct
->status
);
123 NFA_PUT(skb
, CTA_STATUS
, sizeof(status
), &status
);
131 ctnetlink_dump_timeout(struct sk_buff
*skb
, const struct nf_conn
*ct
)
133 long timeout_l
= ct
->timeout
.expires
- jiffies
;
139 timeout
= htonl(timeout_l
/ HZ
);
141 NFA_PUT(skb
, CTA_TIMEOUT
, sizeof(timeout
), &timeout
);
149 ctnetlink_dump_protoinfo(struct sk_buff
*skb
, const struct nf_conn
*ct
)
151 struct nf_conntrack_protocol
*proto
= nf_ct_proto_find_get(ct
->tuplehash
[IP_CT_DIR_ORIGINAL
].tuple
.src
.l3num
, ct
->tuplehash
[IP_CT_DIR_ORIGINAL
].tuple
.dst
.protonum
);
152 struct nfattr
*nest_proto
;
155 if (!proto
->to_nfattr
) {
156 nf_ct_proto_put(proto
);
160 nest_proto
= NFA_NEST(skb
, CTA_PROTOINFO
);
162 ret
= proto
->to_nfattr(skb
, nest_proto
, ct
);
164 nf_ct_proto_put(proto
);
166 NFA_NEST_END(skb
, nest_proto
);
175 ctnetlink_dump_helpinfo(struct sk_buff
*skb
, const struct nf_conn
*ct
)
177 struct nfattr
*nest_helper
;
178 const struct nf_conn_help
*help
= nfct_help(ct
);
180 if (!help
|| !help
->helper
)
183 nest_helper
= NFA_NEST(skb
, CTA_HELP
);
184 NFA_PUT(skb
, CTA_HELP_NAME
, strlen(help
->helper
->name
), help
->helper
->name
);
186 if (help
->helper
->to_nfattr
)
187 help
->helper
->to_nfattr(skb
, ct
);
189 NFA_NEST_END(skb
, nest_helper
);
197 #ifdef CONFIG_NF_CT_ACCT
199 ctnetlink_dump_counters(struct sk_buff
*skb
, const struct nf_conn
*ct
,
200 enum ip_conntrack_dir dir
)
202 enum ctattr_type type
= dir
? CTA_COUNTERS_REPLY
: CTA_COUNTERS_ORIG
;
203 struct nfattr
*nest_count
= NFA_NEST(skb
, type
);
206 tmp
= htonl(ct
->counters
[dir
].packets
);
207 NFA_PUT(skb
, CTA_COUNTERS32_PACKETS
, sizeof(u_int32_t
), &tmp
);
209 tmp
= htonl(ct
->counters
[dir
].bytes
);
210 NFA_PUT(skb
, CTA_COUNTERS32_BYTES
, sizeof(u_int32_t
), &tmp
);
212 NFA_NEST_END(skb
, nest_count
);
220 #define ctnetlink_dump_counters(a, b, c) (0)
223 #ifdef CONFIG_NF_CONNTRACK_MARK
225 ctnetlink_dump_mark(struct sk_buff
*skb
, const struct nf_conn
*ct
)
227 u_int32_t mark
= htonl(ct
->mark
);
229 NFA_PUT(skb
, CTA_MARK
, sizeof(u_int32_t
), &mark
);
236 #define ctnetlink_dump_mark(a, b) (0)
240 ctnetlink_dump_id(struct sk_buff
*skb
, const struct nf_conn
*ct
)
242 u_int32_t id
= htonl(ct
->id
);
243 NFA_PUT(skb
, CTA_ID
, sizeof(u_int32_t
), &id
);
251 ctnetlink_dump_use(struct sk_buff
*skb
, const struct nf_conn
*ct
)
253 u_int32_t use
= htonl(atomic_read(&ct
->ct_general
.use
));
255 NFA_PUT(skb
, CTA_USE
, sizeof(u_int32_t
), &use
);
262 #define tuple(ct, dir) (&(ct)->tuplehash[dir].tuple)
265 ctnetlink_fill_info(struct sk_buff
*skb
, u32 pid
, u32 seq
,
266 int event
, int nowait
,
267 const struct nf_conn
*ct
)
269 struct nlmsghdr
*nlh
;
270 struct nfgenmsg
*nfmsg
;
271 struct nfattr
*nest_parms
;
276 event
|= NFNL_SUBSYS_CTNETLINK
<< 8;
277 nlh
= NLMSG_PUT(skb
, pid
, seq
, event
, sizeof(struct nfgenmsg
));
278 nfmsg
= NLMSG_DATA(nlh
);
280 nlh
->nlmsg_flags
= (nowait
&& pid
) ? NLM_F_MULTI
: 0;
281 nfmsg
->nfgen_family
=
282 ct
->tuplehash
[IP_CT_DIR_ORIGINAL
].tuple
.src
.l3num
;
283 nfmsg
->version
= NFNETLINK_V0
;
286 nest_parms
= NFA_NEST(skb
, CTA_TUPLE_ORIG
);
287 if (ctnetlink_dump_tuples(skb
, tuple(ct
, IP_CT_DIR_ORIGINAL
)) < 0)
289 NFA_NEST_END(skb
, nest_parms
);
291 nest_parms
= NFA_NEST(skb
, CTA_TUPLE_REPLY
);
292 if (ctnetlink_dump_tuples(skb
, tuple(ct
, IP_CT_DIR_REPLY
)) < 0)
294 NFA_NEST_END(skb
, nest_parms
);
296 if (ctnetlink_dump_status(skb
, ct
) < 0 ||
297 ctnetlink_dump_timeout(skb
, ct
) < 0 ||
298 ctnetlink_dump_counters(skb
, ct
, IP_CT_DIR_ORIGINAL
) < 0 ||
299 ctnetlink_dump_counters(skb
, ct
, IP_CT_DIR_REPLY
) < 0 ||
300 ctnetlink_dump_protoinfo(skb
, ct
) < 0 ||
301 ctnetlink_dump_helpinfo(skb
, ct
) < 0 ||
302 ctnetlink_dump_mark(skb
, ct
) < 0 ||
303 ctnetlink_dump_id(skb
, ct
) < 0 ||
304 ctnetlink_dump_use(skb
, ct
) < 0)
307 nlh
->nlmsg_len
= skb
->tail
- b
;
312 skb_trim(skb
, b
- skb
->data
);
316 #ifdef CONFIG_NF_CONNTRACK_EVENTS
317 static int ctnetlink_conntrack_event(struct notifier_block
*this,
318 unsigned long events
, void *ptr
)
320 struct nlmsghdr
*nlh
;
321 struct nfgenmsg
*nfmsg
;
322 struct nfattr
*nest_parms
;
323 struct nf_conn
*ct
= (struct nf_conn
*)ptr
;
327 unsigned int flags
= 0, group
;
329 /* ignore our fake conntrack entry */
330 if (ct
== &nf_conntrack_untracked
)
333 if (events
& IPCT_DESTROY
) {
334 type
= IPCTNL_MSG_CT_DELETE
;
335 group
= NFNLGRP_CONNTRACK_DESTROY
;
336 } else if (events
& (IPCT_NEW
| IPCT_RELATED
)) {
337 type
= IPCTNL_MSG_CT_NEW
;
338 flags
= NLM_F_CREATE
|NLM_F_EXCL
;
339 /* dump everything */
341 group
= NFNLGRP_CONNTRACK_NEW
;
342 } else if (events
& (IPCT_STATUS
| IPCT_PROTOINFO
)) {
343 type
= IPCTNL_MSG_CT_NEW
;
344 group
= NFNLGRP_CONNTRACK_UPDATE
;
348 if (!nfnetlink_has_listeners(group
))
351 skb
= alloc_skb(NLMSG_GOODSIZE
, GFP_ATOMIC
);
357 type
|= NFNL_SUBSYS_CTNETLINK
<< 8;
358 nlh
= NLMSG_PUT(skb
, 0, 0, type
, sizeof(struct nfgenmsg
));
359 nfmsg
= NLMSG_DATA(nlh
);
361 nlh
->nlmsg_flags
= flags
;
362 nfmsg
->nfgen_family
= ct
->tuplehash
[IP_CT_DIR_ORIGINAL
].tuple
.src
.l3num
;
363 nfmsg
->version
= NFNETLINK_V0
;
366 nest_parms
= NFA_NEST(skb
, CTA_TUPLE_ORIG
);
367 if (ctnetlink_dump_tuples(skb
, tuple(ct
, IP_CT_DIR_ORIGINAL
)) < 0)
369 NFA_NEST_END(skb
, nest_parms
);
371 nest_parms
= NFA_NEST(skb
, CTA_TUPLE_REPLY
);
372 if (ctnetlink_dump_tuples(skb
, tuple(ct
, IP_CT_DIR_REPLY
)) < 0)
374 NFA_NEST_END(skb
, nest_parms
);
376 /* NAT stuff is now a status flag */
377 if ((events
& IPCT_STATUS
|| events
& IPCT_NATINFO
)
378 && ctnetlink_dump_status(skb
, ct
) < 0)
380 if (events
& IPCT_REFRESH
381 && ctnetlink_dump_timeout(skb
, ct
) < 0)
383 if (events
& IPCT_PROTOINFO
384 && ctnetlink_dump_protoinfo(skb
, ct
) < 0)
386 if (events
& IPCT_HELPINFO
387 && ctnetlink_dump_helpinfo(skb
, ct
) < 0)
390 if (ctnetlink_dump_counters(skb
, ct
, IP_CT_DIR_ORIGINAL
) < 0 ||
391 ctnetlink_dump_counters(skb
, ct
, IP_CT_DIR_REPLY
) < 0)
394 if (events
& IPCT_MARK
395 && ctnetlink_dump_mark(skb
, ct
) < 0)
398 nlh
->nlmsg_len
= skb
->tail
- b
;
399 nfnetlink_send(skb
, 0, group
, 0);
407 #endif /* CONFIG_NF_CONNTRACK_EVENTS */
409 static int ctnetlink_done(struct netlink_callback
*cb
)
412 nf_ct_put((struct nf_conn
*)cb
->args
[1]);
413 DEBUGP("entered %s\n", __FUNCTION__
);
417 #define L3PROTO(ct) ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num
420 ctnetlink_dump_table(struct sk_buff
*skb
, struct netlink_callback
*cb
)
422 struct nf_conn
*ct
, *last
;
423 struct nf_conntrack_tuple_hash
*h
;
425 struct nfgenmsg
*nfmsg
= NLMSG_DATA(cb
->nlh
);
426 u_int8_t l3proto
= nfmsg
->nfgen_family
;
428 DEBUGP("entered %s, last bucket=%lu id=%u\n", __FUNCTION__
,
431 read_lock_bh(&nf_conntrack_lock
);
432 last
= (struct nf_conn
*)cb
->args
[1];
433 for (; cb
->args
[0] < nf_conntrack_htable_size
; cb
->args
[0]++) {
435 list_for_each_prev(i
, &nf_conntrack_hash
[cb
->args
[0]]) {
436 h
= (struct nf_conntrack_tuple_hash
*) i
;
437 if (DIRECTION(h
) != IP_CT_DIR_ORIGINAL
)
439 ct
= nf_ct_tuplehash_to_ctrack(h
);
440 /* Dump entries of a given L3 protocol number.
441 * If it is not specified, ie. l3proto == 0,
442 * then dump everything. */
443 if (l3proto
&& L3PROTO(ct
) != l3proto
)
450 if (ctnetlink_fill_info(skb
, NETLINK_CB(cb
->skb
).pid
,
454 nf_conntrack_get(&ct
->ct_general
);
455 cb
->args
[1] = (unsigned long)ct
;
458 #ifdef CONFIG_NF_CT_ACCT
459 if (NFNL_MSG_TYPE(cb
->nlh
->nlmsg_type
) ==
460 IPCTNL_MSG_CT_GET_CTRZERO
)
461 memset(&ct
->counters
, 0, sizeof(ct
->counters
));
470 read_unlock_bh(&nf_conntrack_lock
);
474 DEBUGP("leaving, last bucket=%lu id=%u\n", cb
->args
[0], *id
);
479 ctnetlink_parse_tuple_ip(struct nfattr
*attr
, struct nf_conntrack_tuple
*tuple
)
481 struct nfattr
*tb
[CTA_IP_MAX
];
482 struct nf_conntrack_l3proto
*l3proto
;
485 DEBUGP("entered %s\n", __FUNCTION__
);
487 nfattr_parse_nested(tb
, CTA_IP_MAX
, attr
);
489 l3proto
= nf_ct_l3proto_find_get(tuple
->src
.l3num
);
491 if (likely(l3proto
->nfattr_to_tuple
))
492 ret
= l3proto
->nfattr_to_tuple(tb
, tuple
);
494 nf_ct_l3proto_put(l3proto
);
501 static const size_t cta_min_proto
[CTA_PROTO_MAX
] = {
502 [CTA_PROTO_NUM
-1] = sizeof(u_int8_t
),
506 ctnetlink_parse_tuple_proto(struct nfattr
*attr
,
507 struct nf_conntrack_tuple
*tuple
)
509 struct nfattr
*tb
[CTA_PROTO_MAX
];
510 struct nf_conntrack_protocol
*proto
;
513 DEBUGP("entered %s\n", __FUNCTION__
);
515 nfattr_parse_nested(tb
, CTA_PROTO_MAX
, attr
);
517 if (nfattr_bad_size(tb
, CTA_PROTO_MAX
, cta_min_proto
))
520 if (!tb
[CTA_PROTO_NUM
-1])
522 tuple
->dst
.protonum
= *(u_int8_t
*)NFA_DATA(tb
[CTA_PROTO_NUM
-1]);
524 proto
= nf_ct_proto_find_get(tuple
->src
.l3num
, tuple
->dst
.protonum
);
526 if (likely(proto
->nfattr_to_tuple
))
527 ret
= proto
->nfattr_to_tuple(tb
, tuple
);
529 nf_ct_proto_put(proto
);
535 ctnetlink_parse_tuple(struct nfattr
*cda
[], struct nf_conntrack_tuple
*tuple
,
536 enum ctattr_tuple type
, u_int8_t l3num
)
538 struct nfattr
*tb
[CTA_TUPLE_MAX
];
541 DEBUGP("entered %s\n", __FUNCTION__
);
543 memset(tuple
, 0, sizeof(*tuple
));
545 nfattr_parse_nested(tb
, CTA_TUPLE_MAX
, cda
[type
-1]);
547 if (!tb
[CTA_TUPLE_IP
-1])
550 tuple
->src
.l3num
= l3num
;
552 err
= ctnetlink_parse_tuple_ip(tb
[CTA_TUPLE_IP
-1], tuple
);
556 if (!tb
[CTA_TUPLE_PROTO
-1])
559 err
= ctnetlink_parse_tuple_proto(tb
[CTA_TUPLE_PROTO
-1], tuple
);
563 /* orig and expect tuples get DIR_ORIGINAL */
564 if (type
== CTA_TUPLE_REPLY
)
565 tuple
->dst
.dir
= IP_CT_DIR_REPLY
;
567 tuple
->dst
.dir
= IP_CT_DIR_ORIGINAL
;
569 NF_CT_DUMP_TUPLE(tuple
);
576 #ifdef CONFIG_IP_NF_NAT_NEEDED
577 static const size_t cta_min_protonat
[CTA_PROTONAT_MAX
] = {
578 [CTA_PROTONAT_PORT_MIN
-1] = sizeof(u_int16_t
),
579 [CTA_PROTONAT_PORT_MAX
-1] = sizeof(u_int16_t
),
582 static int ctnetlink_parse_nat_proto(struct nfattr
*attr
,
583 const struct nf_conn
*ct
,
584 struct ip_nat_range
*range
)
586 struct nfattr
*tb
[CTA_PROTONAT_MAX
];
587 struct ip_nat_protocol
*npt
;
589 DEBUGP("entered %s\n", __FUNCTION__
);
591 nfattr_parse_nested(tb
, CTA_PROTONAT_MAX
, attr
);
593 if (nfattr_bad_size(tb
, CTA_PROTONAT_MAX
, cta_min_protonat
))
596 npt
= ip_nat_proto_find_get(ct
->tuplehash
[IP_CT_DIR_ORIGINAL
].tuple
.dst
.protonum
);
598 if (!npt
->nfattr_to_range
) {
599 ip_nat_proto_put(npt
);
603 /* nfattr_to_range returns 1 if it parsed, 0 if not, neg. on error */
604 if (npt
->nfattr_to_range(tb
, range
) > 0)
605 range
->flags
|= IP_NAT_RANGE_PROTO_SPECIFIED
;
607 ip_nat_proto_put(npt
);
613 static const size_t cta_min_nat
[CTA_NAT_MAX
] = {
614 [CTA_NAT_MINIP
-1] = sizeof(u_int32_t
),
615 [CTA_NAT_MAXIP
-1] = sizeof(u_int32_t
),
619 ctnetlink_parse_nat(struct nfattr
*nat
,
620 const struct nf_conn
*ct
, struct ip_nat_range
*range
)
622 struct nfattr
*tb
[CTA_NAT_MAX
];
625 DEBUGP("entered %s\n", __FUNCTION__
);
627 memset(range
, 0, sizeof(*range
));
629 nfattr_parse_nested(tb
, CTA_NAT_MAX
, nat
);
631 if (nfattr_bad_size(tb
, CTA_NAT_MAX
, cta_min_nat
))
634 if (tb
[CTA_NAT_MINIP
-1])
635 range
->min_ip
= *(u_int32_t
*)NFA_DATA(tb
[CTA_NAT_MINIP
-1]);
637 if (!tb
[CTA_NAT_MAXIP
-1])
638 range
->max_ip
= range
->min_ip
;
640 range
->max_ip
= *(u_int32_t
*)NFA_DATA(tb
[CTA_NAT_MAXIP
-1]);
643 range
->flags
|= IP_NAT_RANGE_MAP_IPS
;
645 if (!tb
[CTA_NAT_PROTO
-1])
648 err
= ctnetlink_parse_nat_proto(tb
[CTA_NAT_PROTO
-1], ct
, range
);
658 ctnetlink_parse_help(struct nfattr
*attr
, char **helper_name
)
660 struct nfattr
*tb
[CTA_HELP_MAX
];
662 DEBUGP("entered %s\n", __FUNCTION__
);
664 nfattr_parse_nested(tb
, CTA_HELP_MAX
, attr
);
666 if (!tb
[CTA_HELP_NAME
-1])
669 *helper_name
= NFA_DATA(tb
[CTA_HELP_NAME
-1]);
674 static const size_t cta_min
[CTA_MAX
] = {
675 [CTA_STATUS
-1] = sizeof(u_int32_t
),
676 [CTA_TIMEOUT
-1] = sizeof(u_int32_t
),
677 [CTA_MARK
-1] = sizeof(u_int32_t
),
678 [CTA_USE
-1] = sizeof(u_int32_t
),
679 [CTA_ID
-1] = sizeof(u_int32_t
)
683 ctnetlink_del_conntrack(struct sock
*ctnl
, struct sk_buff
*skb
,
684 struct nlmsghdr
*nlh
, struct nfattr
*cda
[], int *errp
)
686 struct nf_conntrack_tuple_hash
*h
;
687 struct nf_conntrack_tuple tuple
;
689 struct nfgenmsg
*nfmsg
= NLMSG_DATA(nlh
);
690 u_int8_t u3
= nfmsg
->nfgen_family
;
693 DEBUGP("entered %s\n", __FUNCTION__
);
695 if (nfattr_bad_size(cda
, CTA_MAX
, cta_min
))
698 if (cda
[CTA_TUPLE_ORIG
-1])
699 err
= ctnetlink_parse_tuple(cda
, &tuple
, CTA_TUPLE_ORIG
, u3
);
700 else if (cda
[CTA_TUPLE_REPLY
-1])
701 err
= ctnetlink_parse_tuple(cda
, &tuple
, CTA_TUPLE_REPLY
, u3
);
703 /* Flush the whole table */
704 nf_conntrack_flush();
711 h
= nf_conntrack_find_get(&tuple
, NULL
);
713 DEBUGP("tuple not found in conntrack hash\n");
717 ct
= nf_ct_tuplehash_to_ctrack(h
);
720 u_int32_t id
= ntohl(*(u_int32_t
*)NFA_DATA(cda
[CTA_ID
-1]));
726 if (del_timer(&ct
->timeout
))
727 ct
->timeout
.function((unsigned long)ct
);
736 ctnetlink_get_conntrack(struct sock
*ctnl
, struct sk_buff
*skb
,
737 struct nlmsghdr
*nlh
, struct nfattr
*cda
[], int *errp
)
739 struct nf_conntrack_tuple_hash
*h
;
740 struct nf_conntrack_tuple tuple
;
742 struct sk_buff
*skb2
= NULL
;
743 struct nfgenmsg
*nfmsg
= NLMSG_DATA(nlh
);
744 u_int8_t u3
= nfmsg
->nfgen_family
;
747 DEBUGP("entered %s\n", __FUNCTION__
);
749 if (nlh
->nlmsg_flags
& NLM_F_DUMP
) {
752 #ifndef CONFIG_NF_CT_ACCT
753 if (NFNL_MSG_TYPE(nlh
->nlmsg_type
) == IPCTNL_MSG_CT_GET_CTRZERO
)
756 if ((*errp
= netlink_dump_start(ctnl
, skb
, nlh
,
757 ctnetlink_dump_table
,
758 ctnetlink_done
)) != 0)
761 rlen
= NLMSG_ALIGN(nlh
->nlmsg_len
);
768 if (nfattr_bad_size(cda
, CTA_MAX
, cta_min
))
771 if (cda
[CTA_TUPLE_ORIG
-1])
772 err
= ctnetlink_parse_tuple(cda
, &tuple
, CTA_TUPLE_ORIG
, u3
);
773 else if (cda
[CTA_TUPLE_REPLY
-1])
774 err
= ctnetlink_parse_tuple(cda
, &tuple
, CTA_TUPLE_REPLY
, u3
);
781 h
= nf_conntrack_find_get(&tuple
, NULL
);
783 DEBUGP("tuple not found in conntrack hash");
786 DEBUGP("tuple found\n");
787 ct
= nf_ct_tuplehash_to_ctrack(h
);
790 skb2
= alloc_skb(NLMSG_GOODSIZE
, GFP_KERNEL
);
795 NETLINK_CB(skb2
).dst_pid
= NETLINK_CB(skb
).pid
;
797 err
= ctnetlink_fill_info(skb2
, NETLINK_CB(skb
).pid
, nlh
->nlmsg_seq
,
798 IPCTNL_MSG_CT_NEW
, 1, ct
);
803 err
= netlink_unicast(ctnl
, skb2
, NETLINK_CB(skb
).pid
, MSG_DONTWAIT
);
817 ctnetlink_change_status(struct nf_conn
*ct
, struct nfattr
*cda
[])
820 unsigned status
= ntohl(*(u_int32_t
*)NFA_DATA(cda
[CTA_STATUS
-1]));
821 d
= ct
->status
^ status
;
823 if (d
& (IPS_EXPECTED
|IPS_CONFIRMED
|IPS_DYING
))
827 if (d
& IPS_SEEN_REPLY
&& !(status
& IPS_SEEN_REPLY
))
828 /* SEEN_REPLY bit can only be set */
832 if (d
& IPS_ASSURED
&& !(status
& IPS_ASSURED
))
833 /* ASSURED bit can only be set */
836 if (cda
[CTA_NAT_SRC
-1] || cda
[CTA_NAT_DST
-1]) {
837 #ifndef CONFIG_IP_NF_NAT_NEEDED
840 struct ip_nat_range range
;
842 if (cda
[CTA_NAT_DST
-1]) {
843 if (ctnetlink_parse_nat(cda
[CTA_NAT_DST
-1], ct
,
846 if (ip_nat_initialized(ct
,
847 HOOK2MANIP(NF_IP_PRE_ROUTING
)))
849 ip_nat_setup_info(ct
, &range
, hooknum
);
851 if (cda
[CTA_NAT_SRC
-1]) {
852 if (ctnetlink_parse_nat(cda
[CTA_NAT_SRC
-1], ct
,
855 if (ip_nat_initialized(ct
,
856 HOOK2MANIP(NF_IP_POST_ROUTING
)))
858 ip_nat_setup_info(ct
, &range
, hooknum
);
863 /* Be careful here, modifying NAT bits can screw up things,
864 * so don't let users modify them directly if they don't pass
866 ct
->status
|= status
& ~(IPS_NAT_DONE_MASK
| IPS_NAT_MASK
);
872 ctnetlink_change_helper(struct nf_conn
*ct
, struct nfattr
*cda
[])
874 struct nf_conntrack_helper
*helper
;
875 struct nf_conn_help
*help
= nfct_help(ct
);
879 DEBUGP("entered %s\n", __FUNCTION__
);
882 /* FIXME: we need to reallocate and rehash */
886 /* don't change helper of sibling connections */
890 err
= ctnetlink_parse_help(cda
[CTA_HELP
-1], &helpname
);
894 helper
= __nf_conntrack_helper_find_byname(helpname
);
896 if (!strcmp(helpname
, ""))
904 /* we had a helper before ... */
905 nf_ct_remove_expectations(ct
);
908 /* need to zero data of old helper */
909 memset(&help
->help
, 0, sizeof(help
->help
));
913 help
->helper
= helper
;
919 ctnetlink_change_timeout(struct nf_conn
*ct
, struct nfattr
*cda
[])
921 u_int32_t timeout
= ntohl(*(u_int32_t
*)NFA_DATA(cda
[CTA_TIMEOUT
-1]));
923 if (!del_timer(&ct
->timeout
))
926 ct
->timeout
.expires
= jiffies
+ timeout
* HZ
;
927 add_timer(&ct
->timeout
);
933 ctnetlink_change_protoinfo(struct nf_conn
*ct
, struct nfattr
*cda
[])
935 struct nfattr
*tb
[CTA_PROTOINFO_MAX
], *attr
= cda
[CTA_PROTOINFO
-1];
936 struct nf_conntrack_protocol
*proto
;
937 u_int16_t npt
= ct
->tuplehash
[IP_CT_DIR_ORIGINAL
].tuple
.dst
.protonum
;
938 u_int16_t l3num
= ct
->tuplehash
[IP_CT_DIR_ORIGINAL
].tuple
.src
.l3num
;
941 nfattr_parse_nested(tb
, CTA_PROTOINFO_MAX
, attr
);
943 proto
= nf_ct_proto_find_get(l3num
, npt
);
945 if (proto
->from_nfattr
)
946 err
= proto
->from_nfattr(tb
, ct
);
947 nf_ct_proto_put(proto
);
953 ctnetlink_change_conntrack(struct nf_conn
*ct
, struct nfattr
*cda
[])
957 DEBUGP("entered %s\n", __FUNCTION__
);
959 if (cda
[CTA_HELP
-1]) {
960 err
= ctnetlink_change_helper(ct
, cda
);
965 if (cda
[CTA_TIMEOUT
-1]) {
966 err
= ctnetlink_change_timeout(ct
, cda
);
971 if (cda
[CTA_STATUS
-1]) {
972 err
= ctnetlink_change_status(ct
, cda
);
977 if (cda
[CTA_PROTOINFO
-1]) {
978 err
= ctnetlink_change_protoinfo(ct
, cda
);
983 #if defined(CONFIG_NF_CONNTRACK_MARK)
985 ct
->mark
= ntohl(*(u_int32_t
*)NFA_DATA(cda
[CTA_MARK
-1]));
988 DEBUGP("all done\n");
993 ctnetlink_create_conntrack(struct nfattr
*cda
[],
994 struct nf_conntrack_tuple
*otuple
,
995 struct nf_conntrack_tuple
*rtuple
)
1000 DEBUGP("entered %s\n", __FUNCTION__
);
1002 ct
= nf_conntrack_alloc(otuple
, rtuple
);
1003 if (ct
== NULL
|| IS_ERR(ct
))
1006 if (!cda
[CTA_TIMEOUT
-1])
1008 ct
->timeout
.expires
= ntohl(*(u_int32_t
*)NFA_DATA(cda
[CTA_TIMEOUT
-1]));
1010 ct
->timeout
.expires
= jiffies
+ ct
->timeout
.expires
* HZ
;
1011 ct
->status
|= IPS_CONFIRMED
;
1013 err
= ctnetlink_change_status(ct
, cda
);
1017 if (cda
[CTA_PROTOINFO
-1]) {
1018 err
= ctnetlink_change_protoinfo(ct
, cda
);
1023 #if defined(CONFIG_NF_CONNTRACK_MARK)
1024 if (cda
[CTA_MARK
-1])
1025 ct
->mark
= ntohl(*(u_int32_t
*)NFA_DATA(cda
[CTA_MARK
-1]));
1028 add_timer(&ct
->timeout
);
1029 nf_conntrack_hash_insert(ct
);
1031 DEBUGP("conntrack with id %u inserted\n", ct
->id
);
1035 nf_conntrack_free(ct
);
1040 ctnetlink_new_conntrack(struct sock
*ctnl
, struct sk_buff
*skb
,
1041 struct nlmsghdr
*nlh
, struct nfattr
*cda
[], int *errp
)
1043 struct nf_conntrack_tuple otuple
, rtuple
;
1044 struct nf_conntrack_tuple_hash
*h
= NULL
;
1045 struct nfgenmsg
*nfmsg
= NLMSG_DATA(nlh
);
1046 u_int8_t u3
= nfmsg
->nfgen_family
;
1049 DEBUGP("entered %s\n", __FUNCTION__
);
1051 if (nfattr_bad_size(cda
, CTA_MAX
, cta_min
))
1054 if (cda
[CTA_TUPLE_ORIG
-1]) {
1055 err
= ctnetlink_parse_tuple(cda
, &otuple
, CTA_TUPLE_ORIG
, u3
);
1060 if (cda
[CTA_TUPLE_REPLY
-1]) {
1061 err
= ctnetlink_parse_tuple(cda
, &rtuple
, CTA_TUPLE_REPLY
, u3
);
1066 write_lock_bh(&nf_conntrack_lock
);
1067 if (cda
[CTA_TUPLE_ORIG
-1])
1068 h
= __nf_conntrack_find(&otuple
, NULL
);
1069 else if (cda
[CTA_TUPLE_REPLY
-1])
1070 h
= __nf_conntrack_find(&rtuple
, NULL
);
1073 write_unlock_bh(&nf_conntrack_lock
);
1074 DEBUGP("no such conntrack, create new\n");
1076 if (nlh
->nlmsg_flags
& NLM_F_CREATE
)
1077 err
= ctnetlink_create_conntrack(cda
, &otuple
, &rtuple
);
1080 /* implicit 'else' */
1082 /* we only allow nat config for new conntracks */
1083 if (cda
[CTA_NAT_SRC
-1] || cda
[CTA_NAT_DST
-1]) {
1088 /* We manipulate the conntrack inside the global conntrack table lock,
1089 * so there's no need to increase the refcount */
1090 DEBUGP("conntrack found\n");
1092 if (!(nlh
->nlmsg_flags
& NLM_F_EXCL
))
1093 err
= ctnetlink_change_conntrack(nf_ct_tuplehash_to_ctrack(h
), cda
);
1096 write_unlock_bh(&nf_conntrack_lock
);
1100 /***********************************************************************
1102 ***********************************************************************/
1105 ctnetlink_exp_dump_tuple(struct sk_buff
*skb
,
1106 const struct nf_conntrack_tuple
*tuple
,
1107 enum ctattr_expect type
)
1109 struct nfattr
*nest_parms
= NFA_NEST(skb
, type
);
1111 if (ctnetlink_dump_tuples(skb
, tuple
) < 0)
1112 goto nfattr_failure
;
1114 NFA_NEST_END(skb
, nest_parms
);
1123 ctnetlink_exp_dump_mask(struct sk_buff
*skb
,
1124 const struct nf_conntrack_tuple
*tuple
,
1125 const struct nf_conntrack_tuple
*mask
)
1128 struct nf_conntrack_l3proto
*l3proto
;
1129 struct nf_conntrack_protocol
*proto
;
1130 struct nfattr
*nest_parms
= NFA_NEST(skb
, CTA_EXPECT_MASK
);
1132 l3proto
= nf_ct_l3proto_find_get(tuple
->src
.l3num
);
1133 ret
= ctnetlink_dump_tuples_ip(skb
, mask
, l3proto
);
1134 nf_ct_l3proto_put(l3proto
);
1136 if (unlikely(ret
< 0))
1137 goto nfattr_failure
;
1139 proto
= nf_ct_proto_find_get(tuple
->src
.l3num
, tuple
->dst
.protonum
);
1140 ret
= ctnetlink_dump_tuples_proto(skb
, mask
, proto
);
1141 nf_ct_proto_put(proto
);
1142 if (unlikely(ret
< 0))
1143 goto nfattr_failure
;
1145 NFA_NEST_END(skb
, nest_parms
);
1154 ctnetlink_exp_dump_expect(struct sk_buff
*skb
,
1155 const struct nf_conntrack_expect
*exp
)
1157 struct nf_conn
*master
= exp
->master
;
1158 u_int32_t timeout
= htonl((exp
->timeout
.expires
- jiffies
) / HZ
);
1159 u_int32_t id
= htonl(exp
->id
);
1161 if (ctnetlink_exp_dump_tuple(skb
, &exp
->tuple
, CTA_EXPECT_TUPLE
) < 0)
1162 goto nfattr_failure
;
1163 if (ctnetlink_exp_dump_mask(skb
, &exp
->tuple
, &exp
->mask
) < 0)
1164 goto nfattr_failure
;
1165 if (ctnetlink_exp_dump_tuple(skb
,
1166 &master
->tuplehash
[IP_CT_DIR_ORIGINAL
].tuple
,
1167 CTA_EXPECT_MASTER
) < 0)
1168 goto nfattr_failure
;
1170 NFA_PUT(skb
, CTA_EXPECT_TIMEOUT
, sizeof(timeout
), &timeout
);
1171 NFA_PUT(skb
, CTA_EXPECT_ID
, sizeof(u_int32_t
), &id
);
1180 ctnetlink_exp_fill_info(struct sk_buff
*skb
, u32 pid
, u32 seq
,
1183 const struct nf_conntrack_expect
*exp
)
1185 struct nlmsghdr
*nlh
;
1186 struct nfgenmsg
*nfmsg
;
1191 event
|= NFNL_SUBSYS_CTNETLINK_EXP
<< 8;
1192 nlh
= NLMSG_PUT(skb
, pid
, seq
, event
, sizeof(struct nfgenmsg
));
1193 nfmsg
= NLMSG_DATA(nlh
);
1195 nlh
->nlmsg_flags
= (nowait
&& pid
) ? NLM_F_MULTI
: 0;
1196 nfmsg
->nfgen_family
= exp
->tuple
.src
.l3num
;
1197 nfmsg
->version
= NFNETLINK_V0
;
1200 if (ctnetlink_exp_dump_expect(skb
, exp
) < 0)
1201 goto nfattr_failure
;
1203 nlh
->nlmsg_len
= skb
->tail
- b
;
1208 skb_trim(skb
, b
- skb
->data
);
1212 #ifdef CONFIG_NF_CONNTRACK_EVENTS
1213 static int ctnetlink_expect_event(struct notifier_block
*this,
1214 unsigned long events
, void *ptr
)
1216 struct nlmsghdr
*nlh
;
1217 struct nfgenmsg
*nfmsg
;
1218 struct nf_conntrack_expect
*exp
= (struct nf_conntrack_expect
*)ptr
;
1219 struct sk_buff
*skb
;
1224 if (events
& IPEXP_NEW
) {
1225 type
= IPCTNL_MSG_EXP_NEW
;
1226 flags
= NLM_F_CREATE
|NLM_F_EXCL
;
1230 if (!nfnetlink_has_listeners(NFNLGRP_CONNTRACK_EXP_NEW
))
1233 skb
= alloc_skb(NLMSG_GOODSIZE
, GFP_ATOMIC
);
1239 type
|= NFNL_SUBSYS_CTNETLINK_EXP
<< 8;
1240 nlh
= NLMSG_PUT(skb
, 0, 0, type
, sizeof(struct nfgenmsg
));
1241 nfmsg
= NLMSG_DATA(nlh
);
1243 nlh
->nlmsg_flags
= flags
;
1244 nfmsg
->nfgen_family
= exp
->tuple
.src
.l3num
;
1245 nfmsg
->version
= NFNETLINK_V0
;
1248 if (ctnetlink_exp_dump_expect(skb
, exp
) < 0)
1249 goto nfattr_failure
;
1251 nlh
->nlmsg_len
= skb
->tail
- b
;
1252 nfnetlink_send(skb
, 0, NFNLGRP_CONNTRACK_EXP_NEW
, 0);
1263 ctnetlink_exp_dump_table(struct sk_buff
*skb
, struct netlink_callback
*cb
)
1265 struct nf_conntrack_expect
*exp
= NULL
;
1266 struct list_head
*i
;
1267 u_int32_t
*id
= (u_int32_t
*) &cb
->args
[0];
1268 struct nfgenmsg
*nfmsg
= NLMSG_DATA(cb
->nlh
);
1269 u_int8_t l3proto
= nfmsg
->nfgen_family
;
1271 DEBUGP("entered %s, last id=%llu\n", __FUNCTION__
, *id
);
1273 read_lock_bh(&nf_conntrack_lock
);
1274 list_for_each_prev(i
, &nf_conntrack_expect_list
) {
1275 exp
= (struct nf_conntrack_expect
*) i
;
1276 if (l3proto
&& exp
->tuple
.src
.l3num
!= l3proto
)
1280 if (ctnetlink_exp_fill_info(skb
, NETLINK_CB(cb
->skb
).pid
,
1288 read_unlock_bh(&nf_conntrack_lock
);
1290 DEBUGP("leaving, last id=%llu\n", *id
);
1295 static const size_t cta_min_exp
[CTA_EXPECT_MAX
] = {
1296 [CTA_EXPECT_TIMEOUT
-1] = sizeof(u_int32_t
),
1297 [CTA_EXPECT_ID
-1] = sizeof(u_int32_t
)
1301 ctnetlink_get_expect(struct sock
*ctnl
, struct sk_buff
*skb
,
1302 struct nlmsghdr
*nlh
, struct nfattr
*cda
[], int *errp
)
1304 struct nf_conntrack_tuple tuple
;
1305 struct nf_conntrack_expect
*exp
;
1306 struct sk_buff
*skb2
;
1307 struct nfgenmsg
*nfmsg
= NLMSG_DATA(nlh
);
1308 u_int8_t u3
= nfmsg
->nfgen_family
;
1311 DEBUGP("entered %s\n", __FUNCTION__
);
1313 if (nfattr_bad_size(cda
, CTA_EXPECT_MAX
, cta_min_exp
))
1316 if (nlh
->nlmsg_flags
& NLM_F_DUMP
) {
1319 if ((*errp
= netlink_dump_start(ctnl
, skb
, nlh
,
1320 ctnetlink_exp_dump_table
,
1321 ctnetlink_done
)) != 0)
1323 rlen
= NLMSG_ALIGN(nlh
->nlmsg_len
);
1324 if (rlen
> skb
->len
)
1326 skb_pull(skb
, rlen
);
1330 if (cda
[CTA_EXPECT_MASTER
-1])
1331 err
= ctnetlink_parse_tuple(cda
, &tuple
, CTA_EXPECT_MASTER
, u3
);
1338 exp
= nf_conntrack_expect_find(&tuple
);
1342 if (cda
[CTA_EXPECT_ID
-1]) {
1343 u_int32_t id
= *(u_int32_t
*)NFA_DATA(cda
[CTA_EXPECT_ID
-1]);
1344 if (exp
->id
!= ntohl(id
)) {
1345 nf_conntrack_expect_put(exp
);
1351 skb2
= alloc_skb(NLMSG_GOODSIZE
, GFP_KERNEL
);
1354 NETLINK_CB(skb2
).dst_pid
= NETLINK_CB(skb
).pid
;
1356 err
= ctnetlink_exp_fill_info(skb2
, NETLINK_CB(skb
).pid
,
1357 nlh
->nlmsg_seq
, IPCTNL_MSG_EXP_NEW
,
1362 nf_conntrack_expect_put(exp
);
1364 return netlink_unicast(ctnl
, skb2
, NETLINK_CB(skb
).pid
, MSG_DONTWAIT
);
1369 nf_conntrack_expect_put(exp
);
1374 ctnetlink_del_expect(struct sock
*ctnl
, struct sk_buff
*skb
,
1375 struct nlmsghdr
*nlh
, struct nfattr
*cda
[], int *errp
)
1377 struct nf_conntrack_expect
*exp
, *tmp
;
1378 struct nf_conntrack_tuple tuple
;
1379 struct nf_conntrack_helper
*h
;
1380 struct nfgenmsg
*nfmsg
= NLMSG_DATA(nlh
);
1381 u_int8_t u3
= nfmsg
->nfgen_family
;
1384 if (nfattr_bad_size(cda
, CTA_EXPECT_MAX
, cta_min_exp
))
1387 if (cda
[CTA_EXPECT_TUPLE
-1]) {
1388 /* delete a single expect by tuple */
1389 err
= ctnetlink_parse_tuple(cda
, &tuple
, CTA_EXPECT_TUPLE
, u3
);
1393 /* bump usage count to 2 */
1394 exp
= nf_conntrack_expect_find(&tuple
);
1398 if (cda
[CTA_EXPECT_ID
-1]) {
1400 *(u_int32_t
*)NFA_DATA(cda
[CTA_EXPECT_ID
-1]);
1401 if (exp
->id
!= ntohl(id
)) {
1402 nf_conntrack_expect_put(exp
);
1407 /* after list removal, usage count == 1 */
1408 nf_conntrack_unexpect_related(exp
);
1409 /* have to put what we 'get' above.
1410 * after this line usage count == 0 */
1411 nf_conntrack_expect_put(exp
);
1412 } else if (cda
[CTA_EXPECT_HELP_NAME
-1]) {
1413 char *name
= NFA_DATA(cda
[CTA_EXPECT_HELP_NAME
-1]);
1415 /* delete all expectations for this helper */
1416 write_lock_bh(&nf_conntrack_lock
);
1417 h
= __nf_conntrack_helper_find_byname(name
);
1419 write_unlock_bh(&nf_conntrack_lock
);
1422 list_for_each_entry_safe(exp
, tmp
, &nf_conntrack_expect_list
,
1424 struct nf_conn_help
*m_help
= nfct_help(exp
->master
);
1425 if (m_help
->helper
== h
1426 && del_timer(&exp
->timeout
)) {
1427 nf_ct_unlink_expect(exp
);
1428 nf_conntrack_expect_put(exp
);
1431 write_unlock_bh(&nf_conntrack_lock
);
1433 /* This basically means we have to flush everything*/
1434 write_lock_bh(&nf_conntrack_lock
);
1435 list_for_each_entry_safe(exp
, tmp
, &nf_conntrack_expect_list
,
1437 if (del_timer(&exp
->timeout
)) {
1438 nf_ct_unlink_expect(exp
);
1439 nf_conntrack_expect_put(exp
);
1442 write_unlock_bh(&nf_conntrack_lock
);
1448 ctnetlink_change_expect(struct nf_conntrack_expect
*x
, struct nfattr
*cda
[])
1454 ctnetlink_create_expect(struct nfattr
*cda
[], u_int8_t u3
)
1456 struct nf_conntrack_tuple tuple
, mask
, master_tuple
;
1457 struct nf_conntrack_tuple_hash
*h
= NULL
;
1458 struct nf_conntrack_expect
*exp
;
1460 struct nf_conn_help
*help
;
1463 DEBUGP("entered %s\n", __FUNCTION__
);
1465 /* caller guarantees that those three CTA_EXPECT_* exist */
1466 err
= ctnetlink_parse_tuple(cda
, &tuple
, CTA_EXPECT_TUPLE
, u3
);
1469 err
= ctnetlink_parse_tuple(cda
, &mask
, CTA_EXPECT_MASK
, u3
);
1472 err
= ctnetlink_parse_tuple(cda
, &master_tuple
, CTA_EXPECT_MASTER
, u3
);
1476 /* Look for master conntrack of this expectation */
1477 h
= nf_conntrack_find_get(&master_tuple
, NULL
);
1480 ct
= nf_ct_tuplehash_to_ctrack(h
);
1481 help
= nfct_help(ct
);
1483 if (!help
|| !help
->helper
) {
1484 /* such conntrack hasn't got any helper, abort */
1489 exp
= nf_conntrack_expect_alloc(ct
);
1495 exp
->expectfn
= NULL
;
1498 memcpy(&exp
->tuple
, &tuple
, sizeof(struct nf_conntrack_tuple
));
1499 memcpy(&exp
->mask
, &mask
, sizeof(struct nf_conntrack_tuple
));
1501 err
= nf_conntrack_expect_related(exp
);
1502 nf_conntrack_expect_put(exp
);
1505 nf_ct_put(nf_ct_tuplehash_to_ctrack(h
));
1510 ctnetlink_new_expect(struct sock
*ctnl
, struct sk_buff
*skb
,
1511 struct nlmsghdr
*nlh
, struct nfattr
*cda
[], int *errp
)
1513 struct nf_conntrack_tuple tuple
;
1514 struct nf_conntrack_expect
*exp
;
1515 struct nfgenmsg
*nfmsg
= NLMSG_DATA(nlh
);
1516 u_int8_t u3
= nfmsg
->nfgen_family
;
1519 DEBUGP("entered %s\n", __FUNCTION__
);
1521 if (nfattr_bad_size(cda
, CTA_EXPECT_MAX
, cta_min_exp
))
1524 if (!cda
[CTA_EXPECT_TUPLE
-1]
1525 || !cda
[CTA_EXPECT_MASK
-1]
1526 || !cda
[CTA_EXPECT_MASTER
-1])
1529 err
= ctnetlink_parse_tuple(cda
, &tuple
, CTA_EXPECT_TUPLE
, u3
);
1533 write_lock_bh(&nf_conntrack_lock
);
1534 exp
= __nf_conntrack_expect_find(&tuple
);
1537 write_unlock_bh(&nf_conntrack_lock
);
1539 if (nlh
->nlmsg_flags
& NLM_F_CREATE
)
1540 err
= ctnetlink_create_expect(cda
, u3
);
1545 if (!(nlh
->nlmsg_flags
& NLM_F_EXCL
))
1546 err
= ctnetlink_change_expect(exp
, cda
);
1547 write_unlock_bh(&nf_conntrack_lock
);
1549 DEBUGP("leaving\n");
1554 #ifdef CONFIG_NF_CONNTRACK_EVENTS
1555 static struct notifier_block ctnl_notifier
= {
1556 .notifier_call
= ctnetlink_conntrack_event
,
1559 static struct notifier_block ctnl_notifier_exp
= {
1560 .notifier_call
= ctnetlink_expect_event
,
1564 static struct nfnl_callback ctnl_cb
[IPCTNL_MSG_MAX
] = {
1565 [IPCTNL_MSG_CT_NEW
] = { .call
= ctnetlink_new_conntrack
,
1566 .attr_count
= CTA_MAX
, },
1567 [IPCTNL_MSG_CT_GET
] = { .call
= ctnetlink_get_conntrack
,
1568 .attr_count
= CTA_MAX
, },
1569 [IPCTNL_MSG_CT_DELETE
] = { .call
= ctnetlink_del_conntrack
,
1570 .attr_count
= CTA_MAX
, },
1571 [IPCTNL_MSG_CT_GET_CTRZERO
] = { .call
= ctnetlink_get_conntrack
,
1572 .attr_count
= CTA_MAX
, },
1575 static struct nfnl_callback ctnl_exp_cb
[IPCTNL_MSG_EXP_MAX
] = {
1576 [IPCTNL_MSG_EXP_GET
] = { .call
= ctnetlink_get_expect
,
1577 .attr_count
= CTA_EXPECT_MAX
, },
1578 [IPCTNL_MSG_EXP_NEW
] = { .call
= ctnetlink_new_expect
,
1579 .attr_count
= CTA_EXPECT_MAX
, },
1580 [IPCTNL_MSG_EXP_DELETE
] = { .call
= ctnetlink_del_expect
,
1581 .attr_count
= CTA_EXPECT_MAX
, },
1584 static struct nfnetlink_subsystem ctnl_subsys
= {
1585 .name
= "conntrack",
1586 .subsys_id
= NFNL_SUBSYS_CTNETLINK
,
1587 .cb_count
= IPCTNL_MSG_MAX
,
1591 static struct nfnetlink_subsystem ctnl_exp_subsys
= {
1592 .name
= "conntrack_expect",
1593 .subsys_id
= NFNL_SUBSYS_CTNETLINK_EXP
,
1594 .cb_count
= IPCTNL_MSG_EXP_MAX
,
1598 MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK
);
1599 MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_EXP
);
1601 static int __init
ctnetlink_init(void)
1605 printk("ctnetlink v%s: registering with nfnetlink.\n", version
);
1606 ret
= nfnetlink_subsys_register(&ctnl_subsys
);
1608 printk("ctnetlink_init: cannot register with nfnetlink.\n");
1612 ret
= nfnetlink_subsys_register(&ctnl_exp_subsys
);
1614 printk("ctnetlink_init: cannot register exp with nfnetlink.\n");
1615 goto err_unreg_subsys
;
1618 #ifdef CONFIG_NF_CONNTRACK_EVENTS
1619 ret
= nf_conntrack_register_notifier(&ctnl_notifier
);
1621 printk("ctnetlink_init: cannot register notifier.\n");
1622 goto err_unreg_exp_subsys
;
1625 ret
= nf_conntrack_expect_register_notifier(&ctnl_notifier_exp
);
1627 printk("ctnetlink_init: cannot expect register notifier.\n");
1628 goto err_unreg_notifier
;
1634 #ifdef CONFIG_NF_CONNTRACK_EVENTS
1636 nf_conntrack_unregister_notifier(&ctnl_notifier
);
1637 err_unreg_exp_subsys
:
1638 nfnetlink_subsys_unregister(&ctnl_exp_subsys
);
1641 nfnetlink_subsys_unregister(&ctnl_subsys
);
1646 static void __exit
ctnetlink_exit(void)
1648 printk("ctnetlink: unregistering from nfnetlink.\n");
1650 #ifdef CONFIG_NF_CONNTRACK_EVENTS
1651 nf_conntrack_expect_unregister_notifier(&ctnl_notifier_exp
);
1652 nf_conntrack_unregister_notifier(&ctnl_notifier
);
1655 nfnetlink_subsys_unregister(&ctnl_exp_subsys
);
1656 nfnetlink_subsys_unregister(&ctnl_subsys
);
1660 module_init(ctnetlink_init
);
1661 module_exit(ctnetlink_exit
);