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