summaryrefslogtreecommitdiff
path: root/tests/src
diff options
context:
space:
mode:
authorRobert Ancell <robert.ancell@canonical.com>2014-11-12 12:14:06 +1300
committerRobert Ancell <robert.ancell@canonical.com>2014-11-12 12:14:06 +1300
commit705927dd0d9228894be57975d20c6968e10cb571 (patch)
tree420125d3a6a6fdd4e3c0694d823ced1a0419e338 /tests/src
parent98778683a05c3a27902309763ed27cb473ef6c05 (diff)
downloadlightdm-705927dd0d9228894be57975d20c6968e10cb571.tar.gz
Redirect bound socket ports so networking tests can be run non-root
Diffstat (limited to 'tests/src')
-rw-r--r--tests/src/libsystem.c184
-rw-r--r--tests/src/vnc-client.c31
2 files changed, 186 insertions, 29 deletions
diff --git a/tests/src/libsystem.c b/tests/src/libsystem.c
index 0510c9a5..88d9a61d 100644
--- a/tests/src/libsystem.c
+++ b/tests/src/libsystem.c
@@ -8,6 +8,8 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
#include <pwd.h>
#include <unistd.h>
#include <dirent.h>
@@ -542,6 +544,188 @@ ioctl (int d, unsigned long request, ...)
}
}
+static void
+add_port_redirect (int requested_port, int redirected_port)
+{
+ GKeyFile *file;
+ gchar *path, *name, *data;
+
+ file = g_key_file_new ();
+ path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), ".port-redirects", NULL);
+ g_key_file_load_from_file (file, path, G_KEY_FILE_NONE, NULL);
+
+ name = g_strdup_printf ("%d", requested_port);
+ g_key_file_set_integer (file, name, "redirected", redirected_port);
+ g_free (name);
+
+ data = g_key_file_to_data (file, NULL, NULL);
+ g_file_set_contents (path, data, -1, NULL);
+ g_free (data);
+ g_free (path);
+
+ g_key_file_free (file);
+}
+
+static int
+find_port_redirect (int port)
+{
+ GKeyFile *file;
+ gchar *path, *name;
+ int redirected_port;
+
+ file = g_key_file_new ();
+ path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), ".port-redirects", NULL);
+ g_key_file_load_from_file (file, path, G_KEY_FILE_NONE, NULL);
+ g_free (path);
+
+ name = g_strdup_printf ("%d", port);
+ redirected_port = g_key_file_get_integer (file, name, "redirected", NULL);
+ g_free (name);
+ g_key_file_free (file);
+
+ return redirected_port;
+}
+
+int
+bind (int sockfd, const struct sockaddr *addr, socklen_t addrlen)
+{
+ int port = 0, redirected_port = 0;
+ int (*_bind) (int sockfd, const struct sockaddr *addr, socklen_t addrlen);
+ const struct sockaddr *modified_addr = addr;
+ struct sockaddr_in temp_addr;
+ struct sockaddr_in6 temp_addr6;
+ int retval;
+
+ _bind = (int (*)(int sockfd, const struct sockaddr *addr, socklen_t addrlen)) dlsym (RTLD_NEXT, "bind");
+
+ switch (addr->sa_family)
+ {
+ case AF_INET:
+ port = ntohs (((const struct sockaddr_in *) addr)->sin_port);
+ redirected_port = find_port_redirect (port);
+ memcpy (&temp_addr, addr, sizeof (struct sockaddr_in));
+ modified_addr = (struct sockaddr *) &temp_addr;
+ if (redirected_port != 0)
+ temp_addr.sin_port = htons (redirected_port);
+ else
+ temp_addr.sin_port = 0;
+ break;
+ case AF_INET6:
+ port = ntohs (((const struct sockaddr_in6 *) addr)->sin6_port);
+ redirected_port = find_port_redirect (port);
+ memcpy (&temp_addr6, addr, sizeof (struct sockaddr_in6));
+ modified_addr = (struct sockaddr *) &temp_addr6;
+ if (redirected_port != 0)
+ temp_addr6.sin6_port = htons (redirected_port);
+ else
+ temp_addr6.sin6_port = 0;
+ break;
+ }
+
+ retval = _bind (sockfd, modified_addr, addrlen);
+
+ socklen_t temp_addr_len;
+ switch (addr->sa_family)
+ {
+ case AF_INET:
+ temp_addr_len = sizeof (temp_addr);
+ getsockname (sockfd, &temp_addr, &temp_addr_len);
+ if (redirected_port == 0)
+ {
+ redirected_port = ntohs (temp_addr.sin_port);
+ add_port_redirect (port, redirected_port);
+ }
+ break;
+ case AF_INET6:
+ temp_addr_len = sizeof (temp_addr6);
+ getsockname (sockfd, &temp_addr6, &temp_addr_len);
+ if (redirected_port == 0)
+ {
+ redirected_port = ntohs (temp_addr6.sin6_port);
+ add_port_redirect (port, redirected_port);
+ }
+ break;
+ }
+
+ return retval;
+}
+
+int
+connect (int sockfd, const struct sockaddr *addr, socklen_t addrlen)
+{
+ int port, redirected_port;
+ const struct sockaddr *modified_addr = addr;
+ struct sockaddr_in temp_addr;
+ struct sockaddr_in6 temp_addr6;
+ int (*_connect) (int sockfd, const struct sockaddr *addr, socklen_t addrlen);
+
+ _connect = (int (*)(int sockfd, const struct sockaddr *addr, socklen_t addrlen)) dlsym (RTLD_NEXT, "connect");
+
+ switch (addr->sa_family)
+ {
+ case AF_INET:
+ port = ntohs (((const struct sockaddr_in *) addr)->sin_port);
+ redirected_port = find_port_redirect (port);
+ if (redirected_port != 0)
+ {
+ memcpy (&temp_addr, addr, sizeof (struct sockaddr_in));
+ temp_addr.sin_port = htons (redirected_port);
+ modified_addr = (struct sockaddr *) &temp_addr;
+ }
+ break;
+ case AF_INET6:
+ port = ntohs (((const struct sockaddr_in6 *) addr)->sin6_port);
+ redirected_port = find_port_redirect (port);
+ if (redirected_port != 0)
+ {
+ memcpy (&temp_addr6, addr, sizeof (struct sockaddr_in6));
+ temp_addr6.sin6_port = htons (redirected_port);
+ modified_addr = (struct sockaddr *) &temp_addr6;
+ }
+ break;
+ }
+
+ return _connect (sockfd, modified_addr, addrlen);
+}
+
+ssize_t
+sendto (int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen)
+{
+ int port, redirected_port;
+ const struct sockaddr *modified_addr = dest_addr;
+ struct sockaddr_in temp_addr;
+ struct sockaddr_in6 temp_addr6;
+ ssize_t (*_sendto) (int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
+
+ _sendto = (ssize_t (*)(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen)) dlsym (RTLD_NEXT, "sendto");
+
+ switch (dest_addr->sa_family)
+ {
+ case AF_INET:
+ port = ntohs (((const struct sockaddr_in *) dest_addr)->sin_port);
+ redirected_port = find_port_redirect (port);
+ if (redirected_port != 0)
+ {
+ memcpy (&temp_addr, dest_addr, sizeof (struct sockaddr_in));
+ temp_addr.sin_port = htons (redirected_port);
+ modified_addr = (struct sockaddr *) &temp_addr;
+ }
+ break;
+ case AF_INET6:
+ port = ntohs (((const struct sockaddr_in6 *) dest_addr)->sin6_port);
+ redirected_port = find_port_redirect (port);
+ if (redirected_port != 0)
+ {
+ memcpy (&temp_addr6, dest_addr, sizeof (struct sockaddr_in6));
+ temp_addr6.sin6_port = htons (redirected_port);
+ modified_addr = (struct sockaddr *) &temp_addr6;
+ }
+ break;
+ }
+
+ return _sendto (sockfd, buf, len, flags, modified_addr, addrlen);
+}
+
int
close (int fd)
{
diff --git a/tests/src/vnc-client.c b/tests/src/vnc-client.c
index b1917049..2fe0a017 100644
--- a/tests/src/vnc-client.c
+++ b/tests/src/vnc-client.c
@@ -12,9 +12,6 @@ static GKeyFile *config;
int
main (int argc, char **argv)
{
- gchar *server_address;
- gchar *hostname, *c;
- gint port;
GError *error = NULL;
GSocket *socket;
GSocketConnectable *address;
@@ -34,12 +31,7 @@ main (int argc, char **argv)
config = g_key_file_new ();
g_key_file_load_from_file (config, g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "script", NULL), G_KEY_FILE_NONE, NULL);
- if (argc > 1)
- server_address = g_strdup (argv[1]);
- else
- server_address = g_strdup (":0");
-
- status_notify ("VNC-CLIENT CONNECT SERVER=%s", server_address);
+ status_notify ("VNC-CLIENT CONNECT");
socket = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_TCP, &error);
if (error)
@@ -48,26 +40,7 @@ main (int argc, char **argv)
if (!socket)
return EXIT_FAILURE;
- hostname = g_strdup (server_address);
- c = strchr (hostname, ':');
- if (c)
- {
- *c = '\0';
- gchar *port_string = c + 1;
- if (g_str_has_prefix (port_string, ":"))
- port = atoi (port_string + 1);
- else
- port = 5900 + atoi (port_string);
- }
- else
- port = 5900;
- if (strcmp (hostname, "") == 0)
- {
- g_free (hostname);
- hostname = g_strdup ("localhost");
- }
-
- address = g_network_address_new (hostname, port);
+ address = g_network_address_new ("localhost", 5900);
enumerator = g_socket_connectable_enumerate (address);
result = FALSE;
while (TRUE)