Code

frontend: Add support for TCP connections.
authorSebastian Harl <sh@tokkee.org>
Wed, 14 Jan 2015 21:47:10 +0000 (22:47 +0100)
committerSebastian Harl <sh@tokkee.org>
Wed, 14 Jan 2015 21:47:10 +0000 (22:47 +0100)
This is the new default listener type (unless the listen address starts with a
slash in which case a UNIXSOCK connection is used).

This does not support any kind of peer lookup yet. Instead, it'll fully trust
the client for now and accept any username. In the future, this will be
configurable and multiple mechanisms (e.g. ident, SSL cert) will be supported.

src/frontend/connection.c
src/frontend/session.c
src/frontend/sock.c

index 700c84ae42af2e0793b289e82c770807df609e51..5f368892c0970f89c14085172eb45e2bdf61fece 100644 (file)
@@ -123,12 +123,6 @@ connection_init(sdb_object_t *obj, va_list ap)
        conn->finish = NULL;
        conn->session = NULL;
 
-       if (conn->client_addr.ss_family != AF_UNIX) {
-               sdb_log(SDB_LOG_ERR, "frontend: Accepted connection using "
-                               "unexpected family type %d", conn->client_addr.ss_family);
-               return -1;
-       }
-
        sock_fl = fcntl(conn->fd, F_GETFL);
        if (fcntl(conn->fd, F_SETFL, sock_fl | O_NONBLOCK)) {
                char buf[1024];
index ab45cdd17c30cb154a7cf051cf940ba11e47e4b0..ed68c61cc747e89dbbadba928a29536cca702bb5 100644 (file)
@@ -57,13 +57,11 @@ sdb_fe_session_start(sdb_conn_t *conn)
        username[conn->cmd_len] = '\0';
 
        if (! conn->username) {
-               /* We couldn't determine the remote peer when setting up the
-                * connection; TODO: add support for password authentication */
-               sdb_strbuf_sprintf(conn->errbuf, "Password authentication "
-                               "not supported");
-               return -1;
+               /* We trust the remote peer.
+                * TODO: make the auth mechanism configurable */
+               conn->username = strdup(username);
        }
-       if (strcmp(conn->username, username)) {
+       else if (strcmp(conn->username, username)) {
                sdb_strbuf_sprintf(conn->errbuf, "%s cannot act on behalf of %s",
                                conn->username, username);
                return -1;
index 2def8da868f9e94df057681e99d2508abced36c6..7cb985d9735530c30caba90c26cbe85159ecd027 100644 (file)
@@ -65,6 +65,7 @@
 
 #include <pwd.h>
 
+#include <netdb.h>
 #include <libgen.h>
 #include <pthread.h>
 
@@ -217,6 +218,71 @@ close_unixsock(listener_t *listener)
        unlink(listener->address);
 } /* close_unixsock */
 
+static int
+open_tcp(listener_t *listener)
+{
+       struct addrinfo *ai, *ai_list = NULL;
+       int status;
+
+       assert(listener);
+
+       if ((status = sdb_resolve(SDB_NET_TCP, listener->address, &ai_list))) {
+               sdb_log(SDB_LOG_ERR, "frontend: Failed to resolve '%s': %s",
+                               listener->address, gai_strerror(status));
+               return -1;
+       }
+
+       for (ai = ai_list; ai != NULL; ai = ai->ai_next) {
+               char errbuf[1024];
+               int reuse = 1;
+
+               listener->sock_fd = socket(ai->ai_family,
+                               ai->ai_socktype, ai->ai_protocol);
+               if (listener->sock_fd < 0) {
+                       sdb_log(SDB_LOG_ERR, "frontend: Failed to open socket for %s: %s",
+                                       listener->address,
+                                       sdb_strerror(errno, errbuf, sizeof(errbuf)));
+                       continue;
+               }
+
+               if (setsockopt(listener->sock_fd, SOL_SOCKET, SO_REUSEADDR,
+                                       &reuse, sizeof(reuse)) < 0) {
+                       sdb_log(SDB_LOG_ERR, "frontend: Failed to set socket option: %s",
+                                       sdb_strerror(errno, errbuf, sizeof(errbuf)));
+                       close(listener->sock_fd);
+                       listener->sock_fd = -1;
+                       continue;
+               }
+
+               if (bind(listener->sock_fd, ai->ai_addr, ai->ai_addrlen) < 0) {
+                       char host[1024], port[32];
+                       getnameinfo(ai->ai_addr, ai->ai_addrlen, host, sizeof(host),
+                                       port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV);
+                       sdb_log(SDB_LOG_ERR, "frontend: Failed to bind to %s:%s: %s",
+                                       host, port, sdb_strerror(errno, errbuf, sizeof(errbuf)));
+                       close(listener->sock_fd);
+                       listener->sock_fd = -1;
+                       continue;
+               }
+               break;
+       }
+       freeaddrinfo(ai_list);
+
+       if (listener->sock_fd < 0)
+               return -1;
+       return 0;
+} /* open_tcp */
+
+static void
+close_tcp(listener_t *listener)
+{
+       assert(listener);
+
+       if (listener->sock_fd >= 0)
+               close(listener->sock_fd);
+       listener->sock_fd = -1;
+} /* close_tcp */
+
 /*
  * private variables
  */
@@ -224,9 +290,11 @@ close_unixsock(listener_t *listener)
 /* the enum has to be sorted the same as the implementations array
  * to ensure that the type may be used as index into the array */
 enum {
-       LISTENER_UNIXSOCK = 0, /* this is the default */
+       LISTENER_TCP = 0, /* this is the default */
+       LISTENER_UNIXSOCK,
 };
 static fe_listener_impl_t listener_impls[] = {
+       { LISTENER_TCP,      "tcp",  open_tcp,      close_tcp },
        { LISTENER_UNIXSOCK, "unix", open_unixsock, close_unixsock },
 };
 
@@ -274,6 +342,8 @@ get_type(const char *address)
        size_t len;
        size_t i;
 
+       if (*address == '/')
+               return LISTENER_UNIXSOCK;
        sep = strchr(address, (int)':');
        if (! sep)
                return listener_impls[0].type;
@@ -347,6 +417,7 @@ listener_create(sdb_fe_socket_t *sock, const char *address)
        }
        listener->type = type;
        listener->accept = NULL;
+       listener->peer = NULL;
 
        if (listener_impls[type].open(listener)) {
                /* prints error */