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

📄 nf_conntrack_h323_main.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		if (ret < 0)			return -1;	}	return 0;}/****************************************************************************/static int process_olca(struct sk_buff *skb, struct nf_conn *ct,			enum ip_conntrack_info ctinfo,			unsigned char **data, int dataoff,			OpenLogicalChannelAck *olca){	H2250LogicalChannelAckParameters *ack;	int ret;	pr_debug("nf_ct_h323: OpenLogicalChannelAck\n");	if ((olca->options &	     eOpenLogicalChannelAck_reverseLogicalChannelParameters) &&	    (olca->reverseLogicalChannelParameters.options &	     eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters)	    && (olca->reverseLogicalChannelParameters.multiplexParameters.		choice ==		eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters))	{		ret = process_h245_channel(skb, ct, ctinfo, data, dataoff,					   &olca->					   reverseLogicalChannelParameters.					   multiplexParameters.					   h2250LogicalChannelParameters);		if (ret < 0)			return -1;	}	if ((olca->options &	     eOpenLogicalChannelAck_forwardMultiplexAckParameters) &&	    (olca->forwardMultiplexAckParameters.choice ==	     eOpenLogicalChannelAck_forwardMultiplexAckParameters_h2250LogicalChannelAckParameters))	{		ack = &olca->forwardMultiplexAckParameters.		    h2250LogicalChannelAckParameters;		if (ack->options &		    eH2250LogicalChannelAckParameters_mediaChannel) {			/* RTP */			ret = expect_rtp_rtcp(skb, ct, ctinfo, data, dataoff,					      &ack->mediaChannel);			if (ret < 0)				return -1;		}		if (ack->options &		    eH2250LogicalChannelAckParameters_mediaControlChannel) {			/* RTCP */			ret = expect_rtp_rtcp(skb, ct, ctinfo, data, dataoff,					      &ack->mediaControlChannel);			if (ret < 0)				return -1;		}	}	if ((olca->options & eOpenLogicalChannelAck_separateStack) &&		olca->separateStack.networkAddress.choice ==		eNetworkAccessParameters_networkAddress_localAreaAddress) {		ret = expect_t120(skb, ct, ctinfo, data, dataoff,				  &olca->separateStack.networkAddress.				  localAreaAddress);		if (ret < 0)			return -1;	}	return 0;}/****************************************************************************/static int process_h245(struct sk_buff *skb, struct nf_conn *ct,			enum ip_conntrack_info ctinfo,			unsigned char **data, int dataoff,			MultimediaSystemControlMessage *mscm){	switch (mscm->choice) {	case eMultimediaSystemControlMessage_request:		if (mscm->request.choice ==		    eRequestMessage_openLogicalChannel) {			return process_olc(skb, ct, ctinfo, data, dataoff,					   &mscm->request.openLogicalChannel);		}		pr_debug("nf_ct_h323: H.245 Request %d\n",			 mscm->request.choice);		break;	case eMultimediaSystemControlMessage_response:		if (mscm->response.choice ==		    eResponseMessage_openLogicalChannelAck) {			return process_olca(skb, ct, ctinfo, data, dataoff,					    &mscm->response.					    openLogicalChannelAck);		}		pr_debug("nf_ct_h323: H.245 Response %d\n",			 mscm->response.choice);		break;	default:		pr_debug("nf_ct_h323: H.245 signal %d\n", mscm->choice);		break;	}	return 0;}/****************************************************************************/static int h245_help(struct sk_buff *skb, unsigned int protoff,		     struct nf_conn *ct, enum ip_conntrack_info ctinfo){	static MultimediaSystemControlMessage mscm;	unsigned char *data = NULL;	int datalen;	int dataoff;	int ret;	/* Until there's been traffic both ways, don't look in packets. */	if (ctinfo != IP_CT_ESTABLISHED &&	    ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {		return NF_ACCEPT;	}	pr_debug("nf_ct_h245: skblen = %u\n", skb->len);	spin_lock_bh(&nf_h323_lock);	/* Process each TPKT */	while (get_tpkt_data(skb, protoff, ct, ctinfo,			     &data, &datalen, &dataoff)) {		pr_debug("nf_ct_h245: TPKT len=%d ", datalen);		NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);		/* Decode H.245 signal */		ret = DecodeMultimediaSystemControlMessage(data, datalen,							   &mscm);		if (ret < 0) {			pr_debug("nf_ct_h245: decoding error: %s\n",				 ret == H323_ERROR_BOUND ?				 "out of bound" : "out of range");			/* We don't drop when decoding error */			break;		}		/* Process H.245 signal */		if (process_h245(skb, ct, ctinfo, &data, dataoff, &mscm) < 0)			goto drop;	}	spin_unlock_bh(&nf_h323_lock);	return NF_ACCEPT;      drop:	spin_unlock_bh(&nf_h323_lock);	if (net_ratelimit())		printk("nf_ct_h245: packet dropped\n");	return NF_DROP;}/****************************************************************************/static struct nf_conntrack_helper nf_conntrack_helper_h245 __read_mostly = {	.name			= "H.245",	.me			= THIS_MODULE,	.max_expected		= H323_RTP_CHANNEL_MAX * 4 + 2 /* T.120 */,	.timeout		= 240,	.tuple.dst.protonum	= IPPROTO_UDP,	.help			= h245_help};/****************************************************************************/int get_h225_addr(struct nf_conn *ct, unsigned char *data,		  TransportAddress *taddr,		  union nf_conntrack_address *addr, __be16 *port){	unsigned char *p;	int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;	int len;	switch (taddr->choice) {	case eTransportAddress_ipAddress:		if (family != AF_INET)			return 0;		p = data + taddr->ipAddress.ip;		len = 4;		break;	case eTransportAddress_ip6Address:		if (family != AF_INET6)			return 0;		p = data + taddr->ip6Address.ip;		len = 16;		break;	default:		return 0;	}	memcpy(addr, p, len);	memset((void *)addr + len, 0, sizeof(*addr) - len);	memcpy(port, p + len, sizeof(__be16));	return 1;}/****************************************************************************/static int expect_h245(struct sk_buff *skb, struct nf_conn *ct,		       enum ip_conntrack_info ctinfo,		       unsigned char **data, int dataoff,		       TransportAddress *taddr){	int dir = CTINFO2DIR(ctinfo);	int ret = 0;	__be16 port;	union nf_conntrack_address addr;	struct nf_conntrack_expect *exp;	typeof(nat_h245_hook) nat_h245;	/* Read h245Address */	if (!get_h225_addr(ct, *data, taddr, &addr, &port) ||	    memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) ||	    port == 0)		return 0;	/* Create expect for h245 connection */	if ((exp = nf_ct_expect_alloc(ct)) == NULL)		return -1;	nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,			  &ct->tuplehash[!dir].tuple.src.u3,			  &ct->tuplehash[!dir].tuple.dst.u3,			  IPPROTO_TCP, NULL, &port);	exp->helper = &nf_conntrack_helper_h245;	if (memcmp(&ct->tuplehash[dir].tuple.src.u3,		   &ct->tuplehash[!dir].tuple.dst.u3,		   sizeof(ct->tuplehash[dir].tuple.src.u3)) &&	    (nat_h245 = rcu_dereference(nat_h245_hook)) &&	    ct->status & IPS_NAT_MASK) {		/* NAT needed */		ret = nat_h245(skb, ct, ctinfo, data, dataoff, taddr,			       port, exp);	} else {		/* Conntrack only */		if (nf_ct_expect_related(exp) == 0) {			pr_debug("nf_ct_q931: expect H.245 ");			NF_CT_DUMP_TUPLE(&exp->tuple);		} else			ret = -1;	}	nf_ct_expect_put(exp);	return ret;}/* If the calling party is on the same side of the forward-to party, * we don't need to track the second call */static int callforward_do_filter(union nf_conntrack_address *src,				 union nf_conntrack_address *dst,				 int family){	struct flowi fl1, fl2;	int ret = 0;	memset(&fl1, 0, sizeof(fl1));	memset(&fl2, 0, sizeof(fl2));	switch (family) {	case AF_INET: {		struct rtable *rt1, *rt2;		fl1.fl4_dst = src->ip;		fl2.fl4_dst = dst->ip;		if (ip_route_output_key(&rt1, &fl1) == 0) {			if (ip_route_output_key(&rt2, &fl2) == 0) {				if (rt1->rt_gateway == rt2->rt_gateway &&				    rt1->u.dst.dev  == rt2->u.dst.dev)					ret = 1;				dst_release(&rt2->u.dst);			}			dst_release(&rt1->u.dst);		}		break;	}#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)	case AF_INET6: {		struct rt6_info *rt1, *rt2;		memcpy(&fl1.fl6_dst, src, sizeof(fl1.fl6_dst));		memcpy(&fl2.fl6_dst, dst, sizeof(fl2.fl6_dst));		rt1 = (struct rt6_info *)ip6_route_output(NULL, &fl1);		if (rt1) {			rt2 = (struct rt6_info *)ip6_route_output(NULL, &fl2);			if (rt2) {				if (!memcmp(&rt1->rt6i_gateway, &rt2->rt6i_gateway,					    sizeof(rt1->rt6i_gateway)) &&				    rt1->u.dst.dev == rt2->u.dst.dev)					ret = 1;				dst_release(&rt2->u.dst);			}			dst_release(&rt1->u.dst);		}		break;	}#endif	}	return ret;}/****************************************************************************/static int expect_callforwarding(struct sk_buff *skb,				 struct nf_conn *ct,				 enum ip_conntrack_info ctinfo,				 unsigned char **data, int dataoff,				 TransportAddress *taddr){	int dir = CTINFO2DIR(ctinfo);	int ret = 0;	__be16 port;	union nf_conntrack_address addr;	struct nf_conntrack_expect *exp;	typeof(nat_callforwarding_hook) nat_callforwarding;	/* Read alternativeAddress */	if (!get_h225_addr(ct, *data, taddr, &addr, &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 (callforward_filter &&	    callforward_do_filter(&addr, &ct->tuplehash[!dir].tuple.src.u3,				  ct->tuplehash[!dir].tuple.src.l3num)) {		pr_debug("nf_ct_q931: Call Forwarding not tracked\n");		return 0;	}	/* Create expect for the second call leg */	if ((exp = nf_ct_expect_alloc(ct)) == NULL)		return -1;	nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,			  &ct->tuplehash[!dir].tuple.src.u3, &addr,			  IPPROTO_TCP, NULL, &port);	exp->helper = nf_conntrack_helper_q931;	if (memcmp(&ct->tuplehash[dir].tuple.src.u3,		   &ct->tuplehash[!dir].tuple.dst.u3,		   sizeof(ct->tuplehash[dir].tuple.src.u3)) &&	    (nat_callforwarding = rcu_dereference(nat_callforwarding_hook)) &&	    ct->status & IPS_NAT_MASK) {		/* Need NAT */		ret = nat_callforwarding(skb, ct, ctinfo, data, dataoff,					 taddr, port, exp);	} else {		/* Conntrack only */		if (nf_ct_expect_related(exp) == 0) {			pr_debug("nf_ct_q931: expect Call Forwarding ");			NF_CT_DUMP_TUPLE(&exp->tuple);		} else			ret = -1;	}	nf_ct_expect_put(exp);	return ret;}/****************************************************************************/static int process_setup(struct sk_buff *skb, struct nf_conn *ct,			 enum ip_conntrack_info ctinfo,			 unsigned char **data, int dataoff,			 Setup_UUIE *setup){	int dir = CTINFO2DIR(ctinfo);	int ret;	int i;	__be16 port;	union nf_conntrack_address addr;	typeof(set_h225_addr_hook) set_h225_addr;	pr_debug("nf_ct_q931: Setup\n");	if (setup->options & eSetup_UUIE_h245Address) {		ret = expect_h245(skb, ct, ctinfo, data, dataoff,				  &setup->h245Address);		if (ret < 0)			return -1;	}	set_h225_addr = rcu_dereference(set_h225_addr_hook);	if ((setup->options & eSetup_UUIE_destCallSignalAddress) &&	    (set_h225_addr) && ct->status && IPS_NAT_MASK &&	    get_h225_addr(ct, *data, &setup->destCallSignalAddress,			  &addr, &port) &&	    memcmp(&addr, &ct->tuplehash[!dir].tuple.src.u3, sizeof(addr))) {		pr_debug("nf_ct_q931: set destCallSignalAddress "			 NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n",			 NIP6(*(struct in6_addr *)&addr), ntohs(port),			 NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.src.u3),			 ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port));		ret = set_h225_addr(skb, data, dataoff,				    &setup->destCallSignalAddress,				    &ct->tuplehash[!dir].tuple.src.u3,				    ct->tuplehash[!dir].tuple.src.u.tcp.port);		if (ret < 0)			return -1;	}	if ((setup->options & eSetup_UUIE_sourceCallSignalAddress) &&	    (set_h225_addr) && ct->status & IPS_NAT_MASK &&	    get_h225_addr(ct, *data, &setup->sourceCallSignalAddress,			  &addr, &port) &&	    memcmp(&addr, &ct->tuplehash[!dir].tuple.dst.u3, sizeof(addr))) {		pr_debug("nf_ct_q931: set sourceCallSignalAddress "			 NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n",			 NIP6(*(struct in6_addr *)&addr), ntohs(port),			 NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.dst.u3),			 ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port));		ret = set_h225_addr(skb, data, dataoff,				    &setup->sourceCallSignalAddress,				    &ct->tuplehash[!dir].tuple.dst.u3,				    ct->tuplehash[!dir].tuple.dst.u.tcp.port);		if (ret < 0)			return -1;	}	if (setup->options & eSetup_UUIE_fastStart) {		for (i = 0; i < setup->fastStart.count; i++) {			ret = process_olc(skb, ct, ctinfo, data, dataoff,					  &setup->fastStart.item[i]);			if (ret < 0)				return -1;		}	}	return 0;}/****************************************************************************/static int process_callproceeding(struct sk_buff *skb,				  struct nf_conn *ct,				  enum ip_conntrack_info ctinfo,				  unsigned char **data, int dataoff,				  CallProceeding_UUIE *callproc){	int ret;	int i;	pr_debug("nf_ct_q931: CallProceeding\n");	if (callproc->options & eCallProceeding_UUIE_h245Address) {		ret = expect_h245(skb, ct, ctinfo, data, dataoff,				  &callproc->h245Address);		if (ret < 0)			return -1;	}	if (callproc->options & eCallProceeding_UUIE_fastStart) {

⌨️ 快捷键说明

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