summaryrefslogtreecommitdiffstats
path: root/ctdb/tools
diff options
context:
space:
mode:
authorMartin Schwenke <martin@meltin.net>2013-07-25 13:28:26 +1000
committerAmitay Isaacs <amitay@gmail.com>2013-07-29 15:51:03 +1000
commit200c28fbb21a5f851d07adea8be16eb280addfd2 (patch)
treecf12e82341ce4d812ace2601b29637c620a87070 /ctdb/tools
parent34d55048bc21005b7e5b15a8ceca1a0f6377a024 (diff)
downloadsamba-200c28fbb21a5f851d07adea8be16eb280addfd2.tar.gz
samba-200c28fbb21a5f851d07adea8be16eb280addfd2.tar.xz
samba-200c28fbb21a5f851d07adea8be16eb280addfd2.zip
tools/ctdb: Allow killtcp to read connections from standard input
This will allows eventscripts to send information about multiple tcp connections to a single "ctdb killtcp" command, saving the overhead of setting up a client connection per tcp connection. Signed-off-by: Martin Schwenke <martin@meltin.net> Pair-programmed-with: Amitay Isaacs <amitay@gmail.com> (This used to be ctdb commit af5aa369c266430fe912df0c26116b68bac3572e)
Diffstat (limited to 'ctdb/tools')
-rw-r--r--ctdb/tools/ctdb.c112
1 files changed, 111 insertions, 1 deletions
diff --git a/ctdb/tools/ctdb.c b/ctdb/tools/ctdb.c
index 313ec3cfb6..4c047257b2 100644
--- a/ctdb/tools/ctdb.c
+++ b/ctdb/tools/ctdb.c
@@ -2278,6 +2278,112 @@ static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv)
return 0;
}
+static int kill_tcp_from_file(struct ctdb_context *ctdb,
+ int argc, const char **argv)
+{
+ struct ctdb_control_killtcp *killtcp;
+ int max_entries, current, i;
+ struct timeval timeout;
+ char line[128], src[128], dst[128];
+ int linenum;
+ TDB_DATA data;
+ struct client_async_data *async_data;
+ struct ctdb_client_control_state *state;
+
+ if (argc != 0) {
+ usage();
+ }
+
+ if (options.pnn == CTDB_BROADCAST_ALL ||
+ options.pnn == CTDB_MULTICAST) {
+ DEBUG(DEBUG_ERR, ("Can not use killtcp to multiple nodes\n"));
+ return -1;
+ }
+
+ linenum = 1;
+ killtcp = NULL;
+ max_entries = 0;
+ current = 0;
+ while (!feof(stdin)) {
+ if (fgets(line, sizeof(line), stdin) == NULL) {
+ continue;
+ }
+
+ /* Silently skip empty lines */
+ if (line[0] == '\n') {
+ continue;
+ }
+
+ if (sscanf(line, "%s %s\n", src, dst) != 2) {
+ DEBUG(DEBUG_ERR, ("Bad line [%d]: '%s'\n",
+ linenum, line));
+ talloc_free(killtcp);
+ return -1;
+ }
+
+ if (current >= max_entries) {
+ max_entries += 1024;
+ killtcp = talloc_realloc(ctdb, killtcp,
+ struct ctdb_control_killtcp,
+ max_entries);
+ CTDB_NO_MEMORY(ctdb, killtcp);
+ }
+
+ if (!parse_ip_port(src, &killtcp[current].src_addr)) {
+ DEBUG(DEBUG_ERR, ("Bad IP:port on line [%d]: '%s'\n",
+ linenum, src));
+ talloc_free(killtcp);
+ return -1;
+ }
+
+ if (!parse_ip_port(dst, &killtcp[current].dst_addr)) {
+ DEBUG(DEBUG_ERR, ("Bad IP:port on line [%d]: '%s'\n",
+ linenum, dst));
+ talloc_free(killtcp);
+ return -1;
+ }
+
+ current++;
+ }
+
+ async_data = talloc_zero(ctdb, struct client_async_data);
+ if (async_data == NULL) {
+ talloc_free(killtcp);
+ return -1;
+ }
+
+ for (i = 0; i < current; i++) {
+
+ data.dsize = sizeof(struct ctdb_control_killtcp);
+ data.dptr = (unsigned char *)&killtcp[i];
+
+ timeout = TIMELIMIT();
+ state = ctdb_control_send(ctdb, options.pnn, 0,
+ CTDB_CONTROL_KILL_TCP, 0, data,
+ async_data, &timeout, NULL);
+
+ if (state == NULL) {
+ DEBUG(DEBUG_ERR,
+ ("Failed to call async killtcp control to node %u\n",
+ options.pnn));
+ talloc_free(killtcp);
+ return -1;
+ }
+
+ ctdb_client_async_add(async_data, state);
+ }
+
+ if (ctdb_client_async_wait(ctdb, async_data) != 0) {
+ DEBUG(DEBUG_ERR,("killtcp failed\n"));
+ talloc_free(killtcp);
+ return -1;
+ }
+
+ talloc_free(killtcp);
+ return 0;
+}
+
+
/*
kill a tcp connection
*/
@@ -2286,6 +2392,10 @@ static int kill_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
int ret;
struct ctdb_control_killtcp killtcp;
+ if (argc == 0) {
+ return kill_tcp_from_file(ctdb, argc, argv);
+ }
+
if (argc < 2) {
usage();
}
@@ -5913,7 +6023,7 @@ static const struct {
{ "ipreallocate", control_ipreallocate, true, false, "force the recovery daemon to perform a ip reallocation procedure" },
{ "thaw", control_thaw, true, false, "thaw databases", "[priority:1-3]" },
{ "isnotrecmaster", control_isnotrecmaster, false, false, "check if the local node is recmaster or not" },
- { "killtcp", kill_tcp, false, false, "kill a tcp connection.", "<srcip:port> <dstip:port>" },
+ { "killtcp", kill_tcp, false, false, "kill a tcp connection.", "[<srcip:port> <dstip:port>]" },
{ "gratiousarp", control_gratious_arp, false, false, "send a gratious arp", "<ip> <interface>" },
{ "tickle", tickle_tcp, false, false, "send a tcp tickle ack", "<srcip:port> <dstip:port>" },
{ "gettickles", control_get_tickles, false, false, "get the list of tickles registered for this ip", "<ip> [<port>]" },