commit - c29b0f4c291d5ed73f7e1d388bc6d4d4809483a1
commit + 751c0a50f0df04c86eb1683ae8c653d086971ca5
blob - eb61f54564d20341ee600522a273544e76a332d5
blob + 25ea75d7ab2c19be6d982c7cc471af1b23f72ef4
--- gotwebd/config.c
+++ gotwebd/config.c
env->server_cnt = 0;
TAILQ_INIT(&env->servers);
TAILQ_INIT(&env->sockets);
+ TAILQ_INIT(&env->addresses);
return 0;
}
memcpy(srv, p, sizeof(*srv));
/* log server info */
- log_debug("%s: server=%s fcgi_socket=%s unix_socket=%s", __func__,
- srv->name, srv->fcgi_socket ? "yes" : "no", srv->unix_socket ?
- "yes" : "no");
+ log_debug("%s: server=%s", __func__, srv->name);
TAILQ_INSERT_TAIL(&env->servers, srv, entry);
sock->pack_fds[i] = -1;
/* log new socket info */
- log_debug("%s: name=%s id=%d server=%s af_type=%s socket_path=%s",
- __func__, sock->conf.name, sock->conf.id, sock->conf.srv_name,
+ log_debug("%s: id=%d af_type=%s socket_path=%s",
+ __func__, sock->conf.id,
sock->conf.af_type == AF_UNIX ? "unix" :
(sock->conf.af_type == AF_INET ? "inet" :
(sock->conf.af_type == AF_INET6 ? "inet6" : "unknown")),
blob - 2c4a828f3b8cde396a60854daae3bbc690ecdfd3
blob + b5bdf32e07b935f396dc7b1a3860b7f418eef2cf
--- gotwebd/gotwebd.conf.5
+++ gotwebd/gotwebd.conf.5
Run the specified number of server processes.
.Xr gotwebd 8
runs 3 server processes by default.
-.It Ic unix_socket Ar on | off
-Controls whether the servers will listen on unix sockets by default.
-Listening on unix sockets is the default.
.It Ic unix_socket_name Ar path
Set the path to the default unix socket.
Defaults to
May be specified multiple times to build up a list of listening sockets.
However, a given combination of address and port may only be used by
one server.
-.It Ic listen on socket off
-Disable use of unix socket.
.It Ic listen on socket Ar path
Set the path to the unix socket used by the server.
.It Ic logo Ar path
socket.
.Bd -literal -offset indent
server "localhost" {
- listen on socket off
listen on 127.0.0.1 port 9000
listen on ::1 port 9000
}
blob - 207c4dbc424493d3ff719acc1447d3cad5906547
blob + a0fde1eafb66028107363d6beae5bb5acc7fd2a5
--- gotwebd/gotwebd.h
+++ gotwebd/gotwebd.h
int show_repo_description;
int show_repo_cloneurl;
int respect_exportok;
-
- int unix_socket;
- char unix_socket_name[PATH_MAX];
-
- int fcgi_socket;
};
TAILQ_HEAD(serverlist, server);
struct socket_conf {
struct address addr;
- char name[GOTWEBD_MAXTEXT];
- char srv_name[GOTWEBD_MAXTEXT];
-
int id;
int af_type;
char unix_socket_name[PATH_MAX];
struct gotwebd {
struct serverlist servers;
struct socketlist sockets;
+ struct addresslist addresses;
const char *gotwebd_conffile;
char httpd_chroot[PATH_MAX];
- int unix_socket;
char unix_socket_name[PATH_MAX];
};
blob - 11a62a33f5dcf8dbf78a22fe7030c3d1848b689c
blob + 11da7e60c5c605bd07cb1abcbca71e6c7c4d6044
--- gotwebd/parse.y
+++ gotwebd/parse.y
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/stat.h>
+#include <sys/un.h>
#include <net/if.h>
#include <netinet/in.h>
int n;
int get_addrs(const char *, const char *, struct server *);
-int addr_dup_check(struct addresslist *, struct address *,
- const char *, const char *);
+int get_unix_addr(const char *, struct server *);
+int addr_dup_check(struct addresslist *, struct address *);
int add_addr(struct server *, struct address *);
typedef struct {
%token LOGO_URL SHOW_REPO_OWNER SHOW_REPO_AGE SHOW_REPO_DESCRIPTION
%token MAX_REPOS_DISPLAY REPOS_PATH MAX_COMMITS_DISPLAY ON ERROR
%token SHOW_SITE_OWNER SHOW_REPO_CLONEURL PORT PREFORK RESPECT_EXPORTOK
-%token UNIX_SOCKET UNIX_SOCKET_NAME SERVER CHROOT CUSTOM_CSS SOCKET
+%token UNIX_SOCKET_NAME SERVER CHROOT CUSTOM_CSS SOCKET
%token SUMMARY_COMMITS_DISPLAY SUMMARY_TAGS_DISPLAY
%token <v.string> STRING
}
free($2);
}
- | UNIX_SOCKET boolean {
- gotwebd->unix_socket = $2;
- }
| UNIX_SOCKET_NAME STRING {
n = snprintf(gotwebd->unix_socket_name,
sizeof(gotwebd->unix_socket_name), "%s%s",
}
free($3);
free($5);
- new_srv->fcgi_socket = 1;
}
| LISTEN ON listen_addr PORT NUMBER {
char portno[32];
YYERROR;
}
free($3);
- new_srv->fcgi_socket = 1;
}
| LISTEN ON SOCKET STRING {
- if (strcasecmp($4, "off") == 0) {
- new_srv->unix_socket = 0;
- free($4);
- YYACCEPT;
- }
-
- new_srv->unix_socket = 1;
-
- n = snprintf(new_srv->unix_socket_name,
- sizeof(new_srv->unix_socket_name), "%s%s",
- gotwebd->httpd_chroot, $4);
- if (n < 0 ||
- (size_t)n >= sizeof(new_srv->unix_socket_name)) {
- yyerror("%s: unix_socket_name truncated",
- __func__);
+ if (get_unix_addr($4, new_srv) == -1) {
+ yyerror("can't listen on %s", $4);
free($4);
YYERROR;
}
{ "socket", SOCKET },
{ "summary_commits_display", SUMMARY_COMMITS_DISPLAY },
{ "summary_tags_display", SUMMARY_TAGS_DISPLAY },
- { "unix_socket", UNIX_SOCKET },
{ "unix_socket_name", UNIX_SOCKET_NAME },
};
const struct keywords *p;
parse_config(const char *filename, struct gotwebd *env)
{
struct sym *sym, *next;
+ struct server *srv;
+ int n;
if (config_init(env) == -1)
fatalx("failed to initialize configuration");
gotwebd = env;
+ n = snprintf(env->unix_socket_name, sizeof(env->unix_socket_name),
+ "%s%s", D_HTTPD_CHROOT, D_UNIX_SOCKET);
+ if (n < 0 || (size_t)n >= sizeof(env->unix_socket_name))
+ fatalx("%s: snprintf", __func__);
+
file = newfile(filename, 0);
if (file == NULL) {
add_default_server();
}
}
- if (errors)
- return (-1);
-
/* just add default server if no config specified */
if (gotwebd->server_cnt == 0)
add_default_server();
+ /* add the implicit listen on socket where missing */
+ TAILQ_FOREACH(srv, &gotwebd->servers, entry) {
+ if (!TAILQ_EMPTY(&srv->al))
+ continue;
+ if (get_unix_addr(env->unix_socket_name, srv) == -1)
+ yyerror("can't listen on %s", env->unix_socket_name);
+ }
+
+ if (errors)
+ return (-1);
+
/* setup our listening sockets */
sockets_parse_sockets(env);
n = strlcpy(srv->name, name, sizeof(srv->name));
if (n >= sizeof(srv->name))
fatalx("%s: strlcpy", __func__);
- n = snprintf(srv->unix_socket_name,
- sizeof(srv->unix_socket_name), "%s%s", D_HTTPD_CHROOT,
- D_UNIX_SOCKET);
- if (n < 0 || (size_t)n >= sizeof(srv->unix_socket_name))
- fatalx("%s: snprintf", __func__);
n = strlcpy(srv->repos_path, D_GOTPATH,
sizeof(srv->repos_path));
if (n >= sizeof(srv->repos_path))
srv->summary_commits_display = D_MAXSLCOMMDISP;
srv->summary_tags_display = D_MAXSLTAGDISP;
- srv->unix_socket = 1;
- srv->fcgi_socket = 0;
-
TAILQ_INIT(&srv->al);
TAILQ_INSERT_TAIL(&gotwebd->servers, srv, entry);
gotwebd->server_cnt++;
}
int
-addr_dup_check(struct addresslist *al, struct address *h, const char *new_srv,
- const char *other_srv)
+get_unix_addr(const char *path, struct server *new_srv)
{
+ struct address *h;
+ struct sockaddr_un *sun;
+
+ if ((h = calloc(1, sizeof(*h))) == NULL)
+ fatal("%s: calloc", __func__);
+
+ h->ai_family = AF_UNIX;
+ h->ai_socktype = SOCK_STREAM;
+ h->ai_protocol = PF_UNSPEC;
+ h->slen = sizeof(*sun);
+
+ sun = (struct sockaddr_un *)&h->ss;
+ sun->sun_family = AF_UNIX;
+ if (strlcpy(sun->sun_path, path, sizeof(sun->sun_path)) >=
+ sizeof(sun->sun_path)) {
+ log_warnx("socket path too long: %s", sun->sun_path);
+ return (-1);
+ }
+
+ return add_addr(new_srv, h);
+}
+
+int
+addr_dup_check(struct addresslist *al, struct address *h)
+{
struct address *a;
- void *ia;
- char buf[INET6_ADDRSTRLEN];
- const char *addrstr;
TAILQ_FOREACH(a, al, entry) {
if (a->ai_family != h->ai_family ||
a->slen != h->slen ||
memcmp(&a->ss, &h->ss, a->slen) != 0)
continue;
-
- switch (h->ss.ss_family) {
- case AF_INET:
- ia = &((struct sockaddr_in *)(&h->ss))->sin_addr;
- break;
- case AF_INET6:
- ia = &((struct sockaddr_in6 *)(&h->ss))->sin6_addr;
- break;
- default:
- yyerror("unknown address family: %d", h->ss.ss_family);
- return -1;
- }
- addrstr = inet_ntop(h->ss.ss_family, ia, buf, sizeof(buf));
- if (addrstr) {
- if (other_srv) {
- yyerror("server %s: duplicate fcgi listen "
- "address %s:%d, already used by server %s",
- new_srv, addrstr, h->port, other_srv);
- } else {
- log_warnx("server: %s: duplicate fcgi listen "
- "address %s:%d", new_srv, addrstr, h->port);
- }
- } else {
- if (other_srv) {
- yyerror("server: %s: duplicate fcgi listen "
- "address, already used by server %s",
- new_srv, other_srv);
- } else {
- log_warnx("server %s: duplicate fcgi listen "
- "address", new_srv);
- }
- }
-
return -1;
}
add_addr(struct server *new_srv, struct address *h)
{
struct server *srv;
+ struct address *dup;
- /* Address cannot be shared between different servers. */
TAILQ_FOREACH(srv, &gotwebd->servers, entry) {
- if (srv == new_srv)
- continue;
- if (addr_dup_check(&srv->al, h, new_srv->name, srv->name))
- return -1;
+ if (addr_dup_check(&srv->al, h) == -1) {
+ free(h);
+ return 0;
+ }
}
- /* Tolerate duplicate address lines within the scope of a server. */
- if (addr_dup_check(&new_srv->al, h, NULL, NULL) == 0)
- TAILQ_INSERT_TAIL(&new_srv->al, h, entry);
- else
- free(h);
+ if (addr_dup_check(&gotwebd->addresses, h) == 0) {
+ if ((dup = calloc(1, sizeof(*dup))) == NULL)
+ fatal("%s: calloc", __func__);
+ memcpy(dup, h, sizeof(*dup));
+ TAILQ_INSERT_TAIL(&gotwebd->addresses, dup, entry);
+ }
- return 0;
+ TAILQ_INSERT_TAIL(&new_srv->al, h, entry);
+ return (0);
}
blob - e69a8e9f0c23d323ad013f7751187f5a401d5fa1
blob + 86ecfa5f85dfca0b2c75426a47d930b7e9f29e50
--- gotwebd/sockets.c
+++ gotwebd/sockets.c
static int sockets_accept_reserve(int, struct sockaddr *, socklen_t *,
int, volatile int *);
-static struct socket *sockets_conf_new_socket_unix(struct gotwebd *,
- struct server *, int);
-static struct socket *sockets_conf_new_socket_fcgi(struct gotwebd *,
- struct server *, int, struct address *);
+static struct socket *sockets_conf_new_socket(struct gotwebd *,
+ int, struct address *);
int cgi_inflight = 0;
void
sockets_parse_sockets(struct gotwebd *env)
{
- struct server *srv;
struct address *a;
struct socket *new_sock = NULL;
int sock_id = 1;
- TAILQ_FOREACH(srv, &env->servers, entry) {
- if (srv->unix_socket) {
- new_sock = sockets_conf_new_socket_unix(env, srv,
- sock_id);
- if (new_sock) {
- sock_id++;
- TAILQ_INSERT_TAIL(&env->sockets, new_sock,
- entry);
- }
+ TAILQ_FOREACH(a, &env->addresses, entry) {
+ new_sock = sockets_conf_new_socket(env, sock_id, a);
+ if (new_sock) {
+ sock_id++;
+ TAILQ_INSERT_TAIL(&env->sockets,
+ new_sock, entry);
}
-
- if (srv->fcgi_socket) {
- if (TAILQ_EMPTY(&srv->al)) {
- fatalx("%s: server %s has no IP addresses to "
- "listen for FCGI connections", __func__,
- srv->name);
- }
- TAILQ_FOREACH(a, &srv->al, entry) {
- if (a->ss.ss_family != AF_INET &&
- a->ss.ss_family != AF_INET6)
- continue;
- new_sock = sockets_conf_new_socket_fcgi(env,
- srv, sock_id, a);
- if (new_sock) {
- sock_id++;
- TAILQ_INSERT_TAIL(&env->sockets,
- new_sock, entry);
- }
- }
- }
- }
-}
-
-static struct socket *
-sockets_conf_new_socket_unix(struct gotwebd *env, struct server *srv, int id)
-{
- struct socket *sock;
- int n;
-
- if ((sock = calloc(1, sizeof(*sock))) == NULL)
- fatalx("%s: calloc", __func__);
-
- sock->conf.id = id;
- sock->fd = -1;
- sock->conf.af_type = AF_UNIX;
-
- if (strlcpy(sock->conf.unix_socket_name,
- srv->unix_socket_name,
- sizeof(sock->conf.unix_socket_name)) >=
- sizeof(sock->conf.unix_socket_name)) {
- free(sock);
- fatalx("%s: strlcpy", __func__);
- }
-
- n = snprintf(sock->conf.name, GOTWEBD_MAXTEXT, "%s_parent",
- srv->name);
- if (n < 0 || (size_t)n >= GOTWEBD_MAXTEXT) {
- free(sock);
- fatalx("%s: snprintf", __func__);
}
-
- if (strlcpy(sock->conf.srv_name, srv->name,
- sizeof(sock->conf.srv_name)) >= sizeof(sock->conf.srv_name)) {
- free(sock);
- fatalx("%s: strlcpy", __func__);
- }
-
- return sock;
}
static struct socket *
-sockets_conf_new_socket_fcgi(struct gotwebd *env, struct server *srv, int id,
- struct address *a)
+sockets_conf_new_socket(struct gotwebd *env, int id, struct address *a)
{
struct socket *sock;
struct address *acp;
- int n;
if ((sock = calloc(1, sizeof(*sock))) == NULL)
fatalx("%s: calloc", __func__);
sock->fd = -1;
sock->conf.af_type = a->ss.ss_family;
- sock->conf.fcgi_socket_port = a->port;
+ if (a->ss.ss_family == AF_UNIX) {
+ struct sockaddr_un *sun;
- n = snprintf(sock->conf.name, GOTWEBD_MAXTEXT, "%s_parent",
- srv->name);
- if (n < 0 || (size_t)n >= GOTWEBD_MAXTEXT) {
- free(sock);
- fatalx("%s: snprintf", __func__);
+ sun = (struct sockaddr_un *)&a->ss;
+ if (strlcpy(sock->conf.unix_socket_name, sun->sun_path,
+ sizeof(sock->conf.unix_socket_name)) >=
+ sizeof(sock->conf.unix_socket_name))
+ fatalx("unix socket path too long: %s", sun->sun_path);
}
- if (strlcpy(sock->conf.srv_name, srv->name,
- sizeof(sock->conf.srv_name)) >= sizeof(sock->conf.srv_name)) {
- free(sock);
- fatalx("%s: strlcpy", __func__);
- }
+ sock->conf.fcgi_socket_port = a->port;
acp = &sock->conf.addr;
}
if (sock->conf.af_type == AF_INET || sock->conf.af_type == AF_INET6) {
- log_debug("%s: initializing %s FCGI socket on port %d for %s",
+ log_debug("%s: initializing %s FCGI socket on port %d",
__func__, sock->conf.af_type == AF_INET ? "inet" : "inet6",
- sock->conf.fcgi_socket_port, sock->conf.name);
+ sock->conf.fcgi_socket_port);
sock->fd = sockets_create_socket(&sock->conf.addr);
if (sock->fd == -1) {
log_warnx("%s: create FCGI socket failed", __func__);
static int
sockets_unix_socket_listen(struct gotwebd *env, struct socket *sock)
{
- struct sockaddr_un sun;
- struct socket *tsock;
int u_fd = -1;
mode_t old_umask, mode;
- TAILQ_FOREACH(tsock, &env->sockets, entry) {
- if (strcmp(tsock->conf.unix_socket_name,
- sock->conf.unix_socket_name) == 0 &&
- tsock->fd != -1)
- return (tsock->fd);
- }
-
- /* TA: FIXME: this needs upstreaming. */
- int socket_flags = SOCK_STREAM | SOCK_NONBLOCK;
-#ifdef SOCK_CLOEXEC
- socket_flags |= SOCK_CLOEXEC;
-#endif
- u_fd = socket(AF_UNIX, socket_flags, 0);
+ u_fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK| SOCK_CLOEXEC, 0);
if (u_fd == -1) {
log_warn("%s: socket", __func__);
return -1;
}
- sun.sun_family = AF_UNIX;
- if (strlcpy(sun.sun_path, sock->conf.unix_socket_name,
- sizeof(sun.sun_path)) >= sizeof(sun.sun_path)) {
- log_warn("%s: %s name too long", __func__,
- sock->conf.unix_socket_name);
- close(u_fd);
- return -1;
- }
-
if (unlink(sock->conf.unix_socket_name) == -1) {
if (errno != ENOENT) {
log_warn("%s: unlink %s", __func__,
old_umask = umask(S_IXUSR|S_IXGRP|S_IWOTH|S_IROTH|S_IXOTH);
mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP;
- if (bind(u_fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
+ if (bind(u_fd, (struct sockaddr *)&sock->conf.addr.ss,
+ sock->conf.addr.slen) == -1) {
log_warn("%s: bind: %s", __func__, sock->conf.unix_socket_name);
close(u_fd);
(void)umask(old_umask);