kore

a fork of the worlds most advanced web framework
Log | Files | Refs | README | LICENSE

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:
Minclude/kore/kore.h | 14+++++++-------
Msrc/accesslog.c | 24+++++++++++++++++-------
Msrc/config.c | 14++++++++++++++
Msrc/connection.c | 18++++++++++++++----
Msrc/http.c | 2+-
Msrc/kore.c | 138++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
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); } }