124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//===-- RNBSocket.cpp -------------------------------------------*- C++ -*-===// 224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// 324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// The LLVM Compiler Infrastructure 424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// 524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// This file is distributed under the University of Illinois Open Source 624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// License. See LICENSE.TXT for details. 724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// 824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//===----------------------------------------------------------------------===// 924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// 1024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Created by Greg Clayton on 12/12/07. 1124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// 1224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//===----------------------------------------------------------------------===// 1324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 1424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "RNBSocket.h" 15ff39f746ebaa3710c44ba49bd9b0a6cf05f60a3fGreg Clayton#include <arpa/inet.h> 1624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <errno.h> 1724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <fcntl.h> 18ff39f746ebaa3710c44ba49bd9b0a6cf05f60a3fGreg Clayton#include <netdb.h> 1924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <netinet/in.h> 2024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <netinet/tcp.h> 2124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <termios.h> 2224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "DNBLog.h" 2324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "DNBError.h" 2424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 259a5bbd2a14cacac731424f7a253f6cc16b22c10aJason Molenda#ifdef WITH_LOCKDOWN 2624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lockdown.h" 2724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#endif 2824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 2924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner/* Once we have a RNBSocket object with a port # specified, 3024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner this function is called to wait for an incoming connection. 3124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner This function blocks while waiting for that connection. */ 3224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 33a619e8ec81ff9c838285105c034ee70a290be904Greg Claytonbool 34a619e8ec81ff9c838285105c034ee70a290be904Greg ClaytonResolveIPV4HostName (const char *hostname, in_addr_t &addr) 35a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton{ 36a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton if (hostname == NULL || 37a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton hostname[0] == '\0' || 38a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton strcmp(hostname, "localhost") == 0 || 39a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton strcmp(hostname, "127.0.0.1") == 0) 40a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton { 41a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton addr = htonl (INADDR_LOOPBACK); 42a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton return true; 43a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton } 44a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton else if (strcmp(hostname, "*") == 0) 45a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton { 46a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton addr = htonl (INADDR_ANY); 47a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton return true; 48a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton } 49a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton else 50a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton { 51a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton // See if an IP address was specified as numbers 52a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton int inet_pton_result = ::inet_pton (AF_INET, hostname, &addr); 53a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton 54a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton if (inet_pton_result == 1) 55a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton return true; 56a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton 57a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton struct hostent *host_entry = gethostbyname (hostname); 58a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton if (host_entry) 59a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton { 60a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton std::string ip_str (::inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list)); 61a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton inet_pton_result = ::inet_pton (AF_INET, ip_str.c_str(), &addr); 62a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton if (inet_pton_result == 1) 63a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton return true; 64a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton } 65a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton } 66a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton return false; 67a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton} 68a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton 6924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerrnb_err_t 70a619e8ec81ff9c838285105c034ee70a290be904Greg ClaytonRNBSocket::Listen (const char *listen_host, in_port_t port, PortBoundCallback callback, const void *callback_baton) 7124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 7224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner //DNBLogThreadedIf(LOG_RNB_COMM, "%8u RNBSocket::%s called", (uint32_t)m_timer.ElapsedMicroSeconds(true), __FUNCTION__); 7324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Disconnect without saving errno 7424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner Disconnect (false); 7524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 76a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton // Now figure out the hostname that will be attaching and palce it into 77a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton struct sockaddr_in listen_addr; 78a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton ::memset (&listen_addr, 0, sizeof listen_addr); 79a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton listen_addr.sin_len = sizeof listen_addr; 80a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton listen_addr.sin_family = AF_INET; 81a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton listen_addr.sin_port = htons (port); 82a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton listen_addr.sin_addr.s_addr = INADDR_ANY; 83a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton 84a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton if (!ResolveIPV4HostName(listen_host, listen_addr.sin_addr.s_addr)) 85a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton { 86a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton DNBLogThreaded("error: failed to resolve connecting host '%s'", listen_host); 87a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton return rnb_err; 88a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton } 89a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton 9024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner DNBError err; 91b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton int listen_fd = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); 92b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton if (listen_fd == -1) 9324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner err.SetError(errno, DNBError::POSIX); 9424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 9524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) 96b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton err.LogThreaded("::socket ( domain = AF_INET, type = SOCK_STREAM, protocol = IPPROTO_TCP ) => socket = %i", listen_fd); 9724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 9824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (err.Fail()) 9924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return rnb_err; 10024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 10124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // enable local address reuse 102b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton SetSocketOption (listen_fd, SOL_SOCKET, SO_REUSEADDR, 1); 10324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 10424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner struct sockaddr_in sa; 10524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ::memset (&sa, 0, sizeof sa); 10624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner sa.sin_len = sizeof sa; 10724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner sa.sin_family = AF_INET; 108b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton sa.sin_port = htons (port); 109a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton sa.sin_addr.s_addr = INADDR_ANY; // Let incoming connections bind to any host network interface (this is NOT who can connect to us) 110b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton int error = ::bind (listen_fd, (struct sockaddr *) &sa, sizeof(sa)); 11124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (error == -1) 11224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner err.SetError(errno, DNBError::POSIX); 11324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 11424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) 115b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton err.LogThreaded("::bind ( socket = %i, (struct sockaddr *) &sa, sizeof(sa)) )", listen_fd); 11624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 11724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (err.Fail()) 11824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 119b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton ClosePort (listen_fd, false); 12024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return rnb_err; 12124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 12224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 123b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton if (callback && port == 0) 124b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton { 125b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton // We were asked to listen on port zero which means we 126b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton // must now read the actual port that was given to us 127b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton // as port zero is a special code for "find an open port 128b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton // for me". 129b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton socklen_t sa_len = sizeof (sa); 130b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton if (getsockname(listen_fd, (struct sockaddr *)&sa, &sa_len) == 0) 131b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton { 132b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton port = ntohs (sa.sin_port); 133b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton callback (callback_baton, port); 134b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton } 135b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton } 136b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton 137a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton error = ::listen (listen_fd, 5); 13824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (error == -1) 13924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner err.SetError(errno, DNBError::POSIX); 14024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 14124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) 142b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton err.LogThreaded("::listen ( socket = %i, backlog = 1 )", listen_fd); 14324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 14424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (err.Fail()) 14524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 146b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton ClosePort (listen_fd, false); 14724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return rnb_err; 14824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 14924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 150a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton struct sockaddr_in accept_addr; 151a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton ::memset (&accept_addr, 0, sizeof accept_addr); 152a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton accept_addr.sin_len = sizeof accept_addr; 15324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 154a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton bool accept_connection = false; 155a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton 156a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton // Loop until we are happy with our connection 157a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton while (!accept_connection) 158a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton { 159a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton socklen_t accept_addr_len = sizeof accept_addr; 160a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton m_fd = ::accept (listen_fd, (struct sockaddr *)&accept_addr, &accept_addr_len); 161a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton 162a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton if (m_fd == -1) 163a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton err.SetError(errno, DNBError::POSIX); 164a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton 165a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) 166a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton err.LogThreaded("::accept ( socket = %i, address = %p, address_len = %u )", listen_fd, &accept_addr, accept_addr_len); 167a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton 168a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton if (err.Fail()) 169a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton break; 170a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton 171a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton if (listen_addr.sin_addr.s_addr == INADDR_ANY) 172a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton accept_connection = true; 173a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton else 174a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton { 175a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton if (accept_addr_len == listen_addr.sin_len && 176a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton accept_addr.sin_addr.s_addr == listen_addr.sin_addr.s_addr) 177a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton { 178a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton accept_connection = true; 179a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton } 180a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton else 181a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton { 182a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton ::close (m_fd); 183a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton m_fd = -1; 184a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton const uint8_t *accept_ip = (const uint8_t *)&accept_addr.sin_addr.s_addr; 185a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton const uint8_t *listen_ip = (const uint8_t *)&listen_addr.sin_addr.s_addr; 186a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton ::fprintf (stderr, 187a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton "error: rejecting incoming connection from %u.%u.%u.%u (expecting %u.%u.%u.%u)\n", 188a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3], 189a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]); 190a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton DNBLogThreaded ("error: rejecting connection from %u.%u.%u.%u (expecting %u.%u.%u.%u)", 191a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3], 192a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]); 193a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton } 194a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton } 195a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton } 196b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton 197b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton ClosePort (listen_fd, false); 19824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 19924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (err.Fail()) 20024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 20124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return rnb_err; 20224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 20324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else 20424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 20524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Keep our TCP packets coming without any delays. 206b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1); 20724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 20824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 20924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return rnb_success; 21024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 21124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 212ff39f746ebaa3710c44ba49bd9b0a6cf05f60a3fGreg Claytonrnb_err_t 213ff39f746ebaa3710c44ba49bd9b0a6cf05f60a3fGreg ClaytonRNBSocket::Connect (const char *host, uint16_t port) 214ff39f746ebaa3710c44ba49bd9b0a6cf05f60a3fGreg Clayton{ 215ff39f746ebaa3710c44ba49bd9b0a6cf05f60a3fGreg Clayton Disconnect (false); 216ff39f746ebaa3710c44ba49bd9b0a6cf05f60a3fGreg Clayton 217ff39f746ebaa3710c44ba49bd9b0a6cf05f60a3fGreg Clayton // Create the socket 218b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton m_fd = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); 219b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton if (m_fd == -1) 220ff39f746ebaa3710c44ba49bd9b0a6cf05f60a3fGreg Clayton return rnb_err; 221ff39f746ebaa3710c44ba49bd9b0a6cf05f60a3fGreg Clayton 222ff39f746ebaa3710c44ba49bd9b0a6cf05f60a3fGreg Clayton // Enable local address reuse 223b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton SetSocketOption (m_fd, SOL_SOCKET, SO_REUSEADDR, 1); 224ff39f746ebaa3710c44ba49bd9b0a6cf05f60a3fGreg Clayton 225ff39f746ebaa3710c44ba49bd9b0a6cf05f60a3fGreg Clayton struct sockaddr_in sa; 226ff39f746ebaa3710c44ba49bd9b0a6cf05f60a3fGreg Clayton ::memset (&sa, 0, sizeof (sa)); 227ff39f746ebaa3710c44ba49bd9b0a6cf05f60a3fGreg Clayton sa.sin_family = AF_INET; 228ff39f746ebaa3710c44ba49bd9b0a6cf05f60a3fGreg Clayton sa.sin_port = htons (port); 229ff39f746ebaa3710c44ba49bd9b0a6cf05f60a3fGreg Clayton 230a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton if (!ResolveIPV4HostName(host, sa.sin_addr.s_addr)) 231ff39f746ebaa3710c44ba49bd9b0a6cf05f60a3fGreg Clayton { 232a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton DNBLogThreaded("error: failed to resolve host '%s'", host); 233a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton Disconnect (false); 234a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton return rnb_err; 235ff39f746ebaa3710c44ba49bd9b0a6cf05f60a3fGreg Clayton } 236ff39f746ebaa3710c44ba49bd9b0a6cf05f60a3fGreg Clayton 237b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton if (-1 == ::connect (m_fd, (const struct sockaddr *)&sa, sizeof(sa))) 238ff39f746ebaa3710c44ba49bd9b0a6cf05f60a3fGreg Clayton { 239ff39f746ebaa3710c44ba49bd9b0a6cf05f60a3fGreg Clayton Disconnect (false); 240ff39f746ebaa3710c44ba49bd9b0a6cf05f60a3fGreg Clayton return rnb_err; 241ff39f746ebaa3710c44ba49bd9b0a6cf05f60a3fGreg Clayton } 242ff39f746ebaa3710c44ba49bd9b0a6cf05f60a3fGreg Clayton 243ff39f746ebaa3710c44ba49bd9b0a6cf05f60a3fGreg Clayton // Keep our TCP packets coming without any delays. 244b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1); 245ff39f746ebaa3710c44ba49bd9b0a6cf05f60a3fGreg Clayton return rnb_success; 246ff39f746ebaa3710c44ba49bd9b0a6cf05f60a3fGreg Clayton} 247ff39f746ebaa3710c44ba49bd9b0a6cf05f60a3fGreg Clayton 2489a5bbd2a14cacac731424f7a253f6cc16b22c10aJason Molendarnb_err_t 2499a5bbd2a14cacac731424f7a253f6cc16b22c10aJason MolendaRNBSocket::useFD(int fd) 2509a5bbd2a14cacac731424f7a253f6cc16b22c10aJason Molenda{ 2519a5bbd2a14cacac731424f7a253f6cc16b22c10aJason Molenda if (fd < 0) { 2529a5bbd2a14cacac731424f7a253f6cc16b22c10aJason Molenda DNBLogThreadedIf(LOG_RNB_COMM, "Bad file descriptor passed in."); 2539a5bbd2a14cacac731424f7a253f6cc16b22c10aJason Molenda return rnb_err; 2549a5bbd2a14cacac731424f7a253f6cc16b22c10aJason Molenda } 2559a5bbd2a14cacac731424f7a253f6cc16b22c10aJason Molenda 2569a5bbd2a14cacac731424f7a253f6cc16b22c10aJason Molenda m_fd = fd; 2579a5bbd2a14cacac731424f7a253f6cc16b22c10aJason Molenda return rnb_success; 2589a5bbd2a14cacac731424f7a253f6cc16b22c10aJason Molenda} 2599a5bbd2a14cacac731424f7a253f6cc16b22c10aJason Molenda 2609a5bbd2a14cacac731424f7a253f6cc16b22c10aJason Molenda#ifdef WITH_LOCKDOWN 26124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerrnb_err_t 26224943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerRNBSocket::ConnectToService() 26324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 26424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner DNBLog("Connecting to com.apple.%s service...", DEBUGSERVER_PROGRAM_NAME); 26524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Disconnect from any previous connections 26624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner Disconnect(false); 2677d96ecc2fe57d7d7289bed7fc633154a310979c7Jason Molenda if (::secure_lockdown_checkin (&m_ld_conn, NULL, NULL) != kLDESuccess) 26824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 2697d96ecc2fe57d7d7289bed7fc633154a310979c7Jason Molenda DNBLogThreadedIf(LOG_RNB_COMM, "::secure_lockdown_checkin(&m_fd, NULL, NULL) failed"); 27070eddebd1c5868a87a3ba9ddf717fc964a257f66Jason Molenda m_fd = -1; 27124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return rnb_not_connected; 27224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 2737d96ecc2fe57d7d7289bed7fc633154a310979c7Jason Molenda m_fd = ::lockdown_get_socket (m_ld_conn); 2747d96ecc2fe57d7d7289bed7fc633154a310979c7Jason Molenda if (m_fd == -1) 2757d96ecc2fe57d7d7289bed7fc633154a310979c7Jason Molenda { 2767d96ecc2fe57d7d7289bed7fc633154a310979c7Jason Molenda DNBLogThreadedIf(LOG_RNB_COMM, "::lockdown_get_socket() failed"); 2777d96ecc2fe57d7d7289bed7fc633154a310979c7Jason Molenda return rnb_not_connected; 2787d96ecc2fe57d7d7289bed7fc633154a310979c7Jason Molenda } 279b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton m_fd_from_lockdown = true; 28024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return rnb_success; 28124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 28224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#endif 28324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 28424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerrnb_err_t 28524943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerRNBSocket::OpenFile (const char *path) 28624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 28724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner DNBError err; 288b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton m_fd = open (path, O_RDWR); 289b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton if (m_fd == -1) 29024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 29124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner err.SetError(errno, DNBError::POSIX); 29224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner err.LogThreaded ("can't open file '%s'", path); 29324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return rnb_not_connected; 29424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 29524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else 29624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 29724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner struct termios stdin_termios; 29824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 299b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton if (::tcgetattr (m_fd, &stdin_termios) == 0) 30024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 30124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner stdin_termios.c_lflag &= ~ECHO; // Turn off echoing 30224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner stdin_termios.c_lflag &= ~ICANON; // Get one char at a time 303b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton ::tcsetattr (m_fd, TCSANOW, &stdin_termios); 30424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 30524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 30624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return rnb_success; 30724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 30824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 30924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerint 31024943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerRNBSocket::SetSocketOption(int fd, int level, int option_name, int option_value) 31124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 31224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return ::setsockopt(fd, level, option_name, &option_value, sizeof(option_value)); 31324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 31424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 31524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerrnb_err_t 31624943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerRNBSocket::Disconnect (bool save_errno) 31724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 3189a5bbd2a14cacac731424f7a253f6cc16b22c10aJason Molenda#ifdef WITH_LOCKDOWN 319b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton if (m_fd_from_lockdown) 3207d96ecc2fe57d7d7289bed7fc633154a310979c7Jason Molenda { 321b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton m_fd_from_lockdown = false; 3227d96ecc2fe57d7d7289bed7fc633154a310979c7Jason Molenda m_fd = -1; 3233138ad6178b98337ea875e30e7c808e35eae734dJim Ingham lockdown_disconnect (m_ld_conn); 3243138ad6178b98337ea875e30e7c808e35eae734dJim Ingham return rnb_success; 3257d96ecc2fe57d7d7289bed7fc633154a310979c7Jason Molenda } 3269a5bbd2a14cacac731424f7a253f6cc16b22c10aJason Molenda#endif 327b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton return ClosePort (m_fd, save_errno); 32824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 32924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 33024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 33124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerrnb_err_t 33224943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerRNBSocket::Read (std::string &p) 33324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 33424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner char buf[1024]; 33524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner p.clear(); 33624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 33724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Note that BUF is on the stack so we must be careful to keep any 33824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // writes to BUF from overflowing or we'll have security issues. 33924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 340b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton if (m_fd == -1) 34124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return rnb_err; 34224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 34324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner //DNBLogThreadedIf(LOG_RNB_COMM, "%8u RNBSocket::%s calling read()", (uint32_t)m_timer.ElapsedMicroSeconds(true), __FUNCTION__); 34424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner DNBError err; 345b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton int bytesread = read (m_fd, buf, sizeof (buf)); 34624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (bytesread <= 0) 34724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner err.SetError(errno, DNBError::POSIX); 34824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else 34924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner p.append(buf, bytesread); 35024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 35124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) 352851e30ec6a1b1d2c154bb7d69ed0d05b5fd14705Greg Clayton err.LogThreaded("::read ( %i, %p, %llu ) => %i", m_fd, buf, sizeof (buf), (uint64_t)bytesread); 35324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 35424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Our port went away - we have to mark this so IsConnected will return the truth. 35524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (bytesread == 0) 35624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 357b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton m_fd = -1; 35824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return rnb_not_connected; 35924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 36024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else if (bytesread == -1) 36124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 362b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton m_fd = -1; 36324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return rnb_err; 36424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 36524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Strip spaces from the end of the buffer 36624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner while (!p.empty() && isspace (p[p.size() - 1])) 36724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner p.erase (p.size () - 1); 36824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 36924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Most data in the debugserver packets valid printable characters... 37024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner DNBLogThreadedIf(LOG_RNB_COMM, "read: %s", p.c_str()); 37124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return rnb_success; 37224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 37324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 37424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerrnb_err_t 37524943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerRNBSocket::Write (const void *buffer, size_t length) 37624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 377b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton if (m_fd == -1) 37824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return rnb_err; 37924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 38024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner DNBError err; 3819a5bbd2a14cacac731424f7a253f6cc16b22c10aJason Molenda int bytessent = write (m_fd, buffer, length); 38224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (bytessent < 0) 38324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner err.SetError(errno, DNBError::POSIX); 38424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 38524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) 386851e30ec6a1b1d2c154bb7d69ed0d05b5fd14705Greg Clayton err.LogThreaded("::write ( socket = %i, buffer = %p, length = %llu) => %i", m_fd, buffer, length, (uint64_t)bytessent); 38724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 38824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (bytessent < 0) 38924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return rnb_err; 39024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 39124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (bytessent != length) 39224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return rnb_err; 39324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 3940e8147bd867e4cdaae9400f56d02c7aacd40a9b3Greg Clayton DNBLogThreadedIf(LOG_RNB_PACKETS, "putpkt: %*s", (int)length, (char *)buffer); // All data is string based in debugserver, so this is safe 3950e8147bd867e4cdaae9400f56d02c7aacd40a9b3Greg Clayton DNBLogThreadedIf(LOG_RNB_COMM, "sent: %*s", (int)length, (char *)buffer); 39624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 39724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return rnb_success; 39824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 39924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 40024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 40124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerrnb_err_t 40224943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerRNBSocket::ClosePort (int& fd, bool save_errno) 40324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 40424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner int close_err = 0; 40524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (fd > 0) 40624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 40724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner errno = 0; 40824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner close_err = close (fd); 40924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner fd = -1; 41024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 41124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return close_err != 0 ? rnb_err : rnb_success; 41224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 41324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 41424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 415