]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
add a control to send gratious arps from the ctdb daemon
authorRonnie Sahlberg <sahlberg@ronnie>
Tue, 9 Oct 2007 01:56:09 +0000 (11:56 +1000)
committerRonnie Sahlberg <sahlberg@ronnie>
Tue, 9 Oct 2007 01:56:09 +0000 (11:56 +1000)
(This used to be ctdb commit 563819dd1acb344f95aabb4bad990b36f7ea4520)

ctdb/client/ctdb_client.c
ctdb/include/ctdb_private.h
ctdb/server/ctdb_control.c
ctdb/server/ctdb_takeover.c
ctdb/tools/ctdb.c

index b816d2d720c382e4ec4b74fc1cc46422411b7ab6..8957ad3145709c30cac223caafcc93075da2994d 100644 (file)
@@ -2339,6 +2339,47 @@ int ctdb_ctrl_killtcp(struct ctdb_context *ctdb,
        return 0;
 }
 
+/*
+  send a gratious arp
+ */
+int ctdb_ctrl_gratious_arp(struct ctdb_context *ctdb, 
+                     struct timeval timeout, 
+                     uint32_t destnode,
+                     struct sockaddr_in *sin,
+                     const char *ifname)
+{
+       TDB_DATA data;
+       int32_t res;
+       int ret, len;
+       struct ctdb_control_gratious_arp *gratious_arp;
+       TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
+
+
+       len = strlen(ifname)+1;
+       gratious_arp = talloc_size(tmp_ctx, 
+               offsetof(struct ctdb_control_gratious_arp, iface) + len);
+       CTDB_NO_MEMORY(ctdb, gratious_arp);
+
+       gratious_arp->sin = *sin;
+       gratious_arp->len = len;
+       memcpy(&gratious_arp->iface[0], ifname, len);
+
+
+       data.dsize = offsetof(struct ctdb_control_gratious_arp, iface) + len;
+       data.dptr  = (unsigned char *)gratious_arp;
+
+       ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SEND_GRATIOUS_ARP, 0, data, NULL,
+                          NULL, &res, &timeout, NULL);
+       if (ret != 0 || res != 0) {
+               DEBUG(0,(__location__ " ctdb_control for gratious_arp failed\n"));
+               talloc_free(tmp_ctx);
+               return -1;
+       }
+
+       talloc_free(tmp_ctx);
+       return 0;
+}
+
 /*
   get a list of all tcp tickles that a node knows about for a particular vnn
  */
index ea5efabbcd9911639f4465355fb54885c4517b9c..983871006aff1ba3a7a3800f5bf259e43f094699 100644 (file)
@@ -471,6 +471,7 @@ enum ctdb_controls {CTDB_CONTROL_PROCESS_EXISTS          = 0,
                    CTDB_CONTROL_DB_ATTACH_PERSISTENT    = 61,
                    CTDB_CONTROL_PERSISTENT_STORE        = 62,
                    CTDB_CONTROL_UPDATE_RECORD           = 63,
+                   CTDB_CONTROL_SEND_GRATIOUS_ARP       = 64,
 };     
 
 /*
@@ -514,6 +515,15 @@ struct ctdb_control_killtcp {
        struct sockaddr_in dst;
 };
 
+/*
+  struct for send_gratious_arp
+ */
+struct ctdb_control_gratious_arp {
+       struct sockaddr_in sin;
+       uint32_t len;
+       char iface[1];
+};
+
 /*
   struct for tcp_add and tcp_remove controls
  */
@@ -1095,6 +1105,7 @@ int32_t ctdb_control_tcp_add(struct ctdb_context *ctdb, TDB_DATA indata);
 int32_t ctdb_control_tcp_remove(struct ctdb_context *ctdb, TDB_DATA indata);
 int32_t ctdb_control_startup(struct ctdb_context *ctdb, uint32_t vnn);
 int32_t ctdb_control_kill_tcp(struct ctdb_context *ctdb, TDB_DATA indata);
+int32_t ctdb_control_send_gratious_arp(struct ctdb_context *ctdb, TDB_DATA indata);
 int32_t ctdb_control_get_tcp_tickle_list(struct ctdb_context *ctdb, TDB_DATA indata, TDB_DATA *outdata);
 int32_t ctdb_control_set_tcp_tickle_list(struct ctdb_context *ctdb, TDB_DATA indata);
 
@@ -1144,6 +1155,12 @@ int ctdb_ctrl_killtcp(struct ctdb_context *ctdb,
                      uint32_t destnode,
                      struct ctdb_control_killtcp *killtcp);
 
+int ctdb_ctrl_gratious_arp(struct ctdb_context *ctdb, 
+                     struct timeval timeout, 
+                     uint32_t destnode,
+                     struct sockaddr_in *sin,
+                     const char *ifname);
+
 int ctdb_ctrl_get_tcp_tickles(struct ctdb_context *ctdb, 
                      struct timeval timeout, 
                      uint32_t destnode,
index cd6c9c6e52a8fd93c7b133baaa944f021c770a10..959705de6e3c0859b88b75943a97eac78b44e38d 100644 (file)
@@ -321,6 +321,9 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
        case CTDB_CONTROL_UPDATE_RECORD:
                return ctdb_control_update_record(ctdb, c, indata, async_reply);
 
+       case CTDB_CONTROL_SEND_GRATIOUS_ARP:
+               return ctdb_control_send_gratious_arp(ctdb, indata);
+
        default:
                DEBUG(0,(__location__ " Unknown CTDB control opcode %u\n", opcode));
                return -1;
index a5baa86692164fefd196e3f6bc82dde92d4bf2f6..49d8e8741a513976fc50bdaaa1c9624e2ec28804 100644 (file)
@@ -980,7 +980,7 @@ int32_t ctdb_control_tcp_add(struct ctdb_context *ctdb, TDB_DATA indata)
        if (vnn == NULL) {
                DEBUG(0,(__location__ " got TCP_ADD control for an address which is not a public address '%s'\n", 
                         inet_ntoa(p->dest.sin_addr)));
-               return-1;
+               return -1;
        }
 
 
@@ -1651,3 +1651,87 @@ void ctdb_start_tcp_tickle_update(struct ctdb_context *ctdb)
                             timeval_current_ofs(ctdb->tunable.tickle_update_interval, 0), 
                             ctdb_update_tcp_tickles, ctdb);
 }
