12 #include "internal/internal.h"
14 #include <libmnl/libmnl.h>
17 nfct_build_tuple_ip(
struct nlmsghdr *nlh,
const struct __nfct_tuple *t)
21 nest = mnl_attr_nest_start(nlh, CTA_TUPLE_IP);
25 switch(t->l3protonum) {
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);
31 mnl_attr_put(nlh, CTA_IP_V6_SRC,
sizeof(
struct in6_addr),
33 mnl_attr_put(nlh, CTA_IP_V6_DST,
sizeof(
struct in6_addr),
37 mnl_attr_nest_cancel(nlh, nest);
40 mnl_attr_nest_end(nlh, nest);
45 nfct_build_tuple_proto(
struct nlmsghdr *nlh,
const struct __nfct_tuple *t)
49 nest = mnl_attr_nest_start(nlh, CTA_TUPLE_PROTO);
53 mnl_attr_put_u8(nlh, CTA_PROTO_NUM, t->protonum);
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);
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);
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);
76 mnl_attr_nest_cancel(nlh, nest);
79 mnl_attr_nest_end(nlh, nest);
84 nfct_build_tuple_raw(
struct nlmsghdr *nlh,
const struct __nfct_tuple *t)
86 if (nfct_build_tuple_ip(nlh, t) < 0)
88 if (nfct_build_tuple_proto(nlh, t) < 0)
95 nfct_build_tuple(
struct nlmsghdr *nlh,
const struct __nfct_tuple *t,
int type)
99 nest = mnl_attr_nest_start(nlh, type);
103 if (nfct_build_tuple_raw(nlh, t) < 0)
106 mnl_attr_nest_end(nlh, nest);
109 mnl_attr_nest_cancel(nlh, nest);
114 nfct_build_protoinfo(
struct nlmsghdr *nlh,
const struct nf_conntrack *ct)
116 struct nlattr *nest, *nest_proto;
118 switch(ct->head.orig.protonum) {
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))) {
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);
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]);
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]);
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]);
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]);
158 mnl_attr_nest_end(nlh, nest_proto);
159 mnl_attr_nest_end(nlh, nest);
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))) {
168 nest = mnl_attr_nest_start(nlh, CTA_PROTOINFO);
169 nest_proto = mnl_attr_nest_start(nlh, CTA_PROTOINFO_SCTP);
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);
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]));
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]));
183 mnl_attr_nest_end(nlh, nest_proto);
184 mnl_attr_nest_end(nlh, nest);
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))) {
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);
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);
203 if (test_bit(ATTR_DCCP_HANDSHAKE_SEQ, ct->head.set)) {
204 uint64_t handshake_seq =
205 be64toh(ct->protoinfo.dccp.handshake_seq);
207 mnl_attr_put_u64(nlh, CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ,
210 mnl_attr_nest_end(nlh, nest_proto);
211 mnl_attr_nest_end(nlh, nest);
219 nfct_nat_seq_adj(
struct nlmsghdr *nlh,
const struct nf_conntrack *ct,
int dir)
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));
231 nfct_build_nat_seq_adj(
struct nlmsghdr *nlh,
const struct nf_conntrack *ct,
234 int type = (dir == __DIR_ORIG) ? CTA_NAT_SEQ_ADJ_ORIG :
235 CTA_NAT_SEQ_ADJ_REPLY;
238 nest = mnl_attr_nest_start(nlh, type);
239 nfct_nat_seq_adj(nlh, ct, dir);
240 mnl_attr_nest_end(nlh, nest);
246 nfct_build_protonat(
struct nlmsghdr *nlh,
const struct nf_conntrack *ct,
247 const struct __nfct_nat *nat)
251 nest = mnl_attr_nest_start(nlh, CTA_NAT_PROTO);
253 switch (ct->head.orig.protonum) {
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);
262 mnl_attr_nest_end(nlh, nest);
267 nfct_build_nat(
struct nlmsghdr *nlh,
const struct __nfct_nat *nat,
270 switch (l3protonum) {
272 mnl_attr_put_u32(nlh, CTA_NAT_MINIP, nat->min_ip.v4);
275 mnl_attr_put(nlh, CTA_NAT_V6_MINIP,
sizeof(
struct in6_addr),
285 nfct_build_snat(
struct nlmsghdr *nlh,
const struct nf_conntrack *ct,
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);
298 nfct_build_snat_ipv4(
struct nlmsghdr *nlh,
const struct nf_conntrack *ct)
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);
309 nfct_build_snat_ipv6(
struct nlmsghdr *nlh,
const struct nf_conntrack *ct)
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);
320 nfct_build_snat_port(
struct nlmsghdr *nlh,
const struct nf_conntrack *ct)
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);
331 nfct_build_dnat(
struct nlmsghdr *nlh,
const struct nf_conntrack *ct,
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);
344 nfct_build_dnat_ipv4(
struct nlmsghdr *nlh,
const struct nf_conntrack *ct)
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);
355 nfct_build_dnat_ipv6(
struct nlmsghdr *nlh,
const struct nf_conntrack *ct)
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);
366 nfct_build_dnat_port(
struct nlmsghdr *nlh,
const struct nf_conntrack *ct)
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);
377 nfct_build_status(
struct nlmsghdr *nlh,
const struct nf_conntrack *ct)
379 mnl_attr_put_u32(nlh, CTA_STATUS, htonl(ct->status | IPS_CONFIRMED));
384 nfct_build_timeout(
struct nlmsghdr *nlh,
const struct nf_conntrack *ct)
386 mnl_attr_put_u32(nlh, CTA_TIMEOUT, htonl(ct->timeout));
391 nfct_build_mark(
struct nlmsghdr *nlh,
const struct nf_conntrack *ct)
393 mnl_attr_put_u32(nlh, CTA_MARK, htonl(ct->mark));
398 nfct_build_secmark(
struct nlmsghdr *nlh,
const struct nf_conntrack *ct)
400 mnl_attr_put_u32(nlh, CTA_SECMARK, htonl(ct->secmark));
405 nfct_build_helper_name(
struct nlmsghdr *nlh,
const struct nf_conntrack *ct)
409 nest = mnl_attr_nest_start(nlh, CTA_HELP);
410 mnl_attr_put_strz(nlh, CTA_HELP_NAME, ct->helper_name);
412 if (ct->helper_info != NULL) {
413 mnl_attr_put(nlh, CTA_HELP_INFO, ct->helper_info_len,
416 mnl_attr_nest_end(nlh, nest);
421 nfct_build_zone(
struct nlmsghdr *nlh,
const struct nf_conntrack *ct)
423 mnl_attr_put_u16(nlh, CTA_ZONE, htons(ct->zone));
428 nfct_build_labels(
struct nlmsghdr *nlh,
const struct nf_conntrack *ct)
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);
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);
442 nfct_nlmsg_build(
struct nlmsghdr *nlh,
const struct nf_conntrack *ct)
444 if (!test_bit(ATTR_ORIG_L3PROTO, ct->head.set)) {
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;
464 nest = mnl_attr_nest_start(nlh, CTA_TUPLE_ORIG);
468 if (nfct_build_tuple_raw(nlh, t) < 0) {
469 mnl_attr_nest_cancel(nlh, nest);
473 if (test_bit(ATTR_ORIG_ZONE, ct->head.set))
474 mnl_attr_put_u16(nlh, CTA_TUPLE_ZONE, htons(t->zone));
476 mnl_attr_nest_end(nlh, nest);
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;
494 nest = mnl_attr_nest_start(nlh, CTA_TUPLE_REPLY);
498 if (nfct_build_tuple_raw(nlh, t) < 0) {
499 mnl_attr_nest_cancel(nlh, nest);
503 if (test_bit(ATTR_REPL_ZONE, ct->head.set))
504 mnl_attr_put_u16(nlh, CTA_TUPLE_ZONE, htons(t->zone));
506 mnl_attr_nest_end(nlh, nest);
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);
520 if (test_bit(ATTR_STATUS, ct->head.set))
521 nfct_build_status(nlh, ct);
523 if (test_bit(ATTR_TIMEOUT, ct->head.set))
524 nfct_build_timeout(nlh, ct);
526 if (test_bit(ATTR_MARK, ct->head.set))
527 nfct_build_mark(nlh, ct);
529 if (test_bit(ATTR_SECMARK, ct->head.set))
530 nfct_build_secmark(nlh, ct);
532 nfct_build_protoinfo(nlh, ct);
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);
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);
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);
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);
573 if (test_bit(ATTR_HELPER_NAME, ct->head.set))
574 nfct_build_helper_name(nlh, ct);
576 if (test_bit(ATTR_ZONE, ct->head.set))
577 nfct_build_zone(nlh, ct);
579 if (test_bit(ATTR_CONNLABELS, ct->head.set))
580 nfct_build_labels(nlh, ct);