1/*
2 * (C) 2005-2012 by Pablo Neira Ayuso <pablo@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
16static int
17nfct_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
44static int
45nfct_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
83int
84nfct_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
94int
95nfct_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;
108err:
109	mnl_attr_nest_cancel(nlh, nest);
110	return -1;
111}
112
113static int
114nfct_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
218static int
219nfct_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
230static int
231nfct_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
245static int
246nfct_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
266static int
267nfct_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
284static int
285nfct_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
297static int
298nfct_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
308static int
309nfct_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
319static int
320nfct_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
330static int
331nfct_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
343static int
344nfct_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
354static int
355nfct_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
365static int
366nfct_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
376static int
377nfct_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
383static int
384nfct_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
390static int
391nfct_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
397static int
398nfct_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
404static int
405nfct_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
420static int
421nfct_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
427static void
428nfct_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
441int
442nfct_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