we try to bind to it, and if that fails then we don't have that IP
on an interface
- if is_loopback is specified it will also return whether the ip address
- is attached to the loopback interface or not
ifname, if non-NULL, will return the name of the interface this ip is tied to
*/
-bool ctdb_sys_have_ip(struct sockaddr_in ip, bool *is_loopback, TALLOC_CTX *mem_ctx, char **ifname)
+bool ctdb_sys_have_ip(struct sockaddr_in ip)
{
- struct ifreq *ifr = NULL;
- struct ifconf ifc;
- int s, i, num_ifs;
+ int s;
int ret;
- if (is_loopback) {
- *is_loopback = false;
- }
- if (*ifname) {
- *ifname = NULL;
- }
-
ip.sin_port = 0;
s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (s == -1) {
return false;
}
ret = bind(s, (struct sockaddr *)&ip, sizeof(ip));
- if (ret) {
- goto finished;
- }
-
-
- /* find out how much space we need to store the interface details */
- ifc.ifc_len = 0;
- ifc.ifc_req = NULL;
- ret = ioctl(s, SIOCGIFCONF, &ifc);
- if (ret) {
- DEBUG(0,(__location__ " ioctl to read interface list failed\n"));
- goto finished;
- }
-
- ifr = talloc_size(mem_ctx, ifc.ifc_len);
-
- /* get a list of all interface names and addresses */
- ifc.ifc_req = ifr;
- ret = ioctl(s, SIOCGIFCONF, &ifc);
- if (ret) {
- DEBUG(0,(__location__ " ioctl to read interface list failed\n"));
- goto finished;
- }
-
- /* loop over all interfaces and search for the one matching ip */
- num_ifs = ifc.ifc_len/sizeof(struct ifreq);
- for (i=0; i<num_ifs;i++) {
- struct sockaddr_in *sa;
-
- /* we only care bout ipv4 addresses */
- sa = (struct sockaddr_in *)&ifr[i].ifr_addr;
- if (sa->sin_family != AF_INET) {
- continue;
- }
-
- /* this is not the interface you are looking for */
- if (!ctdb_same_ip(sa, &ip)) {
- continue;
- }
-
- /* this is the ifr entry for this interface/address
- read the interface flags so we can tell if it is
- loopback or not
- */
- ret = ioctl(s, SIOCGIFFLAGS, &ifr[i]);
- if (ret) {
- DEBUG(0,(__location__ " failed to read interface flags for interface %s\n", ifr[i].ifr_name));
- goto finished;
- }
-
- /* was this ip tied to a loopback interface ? */
- if (ifr[i].ifr_flags & IFF_LOOPBACK) {
- if (is_loopback != NULL) {
- *is_loopback = true;
- }
- }
-
- if (ifname) {
- *ifname = talloc_asprintf(mem_ctx, "%s", ifr[i].ifr_name);
- }
-
- /* if we got this far, we have found our interface so we can
- exit the loop.
- */
- break;
- }
-
-finished:
- talloc_free(ifr);
close(s);
return ret == 0;
}
TDB_DATA indata,
bool *async_reply)
{
- TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
int ret;
struct takeover_callback_state *state;
struct ctdb_public_ip *pip = (struct ctdb_public_ip *)indata.dptr;
struct ctdb_vnn *vnn;
- bool have_ip, is_loopback;
- char *ifname = NULL;
/* update out vnn list */
vnn = find_public_ip_vnn(ctdb, pip->sin);
if (vnn == NULL) {
DEBUG(0,("takeoverip called for an ip '%s' that is not a public address\n",
inet_ntoa(pip->sin.sin_addr)));
- talloc_free(tmp_ctx);
return 0;
}
vnn->pnn = pip->pnn;
/* if our kernel already has this IP, do nothing */
- have_ip = ctdb_sys_have_ip(pip->sin, &is_loopback, tmp_ctx, &ifname);
- /* if we have the ip and it is not set to a loopback address */
- if (have_ip && !is_loopback) {
- talloc_free(tmp_ctx);
+ if (ctdb_sys_have_ip(pip->sin)) {
return 0;
}
if (ret != 0) {
DEBUG(0,(__location__ " Failed to takeover IP %s on interface %s\n",
inet_ntoa(pip->sin.sin_addr), vnn->iface));
- talloc_free(tmp_ctx);
talloc_free(state);
return -1;
}
/* tell ctdb_control.c that we will be replying asynchronously */
*async_reply = true;
- talloc_free(tmp_ctx);
return 0;
}
TDB_DATA indata,
bool *async_reply)
{
- TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
int ret;
struct takeover_callback_state *state;
struct ctdb_public_ip *pip = (struct ctdb_public_ip *)indata.dptr;
struct ctdb_vnn *vnn;
- bool have_ip, is_loopback;
- char *ifname = NULL;
/* update our vnn list */
vnn = find_public_ip_vnn(ctdb, pip->sin);
if (vnn == NULL) {
DEBUG(0,("releaseip called for an ip '%s' that is not a public address\n",
inet_ntoa(pip->sin.sin_addr)));
- talloc_free(tmp_ctx);
return 0;
}
vnn->pnn = pip->pnn;
talloc_free(vnn->takeover_ctx);
vnn->takeover_ctx = NULL;
- have_ip = ctdb_sys_have_ip(pip->sin, &is_loopback, tmp_ctx, &ifname);
- if ( (!have_ip) || is_loopback) {
- DEBUG(0,("Redundant release of IP %s/%u on interface %s (ip not held)\n",
+ if (!ctdb_sys_have_ip(pip->sin)) {
+ DEBUG(2,("Redundant release of IP %s/%u on interface %s (ip not held)\n",
inet_ntoa(pip->sin.sin_addr), vnn->public_netmask_bits,
vnn->iface));
- talloc_free(tmp_ctx);
return 0;
}
if (ret != 0) {
DEBUG(0,(__location__ " Failed to release IP %s on interface %s\n",
inet_ntoa(pip->sin.sin_addr), vnn->iface));
- talloc_free(tmp_ctx);
talloc_free(state);
return -1;
}
/* tell the control that we will be reply asynchronously */
*async_reply = true;
-
- talloc_free(tmp_ctx);
return 0;
}
void ctdb_release_all_ips(struct ctdb_context *ctdb)
{
struct ctdb_vnn *vnn;
- TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
- bool have_ip, is_loopback;
- char *ifname = NULL;
for (vnn=ctdb->vnn;vnn;vnn=vnn->next) {
- have_ip = ctdb_sys_have_ip(vnn->public_address, &is_loopback, tmp_ctx, &ifname);
- if (have_ip && !is_loopback) {
- ctdb_event_script(ctdb, "releaseip %s %s %u",
- vnn->iface,
- inet_ntoa(vnn->public_address.sin_addr),
- vnn->public_netmask_bits);
- release_kill_clients(ctdb, vnn->public_address);
+ if (!ctdb_sys_have_ip(vnn->public_address)) {
+ continue;
}
+ ctdb_event_script(ctdb, "releaseip %s %s %u",
+ vnn->iface,
+ inet_ntoa(vnn->public_address.sin_addr),
+ vnn->public_netmask_bits);
+ release_kill_clients(ctdb, vnn->public_address);
}
- talloc_free(tmp_ctx);
}