diff options
Diffstat (limited to 'indra')
-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 |