From cb879d9f3744190f47cf44cf9bcb1ef705f056a5 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Wed, 11 Oct 2017 11:27:23 -0700 Subject: [PATCH] scoutfs: add network greeting message Add a network greeting message that's exchanged between the client and server on every connection to make sure that we have the correct file system and format hash. Signed-off-by: Zach Brown --- kmod/src/client.c | 30 ++++++++++++++++++++++++++++++ kmod/src/format.h | 5 +++++ kmod/src/server.c | 39 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 73 insertions(+), 1 deletion(-) diff --git a/kmod/src/client.c b/kmod/src/client.c index 8cf43653..16517ccb 100644 --- a/kmod/src/client.c +++ b/kmod/src/client.c @@ -251,9 +251,11 @@ static int client_connect(struct client_info *client) { struct super_block *sb = client->sb; struct scoutfs_super_block super; + struct scoutfs_net_greeting greet; struct sockaddr_in *sin; struct socket *sock = NULL; struct timeval tv; + struct kvec kv; int retries; int addrlen; int optval; @@ -323,6 +325,34 @@ static int client_connect(struct client_info *client) if (ret) continue; + greet.fsid = super.id; + greet.format_hash = super.format_hash; + kv.iov_base = &greet; + kv.iov_len = sizeof(greet); + ret = scoutfs_sock_sendmsg(sock, &kv, 1); + if (ret) + continue; + + ret = scoutfs_sock_recvmsg(sock, &greet, sizeof(greet)); + if (ret) + continue; + + if (greet.fsid != super.id) { + scoutfs_warn(sb, "server "SIN_FMT" has fsid 0x%llx, expected 0x%llx", + SIN_ARG(&client->peername), + le64_to_cpu(greet.fsid), + le64_to_cpu(super.id)); + continue; + } + + if (greet.format_hash != super.format_hash) { + scoutfs_warn(sb, "server "SIN_FMT" has format hash 0x%llx, expected 0x%llx", + SIN_ARG(&client->peername), + le64_to_cpu(greet.format_hash), + le64_to_cpu(super.format_hash)); + continue; + } + /* but use a keepalive timeout instead of send timeout */ tv.tv_sec = 0; tv.tv_usec = 0; diff --git a/kmod/src/format.h b/kmod/src/format.h index d9be949b..ffe5ce44 100644 --- a/kmod/src/format.h +++ b/kmod/src/format.h @@ -566,6 +566,11 @@ struct scoutfs_lock_name { * messages over the wire. */ +struct scoutfs_net_greeting { + __le64 fsid; + __le64 format_hash; +} __packed; + /* * This header precedes and describes all network messages sent over * sockets. The id is set by the request and sent in the reply. The diff --git a/kmod/src/server.c b/kmod/src/server.c index a12da887..007ca7d6 100644 --- a/kmod/src/server.c +++ b/kmod/src/server.c @@ -765,11 +765,16 @@ static void scoutfs_server_recv_func(struct work_struct *work) recv_work); struct server_info *server = conn->server; struct super_block *sb = server->sb; + struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); + struct scoutfs_super_block *super = &sbi->super; struct socket *sock = conn->sock; struct workqueue_struct *req_wq; + struct scoutfs_net_greeting greet; struct scoutfs_net_header nh; struct server_request *req; + bool passed_greeting; unsigned data_len; + struct kvec kv; int ret; req_wq = alloc_workqueue("scoutfs_server_requests", @@ -779,13 +784,45 @@ static void scoutfs_server_recv_func(struct work_struct *work) goto out; } - for (;;) { + /* first bounce the greeting */ + ret = scoutfs_sock_recvmsg(sock, &greet, sizeof(greet)); + if (ret) + goto out; + /* we'll close conn after failed greeting to let client see ours */ + passed_greeting = false; + + if (greet.fsid != super->id) { + scoutfs_warn(sb, "client "SIN_FMT" has fsid 0x%llx, expected 0x%llx", + SIN_ARG(&conn->peername), + le64_to_cpu(greet.fsid), + le64_to_cpu(super->id)); + } else if (greet.format_hash != super->format_hash) { + scoutfs_warn(sb, "client "SIN_FMT" has format hash 0x%llx, expected 0x%llx", + SIN_ARG(&conn->peername), + le64_to_cpu(greet.format_hash), + le64_to_cpu(super->format_hash)); + } else { + passed_greeting = true; + } + + greet.fsid = super->id; + greet.format_hash = super->format_hash; + kv.iov_base = &greet; + kv.iov_len = sizeof(greet); + ret = scoutfs_sock_sendmsg(sock, &kv, 1); + if (ret) + goto out; + + for (;;) { /* receive the header */ ret = scoutfs_sock_recvmsg(sock, &nh, sizeof(nh)); if (ret) break; + if (!passed_greeting) + break; + trace_scoutfs_server_recv_request(conn->server->sb, &conn->sockname, &conn->peername, &nh);