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())); }
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()); }
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; }
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()); }
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; }
/** * @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; }