diff options
Diffstat (limited to 'indra/llmessage')
-rw-r--r-- | indra/llmessage/CMakeLists.txt | 2 | ||||
-rw-r--r-- | indra/llmessage/llcurl.cpp | 133 | ||||
-rw-r--r-- | indra/llmessage/llcurl.h | 118 | ||||
-rw-r--r-- | indra/llmessage/llhttpassetstorage.cpp | 5 | ||||
-rw-r--r-- | indra/llmessage/llhttpclient.cpp | 5 | ||||
-rw-r--r-- | indra/llmessage/lliosocket.cpp | 2 | ||||
-rw-r--r-- | indra/llmessage/lliosocket.h | 14 | ||||
-rw-r--r-- | indra/llmessage/llpacketring.cpp | 65 | ||||
-rw-r--r-- | indra/llmessage/llpacketring.h | 12 | ||||
-rw-r--r-- | indra/llmessage/llproxy.cpp | 411 | ||||
-rw-r--r-- | indra/llmessage/llproxy.h | 266 | ||||
-rw-r--r-- | indra/llmessage/llurlrequest.cpp | 5 | ||||
-rw-r--r-- | indra/llmessage/net.cpp | 39 | ||||
-rw-r--r-- | indra/llmessage/net.h | 4 |
14 files changed, 919 insertions, 162 deletions
diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index c5f82cf052..0f40a670fa 100644 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -65,6 +65,7 @@ set(llmessage_SOURCE_FILES llpacketbuffer.cpp llpacketring.cpp llpartdata.cpp + llproxy.cpp llpumpio.cpp llregionpresenceverifier.cpp llsdappservices.cpp @@ -161,6 +162,7 @@ set(llmessage_HEADER_FILES llpacketring.h llpartdata.h llpumpio.h + llproxy.h llqueryflags.h llregionflags.h llregionhandle.h diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 0735842dcd..7a041239bc 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -46,8 +46,9 @@ #endif #include "llbufferstream.h" -#include "llstl.h" +#include "llproxy.h" #include "llsdserialize.h" +#include "llstl.h" #include "llthread.h" #include "lltimer.h" @@ -204,7 +205,7 @@ namespace boost void intrusive_ptr_release(LLCurl::Responder* p) { - if(p && 0 == --p->mReferenceCount) + if (p && 0 == --p->mReferenceCount) { delete p; } @@ -214,73 +215,6 @@ namespace boost ////////////////////////////////////////////////////////////////////////////// - -class LLCurl::Easy -{ - LOG_CLASS(Easy); - -private: - Easy(); - -public: - static Easy* getEasy(); - ~Easy(); - - CURL* getCurlHandle() const { return mCurlEasyHandle; } - - void setErrorBuffer(); - void setCA(); - - void setopt(CURLoption option, S32 value); - // These assume the setter does not free value! - void setopt(CURLoption option, void* value); - void setopt(CURLoption option, char* value); - // Copies the string so that it is gauranteed to stick around - void setoptString(CURLoption option, const std::string& value); - - void slist_append(const char* str); - void setHeaders(); - - U32 report(CURLcode); - void getTransferInfo(LLCurl::TransferInfo* info); - - void prepRequest(const std::string& url, const std::vector<std::string>& headers, ResponderPtr, bool post = false); - - const char* getErrorBuffer(); - - std::stringstream& getInput() { return mInput; } - std::stringstream& getHeaderOutput() { return mHeaderOutput; } - LLIOPipe::buffer_ptr_t& getOutput() { return mOutput; } - const LLChannelDescriptors& getChannels() { return mChannels; } - - void resetState(); - - static CURL* allocEasyHandle(); - static void releaseEasyHandle(CURL* handle); - -private: - friend class LLCurl; - - CURL* mCurlEasyHandle; - struct curl_slist* mHeaders; - - std::stringstream mRequest; - LLChannelDescriptors mChannels; - LLIOPipe::buffer_ptr_t mOutput; - std::stringstream mInput; - std::stringstream mHeaderOutput; - char mErrorBuffer[CURL_ERROR_SIZE]; - - // Note: char*'s not strings since we pass pointers to curl - std::vector<char*> mStrings; - - ResponderPtr mResponder; - - static std::set<CURL*> sFreeHandles; - static std::set<CURL*> sActiveHandles; - static LLMutex* sHandleMutex; -}; - std::set<CURL*> LLCurl::Easy::sFreeHandles; std::set<CURL*> LLCurl::Easy::sActiveHandles; LLMutex* LLCurl::Easy::sHandleMutex = NULL; @@ -404,11 +338,11 @@ const char* LLCurl::Easy::getErrorBuffer() void LLCurl::Easy::setCA() { - if(!sCAPath.empty()) + if (!sCAPath.empty()) { setoptString(CURLOPT_CAPATH, sCAPath); } - if(!sCAFile.empty()) + if (!sCAFile.empty()) { setoptString(CURLOPT_CAINFO, sCAFile); } @@ -531,9 +465,12 @@ void LLCurl::Easy::prepRequest(const std::string& url, if (post) setoptString(CURLOPT_ENCODING, ""); - //setopt(CURLOPT_VERBOSE, 1); // usefull for debugging + //setopt(CURLOPT_VERBOSE, 1); // useful for debugging setopt(CURLOPT_NOSIGNAL, 1); + // Set the CURL options for either Socks or HTTP proxy + LLProxy::getInstance()->applyProxySettings(this); + mOutput.reset(new LLBufferArray); setopt(CURLOPT_WRITEFUNCTION, (void*)&curlWriteCallback); setopt(CURLOPT_WRITEDATA, (void*)this); @@ -545,7 +482,7 @@ void LLCurl::Easy::prepRequest(const std::string& url, setopt(CURLOPT_HEADERDATA, (void*)this); // Allow up to five redirects - if(responder && responder->followRedir()) + if (responder && responder->followRedir()) { setopt(CURLOPT_FOLLOWLOCATION, 1); setopt(CURLOPT_MAXREDIRS, MAX_REDIRECTS); @@ -579,54 +516,6 @@ void LLCurl::Easy::prepRequest(const std::string& url, //////////////////////////////////////////////////////////////////////////// -class LLCurl::Multi : public LLThread -{ - LOG_CLASS(Multi); -public: - - typedef enum - { - PERFORM_STATE_READY=0, - PERFORM_STATE_PERFORMING=1, - PERFORM_STATE_COMPLETED=2 - } ePerformState; - - Multi(); - ~Multi(); - - Easy* allocEasy(); - bool addEasy(Easy* easy); - - void removeEasy(Easy* easy); - - S32 process(); - void perform(); - - virtual void run(); - - CURLMsg* info_read(S32* msgs_in_queue); - - S32 mQueued; - S32 mErrorCount; - - S32 mPerformState; - - LLCondition* mSignal; - bool mQuitting; - -private: - void easyFree(Easy*); - - CURLM* mCurlMultiHandle; - - typedef std::set<Easy*> easy_active_list_t; - easy_active_list_t mEasyActiveList; - typedef std::map<CURL*, Easy*> easy_active_map_t; - easy_active_map_t mEasyActiveMap; - typedef std::set<Easy*> easy_free_list_t; - easy_free_list_t mEasyFreeList; -}; - LLCurl::Multi::Multi() : LLThread("Curl Multi"), mQueued(0), @@ -1025,6 +914,8 @@ LLCurlEasyRequest::LLCurlEasyRequest() { mEasy->setErrorBuffer(); mEasy->setCA(); + // Set proxy settings if configured to do so. + LLProxy::getInstance()->applyProxySettings(mEasy); } } diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index 2f951d6ab8..79f5eeb927 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -41,6 +41,7 @@ #include "llbuffer.h" #include "lliopipe.h" #include "llsd.h" +#include "llthread.h" class LLMutex; @@ -184,6 +185,120 @@ private: static const unsigned int MAX_REDIRECTS; }; +class LLCurl::Easy +{ + LOG_CLASS(Easy); + +private: + Easy(); + +public: + static Easy* getEasy(); + ~Easy(); + + CURL* getCurlHandle() const { return mCurlEasyHandle; } + + void setErrorBuffer(); + void setCA(); + + void setopt(CURLoption option, S32 value); + // These assume the setter does not free value! + void setopt(CURLoption option, void* value); + void setopt(CURLoption option, char* value); + // Copies the string so that it is guaranteed to stick around + void setoptString(CURLoption option, const std::string& value); + + void slist_append(const char* str); + void setHeaders(); + + U32 report(CURLcode); + void getTransferInfo(LLCurl::TransferInfo* info); + + void prepRequest(const std::string& url, const std::vector<std::string>& headers, ResponderPtr, bool post = false); + + const char* getErrorBuffer(); + + std::stringstream& getInput() { return mInput; } + std::stringstream& getHeaderOutput() { return mHeaderOutput; } + LLIOPipe::buffer_ptr_t& getOutput() { return mOutput; } + const LLChannelDescriptors& getChannels() { return mChannels; } + + void resetState(); + + static CURL* allocEasyHandle(); + static void releaseEasyHandle(CURL* handle); + +private: + friend class LLCurl; + + CURL* mCurlEasyHandle; + struct curl_slist* mHeaders; + + std::stringstream mRequest; + LLChannelDescriptors mChannels; + LLIOPipe::buffer_ptr_t mOutput; + std::stringstream mInput; + std::stringstream mHeaderOutput; + char mErrorBuffer[CURL_ERROR_SIZE]; + + // Note: char*'s not strings since we pass pointers to curl + std::vector<char*> mStrings; + + ResponderPtr mResponder; + + static std::set<CURL*> sFreeHandles; + static std::set<CURL*> sActiveHandles; + static LLMutex* sHandleMutex; +}; + +class LLCurl::Multi : public LLThread +{ + LOG_CLASS(Multi); +public: + + typedef enum + { + PERFORM_STATE_READY=0, + PERFORM_STATE_PERFORMING=1, + PERFORM_STATE_COMPLETED=2 + } ePerformState; + + Multi(); + ~Multi(); + + Easy* allocEasy(); + bool addEasy(Easy* easy); + + void removeEasy(Easy* easy); + + S32 process(); + void perform(); + + virtual void run(); + + CURLMsg* info_read(S32* msgs_in_queue); + + S32 mQueued; + S32 mErrorCount; + + S32 mPerformState; + + LLCondition* mSignal; + bool mQuitting; + +private: + void easyFree(Easy*); + + CURLM* mCurlMultiHandle; + + typedef std::set<Easy*> easy_active_list_t; + easy_active_list_t mEasyActiveList; + typedef std::map<CURL*, Easy*> easy_active_map_t; + easy_active_map_t mEasyActiveMap; + typedef std::set<Easy*> easy_free_list_t; + easy_free_list_t mEasyFreeList; +}; + namespace boost { void intrusive_ptr_add_ref(LLCurl::Responder* p); @@ -250,4 +365,7 @@ private: bool mResultReturned; }; +void check_curl_code(CURLcode code); +void check_curl_multi_code(CURLMcode code); + #endif // LL_LLCURL_H diff --git a/indra/llmessage/llhttpassetstorage.cpp b/indra/llmessage/llhttpassetstorage.cpp index 5a38b7fd9f..2bca517e97 100644 --- a/indra/llmessage/llhttpassetstorage.cpp +++ b/indra/llmessage/llhttpassetstorage.cpp @@ -33,6 +33,7 @@ #include "indra_constants.h" #include "message.h" +#include "llproxy.h" #include "llvfile.h" #include "llvfs.h" @@ -232,6 +233,10 @@ void LLHTTPAssetRequest::setupCurlHandle() { // *NOTE: Similar code exists in mapserver/llcurlutil.cpp JC mCurlHandle = curl_easy_init(); + + // Apply proxy settings if configured to do so + LLProxy::getInstance()->applyProxySettings(mCurlHandle); + curl_easy_setopt(mCurlHandle, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(mCurlHandle, CURLOPT_NOPROGRESS, 1); curl_easy_setopt(mCurlHandle, CURLOPT_URL, mURLBuffer.c_str()); diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp index 0e5206a520..dd4e3a6300 100644 --- a/indra/llmessage/llhttpclient.cpp +++ b/indra/llmessage/llhttpclient.cpp @@ -428,6 +428,9 @@ static LLSD blocking_request( std::string body_str; // other request method checks root cert first, we skip? + + // Apply configured proxy settings + LLProxy::getInstance()->applyProxySettings(curlp); // * Set curl handle options curl_easy_setopt(curlp, CURLOPT_NOSIGNAL, 1); // don't use SIGALRM for timeouts @@ -436,7 +439,7 @@ static LLSD blocking_request( curl_easy_setopt(curlp, CURLOPT_WRITEDATA, &http_buffer); curl_easy_setopt(curlp, CURLOPT_URL, url.c_str()); curl_easy_setopt(curlp, CURLOPT_ERRORBUFFER, curl_error_buffer); - + // * Setup headers (don't forget to free them after the call!) curl_slist* headers_list = NULL; if (headers.isMap()) diff --git a/indra/llmessage/lliosocket.cpp b/indra/llmessage/lliosocket.cpp index b717e321bf..ee9379f205 100644 --- a/indra/llmessage/lliosocket.cpp +++ b/indra/llmessage/lliosocket.cpp @@ -251,10 +251,12 @@ LLSocket::~LLSocket() { ll_debug_socket("Destroying socket", mSocket); apr_socket_close(mSocket); + mSocket = NULL; } if(mPool) { apr_pool_destroy(mPool); + mPool = NULL; } } diff --git a/indra/llmessage/lliosocket.h b/indra/llmessage/lliosocket.h index e0f6c1e34d..be0f7dfcc6 100644 --- a/indra/llmessage/lliosocket.h +++ b/indra/llmessage/lliosocket.h @@ -145,13 +145,6 @@ public: */ apr_socket_t* getSocket() const { return mSocket; } -protected: - /** - * @brief Protected constructor since should only make sockets - * with one of the two <code>create()</code> calls. - */ - LLSocket(apr_socket_t* socket, apr_pool_t* pool); - /** * @brief Set default socket options, with SO_NONBLOCK = 0 and a timeout in us. * @param timeout Number of microseconds to wait on this socket. Any @@ -164,6 +157,13 @@ protected: */ void setNonBlocking(); +protected: + /** + * @brief Protected constructor since should only make sockets + * with one of the two <code>create()</code> calls. + */ + LLSocket(apr_socket_t* socket, apr_pool_t* pool); + public: /** * @brief Do not call this directly. diff --git a/indra/llmessage/llpacketring.cpp b/indra/llmessage/llpacketring.cpp index 8999dec64a..ba82957b47 100644 --- a/indra/llmessage/llpacketring.cpp +++ b/indra/llmessage/llpacketring.cpp @@ -28,11 +28,20 @@ #include "llpacketring.h" +#if LL_WINDOWS + #include <winsock2.h> +#else + #include <sys/socket.h> + #include <netinet/in.h> +#endif + // linden library includes #include "llerror.h" #include "lltimer.h" -#include "timing.h" +#include "llproxy.h" #include "llrand.h" +#include "message.h" +#include "timing.h" #include "u64.h" /////////////////////////////////////////////////////////// @@ -216,8 +225,32 @@ S32 LLPacketRing::receivePacket (S32 socket, char *datap) else { // no delay, pull straight from net - packet_size = receive_packet(socket, datap); - mLastSender = ::get_sender(); + if (LLProxy::isEnabled()) + { + U8 buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE]; + packet_size = receive_packet(socket, reinterpret_cast<char *>(buffer)); + + if (packet_size > SOCKS_HEADER_SIZE) + { + // *FIX We are assuming ATYP is 0x01 (IPv4), not 0x03 (hostname) or 0x04 (IPv6) + memcpy(datap, buffer + SOCKS_HEADER_SIZE, packet_size - SOCKS_HEADER_SIZE); + proxywrap_t * header = reinterpret_cast<proxywrap_t *>(buffer); + mLastSender.setAddress(header->addr); + mLastSender.setPort(ntohs(header->port)); + + packet_size -= SOCKS_HEADER_SIZE; // The unwrapped packet size + } + else + { + packet_size = 0; + } + } + else + { + packet_size = receive_packet(socket, datap); + mLastSender = ::get_sender(); + } + mLastReceivingIF = ::get_receiving_interface(); if (packet_size) // did we actually get a packet? @@ -243,7 +276,7 @@ BOOL LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LL BOOL status = TRUE; if (!mUseOutThrottle) { - return send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort() ); + return sendPacketImpl(h_socket, send_buffer, buf_size, host ); } else { @@ -264,7 +297,7 @@ BOOL LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LL mOutBufferLength -= packetp->getSize(); packet_size = packetp->getSize(); - status = send_packet(h_socket, packetp->getData(), packet_size, packetp->getHost().getAddress(), packetp->getHost().getPort()); + status = sendPacketImpl(h_socket, packetp->getData(), packet_size, packetp->getHost()); delete packetp; // Update the throttle @@ -273,7 +306,7 @@ BOOL LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LL else { // If the queue's empty, we can just send this packet right away. - status = send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort() ); + status = sendPacketImpl(h_socket, send_buffer, buf_size, host ); packet_size = buf_size; // Update the throttle @@ -311,3 +344,23 @@ BOOL LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LL return status; } + +BOOL LLPacketRing::sendPacketImpl(int h_socket, const char * send_buffer, S32 buf_size, LLHost host) +{ + + if (!LLProxy::isEnabled()) + { + return send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort()); + } + + proxywrap_t *socks_header = reinterpret_cast<proxywrap_t *>(&mProxyWrappedSendBuffer); + socks_header->rsv = 0; + socks_header->addr = host.getAddress(); + socks_header->port = htons(host.getPort()); + socks_header->atype = ADDRESS_IPV4; + socks_header->frag = 0; + + memcpy(mProxyWrappedSendBuffer + SOCKS_HEADER_SIZE, send_buffer, buf_size); + + return send_packet(h_socket, (const char*) mProxyWrappedSendBuffer, buf_size + 10, LLProxy::getInstance()->getUDPProxy().getAddress(), LLProxy::getInstance()->getUDPProxy().getPort()); +} diff --git a/indra/llmessage/llpacketring.h b/indra/llmessage/llpacketring.h index e6409d2048..7edcc834db 100644 --- a/indra/llmessage/llpacketring.h +++ b/indra/llmessage/llpacketring.h @@ -30,11 +30,11 @@ #include <queue> -#include "llpacketbuffer.h" #include "llhost.h" -#include "net.h" +#include "llpacketbuffer.h" +#include "llproxy.h" #include "llthrottle.h" - +#include "net.h" class LLPacketRing { @@ -82,6 +82,12 @@ protected: LLHost mLastSender; LLHost mLastReceivingIF; + + + U8 mProxyWrappedSendBuffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE]; + +private: + BOOL sendPacketImpl(int h_socket, const char * send_buffer, S32 buf_size, LLHost host); }; diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp new file mode 100644 index 0000000000..d34ad1a811 --- /dev/null +++ b/indra/llmessage/llproxy.cpp @@ -0,0 +1,411 @@ +/** + * @file llsocks5.cpp + * @brief SOCKS 5 implementation + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llproxy.h" + +#include <algorithm> +#include <string> +#include <curl/curl.h> + +#include "llapr.h" +#include "llcurl.h" +#include "llhost.h" +#include "message.h" +#include "net.h" + +// Static class variable instances + +// We want this to be static to avoid excessive indirection on every +// incoming packet just to do a simple bool test. The getter for this +// member is also static +bool LLProxy::sUDPProxyEnabled = false; +bool LLProxy::sHTTPProxyEnabled = false; + +// Some helpful TCP functions +static LLSocket::ptr_t tcp_open_channel(apr_pool_t* pool, LLHost host); // Open a TCP channel to a given host +static void tcp_close_channel(LLSocket::ptr_t* handle_ptr); // Close an open TCP channel +static S32 tcp_handshake(LLSocket::ptr_t handle, char * dataout, apr_size_t outlen, char * datain, apr_size_t maxinlen); // Do a TCP data handshake + +LLProxy::LLProxy(): + mProxyType(LLPROXY_SOCKS), + mUDPProxy(), + mTCPProxy(), + mHTTPProxy(), + mAuthMethodSelected(METHOD_NOAUTH), + mSocksUsername(), + mSocksPassword(), + mPool(gAPRPoolp), + mSOCKSAuthStrings(), + mHTTPProxyAddrStrings(), + mProxyMutex(0) +{ +} + +LLProxy::~LLProxy() +{ + stopProxy(); + sUDPProxyEnabled = false; + sHTTPProxyEnabled = false; + + // Delete c_str versions of the addresses and credentials. + for_each(mSOCKSAuthStrings.begin(), mSOCKSAuthStrings.end(), DeletePointerArray()); + for_each(mHTTPProxyAddrStrings.begin(), mHTTPProxyAddrStrings.end(), DeletePointerArray()); +} + +// Perform a SOCKS 5 authentication and UDP association to the proxy +// specified by proxy, and associate UDP port message_port +S32 LLProxy::proxyHandshake(LLHost proxy, U32 message_port) +{ + S32 result; + + /* SOCKS 5 Auth request */ + socks_auth_request_t socks_auth_request; + socks_auth_response_t socks_auth_response; + + socks_auth_request.version = SOCKS_VERSION; // SOCKS version 5 + socks_auth_request.num_methods = 1; // Sending 1 method. + socks_auth_request.methods = mAuthMethodSelected; // Send only the selected method. + + result = tcp_handshake(mProxyControlChannel, (char*)&socks_auth_request, sizeof(socks_auth_request), (char*)&socks_auth_response, sizeof(socks_auth_response)); + if (result != 0) + { + LL_WARNS("Proxy") << "SOCKS authentication request failed, error on TCP control channel : " << result << LL_ENDL; + stopProxy(); + return SOCKS_CONNECT_ERROR; + } + + if (socks_auth_response.method == AUTH_NOT_ACCEPTABLE) + { + LL_WARNS("Proxy") << "SOCKS 5 server refused all our authentication methods" << LL_ENDL; + stopProxy(); + return SOCKS_NOT_ACCEPTABLE; + } + + // SOCKS 5 USERNAME/PASSWORD authentication + if (socks_auth_response.method == METHOD_PASSWORD) + { + // The server has requested a username/password combination + U32 request_size = mSocksUsername.size() + mSocksPassword.size() + 3; + char * password_auth = new char[request_size]; + password_auth[0] = 0x01; + password_auth[1] = mSocksUsername.size(); + memcpy(&password_auth[2], mSocksUsername.c_str(), mSocksUsername.size()); + password_auth[mSocksUsername.size() + 2] = mSocksPassword.size(); + memcpy(&password_auth[mSocksUsername.size()+3], mSocksPassword.c_str(), mSocksPassword.size()); + + authmethod_password_reply_t password_reply; + + result = tcp_handshake(mProxyControlChannel, password_auth, request_size, (char*)&password_reply, sizeof(password_reply)); + delete[] password_auth; + + if (result != 0) + { + LL_WARNS("Proxy") << "SOCKS authentication failed, error on TCP control channel : " << result << LL_ENDL; + stopProxy(); + return SOCKS_CONNECT_ERROR; + } + + if (password_reply.status != AUTH_SUCCESS) + { + LL_WARNS("Proxy") << "SOCKS authentication failed" << LL_ENDL; + stopProxy(); + return SOCKS_AUTH_FAIL; + } + } + + /* SOCKS5 connect request */ + + socks_command_request_t connect_request; + socks_command_response_t connect_reply; + + connect_request.version = SOCKS_VERSION; // SOCKS V5 + connect_request.command = COMMAND_UDP_ASSOCIATE; // Associate UDP + connect_request.reserved = FIELD_RESERVED; + connect_request.atype = ADDRESS_IPV4; + connect_request.address = htonl(0); // 0.0.0.0 + connect_request.port = htons(0); // 0 + // "If the client is not in possession of the information at the time of the UDP ASSOCIATE, + // the client MUST use a port number and address of all zeros. RFC 1928" + + result = tcp_handshake(mProxyControlChannel, (char*)&connect_request, sizeof(connect_request), (char*)&connect_reply, sizeof(connect_reply)); + if (result != 0) + { + LL_WARNS("Proxy") << "SOCKS connect request failed, error on TCP control channel : " << result << LL_ENDL; + stopProxy(); + return SOCKS_CONNECT_ERROR; + } + + if (connect_reply.reply != REPLY_REQUEST_GRANTED) + { + LL_WARNS("Proxy") << "Connection to SOCKS 5 server failed, UDP forward request not granted" << LL_ENDL; + stopProxy(); + return SOCKS_UDP_FWD_NOT_GRANTED; + } + + mUDPProxy.setPort(ntohs(connect_reply.port)); // reply port is in network byte order + mUDPProxy.setAddress(proxy.getAddress()); + // The connection was successful. We now have the UDP port to send requests that need forwarding to. + LL_INFOS("Proxy") << "SOCKS 5 UDP proxy connected on " << mUDPProxy << LL_ENDL; + return SOCKS_OK; +} + +S32 LLProxy::startProxy(std::string host, U32 port) +{ + mTCPProxy.setHostByName(host); + mTCPProxy.setPort(port); + + S32 status; + + if (mProxyControlChannel) + { + tcp_close_channel(&mProxyControlChannel); + } + + mProxyControlChannel = tcp_open_channel(mPool, mTCPProxy); + if (!mProxyControlChannel) + { + return SOCKS_HOST_CONNECT_FAILED; + } + status = proxyHandshake(mTCPProxy, (U32)gMessageSystem->mPort); + if (status == SOCKS_OK) + { + sUDPProxyEnabled = true; + } + else + { + stopProxy(); + } + return status; + +} + +void LLProxy::stopProxy() +{ + sUDPProxyEnabled = false; + + // If the SOCKS proxy is requested to stop and we are using that for HTTP as well + // then we must shut down any HTTP proxy operations. But it is allowable if web + // proxy is being used to continue proxying HTTP. + + if (LLPROXY_SOCKS == mProxyType) + { + void disableHTTPProxy(); + } + + if (mProxyControlChannel) + { + tcp_close_channel(&mProxyControlChannel); + } +} + +void LLProxy::setAuthNone() +{ + mAuthMethodSelected = METHOD_NOAUTH; +} + +void LLProxy::setAuthPassword(const std::string &username, const std::string &password) +{ + mAuthMethodSelected = METHOD_PASSWORD; + mSocksUsername = username; + mSocksPassword = password; + + U32 size = username.length() + password.length() + 2; + char* curl_auth_string = new char[size]; + snprintf(curl_auth_string, size, "%s:%s", username.c_str(), password.c_str()); + + LLMutexLock lock(&mProxyMutex); + mSOCKSAuthStrings.push_back(curl_auth_string); +} + +void LLProxy::enableHTTPProxy(LLHost httpHost, LLHttpProxyType type) +{ + LLMutexLock lock(&mProxyMutex); + + sHTTPProxyEnabled = true; + mHTTPProxy = httpHost; + mProxyType = type; + + U32 size = httpHost.getIPString().length() + 1; + char* http_addr_string = new char[size]; + strncpy(http_addr_string, httpHost.getIPString().c_str(), size); + mHTTPProxyAddrStrings.push_back(http_addr_string); +} + +void LLProxy::enableHTTPProxy() +{ + LLMutexLock lock(&mProxyMutex); + + sHTTPProxyEnabled = true; +} + +void LLProxy::disableHTTPProxy() +{ + LLMutexLock lock(&mProxyMutex); + + sHTTPProxyEnabled = false; +} + +//static +void LLProxy::cleanupClass() +{ + getInstance()->stopProxy(); + deleteSingleton(); +} + +// Apply proxy settings to CuRL request if either type of HTTP proxy is enabled. +void LLProxy::applyProxySettings(LLCurl::Easy* handle) +{ + if (sHTTPProxyEnabled) + { + std::string address = mHTTPProxy.getIPString(); + U16 port = mHTTPProxy.getPort(); + handle->setoptString(CURLOPT_PROXY, address.c_str()); + handle->setopt(CURLOPT_PROXYPORT, port); + if (mProxyType == LLPROXY_SOCKS) + { + handle->setopt(CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); + if (mAuthMethodSelected == METHOD_PASSWORD) + { + handle->setoptString(CURLOPT_PROXYUSERPWD, getProxyUserPwdCURL()); + } + } + else + { + handle->setopt(CURLOPT_PROXYTYPE, CURLPROXY_HTTP); + } + } +} + +void LLProxy::applyProxySettings(LLCurlEasyRequest* handle) +{ + if (sHTTPProxyEnabled) + { + std::string address = mHTTPProxy.getIPString(); + U16 port = mHTTPProxy.getPort(); + handle->setoptString(CURLOPT_PROXY, address.c_str()); + handle->setopt(CURLOPT_PROXYPORT, port); + if (mProxyType == LLPROXY_SOCKS) + { + handle->setopt(CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); + if (mAuthMethodSelected == METHOD_PASSWORD) + { + handle->setoptString(CURLOPT_PROXYUSERPWD, getProxyUserPwdCURL()); + } + } + else + { + handle->setopt(CURLOPT_PROXYTYPE, CURLPROXY_HTTP); + } + } +} + +void LLProxy::applyProxySettings(CURL* handle) +{ + LLMutexLock lock(&mProxyMutex); + if (sHTTPProxyEnabled) + { + check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXY, mHTTPProxyAddrStrings.back())); + U16 port = mHTTPProxy.getPort(); + check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYPORT, port)); + + if (mProxyType == LLPROXY_SOCKS) + { + check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5)); + if (mAuthMethodSelected == METHOD_PASSWORD) + { + check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, mSOCKSAuthStrings.back())); + } + } + else + { + check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP)); + } + } +} + +static S32 tcp_handshake(LLSocket::ptr_t handle, char * dataout, apr_size_t outlen, char * datain, apr_size_t maxinlen) +{ + + apr_socket_t* apr_socket = handle->getSocket(); + apr_status_t rv = APR_SUCCESS; + + apr_size_t expected_len = outlen; + + handle->setBlocking(1000); + + rv = apr_socket_send(apr_socket, dataout, &outlen); + if (APR_SUCCESS != rv || expected_len != outlen) + { + LL_WARNS("Proxy") << "Error sending data to proxy control channel" << LL_ENDL; + ll_apr_warn_status(rv); + } + else if (expected_len != outlen) + { + LL_WARNS("Proxy") << "Error sending data to proxy control channel" << LL_ENDL; + rv = -1; + } + + if (APR_SUCCESS == rv) + { + expected_len = maxinlen; + rv = apr_socket_recv(apr_socket, datain, &maxinlen); + if (rv != APR_SUCCESS) + { + LL_WARNS("Proxy") << "Error receiving data from proxy control channel, status: " << rv << LL_ENDL; + ll_apr_warn_status(rv); + } + else if (expected_len != maxinlen) + { + LL_WARNS("Proxy") << "Received incorrect amount of data in proxy control channel" << LL_ENDL; + rv = -1; + } + } + + handle->setNonBlocking(); + + return rv; +} + +static LLSocket::ptr_t tcp_open_channel(apr_pool_t* pool, LLHost host) +{ + LLSocket::ptr_t socket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP); + bool connected = socket->blockingConnect(host); + if (!connected) + { + tcp_close_channel(&socket); + } + + return socket; +} + +// Pass a pointer-to-pointer to avoid changing use_count(). +static void tcp_close_channel(LLSocket::ptr_t* handle_ptr) +{ + LL_DEBUGS("Proxy") << "Resetting proxy LLSocket handle, use_count == " << handle_ptr->use_count() << LL_ENDL; + handle_ptr->reset(); +} diff --git a/indra/llmessage/llproxy.h b/indra/llmessage/llproxy.h new file mode 100644 index 0000000000..df1ec9121e --- /dev/null +++ b/indra/llmessage/llproxy.h @@ -0,0 +1,266 @@ +/** + * @file llsocks5.h + * @brief Socks 5 implementation + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_PROXY_H +#define LL_PROXY_H + +#include "llcurl.h" +#include "llhost.h" +#include "lliosocket.h" +#include "llmemory.h" +#include "llsingleton.h" +#include "llthread.h" +#include <string> + +// Error codes returned from the StartProxy method + +#define SOCKS_OK 0 +#define SOCKS_CONNECT_ERROR (-1) +#define SOCKS_NOT_PERMITTED (-2) +#define SOCKS_NOT_ACCEPTABLE (-3) +#define SOCKS_AUTH_FAIL (-4) +#define SOCKS_UDP_FWD_NOT_GRANTED (-5) +#define SOCKS_HOST_CONNECT_FAILED (-6) + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN (255 + 1) /* socks5: 255, +1 for len. */ +#endif + +#define SOCKS_VERSION 0x05 // we are using SOCKS 5 + +#define SOCKS_HEADER_SIZE 10 + +// SOCKS 5 address/hostname types +#define ADDRESS_IPV4 0x01 +#define ADDRESS_HOSTNAME 0x03 +#define ADDRESS_IPV6 0x04 + +// Lets just use our own ipv4 struct rather than dragging in system +// specific headers +union ipv4_address_t { + U8 octets[4]; + U32 addr32; +}; + +// SOCKS 5 control channel commands +#define COMMAND_TCP_STREAM 0x01 +#define COMMAND_TCP_BIND 0x02 +#define COMMAND_UDP_ASSOCIATE 0x03 + +// SOCKS 5 command replies +#define REPLY_REQUEST_GRANTED 0x00 +#define REPLY_GENERAL_FAIL 0x01 +#define REPLY_RULESET_FAIL 0x02 +#define REPLY_NETWORK_UNREACHABLE 0x03 +#define REPLY_HOST_UNREACHABLE 0x04 +#define REPLY_CONNECTION_REFUSED 0x05 +#define REPLY_TTL_EXPIRED 0x06 +#define REPLY_PROTOCOL_ERROR 0x07 +#define REPLY_TYPE_NOT_SUPPORTED 0x08 + +#define FIELD_RESERVED 0x00 + +// The standard SOCKS 5 request packet +// Push current alignment to stack and set alignment to 1 byte boundary +// This enabled us to use structs directly to set up and receive network packets +// into the correct fields, without fear of boundary alignment causing issues +#pragma pack(push,1) + +// SOCKS 5 command packet +struct socks_command_request_t { + U8 version; + U8 command; + U8 reserved; + U8 atype; + U32 address; + U16 port; +}; + +// Standard SOCKS 5 reply packet +struct socks_command_response_t { + U8 version; + U8 reply; + U8 reserved; + U8 atype; + U8 add_bytes[4]; + U16 port; +}; + +#define AUTH_NOT_ACCEPTABLE 0xFF // reply if preferred methods are not available +#define AUTH_SUCCESS 0x00 // reply if authentication successful + +// SOCKS 5 authentication request, stating which methods the client supports +struct socks_auth_request_t { + U8 version; + U8 num_methods; + U8 methods; // We are only using a single method currently +}; + +// SOCKS 5 authentication response packet, stating server preferred method +struct socks_auth_response_t { + U8 version; + U8 method; +}; + +// SOCKS 5 password reply packet +struct authmethod_password_reply_t { + U8 version; + U8 status; +}; + +// SOCKS 5 UDP packet header +struct proxywrap_t { + U16 rsv; + U8 frag; + U8 atype; + U32 addr; + U16 port; +}; + +#pragma pack(pop) /* restore original alignment from stack */ + + +// Currently selected HTTP proxy type +enum LLHttpProxyType +{ + LLPROXY_SOCKS = 0, + LLPROXY_HTTP = 1 +}; + +// Auth types +enum LLSocks5AuthType +{ + METHOD_NOAUTH = 0x00, // Client supports no auth + METHOD_GSSAPI = 0x01, // Client supports GSSAPI (Not currently supported) + METHOD_PASSWORD = 0x02 // Client supports username/password +}; + +class LLProxy: public LLSingleton<LLProxy> +{ +public: + LLProxy(); + ~LLProxy(); + + // Start a connection to the SOCKS 5 proxy + S32 startProxy(std::string host, U32 port); + + // Disconnect and clean up any connection to the SOCKS 5 proxy + void stopProxy(); + + // Delete LLProxy singleton, destroying the APR pool used by the control channel. + static void cleanupClass(); + + // Set up to use Password auth when connecting to the SOCKS proxy + void setAuthPassword(const std::string &username, const std::string &password); + + // Set up to use No Auth when connecting to the SOCKS proxy + void setAuthNone(); + + // get the currently selected auth method + LLSocks5AuthType getSelectedAuthMethod() const { return mAuthMethodSelected; } + + // static check for enabled status for UDP packets + static bool isEnabled() { return sUDPProxyEnabled; } + + // static check for enabled status for http packets + static bool isHTTPProxyEnabled() { return sHTTPProxyEnabled; } + + // Proxy HTTP packets via httpHost, which can be a SOCKS 5 or a HTTP proxy + // as specified in type + void enableHTTPProxy(LLHost httpHost, LLHttpProxyType type); + void enableHTTPProxy(); + + // Stop proxying HTTP packets + void disableHTTPProxy(); + + // Get the UDP proxy address and port + LLHost getUDPProxy() const { return mUDPProxy; } + + // Get the SOCKS 5 TCP control channel address and port + LLHost getTCPProxy() const { return mTCPProxy; } + + // Get the HTTP proxy address and port + LLHost getHTTPProxy() const { return mHTTPProxy; } + + // Get the currently selected HTTP proxy type + LLHttpProxyType getHTTPProxyType() const { return mProxyType; } + + // Get the username password in a curl compatible format + std::string getProxyUserPwdCURL() const { return (mSocksUsername + ":" + mSocksPassword); } + + std::string getSocksPwd() const { return mSocksPassword; } + std::string getSocksUser() const { return mSocksUsername; } + + // Apply the current proxy settings to a curl request. Doesn't do anything if sHTTPProxyEnabled is false. + void applyProxySettings(CURL* handle); + void applyProxySettings(LLCurl::Easy* handle); + void applyProxySettings(LLCurlEasyRequest* handle); + +private: + // Open a communication channel to the SOCKS 5 proxy proxy, at port messagePort + S32 proxyHandshake(LLHost proxy, U32 messagePort); + +private: + // socket handle to proxy TCP control channel + LLSocket::ptr_t mProxyControlChannel; + + // Is the UDP proxy enabled? + static bool sUDPProxyEnabled; + // Is the HTTP proxy enabled? + // Do not toggle directly, use enableHTTPProxy() and disableHTTPProxy() + static bool sHTTPProxyEnabled; + + // currently selected http proxy type + LLHttpProxyType mProxyType; + + // UDP proxy address and port + LLHost mUDPProxy; + // TCP proxy control channel address and port + LLHost mTCPProxy; + // HTTP proxy address and port + LLHost mHTTPProxy; + + // SOCKS 5 auth method selected + LLSocks5AuthType mAuthMethodSelected; + + // SOCKS 5 username + std::string mSocksUsername; + // SOCKS 5 password + std::string mSocksPassword; + + // Vectors to store valid pointers to string options that might have been set on CURL requests. + // This results in a behavior similar to LLCurl::Easy::setoptstring() + std::vector<char*> mSOCKSAuthStrings; + std::vector<char*> mHTTPProxyAddrStrings; + + // Mutex to protect members in cross-thread calls to applyProxySettings() + LLMutex mProxyMutex; + + // APR pool for the socket + apr_pool_t* mPool; +}; + +#endif diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index e8e35d00a2..a186596582 100644 --- a/indra/llmessage/llurlrequest.cpp +++ b/indra/llmessage/llurlrequest.cpp @@ -35,6 +35,7 @@ #include "llcurl.h" #include "llioutil.h" #include "llmemtype.h" +#include "llproxy.h" #include "llpumpio.h" #include "llsd.h" #include "llstring.h" @@ -227,8 +228,7 @@ void LLURLRequest::useProxy(bool use_proxy) } } - - lldebugs << "use_proxy = " << (use_proxy?'Y':'N') << ", env_proxy = " << (env_proxy ? env_proxy : "(null)") << llendl; + LL_DEBUGS("Proxy") << "use_proxy = " << (use_proxy?'Y':'N') << ", env_proxy = " << (env_proxy ? env_proxy : "(null)") << LL_ENDL; if (env_proxy && use_proxy) { @@ -438,6 +438,7 @@ void LLURLRequest::initialize() LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST); mState = STATE_INITIALIZED; mDetail = new LLURLRequestDetail; + LLProxy::getInstance()->applyProxySettings(mDetail->mCurlRequest); mDetail->mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1); mDetail->mCurlRequest->setWriteCallback(&downCallback, (void*)this); mDetail->mCurlRequest->setReadCallback(&upCallback, (void*)this); diff --git a/indra/llmessage/net.cpp b/indra/llmessage/net.cpp index 97611c3b51..85aef5da00 100644 --- a/indra/llmessage/net.cpp +++ b/indra/llmessage/net.cpp @@ -50,7 +50,6 @@ #include "lltimer.h" #include "indra_constants.h" - // Globals #if LL_WINDOWS @@ -174,7 +173,7 @@ U32 ip_string_to_u32(const char* ip_string) // use wildcard addresses. -Ambroff U32 ip = inet_addr(ip_string); if (ip == INADDR_NONE - && strncmp(ip_string, BROADCAST_ADDRESS_STRING, MAXADDRSTR) != 0) + && strncmp(ip_string, BROADCAST_ADDRESS_STRING, MAXADDRSTR) != 0) { llwarns << "ip_string_to_u32() failed, Error: Invalid IP string '" << ip_string << "'" << llendl; return INVALID_HOST_IP_ADDRESS; @@ -188,11 +187,11 @@ U32 ip_string_to_u32(const char* ip_string) ////////////////////////////////////////////////////////////////////////////////////////// #if LL_WINDOWS - + S32 start_net(S32& socket_out, int& nPort) { // Create socket, make non-blocking - // Init WinSock + // Init WinSock int nRet; int hSocket; @@ -201,7 +200,7 @@ S32 start_net(S32& socket_out, int& nPort) int buff_size = 4; // Initialize windows specific stuff - if(WSAStartup(0x0202, &stWSAData)) + if (WSAStartup(0x0202, &stWSAData)) { S32 err = WSAGetLastError(); WSACleanup(); @@ -210,8 +209,8 @@ S32 start_net(S32& socket_out, int& nPort) } // Get a datagram socket - hSocket = (int)socket(AF_INET, SOCK_DGRAM, 0); - if (hSocket == INVALID_SOCKET) + hSocket = (int)socket(AF_INET, SOCK_DGRAM, 0); + if (hSocket == INVALID_SOCKET) { S32 err = WSAGetLastError(); WSACleanup(); @@ -304,7 +303,7 @@ S32 start_net(S32& socket_out, int& nPort) // Setup a destination address stDstAddr.sin_family = AF_INET; stDstAddr.sin_addr.s_addr = INVALID_HOST_IP_ADDRESS; - stDstAddr.sin_port = htons(nPort); + stDstAddr.sin_port = htons(nPort); socket_out = hSocket; return 0; @@ -393,10 +392,10 @@ S32 start_net(S32& socket_out, int& nPort) int rec_size = RECEIVE_BUFFER_SIZE; socklen_t buff_size = 4; - + // Create socket - hSocket = socket(AF_INET, SOCK_DGRAM, 0); - if (hSocket < 0) + hSocket = socket(AF_INET, SOCK_DGRAM, 0); + if (hSocket < 0) { llwarns << "socket() failed" << llendl; return 1; @@ -429,7 +428,7 @@ S32 start_net(S32& socket_out, int& nPort) } else { - // Name the socket (assign the local port number to receive on) + // Name the socket (assign the local port number to receive on) stLclAddr.sin_family = AF_INET; stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY); stLclAddr.sin_port = htons(nPort); @@ -474,7 +473,7 @@ S32 start_net(S32& socket_out, int& nPort) nPort = attempt_port; } // Set socket to be non-blocking - fcntl(hSocket, F_SETFL, O_NONBLOCK); + fcntl(hSocket, F_SETFL, O_NONBLOCK); // set a large receive buffer nRet = setsockopt(hSocket, SOL_SOCKET, SO_RCVBUF, (char *)&rec_size, buff_size); if (nRet) @@ -510,8 +509,8 @@ S32 start_net(S32& socket_out, int& nPort) // Setup a destination address char achMCAddr[MAXADDRSTR] = "127.0.0.1"; /* Flawfinder: ignore */ stDstAddr.sin_family = AF_INET; - stDstAddr.sin_addr.s_addr = ip_string_to_u32(achMCAddr); - stDstAddr.sin_port = htons(nPort); + stDstAddr.sin_addr.s_addr = ip_string_to_u32(achMCAddr); + stDstAddr.sin_port = htons(nPort); socket_out = hSocket; return 0; @@ -537,7 +536,7 @@ static int recvfrom_destip( int socket, void *buf, int len, struct sockaddr *fro iov[0].iov_base = buf; iov[0].iov_len = len; - memset( &msg, 0, sizeof msg ); + memset(&msg, 0, sizeof msg); msg.msg_name = from; msg.msg_namelen = *fromlen; msg.msg_iov = iov; @@ -545,14 +544,14 @@ static int recvfrom_destip( int socket, void *buf, int len, struct sockaddr *fro msg.msg_control = &cmsg; msg.msg_controllen = sizeof(cmsg); - size = recvmsg( socket, &msg, 0 ); + size = recvmsg(socket, &msg, 0); - if( size == -1 ) + if (size == -1) { return -1; } - for( cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR( &msg, cmsgptr ) ) + for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR( &msg, cmsgptr)) { if( cmsgptr->cmsg_level == SOL_IP && cmsgptr->cmsg_type == IP_PKTINFO ) { @@ -650,7 +649,7 @@ BOOL send_packet(int hSocket, const char * sendBuffer, int size, U32 recipient, } } } - while ( resend && send_attempts < 3); + while (resend && send_attempts < 3); if (send_attempts >= 3) { diff --git a/indra/llmessage/net.h b/indra/llmessage/net.h index 9f4f5c5821..0f2437479d 100644 --- a/indra/llmessage/net.h +++ b/indra/llmessage/net.h @@ -46,10 +46,10 @@ S32 receive_packet(int hSocket, char * receiveBuffer); BOOL send_packet(int hSocket, const char *sendBuffer, int size, U32 recipient, int nPort); // Returns TRUE on success. //void get_sender(char * tmp); -LLHost get_sender(); +LLHost get_sender(); U32 get_sender_port(); U32 get_sender_ip(void); -LLHost get_receiving_interface(); +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 |