summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@gmail.com>2013-11-04 09:48:33 +0100
committerDavid Herrmann <dh.herrmann@gmail.com>2013-11-04 09:48:33 +0100
commita03e95ff50e9d63f7415c5f67c1b51d250a51ca7 (patch)
treec5b8ce0dff735edfccec92a9b81f231e25319212
parentc1fe726970fc85118730f041c1721598eeed2f68 (diff)
owfd: dhcp: add dhcp helpers skeleton
All known dhcp daemons have horrible interfaces if you want to use them for short-lived ad-hoc networks like Wifi-P2P. Therefore, we use our own helper with gdhcp as DHCP implementation. openwfd_dhcp implements a DHCP server and daemon. Depending in the given command-line argument, it is run as either. All configuration parameters are passed via command-line. Note that openwfd_dhcp is a workaround and should only be used as such. Once network-managers pick up proper Wifi-P2P APIs, we can remove openwfd_p2pd (including openwfd_dhcp) and start using their APIs. Until then, we need this small hack. This patch only adds the dhcp skeleton. No real functionality is added, yet. Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
-rw-r--r--.gitignore1
-rw-r--r--Makefile.am24
-rw-r--r--configure.ac8
-rw-r--r--src/dhcp.c205
-rw-r--r--src/dhcp.h66
-rw-r--r--src/dhcp_config.c354
6 files changed, 657 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
index d50f367..c371dc8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,6 +21,7 @@ config.status
configure
libtool
m4/
+openwfd_dhcp
openwfd_ie
openwfd_p2pd
stamp-h1
diff --git a/Makefile.am b/Makefile.am
index d1aa135..6f78a38 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -62,7 +62,8 @@ AM_LDFLAGS = \
AM_CPPFLAGS += \
-DBUILD_ENABLE_DEBUG \
- "-DBUILD_BINDIR_WPA_SUPPLICANT=\"/bin\""
+ "-DBUILD_BINDIR_WPA_SUPPLICANT=\"/bin\"" \
+ "-DBUILD_BINDIR_IP=\"/bin\""
#
# SHL - Static Helper Library
@@ -142,6 +143,27 @@ openwfd_p2pd_LDADD = \
openwfd_p2pd_LDFLAGS = $(AM_LDFLAGS)
#
+# openwfd_dhcp
+#
+
+bin_PROGRAMS += openwfd_dhcp
+
+openwfd_dhcp_SOURCES = \
+ src/dhcp.h \
+ src/dhcp.c \
+ src/dhcp_config.c
+
+openwfd_dhcp_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ $(DHCP_CFLAGS)
+openwfd_dhcp_LDADD = \
+ $(DHCP_LIBS) \
+ libgdhcp.la \
+ libowfd.la \
+ libshl.la
+openwfd_dhcp_LDFLAGS = $(AM_LDFLAGS)
+
+#
# Tools
#
diff --git a/configure.ac b/configure.ac
index d1f635f..7883ba3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -45,6 +45,14 @@ AC_SUBST(GDHCP_CFLAGS)
AC_SUBST(GDHCP_LIBS)
#
+# Test for dhcp dependencies
+#
+
+PKG_CHECK_MODULES([DHCP], [glib-2.0])
+AC_SUBST(DHCP_CFLAGS)
+AC_SUBST(DHCP_LIBS)
+
+#
# Test for "check" which we use for our test-suite. If not found, we disable
# all tests.
#
diff --git a/src/dhcp.c b/src/dhcp.c
new file mode 100644
index 0000000..3894563
--- /dev/null
+++ b/src/dhcp.c
@@ -0,0 +1,205 @@
+/*
+ * OpenWFD - Open-Source Wifi-Display Implementation
+ *
+ * Copyright (c) 2013 David Herrmann <dh.herrmann@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <glib.h>
+#include <netinet/in.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/epoll.h>
+#include <sys/signalfd.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include "dhcp.h"
+#include "gdhcp/gdhcp.h"
+#include "shl_log.h"
+
+struct owfd_dhcp {
+ struct owfd_dhcp_config config;
+ GMainLoop *loop;
+
+ int sfd;
+ GIOChannel *sfd_chan;
+ guint sfd_id;
+};
+
+static gboolean owfd_dhcp_sfd_fn(GIOChannel *chan, GIOCondition mask,
+ gpointer data)
+{
+ struct owfd_dhcp *dhcp = data;
+ ssize_t l;
+ struct signalfd_siginfo info;
+
+ if (mask & (G_IO_HUP | G_IO_ERR)) {
+ log_vEPIPE();
+ g_main_loop_quit(dhcp->loop);
+ return FALSE;
+ }
+
+ l = read(dhcp->sfd, &info, sizeof(info));
+ if (l < 0) {
+ log_vERRNO();
+ g_main_loop_quit(dhcp->loop);
+ return FALSE;
+ } else if (l != sizeof(info)) {
+ log_vEFAULT();
+ return TRUE;
+ }
+
+ log_notice("received signal %d: %s",
+ info.ssi_signo, strsignal(info.ssi_signo));
+
+ g_main_loop_quit(dhcp->loop);
+ return FALSE;
+}
+
+static int owfd_dhcp_run(struct owfd_dhcp *dhcp)
+{
+ g_main_loop_run(dhcp->loop);
+
+ return 0;
+}
+
+static void owfd_dhcp_teardown(struct owfd_dhcp *dhcp)
+{
+ if (dhcp->sfd >= 0) {
+ g_source_remove(dhcp->sfd_id);
+ g_io_channel_unref(dhcp->sfd_chan);
+ close(dhcp->sfd);
+ }
+
+ if (dhcp->loop)
+ g_main_loop_unref(dhcp->loop);
+}
+
+static void sig_dummy(int sig)
+{
+}
+
+static int owfd_dhcp_setup(struct owfd_dhcp *dhcp)
+{
+ static const int sigs[] = {
+ SIGINT,
+ SIGTERM,
+ SIGQUIT,
+ SIGHUP,
+ SIGPIPE,
+ 0
+ };
+ int r, i;
+ sigset_t mask;
+ struct sigaction sig;
+
+ dhcp->loop = g_main_loop_new(NULL, FALSE);
+
+ sigemptyset(&mask);
+ memset(&sig, 0, sizeof(sig));
+ sig.sa_handler = sig_dummy;
+ sig.sa_flags = SA_RESTART;
+
+ for (i = 0; sigs[i]; ++i) {
+ sigaddset(&mask, sigs[i]);
+ r = sigaction(sigs[i], &sig, NULL);
+ if (r < 0) {
+ r = log_ERRNO();
+ goto error;
+ }
+ }
+
+ r = sigprocmask(SIG_BLOCK, &mask, NULL);
+ if (r < 0) {
+ r = log_ERRNO();
+ goto error;
+ }
+
+ dhcp->sfd = signalfd(-1, &mask, SFD_CLOEXEC | SFD_NONBLOCK);
+ if (dhcp->sfd < 0) {
+ r = log_ERRNO();
+ goto error;
+ }
+
+ dhcp->sfd_chan = g_io_channel_unix_new(dhcp->sfd);
+ dhcp->sfd_id = g_io_add_watch(dhcp->sfd_chan,
+ G_IO_HUP | G_IO_ERR | G_IO_IN,
+ owfd_dhcp_sfd_fn,
+ dhcp);
+
+ return 0;
+
+error:
+ owfd_dhcp_teardown(dhcp);
+ return r;
+}
+
+int main(int argc, char **argv)
+{
+ struct owfd_dhcp dhcp;
+ int r;
+
+ memset(&dhcp, 0, sizeof(dhcp));
+ dhcp.sfd = -1;
+ owfd_dhcp_init_config(&dhcp.config);
+
+ r = owfd_dhcp_parse_argv(&dhcp.config, argc, argv);
+ if (r < 0)
+ goto err_out;
+
+ if (dhcp.config.debug)
+ log_max_sev = LOG_DEBUG;
+ else if (dhcp.config.verbose)
+ log_max_sev = LOG_INFO;
+ else if (dhcp.config.silent)
+ log_max_sev = LOG_ERROR;
+
+ if (dhcp.config.silent)
+ log_debug("-");
+ else
+ log_format(LOG_DEFAULT_BASE, NULL, LOG_SEV_NUM,
+ "openwfd_dhcp - revision %s %s %s",
+ "some-rev-TODO-xyz", __DATE__, __TIME__);
+
+ log_info("initializing");
+ r = owfd_dhcp_setup(&dhcp);
+ if (r < 0)
+ goto err_conf;
+
+ log_info("running");
+ r = owfd_dhcp_run(&dhcp);
+
+ owfd_dhcp_teardown(&dhcp);
+err_conf:
+ owfd_dhcp_clear_config(&dhcp.config);
+ if (r < 0) {
+ errno = -r;
+ log_error("initialization failed (%d): %m", r);
+ }
+ log_info("exiting");
+err_out:
+ return -r;
+}
diff --git a/src/dhcp.h b/src/dhcp.h
new file mode 100644
index 0000000..64aa261
--- /dev/null
+++ b/src/dhcp.h
@@ -0,0 +1,66 @@
+/*
+ * OpenWFD - Open-Source Wifi-Display Implementation
+ *
+ * Copyright (c) 2013 David Herrmann <dh.herrmann@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef OWFD_DHCP_H
+#define OWFD_DHCP_H
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* config handling */
+
+struct owfd_dhcp_config {
+ unsigned int verbose : 1;
+ unsigned int silent : 1;
+ unsigned int debug : 1;
+
+ unsigned int client : 1;
+ unsigned int server : 1;
+
+ char *interface;
+ char *ip_binary;
+
+ char *local;
+ char *gateway;
+ char *dns;
+ char *subnet;
+ char *ip_from;
+ char *ip_to;
+};
+
+void owfd_dhcp_init_config(struct owfd_dhcp_config *conf);
+void owfd_dhcp_clear_config(struct owfd_dhcp_config *conf);
+int owfd_dhcp_parse_argv(struct owfd_dhcp_config *conf,
+ int argc, char **argv);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OWFD_DHCP_H */
diff --git a/src/dhcp_config.c b/src/dhcp_config.c
new file mode 100644
index 0000000..28d050c
--- /dev/null
+++ b/src/dhcp_config.c
@@ -0,0 +1,354 @@
+/*
+ * OpenWFD - Open-Source Wifi-Display Implementation
+ *
+ * Copyright (c) 2013 David Herrmann <dh.herrmann@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <getopt.h>
+#include <netinet/in.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include "dhcp.h"
+
+#define LONG_OPT_OFFSET 10000
+
+enum {
+ OPT_HELP,
+ OPT_VERBOSE,
+ OPT_SILENT,
+ OPT_DEBUG,
+
+ OPT_CLIENT,
+ OPT_SERVER,
+
+ OPT_INTERFACE,
+ OPT_IP_BINARY,
+
+ OPT_LOCAL,
+ OPT_GATEWAY,
+ OPT_DNS,
+ OPT_SUBNET,
+ OPT_IP_FROM,
+ OPT_IP_TO,
+};
+
+const char short_options[] = ":hvcsi:";
+
+#define OPT(_name, _arg, _val) \
+ { .name = _name, .has_arg = _arg, .val = LONG_OPT_OFFSET + _val }
+const struct option long_options[] = {
+ OPT("help", 0, OPT_HELP),
+ OPT("verbose", 0, OPT_VERBOSE),
+ OPT("silent", 0, OPT_SILENT),
+ OPT("debug", 0, OPT_DEBUG),
+
+ OPT("client", 0, OPT_CLIENT),
+ OPT("server", 0, OPT_SERVER),
+
+ OPT("interface", 1, OPT_INTERFACE),
+ OPT("ip-binary", 1, OPT_IP_BINARY),
+
+ OPT("local", 1, OPT_LOCAL),
+ OPT("gateway", 1, OPT_GATEWAY),
+ OPT("dns", 1, OPT_DNS),
+ OPT("subnet", 1, OPT_SUBNET),
+ OPT("ip-from", 1, OPT_IP_FROM),
+ OPT("ip-to", 1, OPT_IP_TO),
+
+ OPT(NULL, 0, 0),
+};
+#undef OPT
+
+void owfd_dhcp_init_config(struct owfd_dhcp_config *conf)
+{
+ memset(conf, 0, sizeof(*conf));
+}
+
+void owfd_dhcp_clear_config(struct owfd_dhcp_config *conf)
+{
+ free(conf->interface);
+ free(conf->ip_binary);
+
+ free(conf->local);
+ free(conf->gateway);
+ free(conf->dns);
+ free(conf->subnet);
+ free(conf->ip_from);
+ free(conf->ip_to);
+}
+
+static void show_help(void)
+{
+ /*
+ * Usage/Help information
+ * This should be scaled to a maximum of 80 characters per line:
+ *
+ * 80 char line:
+ * | 10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 |
+ * "12345678901234567890123456789012345678901234567890123456789012345678901234567890\n"
+ * 80 char line starting with tab:
+ * |10| 20 | 30 | 40 | 50 | 60 | 70 | 80 |
+ * "\t901234567890123456789012345678901234567890123456789012345678901234567890\n"
+ */
+ fprintf(stderr,
+ "Usage:\n"
+ "\t%1$s [options]\n"
+ "\t%1$s -h [options]\n"
+ "\n"
+ "All addresses must be given as IPv6 address. If you want to pass an IPv4\n"
+ "address, use '::FFFF:<ipv4>' as usual.\n"
+ "\n"
+ "General Options:\n"
+ "\t-h, --help [off] Print this help and exit\n"
+ "\t-v, --verbose [off] Print verbose messages\n"
+ "\t --debug [off] Enable debug mode\n"
+ "\t --silent [off] Suppress notices and warnings\n"
+ "\n"
+ "Modus Options:\n"
+ "\t-c, --client [off] Run as DHCP client\n"
+ "\t-s, --server [off] Run as DHCP server\n"
+ "\n"
+ "Network Options:\n"
+ "\t-i, --interface <wlan0> [] Wireless interface to run on\n"
+ "\t --ip-binary </path> [%2$s]\n"
+ "\t Path to 'ip' binary\n"
+ "\n"
+ "Server Options:\n"
+ "\t --local <addr> [] Local IPv6 address\n"
+ "\t --gateway <addr> [] Gateway IPv6 address\n"
+ "\t --dns <addr> [] DNS-Server IPv6 address\n"
+ "\t --subnet <mask> [] Subnet mask\n"
+ "\t --ip-from <addr> [] Server IPv6-range start address\n"
+ "\t --ip-to <addr> [] Server IPv6-range end address\n"
+ , "openwfd_dhcp",
+ BUILD_BINDIR_IP "/ip");
+ /*
+ * 80 char line:
+ * | 10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 |
+ * "12345678901234567890123456789012345678901234567890123456789012345678901234567890\n"
+ * 80 char line starting with tab:
+ * |10| 20 | 30 | 40 | 50 | 60 | 70 | 80 |
+ * "\t901234567890123456789012345678901234567890123456789012345678901234567890\n"
+ */
+}
+
+static int OOM(void)
+{
+ fprintf(stderr, "out of memory\n");
+ return -ENOMEM;
+}
+
+static int verify_address(const char *argname, const char *argval)
+{
+ int r;
+ struct in6_addr addr;
+
+ if (!argval) {
+ fprintf(stderr, "no value given for %s\n", argname);
+ return -EINVAL;
+ }
+
+ r = inet_pton(AF_INET6, argval, &addr);
+ if (r != 1) {
+ fprintf(stderr, "invalid IPv6 address for %s\n", argname);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int owfd_dhcp_parse_argv(struct owfd_dhcp_config *conf, int argc, char **argv)
+{
+ int c;
+ bool help = false;
+ char *t;
+ int r;
+
+ opterr = 0;
+ while (1) {
+ c = getopt_long(argc, argv, short_options, long_options, NULL);
+ if (c <= 0) {
+ break;
+ } else if (c == ':') {
+ fprintf(stderr, "missing argument for: %s\n",
+ argv[optind - 1]);
+ return -EINVAL;
+ } else if (c == '?') {
+ if (optopt && optopt < LONG_OPT_OFFSET)
+ fprintf(stderr, "unknown argument: -%c\n",
+ optopt);
+ else if (!optopt)
+ fprintf(stderr, "unknown argument: %s\n",
+ argv[optind - 1]);
+ else
+ fprintf(stderr, "option takes no arg: %s\n",
+ argv[optind - 1]);
+ return -EINVAL;
+ }
+
+#define OPT(_num) LONG_OPT_OFFSET + _num
+ switch (c) {
+ case 'h':
+ case OPT(OPT_HELP):
+ help = true;
+ break;
+ case 'v':
+ case OPT(OPT_VERBOSE):
+ conf->verbose = 1;
+ break;
+ case OPT(OPT_SILENT):
+ conf->silent = 1;
+ break;
+ case OPT(OPT_DEBUG):
+ conf->debug = 1;
+ break;
+
+ case 'c':
+ case OPT(OPT_CLIENT):
+ conf->server = 0;
+ conf->client = 1;
+ break;
+ case 's':
+ case OPT(OPT_SERVER):
+ conf->client = 0;
+ conf->server = 1;
+ break;
+
+ case 'i':
+ case OPT(OPT_INTERFACE):
+ t = strdup(optarg);
+ if (!t)
+ return OOM();
+ free(conf->interface);
+ conf->interface = t;
+ break;
+ case OPT(OPT_IP_BINARY):
+ t = strdup(optarg);
+ if (!t)
+ return OOM();
+ free(conf->ip_binary);
+ conf->ip_binary = t;
+ break;
+
+ case OPT(OPT_LOCAL):
+ t = strdup(optarg);
+ if (!t)
+ return OOM();
+ free(conf->local);
+ conf->local = t;
+ break;
+ case OPT(OPT_GATEWAY):
+ t = strdup(optarg);
+ if (!t)
+ return OOM();
+ free(conf->gateway);
+ conf->gateway = t;
+ break;
+ case OPT(OPT_DNS):
+ t = strdup(optarg);
+ if (!t)
+ return OOM();
+ free(conf->dns);
+ conf->dns = t;
+ break;
+ case OPT(OPT_SUBNET):
+ t = strdup(optarg);
+ if (!t)
+ return OOM();
+ free(conf->subnet);
+ conf->subnet = t;
+ break;
+ case OPT(OPT_IP_FROM):
+ t = strdup(optarg);
+ if (!t)
+ return OOM();
+ free(conf->ip_from);
+ conf->ip_from = t;
+ break;
+ case OPT(OPT_IP_TO):
+ t = strdup(optarg);
+ if (!t)
+ return OOM();
+ free(conf->ip_to);
+ conf->ip_to = t;
+ break;
+ }
+#undef OPT
+ }
+
+ if (help) {
+ show_help();
+ return -EAGAIN;
+ }
+
+ if (optind < argc) {
+ fprintf(stderr,
+ "unparsed remaining arguments starting with: %s\n",
+ argv[optind]);
+ return -EINVAL;
+ }
+
+ if (!conf->client && !conf->server) {
+ fprintf(stderr,
+ "no --client or --server given\n");
+ return -EINVAL;
+ }
+
+ if (!conf->interface) {
+ fprintf(stderr, "no interface given, use: -i <iface>\n");
+ return -EINVAL;
+ }
+
+ if (!conf->ip_binary) {
+ conf->ip_binary = strdup(BUILD_BINDIR_IP "/ip");
+ if (!conf->ip_binary)
+ return OOM();
+ }
+
+ if (conf->server) {
+ r = verify_address("--local", conf->local);
+ if (r < 0)
+ return r;
+ r = verify_address("--gateway", conf->gateway);
+ if (r < 0)
+ return r;
+ r = verify_address("--dns", conf->dns);
+ if (r < 0)
+ return r;
+ r = verify_address("--subnet", conf->subnet);
+ if (r < 0)
+ return r;
+ r = verify_address("--ip-from", conf->ip_from);
+ if (r < 0)
+ return r;
+ r = verify_address("--ip-to", conf->ip_to);
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
+}