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       (char *)
377           buffer); // All data is string based in debugserver, so this is safe
378   DNBLogThreadedIf(LOG_RNB_COMM, "sent: %*s", (int)length, (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