1
0
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:
Andrew Tridgell 2007-05-25 14:53:21 +10:00
commit 67677f7550
5 changed files with 299 additions and 0 deletions

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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

View File

@ -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 },
};