diff options
author | David Herrmann <dh.herrmann@gmail.com> | 2013-11-04 17:48:43 +0100 |
---|---|---|
committer | David Herrmann <dh.herrmann@gmail.com> | 2013-11-04 17:48:43 +0100 |
commit | 26ef7dae09dd27c837290c294063c20f5da9e537 (patch) | |
tree | d6fb49f55a1d522efeb888188e37f754f32622dd | |
parent | f9669a929c07800b44feda6c2ec06073da325d52 (diff) |
owfd: dhcp: convert ipv6 input to ipv4
gdhcp uses inet_aton() and thus cannot deal with embedded IPv4. Add a
small parser to convert addresses if IPv4 is selected. Otherwise, the
gdhcp server will fail to read them.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
-rw-r--r-- | src/dhcp_config.c | 72 |
1 files changed, 65 insertions, 7 deletions
diff --git a/src/dhcp_config.c b/src/dhcp_config.c index 599628d..e088cf6 100644 --- a/src/dhcp_config.c +++ b/src/dhcp_config.c @@ -24,6 +24,7 @@ */ #include <arpa/inet.h> +#include <endian.h> #include <errno.h> #include <getopt.h> #include <netinet/in.h> @@ -168,8 +169,11 @@ static int OOM(void) return -ENOMEM; } -static int verify_address(const char *argname, const char *argval) +static int verify_address(const char *argname, const char *argval, bool ipv4) { + static const char prefix[] = { 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0xff, 0xff }; int r; struct in6_addr addr; @@ -178,12 +182,49 @@ static int verify_address(const char *argname, const char *argval) return -EINVAL; } + memset(&addr, 0, sizeof(addr)); r = inet_pton(AF_INET6, argval, &addr); if (r != 1) { fprintf(stderr, "invalid IPv6 address for %s\n", argname); return -EINVAL; } + if (ipv4) { + if (memcmp(addr.s6_addr, prefix, sizeof(prefix))) { + fprintf(stderr, + "invalid IPv4-in-IPv6 address for %s\n", + argname); + return -EINVAL; + } + } + + return 0; +} + +static int make_ipv4(char **argval) +{ + struct in6_addr addr; + struct in_addr src; + char buf[INET_ADDRSTRLEN + 1], *str; + + memset(&addr, 0, sizeof(addr)); + + /* already verified */ + inet_pton(AF_INET6, *argval, &addr); + src.s_addr = htonl((addr.s6_addr[12] << 24) | + (addr.s6_addr[13] << 16) | + (addr.s6_addr[14] << 8) | + (addr.s6_addr[15])); + inet_ntop(AF_INET, &src, buf, sizeof(buf)); + buf[sizeof(buf) - 1] = 0; + + str = strdup(buf); + if (!str) + return OOM(); + + free(*argval); + *argval = str; + return 0; } @@ -356,22 +397,39 @@ int owfd_dhcp_parse_argv(struct owfd_dhcp_config *conf, int argc, char **argv) } if (conf->server) { - r = verify_address("--local", conf->local); + r = verify_address("--local", conf->local, conf->ipv4); + if (r >= 0 && conf->ipv4) + r = make_ipv4(&conf->local); if (r < 0) return r; - r = verify_address("--gateway", conf->gateway); + + r = verify_address("--gateway", conf->gateway, conf->ipv4); + if (r >= 0 && conf->ipv4) + r = make_ipv4(&conf->gateway); if (r < 0) return r; - r = verify_address("--dns", conf->dns); + + r = verify_address("--dns", conf->dns, conf->ipv4); + if (r >= 0 && conf->ipv4) + r = make_ipv4(&conf->dns); if (r < 0) return r; - r = verify_address("--subnet", conf->subnet); + + r = verify_address("--subnet", conf->subnet, conf->ipv4); + if (r >= 0 && conf->ipv4) + r = make_ipv4(&conf->subnet); if (r < 0) return r; - r = verify_address("--ip-from", conf->ip_from); + + r = verify_address("--ip-from", conf->ip_from, conf->ipv4); + if (r >= 0 && conf->ipv4) + r = make_ipv4(&conf->ip_from); if (r < 0) return r; - r = verify_address("--ip-to", conf->ip_to); + + r = verify_address("--ip-to", conf->ip_to, conf->ipv4); + if (r >= 0 && conf->ipv4) + r = make_ipv4(&conf->ip_to); if (r < 0) return r; } |