diff options
-rw-r--r-- | ctdb/common/system_aix.c | 4 | ||||
-rw-r--r-- | ctdb/common/system_common.c | 2 | ||||
-rw-r--r-- | ctdb/common/system_linux.c | 22 | ||||
-rw-r--r-- | ctdb/include/ctdb_private.h | 2 | ||||
-rw-r--r-- | ctdb/server/ctdb_takeover.c | 58 |
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; } |