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 14static 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 86static 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 179void __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 206static 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 250static 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 277static 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 304static 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 321static 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 378static 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 425static 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 441static 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 455int __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 472static 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 492static 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 508void __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} 600