summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ctdb/common/system_aix.c4
-rw-r--r--ctdb/common/system_common.c2
-rw-r--r--ctdb/common/system_linux.c22
-rw-r--r--ctdb/include/ctdb_private.h2
-rw-r--r--ctdb/server/ctdb_takeover.c58
5 files changed, 88 insertions, 0 deletions
diff --git a/ctdb/common/system_aix.c b/ctdb/common/system_aix.c
index 5fe54130d4..1404a82901 100644
--- a/ctdb/common/system_aix.c
+++ b/ctdb/common/system_aix.c
@@ -357,4 +357,8 @@ int ctdb_sys_read_tcp_packet(int s, void *private_data,
}
+bool ctdb_sys_check_iface_exists(const char *iface)
+{
+ return true;
+}
diff --git a/ctdb/common/system_common.c b/ctdb/common/system_common.c
index f28045f95e..3fe90e6ef3 100644
--- a/ctdb/common/system_common.c
+++ b/ctdb/common/system_common.c
@@ -73,3 +73,5 @@ bool ctdb_sys_have_ip(ctdb_sock_addr *_addr)
close(s);
return ret == 0;
}
+
+
diff --git a/ctdb/common/system_linux.c b/ctdb/common/system_linux.c
index a498ab2d68..2dcdffb3ec 100644
--- a/ctdb/common/system_linux.c
+++ b/ctdb/common/system_linux.c
@@ -537,3 +537,25 @@ int ctdb_sys_read_tcp_packet(int s, void *private_data,
}
+bool ctdb_sys_check_iface_exists(const char *iface)
+{
+ int s;
+ struct ifreq ifr;
+
+ s = socket(PF_PACKET, SOCK_RAW, 0);
+ if (s == -1){
+ /* We dont know if the interface exists, so assume yes */
+ DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket\n"));
+ return true;
+ }
+
+ strncpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
+ if (ioctl(s, SIOCGIFINDEX, &ifr) < 0 && errno == ENODEV) {
+ DEBUG(DEBUG_CRIT,(__location__ " interface '%s' not found\n", iface));
+ close(s);
+ return false;
+ }
+ close(s);
+
+ return true;
+}
diff --git a/ctdb/include/ctdb_private.h b/ctdb/include/ctdb_private.h
index 6f6aa44f41..edf1d88dd8 100644
--- a/ctdb/include/ctdb_private.h
+++ b/ctdb/include/ctdb_private.h
@@ -414,6 +414,7 @@ struct ctdb_context {
uint32_t recovery_mode;
TALLOC_CTX *tickle_update_context;
TALLOC_CTX *keepalive_ctx;
+ TALLOC_CTX *check_public_ifaces_ctx;
struct ctdb_tunable tunable;
enum ctdb_freeze_mode freeze_mode[NUM_DB_PRIORITIES+1];
struct ctdb_freeze_handle *freeze_handles[NUM_DB_PRIORITIES+1];
@@ -1112,6 +1113,7 @@ int ctdb_ctrl_set_iface_link(struct ctdb_context *ctdb,
uint32_t uint16_checksum(uint16_t *data, size_t n);
int ctdb_sys_send_arp(const ctdb_sock_addr *addr, const char *iface);
bool ctdb_sys_have_ip(ctdb_sock_addr *addr);
+bool ctdb_sys_check_iface_exists(const char *iface);
int ctdb_sys_send_tcp(const ctdb_sock_addr *dest,
const ctdb_sock_addr *src,
uint32_t seq, uint32_t ack, int rst);
diff --git a/ctdb/server/ctdb_takeover.c b/ctdb/server/ctdb_takeover.c
index 1e2e829e4d..4114b40f83 100644
--- a/ctdb/server/ctdb_takeover.c
+++ b/ctdb/server/ctdb_takeover.c
@@ -880,6 +880,16 @@ static int ctdb_add_public_address(struct ctdb_context *ctdb,
int i;
int ret;
+ tmp = talloc_strdup(vnn, ifaces);
+ for (iface = strtok(tmp, ","); iface; iface = strtok(NULL, ",")) {
+ if (!ctdb_sys_check_iface_exists(iface)) {
+ DEBUG(DEBUG_CRIT,("Interface %s does not exist. Can not add public-address : %s\n", iface, ctdb_addr_to_str(addr)));
+ talloc_free(tmp);
+ return -1;
+ }
+ }
+ talloc_free(tmp);
+
/* Verify that we dont have an entry for this ip yet */
for (vnn=ctdb->vnn;vnn;vnn=vnn->next) {
if (ctdb_same_sockaddr(addr, &vnn->public_address)) {
@@ -941,6 +951,51 @@ int ctdb_set_event_script_dir(struct ctdb_context *ctdb, const char *script_dir)
return 0;
}
+static void ctdb_check_interfaces_event(struct event_context *ev, struct timed_event *te,
+ struct timeval t, void *private_data)
+{
+ struct ctdb_context *ctdb = talloc_get_type(private_data,
+ struct ctdb_context);
+ struct ctdb_vnn *vnn;
+
+ for (vnn=ctdb->vnn;vnn;vnn=vnn->next) {
+ int i;
+
+ for (i=0; vnn->ifaces[i] != NULL; i++) {
+ if (!ctdb_sys_check_iface_exists(vnn->ifaces[i])) {
+ DEBUG(DEBUG_CRIT,("Interface %s does not exist but is used by public ip %s\n",
+ vnn->ifaces[i],
+ ctdb_addr_to_str(&vnn->public_address)));
+ }
+ }
+ }
+
+ event_add_timed(ctdb->ev, ctdb->check_public_ifaces_ctx,
+ timeval_current_ofs(30, 0),
+ ctdb_check_interfaces_event, ctdb);
+}
+
+
+static int ctdb_start_monitoring_interfaces(struct ctdb_context *ctdb)
+{
+ if (ctdb->check_public_ifaces_ctx != NULL) {
+ talloc_free(ctdb->check_public_ifaces_ctx);
+ ctdb->check_public_ifaces_ctx = NULL;
+ }
+
+ ctdb->check_public_ifaces_ctx = talloc_new(ctdb);
+ if (ctdb->check_public_ifaces_ctx == NULL) {
+ ctdb_fatal(ctdb, "failed to allocate context for checking interfaces");
+ }
+
+ event_add_timed(ctdb->ev, ctdb->check_public_ifaces_ctx,
+ timeval_current_ofs(30, 0),
+ ctdb_check_interfaces_event, ctdb);
+
+ return 0;
+}
+
+
/*
setup the public address lists from a file
*/
@@ -1003,6 +1058,9 @@ int ctdb_set_public_addresses(struct ctdb_context *ctdb, const char *alist)
}
}
+
+ ctdb_start_monitoring_interfaces(ctdb);
+
talloc_free(lines);
return 0;
}