summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorRobert Knop <prospero@lindenlab.com>2009-01-19 22:05:19 +0000
committerRobert Knop <prospero@lindenlab.com>2009-01-19 22:05:19 +0000
commitce888706c5589bbd30423cd1cbfb7b168b16d680 (patch)
tree9869898ee1d915bfc6faec72a5c9f5198702f2df /indra
parentf1380f2fc3eecd8dfd2f75d053ff86716d5055f7 (diff)
svn merge -r108236:108243 svn+ssh://svn.lindenlab.com/svn/linden/branches/server/server-1.25
Still merging from server-1.25... one day I will catch up! No conflicts
Diffstat (limited to 'indra')
-rw-r--r--indra/llmessage/llpacketbuffer.cpp3
-rw-r--r--indra/llmessage/llpacketbuffer.h8
-rw-r--r--indra/llmessage/llpacketring.cpp2
-rw-r--r--indra/llmessage/llpacketring.h7
-rw-r--r--indra/llmessage/message.cpp22
-rw-r--r--indra/llmessage/message.h14
-rw-r--r--indra/llmessage/net.cpp84
-rw-r--r--indra/llmessage/net.h2
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