diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt
index c5f82cf0527dd7c9c454d71d5345323e834ded07..4b679ef6a5bf35f19a0e1e6122de7ced84ce2f2f 100644
--- a/indra/llmessage/CMakeLists.txt
+++ b/indra/llmessage/CMakeLists.txt
@@ -76,6 +76,7 @@ set(llmessage_SOURCE_FILES
     llsdrpcserver.cpp
     llservicebuilder.cpp
     llservice.cpp
+    llsocks5.cpp
     llstoredmessage.cpp
     lltemplatemessagebuilder.cpp
     lltemplatemessagedispatcher.cpp
@@ -174,6 +175,7 @@ set(llmessage_HEADER_FILES
     llsdrpcserver.h
     llservice.h
     llservicebuilder.h
+    llsocks5.h
     llstoredmessage.h
     lltaskname.h
     llteleportflags.h
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 7c8b7e3584b6818309a3c5936dc768a3cdb43278..9c507517c775b53051302ba440e62da604650769 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -51,6 +51,8 @@
 #include "llthread.h"
 #include "lltimer.h"
 
+#include "llsocks5.h"
+
 //////////////////////////////////////////////////////////////////////////////
 /*
 	The trick to getting curl to do keep-alives is to reuse the
@@ -355,6 +357,27 @@ LLCurl::Easy* LLCurl::Easy::getEasy()
 	// multi handles cache if they are added to one.
 	CURLcode result = curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_DNS_CACHE_TIMEOUT, 0);
 	check_curl_code(result);
+
+	//Set the CURL options for either Socks or HTTP proxy
+	if (LLSocks::getInstance()->isHttpProxyEnabled())
+	{
+		std::string address = LLSocks::getInstance()->getHTTPProxy().getIPString();
+		U16 port = LLSocks::getInstance()->getHTTPProxy().getPort();
+		curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_PROXY,address.c_str());
+		curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_PROXYPORT,port);
+		if (LLSocks::getInstance()->getHttpProxyType() == LLPROXY_SOCKS)
+		{
+			curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
+			if(LLSocks::getInstance()->getSelectedAuthMethod()==METHOD_PASSWORD)
+			{
+				curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_PROXYUSERPWD,LLSocks::getInstance()->getProxyUserPwd().c_str());
+			}
+		}
+		else
+		{
+			curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
+		}
+	}
 	
 	++gCurlEasyCount;
 	return easy;
@@ -534,6 +557,26 @@ void LLCurl::Easy::prepRequest(const std::string& url,
 	//setopt(CURLOPT_VERBOSE, 1); // usefull for debugging
 	setopt(CURLOPT_NOSIGNAL, 1);
 
+	if (LLSocks::getInstance()->isHttpProxyEnabled())
+	{
+		std::string address = LLSocks::getInstance()->getHTTPProxy().getIPString();
+		U16 port = LLSocks::getInstance()->getHTTPProxy().getPort();
+		setoptString(CURLOPT_PROXY, address.c_str());
+		setopt(CURLOPT_PROXYPORT, port);
+		if (LLSocks::getInstance()->getHttpProxyType() == LLPROXY_SOCKS)
+		{
+			setopt(CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
+			if(LLSocks::getInstance()->getSelectedAuthMethod()==METHOD_PASSWORD)
+			{
+				setoptString(CURLOPT_PROXYUSERPWD,LLSocks::getInstance()->getProxyUserPwd());
+			}
+		}
+		else
+		{
+			setopt(CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
+		}
+	}
+
 	mOutput.reset(new LLBufferArray);
 	setopt(CURLOPT_WRITEFUNCTION, (void*)&curlWriteCallback);
 	setopt(CURLOPT_WRITEDATA, (void*)this);
diff --git a/indra/llmessage/llpacketring.cpp b/indra/llmessage/llpacketring.cpp
index 8999dec64a7793b6df21346b069e606b9994f8d7..0c8c5f763cb9a641c3fcd53caa49ca0e5c9b72e4 100644
--- a/indra/llmessage/llpacketring.cpp
+++ b/indra/llmessage/llpacketring.cpp
@@ -35,6 +35,17 @@
 #include "llrand.h"
 #include "u64.h"
 
+#include "llsocks5.h"
+#include "message.h"
+
+#if LL_WINDOWS
+	#include <winsock2.h>
+#else
+	#include <sys/socket.h>
+	#include <netinet/in.h>
+#endif
+
+
 ///////////////////////////////////////////////////////////
 LLPacketRing::LLPacketRing () :
 	mUseInThrottle(FALSE),
@@ -216,8 +227,31 @@ S32 LLPacketRing::receivePacket (S32 socket, char *datap)
 	else
 	{
 		// no delay, pull straight from net
+		if (LLSocks::isEnabled())
+		{
+			U8 buffer[MAX_BUFFER_SIZE];
+			packet_size = receive_packet(socket, (char*)buffer);
+			
+			if (packet_size > 10)
+			{
+				memcpy(datap,buffer+10,packet_size-10);
+			}
+			else
+			{
+				packet_size=0;
+			}
+
+			proxywrap_t * header;
+			header = (proxywrap_t *)buffer;
+			mLastSender.setAddress(header->addr);
+			mLastSender.setPort(ntohs(header->port));
+		}
+		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 +277,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 doSendPacket(h_socket, send_buffer, buf_size, host );
 	}
 	else
 	{
@@ -264,7 +298,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 = doSendPacket(h_socket, packetp->getData(), packet_size, packetp->getHost());
 				
 				delete packetp;
 				// Update the throttle
@@ -273,7 +307,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 =  doSendPacket(h_socket, send_buffer, buf_size, host );
 				packet_size = buf_size;
 
 				// Update the throttle
@@ -311,3 +345,23 @@ BOOL LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LL
 
 	return status;
 }
+
+BOOL LLPacketRing::doSendPacket(int h_socket, const char * send_buffer, S32 buf_size, LLHost host)
+{
+	
+	if (!LLSocks::isEnabled())
+	{
+		return send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort());
+	}
+
+	proxywrap_t *socks_header = (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+10, send_buffer, buf_size);
+
+	return send_packet(h_socket,(const char*) mProxyWrappedSendBuffer, buf_size+10, LLSocks::getInstance()->getUDPProxy().getAddress(), LLSocks::getInstance()->getUDPProxy().getPort());
+}
diff --git a/indra/llmessage/llpacketring.h b/indra/llmessage/llpacketring.h
index e6409d20488270f0f6aff5cd636f119fd42fb6a4..2fe2f8e1e947edef01655ecfc253748976045a86 100644
--- a/indra/llmessage/llpacketring.h
+++ b/indra/llmessage/llpacketring.h
@@ -82,6 +82,9 @@ class LLPacketRing
 
 	LLHost mLastSender;
 	LLHost mLastReceivingIF;
+
+	BOOL doSendPacket(int h_socket, const char * send_buffer, S32 buf_size, LLHost host);
+	U8 mProxyWrappedSendBuffer[NET_BUFFER_SIZE];
 };
 
 
diff --git a/indra/llmessage/llsocks5.cpp b/indra/llmessage/llsocks5.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8a63287f227e49d63ab5ee54e01f7bd34821c5a0
--- /dev/null
+++ b/indra/llmessage/llsocks5.cpp
@@ -0,0 +1,218 @@
+/**
+ * @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 <string>
+
+#include "linden_common.h"
+#include "net.h"
+#include "llhost.h"
+#include "message.h"
+#include "llsocks5.h"
+
+// Static class variable instances
+
+// We want this to be static to avoid excessive indirection on every
+// incomming packet just to do a simple bool test. The getter for this
+// member is also static
+bool LLSocks::sUdpProxyEnabled;
+bool LLSocks::sHttpProxyEnabled;
+
+LLSocks::LLSocks()
+{
+    sUdpProxyEnabled  = false;
+    sHttpProxyEnabled = false;
+    hProxyControlChannel = 0;
+    mProxyType = LLPROXY_SOCKS;
+}
+
+// Perform a Socks5 authentication and UDP assioacation to the proxy
+// specified by proxy, and assiocate UDP port message_port
+int LLSocks::proxyHandshake(LLHost proxy, U32 message_port)
+{
+    int 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 metho
+
+    result = tcp_handshake(hProxyControlChannel, (char*)&socks_auth_request, sizeof(socks_auth_request_t), (char*)&socks_auth_response, sizeof(socks_auth_response_t));
+    if (result != 0)
+    {
+        llwarns << "Socks authentication request failed, error on TCP control channel : " << result << llendl;
+        stopProxy();
+        return SOCKS_CONNECT_ERROR;
+    }
+    
+    if (socks_auth_response.method == AUTH_NOT_ACCEPTABLE)
+    {
+        llwarns << "Socks5 server refused all our authentication methods" << llendl;
+        stopProxy();
+        return SOCKS_NOT_ACCEPTABLE;
+    }
+
+    // SOCKS5 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 = (char *)malloc(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(hProxyControlChannel, password_auth, request_size, (char*)&password_reply, sizeof(authmethod_password_reply_t));
+        free (password_auth);
+
+        if (result != 0)
+        {
+        llwarns << "Socks authentication failed, error on TCP control channel : " << result << llendl;
+            stopProxy();
+            return SOCKS_CONNECT_ERROR;
+        }
+
+        if (password_reply.status != AUTH_SUCCESS)
+        {
+            llwarns << "Socks authentication failed" << llendl;
+            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.flag    = FIELD_RESERVED;
+    connect_request.atype   = ADDRESS_IPV4;
+    connect_request.address = 0; // 0.0.0.0 We are not fussy about address
+                                 // UDP is promiscious receive for our protocol
+    connect_request.port    = 0; // Port must be 0 if you ever want to connect via NAT and your router does port rewrite for you
+
+    result = tcp_handshake(hProxyControlChannel, (char*)&connect_request, sizeof(socks_command_request_t), (char*)&connect_reply, sizeof(socks_command_response_t));
+    if (result != 0)
+    {
+        llwarns << "Socks connect request failed, error on TCP control channel : " << result << llendl;
+        stopProxy();
+        return SOCKS_CONNECT_ERROR;
+    }
+
+    if (connect_reply.reply != REPLY_REQUEST_GRANTED)
+    {
+        //Something went wrong
+        llwarns << "Connection to SOCKS5 server failed, UDP forward request not granted" << llendl;
+        stopProxy();
+        return SOCKS_UDP_FWD_NOT_GRANTED;
+    }
+
+    mUDPProxy.setPort(ntohs(connect_reply.port)); // reply port is in network byte order
+    mUDPProxy.setAddress(proxy.getAddress());
+    // All good now we have been given the UDP port to send requests that need forwarding.
+    llinfos << "Socks 5 UDP proxy connected on " << mUDPProxy << llendl;
+    return SOCKS_OK;
+}
+
+int LLSocks::startProxy(LLHost proxy, U32 message_port)
+{
+    int status;
+
+    mTCPProxy   = proxy;
+
+    if (hProxyControlChannel)
+    {
+        tcp_close_channel(hProxyControlChannel);
+        hProxyControlChannel=0;
+    }
+
+    hProxyControlChannel = tcp_open_channel(proxy);	
+    if (hProxyControlChannel == -1)
+    {
+        return SOCKS_HOST_CONNECT_FAILED;
+    }
+
+    status = proxyHandshake(proxy, message_port);	
+    if (status == SOCKS_OK)
+    {
+        sUdpProxyEnabled=true;
+    }
+    return status;
+}
+
+int LLSocks::startProxy(std::string host, U32 port)
+{
+        mTCPProxy.setHostByName(host);
+        mTCPProxy.setPort(port);
+        return startProxy(mTCPProxy, (U32)gMessageSystem->mPort);
+}
+
+void LLSocks::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)
+    {
+        sHttpProxyEnabled = false;
+    }
+
+    if (hProxyControlChannel)
+    {
+        tcp_close_channel(hProxyControlChannel);
+        hProxyControlChannel=0;
+    }
+}
+
+void LLSocks::setAuthNone()
+{
+    mAuthMethodSelected = METHOD_NOAUTH;
+}
+
+void LLSocks::setAuthPassword(std::string username, std::string password)
+{
+    mAuthMethodSelected = METHOD_PASSWORD;
+    mSocksUsername      = username;
+    mSocksPassword      = password;
+}
+
+void LLSocks::EnableHttpProxy(LLHost httpHost, LLHttpProxyType type)
+{ 
+    sHttpProxyEnabled = true; 
+    mHTTPProxy        = httpHost; 
+    mProxyType        = type;
+}
diff --git a/indra/llmessage/llsocks5.h b/indra/llmessage/llsocks5.h
new file mode 100644
index 0000000000000000000000000000000000000000..a78acb8b2380dcf817211815678e85a893ac6182
--- /dev/null
+++ b/indra/llmessage/llsocks5.h
@@ -0,0 +1,237 @@
+/**
+ * @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_SOCKS5_H
+#define LL_SOCKS5_H
+
+#include "llhost.h"
+#include "llmemory.h"
+#include "llsingleton.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
+
+// 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 {
+    unsigned char octects[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 replys
+#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 socks5 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)
+
+// Socks5 command packet
+struct socks_command_request_t {
+    unsigned char version;
+    unsigned char command;
+    unsigned char flag;
+    unsigned char atype;
+    U32           address;
+    U16           port;
+};
+
+// Standard socks5 reply packet
+struct socks_command_response_t {
+    unsigned char version;
+    unsigned char reply;
+    unsigned char flag;
+    unsigned char atype;
+    unsigned char add_bytes[4];
+    U16           port;
+};
+
+#define AUTH_NOT_ACCEPTABLE 0xFF // reply if prefered methods are not avaiable
+#define AUTH_SUCCESS        0x00 // reply if authentication successfull
+
+// socks 5 authentication request, stating which methods the client supports
+struct socks_auth_request_t {
+    unsigned char version;
+    unsigned char num_methods;
+    unsigned char methods; // We are only using a single method currently
+};
+
+// socks 5 authentication response packet, stating server prefered method
+struct socks_auth_response_t {
+    unsigned char version;
+    unsigned char method;
+};
+
+// socks 5 password reply packet
+struct authmethod_password_reply_t {
+    unsigned char version;
+    unsigned char 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 LLSocks: public LLSingleton<LLSocks>
+{
+public:
+    LLSocks();
+
+    // Start a connection to the socks 5 proxy
+    int startProxy(std::string host,U32 port);
+    int startProxy(LLHost proxy,U32 messagePort);
+
+    // Disconnect and clean up any connection to the socks 5 proxy
+    void stopProxy();
+
+    // Set up to use Password auth when connecting to the socks proxy
+    void setAuthPassword(std::string username,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() { 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 Socks5 or a http proxy
+    // as specified in type
+    void EnableHttpProxy(LLHost httpHost,LLHttpProxyType type);
+
+    // Stop proxying http packets
+    void DisableHttpProxy() {sHttpProxyEnabled = false;};
+
+    // get the UDP proxy address and port
+    LLHost getUDPProxy(){return mUDPProxy;};
+
+    // get the socks 5 TCP control channel address and port
+    LLHost getTCPProxy(){return mTCPProxy;};
+
+    //get the http proxy address and port
+    LLHost getHTTPProxy(){return mHTTPProxy;};
+
+    // get the currently selected http proxy type
+    LLHttpProxyType getHttpProxyType(){return mProxyType;};
+
+    //Get the username password in a curl compatible format
+    std::string getProxyUserPwd(){ return (mSocksUsername + ":" + mSocksPassword);};
+
+private:
+
+    // Open a communication channel to the socks5 proxy proxy, at port messagePort
+    int proxyHandshake(LLHost proxy,U32 messagePort);
+
+    // socket handle to proxy tcp control channel
+    S32 hProxyControlChannel;
+
+    // is the UDP proxy enabled
+    static bool sUdpProxyEnabled;
+    // is the http proxy enabled
+    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;
+};
+
+#endif
diff --git a/indra/llmessage/net.cpp b/indra/llmessage/net.cpp
index 97611c3b5198f4f8ee34b956d63afb724b834bd1..ab5c1950c689dac359dc6ff5dca24e52ffec51d6 100644
--- a/indra/llmessage/net.cpp
+++ b/indra/llmessage/net.cpp
@@ -50,6 +50,7 @@
 #include "lltimer.h"
 #include "indra_constants.h"
 
+#include "llsocks5.h"
 
 // Globals
 #if LL_WINDOWS
@@ -189,6 +190,90 @@ U32 ip_string_to_u32(const char* ip_string)
 
 #if LL_WINDOWS
  
+int tcp_handshake(S32 handle, char * dataout, int outlen, char * datain, int maxinlen)
+{
+	int result;
+	result = send(handle, dataout, outlen, 0);
+	if (result != outlen)
+	{
+		S32 err = WSAGetLastError();
+		llwarns << "Error sending data to proxy control channel, number of bytes sent were " << result << " error code was " << err << llendl;
+		return -1;
+	}
+
+	result = recv(handle, datain, maxinlen, 0);
+	if (result != maxinlen)
+	{
+		S32 err = WSAGetLastError();
+		llwarns << "Error receiving data from proxy control channel, number of bytes received were " << result << " error code was " << err << llendl;
+		return -1;
+	}
+
+	return 0;
+}
+
+S32 tcp_open_channel(LLHost host)
+{
+	// Open a TCP channel
+	// Jump through some hoops to ensure that if the request hosts is down
+	// or not reachable connect() does not block
+
+	S32 handle;
+	handle = socket(AF_INET, SOCK_STREAM, 0);
+	if (!handle)
+	{
+		llwarns << "Error opening TCP control socket, socket() returned " << handle << llendl;
+		return -1;
+	}
+
+	struct sockaddr_in address;
+	address.sin_port        = htons(host.getPort());
+	address.sin_family      = AF_INET;
+	address.sin_addr.s_addr = host.getAddress();
+
+	// Non blocking 
+	WSAEVENT hEvent=WSACreateEvent();
+	WSAEventSelect(handle, hEvent, FD_CONNECT) ;
+	connect(handle, (struct sockaddr*)&address, sizeof(address)) ;
+	// Wait fot 5 seconds, if we can't get a TCP channel open in this
+	// time frame then there is something badly wrong.
+	WaitForSingleObject(hEvent, 1000*5); // 5 seconds time out
+
+	WSANETWORKEVENTS netevents;
+	WSAEnumNetworkEvents(handle,hEvent,&netevents);
+
+	// Check the async event status to see if we connected
+	if ((netevents.lNetworkEvents & FD_CONNECT) == FD_CONNECT)
+	{
+		if (netevents.iErrorCode[FD_CONNECT_BIT] != 0)
+		{
+			llwarns << "Unable to open TCP channel, WSA returned an error code of " << netevents.iErrorCode[FD_CONNECT_BIT] << llendl;
+			WSACloseEvent(hEvent);
+			return -1;
+		}
+
+		// Now we are connected disable non blocking
+		// we don't need support an async interface as
+		// currently our only consumer (socks5) will make one round
+		// of packets then just hold the connection open
+		WSAEventSelect(handle, hEvent, NULL) ;
+		unsigned long NonBlock = 0;
+		ioctlsocket(handle, FIONBIO, &NonBlock);
+
+		return handle;
+	}
+
+	llwarns << "Unable to open TCP channel, Timeout is the host up?" << netevents.iErrorCode[FD_CONNECT_BIT] << llendl;
+	return -1;
+}
+
+void tcp_close_channel(S32 handle)
+{
+	llinfos << "Closing TCP channel" << llendl;
+	shutdown(handle, SD_BOTH);
+	closesocket(handle);
+}
+
 S32 start_net(S32& socket_out, int& nPort) 
 {			
 	// Create socket, make non-blocking
@@ -385,6 +470,77 @@ BOOL send_packet(int hSocket, const char *sendBuffer, int size, U32 recipient, i
 
 #else
 
+
+int tcp_handshake(S32 handle, char * dataout, int outlen, char * datain, int maxinlen)
+{
+	if (send(handle, dataout, outlen, 0) != outlen)
+	{
+		llwarns << "Error sending data to proxy control channel" << llendl;
+		return -1;
+	}
+
+	if (recv(handle, datain, maxinlen, 0) != maxinlen)
+	{
+		llwarns << "Error receiving data to proxy control channel" << llendl;		
+		return -1;
+	}
+
+	return 0;
+}
+
+S32 tcp_open_channel(LLHost host)
+{
+	S32 handle;
+	handle = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+	if (!handle)
+	{
+		llwarns << "Error opening TCP control socket, socket() returned " << handle << llendl;
+		return -1;
+	}
+
+	struct sockaddr_in address;
+	address.sin_port        = htons(host.getPort());
+	address.sin_family      = AF_INET;
+	address.sin_addr.s_addr = host.getAddress();
+
+	// Set the socket to non blocking for the connect()
+	int flags = fcntl(handle, F_GETFL, 0);
+	fcntl(handle, F_SETFL, flags | O_NONBLOCK);
+
+	S32 error = connect(handle, (sockaddr*)&address, sizeof(address));
+	if (error && (errno != EINPROGRESS))
+	{
+			llwarns << "Unable to open TCP channel, error code: " << errno << llendl;
+			return -1;
+	}
+
+	struct timeval timeout;
+	timeout.tv_sec  = 5; // Maximum time to wait for the connect() to complete
+	timeout.tv_usec = 0;
+	fd_set fds;
+	FD_ZERO(&fds);
+	FD_SET(handle, &fds);
+
+	// See if we have connectde or time out after 5 seconds
+	U32 rc = select(sizeof(fds)*8, NULL, &fds, NULL, &timeout);	
+	
+	if (rc != 1) // we require exactly one descriptor to be set
+	{
+			llwarns << "Unable to open TCP channel" << llendl;
+			return -1;
+	}
+
+	// Return the socket to blocking operations
+	fcntl(handle, F_SETFL, flags);
+
+	return handle;
+}
+
+void tcp_close_channel(S32 handle)
+{
+	close(handle);
+}
+
 //  Create socket, make non-blocking
 S32 start_net(S32& socket_out, int& nPort)
 {
diff --git a/indra/llmessage/net.h b/indra/llmessage/net.h
index 9f4f5c5821272ba5fde05c2932220a74cbd5c7c8..d93ed20c98723b7ec9e69776e2c9934364a8a386 100644
--- a/indra/llmessage/net.h
+++ b/indra/llmessage/net.h
@@ -52,6 +52,11 @@ U32		get_sender_ip(void);
 LLHost  get_receiving_interface();
 U32		get_receiving_interface_ip(void);
 
+// Some helpful tcp functions added for the socks 5 proxy support
+S32 tcp_open_channel(LLHost host); // Open a tcp channel to a given host
+void tcp_close_channel(S32 handle); // Close an open tcp channel
+int tcp_handshake(S32 handle, char * dataout, int outlen, char * datain, int maxinlen); // Do a TCP data handshake
+
 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
 U32			ip_string_to_u32(const char* ip_string);	// Wrapper for inet_addr()
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index fc7fd2dd8a03b7b853d76b07e4cd1f8ef1176154..871fd7eb975e32597f7b2a7baafce7cf9338b288 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -796,6 +796,83 @@
       <key>Value</key>
       <integer>5</integer>
     </map>
+    <key>Socks5ProxyEnabled</key>
+    <map>
+      <key>Comment</key>
+      <string>Use Socks5 Proxy</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>1</integer>
+    </map>
+    <key>Socks5HttpProxyType</key>
+    <map>
+      <key>Comment</key>
+      <string>Proxy type to use for HTTP operations</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>String</string>
+      <key>Value</key>
+      <string>Socks</string>
+    </map>
+    <key>Socks5ProxyHost</key>
+    <map>
+      <key>Comment</key>
+      <string>Socks 5 Proxy Host</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>String</string>
+      <key>Value</key>
+      <string>64.79.219.97</string>
+    </map>
+    <key>Socks5ProxyPort</key>
+    <map>
+      <key>Comment</key>
+      <string>Socks 5 Proxy Port</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>U32</string>
+      <key>Value</key>
+      <integer>1080</integer>
+    </map>
+     <key>Socks5Username</key>
+    <map>
+      <key>Comment</key>
+      <string>Socks 5 Username</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>String</string>
+      <key>Value</key>
+      <string></string>
+    </map>
+    <key>Socks5Password</key>
+    <map>
+      <key>Comment</key>
+      <string>Socks 5 Password</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>String</string>
+      <key>Value</key>
+      <string></string>
+    </map>
+    <key>Socks5AuthType</key>
+    <map>
+      <key>Comment</key>
+      <string>Selected Auth mechanism for Socks5</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>String</string>
+      <key>Value</key>
+      <string>None</string>
+    </map>
     <key>BuildAxisDeadZone0</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 60a2f813aaff98a963a38371f4ab8801e7f6e6f3..b49026de38b0b88458e3ca0de6cbc0bb7da468bb 100755
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -105,6 +105,7 @@
 #include "llviewermedia.h"
 #include "llpluginclassmedia.h"
 #include "llteleporthistorystorage.h"
+#include "llsocks5.h"
 
 #include "lllogininstance.h"        // to check if logged in yet
 #include "llsdserialize.h"
@@ -342,6 +343,7 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
 	mCommitCallbackRegistrar.add("Pref.getUIColor",				boost::bind(&LLFloaterPreference::getUIColor, this ,_1, _2));
 	mCommitCallbackRegistrar.add("Pref.MaturitySettings",		boost::bind(&LLFloaterPreference::onChangeMaturity, this));
 	mCommitCallbackRegistrar.add("Pref.BlockList",				boost::bind(&LLFloaterPreference::onClickBlockList, this));
+    mCommitCallbackRegistrar.add("Pref.Proxy",                    boost::bind(&LLFloaterPreference::onClickProxySettings, this));
 	
 	sSkin = gSavedSettings.getString("SkinCurrent");
 
@@ -615,6 +617,12 @@ void LLFloaterPreference::cancel()
 		updateDoubleClickControls();
 		mDoubleClickActionDirty = false;
 	}
+    LLFloaterPreferenceProxy * advanced_socks_settings = LLFloaterReg::findTypedInstance<LLFloaterPreferenceProxy>("prefs_socks5_advanced");
+    if(advanced_socks_settings)
+    {
+        advanced_socks_settings->cancel();
+    }
+    
 }
 
 void LLFloaterPreference::onOpen(const LLSD& key)
@@ -1535,6 +1543,11 @@ void LLFloaterPreference::updateDoubleClickSettings()
 	}
 }
 
+void LLFloaterPreference::onClickProxySettings()
+{
+    LLFloaterReg::showInstance("prefs_proxy");
+}
+
 void LLFloaterPreference::updateDoubleClickControls()
 {
 	// check is one of double-click actions settings enabled
@@ -1902,3 +1915,161 @@ void LLPanelPreferenceGraphics::setHardwareDefaults()
 	resetDirtyChilds();
 	LLPanelPreference::setHardwareDefaults();
 }
+
+
+/* ------------------------------------------------------------ */
+
+LLFloaterPreferenceProxy::LLFloaterPreferenceProxy(const LLSD& key)
+    : LLFloater(key),
+    mSocksSettingsDirty(false)
+{
+    mCommitCallbackRegistrar.add("Proxy.OK",                boost::bind(&LLFloaterPreferenceProxy::onBtnOk, this));
+    mCommitCallbackRegistrar.add("Proxy.Cancel",            boost::bind(&LLFloaterPreferenceProxy::onBtnCancel, this));
+    mCommitCallbackRegistrar.add("Proxy.Change",            boost::bind(&LLFloaterPreferenceProxy::onChangeSocksSettings, this));
+}
+
+LLFloaterPreferenceProxy::~LLFloaterPreferenceProxy()
+{
+}
+
+BOOL LLFloaterPreferenceProxy::postBuild()
+{
+    LLLineEditor* edit = getChild<LLLineEditor>("socks_password_editor");
+    if (edit) edit->setDrawAsterixes(TRUE);
+
+    LLRadioGroup* socksAuth = getChild<LLRadioGroup>("socks5_auth_type");
+    if(socksAuth->getSelectedValue().asString() == "None")
+    {
+        getChild<LLLineEditor>("socks5_username")->setEnabled(false);
+        getChild<LLLineEditor>("socks5_password")->setEnabled(false);
+    }
+
+    center();
+    return TRUE;
+}
+
+void LLFloaterPreferenceProxy::onOpen(const LLSD& key)
+{
+    saveSettings();
+}
+
+void LLFloaterPreferenceProxy::onClose(bool app_quitting)
+{
+    if(mSocksSettingsDirty)
+    {
+
+        // If the user plays with the Socks proxy settings after login, its only fair we let them know
+        // it will not be updated untill next restart.
+        if(LLStartUp::getStartupState()>STATE_LOGIN_WAIT)
+        {        
+            if(this->mSocksSettingsDirty == true )
+            {
+                LLNotifications::instance().add("ChangeSocks5Settings",LLSD(),LLSD());
+                mSocksSettingsDirty = false; // we have notified the user now be quiet again
+            }
+        }
+    }
+}
+
+void LLFloaterPreferenceProxy::saveSettings()
+{
+    // Save the value of all controls in the hierarchy
+    mSavedValues.clear();
+    std::list<LLView*> view_stack;
+    view_stack.push_back(this);
+    while(!view_stack.empty())
+    {
+        // Process view on top of the stack
+        LLView* curview = view_stack.front();
+        view_stack.pop_front();
+
+        LLUICtrl* ctrl = dynamic_cast<LLUICtrl*>(curview);
+        if (ctrl)
+        {
+            LLControlVariable* control = ctrl->getControlVariable();
+            if (control)
+            {
+                mSavedValues[control] = control->getValue();
+            }
+        }
+                    
+        // Push children onto the end of the work stack
+        for (child_list_t::const_iterator iter = curview->getChildList()->begin();
+             iter != curview->getChildList()->end(); ++iter)
+        {
+            view_stack.push_back(*iter);
+        }
+    }    
+
+}
+
+void LLFloaterPreferenceProxy::onBtnOk()
+{
+    // commit any outstanding text entry
+    if (hasFocus())
+    {
+        LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
+        if (cur_focus && cur_focus->acceptsTextInput())
+        {
+            cur_focus->onCommit();
+        }
+    }
+    closeFloater(false);
+}
+
+void LLFloaterPreferenceProxy::onBtnCancel()
+{
+    if (hasFocus())
+    {
+        LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
+        if (cur_focus && cur_focus->acceptsTextInput())
+        {
+            cur_focus->onCommit();
+        }
+        refresh();
+    }
+    
+    cancel();
+    
+}
+void LLFloaterPreferenceProxy::cancel()
+{
+
+    for (control_values_map_t::iterator iter =  mSavedValues.begin();
+         iter !=  mSavedValues.end(); ++iter)
+    {
+        LLControlVariable* control = iter->first;
+        LLSD ctrl_value = iter->second;
+        control->set(ctrl_value);
+    }
+    
+    closeFloater();
+}
+
+void LLFloaterPreferenceProxy::onChangeSocksSettings() 
+{
+    mSocksSettingsDirty = true; 
+
+    LLRadioGroup* socksAuth = getChild<LLRadioGroup>("socks5_auth_type");
+    if(socksAuth->getSelectedValue().asString() == "None")
+    {
+        getChild<LLLineEditor>("socks5_username")->setEnabled(false);
+        getChild<LLLineEditor>("socks5_password")->setEnabled(false);
+    }
+    else
+    {
+        getChild<LLLineEditor>("socks5_username")->setEnabled(true);
+        getChild<LLLineEditor>("socks5_password")->setEnabled(true);
+    }
+
+    //Check for invalid states for the other http proxy radio
+    LLRadioGroup* otherHttpProxy = getChild<LLRadioGroup>("other_http_proxy_selection");
+    if( (otherHttpProxy->getSelectedValue().asString() == "Socks" && 
+        getChild<LLCheckBoxCtrl>("socks_proxy_enabled")->get() == FALSE )||(
+        otherHttpProxy->getSelectedValue().asString() == "Web" && 
+        getChild<LLCheckBoxCtrl>("web_proxy_enabled")->get() == FALSE ) )
+    {    
+        otherHttpProxy->selectFirstItem();
+    }
+
+};
\ No newline at end of file
diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h
index ef9257534763f7d29f42012f2fdd5dec6e4fed73..4a180ce0f74d7f86429c7f1d83aececf508a8b7a 100644
--- a/indra/newview/llfloaterpreference.h
+++ b/indra/newview/llfloaterpreference.h
@@ -155,6 +155,7 @@ class LLFloaterPreference : public LLFloater, public LLAvatarPropertiesObserver
 	void applyResolution();
 	void onChangeMaturity();
 	void onClickBlockList();
+	void onClickProxySettings();
 	void applyUIColor(LLUICtrl* ctrl, const LLSD& param);
 	void getUIColor(LLUICtrl* ctrl, const LLSD& param);
 	
@@ -228,4 +229,33 @@ class LLPanelPreferenceGraphics : public LLPanelPreference
 	
 };
 
+class LLFloaterPreferenceProxy : public LLFloater
+{
+public: 
+	LLFloaterPreferenceProxy(const LLSD& key);
+	~LLFloaterPreferenceProxy();
+
+	/// show off our menu
+	static void show();
+	void cancel();
+	
+protected:
+	BOOL postBuild();
+	void onOpen(const LLSD& key);
+	void onClose(bool app_quitting);
+	void saveSettings();
+	void onBtnOk();
+	void onBtnCancel();
+
+	void onChangeSocksSettings();
+
+private:
+	
+	bool mSocksSettingsDirty;
+	typedef std::map<LLControlVariable*, LLSD> control_values_map_t;
+	control_values_map_t mSavedValues;
+
+};
+
+
 #endif  // LL_LLPREFERENCEFLOATER_H
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 86b09473ab371d1876613bd90ea9a5da9544c748..d54c5b177a534b826d0b59eb918aa88c5582aecc 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -191,6 +191,8 @@
 #include "llevents.h"
 #include "llstartuplistener.h"
 
+#include "llsocks5.h"
+
 #if LL_WINDOWS
 #include "lldxhardware.h"
 #endif
@@ -390,7 +392,7 @@ bool idle_startup()
 		gSavedSettings.setS32("LastGPUClass", LLFeatureManager::getInstance()->getGPUClass());
 
 		// load dynamic GPU/feature tables from website (S3)
-		LLFeatureManager::getInstance()->fetchHTTPTables();
+		//LLFeatureManager::getInstance()->fetchHTTPTables();
 		
 		std::string xml_file = LLUI::locateSkin("xui_version.xml");
 		LLXMLNodePtr root;
@@ -592,6 +594,15 @@ bool idle_startup()
 
 		LL_INFOS("AppInit") << "Message System Initialized." << LL_ENDL;
 		
+		//-------------------------------------------------
+		// Init the socks 5 proxy and open the control TCP 
+		// connection if the user is using SOCKS5
+		// We need to do this early incase the user is using
+		// socks for http so we get the login screen via socks
+		//-------------------------------------------------
+
+		LLStartUp::handleSocksProxy(false);
+
 		//-------------------------------------------------
 		// Init audio, which may be needed for prefs dialog
 		// or audio cues in connection UI.
@@ -807,6 +818,27 @@ bool idle_startup()
 
 	if (STATE_LOGIN_CLEANUP == LLStartUp::getStartupState())
 	{
+		// Post login screen, we should see if any settings have changed that may
+		// require us to either start/stop or change the socks proxy. As various communications
+		// past this point may require the proxy to be up.
+		if ( gSavedSettings.getBOOL("Socks5ProxyEnabled") )
+		{
+			if (!LLStartUp::handleSocksProxy(true))
+			{
+				// Proxy start up failed, we should now bail the state machine
+				// HandleSocksProxy() will have reported an error to the user 
+				// already, so we just go back to the login screen. The user
+				// could then change the preferences to fix the issue. 
+				LLStartUp::setStartupState(STATE_LOGIN_SHOW);
+				return FALSE;
+			}
+		}
+		else
+		{
+			LLSocks::getInstance()->stopProxy();
+		}
+		
+
 		//reset the values that could have come in from a slurl
 		// DEV-42215: Make sure they're not empty -- gUserCredential
 		// might already have been set from gSavedSettings, and it's too bad
@@ -2728,6 +2760,95 @@ void LLStartUp::setStartSLURL(const LLSLURL& slurl)
     }
 }
 
