diff options
| author | Greg Clayton <gclayton@apple.com> | 2013-06-06 22:44:19 +0000 |
|---|---|---|
| committer | Greg Clayton <gclayton@apple.com> | 2013-06-06 22:44:19 +0000 |
| commit | fd23889e5309881267da5b70e2af89812338f096 (patch) | |
| tree | 07a03cc1603a50cbe13f30a1e9367a989fa21c65 | |
| parent | 99e529ea3c68ab927971038d5eafc1dc5b5f4a44 (diff) | |
| download | bcm5719-llvm-fd23889e5309881267da5b70e2af89812338f096.tar.gz bcm5719-llvm-fd23889e5309881267da5b70e2af89812338f096.zip | |
Remove the debugserver "--open-connection" option and obey the hostname that is passed into debugserver.
you can now specify:
debugserver host:port
debugserver port
debugserver /path/to/file
When "host" is specified, we will only accept connections from that host. If host is not specified, we default to "localhost".
llvm-svn: 183457
| -rw-r--r-- | lldb/tools/debugserver/source/RNBSocket.cpp | 135 | ||||
| -rw-r--r-- | lldb/tools/debugserver/source/RNBSocket.h | 5 | ||||
| -rw-r--r-- | lldb/tools/debugserver/source/debugserver.cpp | 46 |
3 files changed, 132 insertions, 54 deletions
diff --git a/lldb/tools/debugserver/source/RNBSocket.cpp b/lldb/tools/debugserver/source/RNBSocket.cpp index 495c890ed27..13939d5af5c 100644 --- a/lldb/tools/debugserver/source/RNBSocket.cpp +++ b/lldb/tools/debugserver/source/RNBSocket.cpp @@ -30,13 +30,63 @@ this function is called to wait for an incoming connection. This function blocks while waiting for that connection. */ +bool +ResolveIPV4HostName (const char *hostname, in_addr_t &addr) +{ + if (hostname == NULL || + hostname[0] == '\0' || + strcmp(hostname, "localhost") == 0 || + strcmp(hostname, "127.0.0.1") == 0) + { + addr = htonl (INADDR_LOOPBACK); + return true; + } + else if (strcmp(hostname, "*") == 0) + { + addr = htonl (INADDR_ANY); + return true; + } + else + { + // See if an IP address was specified as numbers + int inet_pton_result = ::inet_pton (AF_INET, hostname, &addr); + + if (inet_pton_result == 1) + return true; + + struct hostent *host_entry = gethostbyname (hostname); + if (host_entry) + { + std::string ip_str (::inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list)); + inet_pton_result = ::inet_pton (AF_INET, ip_str.c_str(), &addr); + if (inet_pton_result == 1) + return true; + } + } + return false; +} + rnb_err_t -RNBSocket::Listen (in_port_t port, PortBoundCallback callback, const void *callback_baton, bool localhost_only) +RNBSocket::Listen (const char *listen_host, in_port_t port, PortBoundCallback callback, const void *callback_baton) { //DNBLogThreadedIf(LOG_RNB_COMM, "%8u RNBSocket::%s called", (uint32_t)m_timer.ElapsedMicroSeconds(true), __FUNCTION__); // Disconnect without saving errno Disconnect (false); + // Now figure out the hostname that will be attaching and palce it into + struct sockaddr_in listen_addr; + ::memset (&listen_addr, 0, sizeof listen_addr); + listen_addr.sin_len = sizeof listen_addr; + listen_addr.sin_family = AF_INET; + listen_addr.sin_port = htons (port); + listen_addr.sin_addr.s_addr = INADDR_ANY; + + if (!ResolveIPV4HostName(listen_host, listen_addr.sin_addr.s_addr)) + { + DNBLogThreaded("error: failed to resolve connecting host '%s'", listen_host); + return rnb_err; + } + DNBError err; int listen_fd = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); if (listen_fd == -1) @@ -56,15 +106,7 @@ RNBSocket::Listen (in_port_t port, PortBoundCallback callback, const void *callb sa.sin_len = sizeof sa; sa.sin_family = AF_INET; sa.sin_port = htons (port); - if (localhost_only) - { - sa.sin_addr.s_addr = htonl (INADDR_LOOPBACK); - } - else - { - sa.sin_addr.s_addr = htonl (INADDR_ANY); - } - + sa.sin_addr.s_addr = INADDR_ANY; // Let incoming connections bind to any host network interface (this is NOT who can connect to us) int error = ::bind (listen_fd, (struct sockaddr *) &sa, sizeof(sa)); if (error == -1) err.SetError(errno, DNBError::POSIX); @@ -92,7 +134,7 @@ RNBSocket::Listen (in_port_t port, PortBoundCallback callback, const void *callb } } - error = ::listen (listen_fd, 1); + error = ::listen (listen_fd, 5); if (error == -1) err.SetError(errno, DNBError::POSIX); @@ -105,12 +147,52 @@ RNBSocket::Listen (in_port_t port, PortBoundCallback callback, const void *callb return rnb_err; } - m_fd = ::accept (listen_fd, NULL, 0); - if (m_fd == -1) - err.SetError(errno, DNBError::POSIX); + struct sockaddr_in accept_addr; + ::memset (&accept_addr, 0, sizeof accept_addr); + accept_addr.sin_len = sizeof accept_addr; - if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) - err.LogThreaded("::accept ( socket = %i, address = NULL, address_len = 0 )", listen_fd); + bool accept_connection = false; + + // Loop until we are happy with our connection + while (!accept_connection) + { + socklen_t accept_addr_len = sizeof accept_addr; + m_fd = ::accept (listen_fd, (struct sockaddr *)&accept_addr, &accept_addr_len); + + if (m_fd == -1) + err.SetError(errno, DNBError::POSIX); + + if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) + err.LogThreaded("::accept ( socket = %i, address = %p, address_len = %u )", listen_fd, &accept_addr, accept_addr_len); + + if (err.Fail()) + break; + + if (listen_addr.sin_addr.s_addr == INADDR_ANY) + accept_connection = true; + else + { + if (accept_addr_len == listen_addr.sin_len && + accept_addr.sin_addr.s_addr == listen_addr.sin_addr.s_addr) + { + accept_connection = true; + } + else + { + ::close (m_fd); + m_fd = -1; + const uint8_t *accept_ip = (const uint8_t *)&accept_addr.sin_addr.s_addr; + const uint8_t *listen_ip = (const uint8_t *)&listen_addr.sin_addr.s_addr; + ::fprintf (stderr, + "error: rejecting incoming connection from %u.%u.%u.%u (expecting %u.%u.%u.%u)\n", + accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3], + listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]); + DNBLogThreaded ("error: rejecting connection from %u.%u.%u.%u (expecting %u.%u.%u.%u)", + accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3], + listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]); + } + } + } ClosePort (listen_fd, false); @@ -145,24 +227,11 @@ RNBSocket::Connect (const char *host, uint16_t port) sa.sin_family = AF_INET; sa.sin_port = htons (port); - if (host == NULL) - host = "localhost"; - - int inet_pton_result = ::inet_pton (AF_INET, host, &sa.sin_addr); - - if (inet_pton_result <= 0) + if (!ResolveIPV4HostName(host, sa.sin_addr.s_addr)) { - struct hostent *host_entry = gethostbyname (host); - if (host_entry) - { - std::string host_str (::inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list)); - inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr); - if (inet_pton_result <= 0) - { - Disconnect (false); - return rnb_err; - } - } + DNBLogThreaded("error: failed to resolve host '%s'", host); + Disconnect (false); + return rnb_err; } if (-1 == ::connect (m_fd, (const struct sockaddr *)&sa, sizeof(sa))) diff --git a/lldb/tools/debugserver/source/RNBSocket.h b/lldb/tools/debugserver/source/RNBSocket.h index 2417d574f2c..2467bb77bb4 100644 --- a/lldb/tools/debugserver/source/RNBSocket.h +++ b/lldb/tools/debugserver/source/RNBSocket.h @@ -43,7 +43,10 @@ public: Disconnect (false); } - rnb_err_t Listen (in_port_t port, PortBoundCallback callback, const void *callback_baton, bool localhost_only); + rnb_err_t Listen (const char *listen_host, + in_port_t port, + PortBoundCallback callback, + const void *callback_baton); rnb_err_t Connect (const char *host, uint16_t port); rnb_err_t useFD(int fd); diff --git a/lldb/tools/debugserver/source/debugserver.cpp b/lldb/tools/debugserver/source/debugserver.cpp index c69121ee232..8fcf2ad6190 100644 --- a/lldb/tools/debugserver/source/debugserver.cpp +++ b/lldb/tools/debugserver/source/debugserver.cpp @@ -685,13 +685,13 @@ PortWasBoundCallback (const void *baton, in_port_t port) } static int -StartListening (RNBRemote *remote, int listen_port, const char *unix_socket_name, bool localhost_only) +StartListening (RNBRemote *remote, const char *listen_host, int listen_port, const char *unix_socket_name) { if (!remote->Comm().IsConnected()) { if (listen_port != 0) - RNBLogSTDOUT ("Listening to port %i...\n", listen_port); - if (remote->Comm().Listen(listen_port, PortWasBoundCallback, unix_socket_name, localhost_only) != rnb_success) + RNBLogSTDOUT ("Listening to port %i for a connection from %s...\n", listen_port, listen_host ? listen_host : "localhost"); + if (remote->Comm().Listen(listen_host, listen_port, PortWasBoundCallback, unix_socket_name) != rnb_success) { RNBLogSTDERR ("Failed to get connection from a remote gdb process.\n"); return 0; @@ -787,7 +787,6 @@ static struct option g_long_options[] = { "working-dir", required_argument, NULL, 'W' }, // The working directory that the inferior process should have (only if debugserver launches the process) { "platform", required_argument, NULL, 'p' }, // Put this executable into a remote platform mode { "unix-socket", required_argument, NULL, 'u' }, // If we need to handshake with our parent process, an option will be passed down that specifies a unix socket name to use - { "open-connection", no_argument, NULL, 'H' }, // If debugserver is listening to a TCP port, allow connections from any host (as opposed to just "localhost" connections) { NULL, 0, NULL, 0 } }; @@ -843,7 +842,6 @@ main (int argc, char *argv[]) useconds_t waitfor_interval = 1000; // Time in usecs between process lists polls when waiting for a process by name, default 1 msec. useconds_t waitfor_duration = 0; // Time in seconds to wait for a process by name, 0 means wait forever. bool no_stdio = false; - bool localhost_only = true; #if !defined (DNBLOG_ENABLED) compile_options += "(no-logging) "; @@ -1083,10 +1081,6 @@ main (int argc, char *argv[]) case 'u': unix_socket_name.assign (optarg); break; - - case 'H': - localhost_only = false; - break; } } @@ -1156,6 +1150,7 @@ main (int argc, char *argv[]) compile_options.c_str(), RNB_ARCH); + std::string listen_host; int listen_port = INT32_MAX; char str[PATH_MAX]; str[0] = '\0'; @@ -1172,16 +1167,27 @@ main (int argc, char *argv[]) int items_scanned = ::sscanf (argv[0], "%[^:]:%i", str, &listen_port); if (items_scanned == 2) { - DNBLogDebug("host = '%s' port = %i", str, listen_port); - } - else if (argv[0][0] == '/') - { - listen_port = INT32_MAX; - strncpy(str, argv[0], sizeof(str)); + listen_host = str; + DNBLogDebug("host = '%s' port = %i", listen_host.c_str(), listen_port); } else { - show_usage_and_exit (2); + // No hostname means "localhost" + int items_scanned = ::sscanf (argv[0], "%i", &listen_port); + if (items_scanned == 1) + { + listen_host = "localhost"; + DNBLogDebug("host = '%s' port = %i", listen_host.c_str(), listen_port); + } + else if (argv[0][0] == '/') + { + listen_port = INT32_MAX; + strncpy(str, argv[0], sizeof(str)); + } + else + { + show_usage_and_exit (2); + } } // We just used the 'host:port' or the '/path/file' arg... @@ -1292,7 +1298,7 @@ main (int argc, char *argv[]) #endif if (listen_port != INT32_MAX) { - if (!StartListening (remote, listen_port, unix_socket_name.c_str(), localhost_only)) + if (!StartListening (remote, listen_host.c_str(), listen_port, unix_socket_name.c_str())) mode = eRNBRunLoopModeExit; } else if (str[0] == '/') @@ -1405,7 +1411,7 @@ main (int argc, char *argv[]) { if (listen_port != INT32_MAX) { - if (!StartListening (remote, listen_port, unix_socket_name.c_str(), localhost_only)) + if (!StartListening (remote, listen_host.c_str(), listen_port, unix_socket_name.c_str())) mode = eRNBRunLoopModeExit; } else if (str[0] == '/') @@ -1430,7 +1436,7 @@ main (int argc, char *argv[]) { if (listen_port != INT32_MAX) { - if (!StartListening (remote, listen_port, unix_socket_name.c_str(), localhost_only)) + if (!StartListening (remote, listen_host.c_str(), listen_port, unix_socket_name.c_str())) mode = eRNBRunLoopModeExit; } else if (str[0] == '/') @@ -1457,7 +1463,7 @@ main (int argc, char *argv[]) case eRNBRunLoopModePlatformMode: if (listen_port != INT32_MAX) { - if (!StartListening (remote, listen_port, unix_socket_name.c_str(), localhost_only)) + if (!StartListening (remote, listen_host.c_str(), listen_port, unix_socket_name.c_str())) mode = eRNBRunLoopModeExit; } else if (str[0] == '/') |

