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>2021-09-08 02:01:24 +0200
commit553ebab10f3ae777a55b10e2da0595c82cb06819 (patch)
tree4e5616e810925c25a3ff3e24cc5d996826605a02
parent15346de8d3ba422002496526ee24c62a3601ab8c (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. Signed-off-by: Mikael Magnusson <mikma@users.sourceforge.net>
-rw-r--r--listen.c7
-rw-r--r--main.c18
-rw-r--r--uhttpd.h2
3 files changed, 21 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 73e3d42..8f51813 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"
+ " 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"
@@ -256,6 +258,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);
@@ -263,7 +266,7 @@ int main(int argc, char **argv)
init_defaults_pre();
signal(SIGPIPE, SIG_IGN);
- while ((ch = getopt(argc, argv, "A:aC:c:Dd:E:e:fh:H:I:i:K:k:L:l:m:N:n:P:p:qRr:Ss:T:t:U:u:Xx:y:")) != -1) {
+ while ((ch = getopt(argc, argv, "A:abC:c:Dd:E:e:fh:H:I:i:K:k:L:l:m:N:n:P:p:qRr:Ss:T:t:U:u:Xx:y:")) != -1) {
switch(ch) {
#ifdef HAVE_TLS
case 'C':
@@ -282,6 +285,13 @@ int main(int argc, char **argv)
conf.tls_redirect = 1;
break;
+ case 'b':
+ if (optarg[0] == '\0')
+ device = NULL;
+ else
+ device = optarg;
+ break;
+
case 's':
n_tls++;
/* fall through */
@@ -297,7 +307,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':
diff --git a/uhttpd.h b/uhttpd.h
index e61e176..77273a7 100644
--- a/uhttpd.h
+++ b/uhttpd.h
@@ -289,7 +289,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);