+bool LLStartUp::handleSocksProxy(bool reportOK)
+{
+	std::string httpProxyType = gSavedSettings.getString("Socks5HttpProxyType");
+
+	// Determine the http proxy type (if any)
+	if ((httpProxyType.compare("Web") == 0) && gSavedSettings.getBOOL("BrowserProxyEnabled"))
+	{
+		LLHost httpHost;
+		httpHost.setHostByName(gSavedSettings.getString("BrowserProxyAddress"));
+		httpHost.setPort(gSavedSettings.getS32("BrowserProxyPort"));
+		LLSocks::getInstance()->EnableHttpProxy(httpHost,LLPROXY_HTTP);
+	}
+	else if ((httpProxyType.compare("Socks") == 0) && gSavedSettings.getBOOL("Socks5ProxyEnabled"))
+	{
+		LLHost httpHost;
+		httpHost.setHostByName(gSavedSettings.getString("Socks5ProxyHost"));
+		httpHost.setPort(gSavedSettings.getU32("Socks5ProxyPort"));
+		LLSocks::getInstance()->EnableHttpProxy(httpHost,LLPROXY_SOCKS);
+	}
+	else
+	{
+		LLSocks::getInstance()->DisableHttpProxy();
+	}
+	
+	bool use_socks_proxy = gSavedSettings.getBOOL("Socks5ProxyEnabled");
+	if (use_socks_proxy)
+	{	
+
+		// Determine and update LLSocks with the saved authentication system
+		std::string auth_type = gSavedSettings.getString("Socks5AuthType");
+			
+		if (auth_type.compare("None") == 0)
+		{
+			LLSocks::getInstance()->setAuthNone();
+		}
+
+		if (auth_type.compare("UserPass") == 0)
+		{
+			LLSocks::getInstance()->setAuthPassword(gSavedSettings.getString("Socks5Username"),gSavedSettings.getString("Socks5Password"));
+		}
+
+		// Start the proxy and check for errors
+		int status = LLSocks::getInstance()->startProxy(gSavedSettings.getString("Socks5ProxyHost"), gSavedSettings.getU32("Socks5ProxyPort"));
+		LLSD subs;
+		LLSD payload;
+		subs["HOST"] = gSavedSettings.getString("Socks5ProxyHost");
+		subs["PORT"] = (S32)gSavedSettings.getU32("Socks5ProxyPort");
+
+		switch(status)
+		{
+			case SOCKS_OK:
+				return true;
+				break;
+
+			case SOCKS_CONNECT_ERROR: // TCP Fail
+				LLNotifications::instance().add("SOCKS_CONNECT_ERROR", subs,payload);
+				break;
+
+			case SOCKS_NOT_PERMITTED: // Socks5 server rule set refused connection
+				LLNotifications::instance().add("SOCKS_NOT_PERMITTED", subs,payload);
+				break;
+					
+			case SOCKS_NOT_ACCEPTABLE: // Selected authentication is not acceptable to server
+				LLNotifications::instance().add("SOCKS_NOT_ACCEPTABLE", subs,payload);
+				break;
+
+			case SOCKS_AUTH_FAIL: // Authentication failed
+				LLNotifications::instance().add("SOCKS_AUTH_FAIL", subs,payload);
+				break;
+
+			case SOCKS_UDP_FWD_NOT_GRANTED: // UDP forward request failed
+				LLNotifications::instance().add("SOCKS_UDP_FWD_NOT_GRANTED", subs,payload);
+				break;
+
+			case SOCKS_HOST_CONNECT_FAILED: // Failed to open a TCP channel to the socks server
+				LLNotifications::instance().add("SOCKS_HOST_CONNECT_FAILED", subs,payload);
+				break;		
+		}
+
+		return false;
+	}
+	else
+	{
+		LLSocks::getInstance()->stopProxy(); //ensure no UDP proxy is running and its all cleaned up
+	}
+
+	return true;
+}
+
 bool login_alert_done(const LLSD& notification, const LLSD& response)
 {
 	LLPanelLogin::giveFocus();
diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h
index b3d9ef1dcc7805b9a3003ba87fe70c42d3f51c2f..a512ec7bff612f0786598205dd0c05426f31a620 100644
--- a/indra/newview/llstartup.h
+++ b/indra/newview/llstartup.h
@@ -113,6 +113,8 @@ class LLStartUp
 	static void setStartSLURL(const LLSLURL& slurl); 
 	static LLSLURL& getStartSLURL() { return sStartSLURL; } 
 
+	static bool handleSocksProxy(bool reportOK); //handle kicking the socks 5 proxy code at startup time
+
 private:
 	static LLSLURL sStartSLURL;
 
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index a1c2c926af55786d0f5b55b309065e7f751ba964..7a078a8b53c588fd83c710fdc63da052b02a5ece 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -230,6 +230,7 @@ void LLViewerFloaterReg::registerFloaters()
 
 	LLFloaterReg::add("postcard", "floater_postcard.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPostcard>);
 	LLFloaterReg::add("preferences", "floater_preferences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreference>);
+	LLFloaterReg::add("prefs_proxy", "floater_preferences_proxy.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreferenceProxy>);
 	LLFloaterReg::add("prefs_hardware_settings", "floater_hardware_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHardwareSettings>);
 	LLFloaterReg::add("perm_prefs", "floater_perm_prefs.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPerms>);
 	LLFloaterReg::add("pref_joystick", "floater_joystick.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterJoystick>);
diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp
index 257884d921ba1f887e45a4034c9eb1fa08429524..b3d899c61ae5834bea40d5fe812e985b43e05947 100644
--- a/indra/newview/llxmlrpctransaction.cpp
+++ b/indra/newview/llxmlrpctransaction.cpp
@@ -41,6 +41,8 @@
 #include "llappviewer.h"
 #include "lltrans.h"
 
+#include "llsocks5.h"
+
 // Static instance of LLXMLRPCListener declared here so that every time we
 // bring in this code, we instantiate a listener. If we put the static
 // instance of LLXMLRPCListener into llxmlrpclistener.cpp, the linker would
@@ -307,16 +309,23 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip)
 	}
 	mErrorCert = NULL;
 	
-	if (gSavedSettings.getBOOL("BrowserProxyEnabled"))
+	if (LLSocks::getInstance()->isHttpProxyEnabled())
 	{
-		mProxyAddress = gSavedSettings.getString("BrowserProxyAddress");
-		S32 port = gSavedSettings.getS32 ( "BrowserProxyPort" );
-
-		// tell curl about the settings
-		mCurlRequest->setoptString(CURLOPT_PROXY, mProxyAddress);
+		std::string address = LLSocks::getInstance()->getHTTPProxy().getIPString();
+		U16 port = LLSocks::getInstance()->getHTTPProxy().getPort();
+		mCurlRequest->setoptString(CURLOPT_PROXY, address.c_str());
 		mCurlRequest->setopt(CURLOPT_PROXYPORT, port);
+		if (LLSocks::getInstance()->getHttpProxyType() == LLPROXY_SOCKS)
+		{
+			mCurlRequest->setopt(CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
+			if(LLSocks::getInstance()->getSelectedAuthMethod()==METHOD_PASSWORD)
+				mCurlRequest->setoptString(CURLOPT_PROXYUSERPWD,LLSocks::getInstance()->getProxyUserPwd());
+		}
+		else
+		{
 		mCurlRequest->setopt(CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
 	}
+	}
 
 //	mCurlRequest->setopt(CURLOPT_VERBOSE, 1); // usefull for debugging
 	mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1);
diff --git a/indra/newview/skins/default/xui/en/floater_preferences_proxy.xml b/indra/newview/skins/default/xui/en/floater_preferences_proxy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..bb9ade067b7a15e0ec46f2ae4f4424fadf6f860b
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_preferences_proxy.xml
@@ -0,0 +1,274 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ height="490"
+ layout="topleft"
+ name="Socks5 Advanced Settings Floater"
+ help_topic="hardware_settings_floater"
+ title="Socks5 proxy advanced settings"
+ width="385">
+    <check_box
+     control_name="BrowserProxyEnabled"
+     top="30"
+     enabled="true"
+     follows="left|top"
+     height="14"
+     initial_value="false"
+     commit_callback.function="Proxy.Change"
+     label="Use HTTP Proxy for Web pages"
+     left_delta="10"
+     mouse_opaque="true"
+     name="web_proxy_enabled"
+     radio_style="false"
+     width="400"
+     top_pad="5" />
+    <check_box
+     control_name="Socks5ProxyEnabled"
+     height="16"
+     label="Use Socks 5 Proxy for UDP traffic"
+     layout="topleft"
+     left_delta="0"
+     name="socks_proxy_enabled"
+     top_pad="5"
+     width="256"
+     commit_callback.function="Proxy.Change" />
+    <text
+     type="string"
+     length="1"
+     follows="left|top"
+     height="10"
+     layout="topleft"
+     left="10"
+     name="Proxy location"
+     top_delta="30"
+     width="300">
+        Other Http traffic proxy:
+     </text>
+     <radio_group
+      control_name="Socks5HttpProxyType"
+      height="60"
+      layout="topleft"
+      name="other_http_proxy_selection"
+      top_pad="10"
+      width="120"
+      border="1"
+      left_delta="10" 
+      commit_callback.function="Proxy.Change" >
+          <radio_item
+           height="16"
+           label="Do not proxy"
+           layout="topleft"
+           value="None"
+           width="120"
+           tool_tip="Non web Http trafic should NOT be sent to any proxy."/>
+          <radio_item
+           height="16"
+           label="Use Socks 5 Proxy"
+           layout="topleft"
+           value="Socks"
+           width="120"
+           enabled_control="Socks5ProxyEnabled"
+           tool_tip="Non-web Http will be sent to the configured Socks 5 proxy."/>
+          <radio_item
+           height="16"
+           label="Use Http Proxy"
+           layout="topleft"
+           value="Web"
+           width="120"
+           enabled_control="BrowserProxyEnabled"
+           tool_tip="Non-web Http will be sent to the configured Web proxy." />
+    </radio_group>
+    <text
+	 type="string"
+	 length="1"
+	 follows="left|top"
+	 height="10"
+	 left="15"
+	 layout="topleft"
+	 name="Proxy location"
+	 top_delta="82"
+	 width="300">
+	    HTTP Proxy:
+	</text>
+	<line_editor
+	 control_name="BrowserProxyAddress"
+	 enabled_control="BrowserProxyEnabled"
+     follows="left|top"
+	 font="SansSerif"
+	 height="23"
+	 layout="topleft"
+	 left_delta="0"
+	 name="web_proxy_editor"
+	 tool_tip="The DNS name or IP address of the HTTP proxy you would like to use."
+	 top_pad="4"
+	 width="200" />
+	<spinner
+	 control_name="BrowserProxyPort"
+	 enabled_control="BrowserProxyEnabled"
+     decimal_digits="0"
+	 follows="left|top"
+	 height="23"
+	 increment="1"
+	 initial_value="80"
+	 label="Port number:"
+	 label_width="95"
+	 layout="topleft"
+	 left_delta="210"
+	 max_val="12000"
+	 min_val="10"
+	 name="web_proxy_port"
+	 top_delta="0"
+      tool_tip="The port of the HTTP proxy you would like to use."
+	 width="145" />
+	<text
+	 type="string"
+	 length="1"
+	 follows="left|top"
+	 height="10"
+	 layout="topleft"
+	 left="15"
+	 name="Proxy location"
+	 top_delta="32"
+	 width="300">
+	    SOCKS 5 Proxy:
+	</text>
+	<line_editor
+	 control_name="Socks5ProxyHost"
+	 enabled_control="Socks5ProxyEnabled"
+	 follows="left|top"
+	 font="SansSerif"
+	 height="23"
+	 layout="topleft"
+	 left_delta="0"
+	 name="socks_proxy_editor"
+	 tool_tip="The DNS name or IP address of the SOCKS 5 proxy you would like to use."
+	 top_pad="4"
+	 width="200"
+	 commit_callback.function="Proxy.Change" />
+	<spinner
+	 control_name="Socks5ProxyPort"
+	 enabled_control="Socks5ProxyEnabled"
+	 decimal_digits="0"
+	 follows="left|top"
+	 height="23"
+	 increment="1"
+	 initial_value="80"
+	 label="Port number:"
+	 label_width="95"
+	 layout="topleft"
+	 left_delta="210"
+	 max_val="12000"
+	 min_val="10"
+	 name="socks_proxy_port"
+	 top_delta="0"
+	 width="145"
+     tool_tip="The port of the SOCKS 5 proxy you would like to use."
+	 commit_callback.function="Pref.SocksProxy" />
+	<text
+     type="string"
+     length="1"
+     follows="left|top"
+     height="10"
+     layout="topleft"
+     left="16"
+     name="Proxy location"
+     top_delta="35"
+     width="300">
+	    Authentication:
+	</text>
+	<radio_group
+	 control_name="Socks5AuthType"
+	 enabled_control="Socks5ProxyEnabled"
+	 height="50"
+	 layout="topleft"
+	 name="socks5_auth_type"
+	 top_pad="10"
+	 width="120"
+	 border="1"
+	 commit_callback.function="Proxy.Change" >
+	    <radio_item
+		 height="16"
+		 label="No Authentication"
+		 layout="topleft"
+		 name="Socks5NoAuth"
+		 value="None"
+		 tool_tip="Socks5 proxy requires no authentication."/>
+		 width="120" />
+		<radio_item
+		 height="16"
+		 label="Username/Password"
+		 layout="topleft"
+		 name="Socks5UserPass"
+		 value="UserPass"
+		 tool_tip="Socks5 proxy requires username/password authentication."/>
+		 width="120" />
+	</radio_group>
+	<text
+	 type="string"
+	 length="1"
+	 follows="left|top"
+	 height="10"
+	 layout="topleft"
+	 left_delta="20"
+	 top_delta="50"
+	 width="300">
+	    Username:
+	</text>
+	<line_editor
+	 control_name="Socks5Username"
+	 follows="left|top"
+	 font="SansSerif"
+	 height="23"
+	 layout="topleft"
+	 left_delta="0"
+	 name="socks5_username"
+	 tool_tip="The username used to authenticate with your SOCKS 5 server"
+	 top_pad="4"
+	 width="200"
+	 commit_callback.function="Proxy.Change" />
+	<text
+	 type="string"
+	 length="1"
+	 follows="left|top"
+	 height="10"
+	 layout="topleft"
+	 left_delta="0"
+	 top_delta="30"
+	 width="300">
+	    Password:
+	</text>
+	<line_editor
+	 control_name="Socks5Password"
+	 follows="left|top"
+	 font="SansSerif"
+	 height="23"
+	 layout="topleft"
+	 left_delta="0"
+	 name="socks5_password"
+	 tool_tip="The password used to authenticate with your SOCKS 5 server"
+	 top_pad="4"
+	 width="200"
+	 commit_callback.function="Proxy.Change" />
+	<button
+	 follows="left|top"
+	 height="22"
+	 label="OK"
+	 label_selected="OK"
+	 layout="topleft"
+	 right="275"
+	 name="OK"
+	 top_delta="53"
+	 width="90"
+	 commit_callback.function="Proxy.OK" />
+	<button
+	 follows="left|top"
+	 height="22"
+	 label="Cancel"
+	 label_selected="Cancel"
+	 layout="topleft"
+	 right="375"
+	 name="Cancel"
+	 top_delta="0"
+	 width="90"
+	 commit_callback.function="Proxy.Cancel" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index ce96c488b482063cba823331dcc2895d657f97a2..815e8f96ab4a70578b0f265594fb0c4af300737a 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -7158,6 +7158,76 @@ Click and drag anywhere on the world to rotate your view
     </form>
   </notification>
 
+  <notification
+   icon="alertmodal.tga"
+   name="SOCKS_NOT_PERMITTED"
+   type="alertmodal">
+	The Socks5 proxy "[HOST]:[PORT]" refused the connection, not allowed by rule set
+   <usetemplate
+     name="okbutton"
+     yestext="OK"/>
+  </notification>
+
+  <notification
+   icon="alertmodal.tga"
+   name="SOCKS_CONNECT_ERROR"
+   type="alertmodal">
+	The Socks5 proxy "[HOST]:[PORT]" refused the connection, could not open TCP channel
+   <usetemplate
+     name="okbutton"
+     yestext="OK"/>	 
+  </notification>
+
+  <notification
+   icon="alertmodal.tga"
+   name="SOCKS_NOT_ACCEPTABLE"
+   type="alertmodal">
+	The Socks5 proxy "[HOST]:[PORT]" refused the selected authentication system
+   <usetemplate
+     name="okbutton"
+     yestext="OK"/>
+  </notification>
+
+  <notification
+   icon="alertmodal.tga"
+   name="SOCKS_AUTH_FAIL"
+   type="alertmodal">
+	The Socks5 proxy "[HOST]:[PORT]" reported your credentials are invalid
+   <usetemplate
+     name="okbutton"
+     yestext="OK"/>
+  </notification>
+
+  <notification
+   icon="alertmodal.tga"
+   name="SOCKS_UDP_FWD_NOT_GRANTED"
+   type="alertmodal">
+	The Socks5 proxy "[HOST]:[PORT]" refused the UDP associate request
+   <usetemplate
+     name="okbutton"
+     yestext="OK"/>
+  </notification>
+
+  <notification
+   icon="alertmodal.tga"
+   name="SOCKS_HOST_CONNECT_FAILED"
+   type="alertmodal">
+	Could not connect to Socks5 proxy server "[HOST]:[PORT]"
+   <usetemplate
+     name="okbutton"
+     yestext="OK"/>
+  </notification>
+
+  <notification
+   icon="alertmodal.tga"
+   name="ChangeSocks5Settings"
+   type="alert">
+	Socks 5 proxy settings take effect after you restart [APP_NAME].
+   <usetemplate
+     name="okbutton"
+     yestext="OK"/>
+  </notification>
+
   <notification
   name="AuthRequest"
   type="browser">
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
index 1c22a5c02e984138a04ad7cd0b3013c789404fed..d306e46d5e0b4557e0b66eedb64cfe91518b2e2f 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
@@ -70,7 +70,7 @@
    layout="topleft"
    left="77"
    name="connection_port_enabled"
-   top_pad="20"
+   top_pad="10"
    width="256">
     <check_box.commit_callback
      function="Notification.Show"
@@ -195,60 +195,6 @@
     name="media_popup_enabled"
     width="400"           
     top_pad="5"/>
-  <check_box
-    top_delta="4"
-    enabled="true"
-    follows="left|top"
-    height="14"
-    initial_value="false"
-    control_name="BrowserProxyEnabled"
-    label="Enable Web Proxy"
-    left_delta="0"
-    mouse_opaque="true"
-    name="web_proxy_enabled"
-    radio_style="false"
-    width="400"           top_pad="5"/>
-  <text
-   type="string"
-   length="1"
-   follows="left|top"
-   height="10"
-   layout="topleft"
-   left_delta="20"
-   name="Proxy location"
-   top_delta="16"
-   width="300">
-    Proxy location:
-  </text>
-  <line_editor
-   control_name="BrowserProxyAddress"
-   enabled_control="BrowserProxyEnabled"
- follows="left|top"
-   font="SansSerif"
-   height="23"
-   layout="topleft"
-   left_delta="0"
-   name="web_proxy_editor"
-   tool_tip="The name or IP address of the proxy you would like to use"
-   top_pad="4"
-   width="200" />
-  <spinner
-   control_name="BrowserProxyPort"
-   enabled_control="BrowserProxyEnabled"
- decimal_digits="0"
-   follows="left|top"
-   height="23"
-   increment="1"
-   initial_value="80"
-   label="Port number:"
-   label_width="95"
-   layout="topleft"
-   left_delta="210"
-   max_val="12000"
-   min_val="10"
-   name="web_proxy_port"
-   top_delta="0"
-   width="145" />
   <text
      type="string"
      length="1"
@@ -286,4 +232,31 @@
          name="Install_manual"
          value="0" />
   </combo_box>
+  <text
+     type="string"
+     length="1"
+     follows="left|top"
+     height="10"
+     layout="topleft"
+     left="30"
+     name="Software updates:"
+     mouse_opaque="false"
+     top_pad="5"
+     width="300">
+		Proxy Settings:
+  </text>
+  <button
+	label="Adjust proxy settings"
+    follows="left|top"
+    height="23"
+	width="140" 
+    label_selected="Browse"
+    layout="topleft"
+    left_delta="50"
+    name="set_proxy"
+    top_pad="5"
+    >
+		<button.commit_callback
+		  function="Pref.Proxy" />
+  </button>
 </panel>