forked from luck/tmp_suning_uos_patched
[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>
This commit is contained in:
parent
c952616934
commit
c0d4cfd96d
|
@ -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;
|
||||
|
|
|
@ -71,6 +71,13 @@ extern int (*nat_h245_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
|
|||
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,
|
||||
|
|
|
@ -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 { /* SEQUENCE */
|
|||
eFacility_UUIE_destinationInfo = (1 << 14),
|
||||
eFacility_UUIE_h245SecurityMode = (1 << 13),
|
||||
} options;
|
||||
TransportAddress alternativeAddress;
|
||||
FacilityReason reason;
|
||||
TransportAddress h245Address;
|
||||
Facility_UUIE_fastStart fastStart;
|
||||
|
|
|
@ -183,10 +183,10 @@ config IP_NF_H323
|
|||
With this module you can support H.323 on a connection tracking/NAT
|
||||
firewall.
|
||||
|
||||
This module supports RAS, Fast-start, H.245 tunnelling, RTP/RTCP
|
||||
and T.120 based data and applications including audio, video, FAX,
|
||||
chat, whiteboard, file transfer, etc. For more information, please
|
||||
see http://nath323.sourceforge.net/.
|
||||
This module supports RAS, Fast Start, H.245 Tunnelling, Call
|
||||
Forwarding, RTP/RTCP and T.120 based audio, video, fax, chat,
|
||||
whiteboard, file transfer, etc. For more information, please
|
||||
visit http://nath323.sourceforge.net/.
|
||||
|
||||
If you want to compile it as a module, say 'M' here and read
|
||||
Documentation/modules.txt. If unsure, say 'N'.
|
||||
|
|
|
@ -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 ** pskb,
|
|||
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,
|
||||
|
@ -683,6 +698,76 @@ static int expect_h245(struct sk_buff **pskb, struct ip_conntrack *ct,
|
|||
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,
|
||||
|
@ -878,6 +963,15 @@ static int process_facility(struct sk_buff **pskb, struct ip_conntrack *ct,
|
|||
|
||||
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);
|
||||
|
@ -1668,6 +1762,7 @@ static void fini(void)
|
|||
static int __init init(void)
|
||||
{
|
||||
int ret;
|
||||
char *p;
|
||||
|
||||
h323_buffer = kmalloc(65536, GFP_KERNEL);
|
||||
if (!h323_buffer)
|
||||
|
@ -1678,6 +1773,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;
|
||||
}
|
||||
|
@ -1696,6 +1807,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>");
|
||||
|
|
|
@ -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[] = { /* SEQUENCE OF */
|
|||
|
||||
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},
|
||||
|
|
|
@ -486,6 +486,80 @@ static int nat_q931(struct sk_buff **pskb, struct ip_conntrack *ct,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
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)
|
||||
{
|
||||
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user