diff options
author | Zhu Shangzhong <zhu.shangzhong@zte.com.cn> | 2019-03-12 20:49:48 +0800 |
---|---|---|
committer | Karolin Seeger <kseeger@samba.org> | 2019-03-26 07:49:18 +0000 |
commit | 02da215c10422d28fbe8646f5dca07448c12d7e1 (patch) | |
tree | ed37e059b7eb4e05b254fe9db95dd7378fb47579 /ctdb | |
parent | aeba27d3a48fc4bbe06cf2f0d646711f7fb86d31 (diff) | |
download | samba-02da215c10422d28fbe8646f5dca07448c12d7e1.tar.gz |
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)
Diffstat (limited to 'ctdb')
-rw-r--r-- | ctdb/protocol/protocol_util.c | 3 |
1 files changed, 3 insertions, 0 deletions
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); } |