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 #include <linux/icmp.h> 12 #include <linux/icmpv6.h> 13 14 static const uint8_t invmap_icmp[] = { 15 [ICMP_ECHO] = ICMP_ECHOREPLY + 1, 16 [ICMP_ECHOREPLY] = ICMP_ECHO + 1, 17 [ICMP_TIMESTAMP] = ICMP_TIMESTAMPREPLY + 1, 18 [ICMP_TIMESTAMPREPLY] = ICMP_TIMESTAMP + 1, 19 [ICMP_INFO_REQUEST] = ICMP_INFO_REPLY + 1, 20 [ICMP_INFO_REPLY] = ICMP_INFO_REQUEST + 1, 21 [ICMP_ADDRESS] = ICMP_ADDRESSREPLY + 1, 22 [ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1 23 }; 24 25 #ifndef ICMPV6_NI_QUERY 26 #define ICMPV6_NI_QUERY 139 27 #endif 28 29 #ifndef ICMPV6_NI_REPLY 30 #define ICMPV6_NI_REPLY 140 31 #endif 32 33 static const uint8_t invmap_icmpv6[] = { 34 [ICMPV6_ECHO_REQUEST - 128] = ICMPV6_ECHO_REPLY + 1, 35 [ICMPV6_ECHO_REPLY - 128] = ICMPV6_ECHO_REQUEST + 1, 36 [ICMPV6_NI_QUERY - 128] = ICMPV6_NI_QUERY + 1, 37 [ICMPV6_NI_REPLY - 128] = ICMPV6_NI_REPLY + 1 38 }; 39 40 static void 41 set_attr_orig_ipv4_src(struct nf_conntrack *ct, const void *value, size_t len) 42 { 43 ct->head.orig.src.v4 = *((uint32_t *) value); 44 } 45 46 static void 47 set_attr_orig_ipv4_dst(struct nf_conntrack *ct, const void *value, size_t len) 48 { 49 ct->head.orig.dst.v4 = *((uint32_t *) value); 50 } 51 52 static void 53 set_attr_repl_ipv4_src(struct nf_conntrack *ct, const void *value, size_t len) 54 { 55 ct->repl.src.v4 = *((uint32_t *) value); 56 } 57 58 static void 59 set_attr_repl_ipv4_dst(struct nf_conntrack *ct, const void *value, size_t len) 60 { 61 ct->repl.dst.v4 = *((uint32_t *) value); 62 } 63 64 static void 65 set_attr_orig_ipv6_src(struct nf_conntrack *ct, const void *value, size_t len) 66 { 67 memcpy(&ct->head.orig.src.v6, value, sizeof(uint32_t)*4); 68 } 69 70 static void 71 set_attr_orig_ipv6_dst(struct nf_conntrack *ct, const void *value, size_t len) 72 { 73 memcpy(&ct->head.orig.dst.v6, value, sizeof(uint32_t)*4); 74 } 75 76 static void 77 set_attr_repl_ipv6_src(struct nf_conntrack *ct, const void *value, size_t len) 78 { 79 memcpy(&ct->repl.src.v6, value, sizeof(uint32_t)*4); 80 } 81 82 static void 83 set_attr_repl_ipv6_dst(struct nf_conntrack *ct, const void *value, size_t len) 84 { 85 memcpy(&ct->repl.dst.v6, value, sizeof(uint32_t)*4); 86 } 87 88 static void 89 set_attr_orig_port_src(struct nf_conntrack *ct, const void *value, size_t len) 90 { 91 ct->head.orig.l4src.all = *((uint16_t *) value); 92 } 93 94 static void 95 set_attr_orig_port_dst(struct nf_conntrack *ct, const void *value, size_t len) 96 { 97 ct->head.orig.l4dst.all = *((uint16_t *) value); 98 } 99 100 static void 101 set_attr_repl_port_src(struct nf_conntrack *ct, const void *value, size_t len) 102 { 103 ct->repl.l4src.all = *((uint16_t *) value); 104 } 105 106 static void 107 set_attr_repl_port_dst(struct nf_conntrack *ct, const void *value, size_t len) 108 { 109 ct->repl.l4dst.all = *((uint16_t *) value); 110 } 111 112 static void 113 set_attr_orig_zone(struct nf_conntrack *ct, const void *value, size_t len) 114 { 115 ct->head.orig.zone = *((uint16_t *) value); 116 } 117 118 static void 119 set_attr_repl_zone(struct nf_conntrack *ct, const void *value, size_t len) 120 { 121 ct->repl.zone = *((uint16_t *) value); 122 } 123 124 static void 125 set_attr_icmp_type(struct nf_conntrack *ct, const void *value, size_t len) 126 { 127 uint8_t rtype; 128 129 ct->head.orig.l4dst.icmp.type = *((uint8_t *) value); 130 131 switch(ct->head.orig.l3protonum) { 132 case AF_INET: 133 rtype = invmap_icmp[*((uint8_t *) value)]; 134 break; 135 136 case AF_INET6: 137 rtype = invmap_icmpv6[*((uint8_t *) value) - 128]; 138 break; 139 140 default: 141 rtype = 0; /* not found */ 142 } 143 144 if (rtype) 145 ct->repl.l4dst.icmp.type = rtype - 1; 146 else 147 ct->repl.l4dst.icmp.type = 255; /* will fail with -EINVAL */ 148 149 } 150 151 static void 152 set_attr_icmp_code(struct nf_conntrack *ct, const void *value, size_t len) 153 { 154 ct->head.orig.l4dst.icmp.code = *((uint8_t *) value); 155 ct->repl.l4dst.icmp.code = *((uint8_t *) value); 156 } 157 158 static void 159 set_attr_icmp_id(struct nf_conntrack *ct, const void *value, size_t len) 160 { 161 ct->head.orig.l4src.icmp.id = *((uint16_t *) value); 162 ct->repl.l4src.icmp.id = *((uint16_t *) value); 163 } 164 165 static void 166 set_attr_orig_l3proto(struct nf_conntrack *ct, const void *value, size_t len) 167 { 168 ct->head.orig.l3protonum = *((uint8_t *) value); 169 } 170 171 static void 172 set_attr_repl_l3proto(struct nf_conntrack *ct, const void *value, size_t len) 173 { 174 ct->repl.l3protonum = *((uint8_t *) value); 175 } 176 177 static void 178 set_attr_orig_l4proto(struct nf_conntrack *ct, const void *value, size_t len) 179 { 180 ct->head.orig.protonum = *((uint8_t *) value); 181 } 182 183 static void 184 set_attr_repl_l4proto(struct nf_conntrack *ct, const void *value, size_t len) 185 { 186 ct->repl.protonum = *((uint8_t *) value); 187 } 188 189 static void 190 set_attr_tcp_state(struct nf_conntrack *ct, const void *value, size_t len) 191 { 192 ct->protoinfo.tcp.state = *((uint8_t *) value); 193 } 194 195 static void 196 set_attr_tcp_flags_orig(struct nf_conntrack *ct, const void *value, size_t len) 197 { 198 ct->protoinfo.tcp.flags[__DIR_ORIG].value = *((uint8_t *) value); 199 } 200 201 static void 202 set_attr_tcp_mask_orig(struct nf_conntrack *ct, const void *value, size_t len) 203 { 204 ct->protoinfo.tcp.flags[__DIR_ORIG].mask = *((uint8_t *) value); 205 } 206 207 static void 208 set_attr_tcp_flags_repl(struct nf_conntrack *ct, const void *value, size_t len) 209 { 210 ct->protoinfo.tcp.flags[__DIR_REPL].value = *((uint8_t *) value); 211 } 212 213 static void 214 set_attr_tcp_mask_repl(struct nf_conntrack *ct, const void *value, size_t len) 215 { 216 ct->protoinfo.tcp.flags[__DIR_REPL].mask = *((uint8_t *) value); 217 } 218 219 static void 220 set_attr_sctp_state(struct nf_conntrack *ct, const void *value, size_t len) 221 { 222 ct->protoinfo.sctp.state = *((uint8_t *) value); 223 } 224 225 static void 226 set_attr_sctp_vtag_orig(struct nf_conntrack *ct, const void *value, size_t len) 227 { 228 ct->protoinfo.sctp.vtag[__DIR_ORIG] = *((uint32_t *) value); 229 } 230 231 static void 232 set_attr_sctp_vtag_repl(struct nf_conntrack *ct, const void *value, size_t len) 233 { 234 ct->protoinfo.sctp.vtag[__DIR_REPL] = *((uint32_t *) value); 235 } 236 237 static void 238 set_attr_snat_ipv4(struct nf_conntrack *ct, const void *value, size_t len) 239 { 240 ct->snat.min_ip.v4 = ct->snat.max_ip.v4 = *((uint32_t *) value); 241 } 242 243 static void 244 set_attr_dnat_ipv4(struct nf_conntrack *ct, const void *value, size_t len) 245 { 246 ct->dnat.min_ip.v4 = ct->dnat.max_ip.v4 = *((uint32_t *) value); 247 } 248 249 static void 250 set_attr_snat_ipv6(struct nf_conntrack *ct, const void *value, size_t len) 251 { 252 memcpy(&ct->snat.min_ip.v6, value, sizeof(struct in6_addr)); 253 memcpy(&ct->snat.max_ip.v6, value, sizeof(struct in6_addr)); 254 } 255 256 static void 257 set_attr_dnat_ipv6(struct nf_conntrack *ct, const void *value, size_t len) 258 { 259 memcpy(&ct->dnat.min_ip.v6, value, sizeof(struct in6_addr)); 260 memcpy(&ct->dnat.max_ip.v6, value, sizeof(struct in6_addr)); 261 } 262 263 static void 264 set_attr_snat_port(struct nf_conntrack *ct, const void *value, size_t len) 265 { 266 ct->snat.l4min.all = ct->snat.l4max.all = *((uint16_t *) value); 267 } 268 269 static void 270 set_attr_dnat_port(struct nf_conntrack *ct, const void *value, size_t len) 271 { 272 ct->dnat.l4min.all = ct->dnat.l4max.all = *((uint16_t *) value); 273 } 274 275 static void 276 set_attr_timeout(struct nf_conntrack *ct, const void *value, size_t len) 277 { 278 ct->timeout = *((uint32_t *) value); 279 } 280 281 static void 282 set_attr_mark(struct nf_conntrack *ct, const void *value, size_t len) 283 { 284 ct->mark = *((uint32_t *) value); 285 } 286 287 static void 288 set_attr_secmark(struct nf_conntrack *ct, const void *value, size_t len) 289 { 290 ct->secmark = *((uint32_t *) value); 291 } 292 293 static void 294 set_attr_status(struct nf_conntrack *ct, const void *value, size_t len) 295 { 296 ct->status = *((uint32_t *) value); 297 } 298 299 static void 300 set_attr_id(struct nf_conntrack *ct, const void *value, size_t len) 301 { 302 ct->id = *((uint32_t *) value); 303 } 304 305 static void 306 set_attr_master_ipv4_src(struct nf_conntrack *ct, const void *value, size_t len) 307 { 308 ct->master.src.v4 = *((uint32_t *) value); 309 } 310 311 static void 312 set_attr_master_ipv4_dst(struct nf_conntrack *ct, const void *value, size_t len) 313 { 314 ct->master.dst.v4 = *((uint32_t *) value); 315 } 316 317 static void 318 set_attr_master_ipv6_src(struct nf_conntrack *ct, const void *value, size_t len) 319 { 320 memcpy(&ct->master.src.v6, value, sizeof(uint32_t)*4); 321 } 322 323 static void 324 set_attr_master_ipv6_dst(struct nf_conntrack *ct, const void *value, size_t len) 325 { 326 memcpy(&ct->master.dst.v6, value, sizeof(uint32_t)*4); 327 } 328 329 static void 330 set_attr_master_port_src(struct nf_conntrack *ct, const void *value, size_t len) 331 { 332 ct->master.l4src.all = *((uint16_t *) value); 333 } 334 335 static void 336 set_attr_master_port_dst(struct nf_conntrack *ct, const void *value, size_t len) 337 { 338 ct->master.l4dst.all = *((uint16_t *) value); 339 } 340 341 static void 342 set_attr_master_l3proto(struct nf_conntrack *ct, const void *value, size_t len) 343 { 344 ct->master.l3protonum = *((uint8_t *) value); 345 } 346 347 static void 348 set_attr_master_l4proto(struct nf_conntrack *ct, const void *value, size_t len) 349 { 350 ct->master.protonum = *((uint8_t *) value); 351 } 352 353 static void 354 set_attr_orig_cor_pos(struct nf_conntrack *ct, const void *value, size_t len) 355 { 356 ct->natseq[__DIR_ORIG].correction_pos = *((uint32_t *) value); 357 } 358 359 static void 360 set_attr_orig_off_bfr(struct nf_conntrack *ct, const void *value, size_t len) 361 { 362 ct->natseq[__DIR_ORIG].offset_before = *((uint32_t *) value); 363 } 364 365 static void 366 set_attr_orig_off_aft(struct nf_conntrack *ct, const void *value, size_t len) 367 { 368 ct->natseq[__DIR_ORIG].offset_after = *((uint32_t *) value); 369 } 370 371 static void 372 set_attr_repl_cor_pos(struct nf_conntrack *ct, const void *value, size_t len) 373 { 374 ct->natseq[__DIR_REPL].correction_pos = *((uint32_t *) value); 375 } 376 377 static void 378 set_attr_repl_off_bfr(struct nf_conntrack *ct, const void *value, size_t len) 379 { 380 ct->natseq[__DIR_REPL].offset_before = *((uint32_t *) value); 381 } 382 383 static void 384 set_attr_repl_off_aft(struct nf_conntrack *ct, const void *value, size_t len) 385 { 386 ct->natseq[__DIR_REPL].offset_after = *((uint32_t *) value); 387 } 388 389 static void 390 set_attr_helper_name(struct nf_conntrack *ct, const void *value, size_t len) 391 { 392 strncpy(ct->helper_name, value, NFCT_HELPER_NAME_MAX); 393 ct->helper_name[NFCT_HELPER_NAME_MAX-1] = '\0'; 394 } 395 396 static void 397 set_attr_dccp_state(struct nf_conntrack *ct, const void *value, size_t len) 398 { 399 ct->protoinfo.dccp.state = *((uint8_t *) value); 400 } 401 402 static void 403 set_attr_dccp_role(struct nf_conntrack *ct, const void *value, size_t len) 404 { 405 ct->protoinfo.dccp.role = *((uint8_t *) value); 406 } 407 408 static void 409 set_attr_dccp_handshake_seq(struct nf_conntrack *ct, const void *value, 410 size_t len) 411 { 412 ct->protoinfo.dccp.handshake_seq = *((uint64_t *) value); 413 } 414 415 static void 416 set_attr_tcp_wscale_orig(struct nf_conntrack *ct, const void *value, size_t len) 417 { 418 ct->protoinfo.tcp.wscale[__DIR_ORIG] = *((uint8_t *) value); 419 } 420 421 static void 422 set_attr_tcp_wscale_repl(struct nf_conntrack *ct, const void *value, size_t len) 423 { 424 ct->protoinfo.tcp.wscale[__DIR_REPL] = *((uint8_t *) value); 425 } 426 427 static void 428 set_attr_zone(struct nf_conntrack *ct, const void *value, size_t len) 429 { 430 ct->zone = *((uint16_t *) value); 431 } 432 433 static void 434 set_attr_helper_info(struct nf_conntrack *ct, const void *value, size_t len) 435 { 436 if (ct->helper_info == NULL) { 437 retry: 438 ct->helper_info = calloc(1, len); 439 if (ct->helper_info == NULL) 440 return; 441 442 memcpy(ct->helper_info, value, len); 443 } else { 444 free(ct->helper_info); 445 goto retry; 446 } 447 } 448 449 static void 450 do_set_attr_connlabels(struct nfct_bitmask *current, const void *value) 451 { 452 if (current && current != value) 453 nfct_bitmask_destroy(current); 454 } 455 456 static void 457 set_attr_connlabels(struct nf_conntrack *ct, const void *value, size_t len) 458 { 459 do_set_attr_connlabels(ct->connlabels, value); 460 ct->connlabels = (void *) value; 461 } 462 463 static void 464 set_attr_connlabels_mask(struct nf_conntrack *ct, const void *value, size_t len) 465 { 466 do_set_attr_connlabels(ct->connlabels_mask, value); 467 ct->connlabels_mask = (void *) value; 468 } 469 470 static void 471 set_attr_do_nothing(struct nf_conntrack *ct, const void *value, size_t len) {} 472 473 const set_attr set_attr_array[ATTR_MAX] = { 474 [ATTR_ORIG_IPV4_SRC] = set_attr_orig_ipv4_src, 475 [ATTR_ORIG_IPV4_DST] = set_attr_orig_ipv4_dst, 476 [ATTR_REPL_IPV4_SRC] = set_attr_repl_ipv4_src, 477 [ATTR_REPL_IPV4_DST] = set_attr_repl_ipv4_dst, 478 [ATTR_ORIG_IPV6_SRC] = set_attr_orig_ipv6_src, 479 [ATTR_ORIG_IPV6_DST] = set_attr_orig_ipv6_dst, 480 [ATTR_REPL_IPV6_SRC] = set_attr_repl_ipv6_src, 481 [ATTR_REPL_IPV6_DST] = set_attr_repl_ipv6_dst, 482 [ATTR_ORIG_PORT_SRC] = set_attr_orig_port_src, 483 [ATTR_ORIG_PORT_DST] = set_attr_orig_port_dst, 484 [ATTR_REPL_PORT_SRC] = set_attr_repl_port_src, 485 [ATTR_REPL_PORT_DST] = set_attr_repl_port_dst, 486 [ATTR_ICMP_TYPE] = set_attr_icmp_type, 487 [ATTR_ICMP_CODE] = set_attr_icmp_code, 488 [ATTR_ICMP_ID] = set_attr_icmp_id, 489 [ATTR_ORIG_L3PROTO] = set_attr_orig_l3proto, 490 [ATTR_REPL_L3PROTO] = set_attr_repl_l3proto, 491 [ATTR_ORIG_L4PROTO] = set_attr_orig_l4proto, 492 [ATTR_REPL_L4PROTO] = set_attr_repl_l4proto, 493 [ATTR_TCP_STATE] = set_attr_tcp_state, 494 [ATTR_SNAT_IPV4] = set_attr_snat_ipv4, 495 [ATTR_DNAT_IPV4] = set_attr_dnat_ipv4, 496 [ATTR_SNAT_PORT] = set_attr_snat_port, 497 [ATTR_DNAT_PORT] = set_attr_dnat_port, 498 [ATTR_TIMEOUT] = set_attr_timeout, 499 [ATTR_MARK] = set_attr_mark, 500 [ATTR_ORIG_COUNTER_PACKETS] = set_attr_do_nothing, 501 [ATTR_REPL_COUNTER_PACKETS] = set_attr_do_nothing, 502 [ATTR_ORIG_COUNTER_BYTES] = set_attr_do_nothing, 503 [ATTR_REPL_COUNTER_BYTES] = set_attr_do_nothing, 504 [ATTR_USE] = set_attr_do_nothing, 505 [ATTR_ID] = set_attr_id, 506 [ATTR_STATUS] = set_attr_status, 507 [ATTR_TCP_FLAGS_ORIG] = set_attr_tcp_flags_orig, 508 [ATTR_TCP_FLAGS_REPL] = set_attr_tcp_flags_repl, 509 [ATTR_TCP_MASK_ORIG] = set_attr_tcp_mask_orig, 510 [ATTR_TCP_MASK_REPL] = set_attr_tcp_mask_repl, 511 [ATTR_MASTER_IPV4_SRC] = set_attr_master_ipv4_src, 512 [ATTR_MASTER_IPV4_DST] = set_attr_master_ipv4_dst, 513 [ATTR_MASTER_IPV6_SRC] = set_attr_master_ipv6_src, 514 [ATTR_MASTER_IPV6_DST] = set_attr_master_ipv6_dst, 515 [ATTR_MASTER_PORT_SRC] = set_attr_master_port_src, 516 [ATTR_MASTER_PORT_DST] = set_attr_master_port_dst, 517 [ATTR_MASTER_L3PROTO] = set_attr_master_l3proto, 518 [ATTR_MASTER_L4PROTO] = set_attr_master_l4proto, 519 [ATTR_SECMARK] = set_attr_secmark, 520 [ATTR_ORIG_NAT_SEQ_CORRECTION_POS] = set_attr_orig_cor_pos, 521 [ATTR_ORIG_NAT_SEQ_OFFSET_BEFORE] = set_attr_orig_off_bfr, 522 [ATTR_ORIG_NAT_SEQ_OFFSET_AFTER] = set_attr_orig_off_aft, 523 [ATTR_REPL_NAT_SEQ_CORRECTION_POS] = set_attr_repl_cor_pos, 524 [ATTR_REPL_NAT_SEQ_OFFSET_BEFORE] = set_attr_repl_off_bfr, 525 [ATTR_REPL_NAT_SEQ_OFFSET_AFTER] = set_attr_repl_off_aft, 526 [ATTR_SCTP_STATE] = set_attr_sctp_state, 527 [ATTR_SCTP_VTAG_ORIG] = set_attr_sctp_vtag_orig, 528 [ATTR_SCTP_VTAG_REPL] = set_attr_sctp_vtag_repl, 529 [ATTR_HELPER_NAME] = set_attr_helper_name, 530 [ATTR_DCCP_STATE] = set_attr_dccp_state, 531 [ATTR_DCCP_ROLE] = set_attr_dccp_role, 532 [ATTR_DCCP_HANDSHAKE_SEQ] = set_attr_dccp_handshake_seq, 533 [ATTR_TCP_WSCALE_ORIG] = set_attr_tcp_wscale_orig, 534 [ATTR_TCP_WSCALE_REPL] = set_attr_tcp_wscale_repl, 535 [ATTR_ZONE] = set_attr_zone, 536 [ATTR_ORIG_ZONE] = set_attr_orig_zone, 537 [ATTR_REPL_ZONE] = set_attr_repl_zone, 538 [ATTR_SECCTX] = set_attr_do_nothing, 539 [ATTR_TIMESTAMP_START] = set_attr_do_nothing, 540 [ATTR_TIMESTAMP_STOP] = set_attr_do_nothing, 541 [ATTR_HELPER_INFO] = set_attr_helper_info, 542 [ATTR_CONNLABELS] = set_attr_connlabels, 543 [ATTR_CONNLABELS_MASK] = set_attr_connlabels_mask, 544 [ATTR_SNAT_IPV6] = set_attr_snat_ipv6, 545 [ATTR_DNAT_IPV6] = set_attr_dnat_ipv6, 546 }; 547