return true;
}
-static bool parse_ipv6(const char *s, const char *iface, unsigned port, ctdb_sock_addr *saddr)
+static bool parse_ipv6(const char *s, const char *ifaces, unsigned port, ctdb_sock_addr *saddr)
{
saddr->ip6.sin6_family = AF_INET6;
saddr->ip6.sin6_port = htons(port);
return false;
}
- if (iface && IN6_IS_ADDR_LINKLOCAL(&saddr->ip6.sin6_addr)) {
- saddr->ip6.sin6_scope_id = if_nametoindex(iface);
+ if (ifaces && IN6_IS_ADDR_LINKLOCAL(&saddr->ip6.sin6_addr)) {
+ if (strchr(ifaces, ',')) {
+ DEBUG(DEBUG_ERR, (__location__ " Link local address %s "
+ "is specified for multiple ifaces %s\n",
+ s, ifaces));
+ return false;
+ }
+ saddr->ip6.sin6_scope_id = if_nametoindex(ifaces);
}
return true;
/*
parse an ip
*/
-bool parse_ip(const char *addr, const char *iface, unsigned port, ctdb_sock_addr *saddr)
+bool parse_ip(const char *addr, const char *ifaces, unsigned port, ctdb_sock_addr *saddr)
{
char *p;
bool ret;
if (p == NULL) {
ret = parse_ipv4(addr, port, &saddr->ip);
} else {
- ret = parse_ipv6(addr, iface, port, saddr);
+ ret = parse_ipv6(addr, ifaces, port, saddr);
}
return ret;
/*
parse a ip/mask pair
*/
-bool parse_ip_mask(const char *str, const char *iface, ctdb_sock_addr *addr, unsigned *mask)
+bool parse_ip_mask(const char *str, const char *ifaces, ctdb_sock_addr *addr, unsigned *mask)
{
TALLOC_CTX *tmp_ctx = talloc_new(NULL);
char *s, *p;
/* now is this a ipv4 or ipv6 address ?*/
- ret = parse_ip(s, iface, 0, addr);
+ ret = parse_ip(s, ifaces, 0, addr);
talloc_free(tmp_ctx);
return ret;
}
-static int ctdb_add_public_address(struct ctdb_context *ctdb, ctdb_sock_addr *addr, unsigned mask, const char *iface)
+static int ctdb_add_public_address(struct ctdb_context *ctdb,
+ ctdb_sock_addr *addr,
+ unsigned mask, const char *ifaces)
{
struct ctdb_vnn *vnn;
+ uint32_t num = 0;
+ char *tmp;
+ const char *iface;
+ int i;
+ int ret;
/* Verify that we dont have an entry for this ip yet */
for (vnn=ctdb->vnn;vnn;vnn=vnn->next) {
/* create a new vnn structure for this ip address */
vnn = talloc_zero(ctdb, struct ctdb_vnn);
CTDB_NO_MEMORY_FATAL(ctdb, vnn);
- vnn->iface = talloc_strdup(vnn, iface);
- CTDB_NO_MEMORY(ctdb, vnn->iface);
+ vnn->ifaces = talloc_array(vnn, const char *, num + 2);
+ tmp = talloc_strdup(vnn, ifaces);
+ CTDB_NO_MEMORY_FATAL(ctdb, tmp);
+ for (iface = strtok(tmp, ","); iface; iface = strtok(NULL, ",")) {
+ vnn->ifaces = talloc_realloc(vnn, vnn->ifaces, const char *, num + 2);
+ CTDB_NO_MEMORY_FATAL(ctdb, vnn->ifaces);
+ vnn->ifaces[num] = talloc_strdup(vnn, iface);
+ CTDB_NO_MEMORY_FATAL(ctdb, vnn->ifaces[num]);
+ num++;
+ }
+ talloc_free(tmp);
+ vnn->ifaces[num] = NULL;
+ vnn->iface = vnn->ifaces[0];
vnn->public_address = *addr;
vnn->public_netmask_bits = mask;
vnn->pnn = -1;
unsigned mask;
ctdb_sock_addr addr;
const char *addrstr;
- const char *iface;
+ const char *ifaces;
char *tok, *line;
line = lines[i];
talloc_free(lines);
return -1;
}
- iface = ctdb->default_public_interface;
+ ifaces = ctdb->default_public_interface;
} else {
- iface = tok;
+ ifaces = tok;
}
- if (!addrstr || !parse_ip_mask(addrstr, iface, &addr, &mask)) {
+ if (!addrstr || !parse_ip_mask(addrstr, ifaces, &addr, &mask)) {
DEBUG(DEBUG_CRIT,("Badly formed line %u in public address list\n", i+1));
talloc_free(lines);
return -1;
}
- if (ctdb_add_public_address(ctdb, &addr, mask, iface)) {
+ if (ctdb_add_public_address(ctdb, &addr, mask, ifaces)) {
DEBUG(DEBUG_CRIT,("Failed to add line %u to the public address list\n", i+1));
talloc_free(lines);
return -1;
svnn = talloc_zero(ctdb, struct ctdb_vnn);
CTDB_NO_MEMORY(ctdb, svnn);
- svnn->iface = talloc_strdup(svnn, iface);
- CTDB_NO_MEMORY(ctdb, svnn->iface);
+ svnn->ifaces = talloc_array(svnn, const char *, 2);
+ CTDB_NO_MEMORY(ctdb, svnn->ifaces);
+ svnn->ifaces[0] = talloc_strdup(svnn->ifaces, iface);
+ CTDB_NO_MEMORY(ctdb, svnn->ifaces[0]);
+ svnn->ifaces[1] = NULL;
+
+ svnn->iface = svnn->ifaces[0];
ok = parse_ip(ip, iface, 0, &svnn->public_address);
if (!ok) {