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

📄 nat.cpp

📁 贡献一份commoncpp2,有兴趣的可以研究一下
💻 CPP
字号:
// Copyright (C) 2004-2005 TintaDigital - STI, LDA.//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.//// As a special exception, you may use this file as part of a free software// library without restriction.  Specifically, if other files instantiate// templates or use macros or inline functions from this file, or you compile// this file and link it with other files to produce an executable, this// file does not by itself cause the resulting executable to be covered by// the GNU General Public License.  This exception does not however    // invalidate any other reasons why the executable file might be covered by// the GNU General Public License.    //// This exception applies only to the code released under the name GNU// Common C++.  If you copy code from other releases into a copy of GNU// Common C++, as the General Public License permits, the exception does// not apply to the code that you add in this way.  To avoid misleading// anyone as to the status of such modified files, you must delete// this exception notice from them.//// If you write modifications of your own for GNU Common C++, it is your choice// whether to permit this exception to apply to your modifications.// If you do not wish that, delete this exception notice.///** * @file nat.c * @short Network Address Translation interface implementation. * @author Ricardo Gameiro <rgameiro at tintadigital dot com> **/#include <cc++/config.h>#include "nat.h"#ifdef CCXX_NAT#  ifdef HAVE_SYS_TYPES_H#   include <sys/types.h>#  endif#  ifdef HAVE_SYS_SOCKET_H#   include <sys/socket.h>#  endif# ifdef HAVE_NAT_NETFILTER // Linux#  ifdef HAVE_LIMITS_H#   include <limits.h>#  endif#  ifdef HAVE_LINUX_NETFILTER_IPV4_H#   include <linux/netfilter_ipv4.h>#  endif#  ifdef HAVE_LINUX_NETFILTER_IPV6_H#   include <linux/netfilter_ipv6.h>#  endif# else#  ifdef HAVE_NET_IP6_H#   include <netinet/ip6.h>#  endif#  ifdef HAVE_NETINET_IN_H#   include <netinet/in.h>#  endif#  ifdef HAVE_NET_IF_H#   include <net/if.h>#  endif#  ifdef HAVE_SYS_IOCTL_H#   include <sys/ioctl.h>#  endif#  ifdef HAVE_IOCTL_H#   include <ioctl.h>#  endif#  ifdef HAVE_UNISTD_H#   include <unistd.h>#  endif#  ifdef HAVE_ERRNO_H#   include <errno.h>#  endif#  ifdef HAVE_NAT_IPF // Solaris, *BSD (except OpenBSD), HP-UX#   ifdef HAVE_NETINET_IP_COMPAT_H#    include <netinet/ip_compat.h>#   endif#   ifdef HAVE_IP_COMPAT_H#    include <ip_compat.h>#   endif#   ifdef HAVE_NETINET_IP_FIL_COMPAT_H#    include <netinet/ip_fil_compat.h>#   endif#   ifdef HAVE_IP_FIL_COMPAT_H#    include <ip_fil_compat.h>#   endif#   ifdef HAVE_NETINET_IP_FIL_H#    include <netinet/ip_fil.h>#   endif#   ifdef HAVE_IP_FIL_H#    include <ip_fil.h>#   endif#   ifdef HAVE_NETINET_IP_NAT_H#    include <netinet/ip_nat.h>#   endif#   ifdef HAVE_IP_NAT_H#    include <ip_nat.h>#   endif#  endif#  ifdef HAVE_NAT_PF // OpenBSD#   ifdef HAVE_NET_PFVAR_H#    include <net/pfvar.h>#   endif#  endif# endif#endif#ifdef	CCXX_NAMESPACESnamespace ost {#endif#ifdef HAVE_NAT_NETFILTER# define NAT_SYSCALL "getsockopt"# define NAT_DEVICE ""#else# define NAT_SYSCALL "ioctl"# ifdef HAVE_NAT_IPF#  define NAT_DEVICE IPL_NAT# else#  ifdef HAVE_NAT_PF#   define NAT_DEVICE "/dev/pf"#  endif# endif#endif#ifdef CCXX_NATchar * natmsg[] = {                    "nat lookup successful",                    "nat address not in table",                    "nat not supported/implemented",                    "unable to open device "NAT_DEVICE,                    "unable to get socket name",                    "unable to get peer name",                    "unable to get socket type",                    "unable to lookup, nat "NAT_SYSCALL" failed",                    "unkown nat error code"                  };#ifdef HAVE_NAT_NETFILTER // LinuxnatResult natv4Lookup( SOCKET sfd, struct sockaddr_in * nat ){	struct sockaddr_in local;	socklen_t nlen = sizeof( *nat ), llen = sizeof( local );	if( getsockname( sfd, ( struct sockaddr * ) &local, &llen ) )		return natSocknameErr;	memset( &nat->sin_addr.s_addr, 0, sizeof( nat->sin_addr.s_addr ) );	if( getsockopt( sfd, SOL_IP, SO_ORIGINAL_DST, ( struct sockaddr * ) nat, &nlen) )		return natIFaceErr;	if( local.sin_addr.s_addr == nat->sin_addr.s_addr )		return natSearchErr;	nat->sin_family = local.sin_family;	return natOK;}#ifdef CCXX_IPV6natResult natv6Lookup( SOCKET sfd, struct sockaddr_in6 * nat ) {	struct sockaddr_in6 local;	socklen_t llen = sizeof( local ), nlen = sizeof( *nat );	if( getsockname( sfd, ( struct sockaddr * ) &local, &llen ) )		return natSocknameErr;	memset( &nat->sin6_addr.s6_addr, 0, sizeof( nat->sin6_addr.s6_addr ) );	if( getsockopt( sfd, SOL_IP, SO_ORIGINAL_DST, ( struct sockaddr * ) nat, &nlen) )		return natIFaceErr;	if( local.sin6_addr.s6_addr == nat->sin6_addr.s6_addr )		return natSearchErr;	nat->sin6_family = local.sin6_family;	return natOK;}#endif#endif#ifdef HAVE_NAT_IPF // Solaris, *BSD (except OpenBSD), HP-UX, etc.natResult natv4Lookup( int sfd, struct sockaddr_in * nat ) {	static int natfd = -1;	struct sockaddr_in local, peer;	socklen_t  nlen = sizeof( *nat ), llen = sizeof( local ), plen = sizeof( peer );	int socktype;	socklen_t stlen = sizeof( socktype );	struct natlookup nlu;	int nres;	if( natfd < 0 )		if( ( natfd = open( NAT_DEVICE, O_RDONLY, 0 ) ) < 0 )			return natDevUnavail;	if( getsockname( sfd, ( struct sockaddr * ) &local, &llen ) )		return natSocknameErr;	if( getpeername( sfd, ( struct sockaddr * ) &peer, &plen ) )		return natPeernameErr;	if( getsockopt( sfd, SOL_SOCKET, SO_TYPE, ( int * ) &socktype, &stlen ) )		return natSockTypeErr;	memset( &nlu.nl_realip.s_addr, 0, sizeof( nlu.nl_realip.s_addr ) );	nlu.nl_inip = local.sin_addr;	nlu.nl_inport = local.sin_port;	nlu.nl_outip = peer.sin_addr;	nlu.nl_outport = peer.sin_port;	nlu.nl_flags = ( socktype == SOCK_STREAM ) ? IPN_TCP : IPN_UDP;	if( 63 == ( SIOCGNATL & 0xff ) ) {		struct natlookup * nlup = &nlu;		nres = ioctl( natfd, SIOCGNATL, &nlup );	} else		nres = ioctl( natfd, SIOCGNATL, &nlu );	if( nres ) {		if( errno != ESRCH ) {			close( natfd );			natfd = -1;			return natIFaceErr;		} else			return natSearchErr;	}	if( local.sin_addr.s_addr == nlu.nl_realip.s_addr )		return natSearchErr;	nat->sin_family = local.sin_family;	nat->sin_port = nlu.nl_realport;	nat->sin_addr = nlu.nl_realip;	return natOK;}#ifdef CCXX_IPV6 // IPV6 is not yet supported by IPFilter natResult natv6Lookup( SOCKET sfd, struct sockaddr_in6 * nat ) {	return natNotSupported;}#endif#endif#ifdef HAVE_NAT_PF // OpenBSDnatResult natv4Lookup( SOCKET sfd, struct sockaddr_in * nat ) {	static int natfd = -1;	struct sockaddr_in local, peer;	socklen_t  nlen = sizeof( *nat ), llen = sizeof( local ), plen = sizeof( peer );	int socktype;	socklen_t stlen = sizeof( socktype );	struct pfioc_natlook nlu;	int nres;	if( natfd < 0 )		if( ( natfd = open( NAT_DEVICE, O_RDWR ) ) < 0 )			return natDevUnavail;	if( getsockname( sfd, ( struct sockaddr * ) &local, &llen ) )		return natSocknameErr;	if( getpeername( sfd, ( struct sockaddr * ) &peer, &plen ) )		return natPeernameErr;	if( getsockopt( sfd, SOL_SOCKET, SO_TYPE, ( int * ) &socktype, &stlen ) )		return natSockTypeErr;	memset( &nlu, 0, sizeof( nlu ) );	nlu.daddr.v4.s_addr = local.sin_addr.s_addr;	nlu.dport = local.sin_port;	nlu.saddr.v4.s_addr = peer.sin_addr.s_addr;	nlu.sport = peer.sin_port;	nlu.af = AF_INET;	nlu.proto = ( socktype == SOCK_STREAM ) ? IPPROTO_TCP : IPROTO_UDP;	nlu.direction = PF_OUT;	if( ioctl( natfd, DIOCNATLOOK, &nlu ) ) {		if( errno != ESRCH ) {			close( natfd );			natfd = -1;			return natIFaceErr;		} else			return natSearchErr;	}	if( local.sin_addr.s_addr == nlu.raddr.v4.s_addr )		return natSearchErr;	nat->sin_family = local.sin_family;	nat->sin_port = nlu.rdport;	nat->sin_addr = nlu.rdaddr.v4;	return natOK;}#ifdef CCXX_IPV6 natResult natv6Lookup( SOCKET sfd, struct sockaddr_in6 * nat ) {	static int natfd = -1;	struct sockaddr_in6 local, peer;	socklen_t  nlen = sizeof( *nat ), llen = sizeof( local ), plen = sizeof( peer );	int socktype;	socklen_t stlen = sizeof( socktype );	struct pfioc_natlook nlu;	int nres;	if( natfd < 0 )		if( ( natfd = open( NAT_DEVICE, O_RDWR ) ) < 0 )			return natDevUnavail;	if( getsockname( sfd, ( struct sockaddr * ) &local, &llen ) )		return natSocknameErr;	if( getpeername( sfd, ( struct sockaddr * ) &peer, &plen ) )		return natPeernameErr;	if( getsockopt( sfd, SOL_SOCKET, SO_TYPE, ( int * ) &socktype, &stlen ) )		return natSockTypeErr;	memset( &nlu, 0, sizeof( nlu ) );	nlu.daddr.v6.s6_addr = local.sin6_addr.s6_addr;	nlu.dport = local.sin6_port;	nlu.saddr.v6.s6_addr = peer.sin6_addr.s6_addr;	nlu.sport = peer.sin6_port;	nlu.af = AF_INET6;	nlu.proto = ( socktype == SOCK_STREAM ) ? IPPROTO_TCP : IPROTO_UDP;	nlu.direction = PF_OUT;	if( ioctl( natfd, DIOCNATLOOK, &nlu ) ) {		if( errno != ESRCH ) {			close( natfd );			natfd = -1;			return natIFaceErr;		} else			return natSearchErr;	}	if( local.sin6_addr.s6_addr == nlu.raddr.v6.s6_addr )		return natSearchErr;	nat->sin6_family = local.sin6_family;	nat->sin6_flowinfo = local.sin6_flowinfo;	nat->sin6_port = nlu.rdport;	nat->sin6_addr = nlu.rdaddr.v6;	return natOK;}#endif#endifchar * natErrorString( natResult res ) {	return natmsg[ ( res >= natOK && res <= natIFaceErr ) ? res : natUnkownErr ];}#elsenatResult natv4Lookup( SOCKET sfd, struct sockaddr_in * nat ) {	return natNotSupported;}#ifdef CCXX_IPV6natResult natv6Lookup( SOCKET sfd, struct sockaddr_in6 * nat ) {	return natNotSupported;}#endifchar * natErrorString( natResult res ) {	return "nat support not included";}#endif#ifdef	CCXX_NAMESPACES}#endif

⌨️ 快捷键说明

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