summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorRuss Allbery <rra@stanford.edu>2011-05-31 11:10:52 -0700
committerRuss Allbery <rra@stanford.edu>2011-05-31 11:10:52 -0700
commit9146c651aac62b607fb42f804da246f5ea1b6731 (patch)
tree477b57f77cce67ef0237678aacc62a8276b17692 /server
parent8becfde7f614dca33eff4f0c879252df09e2afc4 (diff)
Add support for a -b server flag to set the bind address
The remctld server now supports a -b command-line option specifying which local addresses to which to bind. This option may be given multiple times to bind to multiple local addresses.
Diffstat (limited to 'server')
-rw-r--r--server/remctld.c56
1 files changed, 51 insertions, 5 deletions
diff --git a/server/remctld.c b/server/remctld.c
index 18a0053..d31d0d3 100644
--- a/server/remctld.c
+++ b/server/remctld.c
@@ -28,6 +28,8 @@
#include <util/macros.h>
#include <util/messages.h>
#include <util/network.h>
+#include <util/vector.h>
+#include <util/xmalloc.h>
/*
* Flag indicating whether we've received a SIGCHLD and need to reap children
@@ -74,6 +76,7 @@ struct options {
char *service;
const char *config_path;
const char *pid_path;
+ struct vector *bindaddrs;
};
@@ -234,6 +237,26 @@ server_log_child(pid_t pid, int status)
/*
+ * Given a bind address, return true if it's an IPv6 address. Otherwise, it's
+ * assumed to be an IPv4 address.
+ */
+#ifdef HAVE_INET6
+static bool
+is_ipv6(const char *string)
+{
+ struct in6_addr addr;
+ return inet_pton(AF_INET6, string, &addr) == 1;
+}
+#else
+static bool
+is_ipv6(const char *string UNUSED)
+{
+ return false;
+}
+#endif
+
+
+/*
* Run as a daemon. This is the main dispatch loop, which listens for network
* connections, forks a child to process each connection, and reaps the
* children when they're done. This is only used in standalone mode; when run
@@ -246,6 +269,7 @@ server_daemon(struct options *options, struct config *config,
socket_type s;
unsigned int nfds, i;
socket_type *fds;
+ const char *addr;
pid_t child;
int status;
struct sigaction sa, oldsa;
@@ -278,10 +302,24 @@ server_daemon(struct options *options, struct config *config,
notice("starting");
/* Bind to the network sockets and configure listening addresses. */
- nfds = 0;
- network_bind_all(options->port, &fds, &nfds);
- if (nfds == 0)
- sysdie("cannot bind any sockets");
+ if (options->bindaddrs->count == 0) {
+ nfds = 0;
+ network_bind_all(options->port, &fds, &nfds);
+ if (nfds == 0)
+ sysdie("cannot bind any sockets");
+ } else {
+ nfds = options->bindaddrs->count;
+ fds = xmalloc(nfds * sizeof(socket_type));
+ for (i = 0; i < options->bindaddrs->count; i++) {
+ addr = options->bindaddrs->strings[i];
+ if (is_ipv6(addr))
+ fds[i] = network_bind_ipv6(addr, options->port);
+ else
+ fds[i] = network_bind_ipv4(addr, options->port);
+ if (fds[i] == INVALID_SOCKET)
+ sysdie("cannot bind to address %s", addr);
+ }
+ }
for (i = 0; i < nfds; i++)
if (listen(fds[i], 5) < 0)
sysdie("error listening on socket (fd %d)", fds[i]);
@@ -386,10 +424,14 @@ main(int argc, char *argv[])
options.service = NULL;
options.pid_path = NULL;
options.config_path = CONFIG_FILE;
+ options.bindaddrs = vector_new();
/* Parse options. */
- while ((option = getopt(argc, argv, "dFf:hk:mP:p:Ss:v")) != EOF) {
+ while ((option = getopt(argc, argv, "b:dFf:hk:mP:p:Ss:v")) != EOF) {
switch (option) {
+ case 'b':
+ vector_add(options.bindaddrs, optarg);
+ break;
case 'd':
options.debug = true;
break;
@@ -431,6 +473,10 @@ main(int argc, char *argv[])
}
}
+ /* Check arguments for consistency. */
+ if (options.bindaddrs->count > 0 && !options.standalone)
+ die("-b only makes sense in combination with -m");
+
/* Daemonize if told to do so. */
if (options.standalone && !options.foreground)
daemon(0, options.log_stdout);