⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ip_conntrack_helper_h323.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * H.323 connection tracking helper * * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net> * * This source code is licensed under General Public License version 2. * * Based on the 'brute force' H.323 connection tracking module by * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> * * For more information, please see http://nath323.sourceforge.net/ */#include <linux/config.h>#include <linux/module.h>#include <linux/netfilter.h>#include <linux/ip.h>#include <net/tcp.h>#include <linux/netfilter_ipv4/ip_conntrack.h>#include <linux/netfilter_ipv4/ip_conntrack_core.h>#include <linux/netfilter_ipv4/ip_conntrack_helper.h>#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>#include <linux/netfilter_ipv4/ip_conntrack_h323.h>#include <linux/moduleparam.h>#if 0#define DEBUGP printk#else#define DEBUGP(format, args...)#endif/* Parameters */static unsigned int default_rrq_ttl = 300;module_param(default_rrq_ttl, uint, 0600);MODULE_PARM_DESC(default_rrq_ttl, "use this TTL if it's missing in RRQ");static int gkrouted_only = 1;module_param(gkrouted_only, int, 0600);MODULE_PARM_DESC(gkrouted_only, "only accept calls from gatekeeper");/* Hooks for NAT */int (*set_h245_addr_hook) (struct sk_buff ** pskb,			   unsigned char **data, int dataoff,			   H245_TransportAddress * addr,			   u_int32_t ip, u_int16_t port);int (*set_h225_addr_hook) (struct sk_buff ** pskb,			   unsigned char **data, int dataoff,			   TransportAddress * addr,			   u_int32_t ip, u_int16_t port);int (*set_sig_addr_hook) (struct sk_buff ** pskb,			  struct ip_conntrack * ct,			  enum ip_conntrack_info ctinfo,			  unsigned char **data,			  TransportAddress * addr, int count);int (*set_ras_addr_hook) (struct sk_buff ** pskb,			  struct ip_conntrack * ct,			  enum ip_conntrack_info ctinfo,			  unsigned char **data,			  TransportAddress * addr, int count);int (*nat_rtp_rtcp_hook) (struct sk_buff ** pskb,			  struct ip_conntrack * ct,			  enum ip_conntrack_info ctinfo,			  unsigned char **data, int dataoff,			  H245_TransportAddress * addr,			  u_int16_t port, u_int16_t rtp_port,			  struct ip_conntrack_expect * rtp_exp,			  struct ip_conntrack_expect * rtcp_exp);int (*nat_t120_hook) (struct sk_buff ** pskb,		      struct ip_conntrack * ct,		      enum ip_conntrack_info ctinfo,		      unsigned char **data, int dataoff,		      H245_TransportAddress * addr, u_int16_t port,		      struct ip_conntrack_expect * exp);int (*nat_h245_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,		      unsigned char **data, TransportAddress * addr, int idx,		      u_int16_t port, struct ip_conntrack_expect * exp);static DEFINE_SPINLOCK(ip_h323_lock);static char *h323_buffer;/****************************************************************************/static int get_tpkt_data(struct sk_buff **pskb, struct ip_conntrack *ct,			 enum ip_conntrack_info ctinfo,			 unsigned char **data, int *datalen, int *dataoff){	struct ip_ct_h323_master *info = &ct->help.ct_h323_info;	int dir = CTINFO2DIR(ctinfo);	struct tcphdr _tcph, *th;	int tcpdatalen;	int tcpdataoff;	unsigned char *tpkt;	int tpktlen;	int tpktoff;	/* Get TCP header */	th = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl * 4,				sizeof(_tcph), &_tcph);	if (th == NULL)		return 0;	/* Get TCP data offset */	tcpdataoff = (*pskb)->nh.iph->ihl * 4 + th->doff * 4;	/* Get TCP data length */	tcpdatalen = (*pskb)->len - tcpdataoff;	if (tcpdatalen <= 0)	/* No TCP data */		goto clear_out;	if (*data == NULL) {	/* first TPKT */		/* Get first TPKT pointer */		tpkt = skb_header_pointer(*pskb, tcpdataoff, tcpdatalen,					  h323_buffer);		BUG_ON(tpkt == NULL);		/* Validate TPKT identifier */		if (tcpdatalen < 4 || tpkt[0] != 0x03 || tpkt[1] != 0) {			/* Netmeeting sends TPKT header and data separately */			if (info->tpkt_len[dir] > 0) {				DEBUGP("ip_ct_h323: previous packet "				       "indicated separate TPKT data of %hu "				       "bytes\n", info->tpkt_len[dir]);				if (info->tpkt_len[dir] <= tcpdatalen) {					/* Yes, there was a TPKT header					 * received */					*data = tpkt;					*datalen = info->tpkt_len[dir];					*dataoff = 0;					goto out;				}				/* Fragmented TPKT */				if (net_ratelimit())					printk("ip_ct_h323: "					       "fragmented TPKT\n");				goto clear_out;			}			/* It is not even a TPKT */			return 0;		}		tpktoff = 0;	} else {		/* Next TPKT */		tpktoff = *dataoff + *datalen;		tcpdatalen -= tpktoff;		if (tcpdatalen <= 4)	/* No more TPKT */			goto clear_out;		tpkt = *data + *datalen;		/* Validate TPKT identifier */		if (tpkt[0] != 0x03 || tpkt[1] != 0)			goto clear_out;	}	/* Validate TPKT length */	tpktlen = tpkt[2] * 256 + tpkt[3];	if (tpktlen < 4)		goto clear_out;	if (tpktlen > tcpdatalen) {		if (tcpdatalen == 4) {	/* Separate TPKT header */			/* Netmeeting sends TPKT header and data separately */			DEBUGP("ip_ct_h323: separate TPKT header indicates "			       "there will be TPKT data of %hu bytes\n",			       tpktlen - 4);			info->tpkt_len[dir] = tpktlen - 4;			return 0;		}		if (net_ratelimit())			printk("ip_ct_h323: incomplete TPKT (fragmented?)\n");		goto clear_out;	}	/* This is the encapsulated data */	*data = tpkt + 4;	*datalen = tpktlen - 4;	*dataoff = tpktoff + 4;      out:	/* Clear TPKT length */	info->tpkt_len[dir] = 0;	return 1;      clear_out:	info->tpkt_len[dir] = 0;	return 0;}/****************************************************************************/static int get_h245_addr(unsigned char *data, H245_TransportAddress * addr,			 u_int32_t * ip, u_int16_t * port){	unsigned char *p;	if (addr->choice != eH245_TransportAddress_unicastAddress ||	    addr->unicastAddress.choice != eUnicastAddress_iPAddress)		return 0;	p = data + addr->unicastAddress.iPAddress.network;	*ip = htonl((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]));	*port = (p[4] << 8) | (p[5]);	return 1;}/****************************************************************************/static int expect_rtp_rtcp(struct sk_buff **pskb, struct ip_conntrack *ct,			   enum ip_conntrack_info ctinfo,			   unsigned char **data, int dataoff,			   H245_TransportAddress * addr){	int dir = CTINFO2DIR(ctinfo);	int ret = 0;	u_int32_t ip;	u_int16_t port;	u_int16_t rtp_port;	struct ip_conntrack_expect *rtp_exp;	struct ip_conntrack_expect *rtcp_exp;	/* Read RTP or RTCP address */	if (!get_h245_addr(*data, addr, &ip, &port) ||	    ip != ct->tuplehash[dir].tuple.src.ip || port == 0)		return 0;	/* RTP port is even */	rtp_port = port & (~1);	/* Create expect for RTP */	if ((rtp_exp = ip_conntrack_expect_alloc(ct)) == NULL)		return -1;	rtp_exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;	rtp_exp->tuple.src.u.udp.port = 0;	rtp_exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;	rtp_exp->tuple.dst.u.udp.port = htons(rtp_port);	rtp_exp->tuple.dst.protonum = IPPROTO_UDP;	rtp_exp->mask.src.ip = 0xFFFFFFFF;	rtp_exp->mask.src.u.udp.port = 0;	rtp_exp->mask.dst.ip = 0xFFFFFFFF;	rtp_exp->mask.dst.u.udp.port = 0xFFFF;	rtp_exp->mask.dst.protonum = 0xFF;	rtp_exp->flags = 0;	/* Create expect for RTCP */	if ((rtcp_exp = ip_conntrack_expect_alloc(ct)) == NULL) {		ip_conntrack_expect_put(rtp_exp);		return -1;	}	rtcp_exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;	rtcp_exp->tuple.src.u.udp.port = 0;	rtcp_exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;	rtcp_exp->tuple.dst.u.udp.port = htons(rtp_port + 1);	rtcp_exp->tuple.dst.protonum = IPPROTO_UDP;	rtcp_exp->mask.src.ip = 0xFFFFFFFF;	rtcp_exp->mask.src.u.udp.port = 0;	rtcp_exp->mask.dst.ip = 0xFFFFFFFF;	rtcp_exp->mask.dst.u.udp.port = 0xFFFF;	rtcp_exp->mask.dst.protonum = 0xFF;	rtcp_exp->flags = 0;	if (ct->tuplehash[dir].tuple.src.ip !=	    ct->tuplehash[!dir].tuple.dst.ip && nat_rtp_rtcp_hook) {		/* NAT needed */		ret = nat_rtp_rtcp_hook(pskb, ct, ctinfo, data, dataoff,					addr, port, rtp_port, rtp_exp,					rtcp_exp);	} else {		/* Conntrack only */		rtp_exp->expectfn = NULL;		rtcp_exp->expectfn = NULL;		if (ip_conntrack_expect_related(rtp_exp) == 0) {			if (ip_conntrack_expect_related(rtcp_exp) == 0) {				DEBUGP("ip_ct_h323: expect RTP "				       "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",				       NIPQUAD(rtp_exp->tuple.src.ip),				       ntohs(rtp_exp->tuple.src.u.udp.port),				       NIPQUAD(rtp_exp->tuple.dst.ip),				       ntohs(rtp_exp->tuple.dst.u.udp.port));				DEBUGP("ip_ct_h323: expect RTCP "				       "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",				       NIPQUAD(rtcp_exp->tuple.src.ip),				       ntohs(rtcp_exp->tuple.src.u.udp.port),				       NIPQUAD(rtcp_exp->tuple.dst.ip),				       ntohs(rtcp_exp->tuple.dst.u.udp.port));			} else {				ip_conntrack_unexpect_related(rtp_exp);				ret = -1;			}		} else			ret = -1;	}	ip_conntrack_expect_put(rtp_exp);	ip_conntrack_expect_put(rtcp_exp);	return ret;}/****************************************************************************/static int expect_t120(struct sk_buff **pskb,		       struct ip_conntrack *ct,		       enum ip_conntrack_info ctinfo,		       unsigned char **data, int dataoff,		       H245_TransportAddress * addr){	int dir = CTINFO2DIR(ctinfo);	int ret = 0;	u_int32_t ip;	u_int16_t port;	struct ip_conntrack_expect *exp = NULL;	/* Read T.120 address */	if (!get_h245_addr(*data, addr, &ip, &port) ||	    ip != ct->tuplehash[dir].tuple.src.ip || port == 0)		return 0;	/* Create expect for T.120 connections */	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 = ct->tuplehash[!dir].tuple.dst.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 = IP_CT_EXPECT_PERMANENT;	/* Accept multiple channels */	if (ct->tuplehash[dir].tuple.src.ip !=	    ct->tuplehash[!dir].tuple.dst.ip && nat_t120_hook) {		/* NAT needed */		ret = nat_t120_hook(pskb, ct, ctinfo, data, dataoff, addr,				    port, exp);	} else {		/* Conntrack only */		exp->expectfn = NULL;		if (ip_conntrack_expect_related(exp) == 0) {			DEBUGP("ip_ct_h323: expect T.120 "			       "%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_h245_channel(struct sk_buff **pskb,				struct ip_conntrack *ct,				enum ip_conntrack_info ctinfo,				unsigned char **data, int dataoff,				H2250LogicalChannelParameters * channel){	int ret;	if (channel->options & eH2250LogicalChannelParameters_mediaChannel) {		/* RTP */		ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,				      &channel->mediaChannel);		if (ret < 0)			return -1;	}	if (channel->	    options & eH2250LogicalChannelParameters_mediaControlChannel) {		/* RTCP */		ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,				      &channel->mediaControlChannel);		if (ret < 0)			return -1;	}	return 0;}/****************************************************************************/static int process_olc(struct sk_buff **pskb, struct ip_conntrack *ct,		       enum ip_conntrack_info ctinfo,		       unsigned char **data, int dataoff,		       OpenLogicalChannel * olc){	int ret;	DEBUGP("ip_ct_h323: OpenLogicalChannel\n");	if (olc->forwardLogicalChannelParameters.multiplexParameters.choice ==	    eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)	{		ret = process_h245_channel(pskb, ct, ctinfo, data, dataoff,					   &olc->					   forwardLogicalChannelParameters.					   multiplexParameters.					   h2250LogicalChannelParameters);		if (ret < 0)			return -1;	}	if ((olc->options &	     eOpenLogicalChannel_reverseLogicalChannelParameters) &&	    (olc->reverseLogicalChannelParameters.options &	     eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters)	    && (olc->reverseLogicalChannelParameters.multiplexParameters.		choice ==		eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters))	{		ret =		    process_h245_channel(pskb, ct, ctinfo, data, dataoff,					 &olc->					 reverseLogicalChannelParameters.					 multiplexParameters.					 h2250LogicalChannelParameters);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -