1*30fdc8d8SChris Lattner //===-- RNBSocket.cpp -------------------------------------------*- C++ -*-===// 2*30fdc8d8SChris Lattner // 3*30fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 4*30fdc8d8SChris Lattner // 5*30fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 6*30fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 7*30fdc8d8SChris Lattner // 8*30fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 9*30fdc8d8SChris Lattner // 10*30fdc8d8SChris Lattner // Created by Greg Clayton on 12/12/07. 11*30fdc8d8SChris Lattner // 12*30fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 13*30fdc8d8SChris Lattner 14*30fdc8d8SChris Lattner #include "RNBSocket.h" 15*30fdc8d8SChris Lattner #include <errno.h> 16*30fdc8d8SChris Lattner #include <fcntl.h> 17*30fdc8d8SChris Lattner #include <netinet/in.h> 18*30fdc8d8SChris Lattner #include <netinet/tcp.h> 19*30fdc8d8SChris Lattner #include <termios.h> 20*30fdc8d8SChris Lattner #include "DNBLog.h" 21*30fdc8d8SChris Lattner #include "DNBError.h" 22*30fdc8d8SChris Lattner 23*30fdc8d8SChris Lattner #if defined (__arm__) 24*30fdc8d8SChris Lattner #include "lockdown.h" 25*30fdc8d8SChris Lattner #endif 26*30fdc8d8SChris Lattner 27*30fdc8d8SChris Lattner /* Once we have a RNBSocket object with a port # specified, 28*30fdc8d8SChris Lattner this function is called to wait for an incoming connection. 29*30fdc8d8SChris Lattner This function blocks while waiting for that connection. */ 30*30fdc8d8SChris Lattner 31*30fdc8d8SChris Lattner rnb_err_t 32*30fdc8d8SChris Lattner RNBSocket::Listen (in_port_t listen_port_num) 33*30fdc8d8SChris Lattner { 34*30fdc8d8SChris Lattner //DNBLogThreadedIf(LOG_RNB_COMM, "%8u RNBSocket::%s called", (uint32_t)m_timer.ElapsedMicroSeconds(true), __FUNCTION__); 35*30fdc8d8SChris Lattner // Disconnect without saving errno 36*30fdc8d8SChris Lattner Disconnect (false); 37*30fdc8d8SChris Lattner 38*30fdc8d8SChris Lattner DNBError err; 39*30fdc8d8SChris Lattner int listen_port = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); 40*30fdc8d8SChris Lattner if (listen_port == -1) 41*30fdc8d8SChris Lattner err.SetError(errno, DNBError::POSIX); 42*30fdc8d8SChris Lattner 43*30fdc8d8SChris Lattner if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) 44*30fdc8d8SChris Lattner err.LogThreaded("::socket ( domain = AF_INET, type = SOCK_STREAM, protocol = IPPROTO_TCP ) => socket = %i", listen_port); 45*30fdc8d8SChris Lattner 46*30fdc8d8SChris Lattner if (err.Fail()) 47*30fdc8d8SChris Lattner return rnb_err; 48*30fdc8d8SChris Lattner 49*30fdc8d8SChris Lattner // enable local address reuse 50*30fdc8d8SChris Lattner SetSocketOption (listen_port, SOL_SOCKET, SO_REUSEADDR, 1); 51*30fdc8d8SChris Lattner 52*30fdc8d8SChris Lattner struct sockaddr_in sa; 53*30fdc8d8SChris Lattner ::memset (&sa, 0, sizeof sa); 54*30fdc8d8SChris Lattner sa.sin_len = sizeof sa; 55*30fdc8d8SChris Lattner sa.sin_family = AF_INET; 56*30fdc8d8SChris Lattner sa.sin_port = htons (listen_port_num); 57*30fdc8d8SChris Lattner sa.sin_addr.s_addr = htonl (INADDR_ANY); 58*30fdc8d8SChris Lattner 59*30fdc8d8SChris Lattner int error = ::bind (listen_port, (struct sockaddr *) &sa, sizeof(sa)); 60*30fdc8d8SChris Lattner if (error == -1) 61*30fdc8d8SChris Lattner err.SetError(errno, DNBError::POSIX); 62*30fdc8d8SChris Lattner 63*30fdc8d8SChris Lattner if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) 64*30fdc8d8SChris Lattner err.LogThreaded("::bind ( socket = %i, (struct sockaddr *) &sa, sizeof(sa)) )", listen_port); 65*30fdc8d8SChris Lattner 66*30fdc8d8SChris Lattner if (err.Fail()) 67*30fdc8d8SChris Lattner { 68*30fdc8d8SChris Lattner ClosePort (listen_port, false); 69*30fdc8d8SChris Lattner return rnb_err; 70*30fdc8d8SChris Lattner } 71*30fdc8d8SChris Lattner 72*30fdc8d8SChris Lattner error = ::listen (listen_port, 1); 73*30fdc8d8SChris Lattner if (error == -1) 74*30fdc8d8SChris Lattner err.SetError(errno, DNBError::POSIX); 75*30fdc8d8SChris Lattner 76*30fdc8d8SChris Lattner if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) 77*30fdc8d8SChris Lattner err.LogThreaded("::listen ( socket = %i, backlog = 1 )", listen_port); 78*30fdc8d8SChris Lattner 79*30fdc8d8SChris Lattner if (err.Fail()) 80*30fdc8d8SChris Lattner { 81*30fdc8d8SChris Lattner ClosePort (listen_port, false); 82*30fdc8d8SChris Lattner return rnb_err; 83*30fdc8d8SChris Lattner } 84*30fdc8d8SChris Lattner 85*30fdc8d8SChris Lattner m_conn_port = ::accept (listen_port, NULL, 0); 86*30fdc8d8SChris Lattner if (m_conn_port == -1) 87*30fdc8d8SChris Lattner err.SetError(errno, DNBError::POSIX); 88*30fdc8d8SChris Lattner 89*30fdc8d8SChris Lattner if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) 90*30fdc8d8SChris Lattner err.LogThreaded("::accept ( socket = %i, address = NULL, address_len = 0 )", listen_port); 91*30fdc8d8SChris Lattner 92*30fdc8d8SChris Lattner if (err.Fail()) 93*30fdc8d8SChris Lattner { 94*30fdc8d8SChris Lattner ClosePort (listen_port, false); 95*30fdc8d8SChris Lattner return rnb_err; 96*30fdc8d8SChris Lattner } 97*30fdc8d8SChris Lattner else 98*30fdc8d8SChris Lattner { 99*30fdc8d8SChris Lattner // We are done with the listen port 100*30fdc8d8SChris Lattner ClosePort (listen_port, false); 101*30fdc8d8SChris Lattner 102*30fdc8d8SChris Lattner // Keep our TCP packets coming without any delays. 103*30fdc8d8SChris Lattner SetSocketOption (m_conn_port, IPPROTO_TCP, TCP_NODELAY, 1); 104*30fdc8d8SChris Lattner } 105*30fdc8d8SChris Lattner 106*30fdc8d8SChris Lattner return rnb_success; 107*30fdc8d8SChris Lattner } 108*30fdc8d8SChris Lattner 109*30fdc8d8SChris Lattner #if defined (__arm__) 110*30fdc8d8SChris Lattner rnb_err_t 111*30fdc8d8SChris Lattner RNBSocket::ConnectToService() 112*30fdc8d8SChris Lattner { 113*30fdc8d8SChris Lattner DNBLog("Connecting to com.apple.%s service...", DEBUGSERVER_PROGRAM_NAME); 114*30fdc8d8SChris Lattner // Disconnect from any previous connections 115*30fdc8d8SChris Lattner Disconnect(false); 116*30fdc8d8SChris Lattner 117*30fdc8d8SChris Lattner m_conn_port = ::lockdown_checkin (NULL, NULL); 118*30fdc8d8SChris Lattner if (m_conn_port == -1) 119*30fdc8d8SChris Lattner { 120*30fdc8d8SChris Lattner DNBLogThreadedIf(LOG_RNB_COMM, "::lockdown_checkin(NULL, NULL) failed"); 121*30fdc8d8SChris Lattner return rnb_not_connected; 122*30fdc8d8SChris Lattner } 123*30fdc8d8SChris Lattner m_conn_port_from_lockdown = true; 124*30fdc8d8SChris Lattner return rnb_success; 125*30fdc8d8SChris Lattner } 126*30fdc8d8SChris Lattner #endif 127*30fdc8d8SChris Lattner 128*30fdc8d8SChris Lattner rnb_err_t 129*30fdc8d8SChris Lattner RNBSocket::OpenFile (const char *path) 130*30fdc8d8SChris Lattner { 131*30fdc8d8SChris Lattner DNBError err; 132*30fdc8d8SChris Lattner m_conn_port = open (path, O_RDWR); 133*30fdc8d8SChris Lattner if (m_conn_port == -1) 134*30fdc8d8SChris Lattner { 135*30fdc8d8SChris Lattner err.SetError(errno, DNBError::POSIX); 136*30fdc8d8SChris Lattner err.LogThreaded ("can't open file '%s'", path); 137*30fdc8d8SChris Lattner return rnb_not_connected; 138*30fdc8d8SChris Lattner } 139*30fdc8d8SChris Lattner else 140*30fdc8d8SChris Lattner { 141*30fdc8d8SChris Lattner struct termios stdin_termios; 142*30fdc8d8SChris Lattner 143*30fdc8d8SChris Lattner if (::tcgetattr (m_conn_port, &stdin_termios) == 0) 144*30fdc8d8SChris Lattner { 145*30fdc8d8SChris Lattner stdin_termios.c_lflag &= ~ECHO; // Turn off echoing 146*30fdc8d8SChris Lattner stdin_termios.c_lflag &= ~ICANON; // Get one char at a time 147*30fdc8d8SChris Lattner ::tcsetattr (m_conn_port, TCSANOW, &stdin_termios); 148*30fdc8d8SChris Lattner } 149*30fdc8d8SChris Lattner } 150*30fdc8d8SChris Lattner return rnb_success; 151*30fdc8d8SChris Lattner } 152*30fdc8d8SChris Lattner 153*30fdc8d8SChris Lattner int 154*30fdc8d8SChris Lattner RNBSocket::SetSocketOption(int fd, int level, int option_name, int option_value) 155*30fdc8d8SChris Lattner { 156*30fdc8d8SChris Lattner return ::setsockopt(fd, level, option_name, &option_value, sizeof(option_value)); 157*30fdc8d8SChris Lattner } 158*30fdc8d8SChris Lattner 159*30fdc8d8SChris Lattner rnb_err_t 160*30fdc8d8SChris Lattner RNBSocket::Disconnect (bool save_errno) 161*30fdc8d8SChris Lattner { 162*30fdc8d8SChris Lattner if (m_conn_port_from_lockdown) 163*30fdc8d8SChris Lattner m_conn_port_from_lockdown = false; 164*30fdc8d8SChris Lattner return ClosePort (m_conn_port, save_errno); 165*30fdc8d8SChris Lattner } 166*30fdc8d8SChris Lattner 167*30fdc8d8SChris Lattner 168*30fdc8d8SChris Lattner rnb_err_t 169*30fdc8d8SChris Lattner RNBSocket::Read (std::string &p) 170*30fdc8d8SChris Lattner { 171*30fdc8d8SChris Lattner char buf[1024]; 172*30fdc8d8SChris Lattner p.clear(); 173*30fdc8d8SChris Lattner 174*30fdc8d8SChris Lattner // Note that BUF is on the stack so we must be careful to keep any 175*30fdc8d8SChris Lattner // writes to BUF from overflowing or we'll have security issues. 176*30fdc8d8SChris Lattner 177*30fdc8d8SChris Lattner if (m_conn_port == -1) 178*30fdc8d8SChris Lattner return rnb_err; 179*30fdc8d8SChris Lattner 180*30fdc8d8SChris Lattner //DNBLogThreadedIf(LOG_RNB_COMM, "%8u RNBSocket::%s calling read()", (uint32_t)m_timer.ElapsedMicroSeconds(true), __FUNCTION__); 181*30fdc8d8SChris Lattner DNBError err; 182*30fdc8d8SChris Lattner int bytesread = read (m_conn_port, buf, sizeof (buf)); 183*30fdc8d8SChris Lattner if (bytesread <= 0) 184*30fdc8d8SChris Lattner err.SetError(errno, DNBError::POSIX); 185*30fdc8d8SChris Lattner else 186*30fdc8d8SChris Lattner p.append(buf, bytesread); 187*30fdc8d8SChris Lattner 188*30fdc8d8SChris Lattner if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) 189*30fdc8d8SChris Lattner err.LogThreaded("::read ( %i, %p, %zu ) => %i", m_conn_port, buf, sizeof (buf), bytesread); 190*30fdc8d8SChris Lattner 191*30fdc8d8SChris Lattner // Our port went away - we have to mark this so IsConnected will return the truth. 192*30fdc8d8SChris Lattner if (bytesread == 0) 193*30fdc8d8SChris Lattner { 194*30fdc8d8SChris Lattner m_conn_port = -1; 195*30fdc8d8SChris Lattner return rnb_not_connected; 196*30fdc8d8SChris Lattner } 197*30fdc8d8SChris Lattner else if (bytesread == -1) 198*30fdc8d8SChris Lattner { 199*30fdc8d8SChris Lattner m_conn_port = -1; 200*30fdc8d8SChris Lattner return rnb_err; 201*30fdc8d8SChris Lattner } 202*30fdc8d8SChris Lattner // Strip spaces from the end of the buffer 203*30fdc8d8SChris Lattner while (!p.empty() && isspace (p[p.size() - 1])) 204*30fdc8d8SChris Lattner p.erase (p.size () - 1); 205*30fdc8d8SChris Lattner 206*30fdc8d8SChris Lattner // Most data in the debugserver packets valid printable characters... 207*30fdc8d8SChris Lattner DNBLogThreadedIf(LOG_RNB_COMM, "read: %s", p.c_str()); 208*30fdc8d8SChris Lattner return rnb_success; 209*30fdc8d8SChris Lattner } 210*30fdc8d8SChris Lattner 211*30fdc8d8SChris Lattner rnb_err_t 212*30fdc8d8SChris Lattner RNBSocket::Write (const void *buffer, size_t length) 213*30fdc8d8SChris Lattner { 214*30fdc8d8SChris Lattner if (m_conn_port == -1) 215*30fdc8d8SChris Lattner return rnb_err; 216*30fdc8d8SChris Lattner 217*30fdc8d8SChris Lattner DNBError err; 218*30fdc8d8SChris Lattner int bytessent = send (m_conn_port, buffer, length, 0); 219*30fdc8d8SChris Lattner if (bytessent < 0) 220*30fdc8d8SChris Lattner err.SetError(errno, DNBError::POSIX); 221*30fdc8d8SChris Lattner 222*30fdc8d8SChris Lattner if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) 223*30fdc8d8SChris Lattner err.LogThreaded("::send ( socket = %i, buffer = %p, length = %zu, flags = 0 ) => %i", m_conn_port, buffer, length, bytessent); 224*30fdc8d8SChris Lattner 225*30fdc8d8SChris Lattner if (bytessent < 0) 226*30fdc8d8SChris Lattner return rnb_err; 227*30fdc8d8SChris Lattner 228*30fdc8d8SChris Lattner if (bytessent != length) 229*30fdc8d8SChris Lattner return rnb_err; 230*30fdc8d8SChris Lattner 231*30fdc8d8SChris Lattner DNBLogThreadedIf(LOG_RNB_PACKETS, "putpkt: %*s", length, (char *)buffer); // All data is string based in debugserver, so this is safe 232*30fdc8d8SChris Lattner DNBLogThreadedIf(LOG_RNB_COMM, "sent: %*s", length, (char *)buffer); 233*30fdc8d8SChris Lattner 234*30fdc8d8SChris Lattner return rnb_success; 235*30fdc8d8SChris Lattner } 236*30fdc8d8SChris Lattner 237*30fdc8d8SChris Lattner 238*30fdc8d8SChris Lattner rnb_err_t 239*30fdc8d8SChris Lattner RNBSocket::ClosePort (int& fd, bool save_errno) 240*30fdc8d8SChris Lattner { 241*30fdc8d8SChris Lattner int close_err = 0; 242*30fdc8d8SChris Lattner if (fd > 0) 243*30fdc8d8SChris Lattner { 244*30fdc8d8SChris Lattner errno = 0; 245*30fdc8d8SChris Lattner close_err = close (fd); 246*30fdc8d8SChris Lattner fd = -1; 247*30fdc8d8SChris Lattner } 248*30fdc8d8SChris Lattner return close_err != 0 ? rnb_err : rnb_success; 249*30fdc8d8SChris Lattner } 250*30fdc8d8SChris Lattner 251*30fdc8d8SChris Lattner 252