diff options
| -rw-r--r-- | indra/llmessage/llpacketbuffer.cpp | 3 | ||||
| -rw-r--r-- | indra/llmessage/llpacketbuffer.h | 8 | ||||
| -rw-r--r-- | indra/llmessage/llpacketring.cpp | 2 | ||||
| -rw-r--r-- | indra/llmessage/llpacketring.h | 7 | ||||
| -rw-r--r-- | indra/llmessage/message.cpp | 22 | ||||
| -rw-r--r-- | indra/llmessage/message.h | 14 | ||||
| -rw-r--r-- | indra/llmessage/net.cpp | 84 | ||||
| -rw-r--r-- | indra/llmessage/net.h | 2 | 
8 files changed, 137 insertions, 5 deletions
| diff --git a/indra/llmessage/llpacketbuffer.cpp b/indra/llmessage/llpacketbuffer.cpp index 9907ba0070..027d35cf89 100644 --- a/indra/llmessage/llpacketbuffer.cpp +++ b/indra/llmessage/llpacketbuffer.cpp @@ -74,5 +74,6 @@ void LLPacketBuffer::init (S32 hSocket)  {  	mSize = receive_packet(hSocket, mData);  	mHost = ::get_sender(); +	mReceivingIF = ::get_receiving_interface();  } -	 + diff --git a/indra/llmessage/llpacketbuffer.h b/indra/llmessage/llpacketbuffer.h index 38e1f2f4f0..bbcbdf28b2 100644 --- a/indra/llmessage/llpacketbuffer.h +++ b/indra/llmessage/llpacketbuffer.h @@ -44,15 +44,17 @@ public:  	LLPacketBuffer(S32 hSocket);           // receive a packet  	~LLPacketBuffer(); -	S32			getSize() const		{ return mSize; } -	const char	*getData() const	{ return mData; } -	LLHost		getHost() const		{ return mHost; } +	S32			getSize() const					{ return mSize; } +	const char	*getData() const				{ return mData; } +	LLHost		getHost() const					{ return mHost; } +	LLHost		getReceivingInterface() const	{ return mReceivingIF; }  	void init(S32 hSocket);  protected:  	char	mData[NET_BUFFER_SIZE];        // packet data		/* Flawfinder : ignore */  	S32		mSize;          // size of buffer in bytes  	LLHost	mHost;         // source/dest IP and port +	LLHost	mReceivingIF;         // source/dest IP and port  };  #endif diff --git a/indra/llmessage/llpacketring.cpp b/indra/llmessage/llpacketring.cpp index 6ecdf702ac..35d5aac776 100644 --- a/indra/llmessage/llpacketring.cpp +++ b/indra/llmessage/llpacketring.cpp @@ -141,6 +141,7 @@ S32 LLPacketRing::receiveFromRing (S32 socket, char *datap)  	}  	// need to set sender IP/port!!  	mLastSender = packetp->getHost(); +	mLastReceivingIF = packetp->getReceivingInterface();  	delete packetp;  	this->mInBufferLength -= packet_size; @@ -223,6 +224,7 @@ S32 LLPacketRing::receivePacket (S32 socket, char *datap)  		// no delay, pull straight from net  		packet_size = receive_packet(socket, datap);		  		mLastSender = ::get_sender(); +		mLastReceivingIF = ::get_receiving_interface();  		if (packet_size)  // did we actually get a packet?  		{ diff --git a/indra/llmessage/llpacketring.h b/indra/llmessage/llpacketring.h index a1bac5bc70..4408abeb5f 100644 --- a/indra/llmessage/llpacketring.h +++ b/indra/llmessage/llpacketring.h @@ -62,6 +62,7 @@ public:  	BOOL sendPacket(int h_socket, char * send_buffer, S32 buf_size, LLHost host);  	inline LLHost getLastSender(); +	inline LLHost getLastReceivingInterface();  	S32 getAndResetActualInBits()				{ S32 bits = mActualBitsIn; mActualBitsIn = 0; return bits;}  	S32 getAndResetActualOutBits()				{ S32 bits = mActualBitsOut; mActualBitsOut = 0; return bits;} @@ -86,6 +87,7 @@ protected:  	std::queue<LLPacketBuffer *> mSendQueue;  	LLHost mLastSender; +	LLHost mLastReceivingIF;  }; @@ -94,4 +96,9 @@ inline LLHost LLPacketRing::getLastSender()  	return mLastSender;  } +inline LLHost LLPacketRing::getLastReceivingInterface() +{ +	return mLastReceivingIF; +} +  #endif diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp index 83e1ddb894..d5f362d780 100644 --- a/indra/llmessage/message.cpp +++ b/indra/llmessage/message.cpp @@ -306,6 +306,9 @@ LLMessageSystem::LLMessageSystem(const std::string& filename, U32 port,  	// default to not accepting packets from not alive circuits  	mbProtected = TRUE; +	// default to blocking trusted connections on a public interface if one is specified +	mBlockUntrustedInterface = true; +  	mSendPacketFailureCount = 0;  	mCircuitPrintFreq = 60.f;		// seconds @@ -440,6 +443,7 @@ void LLMessageSystem::clearReceiveState()  	mCurrentRecvPacketID = 0;  	mIncomingCompressedSize = 0;  	mLastSender.invalidate(); +	mLastReceivingIF.invalidate();  	mMessageReader->clearMessage();  } @@ -589,6 +593,7 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count )  		receive_size = mTrueReceiveSize;  		mLastSender = mPacketRing.getLastSender(); +		mLastReceivingIF = mPacketRing.getLastReceivingInterface();  		if (receive_size < (S32) LL_MINIMUM_VALID_PACKET_SIZE)  		{ @@ -2355,6 +2360,23 @@ void process_create_trusted_circuit(LLMessageSystem *msg, void **)  		return;  	} +	U32 untrusted_interface = msg->getUntrustedInterface().getAddress(); +	U32 last_interface = msg->getReceivingInterface().getAddress(); +	if ( ( untrusted_interface != INVALID_HOST_IP_ADDRESS ) && ( untrusted_interface == last_interface ) ) +	{ +		if( msg->getBlockUntrustedInterface() ) +		{ +			LL_WARNS("Messaging") << "Refusing trust on public interface from host: " +				<< msg->getSender() << llendl; +			return; +		} +		else +		{ +			LL_WARNS("Messaging") << "Establishing trust on public interface from host: " +				<< msg->getSender() << llendl; +		} +	} +  	char their_digest[MD5HEX_STR_SIZE];	/* Flawfinder: ignore */  	S32 size = msg->getSizeFast(_PREHASH_DataBlock, _PREHASH_Digest);  	if(size != MD5HEX_STR_BYTES) diff --git a/indra/llmessage/message.h b/indra/llmessage/message.h index f4e136ee4d..25eeb85323 100644 --- a/indra/llmessage/message.h +++ b/indra/llmessage/message.h @@ -212,6 +212,9 @@ class LLMessageSystem  	U8					mSendBuffer[MAX_BUFFER_SIZE];  	S32					mSendSize; +	bool				mBlockUntrustedInterface; +	LLHost				mUntrustedInterface; +   public:  	LLPacketRing				mPacketRing;  	LLReliablePacketParams			mReliablePacketParams; @@ -352,6 +355,8 @@ public:  	U32		getSenderIP() const;			// getSender() is preferred  	U32		getSenderPort() const;		// getSender() is preferred +	const LLHost& getReceivingInterface() const; +  	// This method returns the uuid associated with the sender. The  	// UUID will be null if it is not yet known or is a server  	// circuit. @@ -564,6 +569,12 @@ public:  	/** Return false true if name is unknown or trusted */  	bool isUntrustedMessage(const std::string& name) const; +	// Mark an interface ineligible for trust +	void setUntrustedInterface( const LLHost host ) { mUntrustedInterface = host; } +	LLHost getUntrustedInterface() const { return mUntrustedInterface; } +	void setBlockUntrustedInterface( bool block ) { mBlockUntrustedInterface = block; } // Throw a switch to allow, sending warnings only +	bool getBlockUntrustedInterface() const { return mBlockUntrustedInterface; } +  	// Change this message to be UDP black listed.  	void banUdpMessage(const std::string& name); @@ -747,6 +758,7 @@ private:  	void init(); // ctor shared initialisation.  	LLHost mLastSender; +	LLHost mLastReceivingIF;  	S32 mIncomingCompressedSize;		// original size of compressed msg (0 if uncomp.)  	TPACKETID mCurrentRecvPacketID;       // packet ID of current receive packet (for reporting) @@ -966,6 +978,7 @@ inline void *ntohmemcpy(void *s, const void *ct, EMsgVariableType type, size_t n  inline const LLHost& LLMessageSystem::getSender() const {return mLastSender;} +inline const LLHost& LLMessageSystem::getReceivingInterface() const {return mLastReceivingIF;}  inline U32 LLMessageSystem::getSenderIP() const   { @@ -977,6 +990,7 @@ inline U32 LLMessageSystem::getSenderPort() const  	return mLastSender.getPort();  } +  //-----------------------------------------------------------------------------  // Transmission aliases  //----------------------------------------------------------------------------- diff --git a/indra/llmessage/net.cpp b/indra/llmessage/net.cpp index 4f2242fe52..94a0feb6a7 100644 --- a/indra/llmessage/net.cpp +++ b/indra/llmessage/net.cpp @@ -71,6 +71,7 @@ static WSADATA stWSAData;  struct sockaddr_in stDstAddr;  struct sockaddr_in stSrcAddr;  struct sockaddr_in stLclAddr; +static U32 gsnReceivingIFAddr = INVALID_HOST_IP_ADDRESS; // Address to which datagram was sent  #if LL_DARWIN  #ifndef _SOCKLEN_T @@ -110,6 +111,16 @@ U32 get_sender_port()  	return ntohs(stSrcAddr.sin_port);  } +LLHost get_receiving_interface() +{ +	return LLHost(gsnReceivingIFAddr, INVALID_PORT); +} + +U32 get_receiving_interface_ip(void) +{ +	return gsnReceivingIFAddr; +} +  const char* u32_to_ip_string(U32 ip)  {  	static char buffer[MAXADDRSTR];	 /* Flawfinder: ignore */  @@ -455,6 +466,21 @@ S32 start_net(S32& socket_out, int& nPort)  	llinfos << "startNet - receive buffer size : " << rec_size << llendl;  	llinfos << "startNet - send buffer size    : " << snd_size << llendl; +#if LL_LINUX +	// Turn on recipient address tracking +	{ +		int use_pktinfo = 1; +		if( setsockopt( hSocket, SOL_IP, IP_PKTINFO, &use_pktinfo, sizeof(use_pktinfo) ) == -1 ) +		{ +			llwarns << "No IP_PKTINFO available" << llendl; +		} +		else +		{ +			llinfos << "IP_PKKTINFO enabled" << llendl; +		} +	} +#endif +  	//  Setup a destination address  	char achMCAddr[MAXADDRSTR] = "127.0.0.1";	/* Flawfinder: ignore */   	stDstAddr.sin_family =      AF_INET; @@ -473,6 +499,52 @@ void end_net(S32& socket_out)  	}  } +#if LL_LINUX +static int recvfrom_destip( int socket, void *buf, int len, struct sockaddr *from, socklen_t *fromlen, U32 *dstip ) +{ +	int size; +	struct iovec iov[1]; +	char cmsg[CMSG_SPACE(sizeof(struct in_pktinfo))]; +	struct cmsghdr *cmsgptr; +	struct msghdr msg = {0}; + +	iov[0].iov_base = buf; +	iov[0].iov_len = len; + +	memset( &msg, 0, sizeof msg ); +	msg.msg_name = from; +	msg.msg_namelen = *fromlen; +	msg.msg_iov = iov; +	msg.msg_iovlen = 1; +	msg.msg_control = &cmsg; +	msg.msg_controllen = sizeof(cmsg); + +	size = recvmsg( socket, &msg, 0 ); + +	if( size == -1 ) +	{ +		return -1; +	} + +	for( cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR( &msg, cmsgptr ) ) +	{ +		if( cmsgptr->cmsg_level == SOL_IP && cmsgptr->cmsg_type == IP_PKTINFO ) +		{ +			in_pktinfo *pktinfo = (in_pktinfo *)CMSG_DATA(cmsgptr); +			if( pktinfo ) +			{ +				// Two choices. routed and specified. ipi_addr is routed, ipi_spec_dst is +				// routed. We should stay with specified until we go to multiple +				// interfaces +				*dstip = pktinfo->ipi_spec_dst.s_addr; +			} +		} +	} + +	return size; +} +#endif +  int receive_packet(int hSocket, char * receiveBuffer)  {  	//  Receives data asynchronously from the socket set by initNet(). @@ -482,7 +554,14 @@ int receive_packet(int hSocket, char * receiveBuffer)  	int nRet;  	socklen_t addr_size = sizeof(struct sockaddr_in); -	nRet = recvfrom(hSocket, receiveBuffer, NET_BUFFER_SIZE, 0, (struct sockaddr*)&stSrcAddr, &addr_size); +	gsnReceivingIFAddr = INVALID_HOST_IP_ADDRESS; + +#if LL_LINUX +	nRet = recvfrom_destip(hSocket, receiveBuffer, NET_BUFFER_SIZE, (struct sockaddr*)&stSrcAddr, &addr_size, &gsnReceivingIFAddr); +#else	 +	int recv_flags = 0; +	nRet = recvfrom(hSocket, receiveBuffer, NET_BUFFER_SIZE, recv_flags, (struct sockaddr*)&stSrcAddr, &addr_size); +#endif  	if (nRet == -1)  	{ @@ -490,6 +569,9 @@ int receive_packet(int hSocket, char * receiveBuffer)  		return 0;  	} +	// Uncomment for testing if/when implementing for Mac or Windows: +	// llinfos << "Received datagram to in addr " << u32_to_ip_string(get_receiving_interface_ip()) << llendl; +  	return nRet;  } diff --git a/indra/llmessage/net.h b/indra/llmessage/net.h index 9a97b34100..45b07a0ab8 100644 --- a/indra/llmessage/net.h +++ b/indra/llmessage/net.h @@ -55,6 +55,8 @@ BOOL	send_packet(int hSocket, const char *sendBuffer, int size, U32 recipient, i  LLHost  get_sender();  U32		get_sender_port();  U32		get_sender_ip(void); +LLHost  get_receiving_interface(); +U32		get_receiving_interface_ip(void);  const char*	u32_to_ip_string(U32 ip);					// Returns pointer to internal string buffer, "(bad IP addr)" on failure, cannot nest calls   char*		u32_to_ip_string(U32 ip, char *ip_string);	// NULL on failure, ip_string on success, you must allocate at least MAXADDRSTR chars | 
