1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * H.323 extension for NAT alteration. 4 * 5 * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net> 6 * Copyright (c) 2006-2012 Patrick McHardy <kaber@trash.net> 7 * 8 * Based on the 'brute force' H.323 NAT module by 9 * Jozsef Kadlecsik <kadlec@netfilter.org> 10 */ 11 12 #include <linux/module.h> 13 #include <linux/tcp.h> 14 #include <net/tcp.h> 15 16 #include <net/netfilter/nf_nat.h> 17 #include <net/netfilter/nf_nat_helper.h> 18 #include <net/netfilter/nf_conntrack_helper.h> 19 #include <net/netfilter/nf_conntrack_expect.h> 20 #include <linux/netfilter/nf_conntrack_h323.h> 21 22 /****************************************************************************/ 23 static int set_addr(struct sk_buff *skb, unsigned int protoff, 24 unsigned char **data, int dataoff, 25 unsigned int addroff, __be32 ip, __be16 port) 26 { 27 enum ip_conntrack_info ctinfo; 28 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 29 struct { 30 __be32 ip; 31 __be16 port; 32 } __attribute__ ((__packed__)) buf; 33 const struct tcphdr *th; 34 struct tcphdr _tcph; 35 36 buf.ip = ip; 37 buf.port = port; 38 addroff += dataoff; 39 40 if (ip_hdr(skb)->protocol == IPPROTO_TCP) { 41 if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, 42 protoff, addroff, sizeof(buf), 43 (char *) &buf, sizeof(buf))) { 44 net_notice_ratelimited("nf_nat_h323: nf_nat_mangle_tcp_packet error\n"); 45 return -1; 46 } 47 48 /* Relocate data pointer */ 49 th = skb_header_pointer(skb, ip_hdrlen(skb), 50 sizeof(_tcph), &_tcph); 51 if (th == NULL) 52 return -1; 53 *data = skb->data + ip_hdrlen(skb) + th->doff * 4 + dataoff; 54 } else { 55 if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, 56 protoff, addroff, sizeof(buf), 57 (char *) &buf, sizeof(buf))) { 58 net_notice_ratelimited("nf_nat_h323: nf_nat_mangle_udp_packet error\n"); 59 return -1; 60 } 61 /* nf_nat_mangle_udp_packet uses skb_ensure_writable() to copy 62 * or pull everything in a linear buffer, so we can safely 63 * use the skb pointers now */ 64 *data = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr); 65 } 66 67 return 0; 68 } 69 70 /****************************************************************************/ 71 static int set_h225_addr(struct sk_buff *skb, unsigned int protoff, 72 unsigned char **data, int dataoff, 73 TransportAddress *taddr, 74 union nf_inet_addr *addr, __be16 port) 75 { 76 return set_addr(skb, protoff, data, dataoff, taddr->ipAddress.ip, 77 addr->ip, port); 78 } 79 80 /****************************************************************************/ 81 static int set_h245_addr(struct sk_buff *skb, unsigned protoff, 82 unsigned char **data, int dataoff, 83 H245_TransportAddress *taddr, 84 union nf_inet_addr *addr, __be16 port) 85 { 86 return set_addr(skb, protoff, data, dataoff, 87 taddr->unicastAddress.iPAddress.network, 88 addr->ip, port); 89 } 90 91 /****************************************************************************/ 92 static int set_sig_addr(struct sk_buff *skb, struct nf_conn *ct, 93 enum ip_conntrack_info ctinfo, 94 unsigned int protoff, unsigned char **data, 95 TransportAddress *taddr, int count) 96 { 97 const struct nf_ct_h323_master *info = nfct_help_data(ct); 98 int dir = CTINFO2DIR(ctinfo); 99 int i; 100 __be16 port; 101 union nf_inet_addr addr; 102 103 for (i = 0; i < count; i++) { 104 if (get_h225_addr(ct, *data, &taddr[i], &addr, &port)) { 105 if (addr.ip == ct->tuplehash[dir].tuple.src.u3.ip && 106 port == info->sig_port[dir]) { 107 /* GW->GK */ 108 109 /* Fix for Gnomemeeting */ 110 if (i > 0 && 111 get_h225_addr(ct, *data, &taddr[0], 112 &addr, &port) && 113 (ntohl(addr.ip) & 0xff000000) == 0x7f000000) 114 i = 0; 115 116 pr_debug("nf_nat_ras: set signal address %pI4:%hu->%pI4:%hu\n", 117 &addr.ip, port, 118 &ct->tuplehash[!dir].tuple.dst.u3.ip, 119 info->sig_port[!dir]); 120 return set_h225_addr(skb, protoff, data, 0, 121 &taddr[i], 122 &ct->tuplehash[!dir]. 123 tuple.dst.u3, 124 info->sig_port[!dir]); 125 } else if (addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip && 126 port == info->sig_port[dir]) { 127 /* GK->GW */ 128 pr_debug("nf_nat_ras: set signal address %pI4:%hu->%pI4:%hu\n", 129 &addr.ip, port, 130 &ct->tuplehash[!dir].tuple.src.u3.ip, 131 info->sig_port[!dir]); 132 return set_h225_addr(skb, protoff, data, 0, 133 &taddr[i], 134 &ct->tuplehash[!dir]. 135 tuple.src.u3, 136 info->sig_port[!dir]); 137 } 138 } 139 } 140 141 return 0; 142 } 143 144 /****************************************************************************/ 145 static int set_ras_addr(struct sk_buff *skb, struct nf_conn *ct, 146 enum ip_conntrack_info ctinfo, 147 unsigned int protoff, unsigned char **data, 148 TransportAddress *taddr, int count) 149 { 150 int dir = CTINFO2DIR(ctinfo); 151 int i; 152 __be16 port; 153 union nf_inet_addr addr; 154 155 for (i = 0; i < count; i++) { 156 if (get_h225_addr(ct, *data, &taddr[i], &addr, &port) && 157 addr.ip == ct->tuplehash[dir].tuple.src.u3.ip && 158 port == ct->tuplehash[dir].tuple.src.u.udp.port) { 159 pr_debug("nf_nat_ras: set rasAddress %pI4:%hu->%pI4:%hu\n", 160 &addr.ip, ntohs(port), 161 &ct->tuplehash[!dir].tuple.dst.u3.ip, 162 ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port)); 163 return set_h225_addr(skb, protoff, data, 0, &taddr[i], 164 &ct->tuplehash[!dir].tuple.dst.u3, 165 ct->tuplehash[!dir].tuple. 166 dst.u.udp.port); 167 } 168 } 169 170 return 0; 171 } 172 173 /****************************************************************************/ 174 static int nat_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct, 175 enum ip_conntrack_info ctinfo, 176 unsigned int protoff, unsigned char **data, int dataoff, 177 H245_TransportAddress *taddr, 178 __be16 port, __be16 rtp_port, 179 struct nf_conntrack_expect *rtp_exp, 180 struct nf_conntrack_expect *rtcp_exp) 181 { 182 struct nf_ct_h323_master *info = nfct_help_data(ct); 183 int dir = CTINFO2DIR(ctinfo); 184 int i; 185 u_int16_t nated_port; 186 187 /* Set expectations for NAT */ 188 rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port; 189 rtp_exp->expectfn = nf_nat_follow_master; 190 rtp_exp->dir = !dir; 191 rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port; 192 rtcp_exp->expectfn = nf_nat_follow_master; 193 rtcp_exp->dir = !dir; 194 195 /* Lookup existing expects */ 196 for (i = 0; i < H323_RTP_CHANNEL_MAX; i++) { 197 if (info->rtp_port[i][dir] == rtp_port) { 198 /* Expected */ 199 200 /* Use allocated ports first. This will refresh 201 * the expects */ 202 rtp_exp->tuple.dst.u.udp.port = info->rtp_port[i][dir]; 203 rtcp_exp->tuple.dst.u.udp.port = 204 htons(ntohs(info->rtp_port[i][dir]) + 1); 205 break; 206 } else if (info->rtp_port[i][dir] == 0) { 207 /* Not expected */ 208 break; 209 } 210 } 211 212 /* Run out of expectations */ 213 if (i >= H323_RTP_CHANNEL_MAX) { 214 net_notice_ratelimited("nf_nat_h323: out of expectations\n"); 215 return 0; 216 } 217 218 /* Try to get a pair of ports. */ 219 for (nated_port = ntohs(rtp_exp->tuple.dst.u.udp.port); 220 nated_port != 0; nated_port += 2) { 221 int ret; 222 223 rtp_exp->tuple.dst.u.udp.port = htons(nated_port); 224 ret = nf_ct_expect_related(rtp_exp, 0); 225 if (ret == 0) { 226 rtcp_exp->tuple.dst.u.udp.port = 227 htons(nated_port + 1); 228 ret = nf_ct_expect_related(rtcp_exp, 0); 229 if (ret == 0) 230 break; 231 else if (ret == -EBUSY) { 232 nf_ct_unexpect_related(rtp_exp); 233 continue; 234 } else if (ret < 0) { 235 nf_ct_unexpect_related(rtp_exp); 236 nated_port = 0; 237 break; 238 } 239 } else if (ret != -EBUSY) { 240 nated_port = 0; 241 break; 242 } 243 } 244 245 if (nated_port == 0) { /* No port available */ 246 net_notice_ratelimited("nf_nat_h323: out of RTP ports\n"); 247 return 0; 248 } 249 250 /* Modify signal */ 251 if (set_h245_addr(skb, protoff, data, dataoff, taddr, 252 &ct->tuplehash[!dir].tuple.dst.u3, 253 htons((port & htons(1)) ? nated_port + 1 : 254 nated_port))) { 255 nf_ct_unexpect_related(rtp_exp); 256 nf_ct_unexpect_related(rtcp_exp); 257 return -1; 258 } 259 260 /* Save ports */ 261 info->rtp_port[i][dir] = rtp_port; 262 info->rtp_port[i][!dir] = htons(nated_port); 263 264 /* Success */ 265 pr_debug("nf_nat_h323: expect RTP %pI4:%hu->%pI4:%hu\n", 266 &rtp_exp->tuple.src.u3.ip, 267 ntohs(rtp_exp->tuple.src.u.udp.port), 268 &rtp_exp->tuple.dst.u3.ip, 269 ntohs(rtp_exp->tuple.dst.u.udp.port)); 270 pr_debug("nf_nat_h323: expect RTCP %pI4:%hu->%pI4:%hu\n", 271 &rtcp_exp->tuple.src.u3.ip, 272 ntohs(rtcp_exp->tuple.src.u.udp.port), 273 &rtcp_exp->tuple.dst.u3.ip, 274 ntohs(rtcp_exp->tuple.dst.u.udp.port)); 275 276 return 0; 277 } 278 279 /****************************************************************************/ 280 static int nat_t120(struct sk_buff *skb, struct nf_conn *ct, 281 enum ip_conntrack_info ctinfo, 282 unsigned int protoff, unsigned char **data, int dataoff, 283 H245_TransportAddress *taddr, __be16 port, 284 struct nf_conntrack_expect *exp) 285 { 286 int dir = CTINFO2DIR(ctinfo); 287 u_int16_t nated_port = ntohs(port); 288 289 /* Set expectations for NAT */ 290 exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port; 291 exp->expectfn = nf_nat_follow_master; 292 exp->dir = !dir; 293 294 /* Try to get same port: if not, try to change it. */ 295 for (; nated_port != 0; nated_port++) { 296 int ret; 297 298 exp->tuple.dst.u.tcp.port = htons(nated_port); 299 ret = nf_ct_expect_related(exp, 0); 300 if (ret == 0) 301 break; 302 else if (ret != -EBUSY) { 303 nated_port = 0; 304 break; 305 } 306 } 307 308 if (nated_port == 0) { /* No port available */ 309 net_notice_ratelimited("nf_nat_h323: out of TCP ports\n"); 310 return 0; 311 } 312 313 /* Modify signal */ 314 if (set_h245_addr(skb, protoff, data, dataoff, taddr, 315 &ct->tuplehash[!dir].tuple.dst.u3, 316 htons(nated_port)) < 0) { 317 nf_ct_unexpect_related(exp); 318 return -1; 319 } 320 321 pr_debug("nf_nat_h323: expect T.120 %pI4:%hu->%pI4:%hu\n", 322 &exp->tuple.src.u3.ip, 323 ntohs(exp->tuple.src.u.tcp.port), 324 &exp->tuple.dst.u3.ip, 325 ntohs(exp->tuple.dst.u.tcp.port)); 326 327 return 0; 328 } 329 330 /****************************************************************************/ 331 static int nat_h245(struct sk_buff *skb, struct nf_conn *ct, 332 enum ip_conntrack_info ctinfo, 333 unsigned int protoff, unsigned char **data, int dataoff, 334 TransportAddress *taddr, __be16 port, 335 struct nf_conntrack_expect *exp) 336 { 337 struct nf_ct_h323_master *info = nfct_help_data(ct); 338 int dir = CTINFO2DIR(ctinfo); 339 u_int16_t nated_port = ntohs(port); 340 341 /* Set expectations for NAT */ 342 exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port; 343 exp->expectfn = nf_nat_follow_master; 344 exp->dir = !dir; 345 346 /* Check existing expects */ 347 if (info->sig_port[dir] == port) 348 nated_port = ntohs(info->sig_port[!dir]); 349 350 /* Try to get same port: if not, try to change it. */ 351 for (; nated_port != 0; nated_port++) { 352 int ret; 353 354 exp->tuple.dst.u.tcp.port = htons(nated_port); 355 ret = nf_ct_expect_related(exp, 0); 356 if (ret == 0) 357 break; 358 else if (ret != -EBUSY) { 359 nated_port = 0; 360 break; 361 } 362 } 363 364 if (nated_port == 0) { /* No port available */ 365 net_notice_ratelimited("nf_nat_q931: out of TCP ports\n"); 366 return 0; 367 } 368 369 /* Modify signal */ 370 if (set_h225_addr(skb, protoff, data, dataoff, taddr, 371 &ct->tuplehash[!dir].tuple.dst.u3, 372 htons(nated_port))) { 373 nf_ct_unexpect_related(exp); 374 return -1; 375 } 376 377 /* Save ports */ 378 info->sig_port[dir] = port; 379 info->sig_port[!dir] = htons(nated_port); 380 381 pr_debug("nf_nat_q931: expect H.245 %pI4:%hu->%pI4:%hu\n", 382 &exp->tuple.src.u3.ip, 383 ntohs(exp->tuple.src.u.tcp.port), 384 &exp->tuple.dst.u3.ip, 385 ntohs(exp->tuple.dst.u.tcp.port)); 386 387 return 0; 388 } 389 390 /**************************************************************************** 391 * This conntrack expect function replaces nf_conntrack_q931_expect() 392 * which was set by nf_conntrack_h323.c. 393 ****************************************************************************/ 394 static void ip_nat_q931_expect(struct nf_conn *new, 395 struct nf_conntrack_expect *this) 396 { 397 struct nf_nat_range2 range; 398 399 if (this->tuple.src.u3.ip != 0) { /* Only accept calls from GK */ 400 nf_nat_follow_master(new, this); 401 return; 402 } 403 404 /* This must be a fresh one. */ 405 BUG_ON(new->status & IPS_NAT_DONE_MASK); 406 407 /* Change src to where master sends to */ 408 range.flags = NF_NAT_RANGE_MAP_IPS; 409 range.min_addr = range.max_addr = 410 new->tuplehash[!this->dir].tuple.src.u3; 411 nf_nat_setup_info(new, &range, NF_NAT_MANIP_SRC); 412 413 /* For DST manip, map port here to where it's expected. */ 414 range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED); 415 range.min_proto = range.max_proto = this->saved_proto; 416 range.min_addr = range.max_addr = 417 new->master->tuplehash[!this->dir].tuple.src.u3; 418 nf_nat_setup_info(new, &range, NF_NAT_MANIP_DST); 419 } 420 421 /****************************************************************************/ 422 static int nat_q931(struct sk_buff *skb, struct nf_conn *ct, 423 enum ip_conntrack_info ctinfo, 424 unsigned int protoff, unsigned char **data, 425 TransportAddress *taddr, int idx, 426 __be16 port, struct nf_conntrack_expect *exp) 427 { 428 struct nf_ct_h323_master *info = nfct_help_data(ct); 429 int dir = CTINFO2DIR(ctinfo); 430 u_int16_t nated_port = ntohs(port); 431 union nf_inet_addr addr; 432 433 /* Set expectations for NAT */ 434 exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port; 435 exp->expectfn = ip_nat_q931_expect; 436 exp->dir = !dir; 437 438 /* Check existing expects */ 439 if (info->sig_port[dir] == port) 440 nated_port = ntohs(info->sig_port[!dir]); 441 442 /* Try to get same port: if not, try to change it. */ 443 for (; nated_port != 0; nated_port++) { 444 int ret; 445 446 exp->tuple.dst.u.tcp.port = htons(nated_port); 447 ret = nf_ct_expect_related(exp, 0); 448 if (ret == 0) 449 break; 450 else if (ret != -EBUSY) { 451 nated_port = 0; 452 break; 453 } 454 } 455 456 if (nated_port == 0) { /* No port available */ 457 net_notice_ratelimited("nf_nat_ras: out of TCP ports\n"); 458 return 0; 459 } 460 461 /* Modify signal */ 462 if (set_h225_addr(skb, protoff, data, 0, &taddr[idx], 463 &ct->tuplehash[!dir].tuple.dst.u3, 464 htons(nated_port))) { 465 nf_ct_unexpect_related(exp); 466 return -1; 467 } 468 469 /* Save ports */ 470 info->sig_port[dir] = port; 471 info->sig_port[!dir] = htons(nated_port); 472 473 /* Fix for Gnomemeeting */ 474 if (idx > 0 && 475 get_h225_addr(ct, *data, &taddr[0], &addr, &port) && 476 (ntohl(addr.ip) & 0xff000000) == 0x7f000000) { 477 if (set_h225_addr(skb, protoff, data, 0, &taddr[0], 478 &ct->tuplehash[!dir].tuple.dst.u3, 479 info->sig_port[!dir])) { 480 nf_ct_unexpect_related(exp); 481 return -1; 482 } 483 } 484 485 /* Success */ 486 pr_debug("nf_nat_ras: expect Q.931 %pI4:%hu->%pI4:%hu\n", 487 &exp->tuple.src.u3.ip, 488 ntohs(exp->tuple.src.u.tcp.port), 489 &exp->tuple.dst.u3.ip, 490 ntohs(exp->tuple.dst.u.tcp.port)); 491 492 return 0; 493 } 494 495 /****************************************************************************/ 496 static void ip_nat_callforwarding_expect(struct nf_conn *new, 497 struct nf_conntrack_expect *this) 498 { 499 struct nf_nat_range2 range; 500 501 /* This must be a fresh one. */ 502 BUG_ON(new->status & IPS_NAT_DONE_MASK); 503 504 /* Change src to where master sends to */ 505 range.flags = NF_NAT_RANGE_MAP_IPS; 506 range.min_addr = range.max_addr = 507 new->tuplehash[!this->dir].tuple.src.u3; 508 nf_nat_setup_info(new, &range, NF_NAT_MANIP_SRC); 509 510 /* For DST manip, map port here to where it's expected. */ 511 range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED); 512 range.min_proto = range.max_proto = this->saved_proto; 513 range.min_addr = range.max_addr = this->saved_addr; 514 nf_nat_setup_info(new, &range, NF_NAT_MANIP_DST); 515 } 516 517 /****************************************************************************/ 518 static int nat_callforwarding(struct sk_buff *skb, struct nf_conn *ct, 519 enum ip_conntrack_info ctinfo, 520 unsigned int protoff, 521 unsigned char **data, int dataoff, 522 TransportAddress *taddr, __be16 port, 523 struct nf_conntrack_expect *exp) 524 { 525 int dir = CTINFO2DIR(ctinfo); 526 u_int16_t nated_port; 527 528 /* Set expectations for NAT */ 529 exp->saved_addr = exp->tuple.dst.u3; 530 exp->tuple.dst.u3.ip = ct->tuplehash[!dir].tuple.dst.u3.ip; 531 exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port; 532 exp->expectfn = ip_nat_callforwarding_expect; 533 exp->dir = !dir; 534 535 /* Try to get same port: if not, try to change it. */ 536 for (nated_port = ntohs(port); nated_port != 0; nated_port++) { 537 int ret; 538 539 exp->tuple.dst.u.tcp.port = htons(nated_port); 540 ret = nf_ct_expect_related(exp, 0); 541 if (ret == 0) 542 break; 543 else if (ret != -EBUSY) { 544 nated_port = 0; 545 break; 546 } 547 } 548 549 if (nated_port == 0) { /* No port available */ 550 net_notice_ratelimited("nf_nat_q931: out of TCP ports\n"); 551 return 0; 552 } 553 554 /* Modify signal */ 555 if (set_h225_addr(skb, protoff, data, dataoff, taddr, 556 &ct->tuplehash[!dir].tuple.dst.u3, 557 htons(nated_port))) { 558 nf_ct_unexpect_related(exp); 559 return -1; 560 } 561 562 /* Success */ 563 pr_debug("nf_nat_q931: expect Call Forwarding %pI4:%hu->%pI4:%hu\n", 564 &exp->tuple.src.u3.ip, 565 ntohs(exp->tuple.src.u.tcp.port), 566 &exp->tuple.dst.u3.ip, 567 ntohs(exp->tuple.dst.u.tcp.port)); 568 569 return 0; 570 } 571 572 static struct nf_ct_helper_expectfn q931_nat = { 573 .name = "Q.931", 574 .expectfn = ip_nat_q931_expect, 575 }; 576 577 static struct nf_ct_helper_expectfn callforwarding_nat = { 578 .name = "callforwarding", 579 .expectfn = ip_nat_callforwarding_expect, 580 }; 581 582 static const struct nfct_h323_nat_hooks nathooks = { 583 .set_h245_addr = set_h245_addr, 584 .set_h225_addr = set_h225_addr, 585 .set_sig_addr = set_sig_addr, 586 .set_ras_addr = set_ras_addr, 587 .nat_rtp_rtcp = nat_rtp_rtcp, 588 .nat_t120 = nat_t120, 589 .nat_h245 = nat_h245, 590 .nat_callforwarding = nat_callforwarding, 591 .nat_q931 = nat_q931, 592 }; 593 594 /****************************************************************************/ 595 static int __init nf_nat_h323_init(void) 596 { 597 RCU_INIT_POINTER(nfct_h323_nat_hook, &nathooks); 598 nf_ct_helper_expectfn_register(&q931_nat); 599 nf_ct_helper_expectfn_register(&callforwarding_nat); 600 return 0; 601 } 602 603 /****************************************************************************/ 604 static void __exit nf_nat_h323_fini(void) 605 { 606 RCU_INIT_POINTER(nfct_h323_nat_hook, NULL); 607 nf_ct_helper_expectfn_unregister(&q931_nat); 608 nf_ct_helper_expectfn_unregister(&callforwarding_nat); 609 synchronize_rcu(); 610 } 611 612 /****************************************************************************/ 613 module_init(nf_nat_h323_init); 614 module_exit(nf_nat_h323_fini); 615 616 MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>"); 617 MODULE_DESCRIPTION("H.323 NAT helper"); 618 MODULE_LICENSE("GPL"); 619 MODULE_ALIAS_NF_NAT_HELPER("h323"); 620