144d362409d5469aed47d19e7908d19bd194493aThomas Graf/*
244d362409d5469aed47d19e7908d19bd194493aThomas Graf * lib/netfilter/ct_obj.c	Conntrack Object
344d362409d5469aed47d19e7908d19bd194493aThomas Graf *
444d362409d5469aed47d19e7908d19bd194493aThomas Graf *	This library is free software; you can redistribute it and/or
544d362409d5469aed47d19e7908d19bd194493aThomas Graf *	modify it under the terms of the GNU Lesser General Public
644d362409d5469aed47d19e7908d19bd194493aThomas Graf *	License as published by the Free Software Foundation version 2.1
744d362409d5469aed47d19e7908d19bd194493aThomas Graf *	of the License.
844d362409d5469aed47d19e7908d19bd194493aThomas Graf *
98a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
1044d362409d5469aed47d19e7908d19bd194493aThomas Graf * Copyright (c) 2007 Philip Craig <philipc@snapgear.com>
1144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Copyright (c) 2007 Secure Computing Corporation
1244d362409d5469aed47d19e7908d19bd194493aThomas Graf */
1344d362409d5469aed47d19e7908d19bd194493aThomas Graf
1444d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <sys/types.h>
1544d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <linux/netfilter/nfnetlink_conntrack.h>
1644d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <linux/netfilter/nf_conntrack_common.h>
1744d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <linux/netfilter/nf_conntrack_tcp.h>
1844d362409d5469aed47d19e7908d19bd194493aThomas Graf
1944d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink-local.h>
2044d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/netfilter/nfnl.h>
2144d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/netfilter/ct.h>
2244d362409d5469aed47d19e7908d19bd194493aThomas Graf
2344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @cond SKIP */
2444d362409d5469aed47d19e7908d19bd194493aThomas Graf#define CT_ATTR_FAMILY		(1UL << 0)
2544d362409d5469aed47d19e7908d19bd194493aThomas Graf#define CT_ATTR_PROTO		(1UL << 1)
2644d362409d5469aed47d19e7908d19bd194493aThomas Graf
2744d362409d5469aed47d19e7908d19bd194493aThomas Graf#define CT_ATTR_TCP_STATE	(1UL << 2)
2844d362409d5469aed47d19e7908d19bd194493aThomas Graf
2944d362409d5469aed47d19e7908d19bd194493aThomas Graf#define CT_ATTR_STATUS		(1UL << 3)
3044d362409d5469aed47d19e7908d19bd194493aThomas Graf#define CT_ATTR_TIMEOUT		(1UL << 4)
3144d362409d5469aed47d19e7908d19bd194493aThomas Graf#define CT_ATTR_MARK		(1UL << 5)
3244d362409d5469aed47d19e7908d19bd194493aThomas Graf#define CT_ATTR_USE		(1UL << 6)
3344d362409d5469aed47d19e7908d19bd194493aThomas Graf#define CT_ATTR_ID		(1UL << 7)
3444d362409d5469aed47d19e7908d19bd194493aThomas Graf
3544d362409d5469aed47d19e7908d19bd194493aThomas Graf#define CT_ATTR_ORIG_SRC	(1UL << 8)
3644d362409d5469aed47d19e7908d19bd194493aThomas Graf#define CT_ATTR_ORIG_DST	(1UL << 9)
3744d362409d5469aed47d19e7908d19bd194493aThomas Graf#define CT_ATTR_ORIG_SRC_PORT	(1UL << 10)
3844d362409d5469aed47d19e7908d19bd194493aThomas Graf#define CT_ATTR_ORIG_DST_PORT	(1UL << 11)
3944d362409d5469aed47d19e7908d19bd194493aThomas Graf#define CT_ATTR_ORIG_ICMP_ID	(1UL << 12)
4044d362409d5469aed47d19e7908d19bd194493aThomas Graf#define CT_ATTR_ORIG_ICMP_TYPE	(1UL << 13)
4144d362409d5469aed47d19e7908d19bd194493aThomas Graf#define CT_ATTR_ORIG_ICMP_CODE	(1UL << 14)
4244d362409d5469aed47d19e7908d19bd194493aThomas Graf#define CT_ATTR_ORIG_PACKETS	(1UL << 15)
4344d362409d5469aed47d19e7908d19bd194493aThomas Graf#define CT_ATTR_ORIG_BYTES	(1UL << 16)
4444d362409d5469aed47d19e7908d19bd194493aThomas Graf
4544d362409d5469aed47d19e7908d19bd194493aThomas Graf#define CT_ATTR_REPL_SRC	(1UL << 17)
4644d362409d5469aed47d19e7908d19bd194493aThomas Graf#define CT_ATTR_REPL_DST	(1UL << 18)
4744d362409d5469aed47d19e7908d19bd194493aThomas Graf#define CT_ATTR_REPL_SRC_PORT	(1UL << 19)
4844d362409d5469aed47d19e7908d19bd194493aThomas Graf#define CT_ATTR_REPL_DST_PORT	(1UL << 20)
4944d362409d5469aed47d19e7908d19bd194493aThomas Graf#define CT_ATTR_REPL_ICMP_ID	(1UL << 21)
5044d362409d5469aed47d19e7908d19bd194493aThomas Graf#define CT_ATTR_REPL_ICMP_TYPE	(1UL << 22)
5144d362409d5469aed47d19e7908d19bd194493aThomas Graf#define CT_ATTR_REPL_ICMP_CODE	(1UL << 23)
5244d362409d5469aed47d19e7908d19bd194493aThomas Graf#define CT_ATTR_REPL_PACKETS	(1UL << 24)
5344d362409d5469aed47d19e7908d19bd194493aThomas Graf#define CT_ATTR_REPL_BYTES	(1UL << 25)
5444d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @endcond */
5544d362409d5469aed47d19e7908d19bd194493aThomas Graf
5644d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void ct_free_data(struct nl_object *c)
5744d362409d5469aed47d19e7908d19bd194493aThomas Graf{
5844d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nfnl_ct *ct = (struct nfnl_ct *) c;
5944d362409d5469aed47d19e7908d19bd194493aThomas Graf
6044d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (ct == NULL)
6144d362409d5469aed47d19e7908d19bd194493aThomas Graf		return;
6244d362409d5469aed47d19e7908d19bd194493aThomas Graf
6344d362409d5469aed47d19e7908d19bd194493aThomas Graf	nl_addr_put(ct->ct_orig.src);
6444d362409d5469aed47d19e7908d19bd194493aThomas Graf	nl_addr_put(ct->ct_orig.dst);
6544d362409d5469aed47d19e7908d19bd194493aThomas Graf	nl_addr_put(ct->ct_repl.src);
6644d362409d5469aed47d19e7908d19bd194493aThomas Graf	nl_addr_put(ct->ct_repl.dst);
6744d362409d5469aed47d19e7908d19bd194493aThomas Graf}
6844d362409d5469aed47d19e7908d19bd194493aThomas Graf
6944d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int ct_clone(struct nl_object *_dst, struct nl_object *_src)
7044d362409d5469aed47d19e7908d19bd194493aThomas Graf{
7144d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nfnl_ct *dst = (struct nfnl_ct *) _dst;
7244d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nfnl_ct *src = (struct nfnl_ct *) _src;
7344d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nl_addr *addr;
7444d362409d5469aed47d19e7908d19bd194493aThomas Graf
7544d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (src->ct_orig.src) {
7644d362409d5469aed47d19e7908d19bd194493aThomas Graf		addr = nl_addr_clone(src->ct_orig.src);
7744d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (!addr)
788a3efffa5b3fde252675239914118664d36a2c24Thomas Graf			return -NLE_NOMEM;
7944d362409d5469aed47d19e7908d19bd194493aThomas Graf		dst->ct_orig.src = addr;
8044d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
8144d362409d5469aed47d19e7908d19bd194493aThomas Graf
8244d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (src->ct_orig.dst) {
8344d362409d5469aed47d19e7908d19bd194493aThomas Graf		addr = nl_addr_clone(src->ct_orig.dst);
8444d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (!addr)
858a3efffa5b3fde252675239914118664d36a2c24Thomas Graf			return -NLE_NOMEM;
8644d362409d5469aed47d19e7908d19bd194493aThomas Graf		dst->ct_orig.dst = addr;
8744d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
8844d362409d5469aed47d19e7908d19bd194493aThomas Graf
8944d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (src->ct_repl.src) {
9044d362409d5469aed47d19e7908d19bd194493aThomas Graf		addr = nl_addr_clone(src->ct_repl.src);
9144d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (!addr)
928a3efffa5b3fde252675239914118664d36a2c24Thomas Graf			return -NLE_NOMEM;
9344d362409d5469aed47d19e7908d19bd194493aThomas Graf		dst->ct_repl.src = addr;
9444d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
9544d362409d5469aed47d19e7908d19bd194493aThomas Graf
9644d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (src->ct_repl.dst) {
9744d362409d5469aed47d19e7908d19bd194493aThomas Graf		addr = nl_addr_clone(src->ct_repl.dst);
9844d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (!addr)
998a3efffa5b3fde252675239914118664d36a2c24Thomas Graf			return -NLE_NOMEM;
10044d362409d5469aed47d19e7908d19bd194493aThomas Graf		dst->ct_repl.dst = addr;
10144d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
10244d362409d5469aed47d19e7908d19bd194493aThomas Graf
10344d362409d5469aed47d19e7908d19bd194493aThomas Graf	return 0;
10444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
10544d362409d5469aed47d19e7908d19bd194493aThomas Graf
106337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Grafstatic void dump_addr(struct nl_dump_params *p, struct nl_addr *addr, int port)
10744d362409d5469aed47d19e7908d19bd194493aThomas Graf{
108337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	char buf[64];
10944d362409d5469aed47d19e7908d19bd194493aThomas Graf
11044d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (addr)
111337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		nl_dump(p, "%s", nl_addr2str(addr, buf, sizeof(buf)));
11244d362409d5469aed47d19e7908d19bd194493aThomas Graf
113337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	if (port)
114337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		nl_dump(p, ":%u ", port);
115337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	else if (addr)
116337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		nl_dump(p, " ");
117337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf}
118337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf
119337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Grafstatic void dump_icmp(struct nl_dump_params *p, struct nfnl_ct *ct, int reply)
120337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf{
121337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	if (nfnl_ct_test_icmp_type(ct, reply))
122337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		nl_dump(p, "icmp type %d ", nfnl_ct_get_icmp_type(ct, reply));
123337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf
124337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	if (nfnl_ct_test_icmp_type(ct, reply))
125337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		nl_dump(p, "code %d ", nfnl_ct_get_icmp_code(ct, reply));
126337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf
127337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	if (nfnl_ct_test_icmp_type(ct, reply))
128337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		nl_dump(p, "id %d ", nfnl_ct_get_icmp_id(ct, reply));
129337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf}
130337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf
131337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Grafstatic void ct_dump_tuples(struct nfnl_ct *ct, struct nl_dump_params *p)
132337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf{
133337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	struct nl_addr *orig_src, *orig_dst, *reply_src, *reply_dst;
134337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	int orig_sport = 0, orig_dport = 0, reply_sport = 0, reply_dport = 0;
135337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	int sync = 0;
136337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf
137337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	orig_src = nfnl_ct_get_src(ct, 0);
138337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	orig_dst = nfnl_ct_get_dst(ct, 0);
139337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	reply_src = nfnl_ct_get_src(ct, 1);
140337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	reply_dst = nfnl_ct_get_dst(ct, 1);
14144d362409d5469aed47d19e7908d19bd194493aThomas Graf
142337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	if (nfnl_ct_test_src_port(ct, 0))
143337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		orig_sport = nfnl_ct_get_src_port(ct, 0);
14444d362409d5469aed47d19e7908d19bd194493aThomas Graf
145337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	if (nfnl_ct_test_dst_port(ct, 0))
146337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		orig_dport = nfnl_ct_get_dst_port(ct, 0);
14744d362409d5469aed47d19e7908d19bd194493aThomas Graf
148337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	if (nfnl_ct_test_src_port(ct, 1))
149337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		reply_sport = nfnl_ct_get_src_port(ct, 1);
150337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf
151337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	if (nfnl_ct_test_dst_port(ct, 1))
152337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		reply_dport = nfnl_ct_get_dst_port(ct, 1);
153337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf
154337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	if (orig_src && orig_dst && reply_src && reply_dst &&
155337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	    orig_sport == reply_dport && orig_dport == reply_sport &&
156337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	    !nl_addr_cmp(orig_src, reply_dst) &&
157337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	    !nl_addr_cmp(orig_dst, reply_src))
158337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		sync = 1;
159337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf
160337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	dump_addr(p, orig_src, orig_sport);
161337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	nl_dump(p, sync ? "<-> " : "-> ");
162337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	dump_addr(p, orig_dst, orig_dport);
163337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	dump_icmp(p, ct, 0);
164337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf
165337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	if (!sync) {
166337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		dump_addr(p, reply_src, reply_sport);
167337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		nl_dump(p, "<- ");
168337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		dump_addr(p, reply_dst, reply_dport);
169337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		dump_icmp(p, ct, 1);
170337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	}
17144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
17244d362409d5469aed47d19e7908d19bd194493aThomas Graf
17344d362409d5469aed47d19e7908d19bd194493aThomas Graf/* Compatible with /proc/net/nf_conntrack */
174d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Grafstatic void ct_dump_line(struct nl_object *a, struct nl_dump_params *p)
17544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
17644d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nfnl_ct *ct = (struct nfnl_ct *) a;
17744d362409d5469aed47d19e7908d19bd194493aThomas Graf	char buf[64];
17844d362409d5469aed47d19e7908d19bd194493aThomas Graf
179d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf	nl_new_line(p);
180d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf
181337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	if (nfnl_ct_test_proto(ct))
182337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		nl_dump(p, "%s ",
183337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		  nl_ip_proto2str(nfnl_ct_get_proto(ct), buf, sizeof(buf)));
18444d362409d5469aed47d19e7908d19bd194493aThomas Graf
18544d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (nfnl_ct_test_tcp_state(ct))
186337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		nl_dump(p, "%s ",
18744d362409d5469aed47d19e7908d19bd194493aThomas Graf			nfnl_ct_tcp_state2str(nfnl_ct_get_tcp_state(ct),
18844d362409d5469aed47d19e7908d19bd194493aThomas Graf					      buf, sizeof(buf)));
18944d362409d5469aed47d19e7908d19bd194493aThomas Graf
190337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	ct_dump_tuples(ct, p);
19144d362409d5469aed47d19e7908d19bd194493aThomas Graf
192337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	if (nfnl_ct_test_mark(ct) && nfnl_ct_get_mark(ct))
193337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		nl_dump(p, "mark %u ", nfnl_ct_get_mark(ct));
19444d362409d5469aed47d19e7908d19bd194493aThomas Graf
195337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	nl_dump(p, "\n");
196337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf}
19744d362409d5469aed47d19e7908d19bd194493aThomas Graf
198d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Grafstatic void ct_dump_details(struct nl_object *a, struct nl_dump_params *p)
199337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf{
200337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	struct nfnl_ct *ct = (struct nfnl_ct *) a;
201337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	char buf[64];
202337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	int fp = 0;
203337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf
204d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf	ct_dump_line(a, p);
205337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf
206337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	nl_dump(p, "    id 0x%x ", ct->ct_id);
207337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	nl_dump_line(p, "family %s ",
208337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		nl_af2str(ct->ct_family, buf, sizeof(buf)));
20944d362409d5469aed47d19e7908d19bd194493aThomas Graf
21044d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (nfnl_ct_test_use(ct))
211337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		nl_dump(p, "refcnt %u ", nfnl_ct_get_use(ct));
21244d362409d5469aed47d19e7908d19bd194493aThomas Graf
213337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	if (nfnl_ct_test_timeout(ct)) {
214337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		uint64_t timeout_ms = nfnl_ct_get_timeout(ct) * 1000UL;
215337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		nl_dump(p, "timeout %s ",
216337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf			nl_msec2str(timeout_ms, buf, sizeof(buf)));
217337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	}
21844d362409d5469aed47d19e7908d19bd194493aThomas Graf
219337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	if (ct->ct_status)
220337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		nl_dump(p, "<");
221337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf
222337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf#define PRINT_FLAG(str) \
223337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	{ nl_dump(p, "%s%s", fp++ ? "," : "", (str)); }
224337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf
225337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	if (ct->ct_status & IPS_EXPECTED)
226337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		PRINT_FLAG("EXPECTED");
227337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	if (!(ct->ct_status & IPS_SEEN_REPLY))
228337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		PRINT_FLAG("NOREPLY");
229337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	if (ct->ct_status & IPS_ASSURED)
230337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		PRINT_FLAG("ASSURED");
231337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	if (!(ct->ct_status & IPS_CONFIRMED))
232337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		PRINT_FLAG("NOTSENT");
233337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	if (ct->ct_status & IPS_SRC_NAT)
234337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		PRINT_FLAG("SNAT");
235337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	if (ct->ct_status & IPS_DST_NAT)
236337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		PRINT_FLAG("DNAT");
237337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	if (ct->ct_status & IPS_SEQ_ADJUST)
238337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		PRINT_FLAG("SEQADJUST");
239337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	if (!(ct->ct_status & IPS_SRC_NAT_DONE))
240337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		PRINT_FLAG("SNAT_INIT");
241337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	if (!(ct->ct_status & IPS_DST_NAT_DONE))
242337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		PRINT_FLAG("DNAT_INIT");
243337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	if (ct->ct_status & IPS_DYING)
244337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		PRINT_FLAG("DYING");
245337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	if (ct->ct_status & IPS_FIXED_TIMEOUT)
246337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		PRINT_FLAG("FIXED_TIMEOUT");
247337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf#undef PRINT_FLAG
248337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf
249337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	if (ct->ct_status)
250337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		nl_dump(p, ">");
251337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	nl_dump(p, "\n");
252337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf}
253337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf
254d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Grafstatic void ct_dump_stats(struct nl_object *a, struct nl_dump_params *p)
255337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf{
256337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	struct nfnl_ct *ct = (struct nfnl_ct *) a;
257337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	double res;
258337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	char *unit;
259337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf
260d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf	ct_dump_details(a, p);
261d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf
262d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf	nl_dump_line(p, "        # packets      volume\n");
263337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf
264337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	res = nl_cancel_down_bytes(nfnl_ct_get_bytes(ct, 1), &unit);
265d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf	nl_dump_line(p, "    rx %10llu %7.2f %s\n",
266337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		nfnl_ct_get_packets(ct, 1), res, unit);
267337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf
268337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	res = nl_cancel_down_bytes(nfnl_ct_get_bytes(ct, 0), &unit);
269d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf	nl_dump_line(p, "    tx %10llu %7.2f %s\n",
270337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf		nfnl_ct_get_packets(ct, 0), res, unit);
27144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
27244d362409d5469aed47d19e7908d19bd194493aThomas Graf
27344d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int ct_compare(struct nl_object *_a, struct nl_object *_b,
27444d362409d5469aed47d19e7908d19bd194493aThomas Graf			uint32_t attrs, int flags)
27544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
27644d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nfnl_ct *a = (struct nfnl_ct *) _a;
27744d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nfnl_ct *b = (struct nfnl_ct *) _b;
27844d362409d5469aed47d19e7908d19bd194493aThomas Graf	int diff = 0;
27944d362409d5469aed47d19e7908d19bd194493aThomas Graf
28044d362409d5469aed47d19e7908d19bd194493aThomas Graf#define CT_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, CT_ATTR_##ATTR, a, b, EXPR)
28144d362409d5469aed47d19e7908d19bd194493aThomas Graf#define CT_DIFF_VAL(ATTR, FIELD) CT_DIFF(ATTR, a->FIELD != b->FIELD)
28244d362409d5469aed47d19e7908d19bd194493aThomas Graf#define CT_DIFF_ADDR(ATTR, FIELD) \
283535e83162249ed6274ba46bc72d8cc683ba20e17Thomas Graf	((flags & LOOSE_COMPARISON) \
28444d362409d5469aed47d19e7908d19bd194493aThomas Graf		? CT_DIFF(ATTR, nl_addr_cmp_prefix(a->FIELD, b->FIELD)) \
28544d362409d5469aed47d19e7908d19bd194493aThomas Graf		: CT_DIFF(ATTR, nl_addr_cmp(a->FIELD, b->FIELD)))
28644d362409d5469aed47d19e7908d19bd194493aThomas Graf
28744d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= CT_DIFF_VAL(FAMILY,		ct_family);
28844d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= CT_DIFF_VAL(PROTO,		ct_proto);
28944d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= CT_DIFF_VAL(TCP_STATE,		ct_protoinfo.tcp.state);
29044d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= CT_DIFF_VAL(TIMEOUT,		ct_timeout);
29144d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= CT_DIFF_VAL(MARK,		ct_mark);
29244d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= CT_DIFF_VAL(USE,		ct_use);
29344d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= CT_DIFF_VAL(ID,			ct_id);
29444d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= CT_DIFF_ADDR(ORIG_SRC,		ct_orig.src);
29544d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= CT_DIFF_ADDR(ORIG_DST,		ct_orig.dst);
29644d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= CT_DIFF_VAL(ORIG_SRC_PORT,	ct_orig.proto.port.src);
29744d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= CT_DIFF_VAL(ORIG_DST_PORT,	ct_orig.proto.port.dst);
29844d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= CT_DIFF_VAL(ORIG_ICMP_ID,	ct_orig.proto.icmp.id);
29944d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= CT_DIFF_VAL(ORIG_ICMP_TYPE,	ct_orig.proto.icmp.type);
30044d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= CT_DIFF_VAL(ORIG_ICMP_CODE,	ct_orig.proto.icmp.code);
30144d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= CT_DIFF_VAL(ORIG_PACKETS,	ct_orig.packets);
30244d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= CT_DIFF_VAL(ORIG_BYTES,		ct_orig.bytes);
30344d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= CT_DIFF_ADDR(REPL_SRC,		ct_repl.src);
304104e158bd578bceacf37ba24dd1a1a907fc53d05Philip Craig	diff |= CT_DIFF_ADDR(REPL_DST,		ct_repl.dst);
30544d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= CT_DIFF_VAL(REPL_SRC_PORT,	ct_repl.proto.port.src);
30644d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= CT_DIFF_VAL(REPL_DST_PORT,	ct_repl.proto.port.dst);
30744d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= CT_DIFF_VAL(REPL_ICMP_ID,	ct_repl.proto.icmp.id);
30844d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= CT_DIFF_VAL(REPL_ICMP_TYPE,	ct_repl.proto.icmp.type);
30944d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= CT_DIFF_VAL(REPL_ICMP_CODE,	ct_repl.proto.icmp.code);
31044d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= CT_DIFF_VAL(REPL_PACKETS,	ct_repl.packets);
31144d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= CT_DIFF_VAL(REPL_BYTES,		ct_repl.bytes);
31244d362409d5469aed47d19e7908d19bd194493aThomas Graf
313535e83162249ed6274ba46bc72d8cc683ba20e17Thomas Graf	if (flags & LOOSE_COMPARISON)
314cbe8902265ccc9f6aa6453aeb3a2a4631ed0eb01Philip Craig		diff |= CT_DIFF(STATUS, (a->ct_status ^ b->ct_status) &
315cbe8902265ccc9f6aa6453aeb3a2a4631ed0eb01Philip Craig					b->ct_status_mask);
316cbe8902265ccc9f6aa6453aeb3a2a4631ed0eb01Philip Craig	else
317cbe8902265ccc9f6aa6453aeb3a2a4631ed0eb01Philip Craig		diff |= CT_DIFF(STATUS, a->ct_status != b->ct_status);
318cbe8902265ccc9f6aa6453aeb3a2a4631ed0eb01Philip Craig
31944d362409d5469aed47d19e7908d19bd194493aThomas Graf#undef CT_DIFF
32044d362409d5469aed47d19e7908d19bd194493aThomas Graf#undef CT_DIFF_VAL
32144d362409d5469aed47d19e7908d19bd194493aThomas Graf#undef CT_DIFF_ADDR
32244d362409d5469aed47d19e7908d19bd194493aThomas Graf
32344d362409d5469aed47d19e7908d19bd194493aThomas Graf	return diff;
32444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
32544d362409d5469aed47d19e7908d19bd194493aThomas Graf
32644d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct trans_tbl ct_attrs[] = {
32744d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(CT_ATTR_FAMILY,		family)
32844d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(CT_ATTR_PROTO,		proto)
32944d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(CT_ATTR_TCP_STATE,	tcpstate)
33044d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(CT_ATTR_STATUS,		status)
33144d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(CT_ATTR_TIMEOUT,		timeout)
33244d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(CT_ATTR_MARK,		mark)
33344d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(CT_ATTR_USE,		use)
33444d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(CT_ATTR_ID,		id)
33544d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(CT_ATTR_ORIG_SRC,		origsrc)
33644d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(CT_ATTR_ORIG_DST,		origdst)
33744d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(CT_ATTR_ORIG_SRC_PORT,	origsrcport)
33844d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(CT_ATTR_ORIG_DST_PORT,	origdstport)
33944d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(CT_ATTR_ORIG_ICMP_ID,	origicmpid)
34044d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(CT_ATTR_ORIG_ICMP_TYPE,	origicmptype)
34144d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(CT_ATTR_ORIG_ICMP_CODE,	origicmpcode)
34244d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(CT_ATTR_ORIG_PACKETS,	origpackets)
34344d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(CT_ATTR_ORIG_BYTES,	origbytes)
34444d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(CT_ATTR_REPL_SRC,		replysrc)
34544d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(CT_ATTR_REPL_DST,		replydst)
34644d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(CT_ATTR_REPL_SRC_PORT,	replysrcport)
34744d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(CT_ATTR_REPL_DST_PORT,	replydstport)
34844d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(CT_ATTR_REPL_ICMP_ID,	replyicmpid)
34944d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(CT_ATTR_REPL_ICMP_TYPE,	replyicmptype)
35044d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(CT_ATTR_REPL_ICMP_CODE,	replyicmpcode)
35144d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(CT_ATTR_REPL_PACKETS,	replypackets)
35244d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(CT_ATTR_REPL_BYTES,	replybytes)
35344d362409d5469aed47d19e7908d19bd194493aThomas Graf};
35444d362409d5469aed47d19e7908d19bd194493aThomas Graf
35544d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic char *ct_attrs2str(int attrs, char *buf, size_t len)
35644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
35744d362409d5469aed47d19e7908d19bd194493aThomas Graf	return __flags2str(attrs, buf, len, ct_attrs, ARRAY_SIZE(ct_attrs));
35844d362409d5469aed47d19e7908d19bd194493aThomas Graf}
35944d362409d5469aed47d19e7908d19bd194493aThomas Graf
36044d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
36144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Allocation/Freeing
36244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
36344d362409d5469aed47d19e7908d19bd194493aThomas Graf */
36444d362409d5469aed47d19e7908d19bd194493aThomas Graf
36544d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nfnl_ct *nfnl_ct_alloc(void)
36644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
36744d362409d5469aed47d19e7908d19bd194493aThomas Graf	return (struct nfnl_ct *) nl_object_alloc(&ct_obj_ops);
36844d362409d5469aed47d19e7908d19bd194493aThomas Graf}
36944d362409d5469aed47d19e7908d19bd194493aThomas Graf
37044d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nfnl_ct_get(struct nfnl_ct *ct)
37144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
37244d362409d5469aed47d19e7908d19bd194493aThomas Graf	nl_object_get((struct nl_object *) ct);
37344d362409d5469aed47d19e7908d19bd194493aThomas Graf}
37444d362409d5469aed47d19e7908d19bd194493aThomas Graf
37544d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nfnl_ct_put(struct nfnl_ct *ct)
37644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
37744d362409d5469aed47d19e7908d19bd194493aThomas Graf	nl_object_put((struct nl_object *) ct);
37844d362409d5469aed47d19e7908d19bd194493aThomas Graf}
37944d362409d5469aed47d19e7908d19bd194493aThomas Graf
38044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
38144d362409d5469aed47d19e7908d19bd194493aThomas Graf
38244d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
38344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Attributes
38444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
38544d362409d5469aed47d19e7908d19bd194493aThomas Graf */
38644d362409d5469aed47d19e7908d19bd194493aThomas Graf
38744d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nfnl_ct_set_family(struct nfnl_ct *ct, uint8_t family)
38844d362409d5469aed47d19e7908d19bd194493aThomas Graf{
38944d362409d5469aed47d19e7908d19bd194493aThomas Graf	ct->ct_family = family;
39044d362409d5469aed47d19e7908d19bd194493aThomas Graf	ct->ce_mask |= CT_ATTR_FAMILY;
39144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
39244d362409d5469aed47d19e7908d19bd194493aThomas Graf
39344d362409d5469aed47d19e7908d19bd194493aThomas Grafuint8_t nfnl_ct_get_family(const struct nfnl_ct *ct)
39444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
39544d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (ct->ce_mask & CT_ATTR_FAMILY)
39644d362409d5469aed47d19e7908d19bd194493aThomas Graf		return ct->ct_family;
39744d362409d5469aed47d19e7908d19bd194493aThomas Graf	else
39844d362409d5469aed47d19e7908d19bd194493aThomas Graf		return AF_UNSPEC;
39944d362409d5469aed47d19e7908d19bd194493aThomas Graf}
40044d362409d5469aed47d19e7908d19bd194493aThomas Graf
40144d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nfnl_ct_set_proto(struct nfnl_ct *ct, uint8_t proto)
40244d362409d5469aed47d19e7908d19bd194493aThomas Graf{
40344d362409d5469aed47d19e7908d19bd194493aThomas Graf	ct->ct_proto = proto;
40444d362409d5469aed47d19e7908d19bd194493aThomas Graf	ct->ce_mask |= CT_ATTR_PROTO;
40544d362409d5469aed47d19e7908d19bd194493aThomas Graf}
40644d362409d5469aed47d19e7908d19bd194493aThomas Graf
40744d362409d5469aed47d19e7908d19bd194493aThomas Grafint nfnl_ct_test_proto(const struct nfnl_ct *ct)
40844d362409d5469aed47d19e7908d19bd194493aThomas Graf{
40944d362409d5469aed47d19e7908d19bd194493aThomas Graf	return !!(ct->ce_mask & CT_ATTR_PROTO);
41044d362409d5469aed47d19e7908d19bd194493aThomas Graf}
41144d362409d5469aed47d19e7908d19bd194493aThomas Graf
41244d362409d5469aed47d19e7908d19bd194493aThomas Grafuint8_t nfnl_ct_get_proto(const struct nfnl_ct *ct)
41344d362409d5469aed47d19e7908d19bd194493aThomas Graf{
41444d362409d5469aed47d19e7908d19bd194493aThomas Graf	return ct->ct_proto;
41544d362409d5469aed47d19e7908d19bd194493aThomas Graf}
41644d362409d5469aed47d19e7908d19bd194493aThomas Graf
41744d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nfnl_ct_set_tcp_state(struct nfnl_ct *ct, uint8_t state)
41844d362409d5469aed47d19e7908d19bd194493aThomas Graf{
41944d362409d5469aed47d19e7908d19bd194493aThomas Graf	ct->ct_protoinfo.tcp.state = state;
42044d362409d5469aed47d19e7908d19bd194493aThomas Graf	ct->ce_mask |= CT_ATTR_TCP_STATE;
42144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
42244d362409d5469aed47d19e7908d19bd194493aThomas Graf
42344d362409d5469aed47d19e7908d19bd194493aThomas Grafint nfnl_ct_test_tcp_state(const struct nfnl_ct *ct)
42444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
42544d362409d5469aed47d19e7908d19bd194493aThomas Graf	return !!(ct->ce_mask & CT_ATTR_TCP_STATE);
42644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
42744d362409d5469aed47d19e7908d19bd194493aThomas Graf
42844d362409d5469aed47d19e7908d19bd194493aThomas Grafuint8_t nfnl_ct_get_tcp_state(const struct nfnl_ct *ct)
42944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
43044d362409d5469aed47d19e7908d19bd194493aThomas Graf	return ct->ct_protoinfo.tcp.state;
43144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
43244d362409d5469aed47d19e7908d19bd194493aThomas Graf
43344d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct trans_tbl tcp_states[] = {
43444d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(TCP_CONNTRACK_NONE,NONE)
43544d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(TCP_CONNTRACK_SYN_SENT,SYN_SENT)
43644d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(TCP_CONNTRACK_SYN_RECV,SYN_RECV)
43744d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(TCP_CONNTRACK_ESTABLISHED,ESTABLISHED)
43844d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(TCP_CONNTRACK_FIN_WAIT,FIN_WAIT)
43944d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(TCP_CONNTRACK_CLOSE_WAIT,CLOSE_WAIT)
44044d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(TCP_CONNTRACK_LAST_ACK,LAST_ACK)
44144d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(TCP_CONNTRACK_TIME_WAIT,TIME_WAIT)
44244d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(TCP_CONNTRACK_CLOSE,CLOSE)
44344d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(TCP_CONNTRACK_LISTEN,LISTEN)
44444d362409d5469aed47d19e7908d19bd194493aThomas Graf};
44544d362409d5469aed47d19e7908d19bd194493aThomas Graf
44644d362409d5469aed47d19e7908d19bd194493aThomas Grafchar *nfnl_ct_tcp_state2str(uint8_t state, char *buf, size_t len)
44744d362409d5469aed47d19e7908d19bd194493aThomas Graf{
44844d362409d5469aed47d19e7908d19bd194493aThomas Graf	return __type2str(state, buf, len, tcp_states, ARRAY_SIZE(tcp_states));
44944d362409d5469aed47d19e7908d19bd194493aThomas Graf}
45044d362409d5469aed47d19e7908d19bd194493aThomas Graf
45144d362409d5469aed47d19e7908d19bd194493aThomas Grafint nfnl_ct_str2tcp_state(const char *name)
45244d362409d5469aed47d19e7908d19bd194493aThomas Graf{
45344d362409d5469aed47d19e7908d19bd194493aThomas Graf        return __str2type(name, tcp_states, ARRAY_SIZE(tcp_states));
45444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
45544d362409d5469aed47d19e7908d19bd194493aThomas Graf
45644d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nfnl_ct_set_status(struct nfnl_ct *ct, uint32_t status)
45744d362409d5469aed47d19e7908d19bd194493aThomas Graf{
458cbe8902265ccc9f6aa6453aeb3a2a4631ed0eb01Philip Craig	ct->ct_status_mask |= status;
459cbe8902265ccc9f6aa6453aeb3a2a4631ed0eb01Philip Craig	ct->ct_status |= status;
46044d362409d5469aed47d19e7908d19bd194493aThomas Graf	ct->ce_mask |= CT_ATTR_STATUS;
46144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
46244d362409d5469aed47d19e7908d19bd194493aThomas Graf
463cbe8902265ccc9f6aa6453aeb3a2a4631ed0eb01Philip Craigvoid nfnl_ct_unset_status(struct nfnl_ct *ct, uint32_t status)
46444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
465cbe8902265ccc9f6aa6453aeb3a2a4631ed0eb01Philip Craig	ct->ct_status_mask |= status;
466cbe8902265ccc9f6aa6453aeb3a2a4631ed0eb01Philip Craig	ct->ct_status &= ~status;
467cbe8902265ccc9f6aa6453aeb3a2a4631ed0eb01Philip Craig	ct->ce_mask |= CT_ATTR_STATUS;
46844d362409d5469aed47d19e7908d19bd194493aThomas Graf}
46944d362409d5469aed47d19e7908d19bd194493aThomas Graf
47044d362409d5469aed47d19e7908d19bd194493aThomas Grafuint32_t nfnl_ct_get_status(const struct nfnl_ct *ct)
47144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
47244d362409d5469aed47d19e7908d19bd194493aThomas Graf	return ct->ct_status;
47344d362409d5469aed47d19e7908d19bd194493aThomas Graf}
47444d362409d5469aed47d19e7908d19bd194493aThomas Graf
475337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Grafstatic struct trans_tbl status_flags[] = {
476337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	__ADD(IPS_EXPECTED, expected)
477337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	__ADD(IPS_SEEN_REPLY, seen_reply)
478337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	__ADD(IPS_ASSURED, assured)
479337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	__ADD(IPS_CONFIRMED, confirmed)
480337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	__ADD(IPS_SRC_NAT, snat)
481337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	__ADD(IPS_DST_NAT, dnat)
482337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	__ADD(IPS_SEQ_ADJUST, seqadjust)
483337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	__ADD(IPS_SRC_NAT_DONE, snat_done)
484337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	__ADD(IPS_DST_NAT_DONE, dnat_done)
485337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	__ADD(IPS_DYING, dying)
486337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	__ADD(IPS_FIXED_TIMEOUT, fixed_timeout)
487337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf};
488337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf
489337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Grafchar * nfnl_ct_status2str(int flags, char *buf, size_t len)
490337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf{
491337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	return __flags2str(flags, buf, len, status_flags,
492337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf			   ARRAY_SIZE(status_flags));
493337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf}
494337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf
495337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Grafint nfnl_ct_str2status(const char *name)
496337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf{
497337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf	return __str2flags(name, status_flags, ARRAY_SIZE(status_flags));
498337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf}
499337fbd24cad1f5cf9c8b4287a75f2c69f088adceThomas Graf
50044d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nfnl_ct_set_timeout(struct nfnl_ct *ct, uint32_t timeout)
50144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
50244d362409d5469aed47d19e7908d19bd194493aThomas Graf	ct->ct_timeout = timeout;
50344d362409d5469aed47d19e7908d19bd194493aThomas Graf	ct->ce_mask |= CT_ATTR_TIMEOUT;
50444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
50544d362409d5469aed47d19e7908d19bd194493aThomas Graf
50644d362409d5469aed47d19e7908d19bd194493aThomas Grafint nfnl_ct_test_timeout(const struct nfnl_ct *ct)
50744d362409d5469aed47d19e7908d19bd194493aThomas Graf{
50844d362409d5469aed47d19e7908d19bd194493aThomas Graf	return !!(ct->ce_mask & CT_ATTR_TIMEOUT);
50944d362409d5469aed47d19e7908d19bd194493aThomas Graf}
51044d362409d5469aed47d19e7908d19bd194493aThomas Graf
51144d362409d5469aed47d19e7908d19bd194493aThomas Grafuint32_t nfnl_ct_get_timeout(const struct nfnl_ct *ct)
51244d362409d5469aed47d19e7908d19bd194493aThomas Graf{
51344d362409d5469aed47d19e7908d19bd194493aThomas Graf	return ct->ct_timeout;
51444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
51544d362409d5469aed47d19e7908d19bd194493aThomas Graf
51644d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nfnl_ct_set_mark(struct nfnl_ct *ct, uint32_t mark)
51744d362409d5469aed47d19e7908d19bd194493aThomas Graf{
51844d362409d5469aed47d19e7908d19bd194493aThomas Graf	ct->ct_mark = mark;
51944d362409d5469aed47d19e7908d19bd194493aThomas Graf	ct->ce_mask |= CT_ATTR_MARK;
52044d362409d5469aed47d19e7908d19bd194493aThomas Graf}
52144d362409d5469aed47d19e7908d19bd194493aThomas Graf
52244d362409d5469aed47d19e7908d19bd194493aThomas Grafint nfnl_ct_test_mark(const struct nfnl_ct *ct)
52344d362409d5469aed47d19e7908d19bd194493aThomas Graf{
52444d362409d5469aed47d19e7908d19bd194493aThomas Graf	return !!(ct->ce_mask & CT_ATTR_MARK);
52544d362409d5469aed47d19e7908d19bd194493aThomas Graf}
52644d362409d5469aed47d19e7908d19bd194493aThomas Graf
52744d362409d5469aed47d19e7908d19bd194493aThomas Grafuint32_t nfnl_ct_get_mark(const struct nfnl_ct *ct)
52844d362409d5469aed47d19e7908d19bd194493aThomas Graf{
52944d362409d5469aed47d19e7908d19bd194493aThomas Graf	return ct->ct_mark;
53044d362409d5469aed47d19e7908d19bd194493aThomas Graf}
53144d362409d5469aed47d19e7908d19bd194493aThomas Graf
53244d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nfnl_ct_set_use(struct nfnl_ct *ct, uint32_t use)
53344d362409d5469aed47d19e7908d19bd194493aThomas Graf{
53444d362409d5469aed47d19e7908d19bd194493aThomas Graf	ct->ct_use = use;
53544d362409d5469aed47d19e7908d19bd194493aThomas Graf	ct->ce_mask |= CT_ATTR_USE;
53644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
53744d362409d5469aed47d19e7908d19bd194493aThomas Graf
53844d362409d5469aed47d19e7908d19bd194493aThomas Grafint nfnl_ct_test_use(const struct nfnl_ct *ct)
53944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
54044d362409d5469aed47d19e7908d19bd194493aThomas Graf	return !!(ct->ce_mask & CT_ATTR_USE);
54144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
54244d362409d5469aed47d19e7908d19bd194493aThomas Graf
54344d362409d5469aed47d19e7908d19bd194493aThomas Grafuint32_t nfnl_ct_get_use(const struct nfnl_ct *ct)
54444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
54544d362409d5469aed47d19e7908d19bd194493aThomas Graf	return ct->ct_use;
54644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
54744d362409d5469aed47d19e7908d19bd194493aThomas Graf
54844d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nfnl_ct_set_id(struct nfnl_ct *ct, uint32_t id)
54944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
55044d362409d5469aed47d19e7908d19bd194493aThomas Graf	ct->ct_id = id;
55144d362409d5469aed47d19e7908d19bd194493aThomas Graf	ct->ce_mask |= CT_ATTR_ID;
55244d362409d5469aed47d19e7908d19bd194493aThomas Graf}
55344d362409d5469aed47d19e7908d19bd194493aThomas Graf
55444d362409d5469aed47d19e7908d19bd194493aThomas Grafint nfnl_ct_test_id(const struct nfnl_ct *ct)
55544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
55644d362409d5469aed47d19e7908d19bd194493aThomas Graf	return !!(ct->ce_mask & CT_ATTR_ID);
55744d362409d5469aed47d19e7908d19bd194493aThomas Graf}
55844d362409d5469aed47d19e7908d19bd194493aThomas Graf
55944d362409d5469aed47d19e7908d19bd194493aThomas Grafuint32_t nfnl_ct_get_id(const struct nfnl_ct *ct)
56044d362409d5469aed47d19e7908d19bd194493aThomas Graf{
56144d362409d5469aed47d19e7908d19bd194493aThomas Graf	return ct->ct_id;
56244d362409d5469aed47d19e7908d19bd194493aThomas Graf}
56344d362409d5469aed47d19e7908d19bd194493aThomas Graf
56444d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int ct_set_addr(struct nfnl_ct *ct, struct nl_addr *addr,
56544d362409d5469aed47d19e7908d19bd194493aThomas Graf		int attr, struct nl_addr ** ct_addr)
56644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
56744d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (ct->ce_mask & CT_ATTR_FAMILY) {
56844d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (addr->a_family != ct->ct_family)
5698a3efffa5b3fde252675239914118664d36a2c24Thomas Graf			return -NLE_AF_MISMATCH;
57044d362409d5469aed47d19e7908d19bd194493aThomas Graf	} else
57144d362409d5469aed47d19e7908d19bd194493aThomas Graf		nfnl_ct_set_family(ct, addr->a_family);
57244d362409d5469aed47d19e7908d19bd194493aThomas Graf
57344d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (*ct_addr)
57444d362409d5469aed47d19e7908d19bd194493aThomas Graf		nl_addr_put(*ct_addr);
57544d362409d5469aed47d19e7908d19bd194493aThomas Graf
57644d362409d5469aed47d19e7908d19bd194493aThomas Graf	nl_addr_get(addr);
57744d362409d5469aed47d19e7908d19bd194493aThomas Graf	*ct_addr = addr;
57844d362409d5469aed47d19e7908d19bd194493aThomas Graf	ct->ce_mask |= attr;
57944d362409d5469aed47d19e7908d19bd194493aThomas Graf
58044d362409d5469aed47d19e7908d19bd194493aThomas Graf	return 0;
58144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
58244d362409d5469aed47d19e7908d19bd194493aThomas Graf
58344d362409d5469aed47d19e7908d19bd194493aThomas Grafint nfnl_ct_set_src(struct nfnl_ct *ct, int repl, struct nl_addr *addr)
58444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
58544d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
58644d362409d5469aed47d19e7908d19bd194493aThomas Graf	int attr = repl ? CT_ATTR_REPL_SRC : CT_ATTR_ORIG_SRC;
58744d362409d5469aed47d19e7908d19bd194493aThomas Graf	return ct_set_addr(ct, addr, attr, &dir->src);
58844d362409d5469aed47d19e7908d19bd194493aThomas Graf}
58944d362409d5469aed47d19e7908d19bd194493aThomas Graf
59044d362409d5469aed47d19e7908d19bd194493aThomas Grafint nfnl_ct_set_dst(struct nfnl_ct *ct, int repl, struct nl_addr *addr)
59144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
59244d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
59344d362409d5469aed47d19e7908d19bd194493aThomas Graf	int attr = repl ? CT_ATTR_REPL_DST : CT_ATTR_ORIG_DST;
59444d362409d5469aed47d19e7908d19bd194493aThomas Graf	return ct_set_addr(ct, addr, attr, &dir->dst);
59544d362409d5469aed47d19e7908d19bd194493aThomas Graf}
59644d362409d5469aed47d19e7908d19bd194493aThomas Graf
59744d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_addr *nfnl_ct_get_src(const struct nfnl_ct *ct, int repl)
59844d362409d5469aed47d19e7908d19bd194493aThomas Graf{
59944d362409d5469aed47d19e7908d19bd194493aThomas Graf	const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
60044d362409d5469aed47d19e7908d19bd194493aThomas Graf	int attr = repl ? CT_ATTR_REPL_SRC : CT_ATTR_ORIG_SRC;
60144d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (!(ct->ce_mask & attr))
60244d362409d5469aed47d19e7908d19bd194493aThomas Graf		return NULL;
60344d362409d5469aed47d19e7908d19bd194493aThomas Graf	return dir->src;
60444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
60544d362409d5469aed47d19e7908d19bd194493aThomas Graf
60644d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_addr *nfnl_ct_get_dst(const struct nfnl_ct *ct, int repl)
60744d362409d5469aed47d19e7908d19bd194493aThomas Graf{
60844d362409d5469aed47d19e7908d19bd194493aThomas Graf	const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
60944d362409d5469aed47d19e7908d19bd194493aThomas Graf	int attr = repl ? CT_ATTR_REPL_DST : CT_ATTR_ORIG_DST;
61044d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (!(ct->ce_mask & attr))
61144d362409d5469aed47d19e7908d19bd194493aThomas Graf		return NULL;
61244d362409d5469aed47d19e7908d19bd194493aThomas Graf	return dir->dst;
61344d362409d5469aed47d19e7908d19bd194493aThomas Graf}
61444d362409d5469aed47d19e7908d19bd194493aThomas Graf
61544d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nfnl_ct_set_src_port(struct nfnl_ct *ct, int repl, uint16_t port)
61644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
61744d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
61844d362409d5469aed47d19e7908d19bd194493aThomas Graf	int attr = repl ? CT_ATTR_REPL_SRC_PORT : CT_ATTR_ORIG_SRC_PORT;
61944d362409d5469aed47d19e7908d19bd194493aThomas Graf
62044d362409d5469aed47d19e7908d19bd194493aThomas Graf	dir->proto.port.src = port;
62144d362409d5469aed47d19e7908d19bd194493aThomas Graf	ct->ce_mask |= attr;
62244d362409d5469aed47d19e7908d19bd194493aThomas Graf}
62344d362409d5469aed47d19e7908d19bd194493aThomas Graf
62444d362409d5469aed47d19e7908d19bd194493aThomas Grafint nfnl_ct_test_src_port(const struct nfnl_ct *ct, int repl)
62544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
62644d362409d5469aed47d19e7908d19bd194493aThomas Graf	int attr = repl ? CT_ATTR_REPL_SRC_PORT : CT_ATTR_ORIG_SRC_PORT;
62744d362409d5469aed47d19e7908d19bd194493aThomas Graf	return !!(ct->ce_mask & attr);
62844d362409d5469aed47d19e7908d19bd194493aThomas Graf}
62944d362409d5469aed47d19e7908d19bd194493aThomas Graf
63044d362409d5469aed47d19e7908d19bd194493aThomas Grafuint16_t nfnl_ct_get_src_port(const struct nfnl_ct *ct, int repl)
63144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
63244d362409d5469aed47d19e7908d19bd194493aThomas Graf	const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
63344d362409d5469aed47d19e7908d19bd194493aThomas Graf
63444d362409d5469aed47d19e7908d19bd194493aThomas Graf	return dir->proto.port.src;
63544d362409d5469aed47d19e7908d19bd194493aThomas Graf}
63644d362409d5469aed47d19e7908d19bd194493aThomas Graf
63744d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nfnl_ct_set_dst_port(struct nfnl_ct *ct, int repl, uint16_t port)
63844d362409d5469aed47d19e7908d19bd194493aThomas Graf{
63944d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
64044d362409d5469aed47d19e7908d19bd194493aThomas Graf	int attr = repl ? CT_ATTR_REPL_DST_PORT : CT_ATTR_ORIG_DST_PORT;
64144d362409d5469aed47d19e7908d19bd194493aThomas Graf
64244d362409d5469aed47d19e7908d19bd194493aThomas Graf	dir->proto.port.dst = port;
64344d362409d5469aed47d19e7908d19bd194493aThomas Graf	ct->ce_mask |= attr;
64444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
64544d362409d5469aed47d19e7908d19bd194493aThomas Graf
64644d362409d5469aed47d19e7908d19bd194493aThomas Grafint nfnl_ct_test_dst_port(const struct nfnl_ct *ct, int repl)
64744d362409d5469aed47d19e7908d19bd194493aThomas Graf{
64844d362409d5469aed47d19e7908d19bd194493aThomas Graf	int attr = repl ? CT_ATTR_REPL_DST_PORT : CT_ATTR_ORIG_DST_PORT;
64944d362409d5469aed47d19e7908d19bd194493aThomas Graf	return !!(ct->ce_mask & attr);
65044d362409d5469aed47d19e7908d19bd194493aThomas Graf}
65144d362409d5469aed47d19e7908d19bd194493aThomas Graf
65244d362409d5469aed47d19e7908d19bd194493aThomas Grafuint16_t nfnl_ct_get_dst_port(const struct nfnl_ct *ct, int repl)
65344d362409d5469aed47d19e7908d19bd194493aThomas Graf{
65444d362409d5469aed47d19e7908d19bd194493aThomas Graf	const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
65544d362409d5469aed47d19e7908d19bd194493aThomas Graf
65644d362409d5469aed47d19e7908d19bd194493aThomas Graf	return dir->proto.port.dst;
65744d362409d5469aed47d19e7908d19bd194493aThomas Graf}
65844d362409d5469aed47d19e7908d19bd194493aThomas Graf
65944d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nfnl_ct_set_icmp_id(struct nfnl_ct *ct, int repl, uint16_t id)
66044d362409d5469aed47d19e7908d19bd194493aThomas Graf{
66144d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
66244d362409d5469aed47d19e7908d19bd194493aThomas Graf	int attr = repl ? CT_ATTR_REPL_ICMP_ID : CT_ATTR_ORIG_ICMP_ID;
66344d362409d5469aed47d19e7908d19bd194493aThomas Graf
66444d362409d5469aed47d19e7908d19bd194493aThomas Graf	dir->proto.icmp.id = id;
66544d362409d5469aed47d19e7908d19bd194493aThomas Graf	ct->ce_mask |= attr;
66644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
66744d362409d5469aed47d19e7908d19bd194493aThomas Graf
66844d362409d5469aed47d19e7908d19bd194493aThomas Grafint nfnl_ct_test_icmp_id(const struct nfnl_ct *ct, int repl)
66944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
67044d362409d5469aed47d19e7908d19bd194493aThomas Graf	int attr = repl ? CT_ATTR_REPL_ICMP_ID : CT_ATTR_ORIG_ICMP_ID;
67144d362409d5469aed47d19e7908d19bd194493aThomas Graf	return !!(ct->ce_mask & attr);
67244d362409d5469aed47d19e7908d19bd194493aThomas Graf}
67344d362409d5469aed47d19e7908d19bd194493aThomas Graf
67444d362409d5469aed47d19e7908d19bd194493aThomas Grafuint16_t nfnl_ct_get_icmp_id(const struct nfnl_ct *ct, int repl)
67544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
67644d362409d5469aed47d19e7908d19bd194493aThomas Graf	const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
67744d362409d5469aed47d19e7908d19bd194493aThomas Graf
67844d362409d5469aed47d19e7908d19bd194493aThomas Graf	return dir->proto.icmp.id;
67944d362409d5469aed47d19e7908d19bd194493aThomas Graf}
68044d362409d5469aed47d19e7908d19bd194493aThomas Graf
68144d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nfnl_ct_set_icmp_type(struct nfnl_ct *ct, int repl, uint8_t type)
68244d362409d5469aed47d19e7908d19bd194493aThomas Graf{
68344d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
68444d362409d5469aed47d19e7908d19bd194493aThomas Graf	int attr = repl ? CT_ATTR_REPL_ICMP_TYPE : CT_ATTR_ORIG_ICMP_TYPE;
68544d362409d5469aed47d19e7908d19bd194493aThomas Graf
68644d362409d5469aed47d19e7908d19bd194493aThomas Graf	dir->proto.icmp.type = type;
68744d362409d5469aed47d19e7908d19bd194493aThomas Graf	ct->ce_mask |= attr;
68844d362409d5469aed47d19e7908d19bd194493aThomas Graf}
68944d362409d5469aed47d19e7908d19bd194493aThomas Graf
69044d362409d5469aed47d19e7908d19bd194493aThomas Grafint nfnl_ct_test_icmp_type(const struct nfnl_ct *ct, int repl)
69144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
69244d362409d5469aed47d19e7908d19bd194493aThomas Graf	int attr = repl ? CT_ATTR_REPL_ICMP_TYPE : CT_ATTR_ORIG_ICMP_TYPE;
69344d362409d5469aed47d19e7908d19bd194493aThomas Graf	return !!(ct->ce_mask & attr);
69444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
69544d362409d5469aed47d19e7908d19bd194493aThomas Graf
69644d362409d5469aed47d19e7908d19bd194493aThomas Grafuint8_t nfnl_ct_get_icmp_type(const struct nfnl_ct *ct, int repl)
69744d362409d5469aed47d19e7908d19bd194493aThomas Graf{
69844d362409d5469aed47d19e7908d19bd194493aThomas Graf	const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
69944d362409d5469aed47d19e7908d19bd194493aThomas Graf
70044d362409d5469aed47d19e7908d19bd194493aThomas Graf	return dir->proto.icmp.type;
70144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
70244d362409d5469aed47d19e7908d19bd194493aThomas Graf
70344d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nfnl_ct_set_icmp_code(struct nfnl_ct *ct, int repl, uint8_t code)
70444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
70544d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
70644d362409d5469aed47d19e7908d19bd194493aThomas Graf	int attr = repl ? CT_ATTR_REPL_ICMP_CODE : CT_ATTR_ORIG_ICMP_CODE;
70744d362409d5469aed47d19e7908d19bd194493aThomas Graf
70844d362409d5469aed47d19e7908d19bd194493aThomas Graf	dir->proto.icmp.code = code;
70944d362409d5469aed47d19e7908d19bd194493aThomas Graf	ct->ce_mask |= attr;
71044d362409d5469aed47d19e7908d19bd194493aThomas Graf}
71144d362409d5469aed47d19e7908d19bd194493aThomas Graf
71244d362409d5469aed47d19e7908d19bd194493aThomas Grafint nfnl_ct_test_icmp_code(const struct nfnl_ct *ct, int repl)
71344d362409d5469aed47d19e7908d19bd194493aThomas Graf{
71444d362409d5469aed47d19e7908d19bd194493aThomas Graf	int attr = repl ? CT_ATTR_REPL_ICMP_CODE : CT_ATTR_ORIG_ICMP_CODE;
71544d362409d5469aed47d19e7908d19bd194493aThomas Graf	return !!(ct->ce_mask & attr);
71644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
71744d362409d5469aed47d19e7908d19bd194493aThomas Graf
71844d362409d5469aed47d19e7908d19bd194493aThomas Grafuint8_t nfnl_ct_get_icmp_code(const struct nfnl_ct *ct, int repl)
71944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
72044d362409d5469aed47d19e7908d19bd194493aThomas Graf	const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
72144d362409d5469aed47d19e7908d19bd194493aThomas Graf
72244d362409d5469aed47d19e7908d19bd194493aThomas Graf	return dir->proto.icmp.code;
72344d362409d5469aed47d19e7908d19bd194493aThomas Graf}
72444d362409d5469aed47d19e7908d19bd194493aThomas Graf
72544d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nfnl_ct_set_packets(struct nfnl_ct *ct, int repl, uint64_t packets)
72644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
72744d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
72844d362409d5469aed47d19e7908d19bd194493aThomas Graf	int attr = repl ? CT_ATTR_REPL_PACKETS : CT_ATTR_ORIG_PACKETS;
72944d362409d5469aed47d19e7908d19bd194493aThomas Graf
73044d362409d5469aed47d19e7908d19bd194493aThomas Graf	dir->packets = packets;
73144d362409d5469aed47d19e7908d19bd194493aThomas Graf	ct->ce_mask |= attr;
73244d362409d5469aed47d19e7908d19bd194493aThomas Graf}
73344d362409d5469aed47d19e7908d19bd194493aThomas Graf
73444d362409d5469aed47d19e7908d19bd194493aThomas Grafint nfnl_ct_test_packets(const struct nfnl_ct *ct, int repl)
73544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
73644d362409d5469aed47d19e7908d19bd194493aThomas Graf	int attr = repl ? CT_ATTR_REPL_PACKETS : CT_ATTR_ORIG_PACKETS;
73744d362409d5469aed47d19e7908d19bd194493aThomas Graf	return !!(ct->ce_mask & attr);
73844d362409d5469aed47d19e7908d19bd194493aThomas Graf}
73944d362409d5469aed47d19e7908d19bd194493aThomas Graf
74044d362409d5469aed47d19e7908d19bd194493aThomas Grafuint64_t nfnl_ct_get_packets(const struct nfnl_ct *ct, int repl)
74144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
74244d362409d5469aed47d19e7908d19bd194493aThomas Graf	const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
74344d362409d5469aed47d19e7908d19bd194493aThomas Graf
74444d362409d5469aed47d19e7908d19bd194493aThomas Graf	return dir->packets;
74544d362409d5469aed47d19e7908d19bd194493aThomas Graf}
74644d362409d5469aed47d19e7908d19bd194493aThomas Graf
74744d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nfnl_ct_set_bytes(struct nfnl_ct *ct, int repl, uint64_t bytes)
74844d362409d5469aed47d19e7908d19bd194493aThomas Graf{
74944d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
75044d362409d5469aed47d19e7908d19bd194493aThomas Graf	int attr = repl ? CT_ATTR_REPL_BYTES : CT_ATTR_ORIG_BYTES;
75144d362409d5469aed47d19e7908d19bd194493aThomas Graf
75244d362409d5469aed47d19e7908d19bd194493aThomas Graf	dir->bytes = bytes;
75344d362409d5469aed47d19e7908d19bd194493aThomas Graf	ct->ce_mask |= attr;
75444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
75544d362409d5469aed47d19e7908d19bd194493aThomas Graf
75644d362409d5469aed47d19e7908d19bd194493aThomas Grafint nfnl_ct_test_bytes(const struct nfnl_ct *ct, int repl)
75744d362409d5469aed47d19e7908d19bd194493aThomas Graf{
75844d362409d5469aed47d19e7908d19bd194493aThomas Graf	int attr = repl ? CT_ATTR_REPL_BYTES : CT_ATTR_ORIG_BYTES;
75944d362409d5469aed47d19e7908d19bd194493aThomas Graf	return !!(ct->ce_mask & attr);
76044d362409d5469aed47d19e7908d19bd194493aThomas Graf}
76144d362409d5469aed47d19e7908d19bd194493aThomas Graf
76244d362409d5469aed47d19e7908d19bd194493aThomas Grafuint64_t nfnl_ct_get_bytes(const struct nfnl_ct *ct, int repl)
76344d362409d5469aed47d19e7908d19bd194493aThomas Graf{
76444d362409d5469aed47d19e7908d19bd194493aThomas Graf	const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
76544d362409d5469aed47d19e7908d19bd194493aThomas Graf
76644d362409d5469aed47d19e7908d19bd194493aThomas Graf	return dir->bytes;
76744d362409d5469aed47d19e7908d19bd194493aThomas Graf}
76844d362409d5469aed47d19e7908d19bd194493aThomas Graf
76944d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
77044d362409d5469aed47d19e7908d19bd194493aThomas Graf
77144d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_object_ops ct_obj_ops = {
77244d362409d5469aed47d19e7908d19bd194493aThomas Graf	.oo_name		= "netfilter/ct",
77344d362409d5469aed47d19e7908d19bd194493aThomas Graf	.oo_size		= sizeof(struct nfnl_ct),
77444d362409d5469aed47d19e7908d19bd194493aThomas Graf	.oo_free_data		= ct_free_data,
77544d362409d5469aed47d19e7908d19bd194493aThomas Graf	.oo_clone		= ct_clone,
776d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf	.oo_dump = {
777d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf	    [NL_DUMP_LINE]	= ct_dump_line,
778d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf	    [NL_DUMP_DETAILS]	= ct_dump_details,
779d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf	    [NL_DUMP_STATS]	= ct_dump_stats,
780d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf	},
78144d362409d5469aed47d19e7908d19bd194493aThomas Graf	.oo_compare		= ct_compare,
78244d362409d5469aed47d19e7908d19bd194493aThomas Graf	.oo_attrs2str		= ct_attrs2str,
78344d362409d5469aed47d19e7908d19bd194493aThomas Graf};
78444d362409d5469aed47d19e7908d19bd194493aThomas Graf
78544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
786