Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Socket activation #26

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion configuration.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ static int readConfigTime(xmlTextReaderPtr reader, time_t * value, const char *

static int configListen(WebdavdConfiguration * config, xmlTextReaderPtr reader, const char * configFile) {
//<listen><port>80</port><host>localhost</host><encryption>disabled</encryption></listen>
//<listen><name>http<name/></listen>
int index = config->daemonCount++;
config->daemons = reallocSafe(config->daemons, sizeof(*config->daemons) * config->daemonCount);
memset(&config->daemons[index], 0, sizeof(config->daemons[index]));
Expand All @@ -90,6 +91,8 @@ static int configListen(WebdavdConfiguration * config, xmlTextReaderPtr reader,
result = readConfigInt(reader, &config->daemons[index].port, configFile);
} else if (!strcmp(xmlTextReaderConstLocalName(reader), "host")) {
result = readConfigString(reader, &config->daemons[index].host);
} else if (!strcmp(xmlTextReaderConstLocalName(reader), "name")) {
result = readConfigString(reader, &config->daemons[index].name);
} else if (!strcmp(xmlTextReaderConstLocalName(reader), "encryption")) {
const char * encryptionString;
result = stepOverText(reader, &encryptionString);
Expand Down Expand Up @@ -148,7 +151,7 @@ static int configListen(WebdavdConfiguration * config, xmlTextReaderPtr reader,
result = stepOver(reader);
}
}
if (config->daemons[index].port == -1) {
if (!config->socketActivation && config->daemons[index].port == -1) {
stdLogError(0, "port not specified for listen in %s", configFile);
exit(1);
}
Expand Down Expand Up @@ -282,6 +285,17 @@ static int configUnprotectOptions(WebdavdConfiguration * config, xmlTextReaderPt
return result;
}

static int configSocketActivation(WebdavdConfiguration * config, xmlTextReaderPtr reader, const char * configFile) {
// <socket-activation />
#ifdef HAVE_SYSTEMD
config->socketActivation = true;
return stepOver(reader);
#else
stdLogError(0, "Socket activation support not enable at build time");
return false;
#endif
}

///////////////////////////
// End Handler Functions //
///////////////////////////
Expand Down Expand Up @@ -314,6 +328,7 @@ static const ConfigurationFunction configFunctions[] = {
{ .nodeName = "rap-timeout", .func = &configRapTimeout }, // <rap-timeout />
{ .nodeName = "restricted", .func = &configRestricted }, // <restricted />
{ .nodeName = "session-timeout", .func = &configSessionTimeout }, // <session-timeout />
{ .nodeName = "socket-activation", .func = &configSocketActivation }, // <socket-activation />
{ .nodeName = "ssl-cert", .func = &configConfigSSLCert }, // <ssl-cert />
{ .nodeName = "static-response-dir", .func = &configResponseDir }, // <static-response-dir />
{ .nodeName = "unprotect-options", .func = &configUnprotectOptions } // <unprotect-options />
Expand Down
7 changes: 6 additions & 1 deletion configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@
#define WEBDAV_CONFIGURATION_H

#include <time.h>
#include <stdbool.h>

//////////////////////////////////////
// Webdavd Configuration Structures //
//////////////////////////////////////

typedef struct DaemonConfig {
int port;
const char * host;
const char * host; // For opening socket ourselves
const char * name; // For socket activation, i.e. open socket passed to daemon
int sslEnabled;
int forwardToIsEncrypted;
int forwardToPort;
Expand Down Expand Up @@ -55,6 +57,9 @@ typedef struct WebdavdConfiguration {
// OPTIONS Requests
int unprotectOptions;

// Use systemd/xinetd style socket based activation
bool socketActivation;

} WebdavdConfiguration;

extern WebdavdConfiguration config;
Expand Down
9 changes: 7 additions & 2 deletions makefile
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
CFLAGS=-O3 -s
STATIC_FLAGS=-Werror -Wall -Wno-pointer-sign -Wno-unused-result -std=gnu99 -pthread

ifdef HAVE_SYSTEMD
DEFS+=-DHAVE_SYSTEMD=1
LIBSYSTEMD=-lsystemd
endif

all: build/rap build/webdavd
ls -lh $^

build/webdavd: build/webdavd.o build/shared.o build/configuration.o build/xml.o
gcc ${CFLAGS} ${STATIC_FLAGS} -o $@ $(filter %.o,$^) -lmicrohttpd -lxml2 -lgnutls -luuid
gcc ${CFLAGS} ${STATIC_FLAGS} -o $@ $(filter %.o,$^) -lmicrohttpd -lxml2 -lgnutls -luuid ${LIBSYSTEMD}

build/rap: build/rap.o build/shared.o build/xml.o
gcc ${CFLAGS} ${STATIC_FLAGS} -o $@ $(filter %.o,$^) -lpam -lxml2

build/%.o: %.c makefile | build
gcc ${CFLAGS} ${STATIC_FLAGS} -MMD -o $@ $(filter %.c,$^) -I/usr/include/libxml2 -c
gcc ${CFLAGS} ${STATIC_FLAGS} ${DEFS} -MMD -o $@ $(filter %.c,$^) -I/usr/include/libxml2 -c

build:
mkdir $@
Expand Down
5 changes: 4 additions & 1 deletion package-control/webdavd.spec
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ BuildRequires: libxml2-devel
BuildRequires: pam-devel
BuildRequires: libuuid-devel
BuildRequires: make
BuildRequires: systemd-devel

Requires: gnutls
Requires: libmicrohttpd
Expand All @@ -36,7 +37,7 @@ webdavd is a WebDAV server designed to be a replace for SMBA providing access to
%setup -n WebDAV-Daemon-%{version}

%build
%make_build
%make_build HAVE_SYSTEMD=1

%install
install -Dpm 755 build/webdavd %{buildroot}%{_sbindir}/webdavd
Expand All @@ -46,6 +47,7 @@ install -Dpm 644 package-with/conf.xml %{buildroot}%{_sysconfdir}/webdavd
install -d %{buildroot}%{_datadir}/webdavd
install -Dpm 644 package-with/share/* %{buildroot}%{_datadir}/webdavd
install -Dpm 644 package-with/systemd.service %{buildroot}%{_prefix}/lib/systemd/system/webdavd.service
install -Dpm 644 package-with/webdavd-*.socket %{buildroot}%{_prefix}/lib/systemd/system
install -Dpm 644 package-with/logrotate.conf %{buildroot}%{_sysconfdir}/logrotate.d/webdavd


Expand All @@ -57,6 +59,7 @@ install -Dpm 644 package-with/logrotate.conf %{buildroot}%{_sysconfdir}/logrotat
%{_prefix}/lib/webdavd/webdav-worker
%{_datadir}/webdavd/*
%{_prefix}/lib/systemd/system/webdavd.service
%{_prefix}/lib/systemd/system/webdavd-*.socket
%config %{_sysconfdir}/pam.d/webdavd
%config %{_sysconfdir}/webdavd
%config %{_sysconfdir}/logrotate.d/webdavd
Expand Down
20 changes: 20 additions & 0 deletions package-with/conf.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,18 @@
default port. Default host "any ip". Default encryption is "none". The following
will listening on all ips and be unencrypted -->

<!-- One may use socket based activation, as with a systemd .socket unit or inetd. This
method has systemd open the port(s) listed in the socket units and it will start
webdavd only when a connection is made. The ports, hostnames, UNIX domain socket
pathnames, interfaces bound to, and other options, many of which webdavd does not
support natively, are set in the systemd socket unit(s), see systemd.socket(5).

When using this, the port and host in a listen section will be ignored and may be
omitted. The port(s) from the socket units will be matched to the listen section(s)
in order. Or, FileDescriptorName can be specified in the system socket units and a
matching <name> specified in the <listen> section(s). -->
<!-- <socket-activation /> -->

<listen>

<port>80</port>
Expand All @@ -17,6 +29,11 @@
be convertied to an IP before binding. -->
<!-- <host>myHost.domain.tld</host> -->

<!-- When using socket based activation, described near the socket-activation tag,
the port and host above are not used. A name can be specified here and will
be matched to the "FileDescriptorName" in the systemd socket unit. -->
<name>http</name>

<encryption>none</encryption>

<!-- It is NOT recomended to host content on unencrypted chanels. So this
Expand Down Expand Up @@ -45,6 +62,9 @@

<port>443</port>

<!-- When using socket activation, match name from socket unit and ignore port. -->
<name>https</name>

<!-- Only "none" and "ssl" are currently supported. Encrypting with SSL
requires one or more <ssl-cert> certificates (see below) -->

Expand Down
14 changes: 14 additions & 0 deletions package-with/webdavd-http.socket
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[Unit]
Description=WebDAV server on HTTP socket

[Socket]
Accept=no
ListenStream=80
FileDescriptorName=http
DeferAcceptSec=1
Service=webdavd.service
# Add this to only allow connections over localhost
# BindToDevice=lo

[Install]
WantedBy=sockets.target
14 changes: 14 additions & 0 deletions package-with/webdavd-https.socket
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[Unit]
Description=WebDAV server on HTTPS socket

[Socket]
Accept=no
ListenStream=443
FileDescriptorName=https
DeferAcceptSec=1
Service=webdavd.service
# Add this to only allow connections over localhost
# BindToDevice=lo

[Install]
WantedBy=sockets.target
Loading