All of lore.kernel.org
 help / color / mirror / Atom feed
* [H.323 Helper 1/3]: Add support for Call Forwarding
@ 2006-04-24  3:40 Jing Min Zhao
  2006-04-26 13:48 ` Patrick McHardy
  0 siblings, 1 reply; 14+ messages in thread
From: Jing Min Zhao @ 2006-04-24  3:40 UTC (permalink / raw)
  To: netfilter-devel

[-- Attachment #1: Type: text/plain, Size: 170 bytes --]

This patch is for 2.6.17-rc2. Please visit 
http://nath323.sourceforge.net/#_Toc133598071 for details.

Signed-off-by: Jing Min Zhao <zhaojingmin@users.sourceforge.net> 

[-- Attachment #2: nath323-callforwarding --]
[-- Type: application/octet-stream, Size: 13695 bytes --]

diff -pruN linux-2.6.17-rc2.a/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.6.17-rc2.b/include/linux/netfilter_ipv4/ip_conntrack.h
--- linux-2.6.17-rc2.a/include/linux/netfilter_ipv4/ip_conntrack.h	2006-04-21 20:37:26.000000000 -0400
+++ linux-2.6.17-rc2.b/include/linux/netfilter_ipv4/ip_conntrack.h	2006-04-21 20:41:11.000000000 -0400
@@ -154,6 +154,7 @@ struct ip_conntrack_expect
 	unsigned int flags;
 
 #ifdef CONFIG_IP_NF_NAT_NEEDED
+	u_int32_t saved_ip;
 	/* This is the original per-proto part, used to map the
 	 * expected connection the way the recipient expects. */
 	union ip_conntrack_manip_proto saved_proto;
diff -pruN linux-2.6.17-rc2.a/include/linux/netfilter_ipv4/ip_conntrack_h323.h linux-2.6.17-rc2.b/include/linux/netfilter_ipv4/ip_conntrack_h323.h
--- linux-2.6.17-rc2.a/include/linux/netfilter_ipv4/ip_conntrack_h323.h	2006-04-21 20:37:26.000000000 -0400
+++ linux-2.6.17-rc2.b/include/linux/netfilter_ipv4/ip_conntrack_h323.h	2006-04-21 20:41:11.000000000 -0400
@@ -71,6 +71,13 @@ extern int (*nat_h245_hook) (struct sk_b
 			     unsigned char **data, int dataoff,
 			     TransportAddress * addr, u_int16_t port,
 			     struct ip_conntrack_expect * exp);
+extern int (*nat_callforwarding_hook) (struct sk_buff ** pskb,
+				       struct ip_conntrack * ct,
+				       enum ip_conntrack_info ctinfo,
+				       unsigned char **data, int dataoff,
+				       TransportAddress * addr,
+				       u_int16_t port,
+				       struct ip_conntrack_expect * exp);
 extern int (*nat_q931_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
 			     enum ip_conntrack_info ctinfo,
 			     unsigned char **data, TransportAddress * addr,
diff -pruN linux-2.6.17-rc2.a/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h linux-2.6.17-rc2.b/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h
--- linux-2.6.17-rc2.a/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h	2006-04-21 20:37:26.000000000 -0400
+++ linux-2.6.17-rc2.b/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h	2006-04-21 20:41:11.000000000 -0400
@@ -1,4 +1,4 @@
-/* Generated by Jing Min Zhao's ASN.1 parser, Mar 15 2006
+/* Generated by Jing Min Zhao's ASN.1 parser, Apr 20 2006
  *
  * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
  *
@@ -412,6 +412,7 @@ typedef struct Facility_UUIE {	/* SEQUEN
 		eFacility_UUIE_destinationInfo = (1 << 14),
 		eFacility_UUIE_h245SecurityMode = (1 << 13),
 	} options;
+	TransportAddress alternativeAddress;
 	FacilityReason reason;
 	TransportAddress h245Address;
 	Facility_UUIE_fastStart fastStart;
diff -pruN linux-2.6.17-rc2.a/net/ipv4/netfilter/ip_conntrack_helper_h323.c linux-2.6.17-rc2.b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
--- linux-2.6.17-rc2.a/net/ipv4/netfilter/ip_conntrack_helper_h323.c	2006-04-21 20:37:32.000000000 -0400
+++ linux-2.6.17-rc2.b/net/ipv4/netfilter/ip_conntrack_helper_h323.c	2006-04-21 20:41:11.000000000 -0400
@@ -22,6 +22,8 @@
 #include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
 #include <linux/netfilter_ipv4/ip_conntrack_h323.h>
 #include <linux/moduleparam.h>
+#include <linux/ctype.h>
+#include <linux/inet.h>
 
 #if 0
 #define DEBUGP printk
@@ -38,6 +40,13 @@ static int gkrouted_only = 1;
 module_param(gkrouted_only, int, 0600);
 MODULE_PARM_DESC(gkrouted_only, "only accept calls from gatekeeper");
 
+static char *internal_net = NULL;
+static u_int32_t internal_net_addr = 0;
+static u_int32_t internal_net_mask = 0;
+module_param(internal_net, charp, 0600);
+MODULE_PARM_DESC(internal_net, "specify your internal network using format "
+		 "address/mask. this is used by call forwarding support");
+
 /* Hooks for NAT */
 int (*set_h245_addr_hook) (struct sk_buff ** pskb,
 			   unsigned char **data, int dataoff,
@@ -77,6 +86,12 @@ int (*nat_h245_hook) (struct sk_buff ** 
 		      unsigned char **data, int dataoff,
 		      TransportAddress * addr, u_int16_t port,
 		      struct ip_conntrack_expect * exp);
+int (*nat_callforwarding_hook) (struct sk_buff ** pskb,
+				struct ip_conntrack * ct,
+				enum ip_conntrack_info ctinfo,
+				unsigned char **data, int dataoff,
+				TransportAddress * addr, u_int16_t port,
+				struct ip_conntrack_expect * exp);
 int (*nat_q931_hook) (struct sk_buff ** pskb,
 		      struct ip_conntrack * ct,
 		      enum ip_conntrack_info ctinfo,
@@ -681,6 +696,76 @@ static int expect_h245(struct sk_buff **
 	return ret;
 }
 
+/* Forwarding declaration */
+void ip_conntrack_q931_expect(struct ip_conntrack *new,
+			      struct ip_conntrack_expect *this);
+
+/****************************************************************************/
+static int expect_callforwarding(struct sk_buff **pskb,
+				 struct ip_conntrack *ct,
+				 enum ip_conntrack_info ctinfo,
+				 unsigned char **data, int dataoff,
+				 TransportAddress * addr)
+{
+	int dir = CTINFO2DIR(ctinfo);
+	int ret = 0;
+	u_int32_t ip;
+	u_int16_t port;
+	struct ip_conntrack_expect *exp = NULL;
+
+	/* Read alternativeAddress */
+	if (!get_h225_addr(*data, addr, &ip, &port) || port == 0)
+		return 0;
+
+	/* If the calling party is on the same side of the forward-to party,
+	 * we don't need to track the second call */
+	if (internal_net &&
+	    ((ip & internal_net_mask) == internal_net_addr) ==
+	    ((ct->tuplehash[!dir].tuple.src.ip & internal_net_mask) ==
+	     internal_net_addr)) {
+		DEBUGP("ip_ct_q931: Call Forwarding not tracked\n");
+		return 0;
+	}
+
+	/* Create expect for the second call leg */
+	if ((exp = ip_conntrack_expect_alloc(ct)) == NULL)
+		return -1;
+	exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
+	exp->tuple.src.u.tcp.port = 0;
+	exp->tuple.dst.ip = ip;
+	exp->tuple.dst.u.tcp.port = htons(port);
+	exp->tuple.dst.protonum = IPPROTO_TCP;
+	exp->mask.src.ip = 0xFFFFFFFF;
+	exp->mask.src.u.tcp.port = 0;
+	exp->mask.dst.ip = 0xFFFFFFFF;
+	exp->mask.dst.u.tcp.port = 0xFFFF;
+	exp->mask.dst.protonum = 0xFF;
+	exp->flags = 0;
+
+	if (ct->tuplehash[dir].tuple.src.ip !=
+	    ct->tuplehash[!dir].tuple.dst.ip && nat_callforwarding_hook) {
+		/* Need NAT */
+		ret = nat_callforwarding_hook(pskb, ct, ctinfo, data, dataoff,
+					      addr, port, exp);
+	} else {		/* Conntrack only */
+		exp->expectfn = ip_conntrack_q931_expect;
+
+		if (ip_conntrack_expect_related(exp) == 0) {
+			DEBUGP("ip_ct_q931: expect Call Forwarding "
+			       "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+			       NIPQUAD(exp->tuple.src.ip),
+			       ntohs(exp->tuple.src.u.tcp.port),
+			       NIPQUAD(exp->tuple.dst.ip),
+			       ntohs(exp->tuple.dst.u.tcp.port));
+		} else
+			ret = -1;
+	}
+
+	ip_conntrack_expect_put(exp);
+
+	return ret;
+}
+
 /****************************************************************************/
 static int process_setup(struct sk_buff **pskb, struct ip_conntrack *ct,
 			 enum ip_conntrack_info ctinfo,
@@ -876,6 +961,15 @@ static int process_facility(struct sk_bu
 
 	DEBUGP("ip_ct_q931: Facility\n");
 
+	if (facility->reason.choice == eFacilityReason_callForwarded) {
+		if (facility->options & eFacility_UUIE_alternativeAddress)
+			return expect_callforwarding(pskb, ct, ctinfo, data,
+						     dataoff,
+						     &facility->
+						     alternativeAddress);
+		return 0;
+	}
+
 	if (facility->options & eFacility_UUIE_h245Address) {
 		ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
 				  &facility->h245Address);
@@ -1666,6 +1760,7 @@ static void fini(void)
 static int __init init(void)
 {
 	int ret;
+	char *p;
 
 	h323_buffer = kmalloc(65536, GFP_KERNEL);
 	if (!h323_buffer)
@@ -1676,6 +1771,22 @@ static int __init init(void)
 		return ret;
 	}
 
+	if (internal_net) {
+		if ((p = strchr(internal_net, '/')))
+			*p++ = 0;
+		if (isdigit(internal_net[0])) {
+			internal_net_addr = in_aton(internal_net);
+			if (p && isdigit(p[0]))
+				internal_net_mask = in_aton(p);
+			else
+				internal_net_mask = 0xffffffff;
+			internal_net_addr &= internal_net_mask;
+		}
+		DEBUGP("ip_ct_h323: internal_net = %u.%u.%u.%u/%u.%u.%u.%u\n",
+		       NIPQUAD(internal_net_addr),
+		       NIPQUAD(internal_net_mask));
+	}
+
 	DEBUGP("ip_ct_h323: init success\n");
 	return 0;
 }
@@ -1694,6 +1805,7 @@ EXPORT_SYMBOL_GPL(set_ras_addr_hook);
 EXPORT_SYMBOL_GPL(nat_rtp_rtcp_hook);
 EXPORT_SYMBOL_GPL(nat_t120_hook);
 EXPORT_SYMBOL_GPL(nat_h245_hook);
+EXPORT_SYMBOL_GPL(nat_callforwarding_hook);
 EXPORT_SYMBOL_GPL(nat_q931_hook);
 
 MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
diff -pruN linux-2.6.17-rc2.a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c linux-2.6.17-rc2.b/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c
--- linux-2.6.17-rc2.a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c	2006-04-21 20:37:33.000000000 -0400
+++ linux-2.6.17-rc2.b/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c	2006-04-21 20:41:11.000000000 -0400
@@ -1,4 +1,4 @@
-/* Generated by Jing Min Zhao's ASN.1 parser, Mar 15 2006
+/* Generated by Jing Min Zhao's ASN.1 parser, Apr 20 2006
  *
  * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
  *
@@ -1069,8 +1069,8 @@ static field_t _Facility_UUIE_fastStart[
 
 static field_t _Facility_UUIE[] = {	/* SEQUENCE */
 	{FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
-	{FNAME("alternativeAddress") CHOICE, 3, 7, 7, SKIP | EXT | OPT, 0,
-	 _TransportAddress},
+	{FNAME("alternativeAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
+	 offsetof(Facility_UUIE, alternativeAddress), _TransportAddress},
 	{FNAME("alternativeAliasAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
 	 _Facility_UUIE_alternativeAliasAddress},
 	{FNAME("conferenceID") OCTSTR, FIXD, 16, 0, SKIP | OPT, 0, NULL},
diff -pruN linux-2.6.17-rc2.a/net/ipv4/netfilter/ip_nat_helper_h323.c linux-2.6.17-rc2.b/net/ipv4/netfilter/ip_nat_helper_h323.c
--- linux-2.6.17-rc2.a/net/ipv4/netfilter/ip_nat_helper_h323.c	2006-04-21 20:37:33.000000000 -0400
+++ linux-2.6.17-rc2.b/net/ipv4/netfilter/ip_nat_helper_h323.c	2006-04-21 20:41:11.000000000 -0400
@@ -487,6 +487,80 @@ static int nat_q931(struct sk_buff **psk
 }
 
 /****************************************************************************/
+static void ip_nat_callforwarding_expect(struct ip_conntrack *new,
+					 struct ip_conntrack_expect *this)
+{
+	struct ip_nat_range range;
+
+	/* This must be a fresh one. */
+	BUG_ON(new->status & IPS_NAT_DONE_MASK);
+
+	/* Change src to where master sends to */
+	range.flags = IP_NAT_RANGE_MAP_IPS;
+	range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.ip;
+
+	/* hook doesn't matter, but it has to do source manip */
+	ip_nat_setup_info(new, &range, NF_IP_POST_ROUTING);
+
+	/* For DST manip, map port here to where it's expected. */
+	range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);
+	range.min = range.max = this->saved_proto;
+	range.min_ip = range.max_ip = this->saved_ip;
+
+	/* hook doesn't matter, but it has to do destination manip */
+	ip_nat_setup_info(new, &range, NF_IP_PRE_ROUTING);
+
+	ip_conntrack_q931_expect(new, this);
+}
+
+/****************************************************************************/
+static int nat_callforwarding(struct sk_buff **pskb, struct ip_conntrack *ct,
+			      enum ip_conntrack_info ctinfo,
+			      unsigned char **data, int dataoff,
+			      TransportAddress * addr, u_int16_t port,
+			      struct ip_conntrack_expect *exp)
+{
+	int dir = CTINFO2DIR(ctinfo);
+	u_int16_t nated_port;
+
+	/* Set expectations for NAT */
+	exp->saved_ip = exp->tuple.dst.ip;
+	exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
+	exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
+	exp->expectfn = ip_nat_callforwarding_expect;
+	exp->dir = !dir;
+
+	/* Try to get same port: if not, try to change it. */
+	for (nated_port = port; nated_port != 0; nated_port++) {
+		exp->tuple.dst.u.tcp.port = htons(nated_port);
+		if (ip_conntrack_expect_related(exp) == 0)
+			break;
+	}
+
+	if (nated_port == 0) {	/* No port available */
+		if (net_ratelimit())
+			printk("ip_nat_q931: out of TCP ports\n");
+		return 0;
+	}
+
+	/* Modify signal */
+	if (!set_h225_addr(pskb, data, dataoff, addr,
+			   ct->tuplehash[!dir].tuple.dst.ip,
+			   nated_port) == 0) {
+		ip_conntrack_unexpect_related(exp);
+		return -1;
+	}
+
+	/* Success */
+	DEBUGP("ip_nat_q931: expect Call Forwarding "
+	       "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+	       NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
+	       NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
+
+	return 0;
+}
+
+/****************************************************************************/
 static int __init init(void)
 {
 	BUG_ON(set_h245_addr_hook != NULL);
@@ -496,6 +570,7 @@ static int __init init(void)
 	BUG_ON(nat_rtp_rtcp_hook != NULL);
 	BUG_ON(nat_t120_hook != NULL);
 	BUG_ON(nat_h245_hook != NULL);
+	BUG_ON(nat_callforwarding_hook != NULL);
 	BUG_ON(nat_q931_hook != NULL);
 
 	set_h245_addr_hook = set_h245_addr;
@@ -505,6 +580,7 @@ static int __init init(void)
 	nat_rtp_rtcp_hook = nat_rtp_rtcp;
 	nat_t120_hook = nat_t120;
 	nat_h245_hook = nat_h245;
+	nat_callforwarding_hook = nat_callforwarding;
 	nat_q931_hook = nat_q931;
 
 	DEBUGP("ip_nat_h323: init success\n");
@@ -521,6 +597,7 @@ static void __exit fini(void)
 	nat_rtp_rtcp_hook = NULL;
 	nat_t120_hook = NULL;
 	nat_h245_hook = NULL;
+	nat_callforwarding_hook = NULL;
 	nat_q931_hook = NULL;
 	synchronize_net();
 }

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2006-05-20  4:10 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-04-24  3:40 [H.323 Helper 1/3]: Add support for Call Forwarding Jing Min Zhao
2006-04-26 13:48 ` Patrick McHardy
2006-04-26 14:33   ` Jing Min Zhao
2006-04-26 16:49     ` Patrick McHardy
2006-04-26 18:06       ` Jing Min Zhao
2006-04-26 20:20         ` Patrick McHardy
2006-04-26 20:21         ` Patrick McHardy
2006-04-26 21:15           ` Jing Min Zhao
2006-04-27 19:57             ` Patrick McHardy
2006-04-28 15:07               ` Jing Min Zhao
2006-04-28 15:13                 ` Patrick McHardy
2006-05-20  3:23                   ` Patrick McHardy
2006-05-20  4:10                     ` Jing Min Zhao
2006-05-01 17:51         ` imap.netfilter.org (was Re: [H.323 Helper 1/3]: Add support for Call Forwarding) Harald Welte

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.