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