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

📄 nf_nat_h323.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * H.323 extension for NAT alteration. * * 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 NAT module by * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> */#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/tcp.h>#include <net/tcp.h>#include <net/netfilter/nf_nat.h>#include <net/netfilter/nf_nat_helper.h>#include <net/netfilter/nf_nat_rule.h>#include <net/netfilter/nf_conntrack_helper.h>#include <net/netfilter/nf_conntrack_expect.h>#include <linux/netfilter/nf_conntrack_h323.h>/****************************************************************************/static int set_addr(struct sk_buff *skb,		    unsigned char **data, int dataoff,		    unsigned int addroff, __be32 ip, __be16 port){	enum ip_conntrack_info ctinfo;	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);	struct {		__be32 ip;		__be16 port;	} __attribute__ ((__packed__)) buf;	struct tcphdr _tcph, *th;	buf.ip = ip;	buf.port = port;	addroff += dataoff;	if (ip_hdr(skb)->protocol == IPPROTO_TCP) {		if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo,					      addroff, sizeof(buf),					      (char *) &buf, sizeof(buf))) {			if (net_ratelimit())				printk("nf_nat_h323: nf_nat_mangle_tcp_packet"				       " error\n");			return -1;		}		/* Relocate data pointer */		th = skb_header_pointer(skb, ip_hdrlen(skb),					sizeof(_tcph), &_tcph);		if (th == NULL)			return -1;		*data = skb->data + ip_hdrlen(skb) + th->doff * 4 + dataoff;	} else {		if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo,					      addroff, sizeof(buf),					      (char *) &buf, sizeof(buf))) {			if (net_ratelimit())				printk("nf_nat_h323: nf_nat_mangle_udp_packet"				       " error\n");			return -1;		}		/* nf_nat_mangle_udp_packet uses skb_make_writable() to copy		 * or pull everything in a linear buffer, so we can safely		 * use the skb pointers now */		*data = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr);	}	return 0;}/****************************************************************************/static int set_h225_addr(struct sk_buff *skb,			 unsigned char **data, int dataoff,			 TransportAddress *taddr,			 union nf_conntrack_address *addr, __be16 port){	return set_addr(skb, data, dataoff, taddr->ipAddress.ip,			addr->ip, port);}/****************************************************************************/static int set_h245_addr(struct sk_buff *skb,			 unsigned char **data, int dataoff,			 H245_TransportAddress *taddr,			 union nf_conntrack_address *addr, __be16 port){	return set_addr(skb, data, dataoff,			taddr->unicastAddress.iPAddress.network,			addr->ip, port);}/****************************************************************************/static int set_sig_addr(struct sk_buff *skb, struct nf_conn *ct,			enum ip_conntrack_info ctinfo,			unsigned char **data,			TransportAddress *taddr, int count){	struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;	int dir = CTINFO2DIR(ctinfo);	int i;	__be16 port;	union nf_conntrack_address addr;	for (i = 0; i < count; i++) {		if (get_h225_addr(ct, *data, &taddr[i], &addr, &port)) {			if (addr.ip == ct->tuplehash[dir].tuple.src.u3.ip &&			    port == info->sig_port[dir]) {				/* GW->GK */				/* Fix for Gnomemeeting */				if (i > 0 &&				    get_h225_addr(ct, *data, &taddr[0],						  &addr, &port) &&				    (ntohl(addr.ip) & 0xff000000) == 0x7f000000)					i = 0;				pr_debug("nf_nat_ras: set signal address "					 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",					 NIPQUAD(addr.ip), port,					 NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip),					 info->sig_port[!dir]);				return set_h225_addr(skb, data, 0, &taddr[i],						     &ct->tuplehash[!dir].						     tuple.dst.u3,						     info->sig_port[!dir]);			} else if (addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip &&				   port == info->sig_port[dir]) {				/* GK->GW */				pr_debug("nf_nat_ras: set signal address "					 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",					 NIPQUAD(addr.ip), port,					 NIPQUAD(ct->tuplehash[!dir].tuple.src.u3.ip),					 info->sig_port[!dir]);				return set_h225_addr(skb, data, 0, &taddr[i],						     &ct->tuplehash[!dir].						     tuple.src.u3,						     info->sig_port[!dir]);			}		}	}	return 0;}/****************************************************************************/static int set_ras_addr(struct sk_buff *skb, struct nf_conn *ct,			enum ip_conntrack_info ctinfo,			unsigned char **data,			TransportAddress *taddr, int count){	int dir = CTINFO2DIR(ctinfo);	int i;	__be16 port;	union nf_conntrack_address addr;	for (i = 0; i < count; i++) {		if (get_h225_addr(ct, *data, &taddr[i], &addr, &port) &&		    addr.ip == ct->tuplehash[dir].tuple.src.u3.ip &&		    port == ct->tuplehash[dir].tuple.src.u.udp.port) {			pr_debug("nf_nat_ras: set rasAddress "				 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",				 NIPQUAD(addr.ip), ntohs(port),				 NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip),				 ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port));			return set_h225_addr(skb, data, 0, &taddr[i],					     &ct->tuplehash[!dir].tuple.dst.u3,					     ct->tuplehash[!dir].tuple.								dst.u.udp.port);		}	}	return 0;}/****************************************************************************/static int nat_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,			enum ip_conntrack_info ctinfo,			unsigned char **data, int dataoff,			H245_TransportAddress *taddr,			__be16 port, __be16 rtp_port,			struct nf_conntrack_expect *rtp_exp,			struct nf_conntrack_expect *rtcp_exp){	struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;	int dir = CTINFO2DIR(ctinfo);	int i;	u_int16_t nated_port;	/* Set expectations for NAT */	rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port;	rtp_exp->expectfn = nf_nat_follow_master;	rtp_exp->dir = !dir;	rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port;	rtcp_exp->expectfn = nf_nat_follow_master;	rtcp_exp->dir = !dir;	/* Lookup existing expects */	for (i = 0; i < H323_RTP_CHANNEL_MAX; i++) {		if (info->rtp_port[i][dir] == rtp_port) {			/* Expected */			/* Use allocated ports first. This will refresh			 * the expects */			rtp_exp->tuple.dst.u.udp.port = info->rtp_port[i][dir];			rtcp_exp->tuple.dst.u.udp.port =			    htons(ntohs(info->rtp_port[i][dir]) + 1);			break;		} else if (info->rtp_port[i][dir] == 0) {			/* Not expected */			break;		}	}	/* Run out of expectations */	if (i >= H323_RTP_CHANNEL_MAX) {		if (net_ratelimit())			printk("nf_nat_h323: out of expectations\n");		return 0;	}	/* Try to get a pair of ports. */	for (nated_port = ntohs(rtp_exp->tuple.dst.u.udp.port);	     nated_port != 0; nated_port += 2) {		rtp_exp->tuple.dst.u.udp.port = htons(nated_port);		if (nf_ct_expect_related(rtp_exp) == 0) {			rtcp_exp->tuple.dst.u.udp.port =			    htons(nated_port + 1);			if (nf_ct_expect_related(rtcp_exp) == 0)				break;			nf_ct_unexpect_related(rtp_exp);		}	}	if (nated_port == 0) {	/* No port available */		if (net_ratelimit())			printk("nf_nat_h323: out of RTP ports\n");		return 0;	}	/* Modify signal */	if (set_h245_addr(skb, data, dataoff, taddr,			  &ct->tuplehash[!dir].tuple.dst.u3,			  htons((port & htons(1)) ? nated_port + 1 :						    nated_port)) == 0) {		/* Save ports */		info->rtp_port[i][dir] = rtp_port;		info->rtp_port[i][!dir] = htons(nated_port);	} else {		nf_ct_unexpect_related(rtp_exp);		nf_ct_unexpect_related(rtcp_exp);		return -1;	}	/* Success */	pr_debug("nf_nat_h323: expect RTP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",		 NIPQUAD(rtp_exp->tuple.src.u3.ip),		 ntohs(rtp_exp->tuple.src.u.udp.port),		 NIPQUAD(rtp_exp->tuple.dst.u3.ip),		 ntohs(rtp_exp->tuple.dst.u.udp.port));	pr_debug("nf_nat_h323: expect RTCP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",		 NIPQUAD(rtcp_exp->tuple.src.u3.ip),		 ntohs(rtcp_exp->tuple.src.u.udp.port),		 NIPQUAD(rtcp_exp->tuple.dst.u3.ip),		 ntohs(rtcp_exp->tuple.dst.u.udp.port));	return 0;}/****************************************************************************/static int nat_t120(struct sk_buff *skb, struct nf_conn *ct,		    enum ip_conntrack_info ctinfo,		    unsigned char **data, int dataoff,		    H245_TransportAddress *taddr, __be16 port,		    struct nf_conntrack_expect *exp){	int dir = CTINFO2DIR(ctinfo);	u_int16_t nated_port = ntohs(port);	/* Set expectations for NAT */	exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;	exp->expectfn = nf_nat_follow_master;	exp->dir = !dir;	/* Try to get same port: if not, try to change it. */	for (; nated_port != 0; nated_port++) {		exp->tuple.dst.u.tcp.port = htons(nated_port);		if (nf_ct_expect_related(exp) == 0)			break;	}	if (nated_port == 0) {	/* No port available */		if (net_ratelimit())

⌨️ 快捷键说明

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