From: Chen Fan Date: Tue, 7 Oct 2014 04:07:31 +0000 (+0800) Subject: conf: add check if migration_host is a localhost address X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=24c160376275b7d31f71fbde83af8183cbf744a7;p=libvirt.git conf: add check if migration_host is a localhost address Signed-off-by: Chen Fan Signed-off-by: Ján Tomko --- diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 04bb4f0ab6..9bad47596a 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1916,6 +1916,7 @@ virSocketAddrGetIpPrefix; virSocketAddrGetPort; virSocketAddrGetRange; virSocketAddrIsNetmask; +virSocketAddrIsNumericLocalhost; virSocketAddrIsPrivate; virSocketAddrIsWildcard; virSocketAddrMask; diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index adc6cafb27..e2a3505ed1 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -707,6 +707,17 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg, GET_VALUE_LONG("seccomp_sandbox", cfg->seccompSandbox); GET_VALUE_STR("migration_host", cfg->migrateHost); + virStringStripIPv6Brackets(cfg->migrateHost); + if (cfg->migrateHost && + (STRPREFIX(cfg->migrateHost, "localhost") || + virSocketAddrIsNumericLocalhost(cfg->migrateHost))) { + virReportError(VIR_ERR_CONF_SYNTAX, + _("migration_host must not be the address of" + " the local machine: %s"), + cfg->migrateHost); + goto cleanup; + } + GET_VALUE_STR("migration_address", cfg->migrationAddress); GET_VALUE_BOOL("log_timestamp", cfg->logTimestamp); diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c index 7fe7a151c0..a19e3afccc 100644 --- a/src/util/virsocketaddr.c +++ b/src/util/virsocketaddr.c @@ -878,3 +878,36 @@ virSocketAddrNumericFamily(const char *address) freeaddrinfo(res); return family; } + +/** + * virSocketAddrIsNumericLocalhost: + * @address: address to check + * + * Check if passed address is a numeric 'localhost' address. + * + * Returns: true if @address is a numeric 'localhost' address, + * false otherwise + */ +bool +virSocketAddrIsNumericLocalhost(const char *addr) +{ + struct addrinfo *res; + struct in_addr tmp = { .s_addr = htonl(INADDR_LOOPBACK) }; + struct sockaddr_in *inet4; + struct sockaddr_in6 *inet6; + + if (virSocketAddrParseInternal(&res, addr, AF_UNSPEC, false) < 0) + return false; + + switch (res->ai_addr->sa_family) { + case AF_INET: + inet4 = (struct sockaddr_in*) res->ai_addr; + return memcmp(&inet4->sin_addr.s_addr, &tmp.s_addr, + sizeof(inet4->sin_addr.s_addr)) == 0; + case AF_INET6: + inet6 = (struct sockaddr_in6*) res->ai_addr; + return IN6_IS_ADDR_LOOPBACK(&(inet6->sin6_addr)); + } + return false; + +} diff --git a/src/util/virsocketaddr.h b/src/util/virsocketaddr.h index 35c9c1a589..053855be4c 100644 --- a/src/util/virsocketaddr.h +++ b/src/util/virsocketaddr.h @@ -126,4 +126,6 @@ bool virSocketAddrIsPrivate(const virSocketAddr *addr); bool virSocketAddrIsWildcard(const virSocketAddr *addr); int virSocketAddrNumericFamily(const char *address); + +bool virSocketAddrIsNumericLocalhost(const char *addr); #endif /* __VIR_SOCKETADDR_H__ */ diff --git a/tests/sockettest.c b/tests/sockettest.c index e790b51841..fbb5db81a5 100644 --- a/tests/sockettest.c +++ b/tests/sockettest.c @@ -234,6 +234,21 @@ testNumericHelper(const void *opaque) return 0; } +struct testIsLocalhostData { + const char *addr; + bool result; +}; + +static int +testIsLocalhostHelper(const void *opaque) +{ + const struct testIsLocalhostData *data = opaque; + + if (virSocketAddrIsNumericLocalhost(data->addr) != data->result) + return -1; + return 0; +} + static int mymain(void) { @@ -322,6 +337,13 @@ mymain(void) ret = -1; \ } while (0) +#define DO_TEST_LOCALHOST(addr, pass) \ + do { \ + struct testIsLocalhostData data = { addr, pass }; \ + if (virtTestRun("Test localhost " addr, \ + testIsLocalhostHelper, &data) < 0) \ + ret = -1; \ + } while (0) DO_TEST_PARSE_AND_FORMAT("127.0.0.1", AF_UNSPEC, true); DO_TEST_PARSE_AND_FORMAT("127.0.0.1", AF_INET, true); @@ -391,6 +413,19 @@ mymain(void) DO_TEST_NUMERIC_FAMILY("::ffff", AF_INET6); DO_TEST_NUMERIC_FAMILY("examplehost", -1); + DO_TEST_LOCALHOST("127.0.0.1", true); + DO_TEST_LOCALHOST("2130706433", true); + DO_TEST_LOCALHOST("0177.0.0.01", true); + DO_TEST_LOCALHOST("::1", true); + DO_TEST_LOCALHOST("0::1", true); + DO_TEST_LOCALHOST("0:0:0::1", true); + DO_TEST_LOCALHOST("[00:0::1]", false); + DO_TEST_LOCALHOST("[::1]", false); + DO_TEST_LOCALHOST("128.0.0.1", false); + DO_TEST_LOCALHOST("0.0.0.1", false); + DO_TEST_LOCALHOST("hello", false); + DO_TEST_LOCALHOST("fe80::1:1", false); + return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; }