1 /* 2 * (C) 2005-2011 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 10 #include "internal/internal.h" 11 12 static void copy_attr_orig_ipv4_src(struct nf_conntrack *dest, 13 const struct nf_conntrack *orig) 14 { 15 dest->head.orig.src.v4 = orig->head.orig.src.v4; 16 } 17 18 static void copy_attr_orig_ipv4_dst(struct nf_conntrack *dest, 19 const struct nf_conntrack *orig) 20 { 21 dest->head.orig.dst.v4 = orig->head.orig.dst.v4; 22 } 23 24 static void copy_attr_repl_ipv4_src(struct nf_conntrack *dest, 25 const struct nf_conntrack *orig) 26 { 27 dest->repl.src.v4 = orig->repl.src.v4; 28 } 29 30 static void copy_attr_repl_ipv4_dst(struct nf_conntrack *dest, 31 const struct nf_conntrack *orig) 32 { 33 dest->repl.dst.v4 = orig->repl.dst.v4; 34 } 35 36 static void copy_attr_orig_ipv6_src(struct nf_conntrack *dest, 37 const struct nf_conntrack *orig) 38 { 39 memcpy(&dest->head.orig.src, 40 &orig->head.orig.src, 41 sizeof(union __nfct_address)); 42 } 43 44 static void copy_attr_orig_ipv6_dst(struct nf_conntrack *dest, 45 const struct nf_conntrack *orig) 46 { 47 memcpy(&dest->head.orig.dst, 48 &orig->head.orig.dst, 49 sizeof(union __nfct_address)); 50 } 51 52 static void copy_attr_repl_ipv6_src(struct nf_conntrack *dest, 53 const struct nf_conntrack *orig) 54 { 55 memcpy(&dest->repl.src, 56 &orig->repl.src, 57 sizeof(union __nfct_address)); 58 } 59 60 static void copy_attr_repl_ipv6_dst(struct nf_conntrack *dest, 61 const struct nf_conntrack *orig) 62 { 63 memcpy(&dest->repl.dst, 64 &orig->repl.dst, 65 sizeof(union __nfct_address)); 66 } 67 68 static void copy_attr_orig_port_src(struct nf_conntrack *dest, 69 const struct nf_conntrack *orig) 70 { 71 dest->head.orig.l4src.all = orig->head.orig.l4src.all; 72 } 73 74 static void copy_attr_orig_port_dst(struct nf_conntrack *dest, 75 const struct nf_conntrack *orig) 76 { 77 dest->head.orig.l4dst.all = orig->head.orig.l4dst.all; 78 } 79 80 static void copy_attr_repl_port_src(struct nf_conntrack *dest, 81 const struct nf_conntrack *orig) 82 { 83 dest->repl.l4src.all = orig->repl.l4src.all; 84 } 85 86 static void copy_attr_repl_port_dst(struct nf_conntrack *dest, 87 const struct nf_conntrack *orig) 88 { 89 dest->repl.l4dst.all = orig->repl.l4dst.all; 90 } 91 92 static void copy_attr_orig_zone(struct nf_conntrack *dest, 93 const struct nf_conntrack *orig) 94 { 95 dest->head.orig.zone = orig->head.orig.zone; 96 } 97 98 static void copy_attr_repl_zone(struct nf_conntrack *dest, 99 const struct nf_conntrack *orig) 100 { 101 dest->repl.zone = orig->repl.zone; 102 } 103 104 static void copy_attr_icmp_type(struct nf_conntrack *dest, 105 const struct nf_conntrack *orig) 106 { 107 dest->head.orig.l4dst.icmp.type = 108 orig->head.orig.l4dst.icmp.type; 109 110 } 111 112 static void copy_attr_icmp_code(struct nf_conntrack *dest, 113 const struct nf_conntrack *orig) 114 { 115 dest->head.orig.l4dst.icmp.code = 116 orig->head.orig.l4dst.icmp.code; 117 118 } 119 120 static void copy_attr_icmp_id(struct nf_conntrack *dest, 121 const struct nf_conntrack *orig) 122 { 123 dest->head.orig.l4src.icmp.id = 124 orig->head.orig.l4src.icmp.id; 125 } 126 127 static void copy_attr_orig_l3proto(struct nf_conntrack *dest, 128 const struct nf_conntrack *orig) 129 { 130 dest->head.orig.l3protonum = orig->head.orig.l3protonum; 131 } 132 133 static void copy_attr_repl_l3proto(struct nf_conntrack *dest, 134 const struct nf_conntrack *orig) 135 { 136 dest->repl.l3protonum = orig->repl.l3protonum; 137 } 138 139 static void copy_attr_orig_l4proto(struct nf_conntrack *dest, 140 const struct nf_conntrack *orig) 141 { 142 dest->head.orig.protonum = orig->head.orig.protonum; 143 } 144 145 static void copy_attr_repl_l4proto(struct nf_conntrack *dest, 146 const struct nf_conntrack *orig) 147 { 148 dest->repl.protonum = orig->repl.protonum; 149 } 150 151 static void copy_attr_master_ipv4_src(struct nf_conntrack *dest, 152 const struct nf_conntrack *orig) 153 { 154 dest->master.src.v4 = orig->master.src.v4; 155 } 156 157 static void copy_attr_master_ipv4_dst(struct nf_conntrack *dest, 158 const struct nf_conntrack *orig) 159 { 160 dest->master.dst.v4 = orig->master.dst.v4; 161 } 162 163 static void copy_attr_master_ipv6_src(struct nf_conntrack *dest, 164 const struct nf_conntrack *orig) 165 { 166 memcpy(&dest->master.src, &orig->master.src, 167 sizeof(union __nfct_address)); 168 } 169 170 static void copy_attr_master_ipv6_dst(struct nf_conntrack *dest, 171 const struct nf_conntrack *orig) 172 { 173 memcpy(&dest->master.dst, &orig->master.dst, 174 sizeof(union __nfct_address)); 175 } 176 177 static void copy_attr_master_port_src(struct nf_conntrack *dest, 178 const struct nf_conntrack *orig) 179 { 180 dest->master.l4src.all = orig->master.l4src.all; 181 } 182 183 static void copy_attr_master_port_dst(struct nf_conntrack *dest, 184 const struct nf_conntrack *orig) 185 { 186 dest->master.l4dst.all = orig->master.l4dst.all; 187 } 188 189 static void copy_attr_master_l3proto(struct nf_conntrack *dest, 190 const struct nf_conntrack *orig) 191 { 192 dest->master.l3protonum = orig->master.l3protonum; 193 } 194 195 static void copy_attr_master_l4proto(struct nf_conntrack *dest, 196 const struct nf_conntrack *orig) 197 { 198 dest->master.protonum = orig->master.protonum; 199 } 200 201 static void copy_attr_tcp_state(struct nf_conntrack *dest, 202 const struct nf_conntrack *orig) 203 { 204 dest->protoinfo.tcp.state = orig->protoinfo.tcp.state; 205 } 206 207 static void copy_attr_tcp_flags_orig(struct nf_conntrack *dest, 208 const struct nf_conntrack *orig) 209 { 210 dest->protoinfo.tcp.flags[__DIR_ORIG].value = 211 orig->protoinfo.tcp.flags[__DIR_ORIG].value; 212 } 213 214 static void copy_attr_tcp_flags_repl(struct nf_conntrack *dest, 215 const struct nf_conntrack *orig) 216 { 217 dest->protoinfo.tcp.flags[__DIR_REPL].value = 218 orig->protoinfo.tcp.flags[__DIR_REPL].value; 219 } 220 221 static void copy_attr_tcp_mask_orig(struct nf_conntrack *dest, 222 const struct nf_conntrack *orig) 223 { 224 dest->protoinfo.tcp.flags[__DIR_ORIG].mask = 225 orig->protoinfo.tcp.flags[__DIR_ORIG].mask; 226 } 227 228 static void copy_attr_tcp_mask_repl(struct nf_conntrack *dest, 229 const struct nf_conntrack *orig) 230 { 231 dest->protoinfo.tcp.flags[__DIR_REPL].mask = 232 orig->protoinfo.tcp.flags[__DIR_REPL].mask; 233 } 234 235 static void copy_attr_tcp_wscale_orig(struct nf_conntrack *dest, 236 const struct nf_conntrack *orig) 237 { 238 dest->protoinfo.tcp.wscale[__DIR_ORIG] = 239 orig->protoinfo.tcp.wscale[__DIR_ORIG]; 240 } 241 242 static void copy_attr_tcp_wscale_repl(struct nf_conntrack *dest, 243 const struct nf_conntrack *orig) 244 { 245 dest->protoinfo.tcp.wscale[__DIR_REPL] = 246 orig->protoinfo.tcp.wscale[__DIR_REPL]; 247 } 248 249 static void copy_attr_sctp_state(struct nf_conntrack *dest, 250 const struct nf_conntrack *orig) 251 { 252 dest->protoinfo.sctp.state = orig->protoinfo.sctp.state; 253 } 254 255 static void copy_attr_sctp_vtag_orig(struct nf_conntrack *dest, 256 const struct nf_conntrack *orig) 257 { 258 dest->protoinfo.sctp.vtag[__DIR_ORIG] = 259 orig->protoinfo.sctp.vtag[__DIR_ORIG]; 260 } 261 262 static void copy_attr_sctp_vtag_repl(struct nf_conntrack *dest, 263 const struct nf_conntrack *orig) 264 { 265 dest->protoinfo.sctp.vtag[__DIR_REPL] = 266 orig->protoinfo.sctp.vtag[__DIR_REPL]; 267 } 268 269 static void copy_attr_dccp_state(struct nf_conntrack *dest, 270 const struct nf_conntrack *orig) 271 { 272 dest->protoinfo.dccp.state = orig->protoinfo.dccp.state; 273 } 274 275 static void copy_attr_dccp_role(struct nf_conntrack *dest, 276 const struct nf_conntrack *orig) 277 { 278 dest->protoinfo.dccp.role = orig->protoinfo.dccp.role; 279 } 280 281 static void copy_attr_dccp_handshake_seq(struct nf_conntrack *dest, 282 const struct nf_conntrack *orig) 283 { 284 dest->protoinfo.dccp.handshake_seq = orig->protoinfo.dccp.handshake_seq; 285 } 286 287 static void copy_attr_snat_ipv4(struct nf_conntrack *dest, 288 const struct nf_conntrack *orig) 289 { 290 dest->snat.min_ip.v4 = orig->snat.min_ip.v4; 291 } 292 293 static void copy_attr_dnat_ipv4(struct nf_conntrack *dest, 294 const struct nf_conntrack *orig) 295 { 296 dest->dnat.min_ip.v4 = orig->dnat.min_ip.v4; 297 } 298 299 static void copy_attr_snat_ipv6(struct nf_conntrack *dest, 300 const struct nf_conntrack *orig) 301 { 302 memcpy(&dest->snat.min_ip.v6, &orig->snat.min_ip.v6, 303 sizeof(struct in6_addr)); 304 } 305 306 static void copy_attr_dnat_ipv6(struct nf_conntrack *dest, 307 const struct nf_conntrack *orig) 308 { 309 memcpy(&dest->dnat.min_ip.v6, &orig->dnat.min_ip.v6, 310 sizeof(struct in6_addr)); 311 } 312 313 static void copy_attr_snat_port(struct nf_conntrack *dest, 314 const struct nf_conntrack *orig) 315 { 316 dest->snat.l4min.all = orig->snat.l4min.all; 317 } 318 319 static void copy_attr_dnat_port(struct nf_conntrack *dest, 320 const struct nf_conntrack *orig) 321 { 322 dest->dnat.l4min.all = orig->dnat.l4min.all; 323 } 324 325 static void copy_attr_timeout(struct nf_conntrack *dest, 326 const struct nf_conntrack *orig) 327 { 328 dest->timeout = orig->timeout; 329 } 330 331 static void copy_attr_mark(struct nf_conntrack *dest, 332 const struct nf_conntrack *orig) 333 { 334 dest->mark = orig->mark; 335 } 336 337 static void copy_attr_secmark(struct nf_conntrack *dest, 338 const struct nf_conntrack *orig) 339 { 340 dest->secmark = orig->secmark; 341 } 342 343 static void copy_attr_orig_counter_packets(struct nf_conntrack *dest, 344 const struct nf_conntrack *orig) 345 { 346 dest->counters[__DIR_ORIG].packets = orig->counters[__DIR_ORIG].packets; 347 } 348 349 static void copy_attr_repl_counter_packets(struct nf_conntrack *dest, 350 const struct nf_conntrack *orig) 351 { 352 dest->counters[__DIR_REPL].packets = orig->counters[__DIR_REPL].packets; 353 } 354 355 static void copy_attr_orig_counter_bytes(struct nf_conntrack *dest, 356 const struct nf_conntrack *orig) 357 { 358 dest->counters[__DIR_ORIG].bytes = orig->counters[__DIR_ORIG].bytes; 359 } 360 361 static void copy_attr_repl_counter_bytes(struct nf_conntrack *dest, 362 const struct nf_conntrack *orig) 363 { 364 dest->counters[__DIR_REPL].bytes = orig->counters[__DIR_REPL].bytes; 365 } 366 367 static void copy_attr_status(struct nf_conntrack *dest, 368 const struct nf_conntrack *orig) 369 { 370 dest->status = orig->status; 371 } 372 373 static void copy_attr_use(struct nf_conntrack *dest, 374 const struct nf_conntrack *orig) 375 { 376 dest->use = orig->use; 377 } 378 379 static void copy_attr_id(struct nf_conntrack *dest, 380 const struct nf_conntrack *orig) 381 { 382 dest->id = orig->id; 383 } 384 385 static void copy_attr_orig_cor_pos(struct nf_conntrack *dest, 386 const struct nf_conntrack *orig) 387 { 388 dest->natseq[__DIR_ORIG].correction_pos = 389 orig->natseq[__DIR_ORIG].correction_pos; 390 } 391 392 static void copy_attr_orig_off_bfr(struct nf_conntrack *dest, 393 const struct nf_conntrack *orig) 394 { 395 dest->natseq[__DIR_ORIG].offset_before = 396 orig->natseq[__DIR_ORIG].offset_before; 397 } 398 399 static void copy_attr_orig_off_aft(struct nf_conntrack *dest, 400 const struct nf_conntrack *orig) 401 { 402 dest->natseq[__DIR_ORIG].offset_after = 403 orig->natseq[__DIR_ORIG].offset_after; 404 } 405 406 static void copy_attr_repl_cor_pos(struct nf_conntrack *dest, 407 const struct nf_conntrack *orig) 408 { 409 dest->natseq[__DIR_REPL].correction_pos = 410 orig->natseq[__DIR_REPL].correction_pos; 411 } 412 413 static void copy_attr_repl_off_bfr(struct nf_conntrack *dest, 414 const struct nf_conntrack *orig) 415 { 416 dest->natseq[__DIR_REPL].offset_before = 417 orig->natseq[__DIR_REPL].offset_before; 418 } 419 420 static void copy_attr_repl_off_aft(struct nf_conntrack *dest, 421 const struct nf_conntrack *orig) 422 { 423 dest->natseq[__DIR_REPL].offset_after = 424 orig->natseq[__DIR_REPL].offset_after; 425 } 426 427 static void copy_attr_helper_name(struct nf_conntrack *dest, 428 const struct nf_conntrack *orig) 429 { 430 strncpy(dest->helper_name, orig->helper_name, NFCT_HELPER_NAME_MAX); 431 dest->helper_name[NFCT_HELPER_NAME_MAX-1] = '\0'; 432 } 433 434 static void copy_attr_zone(struct nf_conntrack *dest, 435 const struct nf_conntrack *orig) 436 { 437 dest->zone = orig->zone; 438 } 439 440 static void copy_attr_secctx(struct nf_conntrack *dest, 441 const struct nf_conntrack *orig) 442 { 443 if (dest->secctx) { 444 free(dest->secctx); 445 dest->secctx = NULL; 446 } 447 if (orig->secctx) 448 dest->secctx = strdup(orig->secctx); 449 } 450 451 static void copy_attr_timestamp_start(struct nf_conntrack *dest, 452 const struct nf_conntrack *orig) 453 { 454 dest->timestamp.start = orig->timestamp.start; 455 } 456 457 static void copy_attr_timestamp_stop(struct nf_conntrack *dest, 458 const struct nf_conntrack *orig) 459 { 460 dest->timestamp.stop = orig->timestamp.stop; 461 } 462 463 static void copy_attr_help_info(struct nf_conntrack *dest, 464 const struct nf_conntrack *orig) 465 { 466 if (orig->helper_info == NULL) 467 return; 468 469 if (dest->helper_info != NULL) 470 free(dest->helper_info); 471 472 dest->helper_info = calloc(1, orig->helper_info_len); 473 if (dest->helper_info == NULL) 474 return; 475 476 memcpy(dest->helper_info, orig->helper_info, orig->helper_info_len); 477 } 478 479 static void* do_copy_attr_connlabels(struct nfct_bitmask *dest, 480 const struct nfct_bitmask *orig) 481 { 482 if (orig == NULL) 483 return dest; 484 if (dest) 485 nfct_bitmask_destroy(dest); 486 return nfct_bitmask_clone(orig); 487 } 488 489 static void copy_attr_connlabels(struct nf_conntrack *dest, 490 const struct nf_conntrack *orig) 491 { 492 dest->connlabels = do_copy_attr_connlabels(dest->connlabels, orig->connlabels); 493 } 494 495 static void copy_attr_connlabels_mask(struct nf_conntrack *dest, 496 const struct nf_conntrack *orig) 497 { 498 dest->connlabels_mask = do_copy_attr_connlabels(dest->connlabels_mask, orig->connlabels_mask); 499 } 500 501 const copy_attr copy_attr_array[ATTR_MAX] = { 502 [ATTR_ORIG_IPV4_SRC] = copy_attr_orig_ipv4_src, 503 [ATTR_ORIG_IPV4_DST] = copy_attr_orig_ipv4_dst, 504 [ATTR_REPL_IPV4_SRC] = copy_attr_repl_ipv4_src, 505 [ATTR_REPL_IPV4_DST] = copy_attr_repl_ipv4_dst, 506 [ATTR_ORIG_IPV6_SRC] = copy_attr_orig_ipv6_src, 507 [ATTR_ORIG_IPV6_DST] = copy_attr_orig_ipv6_dst, 508 [ATTR_REPL_IPV6_SRC] = copy_attr_repl_ipv6_src, 509 [ATTR_REPL_IPV6_DST] = copy_attr_repl_ipv6_dst, 510 [ATTR_ORIG_PORT_SRC] = copy_attr_orig_port_src, 511 [ATTR_ORIG_PORT_DST] = copy_attr_orig_port_dst, 512 [ATTR_REPL_PORT_SRC] = copy_attr_repl_port_src, 513 [ATTR_REPL_PORT_DST] = copy_attr_repl_port_dst, 514 [ATTR_ICMP_TYPE] = copy_attr_icmp_type, 515 [ATTR_ICMP_CODE] = copy_attr_icmp_code, 516 [ATTR_ICMP_ID] = copy_attr_icmp_id, 517 [ATTR_ORIG_L3PROTO] = copy_attr_orig_l3proto, 518 [ATTR_REPL_L3PROTO] = copy_attr_repl_l3proto, 519 [ATTR_ORIG_L4PROTO] = copy_attr_orig_l4proto, 520 [ATTR_REPL_L4PROTO] = copy_attr_repl_l4proto, 521 [ATTR_TCP_STATE] = copy_attr_tcp_state, 522 [ATTR_SNAT_IPV4] = copy_attr_snat_ipv4, 523 [ATTR_DNAT_IPV4] = copy_attr_dnat_ipv4, 524 [ATTR_SNAT_PORT] = copy_attr_snat_port, 525 [ATTR_DNAT_PORT] = copy_attr_dnat_port, 526 [ATTR_TIMEOUT] = copy_attr_timeout, 527 [ATTR_MARK] = copy_attr_mark, 528 [ATTR_ORIG_COUNTER_PACKETS] = copy_attr_orig_counter_packets, 529 [ATTR_ORIG_COUNTER_BYTES] = copy_attr_orig_counter_bytes, 530 [ATTR_REPL_COUNTER_PACKETS] = copy_attr_repl_counter_packets, 531 [ATTR_REPL_COUNTER_BYTES] = copy_attr_repl_counter_bytes, 532 [ATTR_USE] = copy_attr_use, 533 [ATTR_ID] = copy_attr_id, 534 [ATTR_STATUS] = copy_attr_status, 535 [ATTR_TCP_FLAGS_ORIG] = copy_attr_tcp_flags_orig, 536 [ATTR_TCP_FLAGS_REPL] = copy_attr_tcp_flags_repl, 537 [ATTR_TCP_MASK_ORIG] = copy_attr_tcp_mask_orig, 538 [ATTR_TCP_MASK_REPL] = copy_attr_tcp_mask_repl, 539 [ATTR_MASTER_IPV4_SRC] = copy_attr_master_ipv4_src, 540 [ATTR_MASTER_IPV4_DST] = copy_attr_master_ipv4_dst, 541 [ATTR_MASTER_IPV6_SRC] = copy_attr_master_ipv6_src, 542 [ATTR_MASTER_IPV6_DST] = copy_attr_master_ipv6_dst, 543 [ATTR_MASTER_PORT_SRC] = copy_attr_master_port_src, 544 [ATTR_MASTER_PORT_DST] = copy_attr_master_port_dst, 545 [ATTR_MASTER_L3PROTO] = copy_attr_master_l3proto, 546 [ATTR_MASTER_L4PROTO] = copy_attr_master_l4proto, 547 [ATTR_SECMARK] = copy_attr_secmark, 548 [ATTR_ORIG_NAT_SEQ_CORRECTION_POS] = copy_attr_orig_cor_pos, 549 [ATTR_ORIG_NAT_SEQ_OFFSET_BEFORE] = copy_attr_orig_off_bfr, 550 [ATTR_ORIG_NAT_SEQ_OFFSET_AFTER] = copy_attr_orig_off_aft, 551 [ATTR_REPL_NAT_SEQ_CORRECTION_POS] = copy_attr_repl_cor_pos, 552 [ATTR_REPL_NAT_SEQ_OFFSET_BEFORE] = copy_attr_repl_off_bfr, 553 [ATTR_REPL_NAT_SEQ_OFFSET_AFTER] = copy_attr_repl_off_aft, 554 [ATTR_SCTP_STATE] = copy_attr_sctp_state, 555 [ATTR_SCTP_VTAG_ORIG] = copy_attr_sctp_vtag_orig, 556 [ATTR_SCTP_VTAG_REPL] = copy_attr_sctp_vtag_repl, 557 [ATTR_HELPER_NAME] = copy_attr_helper_name, 558 [ATTR_DCCP_STATE] = copy_attr_dccp_state, 559 [ATTR_DCCP_ROLE] = copy_attr_dccp_role, 560 [ATTR_DCCP_HANDSHAKE_SEQ] = copy_attr_dccp_handshake_seq, 561 [ATTR_TCP_WSCALE_ORIG] = copy_attr_tcp_wscale_orig, 562 [ATTR_TCP_WSCALE_REPL] = copy_attr_tcp_wscale_repl, 563 [ATTR_ZONE] = copy_attr_zone, 564 [ATTR_ORIG_ZONE] = copy_attr_orig_zone, 565 [ATTR_REPL_ZONE] = copy_attr_repl_zone, 566 [ATTR_SECCTX] = copy_attr_secctx, 567 [ATTR_TIMESTAMP_START] = copy_attr_timestamp_start, 568 [ATTR_TIMESTAMP_STOP] = copy_attr_timestamp_stop, 569 [ATTR_HELPER_INFO] = copy_attr_help_info, 570 [ATTR_CONNLABELS] = copy_attr_connlabels, 571 [ATTR_CONNLABELS_MASK] = copy_attr_connlabels_mask, 572 [ATTR_SNAT_IPV6] = copy_attr_snat_ipv6, 573 [ATTR_DNAT_IPV6] = copy_attr_dnat_ipv6, 574 }; 575 576 /* this is used by nfct_copy() with the NFCT_CP_OVERRIDE flag set. */ 577 void __copy_fast(struct nf_conntrack *ct1, const struct nf_conntrack *ct2) 578 { 579 memcpy(ct1, ct2, sizeof(*ct1)); 580 /* malloc'd attributes: don't free, do copy */ 581 ct1->secctx = NULL; 582 ct1->helper_info = NULL; 583 ct1->connlabels = NULL; 584 ct1->connlabels_mask = NULL; 585 586 copy_attr_secctx(ct1, ct2); 587 copy_attr_help_info(ct1, ct2); 588 copy_attr_connlabels(ct1, ct2); 589 copy_attr_connlabels_mask(ct1, ct2); 590 } 591