1 //===-- RNBSocket.cpp -------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // Created by Greg Clayton on 12/12/07. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "RNBSocket.h" 15 #include "DNBError.h" 16 #include "DNBLog.h" 17 #include <arpa/inet.h> 18 #include <errno.h> 19 #include <fcntl.h> 20 #include <map> 21 #include <netdb.h> 22 #include <netinet/in.h> 23 #include <netinet/tcp.h> 24 #include <sys/event.h> 25 #include <termios.h> 26 #include <vector> 27 28 #include "lldb/Host/SocketAddress.h" 29 30 #ifdef WITH_LOCKDOWN 31 #include "lockdown.h" 32 #endif 33 34 /* Once we have a RNBSocket object with a port # specified, 35 this function is called to wait for an incoming connection. 36 This function blocks while waiting for that connection. */ 37 38 bool ResolveIPV4HostName(const char *hostname, in_addr_t &addr) { 39 if (hostname == NULL || hostname[0] == '\0' || 40 strcmp(hostname, "localhost") == 0 || 41 strcmp(hostname, "127.0.0.1") == 0) { 42 addr = htonl(INADDR_LOOPBACK); 43 return true; 44 } else if (strcmp(hostname, "*") == 0) { 45 addr = htonl(INADDR_ANY); 46 return true; 47 } else { 48 // See if an IP address was specified as numbers 49 int inet_pton_result = ::inet_pton(AF_INET, hostname, &addr); 50 51 if (inet_pton_result == 1) 52 return true; 53 54 struct hostent *host_entry = gethostbyname(hostname); 55 if (host_entry) { 56 std::string ip_str( 57 ::inet_ntoa(*(struct in_addr *)*host_entry->h_addr_list)); 58 inet_pton_result = ::inet_pton(AF_INET, ip_str.c_str(), &addr); 59 if (inet_pton_result == 1) 60 return true; 61 } 62 } 63 return false; 64 } 65 66 rnb_err_t RNBSocket::Listen(const char *listen_host, uint16_t port, 67 PortBoundCallback callback, 68 const void *callback_baton) { 69 // DNBLogThreadedIf(LOG_RNB_COMM, "%8u RNBSocket::%s called", 70 // (uint32_t)m_timer.ElapsedMicroSeconds(true), __FUNCTION__); 71 // Disconnect without saving errno 72 Disconnect(false); 73 74 DNBError err; 75 int queue_id = kqueue(); 76 if (queue_id < 0) { 77 err.SetError(errno, DNBError::MachKernel); 78 err.LogThreaded("error: failed to create kqueue."); 79 return rnb_err; 80 } 81 82 bool any_addr = (strcmp(listen_host, "*") == 0); 83 84 // If the user wants to allow connections from any address we should create 85 // sockets on all families that can resolve localhost. This will allow us to 86 // listen for IPv6 and IPv4 connections from all addresses if those interfaces 87 // are available. 88 const char *local_addr = any_addr ? "localhost" : listen_host; 89 90 std::map<int, lldb_private::SocketAddress> sockets; 91 auto addresses = lldb_private::SocketAddress::GetAddressInfo( 92 local_addr, NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP); 93 94 for (auto address : addresses) { 95 int sock_fd = ::socket(address.GetFamily(), SOCK_STREAM, IPPROTO_TCP); 96 if (sock_fd == -1) 97 continue; 98 99 SetSocketOption(sock_fd, SOL_SOCKET, SO_REUSEADDR, 1); 100 101 lldb_private::SocketAddress bind_address = address; 102 103 if(any_addr || !bind_address.IsLocalhost()) 104 bind_address.SetToAnyAddress(bind_address.GetFamily(), port); 105 else 106 bind_address.SetPort(port); 107 108 int error = 109 ::bind(sock_fd, &bind_address.sockaddr(), bind_address.GetLength()); 110 if (error == -1) { 111 ClosePort(sock_fd, false); 112 continue; 113 } 114 115 error = ::listen(sock_fd, 5); 116 if (error == -1) { 117 ClosePort(sock_fd, false); 118 continue; 119 } 120 121 // We were asked to listen on port zero which means we must now read the 122 // actual port that was given to us as port zero is a special code for "find 123 // an open port for me". This will only execute on the first socket created, 124 // subesquent sockets will reuse this port number. 125 if (port == 0) { 126 socklen_t sa_len = address.GetLength(); 127 if (getsockname(sock_fd, &address.sockaddr(), &sa_len) == 0) 128 port = address.GetPort(); 129 } 130 131 sockets[sock_fd] = address; 132 } 133 134 if (sockets.size() == 0) { 135 err.SetError(errno, DNBError::POSIX); 136 err.LogThreaded("::listen or ::bind failed"); 137 return rnb_err; 138 } 139 140 if (callback) 141 callback(callback_baton, port); 142 143 std::vector<struct kevent> events; 144 events.resize(sockets.size()); 145 int i = 0; 146 for (auto socket : sockets) { 147 EV_SET(&events[i++], socket.first, EVFILT_READ, EV_ADD, 0, 0, 0); 148 } 149 150 bool accept_connection = false; 151 152 // Loop until we are happy with our connection 153 while (!accept_connection) { 154 155 struct kevent event_list[4]; 156 int num_events = 157 kevent(queue_id, events.data(), events.size(), event_list, 4, NULL); 158 159 if (num_events < 0) { 160 err.SetError(errno, DNBError::MachKernel); 161 err.LogThreaded("error: kevent() failed."); 162 } 163 164 for (int i = 0; i < num_events; ++i) { 165 auto sock_fd = event_list[i].ident; 166 auto socket_pair = sockets.find(sock_fd); 167 if (socket_pair == sockets.end()) 168 continue; 169 170 lldb_private::SocketAddress &addr_in = socket_pair->second; 171 lldb_private::SocketAddress accept_addr; 172 socklen_t sa_len = accept_addr.GetMaxLength(); 173 m_fd = ::accept(sock_fd, &accept_addr.sockaddr(), &sa_len); 174 175 if (m_fd == -1) { 176 err.SetError(errno, DNBError::POSIX); 177 err.LogThreaded("error: Socket accept failed."); 178 } 179 180 if (addr_in.IsAnyAddr()) 181 accept_connection = true; 182 else { 183 if (accept_addr == addr_in) 184 accept_connection = true; 185 else { 186 ::close(m_fd); 187 m_fd = -1; 188 ::fprintf( 189 stderr, 190 "error: rejecting incoming connection from %s (expecting %s)\n", 191 accept_addr.GetIPAddress().c_str(), 192 addr_in.GetIPAddress().c_str()); 193 DNBLogThreaded("error: rejecting connection from %s (expecting %s)\n", 194 accept_addr.GetIPAddress().c_str(), 195 addr_in.GetIPAddress().c_str()); 196 err.Clear(); 197 } 198 } 199 } 200 if (err.Fail()) 201 break; 202 } 203 for (auto socket : sockets) { 204 int ListenFd = socket.first; 205 ClosePort(ListenFd, false); 206 } 207 208 if (err.Fail()) 209 return rnb_err; 210 211 // Keep our TCP packets coming without any delays. 212 SetSocketOption(m_fd, IPPROTO_TCP, TCP_NODELAY, 1); 213 214 return rnb_success; 215 } 216 217 rnb_err_t RNBSocket::Connect(const char *host, uint16_t port) { 218 auto result = rnb_err; 219 Disconnect(false); 220 221 auto addresses = lldb_private::SocketAddress::GetAddressInfo( 222 host, NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP); 223 224 for (auto address : addresses) { 225 m_fd = ::socket(address.GetFamily(), SOCK_STREAM, IPPROTO_TCP); 226 if (m_fd == -1) 227 continue; 228 229 // Enable local address reuse 230 SetSocketOption(m_fd, SOL_SOCKET, SO_REUSEADDR, 1); 231 232 address.SetPort(port); 233 234 if (-1 == ::connect(m_fd, &address.sockaddr(), address.GetLength())) { 235 Disconnect(false); 236 continue; 237 } 238 SetSocketOption(m_fd, IPPROTO_TCP, TCP_NODELAY, 1); 239 240 result = rnb_success; 241 break; 242 } 243 return result; 244 } 245 246 rnb_err_t RNBSocket::useFD(int fd) { 247 if (fd < 0) { 248 DNBLogThreadedIf(LOG_RNB_COMM, "Bad file descriptor passed in."); 249 return rnb_err; 250 } 251 252 m_fd = fd; 253 return rnb_success; 254 } 255 256 #ifdef WITH_LOCKDOWN 257 rnb_err_t RNBSocket::ConnectToService() { 258 DNBLog("Connecting to com.apple.%s service...", DEBUGSERVER_PROGRAM_NAME); 259 // Disconnect from any previous connections 260 Disconnect(false); 261 if (::secure_lockdown_checkin(&m_ld_conn, NULL, NULL) != kLDESuccess) { 262 DNBLogThreadedIf(LOG_RNB_COMM, 263 "::secure_lockdown_checkin(&m_fd, NULL, NULL) failed"); 264 m_fd = -1; 265 return rnb_not_connected; 266 } 267 m_fd = ::lockdown_get_socket(m_ld_conn); 268 if (m_fd == -1) { 269 DNBLogThreadedIf(LOG_RNB_COMM, "::lockdown_get_socket() failed"); 270 return rnb_not_connected; 271 } 272 m_fd_from_lockdown = true; 273 return rnb_success; 274 } 275 #endif 276 277 rnb_err_t RNBSocket::OpenFile(const char *path) { 278 DNBError err; 279 m_fd = open(path, O_RDWR); 280 if (m_fd == -1) { 281 err.SetError(errno, DNBError::POSIX); 282 err.LogThreaded("can't open file '%s'", path); 283 return rnb_not_connected; 284 } else { 285 struct termios stdin_termios; 286 287 if (::tcgetattr(m_fd, &stdin_termios) == 0) { 288 stdin_termios.c_lflag &= ~ECHO; // Turn off echoing 289 stdin_termios.c_lflag &= ~ICANON; // Get one char at a time 290 ::tcsetattr(m_fd, TCSANOW, &stdin_termios); 291 } 292 } 293 return rnb_success; 294 } 295 296 int RNBSocket::SetSocketOption(int fd, int level, int option_name, 297 int option_value) { 298 return ::setsockopt(fd, level, option_name, &option_value, 299 sizeof(option_value)); 300 } 301 302 rnb_err_t RNBSocket::Disconnect(bool save_errno) { 303 #ifdef WITH_LOCKDOWN 304 if (m_fd_from_lockdown) { 305 m_fd_from_lockdown = false; 306 m_fd = -1; 307 lockdown_disconnect(m_ld_conn); 308 return rnb_success; 309 } 310 #endif 311 return ClosePort(m_fd, save_errno); 312 } 313 314 rnb_err_t RNBSocket::Read(std::string &p) { 315 char buf[1024]; 316 p.clear(); 317 318 // Note that BUF is on the stack so we must be careful to keep any 319 // writes to BUF from overflowing or we'll have security issues. 320 321 if (m_fd == -1) 322 return rnb_err; 323 324 // DNBLogThreadedIf(LOG_RNB_COMM, "%8u RNBSocket::%s calling read()", 325 // (uint32_t)m_timer.ElapsedMicroSeconds(true), __FUNCTION__); 326 DNBError err; 327 ssize_t bytesread = read(m_fd, buf, sizeof(buf)); 328 if (bytesread <= 0) 329 err.SetError(errno, DNBError::POSIX); 330 else 331 p.append(buf, bytesread); 332 333 if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) 334 err.LogThreaded("::read ( %i, %p, %llu ) => %i", m_fd, buf, sizeof(buf), 335 (uint64_t)bytesread); 336 337 // Our port went away - we have to mark this so IsConnected will return the 338 // truth. 339 if (bytesread == 0) { 340 m_fd = -1; 341 return rnb_not_connected; 342 } else if (bytesread == -1) { 343 m_fd = -1; 344 return rnb_err; 345 } 346 // Strip spaces from the end of the buffer 347 while (!p.empty() && isspace(p[p.size() - 1])) 348 p.erase(p.size() - 1); 349 350 // Most data in the debugserver packets valid printable characters... 351 DNBLogThreadedIf(LOG_RNB_COMM, "read: %s", p.c_str()); 352 return rnb_success; 353 } 354 355 rnb_err_t RNBSocket::Write(const void *buffer, size_t length) { 356 if (m_fd == -1) 357 return rnb_err; 358 359 DNBError err; 360 ssize_t bytessent = write(m_fd, buffer, length); 361 if (bytessent < 0) 362 err.SetError(errno, DNBError::POSIX); 363 364 if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) 365 err.LogThreaded("::write ( socket = %i, buffer = %p, length = %llu) => %i", 366 m_fd, buffer, length, (uint64_t)bytessent); 367 368 if (bytessent < 0) 369 return rnb_err; 370 371 if ((size_t)bytessent != length) 372 return rnb_err; 373 374 DNBLogThreadedIf( 375 LOG_RNB_PACKETS, "putpkt: %*s", (int)length, 376 (const char *) 377 buffer); // All data is string based in debugserver, so this is safe 378 DNBLogThreadedIf(LOG_RNB_COMM, "sent: %*s", (int)length, 379 (const char *)buffer); 380 381 return rnb_success; 382 } 383 384 rnb_err_t RNBSocket::ClosePort(int &fd, bool save_errno) { 385 int close_err = 0; 386 if (fd > 0) { 387 errno = 0; 388 close_err = close(fd); 389 fd = -1; 390 } 391 return close_err != 0 ? rnb_err : rnb_success; 392 } 393