From d83b42ad79ef09877f85405715c73d21f3aaff1f Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Wed, 14 Jan 2015 22:47:10 +0100 Subject: [PATCH] frontend: Add support for TCP connections. 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 | 6 ---- src/frontend/session.c | 10 +++--- src/frontend/sock.c | 73 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 76 insertions(+), 13 deletions(-) diff --git a/src/frontend/connection.c b/src/frontend/connection.c index 700c84a..5f36889 100644 --- a/src/frontend/connection.c +++ b/src/frontend/connection.c @@ -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]; diff --git a/src/frontend/session.c b/src/frontend/session.c index ab45cdd..ed68c61 100644 --- a/src/frontend/session.c +++ b/src/frontend/session.c @@ -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; diff --git a/src/frontend/sock.c b/src/frontend/sock.c index 2def8da..7cb985d 100644 --- a/src/frontend/sock.c +++ b/src/frontend/sock.c @@ -65,6 +65,7 @@ #include +#include #include #include @@ -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 */ -- 2.30.2