The Samba-Bugzilla – Attachment 14941 Details for
Bug 13839
CTDB failover does not kill server end of connections for IPv4-mapped IPv6 addresses
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch for 4.8
BZ13839-v4-8.patch (text/plain), 25.68 KB, created by
Martin Schwenke
on 2019-03-19 03:55:52 UTC
(
hide
)
Description:
Patch for 4.8
Filename:
MIME Type:
Creator:
Martin Schwenke
Created:
2019-03-19 03:55:52 UTC
Size:
25.68 KB
patch
obsolete
>From 4a757eb34173a14bf07cd49362a4f7d78bb04eba Mon Sep 17 00:00:00 2001 >From: Amitay Isaacs <amitay@gmail.com> >Date: Wed, 18 Jul 2018 18:42:10 +1000 >Subject: [PATCH 1/5] ctdb-common: Add line based I/O > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=13520 > >Signed-off-by: Amitay Isaacs <amitay@gmail.com> >Reviewed-by: Martin Schwenke <martin@meltin.net> >(cherry picked from commit c7041b0faf490661818244dd032ad413ce906e5c) >--- > ctdb/common/line.c | 145 ++++++++++++++++++++++++++++++ > ctdb/common/line.h | 62 +++++++++++++ > ctdb/tests/cunit/line_test_001.sh | 90 +++++++++++++++++++ > ctdb/tests/src/line_test.c | 102 +++++++++++++++++++++ > ctdb/wscript | 5 +- > 5 files changed, 403 insertions(+), 1 deletion(-) > create mode 100644 ctdb/common/line.c > create mode 100644 ctdb/common/line.h > create mode 100755 ctdb/tests/cunit/line_test_001.sh > create mode 100644 ctdb/tests/src/line_test.c > >diff --git a/ctdb/common/line.c b/ctdb/common/line.c >new file mode 100644 >index 00000000000..c4c6726875b >--- /dev/null >+++ b/ctdb/common/line.c >@@ -0,0 +1,145 @@ >+/* >+ Line based I/O over fds >+ >+ Copyright (C) Amitay Isaacs 2018 >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 3 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, see <http://www.gnu.org/licenses/>. >+*/ >+ >+#include "replace.h" >+ >+#include <talloc.h> >+ >+#include "lib/util/sys_rw.h" >+ >+#include "common/line.h" >+ >+struct line_read_state { >+ line_process_fn_t callback; >+ void *private_data; >+ char *buf; >+ size_t hint, len, offset; >+ int num_lines; >+}; >+ >+static bool line_read_one(char *buf, size_t start, size_t len, size_t *pos) >+{ >+ size_t i; >+ >+ for (i=start; i<len; i++) { >+ if (buf[i] == '\n' || buf[i] == '\0') { >+ *pos = i; >+ return true; >+ } >+ } >+ >+ return false; >+} >+ >+static int line_read_process(struct line_read_state *state) >+{ >+ size_t start = 0; >+ size_t pos = 0; >+ >+ while (1) { >+ int ret; >+ bool ok; >+ >+ ok = line_read_one(state->buf, start, state->offset, &pos); >+ if (! ok) { >+ break; >+ } >+ >+ state->buf[pos] = '\0'; >+ state->num_lines += 1; >+ >+ ret = state->callback(state->buf + start, state->private_data); >+ if (ret != 0) { >+ return ret; >+ } >+ >+ start = pos+1; >+ } >+ >+ if (pos > 0) { >+ if (pos+1 < state->offset) { >+ memmove(state->buf, >+ state->buf + pos+1, >+ state->offset - (pos+1)); >+ } >+ state->offset -= (pos+1); >+ } >+ >+ return 0; >+} >+ >+int line_read(int fd, >+ size_t length, >+ TALLOC_CTX *mem_ctx, >+ line_process_fn_t callback, >+ void *private_data, >+ int *num_lines) >+{ >+ struct line_read_state state; >+ >+ if (length < 32) { >+ length = 32; >+ } >+ >+ state = (struct line_read_state) { >+ .callback = callback, >+ .private_data = private_data, >+ .hint = length, >+ }; >+ >+ while (1) { >+ ssize_t n; >+ int ret; >+ >+ if (state.offset == state.len) { >+ state.len += state.hint; >+ state.buf = talloc_realloc_size(mem_ctx, >+ state.buf, >+ state.len); >+ if (state.buf == NULL) { >+ return ENOMEM; >+ } >+ } >+ >+ n = sys_read(fd, >+ state.buf + state.offset, >+ state.len - state.offset); >+ if (n < 0) { >+ return errno; >+ } >+ if (n == 0) { >+ break; >+ } >+ >+ state.offset += n; >+ >+ ret = line_read_process(&state); >+ if (ret != 0) { >+ if (num_lines != NULL) { >+ *num_lines = state.num_lines; >+ } >+ return ret; >+ } >+ } >+ >+ if (num_lines != NULL) { >+ *num_lines = state.num_lines; >+ } >+ return 0; >+} >diff --git a/ctdb/common/line.h b/ctdb/common/line.h >new file mode 100644 >index 00000000000..6b67f1e92e1 >--- /dev/null >+++ b/ctdb/common/line.h >@@ -0,0 +1,62 @@ >+/* >+ Line based I/O over fds >+ >+ Copyright (C) Amitay Isaacs 2018 >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 3 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, see <http://www.gnu.org/licenses/>. >+*/ >+ >+#ifndef __CTDB_LINE_H__ >+#define __CTDB_LINE_H__ >+ >+#include <talloc.h> >+ >+/** >+ * @file line.h >+ * >+ * @brief Line based I/O over pipes and sockets >+ */ >+ >+/** >+ * @brief The callback routine called to process a line >+ * >+ * @param[in] line The line read >+ * @param[in] private_data Private data for callback >+ * @return 0 to continue processing lines, non-zero to stop reading >+ */ >+typedef int (*line_process_fn_t)(char *line, void *private_data); >+ >+/** >+ * @brief Read a line (terminated by \n or \0) >+ * >+ * If there is any read error on fd, then errno will be returned. >+ * If callback function returns a non-zero value, then that value will be >+ * returned. >+ * >+ * @param[in] fd The file descriptor >+ * @param[in] length The expected length of a line (this is only a hint) >+ * @param[in] mem_ctx Talloc memory context >+ * @param[in] callback Callback function called when a line is read >+ * @param[in] private_data Private data for callback >+ * @param[out] num_lines Number of lines read so far >+ * @return 0 on on success, errno on failure >+ */ >+int line_read(int fd, >+ size_t length, >+ TALLOC_CTX *mem_ctx, >+ line_process_fn_t callback, >+ void *private_data, >+ int *num_lines); >+ >+#endif /* __CTDB_LINE_H__ */ >diff --git a/ctdb/tests/cunit/line_test_001.sh b/ctdb/tests/cunit/line_test_001.sh >new file mode 100755 >index 00000000000..991d01a24e7 >--- /dev/null >+++ b/ctdb/tests/cunit/line_test_001.sh >@@ -0,0 +1,90 @@ >+#!/bin/sh >+ >+. "${TEST_SCRIPTS_DIR}/unit.sh" >+ >+tfile="${TEST_VAR_DIR}/line.$$" >+ >+remove_files () >+{ >+ rm -f "$tfile" >+} >+ >+test_cleanup remove_files >+ >+> "$tfile" >+ >+ok_null >+unit_test line_test "$tfile" >+ >+printf "\0" > "$tfile" >+ >+required_result 1 <<EOF >+ >+EOF >+ >+unit_test line_test "$tfile" >+ >+echo -n "hello" > "$tfile" >+ >+ok_null >+unit_test line_test "$tfile" >+ >+cat <<EOF > "$tfile" >+hello >+world >+EOF >+ >+required_result 2 << EOF >+hello >+world >+EOF >+unit_test line_test "$tfile" >+ >+required_result 2 << EOF >+hello >+world >+EOF >+unit_test line_test "$tfile" >+ >+cat <<EOF > "$tfile" >+This is a really long long line full of random words and hopefully it will be read properly by the line test program and identified as a single line >+EOF >+ >+required_result 1 <<EOF >+This is a really long long line full of random words and hopefully it will be read properly by the line test program and identified as a single line >+EOF >+unit_test line_test "$tfile" >+ >+cat <<EOF > "$tfile" >+line number one >+line number two >+line number one >+line number two >+line number one >+EOF >+ >+required_result 5 <<EOF >+line number one >+line number two >+line number one >+line number two >+line number one >+EOF >+unit_test line_test "$tfile" 64 >+ >+cat <<EOF > "$tfile" >+this is line number one >+this is line number two >+this is line number three >+this is line number four >+this is line number five >+EOF >+ >+required_result 5 <<EOF >+this is line number one >+this is line number two >+this is line number three >+this is line number four >+this is line number five >+EOF >+unit_test line_test "$tfile" 64 >diff --git a/ctdb/tests/src/line_test.c b/ctdb/tests/src/line_test.c >new file mode 100644 >index 00000000000..0c5a8211392 >--- /dev/null >+++ b/ctdb/tests/src/line_test.c >@@ -0,0 +1,102 @@ >+/* >+ Test code for line based I/O over fds >+ >+ Copyright (C) Amitay Isaacs 2018 >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 3 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, see <http://www.gnu.org/licenses/>. >+*/ >+ >+#include "replace.h" >+#include "system/filesys.h" >+ >+#include <talloc.h> >+#include <assert.h> >+ >+#include "common/line.c" >+ >+static int line_print(char *line, void *private_data) >+{ >+ printf("%s\n", line); >+ fflush(stdout); >+ >+ return 0; >+} >+ >+int main(int argc, const char **argv) >+{ >+ TALLOC_CTX *mem_ctx; >+ size_t hint = 32; >+ pid_t pid; >+ int ret, lines = 0; >+ int pipefd[2]; >+ >+ if (argc < 2 || argc > 3) { >+ fprintf(stderr, "Usage: %s <filename> [<hint>]\n", argv[0]); >+ exit(1); >+ } >+ >+ if (argc == 3) { >+ long value; >+ >+ value = atol(argv[2]); >+ assert(value > 0); >+ hint = value; >+ } >+ >+ ret = pipe(pipefd); >+ assert(ret == 0); >+ >+ pid = fork(); >+ assert(pid != -1); >+ >+ if (pid == 0) { >+ char buffer[16]; >+ ssize_t n, n2; >+ int fd; >+ >+ close(pipefd[0]); >+ >+ fd = open(argv[1], O_RDONLY); >+ assert(fd != -1); >+ >+ while (1) { >+ n = read(fd, buffer, sizeof(buffer)); >+ assert(n >= 0 && n <= sizeof(buffer)); >+ >+ if (n == 0) { >+ break; >+ } >+ >+ n2 = write(pipefd[1], buffer, n); >+ assert(n2 == n); >+ } >+ >+ close(pipefd[1]); >+ close(fd); >+ >+ exit(0); >+ } >+ >+ close(pipefd[1]); >+ >+ mem_ctx = talloc_new(NULL); >+ assert(mem_ctx != NULL); >+ >+ ret = line_read(pipefd[0], hint, NULL, line_print, NULL, &lines); >+ assert(ret == 0); >+ >+ talloc_free(mem_ctx); >+ >+ return lines; >+} >diff --git a/ctdb/wscript b/ctdb/wscript >index f8259c7c1d6..e3bcdf7e962 100644 >--- a/ctdb/wscript >+++ b/ctdb/wscript >@@ -409,7 +409,9 @@ def build(bld): > logging.c rb_tree.c tunable.c > pidfile.c run_proc.c > hash_count.c run_event.c >- sock_client.c version.c'''), >+ sock_client.c version.c >+ line.c >+ '''), > deps='''samba-util sys_rw tevent-util > replace talloc tevent tdb''') > >@@ -765,6 +767,7 @@ def build(bld): > 'sock_io_test', > 'hash_count_test', > 'run_event_test', >+ 'line_test', > ] > > for target in ctdb_unit_tests: >-- >2.20.1 > > >From f05d1defcdaee7820c33d7db30fcd96ff9ca693b Mon Sep 17 00:00:00 2001 >From: Amitay Isaacs <amitay@gmail.com> >Date: Wed, 11 Jul 2018 18:35:46 +1000 >Subject: [PATCH 2/5] ctdb-protocol: Avoid fgets in ctdb_connection_list_read > >C library buffering API can behave in unexpected fashion if underlying >fd for stdin, stdout or stderr is closed and re-opened. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=13520 > >Signed-off-by: Amitay Isaacs <amitay@gmail.com> >Reviewed-by: Martin Schwenke <martin@meltin.net> >(cherry picked from commit c9b42d27e6cf9e6ae36f44970f0a388edc737a7a) >--- > ctdb/protocol/protocol_util.c | 86 ++++++++++++++++++++--------------- > ctdb/wscript | 4 +- > 2 files changed, 51 insertions(+), 39 deletions(-) > >diff --git a/ctdb/protocol/protocol_util.c b/ctdb/protocol/protocol_util.c >index c75555fa734..45c639d747f 100644 >--- a/ctdb/protocol/protocol_util.c >+++ b/ctdb/protocol/protocol_util.c >@@ -22,6 +22,8 @@ > > #include <talloc.h> > >+#include "common/line.h" >+ > #include "protocol.h" > #include "protocol_util.h" > >@@ -603,56 +605,66 @@ const char *ctdb_connection_list_to_string( > return out; > } > >-int ctdb_connection_list_read(TALLOC_CTX *mem_ctx, bool client_first, >- struct ctdb_connection_list **conn_list) >-{ >+struct ctdb_connection_list_read_state { > struct ctdb_connection_list *list; >- char line[128]; /* long enough for IPv6 */ >+ bool client_first; >+}; >+ >+static int ctdb_connection_list_read_line(char *line, void *private_data) >+{ >+ struct ctdb_connection_list_read_state *state = >+ (struct ctdb_connection_list_read_state *)private_data; >+ struct ctdb_connection conn; > int ret; > >- if (conn_list == NULL) { >- return EINVAL; >+ /* Skip empty lines */ >+ if (line[0] == '\0') { >+ return 0; > } > >- list = talloc_zero(mem_ctx, struct ctdb_connection_list); >- if (list == NULL) { >- return ENOMEM; >+ /* Comment */ >+ if (line[0] == '#') { >+ return 0; > } > >- while (fgets(line, sizeof(line), stdin) != NULL) { >- char *t; >- struct ctdb_connection conn; >+ ret = ctdb_connection_from_string(line, state->client_first, &conn); >+ if (ret != 0) { >+ return ret; >+ } > >- /* Skip empty lines */ >- if (line[0] == '\n') { >- continue; >- } >+ ret = ctdb_connection_list_add(state->list, &conn); >+ if (ret != 0) { >+ return ret; >+ } > >- /* Comment */ >- if (line[0] == '#') { >- continue; >- } >+ return 0; >+} > >- t = strtok(line, "\n"); >- if (t == NULL) { >- goto fail; >- } >+int ctdb_connection_list_read(TALLOC_CTX *mem_ctx, bool client_first, >+ struct ctdb_connection_list **conn_list) >+{ >+ struct ctdb_connection_list_read_state state; >+ int ret; > >- ret = ctdb_connection_from_string(t, client_first, &conn); >- if (ret != 0) { >- goto fail; >- } >+ if (conn_list == NULL) { >+ return EINVAL; >+ } > >- ret = ctdb_connection_list_add(list, &conn); >- if (ret != 0) { >- goto fail; >- } >+ state.list = talloc_zero(mem_ctx, struct ctdb_connection_list); >+ if (state.list == NULL) { >+ return ENOMEM; > } > >- *conn_list = list; >- return 0; >+ state.client_first = client_first; >+ >+ ret = line_read(0, >+ 128, >+ mem_ctx, >+ ctdb_connection_list_read_line, >+ &state, >+ NULL); > >-fail: >- talloc_free(list); >- return EINVAL; >+ *conn_list = state.list; >+ >+ return ret; > } >diff --git a/ctdb/wscript b/ctdb/wscript >index e3bcdf7e962..8727fd8aefa 100644 >--- a/ctdb/wscript >+++ b/ctdb/wscript >@@ -433,7 +433,7 @@ def build(bld): > > bld.SAMBA_SUBSYSTEM('ctdb-protocol-util', > source='protocol/protocol_util.c', >- deps='replace talloc tdb') >+ deps='ctdb-util replace talloc tdb') > > bld.SAMBA_SUBSYSTEM('ctdb-client', > source=bld.SUBDIR('client', 'ctdb_client.c'), >@@ -824,7 +824,7 @@ def build(bld): > bld.SAMBA_BINARY(target, > source=src, > deps='''protocol-tests-common >- samba-util talloc tdb''', >+ samba-util ctdb-util talloc tdb''', > install_path='${CTDB_TEST_LIBEXECDIR}') > > bld.SAMBA_SUBSYSTEM('ctdb-tests-common', >-- >2.20.1 > > >From cc42044a131b7919e7f781ff5203788687c58d2f Mon Sep 17 00:00:00 2001 >From: Amitay Isaacs <amitay@gmail.com> >Date: Wed, 18 Jul 2018 19:00:42 +1000 >Subject: [PATCH 3/5] ctdb-common: Add fd argument to > ctdb_connection_list_read() > >This makes testing easier. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=13520 > >Signed-off-by: Amitay Isaacs <amitay@gmail.com> >Reviewed-by: Martin Schwenke <martin@meltin.net> >(cherry picked from commit 3bf753e830c20183ef4f3278880d3be362e53bef) >--- > ctdb/protocol/protocol_util.c | 6 ++++-- > ctdb/protocol/protocol_util.h | 4 +++- > ctdb/tests/src/protocol_util_test.c | 18 ++++++------------ > ctdb/tools/ctdb.c | 6 +++--- > ctdb/tools/ctdb_killtcp.c | 2 +- > 5 files changed, 17 insertions(+), 19 deletions(-) > >diff --git a/ctdb/protocol/protocol_util.c b/ctdb/protocol/protocol_util.c >index 45c639d747f..77e79867443 100644 >--- a/ctdb/protocol/protocol_util.c >+++ b/ctdb/protocol/protocol_util.c >@@ -640,7 +640,9 @@ static int ctdb_connection_list_read_line(char *line, void *private_data) > return 0; > } > >-int ctdb_connection_list_read(TALLOC_CTX *mem_ctx, bool client_first, >+int ctdb_connection_list_read(TALLOC_CTX *mem_ctx, >+ int fd, >+ bool client_first, > struct ctdb_connection_list **conn_list) > { > struct ctdb_connection_list_read_state state; >@@ -657,7 +659,7 @@ int ctdb_connection_list_read(TALLOC_CTX *mem_ctx, bool client_first, > > state.client_first = client_first; > >- ret = line_read(0, >+ ret = line_read(fd, > 128, > mem_ctx, > ctdb_connection_list_read_line, >diff --git a/ctdb/protocol/protocol_util.h b/ctdb/protocol/protocol_util.h >index 66a49136576..347fe8a275a 100644 >--- a/ctdb/protocol/protocol_util.h >+++ b/ctdb/protocol/protocol_util.h >@@ -66,7 +66,9 @@ int ctdb_connection_list_sort(struct ctdb_connection_list *conn_list); > const char *ctdb_connection_list_to_string( > TALLOC_CTX *mem_ctx, > struct ctdb_connection_list *conn_list, bool client_first); >-int ctdb_connection_list_read(TALLOC_CTX *mem_ctx, bool client_first, >+int ctdb_connection_list_read(TALLOC_CTX *mem_ctx, >+ int fd, >+ bool client_first, > struct ctdb_connection_list **conn_list); > > #endif /* __CTDB_PROTOCOL_UTIL_H__ */ >diff --git a/ctdb/tests/src/protocol_util_test.c b/ctdb/tests/src/protocol_util_test.c >index eb7eb0ff88f..5608b13920c 100644 >--- a/ctdb/tests/src/protocol_util_test.c >+++ b/ctdb/tests/src/protocol_util_test.c >@@ -153,7 +153,7 @@ static void test_connection_list_read(const char *s1, const char *s2) > TALLOC_CTX *tmp_ctx; > int pipefd[2]; > pid_t pid; >- struct ctdb_connection_list *conn_list; >+ struct ctdb_connection_list *conn_list = NULL; > const char *t; > int ret; > >@@ -182,14 +182,11 @@ static void test_connection_list_read(const char *s1, const char *s2) > > close(pipefd[1]); > >- ret = dup2(pipefd[0], STDIN_FILENO); >- assert(ret != -1); >+ ret = ctdb_connection_list_read(tmp_ctx, pipefd[0], false, &conn_list); >+ assert(ret == 0); > > close(pipefd[0]); > >- ret = ctdb_connection_list_read(tmp_ctx, false, &conn_list); >- assert(ret == 0); >- > ret = ctdb_connection_list_sort(conn_list); > assert(ret == 0); > >@@ -206,7 +203,7 @@ static void test_connection_list_read_bad(const char *s1) > TALLOC_CTX *tmp_ctx; > int pipefd[2]; > pid_t pid; >- struct ctdb_connection_list *conn_list; >+ struct ctdb_connection_list *conn_list = NULL; > int ret; > > tmp_ctx = talloc_new(NULL); >@@ -234,14 +231,11 @@ static void test_connection_list_read_bad(const char *s1) > > close(pipefd[1]); > >- ret = dup2(pipefd[0], STDIN_FILENO); >- assert(ret != -1); >+ ret = ctdb_connection_list_read(tmp_ctx, pipefd[0], false, &conn_list); >+ assert(ret == EINVAL); > > close(pipefd[0]); > >- ret = ctdb_connection_list_read(tmp_ctx, false, &conn_list); >- assert(ret == EINVAL); >- > talloc_free(tmp_ctx); > } > >diff --git a/ctdb/tools/ctdb.c b/ctdb/tools/ctdb.c >index 2cb46b057f0..a6f8f2904dd 100644 >--- a/ctdb/tools/ctdb.c >+++ b/ctdb/tools/ctdb.c >@@ -3023,7 +3023,7 @@ static int control_tickle(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb, > int i, num_failed; > > /* Client first but the src/dst logic is confused */ >- ret = ctdb_connection_list_read(mem_ctx, false, &clist); >+ ret = ctdb_connection_list_read(mem_ctx, 0, false, &clist); > if (ret != 0) { > return ret; > } >@@ -3241,7 +3241,7 @@ static int control_addtickle(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb, > struct tevent_req *req; > > /* Client first but the src/dst logic is confused */ >- ret = ctdb_connection_list_read(mem_ctx, false, &clist); >+ ret = ctdb_connection_list_read(mem_ctx, 0, false, &clist); > if (ret != 0) { > return ret; > } >@@ -3306,7 +3306,7 @@ static int control_deltickle(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb, > struct tevent_req *req; > > /* Client first but the src/dst logic is confused */ >- ret = ctdb_connection_list_read(mem_ctx, false, &clist); >+ ret = ctdb_connection_list_read(mem_ctx, 0, false, &clist); > if (ret != 0) { > return ret; > } >diff --git a/ctdb/tools/ctdb_killtcp.c b/ctdb/tools/ctdb_killtcp.c >index da497d21d57..b35331d02ed 100644 >--- a/ctdb/tools/ctdb_killtcp.c >+++ b/ctdb/tools/ctdb_killtcp.c >@@ -372,7 +372,7 @@ int main(int argc, char **argv) > goto fail; > } > } else { >- ret = ctdb_connection_list_read(mem_ctx, true, &conn_list); >+ ret = ctdb_connection_list_read(mem_ctx, 0, true, &conn_list); > if (ret != 0) { > D_ERR("Unable to parse connections (%s)\n", > strerror(ret)); >-- >2.20.1 > > >From edbad0618993012106747efb5829ead8bf6c48a9 Mon Sep 17 00:00:00 2001 >From: Zhu Shangzhong <zhu.shangzhong@zte.com.cn> >Date: Tue, 12 Mar 2019 20:49:48 +0800 >Subject: [PATCH 4/5] ctdb: Initialize addr struct to zero before reparsing as > IPV4 > >Failed to kill the tcp connection that using IPv4-mapped IPv6 address >(e.g. ctdb_killtcp eth0 ::ffff:192.168.200.44:2049 >::ffff:192.168.200.45:863). > >When the ctdb_killtcp is used to kill the tcp connection, the IPs and >ports in the connection will be parsed to conn.client and conn.server >(call stack: main->ctdb_sock_addr_from_string->ip_from_string). In >the ip_from_string, as we are using IPv4-mapped IPv6 addresses, the >ipv6_from_string will be used to parse ip to addr.ip6 first. The next >step the ipv4_from_string will be used to reparse ip to addr.ip. > >As a result, the data that dump from conn.server is "2 0 8 1 192 168 >200 44 0 0 0 0 0 0 0 0 0 0 255 255 192 168 200 44 0 0 0 0", the data >from conn.client is "2 0 3 95 192 168 200 45 0 0 0 0 0 0 0 0 0 0 255 255 >192 168 200 45 0 0 0 0". The connection will be add to conn_list by >ctdb_connection_list_add. Then the reset_connections_send uses conn_list >as parameter to start to reset connections in the conn_list. > >In the reset_connections_send, the database "connections" will be >created. The connections from conn_list will be written to the >database(call db_hash_add), and use the data that dump from conn_client >and conn_server as key. > >In the reset_connections_capture_tcp_handler, the >ctdb_sys_read_tcp_packet will receive data on the raw socket. And >extract the IPs and ports from the tcp packet. when extracting IP and >port, the tcp4_extract OR tcp6_extract will be used. Then we got the >new conn.client and conn.server. the data that dump from the >conn.server is "2 0 8 1 192 168 200 44 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 >0 0 0", the data from conn.client is "2 0 3 95 192 168 200 45 0 0 0 0 0 >0 0 0 0 0 0 0 0 0 0 0 0 0 0 0". Finally, we use the data as key to check >if this connection is one being reset(call db_hash_delete). The >db_hash_delete will return ENOENT. Because the two key that being used >by db_hash_delete and db_hash_add are different. > >So, the TCP RST will be NOT sent for the connection forever. We should >initialize addr struct to zero before reparsing as IPV4 in the >ip_from_string. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=13839 > >Signed-off-by: Zhu Shangzhong <zhu.shangzhong@zte.com.cn> >Reviewed-by: Martin Schwenke <martin@meltin.net> >Reviewed-by: Amitay Isaacs <amitay@samba.org> >(cherry picked from commit 539b5ff32b32b7c75dfaaa119e41f5af6ff1e6fc) >--- > ctdb/protocol/protocol_util.c | 3 +++ > 1 file changed, 3 insertions(+) > >diff --git a/ctdb/protocol/protocol_util.c b/ctdb/protocol/protocol_util.c >index 77e79867443..a46cde9f46f 100644 >--- a/ctdb/protocol/protocol_util.c >+++ b/ctdb/protocol/protocol_util.c >@@ -251,6 +251,9 @@ static int ip_from_string(const char *str, ctdb_sock_addr *addr) > if (memcmp(&addr->ip6.sin6_addr.s6_addr[0], > ipv4_mapped_prefix, > sizeof(ipv4_mapped_prefix)) == 0) { >+ /* Initialize addr struct to zero before reparsing as IPV4 */ >+ ZERO_STRUCTP(addr); >+ > /* Reparse as IPv4 */ > ret = ipv4_from_string(p+1, &addr->ip); > } >-- >2.20.1 > > >From 03e9900c7233d6e2d802a178c76e6720e72715bc Mon Sep 17 00:00:00 2001 >From: Martin Schwenke <martin@meltin.net> >Date: Thu, 14 Mar 2019 16:32:02 +1100 >Subject: [PATCH 5/5] ctdb-tests: Add some testing for IPv4-mapped IPv6 address > parsing > >ctdb_sock_addr values are hashed in some contexts. This means that >all of the memory used for the ctdb_sock_addr should be consistent >regardless of how parsing is done. The first 2 cases are just sanity >checks but the 3rd case involving an IPv4-mapped IPv6 address is the >real target of this test addition. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=13839 > >Signed-off-by: Martin Schwenke <martin@meltin.net> >Reviewed-by: Amitay Isaacs <amitay@samba.org> >(cherry picked from commit d9286701cd9253bf3b42cac3d850ae8c23743e6d) >--- > ctdb/tests/src/protocol_util_test.c | 19 +++++++++++++++++++ > 1 file changed, 19 insertions(+) > >diff --git a/ctdb/tests/src/protocol_util_test.c b/ctdb/tests/src/protocol_util_test.c >index 5608b13920c..9be95eca2ef 100644 >--- a/ctdb/tests/src/protocol_util_test.c >+++ b/ctdb/tests/src/protocol_util_test.c >@@ -52,6 +52,20 @@ static void test_sock_addr_from_string_bad(const char *ip, bool with_port) > assert(ret == EINVAL); > } > >+static void test_sock_addr_from_string_memcmp(const char *ip1, >+ const char* ip2) >+{ >+ ctdb_sock_addr sa1, sa2; >+ int ret; >+ >+ ret = ctdb_sock_addr_from_string(ip1, &sa1, false); >+ assert(ret == 0); >+ ret = ctdb_sock_addr_from_string(ip2, &sa2, false); >+ assert(ret == 0); >+ ret = memcmp(&sa1, &sa2, sizeof(ctdb_sock_addr)); >+ assert(ret == 0); >+} >+ > static void test_sock_addr_cmp(const char *ip1, const char *ip2, > bool with_port, int res) > { >@@ -299,6 +313,11 @@ int main(int argc, char *argv[]) > test_sock_addr_from_string_bad("junk", false); > test_sock_addr_from_string_bad("0.0.0.0:0 trailing junk", true); > >+ test_sock_addr_from_string_memcmp("127.0.0.1", "127.0.0.1"); >+ test_sock_addr_from_string_memcmp("fe80::6af7:28ff:fefa:d136", >+ "fe80::6af7:28ff:fefa:d136"); >+ test_sock_addr_from_string_memcmp("::ffff:192.0.2.128", "192.0.2.128"); >+ > test_sock_addr_cmp("127.0.0.1", "127.0.0.1" , false, 0); > test_sock_addr_cmp("127.0.0.1", "127.0.0.2" , false, -1); > test_sock_addr_cmp("127.0.0.2", "127.0.0.1" , false, 1); >-- >2.20.1 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Flags:
amitay
:
review+
Actions:
View
Attachments on
bug 13839
:
14939
|
14940
| 14941