10 #include "internal/internal.h"
12 #include <libmnl/libmnl.h>
14 static void __parse_ip(
const struct nfattr *attr,
15 struct __nfct_tuple *tuple,
19 struct nfattr *tb[CTA_IP_MAX];
21 nfnl_parse_nested(tb, CTA_IP_MAX, attr);
23 if (tb[CTA_IP_V4_SRC-1]) {
24 tuple->src.v4 = *(uint32_t *)NFA_DATA(tb[CTA_IP_V4_SRC-1]);
27 set_bit(ATTR_ORIG_IPV4_SRC, set);
30 set_bit(ATTR_REPL_IPV4_SRC, set);
33 set_bit(ATTR_MASTER_IPV4_SRC, set);
38 if (tb[CTA_IP_V4_DST-1]) {
39 tuple->dst.v4 = *(uint32_t *)NFA_DATA(tb[CTA_IP_V4_DST-1]);
42 set_bit(ATTR_ORIG_IPV4_DST, set);
45 set_bit(ATTR_REPL_IPV4_DST, set);
48 set_bit(ATTR_MASTER_IPV4_DST, set);
53 if (tb[CTA_IP_V6_SRC-1]) {
54 memcpy(&tuple->src.v6, NFA_DATA(tb[CTA_IP_V6_SRC-1]),
55 sizeof(
struct in6_addr));
58 set_bit(ATTR_ORIG_IPV6_SRC, set);
61 set_bit(ATTR_REPL_IPV6_SRC, set);
64 set_bit(ATTR_MASTER_IPV6_SRC, set);
69 if (tb[CTA_IP_V6_DST-1]) {
70 memcpy(&tuple->dst.v6, NFA_DATA(tb[CTA_IP_V6_DST-1]),
71 sizeof(
struct in6_addr));
74 set_bit(ATTR_ORIG_IPV6_DST, set);
77 set_bit(ATTR_REPL_IPV6_DST, set);
80 set_bit(ATTR_MASTER_IPV6_DST, set);
86 static void __parse_proto(
const struct nfattr *attr,
87 struct __nfct_tuple *tuple,
91 struct nfattr *tb[CTA_PROTO_MAX];
93 nfnl_parse_nested(tb, CTA_PROTO_MAX, attr);
95 if (tb[CTA_PROTO_NUM-1]) {
96 tuple->protonum = *(uint8_t *)NFA_DATA(tb[CTA_PROTO_NUM-1]);
99 set_bit(ATTR_ORIG_L4PROTO, set);
102 set_bit(ATTR_REPL_L4PROTO, set);
105 set_bit(ATTR_MASTER_L4PROTO, set);
110 if (tb[CTA_PROTO_SRC_PORT-1]) {
111 tuple->l4src.tcp.port =
112 *(uint16_t *)NFA_DATA(tb[CTA_PROTO_SRC_PORT-1]);
115 set_bit(ATTR_ORIG_PORT_SRC, set);
118 set_bit(ATTR_REPL_PORT_SRC, set);
121 set_bit(ATTR_MASTER_PORT_SRC, set);
126 if (tb[CTA_PROTO_DST_PORT-1]) {
127 tuple->l4dst.tcp.port =
128 *(uint16_t *)NFA_DATA(tb[CTA_PROTO_DST_PORT-1]);
131 set_bit(ATTR_ORIG_PORT_DST, set);
134 set_bit(ATTR_REPL_PORT_DST, set);
137 set_bit(ATTR_MASTER_PORT_DST, set);
142 if (tb[CTA_PROTO_ICMP_TYPE-1]) {
143 tuple->l4dst.icmp.type =
144 *(uint8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_TYPE-1]);
145 set_bit(ATTR_ICMP_TYPE, set);
148 if (tb[CTA_PROTO_ICMP_CODE-1]) {
149 tuple->l4dst.icmp.code =
150 *(uint8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_CODE-1]);
151 set_bit(ATTR_ICMP_CODE, set);
154 if (tb[CTA_PROTO_ICMP_ID-1]) {
155 tuple->l4src.icmp.id =
156 *(uint16_t *)NFA_DATA(tb[CTA_PROTO_ICMP_ID-1]);
157 set_bit(ATTR_ICMP_ID, set);
160 if (tb[CTA_PROTO_ICMPV6_TYPE-1]) {
161 tuple->l4dst.icmp.type =
162 *(uint8_t *)NFA_DATA(tb[CTA_PROTO_ICMPV6_TYPE-1]);
163 set_bit(ATTR_ICMP_TYPE, set);
166 if (tb[CTA_PROTO_ICMPV6_CODE-1]) {
167 tuple->l4dst.icmp.code =
168 *(uint8_t *)NFA_DATA(tb[CTA_PROTO_ICMPV6_CODE-1]);
169 set_bit(ATTR_ICMP_CODE, set);
172 if (tb[CTA_PROTO_ICMPV6_ID-1]) {
173 tuple->l4src.icmp.id =
174 *(uint16_t *)NFA_DATA(tb[CTA_PROTO_ICMPV6_ID-1]);
175 set_bit(ATTR_ICMP_ID, set);
179 void __parse_tuple(
const struct nfattr *attr,
180 struct __nfct_tuple *tuple,
184 struct nfattr *tb[CTA_TUPLE_MAX];
186 nfnl_parse_nested(tb, CTA_TUPLE_MAX, attr);
188 if (tb[CTA_TUPLE_IP-1])
189 __parse_ip(tb[CTA_TUPLE_IP-1], tuple, dir, set);
190 if (tb[CTA_TUPLE_PROTO-1])
191 __parse_proto(tb[CTA_TUPLE_PROTO-1], tuple, dir, set);
193 if (tb[CTA_TUPLE_ZONE-1]) {
194 tuple->zone = ntohs(*(uint16_t *)NFA_DATA(tb[CTA_TUPLE_ZONE-1]));
197 set_bit(ATTR_ORIG_ZONE, set);
200 set_bit(ATTR_REPL_ZONE, set);
206 static void __parse_protoinfo_tcp(
const struct nfattr *attr,
207 struct nf_conntrack *ct)
209 struct nfattr *tb[CTA_PROTOINFO_TCP_MAX];
211 nfnl_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr);
213 if (tb[CTA_PROTOINFO_TCP_STATE-1]) {
214 ct->protoinfo.tcp.state =
215 *(uint8_t *)NFA_DATA(tb[CTA_PROTOINFO_TCP_STATE-1]);
216 set_bit(ATTR_TCP_STATE, ct->head.set);
219 if (tb[CTA_PROTOINFO_TCP_WSCALE_ORIGINAL-1]) {
220 memcpy(&ct->protoinfo.tcp.wscale[__DIR_ORIG],
221 NFA_DATA(tb[CTA_PROTOINFO_TCP_WSCALE_ORIGINAL-1]),
223 set_bit(ATTR_TCP_WSCALE_ORIG, ct->head.set);
226 if (tb[CTA_PROTOINFO_TCP_WSCALE_REPLY-1]) {
227 memcpy(&ct->protoinfo.tcp.wscale[__DIR_REPL],
228 NFA_DATA(tb[CTA_PROTOINFO_TCP_WSCALE_REPLY-1]),
230 set_bit(ATTR_TCP_WSCALE_REPL, ct->head.set);
233 if (tb[CTA_PROTOINFO_TCP_FLAGS_ORIGINAL-1]) {
234 memcpy(&ct->protoinfo.tcp.flags[0],
235 NFA_DATA(tb[CTA_PROTOINFO_TCP_FLAGS_ORIGINAL-1]),
236 sizeof(
struct nf_ct_tcp_flags));
237 set_bit(ATTR_TCP_FLAGS_ORIG, ct->head.set);
238 set_bit(ATTR_TCP_MASK_ORIG, ct->head.set);
241 if (tb[CTA_PROTOINFO_TCP_FLAGS_REPLY-1]) {
242 memcpy(&ct->protoinfo.tcp.flags[1],
243 NFA_DATA(tb[CTA_PROTOINFO_TCP_FLAGS_REPLY-1]),
244 sizeof(
struct nf_ct_tcp_flags));
245 set_bit(ATTR_TCP_FLAGS_REPL, ct->head.set);
246 set_bit(ATTR_TCP_MASK_REPL, ct->head.set);
250 static void __parse_protoinfo_sctp(
const struct nfattr *attr,
251 struct nf_conntrack *ct)
253 struct nfattr *tb[CTA_PROTOINFO_SCTP_MAX];
255 nfnl_parse_nested(tb, CTA_PROTOINFO_SCTP_MAX, attr);
257 if (tb[CTA_PROTOINFO_SCTP_STATE-1]) {
258 ct->protoinfo.sctp.state =
259 *(uint8_t *)NFA_DATA(tb[CTA_PROTOINFO_SCTP_STATE-1]);
260 set_bit(ATTR_SCTP_STATE, ct->head.set);
263 if (tb[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL-1]) {
264 ct->protoinfo.sctp.vtag[__DIR_ORIG] =
265 ntohl(*(uint32_t *)NFA_DATA(tb[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL-1]));
266 set_bit(ATTR_SCTP_VTAG_ORIG, ct->head.set);
269 if (tb[CTA_PROTOINFO_SCTP_VTAG_REPLY-1]) {
270 ct->protoinfo.sctp.vtag[__DIR_REPL] =
271 ntohl(*(uint32_t *)NFA_DATA(tb[CTA_PROTOINFO_SCTP_VTAG_REPLY-1]));
272 set_bit(ATTR_SCTP_VTAG_REPL, ct->head.set);
277 static void __parse_protoinfo_dccp(
const struct nfattr *attr,
278 struct nf_conntrack *ct)
280 struct nfattr *tb[CTA_PROTOINFO_DCCP_MAX];
282 nfnl_parse_nested(tb, CTA_PROTOINFO_DCCP_MAX, attr);
284 if (tb[CTA_PROTOINFO_DCCP_STATE-1]) {
285 ct->protoinfo.dccp.state =
286 *(uint8_t *)NFA_DATA(tb[CTA_PROTOINFO_DCCP_STATE-1]);
287 set_bit(ATTR_DCCP_STATE, ct->head.set);
289 if (tb[CTA_PROTOINFO_DCCP_ROLE-1]) {
290 ct->protoinfo.dccp.role =
291 *(uint8_t *)NFA_DATA(tb[CTA_PROTOINFO_DCCP_ROLE-1]);
292 set_bit(ATTR_DCCP_ROLE, ct->head.set);
294 if (tb[CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ-1]) {
297 NFA_DATA(tb[CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ-1]),
299 ct->protoinfo.dccp.handshake_seq = __be64_to_cpu(tmp);
300 set_bit(ATTR_DCCP_HANDSHAKE_SEQ, ct->head.set);
304 static void __parse_protoinfo(
const struct nfattr *attr,
305 struct nf_conntrack *ct)
307 struct nfattr *tb[CTA_PROTOINFO_MAX];
309 nfnl_parse_nested(tb, CTA_PROTOINFO_MAX, attr);
311 if (tb[CTA_PROTOINFO_TCP-1])
312 __parse_protoinfo_tcp(tb[CTA_PROTOINFO_TCP-1], ct);
314 if (tb[CTA_PROTOINFO_SCTP-1])
315 __parse_protoinfo_sctp(tb[CTA_PROTOINFO_SCTP-1], ct);
317 if (tb[CTA_PROTOINFO_DCCP-1])
318 __parse_protoinfo_dccp(tb[CTA_PROTOINFO_DCCP-1], ct);
321 static void __parse_counters(
const struct nfattr *attr,
322 struct nf_conntrack *ct,
325 struct nfattr *tb[CTA_COUNTERS_MAX];
327 nfnl_parse_nested(tb, CTA_COUNTERS_MAX, attr);
328 if (tb[CTA_COUNTERS_PACKETS-1] || tb[CTA_COUNTERS32_PACKETS-1]) {
330 if (tb[CTA_COUNTERS32_PACKETS-1])
331 ct->counters[dir].packets
332 = ntohl(*(uint32_t *)
333 NFA_DATA(tb[CTA_COUNTERS32_PACKETS-1]));
335 if (tb[CTA_COUNTERS_PACKETS-1]) {
338 NFA_DATA(tb[CTA_COUNTERS_PACKETS-1]),
340 ct->counters[dir].packets = __be64_to_cpu(tmp);
345 set_bit(ATTR_ORIG_COUNTER_PACKETS, ct->head.set);
348 set_bit(ATTR_REPL_COUNTER_PACKETS, ct->head.set);
352 if (tb[CTA_COUNTERS_BYTES-1] || tb[CTA_COUNTERS32_BYTES-1]) {
354 if (tb[CTA_COUNTERS32_BYTES-1])
355 ct->counters[dir].bytes
356 = ntohl(*(uint32_t *)
357 NFA_DATA(tb[CTA_COUNTERS32_BYTES-1]));
359 if (tb[CTA_COUNTERS_BYTES-1]) {
362 NFA_DATA(tb[CTA_COUNTERS_BYTES-1]),
364 ct->counters[dir].bytes = __be64_to_cpu(tmp);
369 set_bit(ATTR_ORIG_COUNTER_BYTES, ct->head.set);
372 set_bit(ATTR_REPL_COUNTER_BYTES, ct->head.set);
379 __parse_nat_seq(
const struct nfattr *attr,
struct nf_conntrack *ct,
int dir)
381 struct nfattr *tb[CTA_NAT_SEQ_MAX];
383 nfnl_parse_nested(tb, CTA_NAT_SEQ_MAX, attr);
385 if (tb[CTA_NAT_SEQ_CORRECTION_POS-1]) {
386 ct->natseq[dir].correction_pos =
387 ntohl(*(uint32_t *)NFA_DATA(tb[CTA_NAT_SEQ_CORRECTION_POS-1]));
390 set_bit(ATTR_ORIG_NAT_SEQ_CORRECTION_POS, ct->head.set);
393 set_bit(ATTR_REPL_NAT_SEQ_CORRECTION_POS, ct->head.set);
398 if (tb[CTA_NAT_SEQ_OFFSET_BEFORE-1]) {
399 ct->natseq[dir].offset_before =
400 ntohl(*(uint32_t *)NFA_DATA(tb[CTA_NAT_SEQ_OFFSET_BEFORE-1]));
403 set_bit(ATTR_ORIG_NAT_SEQ_OFFSET_BEFORE, ct->head.set);
406 set_bit(ATTR_REPL_NAT_SEQ_OFFSET_BEFORE, ct->head.set);
411 if (tb[CTA_NAT_SEQ_OFFSET_AFTER-1]) {
412 ct->natseq[dir].offset_after =
413 ntohl(*(uint32_t *)NFA_DATA(tb[CTA_NAT_SEQ_OFFSET_AFTER-1]));
416 set_bit(ATTR_ORIG_NAT_SEQ_OFFSET_AFTER, ct->head.set);
419 set_bit(ATTR_REPL_NAT_SEQ_OFFSET_AFTER, ct->head.set);
426 __parse_helper(
const struct nfattr *attr,
struct nf_conntrack *ct)
428 struct nfattr *tb[CTA_HELP_MAX];
430 nfnl_parse_nested(tb, CTA_HELP_MAX, attr);
431 if (!tb[CTA_HELP_NAME-1])
434 strncpy(ct->helper_name,
435 NFA_DATA(tb[CTA_HELP_NAME-1]),
436 NFCT_HELPER_NAME_MAX);
437 ct->helper_name[NFCT_HELPER_NAME_MAX-1] =
'\0';
438 set_bit(ATTR_HELPER_NAME, ct->head.set);
442 __parse_secctx(
const struct nfattr *attr,
struct nf_conntrack *ct)
444 struct nfattr *tb[CTA_SECCTX_MAX];
446 nfnl_parse_nested(tb, CTA_SECCTX_MAX, attr);
447 if (!tb[CTA_SECCTX_NAME-1])
450 ct->secctx = strdup(NFA_DATA(tb[CTA_SECCTX_NAME-1]));
452 set_bit(ATTR_SECCTX, ct->head.set);
455 int __parse_message_type(
const struct nlmsghdr *nlh)
457 uint16_t type = NFNL_MSG_TYPE(nlh->nlmsg_type);
458 uint16_t flags = nlh->nlmsg_flags;
459 int ret = NFCT_T_UNKNOWN;
461 if (type == IPCTNL_MSG_CT_NEW) {
462 if (flags & (NLM_F_CREATE|NLM_F_EXCL))
466 }
else if (type == IPCTNL_MSG_CT_DELETE)
467 ret = NFCT_T_DESTROY;
473 __parse_timestamp(
const struct nfattr *attr,
struct nf_conntrack *ct)
475 struct nfattr *tb[CTA_TIMESTAMP_MAX];
477 nfnl_parse_nested(tb, CTA_TIMESTAMP_MAX, attr);
478 if (tb[CTA_TIMESTAMP_START-1]) {
480 memcpy(&tmp, NFA_DATA(tb[CTA_TIMESTAMP_START-1]),
sizeof(tmp));
481 ct->timestamp.start = __be64_to_cpu(tmp);
482 set_bit(ATTR_TIMESTAMP_START, ct->head.set);
484 if (tb[CTA_TIMESTAMP_STOP-1]) {
486 memcpy(&tmp, NFA_DATA(tb[CTA_TIMESTAMP_STOP-1]),
sizeof(tmp));
487 ct->timestamp.stop = __be64_to_cpu(tmp);
488 set_bit(ATTR_TIMESTAMP_STOP, ct->head.set);
493 __parse_labels(
const struct nfattr *attr,
struct nf_conntrack *ct)
495 struct nfct_bitmask *mask;
498 len = NFA_PAYLOAD(attr);
500 mask = nfct_bitmask_new((len * CHAR_BIT) - 1);
503 memcpy(mask->bits, NFA_DATA(attr), len);
508 void __parse_conntrack(
const struct nlmsghdr *nlh,
509 struct nfattr *cda[],
510 struct nf_conntrack *ct)
512 struct nfgenmsg *nfhdr = NLMSG_DATA(nlh);
514 if (cda[CTA_TUPLE_ORIG-1]) {
515 ct->head.orig.l3protonum = nfhdr->nfgen_family;
516 set_bit(ATTR_ORIG_L3PROTO, ct->head.set);
518 __parse_tuple(cda[CTA_TUPLE_ORIG-1],
519 &ct->head.orig, __DIR_ORIG, ct->head.set);
522 if (cda[CTA_TUPLE_REPLY-1]) {
523 ct->repl.l3protonum = nfhdr->nfgen_family;
524 set_bit(ATTR_REPL_L3PROTO, ct->head.set);
526 __parse_tuple(cda[CTA_TUPLE_REPLY-1],
527 &ct->repl, __DIR_REPL, ct->head.set);
530 if (cda[CTA_TUPLE_MASTER-1]) {
531 ct->master.l3protonum = nfhdr->nfgen_family;
532 set_bit(ATTR_MASTER_L3PROTO, ct->head.set);
534 __parse_tuple(cda[CTA_TUPLE_MASTER-1],
535 &ct->master, __DIR_MASTER, ct->head.set);
538 if (cda[CTA_NAT_SEQ_ADJ_ORIG-1])
539 __parse_nat_seq(cda[CTA_NAT_SEQ_ADJ_ORIG-1], ct, __DIR_ORIG);
541 if (cda[CTA_NAT_SEQ_ADJ_REPLY-1])
542 __parse_nat_seq(cda[CTA_NAT_SEQ_ADJ_REPLY-1], ct, __DIR_REPL);
544 if (cda[CTA_STATUS-1]) {
545 ct->status = ntohl(*(uint32_t *)NFA_DATA(cda[CTA_STATUS-1]));
546 set_bit(ATTR_STATUS, ct->head.set);
549 if (cda[CTA_PROTOINFO-1])
550 __parse_protoinfo(cda[CTA_PROTOINFO-1], ct);
552 if (cda[CTA_TIMEOUT-1]) {
553 ct->timeout = ntohl(*(uint32_t *)NFA_DATA(cda[CTA_TIMEOUT-1]));
554 set_bit(ATTR_TIMEOUT, ct->head.set);
557 if (cda[CTA_MARK-1]) {
558 ct->mark = ntohl(*(uint32_t *)NFA_DATA(cda[CTA_MARK-1]));
559 set_bit(ATTR_MARK, ct->head.set);
562 if (cda[CTA_SECMARK-1]) {
563 ct->secmark = ntohl(*(uint32_t *)NFA_DATA(cda[CTA_SECMARK-1]));
564 set_bit(ATTR_SECMARK, ct->head.set);
567 if (cda[CTA_COUNTERS_ORIG-1])
568 __parse_counters(cda[CTA_COUNTERS_ORIG-1], ct, __DIR_ORIG);
570 if (cda[CTA_COUNTERS_REPLY-1])
571 __parse_counters(cda[CTA_COUNTERS_REPLY-1], ct, __DIR_REPL);
573 if (cda[CTA_USE-1]) {
574 ct->use = ntohl(*(uint32_t *)NFA_DATA(cda[CTA_USE-1]));
575 set_bit(ATTR_USE, ct->head.set);
579 ct->id = ntohl(*(uint32_t *)NFA_DATA(cda[CTA_ID-1]));
580 set_bit(ATTR_ID, ct->head.set);
584 __parse_helper(cda[CTA_HELP-1], ct);
586 if (cda[CTA_ZONE-1]) {
587 ct->zone = ntohs(*(uint16_t *)NFA_DATA(cda[CTA_ZONE-1]));
588 set_bit(ATTR_ZONE, ct->head.set);
591 if (cda[CTA_SECCTX-1])
592 __parse_secctx(cda[CTA_SECCTX-1], ct);
594 if (cda[CTA_TIMESTAMP-1])
595 __parse_timestamp(cda[CTA_TIMESTAMP-1], ct);
597 if (cda[CTA_LABELS-1])
598 __parse_labels(cda[CTA_LABELS-1], ct);
void nfct_set_attr(struct nf_conntrack *ct, const enum nf_conntrack_attr type, const void *value)