+
+
+
+
+struct control_gratious_arp {
+       struct ctdb_context *ctdb;
+       struct sockaddr_in sin;
+       const char *iface;
+       int count;
+};
+
+/*
+  send a control_gratuitous arp
+ */
+static void send_gratious_arp(struct event_context *ev, struct timed_event *te, 
+                                 struct timeval t, void *private_data)
+{
+       int ret;
+       struct control_gratious_arp *arp = talloc_get_type(private_data, 
+                                                       struct control_gratious_arp);
+
+DEBUG(0,("SENDING GRATIOUS ARP ip:%s iface:%s\n",inet_ntoa(arp->sin.sin_addr),arp->iface));
+
+       ret = ctdb_sys_send_arp(&arp->sin, arp->iface);
+       if (ret != 0) {
+               DEBUG(0,(__location__ " sending of gratious arp failed (%s)\n", strerror(errno)));
+       }
+
+
+       arp->count++;
+       if (arp->count == CTDB_ARP_REPEAT) {
+               talloc_free(arp);
+               return;
+       }
+
+       event_add_timed(arp->ctdb->ev, arp, 
+                       timeval_current_ofs(CTDB_ARP_INTERVAL, 0), 
+                       send_gratious_arp, arp);
+}
+
+
+/*
+  send a gratious arp 
+ */
+int32_t ctdb_control_send_gratious_arp(struct ctdb_context *ctdb, TDB_DATA indata)
+{
+       struct ctdb_control_gratious_arp *gratious_arp = (struct ctdb_control_gratious_arp *)indata.dptr;
+       struct control_gratious_arp *arp;
+
+
+       /* verify the size of indata */
+       if (indata.dsize < offsetof(struct ctdb_control_gratious_arp, iface)) {
+               DEBUG(0,(__location__ " Too small indata to hold a ctdb_control_gratious_arp structure\n"));
+               return -1;
+       }
+       if (indata.dsize != 
+               ( offsetof(struct ctdb_control_gratious_arp, iface)
+               + gratious_arp->len ) ){
+
+               DEBUG(0,(__location__ " Wrong size of indata. Was %d bytes "
+                       "but should be %d bytes\n", 
+                       indata.dsize, 
+                       offsetof(struct ctdb_control_gratious_arp, iface)+gratious_arp->len));
+               return -1;
+       }
+
+
+       arp = talloc(ctdb, struct control_gratious_arp);
+       CTDB_NO_MEMORY(ctdb, arp);
+
+       arp->ctdb  = ctdb;
+       arp->sin   = gratious_arp->sin;
+       arp->iface = talloc_strdup(arp, gratious_arp->iface);
+       CTDB_NO_MEMORY(ctdb, arp->iface);
+       arp->count = 0;
+       
+       DEBUG(0,("GRATIOUS ARP for interface [%s] and ip:%s\n",arp->iface,inet_ntoa(arp->sin.sin_addr)));
+
+       event_add_timed(arp->ctdb->ev, arp, 
+                       timeval_zero(), send_gratious_arp, arp);
+
+       return 0;
+}
+
index dbefaf946a99e36ea05c9aceb399d00b76e883f6..d896495cf3bb584288b0e1a0d7045a41900d8b8b 100644 (file)
@@ -379,6 +379,33 @@ static int kill_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
 }
 
 
+/*
+  send a gratious arp
+ */
+static int control_gratious_arp(struct ctdb_context *ctdb, int argc, const char **argv)
+{
+       int ret;
+       struct sockaddr_in sin;
+
+       if (argc < 2) {
+               usage();
+       }
+
+       sin.sin_family = AF_INET;
+       if (inet_aton(argv[0], &sin.sin_addr) == 0) {
+               DEBUG(0,("Wrongly formed ip address '%s'\n", argv[0]));
+               return -1;
+       }
+
+       ret = ctdb_ctrl_gratious_arp(ctdb, TIMELIMIT(), options.pnn, &sin, argv[1]);
+       if (ret != 0) {
+               DEBUG(0, ("Unable to send gratious_arp from node %u\n", options.pnn));
+               return ret;
+       }
+
+       return 0;
+}
+
 /*
   register a server id
  */
@@ -1071,6 +1098,7 @@ static const struct {
        { "thaw",            control_thaw,              true,  "thaw all databases" },
        { "isnotrecmaster",  control_isnotrecmaster,    false,  "check if the local node is recmaster or not" },
        { "killtcp",         kill_tcp,                  false, "kill a tcp connection.", "<srcip:port> <dstip:port>" },
+       { "gratiousarp",     control_gratious_arp,      false, "send a gratious arp", "<ip> <interface>" },
        { "tickle",          tickle_tcp,                false, "send a tcp tickle ack", "<srcip:port> <dstip:port>" },
        { "gettickles",      control_get_tickles,       false, "get the list of tickles registered for this ip", "<ip>" },