Home | History | Annotate | Download | only in netfilter
      1 /*
      2  * lib/netfilter/ct.c	Conntrack
      3  *
      4  *	This library is free software; you can redistribute it and/or
      5  *	modify it under the terms of the GNU Lesser General Public
      6  *	License as published by the Free Software Foundation version 2.1
      7  *	of the License.
      8  *
      9  * Copyright (c) 2003-2008 Thomas Graf <tgraf (at) suug.ch>
     10  * Copyright (c) 2007 Philip Craig <philipc (at) snapgear.com>
     11  * Copyright (c) 2007 Secure Computing Corporation
     12  * Copyright (c= 2008 Patrick McHardy <kaber (at) trash.net>
     13  */
     14 
     15 /**
     16  * @ingroup nfnl
     17  * @defgroup ct Conntrack
     18  * @brief
     19  * @{
     20  */
     21 
     22 #include <byteswap.h>
     23 #include <sys/types.h>
     24 #include <linux/netfilter/nfnetlink_conntrack.h>
     25 
     26 #include <netlink-private/netlink.h>
     27 #include <netlink/attr.h>
     28 #include <netlink/netfilter/nfnl.h>
     29 #include <netlink/netfilter/ct.h>
     30 
     31 static struct nl_cache_ops nfnl_ct_ops;
     32 
     33 #if __BYTE_ORDER == __BIG_ENDIAN
     34 static uint64_t ntohll(uint64_t x)
     35 {
     36 	return x;
     37 }
     38 static uint64_t htonll(uint64_t x)
     39 {
     40 	return x;
     41 }
     42 #elif __BYTE_ORDER == __LITTLE_ENDIAN
     43 static uint64_t ntohll(uint64_t x)
     44 {
     45 	return bswap_64(x);
     46 }
     47 static uint64_t htonll(uint64_t x)
     48 {
     49 	return bswap_64(x);
     50 }
     51 #endif
     52 
     53 static struct nla_policy ct_policy[CTA_MAX+1] = {
     54 	[CTA_TUPLE_ORIG]	= { .type = NLA_NESTED },
     55 	[CTA_TUPLE_REPLY]	= { .type = NLA_NESTED },
     56 	[CTA_STATUS]		= { .type = NLA_U32 },
     57 	[CTA_PROTOINFO]		= { .type = NLA_NESTED },
     58 	//[CTA_HELP]
     59 	//[CTA_NAT_SRC]
     60 	[CTA_TIMEOUT]		= { .type = NLA_U32 },
     61 	[CTA_MARK]		= { .type = NLA_U32 },
     62 	[CTA_COUNTERS_ORIG]	= { .type = NLA_NESTED },
     63 	[CTA_COUNTERS_REPLY]	= { .type = NLA_NESTED },
     64 	[CTA_USE]		= { .type = NLA_U32 },
     65 	[CTA_ID]		= { .type = NLA_U32 },
     66 	[CTA_ZONE]		= { .type = NLA_U16 },
     67 	//[CTA_NAT_DST]
     68 };
     69 
     70 static struct nla_policy ct_tuple_policy[CTA_TUPLE_MAX+1] = {
     71 	[CTA_TUPLE_IP]		= { .type = NLA_NESTED },
     72 	[CTA_TUPLE_PROTO]	= { .type = NLA_NESTED },
     73 };
     74 
     75 static struct nla_policy ct_ip_policy[CTA_IP_MAX+1] = {
     76 	[CTA_IP_V4_SRC]		= { .type = NLA_U32 },
     77 	[CTA_IP_V4_DST]		= { .type = NLA_U32 },
     78 	[CTA_IP_V6_SRC]		= { .minlen = 16 },
     79 	[CTA_IP_V6_DST]		= { .minlen = 16 },
     80 };
     81 
     82 static struct nla_policy ct_proto_policy[CTA_PROTO_MAX+1] = {
     83 	[CTA_PROTO_NUM]		= { .type = NLA_U8 },
     84 	[CTA_PROTO_SRC_PORT]	= { .type = NLA_U16 },
     85 	[CTA_PROTO_DST_PORT]	= { .type = NLA_U16 },
     86 	[CTA_PROTO_ICMP_ID]	= { .type = NLA_U16 },
     87 	[CTA_PROTO_ICMP_TYPE]	= { .type = NLA_U8 },
     88 	[CTA_PROTO_ICMP_CODE]	= { .type = NLA_U8 },
     89 	[CTA_PROTO_ICMPV6_ID]	= { .type = NLA_U16 },
     90 	[CTA_PROTO_ICMPV6_TYPE]	= { .type = NLA_U8 },
     91 	[CTA_PROTO_ICMPV6_CODE]	= { .type = NLA_U8 },
     92 };
     93 
     94 static struct nla_policy ct_protoinfo_policy[CTA_PROTOINFO_MAX+1] = {
     95 	[CTA_PROTOINFO_TCP]	= { .type = NLA_NESTED },
     96 };
     97 
     98 static struct nla_policy ct_protoinfo_tcp_policy[CTA_PROTOINFO_TCP_MAX+1] = {
     99 	[CTA_PROTOINFO_TCP_STATE]		= { .type = NLA_U8 },
    100 	[CTA_PROTOINFO_TCP_WSCALE_ORIGINAL]	= { .type = NLA_U8 },
    101 	[CTA_PROTOINFO_TCP_WSCALE_REPLY]	= { .type = NLA_U8 },
    102 	[CTA_PROTOINFO_TCP_FLAGS_ORIGINAL]	= { .minlen = 2 },
    103 	[CTA_PROTOINFO_TCP_FLAGS_REPLY]		= { .minlen = 2 },
    104 
    105 };
    106 
    107 static struct nla_policy ct_counters_policy[CTA_COUNTERS_MAX+1] = {
    108 	[CTA_COUNTERS_PACKETS]	= { .type = NLA_U64 },
    109 	[CTA_COUNTERS_BYTES]	= { .type = NLA_U64 },
    110 	[CTA_COUNTERS32_PACKETS]= { .type = NLA_U32 },
    111 	[CTA_COUNTERS32_BYTES]	= { .type = NLA_U32 },
    112 };
    113 
    114 static struct nla_policy ct_timestamp_policy[CTA_TIMESTAMP_MAX + 1] = {
    115 	[CTA_TIMESTAMP_START]	= { .type = NLA_U64 },
    116 	[CTA_TIMESTAMP_STOP]	= { .type = NLA_U64 },
    117 };
    118 
    119 static int ct_parse_ip(struct nfnl_ct *ct, int repl, struct nlattr *attr)
    120 {
    121 	struct nlattr *tb[CTA_IP_MAX+1];
    122 	struct nl_addr *addr;
    123 	int err;
    124 
    125         err = nla_parse_nested(tb, CTA_IP_MAX, attr, ct_ip_policy);
    126 	if (err < 0)
    127 		goto errout;
    128 
    129 	if (tb[CTA_IP_V4_SRC]) {
    130 		addr = nl_addr_alloc_attr(tb[CTA_IP_V4_SRC], AF_INET);
    131 		if (addr == NULL)
    132 			goto errout_enomem;
    133 		err = nfnl_ct_set_src(ct, repl, addr);
    134 		nl_addr_put(addr);
    135 		if (err < 0)
    136 			goto errout;
    137 	}
    138 	if (tb[CTA_IP_V4_DST]) {
    139 		addr = nl_addr_alloc_attr(tb[CTA_IP_V4_DST], AF_INET);
    140 		if (addr == NULL)
    141 			goto errout_enomem;
    142 		err = nfnl_ct_set_dst(ct, repl, addr);
    143 		nl_addr_put(addr);
    144 		if (err < 0)
    145 			goto errout;
    146 	}
    147 	if (tb[CTA_IP_V6_SRC]) {
    148 		addr = nl_addr_alloc_attr(tb[CTA_IP_V6_SRC], AF_INET6);
    149 		if (addr == NULL)
    150 			goto errout_enomem;
    151 		err = nfnl_ct_set_src(ct, repl, addr);
    152 		nl_addr_put(addr);
    153 		if (err < 0)
    154 			goto errout;
    155 	}
    156 	if (tb[CTA_IP_V6_DST]) {
    157 		addr = nl_addr_alloc_attr(tb[CTA_IP_V6_DST], AF_INET6);
    158 		if (addr == NULL)
    159 			goto errout_enomem;
    160 		err = nfnl_ct_set_dst(ct, repl, addr);
    161 		nl_addr_put(addr);
    162 		if (err < 0)
    163 			goto errout;
    164 	}
    165 
    166 	return 0;
    167 
    168 errout_enomem:
    169 	err = -NLE_NOMEM;
    170 errout:
    171 	return err;
    172 }
    173 
    174 static int ct_parse_proto(struct nfnl_ct *ct, int repl, struct nlattr *attr)
    175 {
    176 	struct nlattr *tb[CTA_PROTO_MAX+1];
    177 	int err;
    178 
    179 	err = nla_parse_nested(tb, CTA_PROTO_MAX, attr, ct_proto_policy);
    180 	if (err < 0)
    181 		return err;
    182 
    183 	if (!repl && tb[CTA_PROTO_NUM])
    184 		nfnl_ct_set_proto(ct, nla_get_u8(tb[CTA_PROTO_NUM]));
    185 	if (tb[CTA_PROTO_SRC_PORT])
    186 		nfnl_ct_set_src_port(ct, repl,
    187 			ntohs(nla_get_u16(tb[CTA_PROTO_SRC_PORT])));
    188 	if (tb[CTA_PROTO_DST_PORT])
    189 		nfnl_ct_set_dst_port(ct, repl,
    190 			ntohs(nla_get_u16(tb[CTA_PROTO_DST_PORT])));
    191 
    192 	if (ct->ct_family == AF_INET) {
    193 		if (tb[CTA_PROTO_ICMP_ID])
    194 			nfnl_ct_set_icmp_id(ct, repl,
    195 				ntohs(nla_get_u16(tb[CTA_PROTO_ICMP_ID])));
    196 		if (tb[CTA_PROTO_ICMP_TYPE])
    197 			nfnl_ct_set_icmp_type(ct, repl,
    198 				nla_get_u8(tb[CTA_PROTO_ICMP_TYPE]));
    199 		if (tb[CTA_PROTO_ICMP_CODE])
    200 			nfnl_ct_set_icmp_code(ct, repl,
    201 				nla_get_u8(tb[CTA_PROTO_ICMP_CODE]));
    202 	} else if (ct->ct_family == AF_INET6) {
    203 		if (tb[CTA_PROTO_ICMPV6_ID])
    204 			nfnl_ct_set_icmp_id(ct, repl,
    205 			    ntohs(nla_get_u16(tb[CTA_PROTO_ICMPV6_ID])));
    206 		if (tb[CTA_PROTO_ICMPV6_TYPE])
    207 			nfnl_ct_set_icmp_type(ct, repl,
    208 				nla_get_u8(tb[CTA_PROTO_ICMPV6_TYPE]));
    209 		if (tb[CTA_PROTO_ICMPV6_CODE])
    210 			nfnl_ct_set_icmp_code(ct, repl,
    211 				nla_get_u8(tb[CTA_PROTO_ICMPV6_CODE]));
    212 	}
    213 
    214 	return 0;
    215 }
    216 
    217 static int ct_parse_tuple(struct nfnl_ct *ct, int repl, struct nlattr *attr)
    218 {
    219 	struct nlattr *tb[CTA_TUPLE_MAX+1];
    220 	int err;
    221 
    222 	err = nla_parse_nested(tb, CTA_TUPLE_MAX, attr, ct_tuple_policy);
    223 	if (err < 0)
    224 		return err;
    225 
    226 	if (tb[CTA_TUPLE_IP]) {
    227 		err = ct_parse_ip(ct, repl, tb[CTA_TUPLE_IP]);
    228 		if (err < 0)
    229 			return err;
    230 	}
    231 
    232 	if (tb[CTA_TUPLE_PROTO]) {
    233 		err = ct_parse_proto(ct, repl, tb[CTA_TUPLE_PROTO]);
    234 		if (err < 0)
    235 			return err;
    236 	}
    237 
    238 	return 0;
    239 }
    240 
    241 static int ct_parse_protoinfo_tcp(struct nfnl_ct *ct, struct nlattr *attr)
    242 {
    243 	struct nlattr *tb[CTA_PROTOINFO_TCP_MAX+1];
    244 	int err;
    245 
    246 	err = nla_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr,
    247 			       ct_protoinfo_tcp_policy);
    248 	if (err < 0)
    249 		return err;
    250 
    251 	if (tb[CTA_PROTOINFO_TCP_STATE])
    252 		nfnl_ct_set_tcp_state(ct,
    253 				nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]));
    254 
    255 	return 0;
    256 }
    257 
    258 static int ct_parse_protoinfo(struct nfnl_ct *ct, struct nlattr *attr)
    259 {
    260 	struct nlattr *tb[CTA_PROTOINFO_MAX+1];
    261 	int err;
    262 
    263 	err = nla_parse_nested(tb, CTA_PROTOINFO_MAX, attr,
    264 			       ct_protoinfo_policy);
    265 	if (err < 0)
    266 		return err;
    267 
    268 	if (tb[CTA_PROTOINFO_TCP]) {
    269 		err = ct_parse_protoinfo_tcp(ct, tb[CTA_PROTOINFO_TCP]);
    270 		if (err < 0)
    271 			return err;
    272 	}
    273 
    274 	return 0;
    275 }
    276 
    277 static int ct_parse_counters(struct nfnl_ct *ct, int repl, struct nlattr *attr)
    278 {
    279 	struct nlattr *tb[CTA_COUNTERS_MAX+1];
    280 	int err;
    281 
    282 	err = nla_parse_nested(tb, CTA_COUNTERS_MAX, attr, ct_counters_policy);
    283 	if (err < 0)
    284 		return err;
    285 
    286 	if (tb[CTA_COUNTERS_PACKETS])
    287 		nfnl_ct_set_packets(ct, repl,
    288 			ntohll(nla_get_u64(tb[CTA_COUNTERS_PACKETS])));
    289 	if (tb[CTA_COUNTERS32_PACKETS])
    290 		nfnl_ct_set_packets(ct, repl,
    291 			ntohl(nla_get_u32(tb[CTA_COUNTERS32_PACKETS])));
    292 	if (tb[CTA_COUNTERS_BYTES])
    293 		nfnl_ct_set_bytes(ct, repl,
    294 			ntohll(nla_get_u64(tb[CTA_COUNTERS_BYTES])));
    295 	if (tb[CTA_COUNTERS32_BYTES])
    296 		nfnl_ct_set_bytes(ct, repl,
    297 			ntohl(nla_get_u32(tb[CTA_COUNTERS32_BYTES])));
    298 
    299 	return 0;
    300 }
    301 
    302 int nfnlmsg_ct_group(struct nlmsghdr *nlh)
    303 {
    304 	switch (nfnlmsg_subtype(nlh)) {
    305 	case IPCTNL_MSG_CT_NEW:
    306 		if (nlh->nlmsg_flags & (NLM_F_CREATE|NLM_F_EXCL))
    307 			return NFNLGRP_CONNTRACK_NEW;
    308 		else
    309 			return NFNLGRP_CONNTRACK_UPDATE;
    310 	case IPCTNL_MSG_CT_DELETE:
    311 		return NFNLGRP_CONNTRACK_DESTROY;
    312 	default:
    313 		return NFNLGRP_NONE;
    314 	}
    315 }
    316 
    317 static int ct_parse_timestamp(struct nfnl_ct *ct, struct nlattr *attr)
    318 {
    319 	struct nlattr *tb[CTA_TIMESTAMP_MAX + 1];
    320 	int err;
    321 
    322 	err = nla_parse_nested(tb, CTA_TIMESTAMP_MAX, attr,
    323 			       ct_timestamp_policy);
    324 	if (err < 0)
    325 		return err;
    326 
    327 	if (tb[CTA_TIMESTAMP_START] && tb[CTA_TIMESTAMP_STOP])
    328 		nfnl_ct_set_timestamp(ct,
    329 			      ntohll(nla_get_u64(tb[CTA_TIMESTAMP_START])),
    330 			      ntohll(nla_get_u64(tb[CTA_TIMESTAMP_STOP])));
    331 
    332 	return 0;
    333 }
    334 
    335 int nfnlmsg_ct_parse(struct nlmsghdr *nlh, struct nfnl_ct **result)
    336 {
    337 	struct nfnl_ct *ct;
    338 	struct nlattr *tb[CTA_MAX+1];
    339 	int err;
    340 
    341 	ct = nfnl_ct_alloc();
    342 	if (!ct)
    343 		return -NLE_NOMEM;
    344 
    345 	ct->ce_msgtype = nlh->nlmsg_type;
    346 
    347 	err = nlmsg_parse(nlh, sizeof(struct nfgenmsg), tb, CTA_MAX,
    348 			  ct_policy);
    349 	if (err < 0)
    350 		goto errout;
    351 
    352 	nfnl_ct_set_family(ct, nfnlmsg_family(nlh));
    353 
    354 	if (tb[CTA_TUPLE_ORIG]) {
    355 		err = ct_parse_tuple(ct, 0, tb[CTA_TUPLE_ORIG]);
    356 		if (err < 0)
    357 			goto errout;
    358 	}
    359 	if (tb[CTA_TUPLE_REPLY]) {
    360 		err = ct_parse_tuple(ct, 1, tb[CTA_TUPLE_REPLY]);
    361 		if (err < 0)
    362 			goto errout;
    363 	}
    364 
    365 	if (tb[CTA_PROTOINFO]) {
    366 		err = ct_parse_protoinfo(ct, tb[CTA_PROTOINFO]);
    367 		if (err < 0)
    368 			goto errout;
    369 	}
    370 
    371 	if (tb[CTA_STATUS])
    372 		nfnl_ct_set_status(ct, ntohl(nla_get_u32(tb[CTA_STATUS])));
    373 	if (tb[CTA_TIMEOUT])
    374 		nfnl_ct_set_timeout(ct, ntohl(nla_get_u32(tb[CTA_TIMEOUT])));
    375 	if (tb[CTA_MARK])
    376 		nfnl_ct_set_mark(ct, ntohl(nla_get_u32(tb[CTA_MARK])));
    377 	if (tb[CTA_USE])
    378 		nfnl_ct_set_use(ct, ntohl(nla_get_u32(tb[CTA_USE])));
    379 	if (tb[CTA_ID])
    380 		nfnl_ct_set_id(ct, ntohl(nla_get_u32(tb[CTA_ID])));
    381 	if (tb[CTA_ZONE])
    382 		nfnl_ct_set_zone(ct, ntohs(nla_get_u16(tb[CTA_ZONE])));
    383 
    384 	if (tb[CTA_COUNTERS_ORIG]) {
    385 		err = ct_parse_counters(ct, 0, tb[CTA_COUNTERS_ORIG]);
    386 		if (err < 0)
    387 			goto errout;
    388 	}
    389 
    390 	if (tb[CTA_COUNTERS_REPLY]) {
    391 		err = ct_parse_counters(ct, 1, tb[CTA_COUNTERS_REPLY]);
    392 		if (err < 0)
    393 			goto errout;
    394 	}
    395 
    396 	if (tb[CTA_TIMESTAMP]) {
    397 		err = ct_parse_timestamp(ct, tb[CTA_TIMESTAMP]);
    398 		if (err < 0)
    399 			goto errout;
    400 	}
    401 
    402 	*result = ct;
    403 	return 0;
    404 
    405 errout:
    406 	nfnl_ct_put(ct);
    407 	return err;
    408 }
    409 
    410 static int ct_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
    411 			 struct nlmsghdr *nlh, struct nl_parser_param *pp)
    412 {
    413 	struct nfnl_ct *ct;
    414 	int err;
    415 
    416 	if ((err = nfnlmsg_ct_parse(nlh, &ct)) < 0)
    417 		return err;
    418 
    419 	err = pp->pp_cb((struct nl_object *) ct, pp);
    420 	nfnl_ct_put(ct);
    421 	return err;
    422 }
    423 
    424 int nfnl_ct_dump_request(struct nl_sock *sk)
    425 {
    426 	return nfnl_send_simple(sk, NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET,
    427 				NLM_F_DUMP, AF_UNSPEC, 0);
    428 }
    429 
    430 static int ct_request_update(struct nl_cache *cache, struct nl_sock *sk)
    431 {
    432 	return nfnl_ct_dump_request(sk);
    433 }
    434 
    435 static int nfnl_ct_build_tuple(struct nl_msg *msg, const struct nfnl_ct *ct,
    436 			       int repl)
    437 {
    438 	struct nlattr *tuple, *ip, *proto;
    439 	struct nl_addr *addr;
    440 	int family;
    441 
    442 	family = nfnl_ct_get_family(ct);
    443 
    444 	tuple = nla_nest_start(msg, repl ? CTA_TUPLE_REPLY : CTA_TUPLE_ORIG);
    445 	if (!tuple)
    446 		goto nla_put_failure;
    447 
    448 	ip = nla_nest_start(msg, CTA_TUPLE_IP);
    449 	if (!ip)
    450 		goto nla_put_failure;
    451 
    452 	addr = nfnl_ct_get_src(ct, repl);
    453 	if (addr)
    454 		NLA_PUT_ADDR(msg,
    455 			     family == AF_INET ? CTA_IP_V4_SRC : CTA_IP_V6_SRC,
    456 			     addr);
    457 
    458 	addr = nfnl_ct_get_dst(ct, repl);
    459 	if (addr)
    460 		NLA_PUT_ADDR(msg,
    461 			     family == AF_INET ? CTA_IP_V4_DST : CTA_IP_V6_DST,
    462 			     addr);
    463 
    464 	nla_nest_end(msg, ip);
    465 
    466 	proto = nla_nest_start(msg, CTA_TUPLE_PROTO);
    467 	if (!proto)
    468 		goto nla_put_failure;
    469 
    470 	if (nfnl_ct_test_proto(ct))
    471 		NLA_PUT_U8(msg, CTA_PROTO_NUM, nfnl_ct_get_proto(ct));
    472 
    473 	if (nfnl_ct_test_src_port(ct, repl))
    474 		NLA_PUT_U16(msg, CTA_PROTO_SRC_PORT,
    475 			htons(nfnl_ct_get_src_port(ct, repl)));
    476 
    477 	if (nfnl_ct_test_dst_port(ct, repl))
    478 		NLA_PUT_U16(msg, CTA_PROTO_DST_PORT,
    479 			htons(nfnl_ct_get_dst_port(ct, repl)));
    480 
    481 	if (family == AF_INET) {
    482 		if (nfnl_ct_test_icmp_id(ct, repl))
    483 			NLA_PUT_U16(msg, CTA_PROTO_ICMP_ID,
    484 						htons(nfnl_ct_get_icmp_id(ct, repl)));
    485 
    486 		if (nfnl_ct_test_icmp_type(ct, repl))
    487 			NLA_PUT_U8(msg, CTA_PROTO_ICMP_TYPE,
    488 					   nfnl_ct_get_icmp_type(ct, repl));
    489 
    490 		if (nfnl_ct_test_icmp_code(ct, repl))
    491 			NLA_PUT_U8(msg, CTA_PROTO_ICMP_CODE,
    492 					   nfnl_ct_get_icmp_code(ct, repl));
    493 	} else if (family == AF_INET6) {
    494 		if (nfnl_ct_test_icmp_id(ct, repl))
    495 			NLA_PUT_U16(msg, CTA_PROTO_ICMPV6_ID,
    496 						htons(nfnl_ct_get_icmp_id(ct, repl)));
    497 
    498 		if (nfnl_ct_test_icmp_type(ct, repl))
    499 			NLA_PUT_U8(msg, CTA_PROTO_ICMPV6_TYPE,
    500 					   nfnl_ct_get_icmp_type(ct, repl));
    501 
    502 		if (nfnl_ct_test_icmp_code(ct, repl))
    503 			NLA_PUT_U8(msg, CTA_PROTO_ICMPV6_CODE,
    504 					   nfnl_ct_get_icmp_code(ct, repl));
    505 	}
    506 
    507 	nla_nest_end(msg, proto);
    508 
    509 	nla_nest_end(msg, tuple);
    510 	return 0;
    511 
    512 nla_put_failure:
    513 	return -NLE_MSGSIZE;
    514 }
    515 
    516 static int nfnl_ct_build_message(const struct nfnl_ct *ct, int cmd, int flags,
    517 				 struct nl_msg **result)
    518 {
    519 	struct nl_msg *msg;
    520 	int err;
    521 
    522 	msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_CTNETLINK, cmd, flags,
    523 				   nfnl_ct_get_family(ct), 0);
    524 	if (msg == NULL)
    525 		return -NLE_NOMEM;
    526 
    527 	if ((err = nfnl_ct_build_tuple(msg, ct, 0)) < 0)
    528 		goto err_out;
    529 
    530 	/* REPLY tuple is optional, dont add unless at least src/dst specified */
    531 
    532 	if ( nfnl_ct_get_src(ct, 1) && nfnl_ct_get_dst(ct, 1) )
    533 		if ((err = nfnl_ct_build_tuple(msg, ct, 1)) < 0)
    534 			goto err_out;
    535 
    536 	if (nfnl_ct_test_status(ct))
    537 		NLA_PUT_U32(msg, CTA_STATUS, htonl(nfnl_ct_get_status(ct)));
    538 
    539 	if (nfnl_ct_test_timeout(ct))
    540 		NLA_PUT_U32(msg, CTA_TIMEOUT, htonl(nfnl_ct_get_timeout(ct)));
    541 
    542 	if (nfnl_ct_test_mark(ct))
    543 		NLA_PUT_U32(msg, CTA_MARK, htonl(nfnl_ct_get_mark(ct)));
    544 
    545 	if (nfnl_ct_test_id(ct))
    546 		NLA_PUT_U32(msg, CTA_ID, htonl(nfnl_ct_get_id(ct)));
    547 
    548 	if (nfnl_ct_test_zone(ct))
    549 		NLA_PUT_U16(msg, CTA_ZONE, htons(nfnl_ct_get_zone(ct)));
    550 
    551 	*result = msg;
    552 	return 0;
    553 
    554 nla_put_failure:
    555 err_out:
    556 	nlmsg_free(msg);
    557 	return err;
    558 }
    559 
    560 int nfnl_ct_build_add_request(const struct nfnl_ct *ct, int flags,
    561 			      struct nl_msg **result)
    562 {
    563 	return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_NEW, flags, result);
    564 }
    565 
    566 int nfnl_ct_add(struct nl_sock *sk, const struct nfnl_ct *ct, int flags)
    567 {
    568 	struct nl_msg *msg;
    569 	int err;
    570 
    571 	if ((err = nfnl_ct_build_add_request(ct, flags, &msg)) < 0)
    572 		return err;
    573 
    574 	err = nl_send_auto_complete(sk, msg);
    575 	nlmsg_free(msg);
    576 	if (err < 0)
    577 		return err;
    578 
    579 	return wait_for_ack(sk);
    580 }
    581 
    582 int nfnl_ct_build_delete_request(const struct nfnl_ct *ct, int flags,
    583 				 struct nl_msg **result)
    584 {
    585 	return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_DELETE, flags, result);
    586 }
    587 
    588 int nfnl_ct_del(struct nl_sock *sk, const struct nfnl_ct *ct, int flags)
    589 {
    590 	struct nl_msg *msg;
    591 	int err;
    592 
    593 	if ((err = nfnl_ct_build_delete_request(ct, flags, &msg)) < 0)
    594 		return err;
    595 
    596 	err = nl_send_auto_complete(sk, msg);
    597 	nlmsg_free(msg);
    598 	if (err < 0)
    599 		return err;
    600 
    601 	return wait_for_ack(sk);
    602 }
    603 
    604 int nfnl_ct_build_query_request(const struct nfnl_ct *ct, int flags,
    605 				struct nl_msg **result)
    606 {
    607 	return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_GET, flags, result);
    608 }
    609 
    610 int nfnl_ct_query(struct nl_sock *sk, const struct nfnl_ct *ct, int flags)
    611 {
    612 	struct nl_msg *msg;
    613 	int err;
    614 
    615 	if ((err = nfnl_ct_build_query_request(ct, flags, &msg)) < 0)
    616 		return err;
    617 
    618 	err = nl_send_auto_complete(sk, msg);
    619 	nlmsg_free(msg);
    620 	if (err < 0)
    621 		return err;
    622 
    623 	return wait_for_ack(sk);
    624 }
    625 
    626 /**
    627  * @name Cache Management
    628  * @{
    629  */
    630 
    631 /**
    632  * Build a conntrack cache holding all conntrack currently in the kernel
    633  * @arg sk		Netlink socket.
    634  * @arg result		Pointer to store resulting cache.
    635  *
    636  * Allocates a new cache, initializes it properly and updates it to
    637  * contain all conntracks currently in the kernel.
    638  *
    639  * @return 0 on success or a negative error code.
    640  */
    641 int nfnl_ct_alloc_cache(struct nl_sock *sk, struct nl_cache **result)
    642 {
    643 	return nl_cache_alloc_and_fill(&nfnl_ct_ops, sk, result);
    644 }
    645 
    646 /** @} */
    647 
    648 /**
    649  * @name Conntrack Addition
    650  * @{
    651  */
    652 
    653 /** @} */
    654 
    655 static struct nl_af_group ct_groups[] = {
    656 	{ AF_UNSPEC, NFNLGRP_CONNTRACK_NEW },
    657 	{ AF_UNSPEC, NFNLGRP_CONNTRACK_UPDATE },
    658 	{ AF_UNSPEC, NFNLGRP_CONNTRACK_DESTROY },
    659 	{ END_OF_GROUP_LIST },
    660 };
    661 
    662 #define NFNLMSG_CT_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_CTNETLINK, (type))
    663 static struct nl_cache_ops nfnl_ct_ops = {
    664 	.co_name		= "netfilter/ct",
    665 	.co_hdrsize		= NFNL_HDRLEN,
    666 	.co_msgtypes		= {
    667 		{ NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_NEW), NL_ACT_NEW, "new" },
    668 		{ NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_GET), NL_ACT_GET, "get" },
    669 		{ NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_DELETE), NL_ACT_DEL, "del" },
    670 		END_OF_MSGTYPES_LIST,
    671 	},
    672 	.co_protocol		= NETLINK_NETFILTER,
    673 	.co_groups		= ct_groups,
    674 	.co_request_update	= ct_request_update,
    675 	.co_msg_parser		= ct_msg_parser,
    676 	.co_obj_ops		= &ct_obj_ops,
    677 };
    678 
    679 static void __init ct_init(void)
    680 {
    681 	nl_cache_mngt_register(&nfnl_ct_ops);
    682 }
    683 
    684 static void __exit ct_exit(void)
    685 {
    686 	nl_cache_mngt_unregister(&nfnl_ct_ops);
    687 }
    688 
    689 /** @} */
    690