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
__build_tuple_ip(struct nfnlhdr * req,size_t size,const struct __nfct_tuple * t)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
__build_tuple_proto(struct nfnlhdr * req,size_t size,const struct __nfct_tuple * t)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
__build_tuple_raw(struct nfnlhdr * req,size_t size,const struct __nfct_tuple * t)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
__build_tuple(struct nfnlhdr * req,size_t size,const struct __nfct_tuple * t,const int type)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
__build_protoinfo(struct nfnlhdr * req,size_t size,const struct nf_conntrack * ct)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
__nat_seq_adj(struct nfnlhdr * req,size_t size,const struct nf_conntrack * ct,int dir)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
__build_nat_seq_adj(struct nfnlhdr * req,size_t size,const struct nf_conntrack * ct,int dir)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
__build_protonat(struct nfnlhdr * req,size_t size,const struct nf_conntrack * ct,const struct __nfct_nat * nat)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
__build_nat(struct nfnlhdr * req,size_t size,const struct __nfct_nat * nat,uint8_t l3protonum)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
__build_snat(struct nfnlhdr * req,size_t size,const struct nf_conntrack * ct,uint8_t l3protonum)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
__build_snat_ipv4(struct nfnlhdr * req,size_t size,const struct nf_conntrack * ct)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
__build_snat_ipv6(struct nfnlhdr * req,size_t size,const struct nf_conntrack * ct)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
__build_snat_port(struct nfnlhdr * req,size_t size,const struct nf_conntrack * ct)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
__build_dnat(struct nfnlhdr * req,size_t size,const struct nf_conntrack * ct,uint8_t l3protonum)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
__build_dnat_ipv4(struct nfnlhdr * req,size_t size,const struct nf_conntrack * ct)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
__build_dnat_ipv6(struct nfnlhdr * req,size_t size,const struct nf_conntrack * ct)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
__build_dnat_port(struct nfnlhdr * req,size_t size,const struct nf_conntrack * ct)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
__build_status(struct nfnlhdr * req,size_t size,const struct nf_conntrack * ct)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
__build_timeout(struct nfnlhdr * req,size_t size,const struct nf_conntrack * ct)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
__build_mark(struct nfnlhdr * req,size_t size,const struct nf_conntrack * ct)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
__build_secmark(struct nfnlhdr * req,size_t size,const struct nf_conntrack * ct)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
__build_helper_name(struct nfnlhdr * req,size_t size,const struct nf_conntrack * ct)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
__build_zone(struct nfnlhdr * req,size_t size,const struct nf_conntrack * ct)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
__build_labels(struct nfnlhdr * req,size_t size,const struct nf_conntrack * ct)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
__build_conntrack(struct nfnl_subsys_handle * ssh,struct nfnlhdr * req,size_t size,uint16_t type,uint16_t flags,const struct nf_conntrack * ct)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 }
599