1 //===-- TcpSocket.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 #include "lldb/Host/common/TCPSocket.h"
11 
12 #include "lldb/Core/Log.h"
13 #include "lldb/Host/Config.h"
14 
15 #ifndef LLDB_DISABLE_POSIX
16 #include <arpa/inet.h>
17 #include <netinet/tcp.h>
18 #include <sys/socket.h>
19 #endif
20 
21 using namespace lldb;
22 using namespace lldb_private;
23 
24 namespace {
25 
26 const int kDomain = AF_INET;
27 const int kType = SOCK_STREAM;
28 }
29 
30 TCPSocket::TCPSocket(NativeSocket socket, bool should_close)
31     : Socket(socket, ProtocolTcp, should_close) {}
32 
33 TCPSocket::TCPSocket(bool child_processes_inherit, Error &error)
34     : TCPSocket(CreateSocket(kDomain, kType, IPPROTO_TCP,
35                              child_processes_inherit, error),
36                 true) {}
37 
38 // Return the port number that is being used by the socket.
39 uint16_t TCPSocket::GetLocalPortNumber() const {
40   if (m_socket != kInvalidSocketValue) {
41     SocketAddress sock_addr;
42     socklen_t sock_addr_len = sock_addr.GetMaxLength();
43     if (::getsockname(m_socket, sock_addr, &sock_addr_len) == 0)
44       return sock_addr.GetPort();
45   }
46   return 0;
47 }
48 
49 std::string TCPSocket::GetLocalIPAddress() const {
50   // We bound to port zero, so we need to figure out which port we actually
51   // bound to
52   if (m_socket != kInvalidSocketValue) {
53     SocketAddress sock_addr;
54     socklen_t sock_addr_len = sock_addr.GetMaxLength();
55     if (::getsockname(m_socket, sock_addr, &sock_addr_len) == 0)
56       return sock_addr.GetIPAddress();
57   }
58   return "";
59 }
60 
61 uint16_t TCPSocket::GetRemotePortNumber() const {
62   if (m_socket != kInvalidSocketValue) {
63     SocketAddress sock_addr;
64     socklen_t sock_addr_len = sock_addr.GetMaxLength();
65     if (::getpeername(m_socket, sock_addr, &sock_addr_len) == 0)
66       return sock_addr.GetPort();
67   }
68   return 0;
69 }
70 
71 std::string TCPSocket::GetRemoteIPAddress() const {
72   // We bound to port zero, so we need to figure out which port we actually
73   // bound to
74   if (m_socket != kInvalidSocketValue) {
75     SocketAddress sock_addr;
76     socklen_t sock_addr_len = sock_addr.GetMaxLength();
77     if (::getpeername(m_socket, sock_addr, &sock_addr_len) == 0)
78       return sock_addr.GetIPAddress();
79   }
80   return "";
81 }
82 
83 Error TCPSocket::Connect(llvm::StringRef name) {
84   if (m_socket == kInvalidSocketValue)
85     return Error("Invalid socket");
86 
87   Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_COMMUNICATION));
88   if (log)
89     log->Printf("TCPSocket::%s (host/port = %s)", __FUNCTION__, name.data());
90 
91   Error error;
92   std::string host_str;
93   std::string port_str;
94   int32_t port = INT32_MIN;
95   if (!DecodeHostAndPort(name, host_str, port_str, port, &error))
96     return error;
97 
98   struct sockaddr_in sa;
99   ::memset(&sa, 0, sizeof(sa));
100   sa.sin_family = kDomain;
101   sa.sin_port = htons(port);
102 
103   int inet_pton_result = ::inet_pton(kDomain, host_str.c_str(), &sa.sin_addr);
104 
105   if (inet_pton_result <= 0) {
106     struct hostent *host_entry = gethostbyname(host_str.c_str());
107     if (host_entry)
108       host_str = ::inet_ntoa(*(struct in_addr *)*host_entry->h_addr_list);
109     inet_pton_result = ::inet_pton(kDomain, host_str.c_str(), &sa.sin_addr);
110     if (inet_pton_result <= 0) {
111       if (inet_pton_result == -1)
112         SetLastError(error);
113       else
114         error.SetErrorStringWithFormat("invalid host string: '%s'",
115                                        host_str.c_str());
116 
117       return error;
118     }
119   }
120 
121   if (-1 ==
122       ::connect(GetNativeSocket(), (const struct sockaddr *)&sa, sizeof(sa))) {
123     SetLastError(error);
124     return error;
125   }
126 
127   // Keep our TCP packets coming without any delays.
128   SetOptionNoDelay();
129   error.Clear();
130   return error;
131 }
132 
133 Error TCPSocket::Listen(llvm::StringRef name, int backlog) {
134   Error error;
135 
136   // enable local address reuse
137   SetOptionReuseAddress();
138 
139   Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
140   if (log)
141     log->Printf("TCPSocket::%s (%s)", __FUNCTION__, name.data());
142 
143   std::string host_str;
144   std::string port_str;
145   int32_t port = INT32_MIN;
146   if (!DecodeHostAndPort(name, host_str, port_str, port, &error))
147     return error;
148 
149   SocketAddress bind_addr;
150 
151   // Only bind to the loopback address if we are expecting a connection from
152   // localhost to avoid any firewall issues.
153   const bool bind_addr_success = (host_str == "127.0.0.1")
154                                      ? bind_addr.SetToLocalhost(kDomain, port)
155                                      : bind_addr.SetToAnyAddress(kDomain, port);
156 
157   if (!bind_addr_success) {
158     error.SetErrorString("Failed to bind port");
159     return error;
160   }
161 
162   int err = ::bind(GetNativeSocket(), bind_addr, bind_addr.GetLength());
163   if (err != -1)
164     err = ::listen(GetNativeSocket(), backlog);
165 
166   if (err == -1)
167     SetLastError(error);
168 
169   return error;
170 }
171 
172 Error TCPSocket::Accept(llvm::StringRef name, bool child_processes_inherit,
173                         Socket *&conn_socket) {
174   Error error;
175   std::string host_str;
176   std::string port_str;
177   int32_t port;
178   if (!DecodeHostAndPort(name, host_str, port_str, port, &error))
179     return error;
180 
181   const sa_family_t family = kDomain;
182   const int socktype = kType;
183   const int protocol = IPPROTO_TCP;
184   SocketAddress listen_addr;
185   if (host_str.empty())
186     listen_addr.SetToLocalhost(family, port);
187   else if (host_str.compare("*") == 0)
188     listen_addr.SetToAnyAddress(family, port);
189   else {
190     if (!listen_addr.getaddrinfo(host_str.c_str(), port_str.c_str(), family,
191                                  socktype, protocol)) {
192       error.SetErrorStringWithFormat("unable to resolve hostname '%s'",
193                                      host_str.c_str());
194       return error;
195     }
196   }
197 
198   bool accept_connection = false;
199   std::unique_ptr<TCPSocket> accepted_socket;
200 
201   // Loop until we are happy with our connection
202   while (!accept_connection) {
203     struct sockaddr_in accept_addr;
204     ::memset(&accept_addr, 0, sizeof accept_addr);
205 #if !(defined(__linux__) || defined(_WIN32))
206     accept_addr.sin_len = sizeof accept_addr;
207 #endif
208     socklen_t accept_addr_len = sizeof accept_addr;
209 
210     int sock = AcceptSocket(GetNativeSocket(), (struct sockaddr *)&accept_addr,
211                             &accept_addr_len, child_processes_inherit, error);
212 
213     if (error.Fail())
214       break;
215 
216     bool is_same_addr = true;
217 #if !(defined(__linux__) || (defined(_WIN32)))
218     is_same_addr = (accept_addr_len == listen_addr.sockaddr_in().sin_len);
219 #endif
220     if (is_same_addr)
221       is_same_addr = (accept_addr.sin_addr.s_addr ==
222                       listen_addr.sockaddr_in().sin_addr.s_addr);
223 
224     if (is_same_addr ||
225         (listen_addr.sockaddr_in().sin_addr.s_addr == INADDR_ANY)) {
226       accept_connection = true;
227       accepted_socket.reset(new TCPSocket(sock, true));
228     } else {
229       const uint8_t *accept_ip = (const uint8_t *)&accept_addr.sin_addr.s_addr;
230       const uint8_t *listen_ip =
231           (const uint8_t *)&listen_addr.sockaddr_in().sin_addr.s_addr;
232       ::fprintf(stderr, "error: rejecting incoming connection from %u.%u.%u.%u "
233                         "(expecting %u.%u.%u.%u)\n",
234                 accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3],
235                 listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]);
236       accepted_socket.reset();
237     }
238   }
239 
240   if (!accepted_socket)
241     return error;
242 
243   // Keep our TCP packets coming without any delays.
244   accepted_socket->SetOptionNoDelay();
245   error.Clear();
246   conn_socket = accepted_socket.release();
247   return error;
248 }
249 
250 int TCPSocket::SetOptionNoDelay() {
251   return SetOption(IPPROTO_TCP, TCP_NODELAY, 1);
252 }
253 
254 int TCPSocket::SetOptionReuseAddress() {
255   return SetOption(SOL_SOCKET, SO_REUSEADDR, 1);
256 }
257