Home | History | Annotate | Download | only in conntrack
      1 /*
      2  * (C) 2005-2012 by Pablo Neira Ayuso <pablo (at) netfilter.org>
      3  *
      4  * This program is free software; you can redistribute it and/or modify it
      5  * under the terms of the GNU General Public License as published by
      6  * the Free Software Foundation; either version 2 of the License, or
      7  * (at your option) any later version.
      8  *
      9  * This code has been sponsored by Vyatta Inc. <http://www.vyatta.com>
     10  */
     11 
     12 #include "internal/internal.h"
     13 #include <limits.h>
     14 #include <libmnl/libmnl.h>
     15 
     16 static int
     17 nfct_build_tuple_ip(struct nlmsghdr *nlh, const struct __nfct_tuple *t)
     18 {
     19 	struct nlattr *nest;
     20 
     21 	nest = mnl_attr_nest_start(nlh, CTA_TUPLE_IP);
     22 	if (nest == NULL)
     23 		return -1;
     24 
     25 	switch(t->l3protonum) {
     26 	case AF_INET:
     27 		mnl_attr_put_u32(nlh, CTA_IP_V4_SRC, t->src.v4);
     28 		mnl_attr_put_u32(nlh, CTA_IP_V4_DST, t->dst.v4);
     29 		break;
     30 	case AF_INET6:
     31 		mnl_attr_put(nlh, CTA_IP_V6_SRC, sizeof(struct in6_addr),
     32 				&t->src.v6);
     33 		mnl_attr_put(nlh, CTA_IP_V6_DST, sizeof(struct in6_addr),
     34 				&t->dst.v6);
     35 		break;
     36 	default:
     37 		mnl_attr_nest_cancel(nlh, nest);
     38 		return -1;
     39 	}
     40 	mnl_attr_nest_end(nlh, nest);
     41 	return 0;
     42 }
     43 
     44 static int
     45 nfct_build_tuple_proto(struct nlmsghdr *nlh, const struct __nfct_tuple *t)
     46 {
     47 	struct nlattr *nest;
     48 
     49 	nest = mnl_attr_nest_start(nlh, CTA_TUPLE_PROTO);
     50 	if (nest == NULL)
     51 		return -1;
     52 
     53 	mnl_attr_put_u8(nlh, CTA_PROTO_NUM, t->protonum);
     54 
     55 	switch(t->protonum) {
     56 	case IPPROTO_UDP:
     57 	case IPPROTO_TCP:
     58 	case IPPROTO_SCTP:
     59 	case IPPROTO_DCCP:
     60 	case IPPROTO_GRE:
     61 	case IPPROTO_UDPLITE:
     62 		mnl_attr_put_u16(nlh, CTA_PROTO_SRC_PORT, t->l4src.tcp.port);
     63 		mnl_attr_put_u16(nlh, CTA_PROTO_DST_PORT, t->l4dst.tcp.port);
     64 		break;
     65 	case IPPROTO_ICMP:
     66 		mnl_attr_put_u8(nlh, CTA_PROTO_ICMP_CODE, t->l4dst.icmp.code);
     67 		mnl_attr_put_u8(nlh, CTA_PROTO_ICMP_TYPE, t->l4dst.icmp.type);
     68 		mnl_attr_put_u16(nlh, CTA_PROTO_ICMP_ID, t->l4src.icmp.id);
     69 		break;
     70 	case IPPROTO_ICMPV6:
     71 		mnl_attr_put_u8(nlh, CTA_PROTO_ICMPV6_CODE, t->l4dst.icmp.code);
     72 		mnl_attr_put_u8(nlh, CTA_PROTO_ICMPV6_TYPE, t->l4dst.icmp.type);
     73 		mnl_attr_put_u16(nlh, CTA_PROTO_ICMPV6_ID, t->l4src.icmp.id);
     74 		break;
     75 	default:
     76 		mnl_attr_nest_cancel(nlh, nest);
     77 		return -1;
     78 	}
     79 	mnl_attr_nest_end(nlh, nest);
     80 	return 0;
     81 }
     82 
     83 int
     84 nfct_build_tuple_raw(struct nlmsghdr *nlh, const struct __nfct_tuple *t)
     85 {
     86 	if (nfct_build_tuple_ip(nlh, t) < 0)
     87 		return -1;
     88 	if (nfct_build_tuple_proto(nlh, t) < 0)
     89 		return -1;
     90 
     91 	return 0;
     92 }
     93 
     94 int
     95 nfct_build_tuple(struct nlmsghdr *nlh, const struct __nfct_tuple *t, int type)
     96 {
     97 	struct nlattr *nest;
     98 
     99 	nest = mnl_attr_nest_start(nlh, type);
    100 	if (nest == NULL)
    101 		return -1;
    102 
    103 	if (nfct_build_tuple_raw(nlh, t) < 0)
    104 		goto err;
    105 
    106 	mnl_attr_nest_end(nlh, nest);
    107 	return 0;
    108 err:
    109 	mnl_attr_nest_cancel(nlh, nest);
    110 	return -1;
    111 }
    112 
    113 static int
    114 nfct_build_protoinfo(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
    115 {
    116 	struct nlattr *nest, *nest_proto;
    117 
    118 	switch(ct->head.orig.protonum) {
    119 	case IPPROTO_TCP:
    120 		/* Preliminary attribute check to avoid sending an empty
    121 		 * CTA_PROTOINFO_TCP nest, which results in EINVAL in
    122 		 * Linux kernel <= 2.6.25. */
    123 		if (!(test_bit(ATTR_TCP_STATE, ct->head.set) ||
    124 		      test_bit(ATTR_TCP_FLAGS_ORIG, ct->head.set) ||
    125 		      test_bit(ATTR_TCP_FLAGS_REPL, ct->head.set) ||
    126 		      test_bit(ATTR_TCP_MASK_ORIG, ct->head.set) ||
    127 		      test_bit(ATTR_TCP_MASK_REPL, ct->head.set) ||
    128 		      test_bit(ATTR_TCP_WSCALE_ORIG, ct->head.set) ||
    129 		      test_bit(ATTR_TCP_WSCALE_REPL, ct->head.set))) {
    130 			break;
    131 		}
    132 		nest = mnl_attr_nest_start(nlh, CTA_PROTOINFO);
    133 		nest_proto = mnl_attr_nest_start(nlh, CTA_PROTOINFO_TCP);
    134 		if (test_bit(ATTR_TCP_STATE, ct->head.set)) {
    135 			mnl_attr_put_u8(nlh, CTA_PROTOINFO_TCP_STATE,
    136 					ct->protoinfo.tcp.state);
    137 		}
    138 		if (test_bit(ATTR_TCP_FLAGS_ORIG, ct->head.set) &&
    139 		    test_bit(ATTR_TCP_MASK_ORIG, ct->head.set)) {
    140 			mnl_attr_put(nlh, CTA_PROTOINFO_TCP_FLAGS_ORIGINAL,
    141 				     sizeof(struct nf_ct_tcp_flags),
    142 				     &ct->protoinfo.tcp.flags[0]);
    143 		}
    144 		if (test_bit(ATTR_TCP_FLAGS_REPL, ct->head.set) &&
    145 		    test_bit(ATTR_TCP_MASK_REPL, ct->head.set)) {
    146 			mnl_attr_put(nlh, CTA_PROTOINFO_TCP_FLAGS_REPLY,
    147 				     sizeof(struct nf_ct_tcp_flags),
    148 				     &ct->protoinfo.tcp.flags[1]);
    149 		}
    150 		if (test_bit(ATTR_TCP_WSCALE_ORIG, ct->head.set)) {
    151 			mnl_attr_put_u8(nlh, CTA_PROTOINFO_TCP_WSCALE_ORIGINAL,
    152 					ct->protoinfo.tcp.wscale[__DIR_ORIG]);
    153 		}
    154 		if (test_bit(ATTR_TCP_WSCALE_REPL, ct->head.set)) {
    155 			mnl_attr_put_u8(nlh, CTA_PROTOINFO_TCP_WSCALE_REPLY,
    156 					ct->protoinfo.tcp.wscale[__DIR_REPL]);
    157 		}
    158 		mnl_attr_nest_end(nlh, nest_proto);
    159 		mnl_attr_nest_end(nlh, nest);
    160 		break;
    161 	case IPPROTO_SCTP:
    162 		/* See comment above on TCP. */
    163 		if (!(test_bit(ATTR_SCTP_STATE, ct->head.set) ||
    164 		      test_bit(ATTR_SCTP_VTAG_ORIG, ct->head.set) ||
    165 		      test_bit(ATTR_SCTP_VTAG_REPL, ct->head.set))) {
    166 			break;
    167 		}
    168 		nest = mnl_attr_nest_start(nlh, CTA_PROTOINFO);
    169 		nest_proto = mnl_attr_nest_start(nlh, CTA_PROTOINFO_SCTP);
    170 
    171 		if (test_bit(ATTR_SCTP_STATE, ct->head.set)) {
    172 			mnl_attr_put_u8(nlh, CTA_PROTOINFO_SCTP_STATE,
    173 					ct->protoinfo.sctp.state);
    174 		}
    175 		if (test_bit(ATTR_SCTP_VTAG_ORIG, ct->head.set)) {
    176 			mnl_attr_put_u32(nlh, CTA_PROTOINFO_SCTP_VTAG_ORIGINAL,
    177 				htonl(ct->protoinfo.sctp.vtag[__DIR_ORIG]));
    178 		}
    179 		if (test_bit(ATTR_SCTP_VTAG_REPL, ct->head.set)) {
    180 			mnl_attr_put_u32(nlh, CTA_PROTOINFO_SCTP_VTAG_REPLY,
    181 				htonl(ct->protoinfo.sctp.vtag[__DIR_REPL]));
    182 		}
    183 		mnl_attr_nest_end(nlh, nest_proto);
    184 		mnl_attr_nest_end(nlh, nest);
    185 		break;
    186 	case IPPROTO_DCCP:
    187 		/* See comment above on TCP. */
    188 		if (!(test_bit(ATTR_DCCP_STATE, ct->head.set) ||
    189 		      test_bit(ATTR_DCCP_ROLE, ct->head.set) ||
    190 		      test_bit(ATTR_DCCP_HANDSHAKE_SEQ, ct->head.set))) {
    191 			break;
    192 		}
    193 		nest = mnl_attr_nest_start(nlh, CTA_PROTOINFO);
    194 		nest_proto = mnl_attr_nest_start(nlh, CTA_PROTOINFO_DCCP);
    195 		if (test_bit(ATTR_DCCP_STATE, ct->head.set)) {
    196 			mnl_attr_put_u8(nlh, CTA_PROTOINFO_DCCP_STATE,
    197 					ct->protoinfo.dccp.state);
    198 		}
    199 		if (test_bit(ATTR_DCCP_ROLE, ct->head.set)) {
    200 			mnl_attr_put_u8(nlh, CTA_PROTOINFO_DCCP_ROLE,
    201 					ct->protoinfo.dccp.role);
    202 		}
    203 		if (test_bit(ATTR_DCCP_HANDSHAKE_SEQ, ct->head.set)) {
    204 			uint64_t handshake_seq =
    205 				be64toh(ct->protoinfo.dccp.handshake_seq);
    206 
    207 			mnl_attr_put_u64(nlh, CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ,
    208 					 handshake_seq);
    209 		}
    210 		mnl_attr_nest_end(nlh, nest_proto);
    211 		mnl_attr_nest_end(nlh, nest);
    212 	default:
    213 		break;
    214 	}
    215 	return 0;
    216 }
    217 
    218 static int
    219 nfct_nat_seq_adj(struct nlmsghdr *nlh, const struct nf_conntrack *ct, int dir)
    220 {
    221 	mnl_attr_put_u32(nlh, CTA_NAT_SEQ_CORRECTION_POS,
    222 			 htonl(ct->natseq[dir].correction_pos));
    223 	mnl_attr_put_u32(nlh, CTA_NAT_SEQ_OFFSET_BEFORE,
    224 			 htonl(ct->natseq[dir].offset_before));
    225 	mnl_attr_put_u32(nlh, CTA_NAT_SEQ_OFFSET_AFTER,
    226 			 htonl(ct->natseq[dir].offset_after));
    227 	return 0;
    228 }
    229 
    230 static int
    231 nfct_build_nat_seq_adj(struct nlmsghdr *nlh, const struct nf_conntrack *ct,
    232 		      int dir)
    233 {
    234 	int type = (dir == __DIR_ORIG) ? CTA_NAT_SEQ_ADJ_ORIG :
    235 					 CTA_NAT_SEQ_ADJ_REPLY;
    236 	struct nlattr *nest;
    237 
    238 	nest = mnl_attr_nest_start(nlh, type);
    239 	nfct_nat_seq_adj(nlh, ct, dir);
    240 	mnl_attr_nest_end(nlh, nest);
    241 
    242 	return 0;
    243 }
    244 
    245 static int
    246 nfct_build_protonat(struct nlmsghdr *nlh, const struct nf_conntrack *ct,
    247 		   const struct __nfct_nat *nat)
    248 {
    249 	struct nlattr *nest;
    250 
    251 	nest = mnl_attr_nest_start(nlh, CTA_NAT_PROTO);
    252 
    253 	switch (ct->head.orig.protonum) {
    254 	case IPPROTO_TCP:
    255 	case IPPROTO_UDP:
    256 		mnl_attr_put_u16(nlh, CTA_PROTONAT_PORT_MIN,
    257 				 nat->l4min.tcp.port);
    258 		mnl_attr_put_u16(nlh, CTA_PROTONAT_PORT_MAX,
    259 				 nat->l4max.tcp.port);
    260 	break;
    261 	}
    262 	mnl_attr_nest_end(nlh, nest);
    263 	return 0;
    264 }
    265 
    266 static int
    267 nfct_build_nat(struct nlmsghdr *nlh, const struct __nfct_nat *nat,
    268 	       uint8_t l3protonum)
    269 {
    270 	switch (l3protonum) {
    271 	case AF_INET:
    272 		mnl_attr_put_u32(nlh, CTA_NAT_MINIP, nat->min_ip.v4);
    273 		break;
    274 	case AF_INET6:
    275 		mnl_attr_put(nlh, CTA_NAT_V6_MINIP, sizeof(struct in6_addr),
    276 			     &nat->min_ip.v6);
    277 		break;
    278 	default:
    279 		break;
    280 	}
    281 	return 0;
    282 }
    283 
    284 static int
    285 nfct_build_snat(struct nlmsghdr *nlh, const struct nf_conntrack *ct,
    286 		uint8_t l3protonum)
    287 {
    288 	struct nlattr *nest;
    289 
    290 	nest = mnl_attr_nest_start(nlh, CTA_NAT_SRC);
    291 	nfct_build_nat(nlh, &ct->snat, l3protonum);
    292 	nfct_build_protonat(nlh, ct, &ct->snat);
    293 	mnl_attr_nest_end(nlh, nest);
    294 	return 0;
    295 }
    296 
    297 static int
    298 nfct_build_snat_ipv4(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
    299 {
    300 	struct nlattr *nest;
    301 
    302 	nest = mnl_attr_nest_start(nlh, CTA_NAT_SRC);
    303 	nfct_build_nat(nlh, &ct->snat, AF_INET);
    304 	mnl_attr_nest_end(nlh, nest);
    305 	return 0;
    306 }
    307 
    308 static int
    309 nfct_build_snat_ipv6(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
    310 {
    311 	struct nlattr *nest;
    312 
    313 	nest = mnl_attr_nest_start(nlh, CTA_NAT_SRC);
    314 	nfct_build_nat(nlh, &ct->snat, AF_INET6);
    315 	mnl_attr_nest_end(nlh, nest);
    316 	return 0;
    317 }
    318 
    319 static int
    320 nfct_build_snat_port(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
    321 {
    322 	struct nlattr *nest;
    323 
    324 	nest = mnl_attr_nest_start(nlh, CTA_NAT_SRC);
    325 	nfct_build_protonat(nlh, ct, &ct->snat);
    326 	mnl_attr_nest_end(nlh, nest);
    327 	return 0;
    328 }
    329 
    330 static int
    331 nfct_build_dnat(struct nlmsghdr *nlh, const struct nf_conntrack *ct,
    332 		uint8_t l3protonum)
    333 {
    334 	struct nlattr *nest;
    335 
    336 	nest = mnl_attr_nest_start(nlh, CTA_NAT_DST);
    337 	nfct_build_nat(nlh, &ct->dnat, l3protonum);
    338 	nfct_build_protonat(nlh, ct, &ct->dnat);
    339 	mnl_attr_nest_end(nlh, nest);
    340 	return 0;
    341 }
    342 
    343 static int
    344 nfct_build_dnat_ipv4(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
    345 {
    346 	struct nlattr *nest;
    347 
    348 	nest = mnl_attr_nest_start(nlh, CTA_NAT_DST);
    349 	nfct_build_nat(nlh, &ct->dnat, AF_INET);
    350 	mnl_attr_nest_end(nlh, nest);
    351 	return 0;
    352 }
    353 
    354 static int
    355 nfct_build_dnat_ipv6(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
    356 {
    357 	struct nlattr *nest;
    358 
    359 	nest = mnl_attr_nest_start(nlh, CTA_NAT_DST);
    360 	nfct_build_nat(nlh, &ct->dnat, AF_INET6);
    361 	mnl_attr_nest_end(nlh, nest);
    362 	return 0;
    363 }
    364 
    365 static int
    366 nfct_build_dnat_port(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
    367 {
    368 	struct nlattr *nest;
    369 
    370 	nest = mnl_attr_nest_start(nlh, CTA_NAT_DST);
    371 	nfct_build_protonat(nlh, ct, &ct->dnat);
    372 	mnl_attr_nest_end(nlh, nest);
    373 	return 0;
    374 }
    375 
    376 static int
    377 nfct_build_status(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
    378 {
    379 	mnl_attr_put_u32(nlh, CTA_STATUS, htonl(ct->status | IPS_CONFIRMED));
    380 	return 0;
    381 }
    382 
    383 static int
    384 nfct_build_timeout(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
    385 {
    386 	mnl_attr_put_u32(nlh, CTA_TIMEOUT, htonl(ct->timeout));
    387 	return 0;
    388 }
    389 
    390 static int
    391 nfct_build_mark(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
    392 {
    393 	mnl_attr_put_u32(nlh, CTA_MARK, htonl(ct->mark));
    394 	return 0;
    395 }
    396 
    397 static int
    398 nfct_build_secmark(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
    399 {
    400 	mnl_attr_put_u32(nlh, CTA_SECMARK, htonl(ct->secmark));
    401 	return 0;
    402 }
    403 
    404 static int
    405 nfct_build_helper_name(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
    406 {
    407 	struct nlattr *nest;
    408 
    409 	nest = mnl_attr_nest_start(nlh, CTA_HELP);
    410 	mnl_attr_put_strz(nlh, CTA_HELP_NAME, ct->helper_name);
    411 
    412 	if (ct->helper_info != NULL) {
    413 		mnl_attr_put(nlh, CTA_HELP_INFO, ct->helper_info_len,
    414 				ct->helper_info);
    415 	}
    416 	mnl_attr_nest_end(nlh, nest);
    417 	return 0;
    418 }
    419 
    420 static int
    421 nfct_build_zone(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
    422 {
    423 	mnl_attr_put_u16(nlh, CTA_ZONE, htons(ct->zone));
    424 	return 0;
    425 }
    426 
    427 static void
    428 nfct_build_labels(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
    429 {
    430 	struct nfct_bitmask *b = ct->connlabels;
    431 	unsigned int size = b->words * sizeof(b->bits[0]);
    432 	mnl_attr_put(nlh, CTA_LABELS, size, b->bits);
    433 
    434 	if (test_bit(ATTR_CONNLABELS_MASK, ct->head.set)) {
    435 		b = ct->connlabels_mask;
    436 		if (size == (b->words * sizeof(b->bits[0])))
    437 			mnl_attr_put(nlh, CTA_LABELS_MASK, size, b->bits);
    438 	}
    439 }
    440 
    441 int
    442 nfct_nlmsg_build(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
    443 {
    444 	if (!test_bit(ATTR_ORIG_L3PROTO, ct->head.set)) {
    445 		errno = EINVAL;
    446 		return -1;
    447 	}
    448 
    449 	if (test_bit(ATTR_ORIG_IPV4_SRC, ct->head.set) ||
    450 	    test_bit(ATTR_ORIG_IPV4_DST, ct->head.set) ||
    451 	    test_bit(ATTR_ORIG_IPV6_SRC, ct->head.set) ||
    452 	    test_bit(ATTR_ORIG_IPV6_DST, ct->head.set) ||
    453 	    test_bit(ATTR_ORIG_PORT_SRC, ct->head.set) ||
    454 	    test_bit(ATTR_ORIG_PORT_DST, ct->head.set) ||
    455 	    test_bit(ATTR_ORIG_L3PROTO, ct->head.set) ||
    456 	    test_bit(ATTR_ORIG_L4PROTO, ct->head.set) ||
    457 	    test_bit(ATTR_ORIG_ZONE, ct->head.set) ||
    458 	    test_bit(ATTR_ICMP_TYPE, ct->head.set) ||
    459 	    test_bit(ATTR_ICMP_CODE, ct->head.set) ||
    460 	    test_bit(ATTR_ICMP_ID, ct->head.set)) {
    461 		const struct __nfct_tuple *t = &ct->head.orig;
    462 		struct nlattr *nest;
    463 
    464 		nest = mnl_attr_nest_start(nlh, CTA_TUPLE_ORIG);
    465 		if (nest == NULL)
    466 			return -1;
    467 
    468 		if (nfct_build_tuple_raw(nlh, t) < 0) {
    469 			mnl_attr_nest_cancel(nlh, nest);
    470 			return -1;
    471 		}
    472 
    473 		if (test_bit(ATTR_ORIG_ZONE, ct->head.set))
    474 			mnl_attr_put_u16(nlh, CTA_TUPLE_ZONE, htons(t->zone));
    475 
    476 		mnl_attr_nest_end(nlh, nest);
    477 	}
    478 
    479 	if (test_bit(ATTR_REPL_IPV4_SRC, ct->head.set) ||
    480 	    test_bit(ATTR_REPL_IPV4_DST, ct->head.set) ||
    481 	    test_bit(ATTR_REPL_IPV6_SRC, ct->head.set) ||
    482 	    test_bit(ATTR_REPL_IPV6_DST, ct->head.set) ||
    483 	    test_bit(ATTR_REPL_PORT_SRC, ct->head.set) ||
    484 	    test_bit(ATTR_REPL_PORT_DST, ct->head.set) ||
    485 	    test_bit(ATTR_REPL_L3PROTO, ct->head.set) ||
    486 	    test_bit(ATTR_REPL_L4PROTO, ct->head.set) ||
    487 	    test_bit(ATTR_REPL_ZONE, ct->head.set) ||
    488 	    test_bit(ATTR_ICMP_TYPE, ct->head.set) ||
    489 	    test_bit(ATTR_ICMP_CODE, ct->head.set) ||
    490 	    test_bit(ATTR_ICMP_ID, ct->head.set)) {
    491 		const struct __nfct_tuple *t = &ct->repl;
    492 		struct nlattr *nest;
    493 
    494 		nest = mnl_attr_nest_start(nlh, CTA_TUPLE_REPLY);
    495 		if (nest == NULL)
    496 			return -1;
    497 
    498 		if (nfct_build_tuple_raw(nlh, t) < 0) {
    499 			mnl_attr_nest_cancel(nlh, nest);
    500 			return -1;
    501 		}
    502 
    503 		if (test_bit(ATTR_REPL_ZONE, ct->head.set))
    504 			mnl_attr_put_u16(nlh, CTA_TUPLE_ZONE, htons(t->zone));
    505 
    506 		mnl_attr_nest_end(nlh, nest);
    507 	}
    508 
    509 	if (test_bit(ATTR_MASTER_IPV4_SRC, ct->head.set) ||
    510 	    test_bit(ATTR_MASTER_IPV4_DST, ct->head.set) ||
    511 	    test_bit(ATTR_MASTER_IPV6_SRC, ct->head.set) ||
    512 	    test_bit(ATTR_MASTER_IPV6_DST, ct->head.set) ||
    513 	    test_bit(ATTR_MASTER_PORT_SRC, ct->head.set) ||
    514 	    test_bit(ATTR_MASTER_PORT_DST, ct->head.set) ||
    515 	    test_bit(ATTR_MASTER_L3PROTO, ct->head.set) ||
    516 	    test_bit(ATTR_MASTER_L4PROTO, ct->head.set)) {
    517 		nfct_build_tuple(nlh, &ct->master, CTA_TUPLE_MASTER);
    518 	}
    519 
    520 	if (test_bit(ATTR_STATUS, ct->head.set))
    521 		nfct_build_status(nlh, ct);
    522 
    523 	if (test_bit(ATTR_TIMEOUT, ct->head.set))
    524 		nfct_build_timeout(nlh, ct);
    525 
    526 	if (test_bit(ATTR_MARK, ct->head.set))
    527 		nfct_build_mark(nlh, ct);
    528 
    529 	if (test_bit(ATTR_SECMARK, ct->head.set))
    530 		nfct_build_secmark(nlh, ct);
    531 
    532 	nfct_build_protoinfo(nlh, ct);
    533 
    534 	if (test_bit(ATTR_SNAT_IPV4, ct->head.set) &&
    535 	    test_bit(ATTR_SNAT_PORT, ct->head.set)) {
    536 		nfct_build_snat(nlh, ct, AF_INET);
    537 	} else if (test_bit(ATTR_SNAT_IPV6, ct->head.set) &&
    538 		   test_bit(ATTR_SNAT_PORT, ct->head.set)) {
    539 		nfct_build_snat(nlh, ct, AF_INET6);
    540 	} else if (test_bit(ATTR_SNAT_IPV4, ct->head.set)) {
    541 		nfct_build_snat_ipv4(nlh, ct);
    542 	} else if (test_bit(ATTR_SNAT_IPV6, ct->head.set)) {
    543 		nfct_build_snat_ipv6(nlh, ct);
    544 	} else if (test_bit(ATTR_SNAT_PORT, ct->head.set)) {
    545 		nfct_build_snat_port(nlh, ct);
    546 	}
    547 
    548 	if (test_bit(ATTR_DNAT_IPV4, ct->head.set) &&
    549 	    test_bit(ATTR_DNAT_PORT, ct->head.set)) {
    550 		nfct_build_dnat(nlh, ct, AF_INET);
    551 	} else if (test_bit(ATTR_DNAT_IPV6, ct->head.set) &&
    552 		   test_bit(ATTR_DNAT_PORT, ct->head.set)) {
    553 		nfct_build_dnat(nlh, ct, AF_INET6);
    554 	} else if (test_bit(ATTR_DNAT_IPV4, ct->head.set)) {
    555 		nfct_build_dnat_ipv4(nlh, ct);
    556 	} else if (test_bit(ATTR_DNAT_IPV6, ct->head.set)) {
    557 		nfct_build_dnat_ipv6(nlh, ct);
    558 	} else if (test_bit(ATTR_DNAT_PORT, ct->head.set)) {
    559 		nfct_build_dnat_port(nlh, ct);
    560 	}
    561 
    562 	if (test_bit(ATTR_ORIG_NAT_SEQ_CORRECTION_POS, ct->head.set) &&
    563 	    test_bit(ATTR_ORIG_NAT_SEQ_OFFSET_BEFORE, ct->head.set) &&
    564 	    test_bit(ATTR_ORIG_NAT_SEQ_OFFSET_AFTER, ct->head.set)) {
    565 		nfct_build_nat_seq_adj(nlh, ct, __DIR_ORIG);
    566 	}
    567 	if (test_bit(ATTR_REPL_NAT_SEQ_CORRECTION_POS, ct->head.set) &&
    568 	    test_bit(ATTR_REPL_NAT_SEQ_OFFSET_BEFORE, ct->head.set) &&
    569 	    test_bit(ATTR_REPL_NAT_SEQ_OFFSET_AFTER, ct->head.set)) {
    570 		nfct_build_nat_seq_adj(nlh, ct, __DIR_REPL);
    571 	}
    572 
    573 	if (test_bit(ATTR_HELPER_NAME, ct->head.set))
    574 		nfct_build_helper_name(nlh, ct);
    575 
    576 	if (test_bit(ATTR_ZONE, ct->head.set))
    577 		nfct_build_zone(nlh, ct);
    578 
    579 	if (test_bit(ATTR_CONNLABELS, ct->head.set))
    580 		nfct_build_labels(nlh, ct);
    581 
    582 	return 0;
    583 }
    584