aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorJing Min Zhao <zhaojingmin@users.sourceforge.net>2006-05-29 21:26:27 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-06-18 00:29:11 -0400
commitc0d4cfd96dd0cc0dbf49435898808b5553af4822 (patch)
treeaa8fb9afbed9da300bb22adfd3798fe7e196cee0 /net/ipv4
parentc95261693467f0aeac7fafa69860ddfb02bc12f8 (diff)
[NETFILTER]: H.323 helper: Add support for Call Forwarding
Signed-off-by: Jing Min Zhao <zhaojingmin@users.sourceforge.net> Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/netfilter/Kconfig8
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323.c112
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323_types.c6
-rw-r--r--net/ipv4/netfilter/ip_nat_helper_h323.c77
4 files changed, 196 insertions, 7 deletions
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 1540e227890f..f86aeda3a5a0 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -183,10 +183,10 @@ config IP_NF_H323
183 With this module you can support H.323 on a connection tracking/NAT 183 With this module you can support H.323 on a connection tracking/NAT
184 firewall. 184 firewall.
185 185
186 This module supports RAS, Fast-start, H.245 tunnelling, RTP/RTCP 186 This module supports RAS, Fast Start, H.245 Tunnelling, Call
187 and T.120 based data and applications including audio, video, FAX, 187 Forwarding, RTP/RTCP and T.120 based audio, video, fax, chat,
188 chat, whiteboard, file transfer, etc. For more information, please 188 whiteboard, file transfer, etc. For more information, please
189 see http://nath323.sourceforge.net/. 189 visit http://nath323.sourceforge.net/.
190 190
191 If you want to compile it as a module, say 'M' here and read 191 If you want to compile it as a module, say 'M' here and read
192 Documentation/modules.txt. If unsure, say 'N'. 192 Documentation/modules.txt. If unsure, say 'N'.
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323.c b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
index 518f581d39ec..3052468a6ab1 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
@@ -22,6 +22,8 @@
22#include <linux/netfilter_ipv4/ip_conntrack_tuple.h> 22#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
23#include <linux/netfilter_ipv4/ip_conntrack_h323.h> 23#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
24#include <linux/moduleparam.h> 24#include <linux/moduleparam.h>
25#include <linux/ctype.h>
26#include <linux/inet.h>
25 27
26#if 0 28#if 0
27#define DEBUGP printk 29#define DEBUGP printk
@@ -38,6 +40,13 @@ static int gkrouted_only = 1;
38module_param(gkrouted_only, int, 0600); 40module_param(gkrouted_only, int, 0600);
39MODULE_PARM_DESC(gkrouted_only, "only accept calls from gatekeeper"); 41MODULE_PARM_DESC(gkrouted_only, "only accept calls from gatekeeper");
40 42
43static char *internal_net = NULL;
44static u_int32_t internal_net_addr = 0;
45static u_int32_t internal_net_mask = 0;
46module_param(internal_net, charp, 0600);
47MODULE_PARM_DESC(internal_net, "specify your internal network using format "
48 "address/mask. this is used by call forwarding support");
49
41/* Hooks for NAT */ 50/* Hooks for NAT */
42int (*set_h245_addr_hook) (struct sk_buff ** pskb, 51int (*set_h245_addr_hook) (struct sk_buff ** pskb,
43 unsigned char **data, int dataoff, 52 unsigned char **data, int dataoff,
@@ -77,6 +86,12 @@ int (*nat_h245_hook) (struct sk_buff ** pskb,
77 unsigned char **data, int dataoff, 86 unsigned char **data, int dataoff,
78 TransportAddress * addr, u_int16_t port, 87 TransportAddress * addr, u_int16_t port,
79 struct ip_conntrack_expect * exp); 88 struct ip_conntrack_expect * exp);
89int (*nat_callforwarding_hook) (struct sk_buff ** pskb,
90 struct ip_conntrack * ct,
91 enum ip_conntrack_info ctinfo,
92 unsigned char **data, int dataoff,
93 TransportAddress * addr, u_int16_t port,
94 struct ip_conntrack_expect * exp);
80int (*nat_q931_hook) (struct sk_buff ** pskb, 95int (*nat_q931_hook) (struct sk_buff ** pskb,
81 struct ip_conntrack * ct, 96 struct ip_conntrack * ct,
82 enum ip_conntrack_info ctinfo, 97 enum ip_conntrack_info ctinfo,
@@ -683,6 +698,76 @@ static int expect_h245(struct sk_buff **pskb, struct ip_conntrack *ct,
683 return ret; 698 return ret;
684} 699}
685 700
701/* Forwarding declaration */
702void ip_conntrack_q931_expect(struct ip_conntrack *new,
703 struct ip_conntrack_expect *this);
704
705/****************************************************************************/
706static int expect_callforwarding(struct sk_buff **pskb,
707 struct ip_conntrack *ct,
708 enum ip_conntrack_info ctinfo,
709 unsigned char **data, int dataoff,
710 TransportAddress * addr)
711{
712 int dir = CTINFO2DIR(ctinfo);
713 int ret = 0;
714 u_int32_t ip;
715 u_int16_t port;
716 struct ip_conntrack_expect *exp = NULL;
717
718 /* Read alternativeAddress */
719 if (!get_h225_addr(*data, addr, &ip, &port) || port == 0)
720 return 0;
721
722 /* If the calling party is on the same side of the forward-to party,
723 * we don't need to track the second call */
724 if (internal_net &&
725 ((ip & internal_net_mask) == internal_net_addr) ==
726 ((ct->tuplehash[!dir].tuple.src.ip & internal_net_mask) ==
727 internal_net_addr)) {
728 DEBUGP("ip_ct_q931: Call Forwarding not tracked\n");
729 return 0;
730 }
731
732 /* Create expect for the second call leg */
733 if ((exp = ip_conntrack_expect_alloc(ct)) == NULL)
734 return -1;
735 exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
736 exp->tuple.src.u.tcp.port = 0;
737 exp->tuple.dst.ip = ip;
738 exp->tuple.dst.u.tcp.port = htons(port);
739 exp->tuple.dst.protonum = IPPROTO_TCP;
740 exp->mask.src.ip = 0xFFFFFFFF;
741 exp->mask.src.u.tcp.port = 0;
742 exp->mask.dst.ip = 0xFFFFFFFF;
743 exp->mask.dst.u.tcp.port = 0xFFFF;
744 exp->mask.dst.protonum = 0xFF;
745 exp->flags = 0;
746
747 if (ct->tuplehash[dir].tuple.src.ip !=
748 ct->tuplehash[!dir].tuple.dst.ip && nat_callforwarding_hook) {
749 /* Need NAT */
750 ret = nat_callforwarding_hook(pskb, ct, ctinfo, data, dataoff,
751 addr, port, exp);
752 } else { /* Conntrack only */
753 exp->expectfn = ip_conntrack_q931_expect;
754
755 if (ip_conntrack_expect_related(exp) == 0) {
756 DEBUGP("ip_ct_q931: expect Call Forwarding "
757 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
758 NIPQUAD(exp->tuple.src.ip),
759 ntohs(exp->tuple.src.u.tcp.port),
760 NIPQUAD(exp->tuple.dst.ip),
761 ntohs(exp->tuple.dst.u.tcp.port));
762 } else
763 ret = -1;
764 }
765
766 ip_conntrack_expect_put(exp);
767
768 return ret;
769}
770
686/****************************************************************************/ 771/****************************************************************************/
687static int process_setup(struct sk_buff **pskb, struct ip_conntrack *ct, 772static int process_setup(struct sk_buff **pskb, struct ip_conntrack *ct,
688 enum ip_conntrack_info ctinfo, 773 enum ip_conntrack_info ctinfo,
@@ -878,6 +963,15 @@ static int process_facility(struct sk_buff **pskb, struct ip_conntrack *ct,
878 963
879 DEBUGP("ip_ct_q931: Facility\n"); 964 DEBUGP("ip_ct_q931: Facility\n");
880 965
966 if (facility->reason.choice == eFacilityReason_callForwarded) {
967 if (facility->options & eFacility_UUIE_alternativeAddress)
968 return expect_callforwarding(pskb, ct, ctinfo, data,
969 dataoff,
970 &facility->
971 alternativeAddress);
972 return 0;
973 }
974
881 if (facility->options & eFacility_UUIE_h245Address) { 975 if (facility->options & eFacility_UUIE_h245Address) {
882 ret = expect_h245(pskb, ct, ctinfo, data, dataoff, 976 ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
883 &facility->h245Address); 977 &facility->h245Address);
@@ -1668,6 +1762,7 @@ static void fini(void)
1668static int __init init(void) 1762static int __init init(void)
1669{ 1763{
1670 int ret; 1764 int ret;
1765 char *p;
1671 1766
1672 h323_buffer = kmalloc(65536, GFP_KERNEL); 1767 h323_buffer = kmalloc(65536, GFP_KERNEL);
1673 if (!h323_buffer) 1768 if (!h323_buffer)
@@ -1678,6 +1773,22 @@ static int __init init(void)
1678 return ret; 1773 return ret;
1679 } 1774 }
1680 1775
1776 if (internal_net) {
1777 if ((p = strchr(internal_net, '/')))
1778 *p++ = 0;
1779 if (isdigit(internal_net[0])) {
1780 internal_net_addr = in_aton(internal_net);
1781 if (p && isdigit(p[0]))
1782 internal_net_mask = in_aton(p);
1783 else
1784 internal_net_mask = 0xffffffff;
1785 internal_net_addr &= internal_net_mask;
1786 }
1787 DEBUGP("ip_ct_h323: internal_net = %u.%u.%u.%u/%u.%u.%u.%u\n",
1788 NIPQUAD(internal_net_addr),
1789 NIPQUAD(internal_net_mask));
1790 }
1791
1681 DEBUGP("ip_ct_h323: init success\n"); 1792 DEBUGP("ip_ct_h323: init success\n");
1682 return 0; 1793 return 0;
1683} 1794}
@@ -1696,6 +1807,7 @@ EXPORT_SYMBOL_GPL(set_ras_addr_hook);
1696EXPORT_SYMBOL_GPL(nat_rtp_rtcp_hook); 1807EXPORT_SYMBOL_GPL(nat_rtp_rtcp_hook);
1697EXPORT_SYMBOL_GPL(nat_t120_hook); 1808EXPORT_SYMBOL_GPL(nat_t120_hook);
1698EXPORT_SYMBOL_GPL(nat_h245_hook); 1809EXPORT_SYMBOL_GPL(nat_h245_hook);
1810EXPORT_SYMBOL_GPL(nat_callforwarding_hook);
1699EXPORT_SYMBOL_GPL(nat_q931_hook); 1811EXPORT_SYMBOL_GPL(nat_q931_hook);
1700 1812
1701MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>"); 1813MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c b/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c
index 022c47b9f6c9..4b359618bedd 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c
@@ -1,4 +1,4 @@
1/* Generated by Jing Min Zhao's ASN.1 parser, Mar 15 2006 1/* Generated by Jing Min Zhao's ASN.1 parser, Apr 20 2006
2 * 2 *
3 * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net> 3 * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
4 * 4 *
@@ -1069,8 +1069,8 @@ static field_t _Facility_UUIE_fastStart[] = { /* SEQUENCE OF */
1069 1069
1070static field_t _Facility_UUIE[] = { /* SEQUENCE */ 1070static field_t _Facility_UUIE[] = { /* SEQUENCE */
1071 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, 1071 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
1072 {FNAME("alternativeAddress") CHOICE, 3, 7, 7, SKIP | EXT | OPT, 0, 1072 {FNAME("alternativeAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
1073 _TransportAddress}, 1073 offsetof(Facility_UUIE, alternativeAddress), _TransportAddress},
1074 {FNAME("alternativeAliasAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, 1074 {FNAME("alternativeAliasAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
1075 _Facility_UUIE_alternativeAliasAddress}, 1075 _Facility_UUIE_alternativeAliasAddress},
1076 {FNAME("conferenceID") OCTSTR, FIXD, 16, 0, SKIP | OPT, 0, NULL}, 1076 {FNAME("conferenceID") OCTSTR, FIXD, 16, 0, SKIP | OPT, 0, NULL},
diff --git a/net/ipv4/netfilter/ip_nat_helper_h323.c b/net/ipv4/netfilter/ip_nat_helper_h323.c
index d45663d137a7..419b878fb467 100644
--- a/net/ipv4/netfilter/ip_nat_helper_h323.c
+++ b/net/ipv4/netfilter/ip_nat_helper_h323.c
@@ -487,6 +487,80 @@ static int nat_q931(struct sk_buff **pskb, struct ip_conntrack *ct,
487} 487}
488 488
489/****************************************************************************/ 489/****************************************************************************/
490static void ip_nat_callforwarding_expect(struct ip_conntrack *new,
491 struct ip_conntrack_expect *this)
492{
493 struct ip_nat_range range;
494
495 /* This must be a fresh one. */
496 BUG_ON(new->status & IPS_NAT_DONE_MASK);
497
498 /* Change src to where master sends to */
499 range.flags = IP_NAT_RANGE_MAP_IPS;
500 range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.ip;
501
502 /* hook doesn't matter, but it has to do source manip */
503 ip_nat_setup_info(new, &range, NF_IP_POST_ROUTING);
504
505 /* For DST manip, map port here to where it's expected. */
506 range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);
507 range.min = range.max = this->saved_proto;
508 range.min_ip = range.max_ip = this->saved_ip;
509
510 /* hook doesn't matter, but it has to do destination manip */
511 ip_nat_setup_info(new, &range, NF_IP_PRE_ROUTING);
512
513 ip_conntrack_q931_expect(new, this);
514}
515
516/****************************************************************************/
517static int nat_callforwarding(struct sk_buff **pskb, struct ip_conntrack *ct,
518 enum ip_conntrack_info ctinfo,
519 unsigned char **data, int dataoff,
520 TransportAddress * addr, u_int16_t port,
521 struct ip_conntrack_expect *exp)
522{
523 int dir = CTINFO2DIR(ctinfo);
524 u_int16_t nated_port;
525
526 /* Set expectations for NAT */
527 exp->saved_ip = exp->tuple.dst.ip;
528 exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
529 exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
530 exp->expectfn = ip_nat_callforwarding_expect;
531 exp->dir = !dir;
532
533 /* Try to get same port: if not, try to change it. */
534 for (nated_port = port; nated_port != 0; nated_port++) {
535 exp->tuple.dst.u.tcp.port = htons(nated_port);
536 if (ip_conntrack_expect_related(exp) == 0)
537 break;
538 }
539
540 if (nated_port == 0) { /* No port available */
541 if (net_ratelimit())
542 printk("ip_nat_q931: out of TCP ports\n");
543 return 0;
544 }
545
546 /* Modify signal */
547 if (!set_h225_addr(pskb, data, dataoff, addr,
548 ct->tuplehash[!dir].tuple.dst.ip,
549 nated_port) == 0) {
550 ip_conntrack_unexpect_related(exp);
551 return -1;
552 }
553
554 /* Success */
555 DEBUGP("ip_nat_q931: expect Call Forwarding "
556 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
557 NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
558 NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
559
560 return 0;
561}
562
563/****************************************************************************/
490static int __init init(void) 564static int __init init(void)
491{ 565{
492 BUG_ON(set_h245_addr_hook != NULL); 566 BUG_ON(set_h245_addr_hook != NULL);
@@ -496,6 +570,7 @@ static int __init init(void)
496 BUG_ON(nat_rtp_rtcp_hook != NULL); 570 BUG_ON(nat_rtp_rtcp_hook != NULL);
497 BUG_ON(nat_t120_hook != NULL); 571 BUG_ON(nat_t120_hook != NULL);
498 BUG_ON(nat_h245_hook != NULL); 572 BUG_ON(nat_h245_hook != NULL);
573 BUG_ON(nat_callforwarding_hook != NULL);
499 BUG_ON(nat_q931_hook != NULL); 574 BUG_ON(nat_q931_hook != NULL);
500 575
501 set_h245_addr_hook = set_h245_addr; 576 set_h245_addr_hook = set_h245_addr;
@@ -505,6 +580,7 @@ static int __init init(void)
505 nat_rtp_rtcp_hook = nat_rtp_rtcp; 580 nat_rtp_rtcp_hook = nat_rtp_rtcp;
506 nat_t120_hook = nat_t120; 581 nat_t120_hook = nat_t120;
507 nat_h245_hook = nat_h245; 582 nat_h245_hook = nat_h245;
583 nat_callforwarding_hook = nat_callforwarding;
508 nat_q931_hook = nat_q931; 584 nat_q931_hook = nat_q931;
509 585
510 DEBUGP("ip_nat_h323: init success\n"); 586 DEBUGP("ip_nat_h323: init success\n");
@@ -521,6 +597,7 @@ static void __exit fini(void)
521 nat_rtp_rtcp_hook = NULL; 597 nat_rtp_rtcp_hook = NULL;
522 nat_t120_hook = NULL; 598 nat_t120_hook = NULL;
523 nat_h245_hook = NULL; 599 nat_h245_hook = NULL;
600 nat_callforwarding_hook = NULL;
524 nat_q931_hook = NULL; 601 nat_q931_hook = NULL;
525 synchronize_net(); 602 synchronize_net();
526} 603}