commit 442bdef79b67965d2e563037d88dcecabe4c5264
parent f87624a459342de33ff58619901da96749fad057
Author: Joris Vink <joris@coders.se>
Date: Sun, 7 Oct 2018 20:49:16 +0200
allow kore to bind to unix sockets via bind_unix.
Diffstat:
6 files changed, 152 insertions(+), 58 deletions(-)
diff --git a/include/kore/kore.h b/include/kore/kore.h
@@ -24,6 +24,7 @@
#include <sys/types.h>
#include <sys/time.h>
#include <sys/queue.h>
+#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@@ -214,10 +215,11 @@ struct connection {
int (*read)(struct connection *, size_t *);
int (*write)(struct connection *, size_t, size_t *);
- u_int8_t addrtype;
+ int family;
union {
struct sockaddr_in ipv4;
struct sockaddr_in6 ipv6;
+ struct sockaddr_un unix;
} addr;
struct {
@@ -271,15 +273,10 @@ extern struct kore_runtime kore_native_runtime;
struct listener {
u_int8_t type;
- u_int8_t addrtype;
int fd;
+ int family;
struct kore_runtime_call *connect;
- union {
- struct sockaddr_in ipv4;
- struct sockaddr_in6 ipv6;
- } addr;
-
LIST_ENTRY(listener) list;
};
@@ -593,6 +590,9 @@ struct kore_timer *kore_timer_add(void (*cb)(void *, u_int64_t),
int kore_sockopt(int, int, int);
void kore_listener_cleanup(void);
+void kore_listener_free(struct listener *);
+struct listener *kore_listener_alloc(int, const char *);
+int kore_server_bind_unix(const char *, const char *);
int kore_server_bind(const char *, const char *, const char *);
#if !defined(KORE_NO_TLS)
int kore_tls_sni_cb(SSL *, int *, void *);
diff --git a/src/accesslog.c b/src/accesslog.c
@@ -26,7 +26,7 @@ struct kore_log_packet {
u_int8_t method;
int status;
size_t length;
- u_int8_t addrtype;
+ int family;
u_int8_t addr[sizeof(struct in6_addr)];
char host[KORE_DOMAINNAME_LEN];
char path[HTTP_URI_LEN];
@@ -102,9 +102,13 @@ kore_accesslog_write(const void *data, u_int32_t len)
cn = logpacket.cn;
#endif
- if (inet_ntop(logpacket.addrtype, &(logpacket.addr),
- addr, sizeof(addr)) == NULL)
- (void)kore_strlcpy(addr, "-", sizeof(addr));
+ if (logpacket.family != AF_UNIX) {
+ if (inet_ntop(logpacket.family, &(logpacket.addr),
+ addr, sizeof(addr)) == NULL)
+ (void)kore_strlcpy(addr, "-", sizeof(addr));
+ } else {
+ (void)kore_strlcpy(addr, "unix-socket", sizeof(addr));
+ }
time(&now);
tm = localtime(&now);
@@ -140,15 +144,21 @@ kore_accesslog(struct http_request *req)
{
struct kore_log_packet logpacket;
- logpacket.addrtype = req->owner->addrtype;
- if (logpacket.addrtype == AF_INET) {
+ logpacket.family = req->owner->family;
+
+ switch (logpacket.family) {
+ case AF_INET:
memcpy(logpacket.addr,
&(req->owner->addr.ipv4.sin_addr),
sizeof(req->owner->addr.ipv4.sin_addr));
- } else {
+ break;
+ case AF_INET6:
memcpy(logpacket.addr,
&(req->owner->addr.ipv6.sin6_addr),
sizeof(req->owner->addr.ipv6.sin6_addr));
+ break;
+ default:
+ break;
}
logpacket.status = req->status;
diff --git a/src/config.c b/src/config.c
@@ -52,6 +52,7 @@ extern u_int32_t asset_len_builtin_kore_conf;
static int configure_include(char *);
static int configure_bind(char *);
+static int configure_bind_unix(char *);
static int configure_domain(char *);
static int configure_root(char *);
static int configure_runas(char *);
@@ -130,6 +131,7 @@ static struct {
} config_names[] = {
{ "include", configure_include },
{ "bind", configure_bind },
+ { "bind_unix", configure_bind_unix },
{ "load", configure_load },
#if defined(KORE_USE_PYTHON)
{ "python_path", configure_python_path },
@@ -375,6 +377,18 @@ configure_bind(char *options)
}
static int
+configure_bind_unix(char *options)
+{
+ char *argv[3];
+
+ kore_split_string(options, " ", argv, 3);
+ if (argv[0] == NULL)
+ return (KORE_RESULT_ERROR);
+
+ return (kore_server_bind_unix(argv[0], argv[1]));
+}
+
+static int
configure_load(char *options)
{
char *argv[3];
diff --git a/src/connection.c b/src/connection.c
@@ -102,13 +102,23 @@ kore_connection_accept(struct listener *listener, struct connection **out)
*out = NULL;
c = kore_connection_new(listener);
- c->addrtype = listener->addrtype;
- if (c->addrtype == AF_INET) {
+ c->family = listener->family;
+
+ switch (c->family) {
+ case AF_INET:
len = sizeof(struct sockaddr_in);
s = (struct sockaddr *)&(c->addr.ipv4);
- } else {
+ break;
+ case AF_INET6:
len = sizeof(struct sockaddr_in6);
s = (struct sockaddr *)&(c->addr.ipv6);
+ break;
+ case AF_UNIX:
+ len = sizeof(struct sockaddr_un);
+ s = (struct sockaddr *)&(c->addr.unix);
+ break;
+ default:
+ fatal("unknown family type %d", c->family);
}
if ((c->fd = accept(listener->fd, s, &len)) == -1) {
@@ -117,7 +127,7 @@ kore_connection_accept(struct listener *listener, struct connection **out)
return (KORE_RESULT_ERROR);
}
- if (!kore_connection_nonblock(c->fd, 1)) {
+ if (!kore_connection_nonblock(c->fd, listener->family != AF_UNIX)) {
close(c->fd);
kore_pool_put(&connection_pool, c);
return (KORE_RESULT_ERROR);
diff --git a/src/http.c b/src/http.c
@@ -1398,7 +1398,7 @@ http_request_new(struct connection *c, const char *host,
hp = NULL;
- switch (c->addrtype) {
+ switch (c->family) {
case AF_INET6:
if (*host == '[') {
if ((hp = strrchr(host, ']')) == NULL) {
diff --git a/src/kore.c b/src/kore.c
@@ -16,6 +16,7 @@
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/un.h>
#include <sys/socket.h>
#include <sys/resource.h>
@@ -299,57 +300,115 @@ kore_server_bind(const char *ip, const char *port, const char *ccb)
if (r != 0)
fatal("getaddrinfo(%s): %s", ip, gai_strerror(r));
- l = kore_malloc(sizeof(struct listener));
- l->type = KORE_TYPE_LISTENER;
- l->addrtype = results->ai_family;
-
- if (l->addrtype != AF_INET && l->addrtype != AF_INET6)
- fatal("getaddrinfo(): unknown address family %d", l->addrtype);
-
- if ((l->fd = socket(results->ai_family, SOCK_STREAM, 0)) == -1) {
- kore_free(l);
+ if ((l = kore_listener_alloc(results->ai_family, ccb)) == NULL) {
freeaddrinfo(results);
- kore_log(LOG_ERR, "socket(): %s", errno_s);
return (KORE_RESULT_ERROR);
}
- if (!kore_connection_nonblock(l->fd, 1)) {
- kore_free(l);
+ if (bind(l->fd, results->ai_addr, results->ai_addrlen) == -1) {
+ kore_listener_free(l);
freeaddrinfo(results);
- kore_log(LOG_ERR, "kore_connection_nonblock(): %s", errno_s);
+ kore_log(LOG_ERR, "bind(): %s", errno_s);
return (KORE_RESULT_ERROR);
}
- if (!kore_sockopt(l->fd, SOL_SOCKET, SO_REUSEADDR)) {
- close(l->fd);
- kore_free(l);
- freeaddrinfo(results);
+ freeaddrinfo(results);
+
+ if (listen(l->fd, kore_socket_backlog) == -1) {
+ kore_listener_free(l);
+ kore_log(LOG_ERR, "listen(): %s", errno_s);
return (KORE_RESULT_ERROR);
}
- if (bind(l->fd, results->ai_addr, results->ai_addrlen) == -1) {
- close(l->fd);
- kore_free(l);
- freeaddrinfo(results);
- kore_log(LOG_ERR, "bind(): %s", errno_s);
+ if (foreground) {
+#if !defined(KORE_NO_TLS)
+ kore_log(LOG_NOTICE, "running on https://%s:%s", ip, port);
+#else
+ kore_log(LOG_NOTICE, "running on http://%s:%s", ip, port);
+#endif
+ }
+
+ return (KORE_RESULT_OK);
+}
+
+int
+kore_server_bind_unix(const char *path, const char *ccb)
+{
+ struct listener *l;
+ struct sockaddr_un sun;
+
+ memset(&sun, 0, sizeof(sun));
+ sun.sun_family = AF_UNIX;
+
+ if (kore_strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
+ sizeof(sun.sun_path)) {
+ kore_log(LOG_ERR, "unix socket path '%s' too long", path);
return (KORE_RESULT_ERROR);
}
- freeaddrinfo(results);
+ if ((l = kore_listener_alloc(AF_UNIX, ccb)) == NULL)
+ return (KORE_RESULT_ERROR);
+
+ if (bind(l->fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
+ kore_log(LOG_ERR, "bind: %s", errno_s);
+ kore_listener_free(l);
+ return (KORE_RESULT_ERROR);
+ }
if (listen(l->fd, kore_socket_backlog) == -1) {
- close(l->fd);
- kore_free(l);
kore_log(LOG_ERR, "listen(): %s", errno_s);
+ kore_listener_free(l);
return (KORE_RESULT_ERROR);
}
+ if (foreground)
+ kore_log(LOG_NOTICE, "running on %s", path);
+
+ return (KORE_RESULT_OK);
+}
+
+struct listener *
+kore_listener_alloc(int family, const char *ccb)
+{
+ struct listener *l;
+
+ switch (family) {
+ case AF_INET:
+ case AF_INET6:
+ case AF_UNIX:
+ break;
+ default:
+ fatal("unknown address family %d", family);
+ }
+
+ l = kore_calloc(1, sizeof(struct listener));
+
+ l->fd = -1;
+ l->family = family;
+ l->type = KORE_TYPE_LISTENER;
+
+ if ((l->fd = socket(family, SOCK_STREAM, 0)) == -1) {
+ kore_listener_free(l);
+ kore_log(LOG_ERR, "socket(): %s", errno_s);
+ return (NULL);
+ }
+
+ if (!kore_connection_nonblock(l->fd, 1)) {
+ kore_listener_free(l);
+ kore_log(LOG_ERR, "kore_connection_nonblock(): %s", errno_s);
+ return (NULL);
+ }
+
+ if (!kore_sockopt(l->fd, SOL_SOCKET, SO_REUSEADDR)) {
+ kore_listener_free(l);
+ return (NULL);
+ }
+
if (ccb != NULL) {
if ((l->connect = kore_runtime_getcall(ccb)) == NULL) {
kore_log(LOG_ERR, "no such callback: '%s'", ccb);
- close(l->fd);
- kore_free(l);
- return (KORE_RESULT_ERROR);
+ kore_listener_free(l);
+ return (NULL);
}
} else {
l->connect = NULL;
@@ -358,15 +417,18 @@ kore_server_bind(const char *ip, const char *port, const char *ccb)
nlisteners++;
LIST_INSERT_HEAD(&listeners, l, list);
- if (foreground) {
-#if !defined(KORE_NO_TLS)
- kore_log(LOG_NOTICE, "running on https://%s:%s", ip, port);
-#else
- kore_log(LOG_NOTICE, "running on http://%s:%s", ip, port);
-#endif
- }
+ return (l);
+}
- return (KORE_RESULT_OK);
+void
+kore_listener_free(struct listener *l)
+{
+ LIST_REMOVE(l, list);
+
+ if (l->fd != -1)
+ close(l->fd);
+
+ kore_free(l);
}
int
@@ -421,9 +483,7 @@ kore_listener_cleanup(void)
while (!LIST_EMPTY(&listeners)) {
l = LIST_FIRST(&listeners);
- LIST_REMOVE(l, list);
- close(l->fd);
- kore_free(l);
+ kore_listener_free(l);
}
}