1 /* 2 * (C) 2005-2012 by Pablo Neira Ayuso <pablo (at) 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 * This code has been sponsored by Vyatta Inc. <http://www.vyatta.com> 10 */ 11 12 #include "internal/internal.h" 13 #include <limits.h> 14 #include <libmnl/libmnl.h> 15 16 static int 17 nfct_build_tuple_ip(struct nlmsghdr *nlh, const struct __nfct_tuple *t) 18 { 19 struct nlattr *nest; 20 21 nest = mnl_attr_nest_start(nlh, CTA_TUPLE_IP); 22 if (nest == NULL) 23 return -1; 24 25 switch(t->l3protonum) { 26 case AF_INET: 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); 29 break; 30 case AF_INET6: 31 mnl_attr_put(nlh, CTA_IP_V6_SRC, sizeof(struct in6_addr), 32 &t->src.v6); 33 mnl_attr_put(nlh, CTA_IP_V6_DST, sizeof(struct in6_addr), 34 &t->dst.v6); 35 break; 36 default: 37 mnl_attr_nest_cancel(nlh, nest); 38 return -1; 39 } 40 mnl_attr_nest_end(nlh, nest); 41 return 0; 42 } 43 44 static int 45 nfct_build_tuple_proto(struct nlmsghdr *nlh, const struct __nfct_tuple *t) 46 { 47 struct nlattr *nest; 48 49 nest = mnl_attr_nest_start(nlh, CTA_TUPLE_PROTO); 50 if (nest == NULL) 51 return -1; 52 53 mnl_attr_put_u8(nlh, CTA_PROTO_NUM, t->protonum); 54 55 switch(t->protonum) { 56 case IPPROTO_UDP: 57 case IPPROTO_TCP: 58 case IPPROTO_SCTP: 59 case IPPROTO_DCCP: 60 case IPPROTO_GRE: 61 case IPPROTO_UDPLITE: 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); 64 break; 65 case IPPROTO_ICMP: 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); 69 break; 70 case IPPROTO_ICMPV6: 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); 74 break; 75 default: 76 mnl_attr_nest_cancel(nlh, nest); 77 return -1; 78 } 79 mnl_attr_nest_end(nlh, nest); 80 return 0; 81 } 82 83 int 84 nfct_build_tuple_raw(struct nlmsghdr *nlh, const struct __nfct_tuple *t) 85 { 86 if (nfct_build_tuple_ip(nlh, t) < 0) 87 return -1; 88 if (nfct_build_tuple_proto(nlh, t) < 0) 89 return -1; 90 91 return 0; 92 } 93 94 int 95 nfct_build_tuple(struct nlmsghdr *nlh, const struct __nfct_tuple *t, int type) 96 { 97 struct nlattr *nest; 98 99 nest = mnl_attr_nest_start(nlh, type); 100 if (nest == NULL) 101 return -1; 102 103 if (nfct_build_tuple_raw(nlh, t) < 0) 104 goto err; 105 106 mnl_attr_nest_end(nlh, nest); 107 return 0; 108 err: 109 mnl_attr_nest_cancel(nlh, nest); 110 return -1; 111 } 112 113 static int 114 nfct_build_protoinfo(struct nlmsghdr *nlh, const struct nf_conntrack *ct) 115 { 116 struct nlattr *nest, *nest_proto; 117 118 switch(ct->head.orig.protonum) { 119 case IPPROTO_TCP: 120 /* Preliminary attribute check to avoid sending an empty 121 * CTA_PROTOINFO_TCP nest, which results in EINVAL in 122 * Linux kernel <= 2.6.25. */ 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))) { 130 break; 131 } 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); 137 } 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]); 143 } 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]); 149 } 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]); 153 } 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]); 157 } 158 mnl_attr_nest_end(nlh, nest_proto); 159 mnl_attr_nest_end(nlh, nest); 160 break; 161 case IPPROTO_SCTP: 162 /* See comment above on TCP. */ 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))) { 166 break; 167 } 168 nest = mnl_attr_nest_start(nlh, CTA_PROTOINFO); 169 nest_proto = mnl_attr_nest_start(nlh, CTA_PROTOINFO_SCTP); 170 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); 174 } 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])); 178 } 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])); 182 } 183 mnl_attr_nest_end(nlh, nest_proto); 184 mnl_attr_nest_end(nlh, nest); 185 break; 186 case IPPROTO_DCCP: 187 /* See comment above on TCP. */ 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))) { 191 break; 192 } 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); 198 } 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); 202 } 203 if (test_bit(ATTR_DCCP_HANDSHAKE_SEQ, ct->head.set)) { 204 uint64_t handshake_seq = 205 be64toh(ct->protoinfo.dccp.handshake_seq); 206 207 mnl_attr_put_u64(nlh, CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ, 208 handshake_seq); 209 } 210 mnl_attr_nest_end(nlh, nest_proto); 211 mnl_attr_nest_end(nlh, nest); 212 default: 213 break; 214 } 215 return 0; 216 } 217 218 static int 219 nfct_nat_seq_adj(struct nlmsghdr *nlh, const struct nf_conntrack *ct, int dir) 220 { 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)); 227 return 0; 228 } 229 230 static int 231 nfct_build_nat_seq_adj(struct nlmsghdr *nlh, const struct nf_conntrack *ct, 232 int dir) 233 { 234 int type = (dir == __DIR_ORIG) ? CTA_NAT_SEQ_ADJ_ORIG : 235 CTA_NAT_SEQ_ADJ_REPLY; 236 struct nlattr *nest; 237 238 nest = mnl_attr_nest_start(nlh, type); 239 nfct_nat_seq_adj(nlh, ct, dir); 240 mnl_attr_nest_end(nlh, nest); 241 242 return 0; 243 } 244 245 static int 246 nfct_build_protonat(struct nlmsghdr *nlh, const struct nf_conntrack *ct, 247 const struct __nfct_nat *nat) 248 { 249 struct nlattr *nest; 250 251 nest = mnl_attr_nest_start(nlh, CTA_NAT_PROTO); 252 253 switch (ct->head.orig.protonum) { 254 case IPPROTO_TCP: 255 case IPPROTO_UDP: 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); 260 break; 261 } 262 mnl_attr_nest_end(nlh, nest); 263 return 0; 264 } 265 266 static int 267 nfct_build_nat(struct nlmsghdr *nlh, const struct __nfct_nat *nat, 268 uint8_t l3protonum) 269 { 270 switch (l3protonum) { 271 case AF_INET: 272 mnl_attr_put_u32(nlh, CTA_NAT_MINIP, nat->min_ip.v4); 273 break; 274 case AF_INET6: 275 mnl_attr_put(nlh, CTA_NAT_V6_MINIP, sizeof(struct in6_addr), 276 &nat->min_ip.v6); 277 break; 278 default: 279 break; 280 } 281 return 0; 282 } 283 284 static int 285 nfct_build_snat(struct nlmsghdr *nlh, const struct nf_conntrack *ct, 286 uint8_t l3protonum) 287 { 288 struct nlattr *nest; 289 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); 294 return 0; 295 } 296 297 static int 298 nfct_build_snat_ipv4(struct nlmsghdr *nlh, const struct nf_conntrack *ct) 299 { 300 struct nlattr *nest; 301 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); 305 return 0; 306 } 307 308 static int 309 nfct_build_snat_ipv6(struct nlmsghdr *nlh, const struct nf_conntrack *ct) 310 { 311 struct nlattr *nest; 312 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); 316 return 0; 317 } 318 319 static int 320 nfct_build_snat_port(struct nlmsghdr *nlh, const struct nf_conntrack *ct) 321 { 322 struct nlattr *nest; 323 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); 327 return 0; 328 } 329 330 static int 331 nfct_build_dnat(struct nlmsghdr *nlh, const struct nf_conntrack *ct, 332 uint8_t l3protonum) 333 { 334 struct nlattr *nest; 335 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); 340 return 0; 341 } 342 343 static int 344 nfct_build_dnat_ipv4(struct nlmsghdr *nlh, const struct nf_conntrack *ct) 345 { 346 struct nlattr *nest; 347 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); 351 return 0; 352 } 353 354 static int 355 nfct_build_dnat_ipv6(struct nlmsghdr *nlh, const struct nf_conntrack *ct) 356 { 357 struct nlattr *nest; 358 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); 362 return 0; 363 } 364 365 static int 366 nfct_build_dnat_port(struct nlmsghdr *nlh, const struct nf_conntrack *ct) 367 { 368 struct nlattr *nest; 369 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); 373 return 0; 374 } 375 376 static int 377 nfct_build_status(struct nlmsghdr *nlh, const struct nf_conntrack *ct) 378 { 379 mnl_attr_put_u32(nlh, CTA_STATUS, htonl(ct->status | IPS_CONFIRMED)); 380 return 0; 381 } 382 383 static int 384 nfct_build_timeout(struct nlmsghdr *nlh, const struct nf_conntrack *ct) 385 { 386 mnl_attr_put_u32(nlh, CTA_TIMEOUT, htonl(ct->timeout)); 387 return 0; 388 } 389 390 static int 391 nfct_build_mark(struct nlmsghdr *nlh, const struct nf_conntrack *ct) 392 { 393 mnl_attr_put_u32(nlh, CTA_MARK, htonl(ct->mark)); 394 return 0; 395 } 396 397 static int 398 nfct_build_secmark(struct nlmsghdr *nlh, const struct nf_conntrack *ct) 399 { 400 mnl_attr_put_u32(nlh, CTA_SECMARK, htonl(ct->secmark)); 401 return 0; 402 } 403 404 static int 405 nfct_build_helper_name(struct nlmsghdr *nlh, const struct nf_conntrack *ct) 406 { 407 struct nlattr *nest; 408 409 nest = mnl_attr_nest_start(nlh, CTA_HELP); 410 mnl_attr_put_strz(nlh, CTA_HELP_NAME, ct->helper_name); 411 412 if (ct->helper_info != NULL) { 413 mnl_attr_put(nlh, CTA_HELP_INFO, ct->helper_info_len, 414 ct->helper_info); 415 } 416 mnl_attr_nest_end(nlh, nest); 417 return 0; 418 } 419 420 static int 421 nfct_build_zone(struct nlmsghdr *nlh, const struct nf_conntrack *ct) 422 { 423 mnl_attr_put_u16(nlh, CTA_ZONE, htons(ct->zone)); 424 return 0; 425 } 426 427 static void 428 nfct_build_labels(struct nlmsghdr *nlh, const struct nf_conntrack *ct) 429 { 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); 433 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); 438 } 439 } 440 441 int 442 nfct_nlmsg_build(struct nlmsghdr *nlh, const struct nf_conntrack *ct) 443 { 444 if (!test_bit(ATTR_ORIG_L3PROTO, ct->head.set)) { 445 errno = EINVAL; 446 return -1; 447 } 448 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; 462 struct nlattr *nest; 463 464 nest = mnl_attr_nest_start(nlh, CTA_TUPLE_ORIG); 465 if (nest == NULL) 466 return -1; 467 468 if (nfct_build_tuple_raw(nlh, t) < 0) { 469 mnl_attr_nest_cancel(nlh, nest); 470 return -1; 471 } 472 473 if (test_bit(ATTR_ORIG_ZONE, ct->head.set)) 474 mnl_attr_put_u16(nlh, CTA_TUPLE_ZONE, htons(t->zone)); 475 476 mnl_attr_nest_end(nlh, nest); 477 } 478 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; 492 struct nlattr *nest; 493 494 nest = mnl_attr_nest_start(nlh, CTA_TUPLE_REPLY); 495 if (nest == NULL) 496 return -1; 497 498 if (nfct_build_tuple_raw(nlh, t) < 0) { 499 mnl_attr_nest_cancel(nlh, nest); 500 return -1; 501 } 502 503 if (test_bit(ATTR_REPL_ZONE, ct->head.set)) 504 mnl_attr_put_u16(nlh, CTA_TUPLE_ZONE, htons(t->zone)); 505 506 mnl_attr_nest_end(nlh, nest); 507 } 508 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); 518 } 519 520 if (test_bit(ATTR_STATUS, ct->head.set)) 521 nfct_build_status(nlh, ct); 522 523 if (test_bit(ATTR_TIMEOUT, ct->head.set)) 524 nfct_build_timeout(nlh, ct); 525 526 if (test_bit(ATTR_MARK, ct->head.set)) 527 nfct_build_mark(nlh, ct); 528 529 if (test_bit(ATTR_SECMARK, ct->head.set)) 530 nfct_build_secmark(nlh, ct); 531 532 nfct_build_protoinfo(nlh, ct); 533 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); 546 } 547 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); 560 } 561 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); 566 } 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); 571 } 572 573 if (test_bit(ATTR_HELPER_NAME, ct->head.set)) 574 nfct_build_helper_name(nlh, ct); 575 576 if (test_bit(ATTR_ZONE, ct->head.set)) 577 nfct_build_zone(nlh, ct); 578 579 if (test_bit(ATTR_CONNLABELS, ct->head.set)) 580 nfct_build_labels(nlh, ct); 581 582 return 0; 583 } 584