summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikael Magnusson <mikma@users.sourceforge.net>2021-09-02 01:10:43 +0200
committerMikael Magnusson <mikma@users.sourceforge.net>2022-04-28 00:26:20 +0200
commit6e1305cd48e44358a5bd1053c7335982e2c99f87 (patch)
tree045f60f73dd66b6e5f5ad906d83bbca5e2fe41dc
parent5f9ae5738372aaa3a6be2f0a278933563d3f191a (diff)
uhttpd: add SO_BINDTODEVICE support
Add command line option "-b <interface>" which binds the ports (and addresses) in the following "-p" and "-s" options to the specified network interface with SO_BINDTODEVICE. Using SO_BINDTODEVICE means uhttpd will only accept incoming traffic from the specified network interface. Or in case a VRF interface is used, from the interfaces associated with the VRF. Signed-off-by: Mikael Magnusson <mikma@users.sourceforge.net>
-rw-r--r--listen.c7
-rw-r--r--main.c22
-rw-r--r--uhttpd.h2
3 files changed, 25 insertions, 6 deletions
diff --git a/listen.c b/listen.c
index 2a54888..908127a 100644
--- a/listen.c
+++ b/listen.c
@@ -128,7 +128,7 @@ void uh_setup_listeners(void)
}
}
-int uh_socket_bind(const char *host, const char *port, bool tls)
+int uh_socket_bind(const char *host, const char *port, const char *device, bool tls)
{
int sock = -1;
int yes = 1;
@@ -169,6 +169,11 @@ int uh_socket_bind(const char *host, const char *port, bool tls)
goto error;
}
+ if (device && setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device)) < 0) {
+ perror("setsockopt()");
+ goto error;
+ }
+
/* bind */
if (bind(sock, p->ai_addr, p->ai_addrlen) < 0) {
perror("bind()");
diff --git a/main.c b/main.c
index 6c29afe..fede07c 100644
--- a/main.c
+++ b/main.c
@@ -103,7 +103,7 @@ static void uh_config_parse(void)
fclose(c);
}
-static int add_listener_arg(char *arg, bool tls)
+static int add_listener_arg(char *arg, const char *device, bool tls)
{
char *host = NULL;
char *port = arg;
@@ -125,7 +125,7 @@ static int add_listener_arg(char *arg, bool tls)
}
}
- return uh_socket_bind(host, port, tls);
+ return uh_socket_bind(host, port, device, tls);
}
static int usage(const char *name)
@@ -134,6 +134,8 @@ static int usage(const char *name)
"Usage: %s -p [addr:]port -h docroot\n"
" -f Do not fork to background\n"
" -c file Configuration file, default is '/etc/httpd.conf'\n"
+ " -b interface Bind subsequent ports (and addresses) to specified\n"
+ " network interface with SO_BINDTODEVICE\n"
" -p [addr:]port Bind to specified address and port, multiple allowed\n"
#ifdef HAVE_TLS
" -s [addr:]port Like -p but provide HTTPS on this port\n"
@@ -254,6 +256,7 @@ int main(int argc, char **argv)
#ifdef HAVE_LUA
const char *lua_prefix = NULL, *lua_handler = NULL;
#endif
+ char *device = NULL;
BUILD_BUG_ON(sizeof(uh_buf) < PATH_MAX);
@@ -261,7 +264,7 @@ int main(int argc, char **argv)
init_defaults_pre();
signal(SIGPIPE, SIG_IGN);
- while ((ch = getopt(argc, argv, "A:aC:c:Dd:E:fh:H:I:i:K:k:L:l:m:N:n:p:qRr:Ss:T:t:U:u:Xx:y:")) != -1) {
+ while ((ch = getopt(argc, argv, "A:ab:C:c:Dd:E:fh:H:I:i:K:k:L:l:m:N:n:p:qRr:Ss:T:t:U:u:Xx:y:")) != -1) {
switch(ch) {
#ifdef HAVE_TLS
case 'C':
@@ -276,6 +279,14 @@ int main(int argc, char **argv)
conf.tls_redirect = 1;
break;
+ case 'b':
+ free(device);
+ if (optarg[0] == '\0')
+ device = NULL;
+ else
+ device = strdup(optarg);
+ break;
+
case 's':
n_tls++;
/* fall through */
@@ -290,7 +301,7 @@ int main(int argc, char **argv)
#endif
case 'p':
optarg = strdup(optarg);
- bound += add_listener_arg(optarg, (ch == 's'));
+ bound += add_listener_arg(optarg, device, (ch == 's'));
break;
case 'h':
@@ -542,6 +553,9 @@ int main(int argc, char **argv)
return 1;
#endif
+ free(device);
+ device = NULL;
+
/* fork (if not disabled) */
if (!nofork) {
switch (fork()) {
diff --git a/uhttpd.h b/uhttpd.h
index f77718e..925b7bb 100644
--- a/uhttpd.h
+++ b/uhttpd.h
@@ -284,7 +284,7 @@ bool uh_accept_client(int fd, bool tls);
void uh_unblock_listeners(void);
void uh_setup_listeners(void);
-int uh_socket_bind(const char *host, const char *port, bool tls);
+int uh_socket_bind(const char *host, const char *port, const char *device, bool tls);
int uh_first_tls_port(int family);