Example #1
0
BOOL LLPacketRing::sendPacketImpl(int h_socket, const char * send_buffer, S32 buf_size, LLHost host)
{
	
	if (!LLProxy::isSOCKSProxyEnabled())
	{
		return send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort());
	}

	char headered_send_buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE];

	proxywrap_t *socks_header = static_cast<proxywrap_t*>(static_cast<void*>(&headered_send_buffer));
	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(headered_send_buffer + SOCKS_HEADER_SIZE, send_buffer, buf_size);

	return send_packet(	h_socket,
						headered_send_buffer,
						buf_size + SOCKS_HEADER_SIZE,
						LLProxy::getInstance()->getUDPProxy().getAddress(),
						LLProxy::getInstance()->getUDPProxy().getPort());
}
	void host_object::test<7>()
	{
		const char* str = "192.168.1.1";
		U32 port = 8080, ip;
		LLHost host;
		host.set(str,port);
		ip = ip_string_to_u32(str);
		ensure("IP address is invalid", (ip == host.getAddress()));
		ensure("Port Number is invalid", (port == host.getPort()));
		
		str = "64.233.187.99";
		ip = ip_string_to_u32(str);
		host.setAddress(str);
		ensure("IP address is invalid", (ip == host.getAddress()));

		ip = 0xc098017b;
		host.setAddress(ip);
		ensure("IP address is invalid", (ip == host.getAddress()));
		// should still use the old port
		ensure("Port Number is invalid", (port == host.getPort()));

		port = 8084;
		host.setPort(port);
		ensure("Port Number is invalid", (port == host.getPort()));
		// should still use the old address
		ensure("IP address is invalid", (ip == host.getAddress()));
	}
	void host_object::test<10>()
	{
		std::string hostStr = "64.233.167.99";		
		LLHost host;
		host.setHostByName(hostStr);	
		ensure("SetHostByName for dotted IP Address failed", host.getAddress() == ip_string_to_u32(hostStr.c_str()));
	}
	void host_object::test<6>()
	{
		U32 ip = 0xc098017d, port = 8080;
		LLHost host;
		host.set(ip,port);
		ensure("IP address is invalid", (ip == host.getAddress()));
		ensure("Port Number is invalid", (port == host.getPort()));
	}
Example #5
0
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()->getUDPPproxy().getAddress(), LLSocks::getInstance()->getUDPPproxy().getPort());
}
Example #6
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;
}
Example #7
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 host_object::test<1>()
	{
		LLHost host;
		ensure("IP address is not NULL", (0 == host.getAddress()) && (0 == host.getPort()) && !host.isOk());
	}
Example #9
0
BOOL LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LLHost host)
{
	BOOL status = TRUE;
	if (!mUseOutThrottle)
	{
		return send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort() );
	}
	else
	{
		mActualBitsOut += buf_size * 8;
		LLPacketBuffer *packetp = NULL;
		// See if we've got enough throttle to send a packet.
		while (!mOutThrottle.checkOverflow(0.f))
		{
			// While we have enough bandwidth, send a packet from the queue or the current packet

			S32 packet_size = 0;
			if (!mSendQueue.empty())
			{
				// Send a packet off of the queue
				LLPacketBuffer *packetp = mSendQueue.front();
				mSendQueue.pop();

				mOutBufferLength -= packetp->getSize();
				packet_size = packetp->getSize();

				status = send_packet(h_socket, packetp->getData(), packet_size, packetp->getHost().getAddress(), packetp->getHost().getPort());
				
				delete packetp;
				// Update the throttle
				mOutThrottle.throttleOverflow(packet_size * 8.f);
			}
			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() );
				packet_size = buf_size;

				// Update the throttle
				mOutThrottle.throttleOverflow(packet_size * 8.f);

				// This was the packet we're sending now, there are no other packets
				// that we need to send
				return status;
			}

		}

		// We haven't sent the incoming packet, add it to the queue
		if (mOutBufferLength + buf_size > mMaxBufferLength)
		{
			// Nuke this packet, we overflowed the buffer.
			// Toss it.
			llwarns << "Throwing away outbound packet, overflowing buffer" << llendl;
		}
		else
		{
			static LLTimer queue_timer;
			if ((mOutBufferLength > 4192) && queue_timer.getElapsedTimeF32() > 1.f)
			{
				// Add it to the queue
				llinfos << "Outbound packet queue " << mOutBufferLength << " bytes" << llendl;
				queue_timer.reset();
			}
			packetp = new LLPacketBuffer(host, send_buffer, buf_size);

			mOutBufferLength += packetp->getSize();
			mSendQueue.push(packetp);
		}
	}

	return status;
}
Example #10
0
/**
 * @brief Open the SOCKS 5 TCP control channel.
 *
 * Perform a SOCKS 5 authentication and UDP association with the proxy server.
 *
 * @param proxy The SOCKS 5 server to connect to.
 * @return SOCKS_OK if successful, otherwise a socks error code from llproxy.h.
 */
S32 LLProxy::proxyHandshake(LLHost proxy)
{
	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		= getSelectedAuthMethod();		// Send only the selected method.

	result = tcp_blocking_handshake(mProxyControlChannel,
									static_cast<char*>(static_cast<void*>(&socks_auth_request)),
									sizeof(socks_auth_request),
									static_cast<char*>(static_cast<void*>(&socks_auth_response)),
									sizeof(socks_auth_response));
	if (result != APR_SUCCESS)
	{
		LL_WARNS("Proxy") << "SOCKS authentication request failed, error on TCP control channel : " << result << LL_ENDL;
		stopSOCKSProxy();
		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;
		stopSOCKSProxy();
		return SOCKS_NOT_ACCEPTABLE;
	}

	/* SOCKS 5 USERNAME/PASSWORD authentication */
	if (socks_auth_response.method == METHOD_PASSWORD)
	{
		// The server has requested a username/password combination
		std::string socks_username(getSocksUser());
		std::string socks_password(getSocksPwd());
		U32 request_size = socks_username.size() + socks_password.size() + 3;
		char * password_auth = new char[request_size];
		password_auth[0] = 0x01;
		password_auth[1] = (char) socks_username.size();
		memcpy(&password_auth[2], socks_username.c_str(), socks_username.size());
		password_auth[socks_username.size() + 2] = (char) socks_password.size();
		memcpy(&password_auth[socks_username.size() + 3], socks_password.c_str(), socks_password.size());

		authmethod_password_reply_t password_reply;

		result = tcp_blocking_handshake(mProxyControlChannel,
										password_auth,
										request_size,
										static_cast<char*>(static_cast<void*>(&password_reply)),
										sizeof(password_reply));
		delete[] password_auth;

		if (result != APR_SUCCESS)
		{
			LL_WARNS("Proxy") << "SOCKS authentication failed, error on TCP control channel : " << result << LL_ENDL;
			stopSOCKSProxy();
			return SOCKS_CONNECT_ERROR;
		}

		if (password_reply.status != AUTH_SUCCESS)
		{
			LL_WARNS("Proxy") << "SOCKS authentication failed" << LL_ENDL;
			stopSOCKSProxy();
			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_blocking_handshake(mProxyControlChannel,
									static_cast<char*>(static_cast<void*>(&connect_request)),
									sizeof(connect_request),
									static_cast<char*>(static_cast<void*>(&connect_reply)),
									sizeof(connect_reply));
	if (result != APR_SUCCESS)
	{
		LL_WARNS("Proxy") << "SOCKS connect request failed, error on TCP control channel : " << result << LL_ENDL;
		stopSOCKSProxy();
		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;
		stopSOCKSProxy();
		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;
}