libnetfilter_conntrack  1.0.6
conntrack/parse.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 #include <limits.h>
12 #include <libmnl/libmnl.h>
13 
14 static void __parse_ip(const struct nfattr *attr,
15  struct __nfct_tuple *tuple,
16  const int dir,
17  uint32_t *set)
18 {
19  struct nfattr *tb[CTA_IP_MAX];
20 
21  nfnl_parse_nested(tb, CTA_IP_MAX, attr);
22 
23  if (tb[CTA_IP_V4_SRC-1]) {
24  tuple->src.v4 = *(uint32_t *)NFA_DATA(tb[CTA_IP_V4_SRC-1]);
25  switch(dir) {
26  case __DIR_ORIG:
27  set_bit(ATTR_ORIG_IPV4_SRC, set);
28  break;
29  case __DIR_REPL:
30  set_bit(ATTR_REPL_IPV4_SRC, set);
31  break;
32  case __DIR_MASTER:
33  set_bit(ATTR_MASTER_IPV4_SRC, set);
34  break;
35  }
36  }
37 
38  if (tb[CTA_IP_V4_DST-1]) {
39  tuple->dst.v4 = *(uint32_t *)NFA_DATA(tb[CTA_IP_V4_DST-1]);
40  switch(dir) {
41  case __DIR_ORIG:
42  set_bit(ATTR_ORIG_IPV4_DST, set);
43  break;
44  case __DIR_REPL:
45  set_bit(ATTR_REPL_IPV4_DST, set);
46  break;
47  case __DIR_MASTER:
48  set_bit(ATTR_MASTER_IPV4_DST, set);
49  break;
50  }
51  }
52 
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));
56  switch(dir) {
57  case __DIR_ORIG:
58  set_bit(ATTR_ORIG_IPV6_SRC, set);
59  break;
60  case __DIR_REPL:
61  set_bit(ATTR_REPL_IPV6_SRC, set);
62  break;
63  case __DIR_MASTER:
64  set_bit(ATTR_MASTER_IPV6_SRC, set);
65  break;
66  }
67  }
68 
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));
72  switch(dir) {
73  case __DIR_ORIG:
74  set_bit(ATTR_ORIG_IPV6_DST, set);
75  break;
76  case __DIR_REPL:
77  set_bit(ATTR_REPL_IPV6_DST, set);
78  break;
79  case __DIR_MASTER:
80  set_bit(ATTR_MASTER_IPV6_DST, set);
81  break;
82  }
83  }
84 }
85 
86 static void __parse_proto(const struct nfattr *attr,
87  struct __nfct_tuple *tuple,
88  const int dir,
89  uint32_t *set)
90 {
91  struct nfattr *tb[CTA_PROTO_MAX];
92 
93  nfnl_parse_nested(tb, CTA_PROTO_MAX, attr);
94 
95  if (tb[CTA_PROTO_NUM-1]) {
96  tuple->protonum = *(uint8_t *)NFA_DATA(tb[CTA_PROTO_NUM-1]);
97  switch(dir) {
98  case __DIR_ORIG:
99  set_bit(ATTR_ORIG_L4PROTO, set);
100  break;
101  case __DIR_REPL:
102  set_bit(ATTR_REPL_L4PROTO, set);
103  break;
104  case __DIR_MASTER:
105  set_bit(ATTR_MASTER_L4PROTO, set);
106  break;
107  }
108  }
109 
110  if (tb[CTA_PROTO_SRC_PORT-1]) {
111  tuple->l4src.tcp.port =
112  *(uint16_t *)NFA_DATA(tb[CTA_PROTO_SRC_PORT-1]);
113  switch(dir) {
114  case __DIR_ORIG:
115  set_bit(ATTR_ORIG_PORT_SRC, set);
116  break;
117  case __DIR_REPL:
118  set_bit(ATTR_REPL_PORT_SRC, set);
119  break;
120  case __DIR_MASTER:
121  set_bit(ATTR_MASTER_PORT_SRC, set);
122  break;
123  }
124  }
125 
126  if (tb[CTA_PROTO_DST_PORT-1]) {
127  tuple->l4dst.tcp.port =
128  *(uint16_t *)NFA_DATA(tb[CTA_PROTO_DST_PORT-1]);
129  switch(dir) {
130  case __DIR_ORIG:
131  set_bit(ATTR_ORIG_PORT_DST, set);
132  break;
133  case __DIR_REPL:
134  set_bit(ATTR_REPL_PORT_DST, set);
135  break;
136  case __DIR_MASTER:
137  set_bit(ATTR_MASTER_PORT_DST, set);
138  break;
139  }
140  }
141 
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);
146  }
147 
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);
152  }
153 
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);
158  }
159 
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);
164  }
165 
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);
170  }
171 
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);
176  }
177 }
178 
179 void __parse_tuple(const struct nfattr *attr,
180  struct __nfct_tuple *tuple,
181  int dir,
182  uint32_t *set)
183 {
184  struct nfattr *tb[CTA_TUPLE_MAX];
185 
186  nfnl_parse_nested(tb, CTA_TUPLE_MAX, attr);
187 
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);
192 
193  if (tb[CTA_TUPLE_ZONE-1]) {
194  tuple->zone = ntohs(*(uint16_t *)NFA_DATA(tb[CTA_TUPLE_ZONE-1]));
195  switch(dir) {
196  case __DIR_ORIG:
197  set_bit(ATTR_ORIG_ZONE, set);
198  break;
199  case __DIR_REPL:
200  set_bit(ATTR_REPL_ZONE, set);
201  break;
202  }
203  }
204 }
205 
206 static void __parse_protoinfo_tcp(const struct nfattr *attr,
207  struct nf_conntrack *ct)
208 {
209  struct nfattr *tb[CTA_PROTOINFO_TCP_MAX];
210 
211  nfnl_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr);
212 
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);
217  }
218 
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]),
222  sizeof(uint8_t));
223  set_bit(ATTR_TCP_WSCALE_ORIG, ct->head.set);
224  }
225 
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]),
229  sizeof(uint8_t));
230  set_bit(ATTR_TCP_WSCALE_REPL, ct->head.set);
231  }
232 
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);
239  }
240 
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);
247  }
248 }
249 
250 static void __parse_protoinfo_sctp(const struct nfattr *attr,
251  struct nf_conntrack *ct)
252 {
253  struct nfattr *tb[CTA_PROTOINFO_SCTP_MAX];
254 
255  nfnl_parse_nested(tb, CTA_PROTOINFO_SCTP_MAX, attr);
256 
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);
261  }
262 
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);
267  }
268 
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);
273  }
274 
275 }
276 
277 static void __parse_protoinfo_dccp(const struct nfattr *attr,
278  struct nf_conntrack *ct)
279 {
280  struct nfattr *tb[CTA_PROTOINFO_DCCP_MAX];
281 
282  nfnl_parse_nested(tb, CTA_PROTOINFO_DCCP_MAX, attr);
283 
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);
288  }
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);
293  }
294  if (tb[CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ-1]) {
295  uint64_t tmp;
296  memcpy(&tmp,
297  NFA_DATA(tb[CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ-1]),
298  sizeof(tmp));
299  ct->protoinfo.dccp.handshake_seq = __be64_to_cpu(tmp);
300  set_bit(ATTR_DCCP_HANDSHAKE_SEQ, ct->head.set);
301  }
302 }
303 
304 static void __parse_protoinfo(const struct nfattr *attr,
305  struct nf_conntrack *ct)
306 {
307  struct nfattr *tb[CTA_PROTOINFO_MAX];
308 
309  nfnl_parse_nested(tb, CTA_PROTOINFO_MAX, attr);
310 
311  if (tb[CTA_PROTOINFO_TCP-1])
312  __parse_protoinfo_tcp(tb[CTA_PROTOINFO_TCP-1], ct);
313 
314  if (tb[CTA_PROTOINFO_SCTP-1])
315  __parse_protoinfo_sctp(tb[CTA_PROTOINFO_SCTP-1], ct);
316 
317  if (tb[CTA_PROTOINFO_DCCP-1])
318  __parse_protoinfo_dccp(tb[CTA_PROTOINFO_DCCP-1], ct);
319 }
320 
321 static void __parse_counters(const struct nfattr *attr,
322  struct nf_conntrack *ct,
323  int dir)
324 {
325  struct nfattr *tb[CTA_COUNTERS_MAX];
326 
327  nfnl_parse_nested(tb, CTA_COUNTERS_MAX, attr);
328  if (tb[CTA_COUNTERS_PACKETS-1] || tb[CTA_COUNTERS32_PACKETS-1]) {
329 
330  if (tb[CTA_COUNTERS32_PACKETS-1])
331  ct->counters[dir].packets
332  = ntohl(*(uint32_t *)
333  NFA_DATA(tb[CTA_COUNTERS32_PACKETS-1]));
334 
335  if (tb[CTA_COUNTERS_PACKETS-1]) {
336  uint64_t tmp;
337  memcpy(&tmp,
338  NFA_DATA(tb[CTA_COUNTERS_PACKETS-1]),
339  sizeof(tmp));
340  ct->counters[dir].packets = __be64_to_cpu(tmp);
341  }
342 
343  switch(dir) {
344  case __DIR_ORIG:
345  set_bit(ATTR_ORIG_COUNTER_PACKETS, ct->head.set);
346  break;
347  case __DIR_REPL:
348  set_bit(ATTR_REPL_COUNTER_PACKETS, ct->head.set);
349  break;
350  }
351  }
352  if (tb[CTA_COUNTERS_BYTES-1] || tb[CTA_COUNTERS32_BYTES-1]) {
353 
354  if (tb[CTA_COUNTERS32_BYTES-1])
355  ct->counters[dir].bytes
356  = ntohl(*(uint32_t *)
357  NFA_DATA(tb[CTA_COUNTERS32_BYTES-1]));
358 
359  if (tb[CTA_COUNTERS_BYTES-1]) {
360  uint64_t tmp;
361  memcpy(&tmp,
362  NFA_DATA(tb[CTA_COUNTERS_BYTES-1]),
363  sizeof(tmp));
364  ct->counters[dir].bytes = __be64_to_cpu(tmp);
365  }
366 
367  switch(dir) {
368  case __DIR_ORIG:
369  set_bit(ATTR_ORIG_COUNTER_BYTES, ct->head.set);
370  break;
371  case __DIR_REPL:
372  set_bit(ATTR_REPL_COUNTER_BYTES, ct->head.set);
373  break;
374  }
375  }
376 }
377 
378 static void
379 __parse_nat_seq(const struct nfattr *attr, struct nf_conntrack *ct, int dir)
380 {
381  struct nfattr *tb[CTA_NAT_SEQ_MAX];
382 
383  nfnl_parse_nested(tb, CTA_NAT_SEQ_MAX, attr);
384 
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]));
388  switch(dir) {
389  case __DIR_ORIG:
390  set_bit(ATTR_ORIG_NAT_SEQ_CORRECTION_POS, ct->head.set);
391  break;
392  case __DIR_REPL:
393  set_bit(ATTR_REPL_NAT_SEQ_CORRECTION_POS, ct->head.set);
394  break;
395  }
396  }
397 
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]));
401  switch(dir) {
402  case __DIR_ORIG:
403  set_bit(ATTR_ORIG_NAT_SEQ_OFFSET_BEFORE, ct->head.set);
404  break;
405  case __DIR_REPL:
406  set_bit(ATTR_REPL_NAT_SEQ_OFFSET_BEFORE, ct->head.set);
407  break;
408  }
409  }
410 
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]));
414  switch(dir) {
415  case __DIR_ORIG:
416  set_bit(ATTR_ORIG_NAT_SEQ_OFFSET_AFTER, ct->head.set);
417  break;
418  case __DIR_REPL:
419  set_bit(ATTR_REPL_NAT_SEQ_OFFSET_AFTER, ct->head.set);
420  break;
421  }
422  }
423 }
424 
425 static void
426 __parse_helper(const struct nfattr *attr, struct nf_conntrack *ct)
427 {
428  struct nfattr *tb[CTA_HELP_MAX];
429 
430  nfnl_parse_nested(tb, CTA_HELP_MAX, attr);
431  if (!tb[CTA_HELP_NAME-1])
432  return;
433 
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);
439 }
440 
441 static void
442 __parse_secctx(const struct nfattr *attr, struct nf_conntrack *ct)
443 {
444  struct nfattr *tb[CTA_SECCTX_MAX];
445 
446  nfnl_parse_nested(tb, CTA_SECCTX_MAX, attr);
447  if (!tb[CTA_SECCTX_NAME-1])
448  return;
449 
450  ct->secctx = strdup(NFA_DATA(tb[CTA_SECCTX_NAME-1]));
451  if (ct->secctx)
452  set_bit(ATTR_SECCTX, ct->head.set);
453 }
454 
455 int __parse_message_type(const struct nlmsghdr *nlh)
456 {
457  uint16_t type = NFNL_MSG_TYPE(nlh->nlmsg_type);
458  uint16_t flags = nlh->nlmsg_flags;
459  int ret = NFCT_T_UNKNOWN;
460 
461  if (type == IPCTNL_MSG_CT_NEW) {
462  if (flags & (NLM_F_CREATE|NLM_F_EXCL))
463  ret = NFCT_T_NEW;
464  else
465  ret = NFCT_T_UPDATE;
466  } else if (type == IPCTNL_MSG_CT_DELETE)
467  ret = NFCT_T_DESTROY;
468 
469  return ret;
470 }
471 
472 static void
473 __parse_timestamp(const struct nfattr *attr, struct nf_conntrack *ct)
474 {
475  struct nfattr *tb[CTA_TIMESTAMP_MAX];
476 
477  nfnl_parse_nested(tb, CTA_TIMESTAMP_MAX, attr);
478  if (tb[CTA_TIMESTAMP_START-1]) {
479  uint64_t tmp;
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);
483  }
484  if (tb[CTA_TIMESTAMP_STOP-1]) {
485  uint64_t tmp;
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);
489  }
490 }
491 
492 static void
493 __parse_labels(const struct nfattr *attr, struct nf_conntrack *ct)
494 {
495  struct nfct_bitmask *mask;
496  uint16_t len;
497 
498  len = NFA_PAYLOAD(attr);
499  if (len) {
500  mask = nfct_bitmask_new((len * CHAR_BIT) - 1);
501  if (!mask)
502  return;
503  memcpy(mask->bits, NFA_DATA(attr), len);
504  nfct_set_attr(ct, ATTR_CONNLABELS, mask);
505  }
506 }
507 
508 void __parse_conntrack(const struct nlmsghdr *nlh,
509  struct nfattr *cda[],
510  struct nf_conntrack *ct)
511 {
512  struct nfgenmsg *nfhdr = NLMSG_DATA(nlh);
513 
514  if (cda[CTA_TUPLE_ORIG-1]) {
515  ct->head.orig.l3protonum = nfhdr->nfgen_family;
516  set_bit(ATTR_ORIG_L3PROTO, ct->head.set);
517 
518  __parse_tuple(cda[CTA_TUPLE_ORIG-1],
519  &ct->head.orig, __DIR_ORIG, ct->head.set);
520  }
521 
522  if (cda[CTA_TUPLE_REPLY-1]) {
523  ct->repl.l3protonum = nfhdr->nfgen_family;
524  set_bit(ATTR_REPL_L3PROTO, ct->head.set);
525 
526  __parse_tuple(cda[CTA_TUPLE_REPLY-1],
527  &ct->repl, __DIR_REPL, ct->head.set);
528  }
529 
530  if (cda[CTA_TUPLE_MASTER-1]) {
531  ct->master.l3protonum = nfhdr->nfgen_family;
532  set_bit(ATTR_MASTER_L3PROTO, ct->head.set);
533 
534  __parse_tuple(cda[CTA_TUPLE_MASTER-1],
535  &ct->master, __DIR_MASTER, ct->head.set);
536  }
537 
538  if (cda[CTA_NAT_SEQ_ADJ_ORIG-1])
539  __parse_nat_seq(cda[CTA_NAT_SEQ_ADJ_ORIG-1], ct, __DIR_ORIG);
540 
541  if (cda[CTA_NAT_SEQ_ADJ_REPLY-1])
542  __parse_nat_seq(cda[CTA_NAT_SEQ_ADJ_REPLY-1], ct, __DIR_REPL);
543 
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);
547  }
548 
549  if (cda[CTA_PROTOINFO-1])
550  __parse_protoinfo(cda[CTA_PROTOINFO-1], ct);
551 
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);
555  }
556 
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);
560  }
561 
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);
565  }
566 
567  if (cda[CTA_COUNTERS_ORIG-1])
568  __parse_counters(cda[CTA_COUNTERS_ORIG-1], ct, __DIR_ORIG);
569 
570  if (cda[CTA_COUNTERS_REPLY-1])
571  __parse_counters(cda[CTA_COUNTERS_REPLY-1], ct, __DIR_REPL);
572 
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);
576  }
577 
578  if (cda[CTA_ID-1]) {
579  ct->id = ntohl(*(uint32_t *)NFA_DATA(cda[CTA_ID-1]));
580  set_bit(ATTR_ID, ct->head.set);
581  }
582 
583  if (cda[CTA_HELP-1])
584  __parse_helper(cda[CTA_HELP-1], ct);
585 
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);
589  }
590 
591  if (cda[CTA_SECCTX-1])
592  __parse_secctx(cda[CTA_SECCTX-1], ct);
593 
594  if (cda[CTA_TIMESTAMP-1])
595  __parse_timestamp(cda[CTA_TIMESTAMP-1], ct);
596 
597  if (cda[CTA_LABELS-1])
598  __parse_labels(cda[CTA_LABELS-1], ct);
599 }
void nfct_set_attr(struct nf_conntrack *ct, const enum nf_conntrack_attr type, const void *value)