mirror of
https://github.com/samba-team/samba.git
synced 2024-12-25 23:21:54 +03:00
merge from ronnie
(This used to be ctdb commit 4a74c61785a6a0181112fb87356207ce9d4854f6)
This commit is contained in:
commit
67677f7550
@ -1826,3 +1826,69 @@ int ctdb_ctrl_delete_low_rsn(struct ctdb_context *ctdb, struct timeval timeout,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
sent to a node to make it take over an ip address
|
||||
*/
|
||||
int ctdb_ctrl_takeover_ip(struct ctdb_context *ctdb, struct timeval timeout,
|
||||
uint32_t destnode, struct sockaddr *sa, const char *iface)
|
||||
{
|
||||
TDB_DATA data;
|
||||
int ret;
|
||||
int32_t res;
|
||||
struct ctdb_control_takeover_ip *ip;
|
||||
|
||||
data.dsize = offsetof(struct ctdb_control_takeover_ip, iface) + strlen(iface)+1;
|
||||
data.dptr = talloc_size(ctdb, data.dsize);
|
||||
|
||||
ip = (struct ctdb_control_takeover_ip *)data.dptr;
|
||||
|
||||
memcpy(&ip->sa, sa, sizeof(struct sockaddr));
|
||||
ip->iflen = strlen(iface);
|
||||
memcpy(&ip->iface[0], iface, strlen(iface)+1);
|
||||
|
||||
ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_TAKEOVER_IP, 0, data, NULL,
|
||||
NULL, &res, &timeout, NULL);
|
||||
talloc_free(data.dptr);
|
||||
|
||||
if (ret != 0 || res != 0) {
|
||||
DEBUG(0,(__location__ " ctdb_control for takeover_ip failed\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
sent to a node to make it release an ip address
|
||||
*/
|
||||
int ctdb_ctrl_release_ip(struct ctdb_context *ctdb, struct timeval timeout,
|
||||
uint32_t destnode, struct sockaddr *sa, const char *iface)
|
||||
{
|
||||
TDB_DATA data;
|
||||
int ret;
|
||||
int32_t res;
|
||||
struct ctdb_control_takeover_ip *ip;
|
||||
|
||||
data.dsize = offsetof(struct ctdb_control_takeover_ip, iface) + strlen(iface)+1;
|
||||
data.dptr = talloc_size(ctdb, data.dsize);
|
||||
|
||||
ip = (struct ctdb_control_takeover_ip *)data.dptr;
|
||||
|
||||
memcpy(&ip->sa, sa, sizeof(struct sockaddr));
|
||||
ip->iflen = strlen(iface);
|
||||
memcpy(&ip->iface[0], iface, strlen(iface)+1);
|
||||
|
||||
ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_RELEASE_IP, 0, data, NULL,
|
||||
NULL, &res, &timeout, NULL);
|
||||
talloc_free(data.dptr);
|
||||
|
||||
if (ret != 0 || res != 0) {
|
||||
DEBUG(0,(__location__ " ctdb_control for release_ip failed\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -260,6 +260,14 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
|
||||
CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_control_set_rsn_nonempty));
|
||||
return ctdb_control_set_rsn_nonempty(ctdb, indata, outdata);
|
||||
|
||||
case CTDB_CONTROL_TAKEOVER_IP:
|
||||
CHECK_CONTROL_DATA_SIZE(offsetof(struct ctdb_control_takeover_ip, iface) + ((struct ctdb_control_takeover_ip *)indata.dptr)->iflen + 1);
|
||||
return ctdb_control_takeover_ip(ctdb, indata, outdata);
|
||||
|
||||
case CTDB_CONTROL_RELEASE_IP:
|
||||
CHECK_CONTROL_DATA_SIZE(offsetof(struct ctdb_control_takeover_ip, iface) + ((struct ctdb_control_takeover_ip *)indata.dptr)->iflen + 1);
|
||||
return ctdb_control_release_ip(ctdb, indata, outdata);
|
||||
|
||||
case CTDB_CONTROL_DELETE_LOW_RSN:
|
||||
CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_control_delete_low_rsn));
|
||||
return ctdb_control_delete_low_rsn(ctdb, indata, outdata);
|
||||
|
@ -27,6 +27,8 @@
|
||||
#include "../include/ctdb_private.h"
|
||||
#include "lib/util/dlinklist.h"
|
||||
#include "db_wrap.h"
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if_arp.h>
|
||||
|
||||
/*
|
||||
lock all databases - mark only
|
||||
@ -614,3 +616,146 @@ int32_t ctdb_control_delete_low_rsn(struct ctdb_context *ctdb, TDB_DATA indata,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
send grat arp after we have taken over an ip address
|
||||
*/
|
||||
static int send_arp(struct sockaddr_in *saddr, char *iface)
|
||||
{
|
||||
int s, ret;
|
||||
struct sockaddr sa;
|
||||
struct ether_header *eh;
|
||||
struct arphdr *ah;
|
||||
struct ifreq if_hwaddr;
|
||||
unsigned char buffer[64]; /*minimum eth frame size */
|
||||
char *ptr;
|
||||
|
||||
|
||||
/* for now, we only handle AF_INET addresses */
|
||||
if (saddr->sin_family != AF_INET) {
|
||||
DEBUG(0,(__location__ " not an ipv4 address\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
s = socket(AF_INET, SOCK_PACKET, htons(ETHERTYPE_ARP));
|
||||
if (s == -1){
|
||||
DEBUG(0,(__location__ "failed to open raw socket\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* get the mac address */
|
||||
strcpy(if_hwaddr.ifr_name, iface);
|
||||
ret = ioctl(s, SIOCGIFHWADDR, &if_hwaddr);
|
||||
if ( ret < 0 ) {
|
||||
close(s);
|
||||
DEBUG(0,(__location__ " ioctl failed\n"));
|
||||
return -1;
|
||||
}
|
||||
if(if_hwaddr.ifr_hwaddr.sa_family != 1){
|
||||
close(s);
|
||||
DEBUG(0,(__location__ " not an ehternet address\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
memset(buffer, 0 , 64);
|
||||
eh = (struct ether_header *)buffer;
|
||||
memset(eh->ether_dhost, 0xff, ETH_ALEN);
|
||||
memcpy(eh->ether_shost, if_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN);
|
||||
eh->ether_type=htons(ETHERTYPE_ARP);
|
||||
|
||||
ah = (struct arphdr *)&buffer[sizeof(struct ether_header)];
|
||||
ah->ar_hrd = htons(ARPHRD_ETHER);
|
||||
ah->ar_pro = htons(ETH_P_IP);
|
||||
ah->ar_hln = ETH_ALEN;
|
||||
ah->ar_pln = 4;
|
||||
|
||||
/* send a gratious arp */
|
||||
ah->ar_op = htons(ARPOP_REQUEST);
|
||||
ptr = (char *)&ah[1];
|
||||
memcpy(ptr, if_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN);
|
||||
ptr+=ETH_ALEN;
|
||||
memcpy(ptr, &saddr->sin_addr, 4);
|
||||
ptr+=4;
|
||||
memset(ptr, 0, ETH_ALEN);
|
||||
ptr+=ETH_ALEN;
|
||||
memcpy(ptr, &saddr->sin_addr, 4);
|
||||
ptr+=4;
|
||||
|
||||
strcpy(sa.sa_data, iface);
|
||||
ret = sendto(s, buffer, 64, 0, &sa, sizeof(sa));
|
||||
if (ret < 0 ){
|
||||
close(s);
|
||||
DEBUG(0,(__location__ " failed sendto\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* send unsolicited arp reply broadcast */
|
||||
ah->ar_op = htons(ARPOP_REPLY);
|
||||
ptr = (char *)&ah[1];
|
||||
memcpy(ptr, if_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN);
|
||||
ptr+=ETH_ALEN;
|
||||
memcpy(ptr, &saddr->sin_addr, 4);
|
||||
ptr+=4;
|
||||
memcpy(ptr, if_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN);
|
||||
ptr+=ETH_ALEN;
|
||||
memcpy(ptr, &saddr->sin_addr, 4);
|
||||
ptr+=4;
|
||||
|
||||
strcpy(sa.sa_data, iface);
|
||||
ret = sendto(s, buffer, 64, 0, &sa, sizeof(sa));
|
||||
if (ret < 0 ){
|
||||
DEBUG(0,(__location__ " failed sendto\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
close(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
take over an ip address
|
||||
*/
|
||||
int32_t ctdb_control_takeover_ip(struct ctdb_context *ctdb, TDB_DATA indata, TDB_DATA *outdata)
|
||||
{
|
||||
int ret;
|
||||
struct ctdb_control_takeover_ip *ip =
|
||||
(struct ctdb_control_takeover_ip *)indata.dptr;
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *)&ip->sa;
|
||||
char cmdstr[256];
|
||||
|
||||
sprintf(cmdstr, "ip addr add %s/32 dev %s",
|
||||
inet_ntoa(sin->sin_addr),
|
||||
ip->iface);
|
||||
|
||||
DEBUG(0,("Taking over IP : %s\n",cmdstr));
|
||||
system(cmdstr);
|
||||
|
||||
ret = send_arp(sin, ip->iface);
|
||||
if (ret != 0) {
|
||||
DEBUG(0,(__location__ "sending of arp failed\n"));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
release an ip address
|
||||
*/
|
||||
int32_t ctdb_control_release_ip(struct ctdb_context *ctdb, TDB_DATA indata, TDB_DATA *outdata)
|
||||
{
|
||||
struct ctdb_control_takeover_ip *ip =
|
||||
(struct ctdb_control_takeover_ip *)indata.dptr;
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *)&ip->sa;
|
||||
char cmdstr[256];
|
||||
|
||||
sprintf(cmdstr, "ip addr del %s/32 dev %s",
|
||||
inet_ntoa(sin->sin_addr),
|
||||
ip->iface);
|
||||
|
||||
DEBUG(0,("Releasing IP : %s\n",cmdstr));
|
||||
system(cmdstr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -22,6 +22,8 @@
|
||||
#define _CTDB_PRIVATE_H
|
||||
|
||||
#include "ctdb.h"
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
/* location of daemon socket */
|
||||
#define CTDB_PATH "/tmp/ctdb.socket"
|
||||
@ -378,6 +380,17 @@ enum ctdb_controls {CTDB_CONTROL_PROCESS_EXISTS,
|
||||
CTDB_CONTROL_MAX_RSN,
|
||||
CTDB_CONTROL_SET_RSN_NONEMPTY,
|
||||
CTDB_CONTROL_DELETE_LOW_RSN,
|
||||
CTDB_CONTROL_TAKEOVER_IP,
|
||||
CTDB_CONTROL_RELEASE_IP,
|
||||
};
|
||||
|
||||
/*
|
||||
structure passed in ctdb_control_takeover_ip and ctdb_control_release_ip
|
||||
*/
|
||||
struct ctdb_control_takeover_ip {
|
||||
struct sockaddr sa;
|
||||
uint8_t iflen;
|
||||
char iface[1];
|
||||
};
|
||||
|
||||
/*
|
||||
@ -865,5 +878,11 @@ int ctdb_ctrl_set_rsn_nonempty(struct ctdb_context *ctdb, struct timeval timeout
|
||||
int ctdb_ctrl_delete_low_rsn(struct ctdb_context *ctdb, struct timeval timeout,
|
||||
uint32_t destnode, uint32_t db_id, uint64_t rsn);
|
||||
void ctdb_set_realtime(void);
|
||||
int32_t ctdb_control_takeover_ip(struct ctdb_context *ctdb, TDB_DATA indata, TDB_DATA *outdata);
|
||||
int ctdb_ctrl_takeover_ip(struct ctdb_context *ctdb, struct timeval timeout,
|
||||
uint32_t destnode, struct sockaddr *sa, const char *iface);
|
||||
int32_t ctdb_control_release_ip(struct ctdb_context *ctdb, TDB_DATA indata, TDB_DATA *outdata);
|
||||
int ctdb_ctrl_release_ip(struct ctdb_context *ctdb, struct timeval timeout,
|
||||
uint32_t destnode, struct sockaddr *sa, const char *iface);
|
||||
|
||||
#endif
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "cmdline.h"
|
||||
#include "../include/ctdb.h"
|
||||
#include "../include/ctdb_private.h"
|
||||
#include <arpa/inet.h>
|
||||
|
||||
static int timelimit = 3;
|
||||
|
||||
@ -62,6 +63,8 @@ static void usage(void)
|
||||
" dumpmemory <vnn|all> dump memory map to log\n"
|
||||
" shutdown <vnn> shutdown a remote ctdb\n"
|
||||
" recovery <vnn> trigger a recovery\n"
|
||||
" takeoverip <vnn> <ip> <iface> take over an ip address\n"
|
||||
" releaseip <vnn> <ip> <iface> release an ip address\n"
|
||||
" freeze <vnn|all> freeze a node\n"
|
||||
" thaw <vnn|all> thaw a node\n"
|
||||
);
|
||||
@ -374,6 +377,62 @@ static int control_shutdown(struct ctdb_context *ctdb, int argc, const char **ar
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
take over an ip address
|
||||
*/
|
||||
static int control_takeoverip(struct ctdb_context *ctdb, int argc, const char **argv)
|
||||
{
|
||||
uint32_t vnn;
|
||||
struct sockaddr_in sin;
|
||||
int ret;
|
||||
|
||||
|
||||
if (argc < 3) {
|
||||
usage();
|
||||
}
|
||||
|
||||
vnn = strtoul(argv[0], NULL, 0);
|
||||
|
||||
sin.sin_family = AF_INET;
|
||||
inet_aton(argv[1], &sin.sin_addr);
|
||||
|
||||
ret = ctdb_ctrl_takeover_ip(ctdb, timeval_current_ofs(1, 0), vnn, (struct sockaddr *)&sin, argv[2]);
|
||||
if (ret != 0) {
|
||||
printf("Unable to takeoverip node %u ip %s iface %s\n", vnn, argv[1], argv[2]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
release an ip address
|
||||
*/
|
||||
static int control_releaseip(struct ctdb_context *ctdb, int argc, const char **argv)
|
||||
{
|
||||
uint32_t vnn;
|
||||
struct sockaddr_in sin;
|
||||
int ret;
|
||||
|
||||
|
||||
if (argc < 3) {
|
||||
usage();
|
||||
}
|
||||
|
||||
vnn = strtoul(argv[0], NULL, 0);
|
||||
|
||||
sin.sin_family = AF_INET;
|
||||
inet_aton(argv[1], &sin.sin_addr);
|
||||
|
||||
ret = ctdb_ctrl_release_ip(ctdb, timeval_current_ofs(1, 0), vnn, (struct sockaddr *)&sin, argv[2]);
|
||||
if (ret != 0) {
|
||||
printf("Unable to releaseip node %u ip %s iface %s\n", vnn, argv[1], argv[2]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
trigger a recovery
|
||||
*/
|
||||
@ -1080,6 +1139,8 @@ int main(int argc, const char *argv[])
|
||||
{ "getpid", control_getpid },
|
||||
{ "shutdown", control_shutdown },
|
||||
{ "recovery", control_recovery },
|
||||
{ "takeoverip", control_takeoverip },
|
||||
{ "releaseip", control_releaseip },
|
||||
{ "freeze", control_freeze },
|
||||
{ "thaw", control_thaw },
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user