[04/11] inet: dump source and destination addresses for closed sockets

Submitted by Andrei Vagin on Nov. 11, 2016, 7:10 a.m.

Details

Message ID 1478848211-23802-5-git-send-email-avagin@openvz.org
State Superseded
Series "tcp: add support of half closed tcp sockets"
Headers show

Commit Message

Andrei Vagin Nov. 11, 2016, 7:10 a.m.
From: Andrei Vagin <avagin@virtuozzo.com>

If a socket has been closed, it still has both addresses and
we need to dump them.

Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
---
 criu/sk-inet.c | 61 +++++++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 45 insertions(+), 16 deletions(-)

Patch hide | download patch | download mbox

diff --git a/criu/sk-inet.c b/criu/sk-inet.c
index 924cf8c..5807ed2 100644
--- a/criu/sk-inet.c
+++ b/criu/sk-inet.c
@@ -180,10 +180,30 @@  static int can_dump_inet_sk(const struct inet_sk_desc *sk)
 	return 1;
 }
 
+union sockaddr_inet {
+	struct sockaddr addr;
+	struct sockaddr_in v4;
+	struct sockaddr_in6 v6;
+};
+
+static int dump_sockaddr(union sockaddr_inet *sa, u32 *pb_port, u32 *pb_addr)
+{
+	if (sa->addr.sa_family == AF_INET) {
+		memcpy(pb_addr, &sa->v4.sin_addr, sizeof(sa->v4.sin_addr));
+		*pb_port = ntohs(sa->v4.sin_port);
+		return 0;
+	} if (sa->addr.sa_family == AF_INET6) {
+		*pb_port = ntohs(sa->v6.sin6_port);
+		memcpy(pb_addr, &sa->v6.sin6_addr, sizeof(sa->v6.sin6_addr));
+		return 0;
+	}
+	return -1;
+}
+
 static struct inet_sk_desc *gen_uncon_sk(int lfd, const struct fd_parms *p, int proto)
 {
 	struct inet_sk_desc *sk;
-	char address;
+	union sockaddr_inet address;
 	socklen_t aux;
 	int ret;
 
@@ -191,26 +211,40 @@  static struct inet_sk_desc *gen_uncon_sk(int lfd, const struct fd_parms *p, int
 	if (!sk)
 		goto err;
 
-	/* It should has no peer name */
-	aux = sizeof(address);
+	ret  = do_dump_opt(lfd, SOL_SOCKET, SO_DOMAIN, &sk->sd.family, sizeof(sk->sd.family));
+	ret |= do_dump_opt(lfd, SOL_SOCKET, SO_TYPE, &sk->type, sizeof(sk->type));
+	if (ret)
+		goto err;
+
+	if (sk->sd.family == AF_INET)
+		aux = sizeof(struct sockaddr_in);
+	else if (sk->sd.family == AF_INET6)
+		aux = sizeof(struct sockaddr_in6);
+	else {
+		pr_err("Unsupported socket family: %d\n", sk->sd.family);
+		goto err;
+	}
+
 	ret = getsockopt(lfd, SOL_SOCKET, SO_PEERNAME, &address, &aux);
 	if (ret < 0) {
 		if (errno != ENOTCONN) {
 			pr_perror("Unexpected error returned from unconnected socket");
 			goto err;
 		}
-	} else if (ret == 0) {
-		pr_err("Name resolved on unconnected socket\n");
+	} else if (dump_sockaddr(&address, &sk->dst_port, sk->dst_addr))
 		goto err;
-	}
 
-	sk->sd.ino = p->stat.st_ino;
-
-	ret  = do_dump_opt(lfd, SOL_SOCKET, SO_DOMAIN, &sk->sd.family, sizeof(sk->sd.family));
-	ret |= do_dump_opt(lfd, SOL_SOCKET, SO_TYPE, &sk->type, sizeof(sk->type));
-	if (ret)
+	ret = getsockname(lfd, &address.addr, &aux);
+	if (ret < 0) {
+		if (errno != ENOTCONN) {
+			pr_perror("Unexpected error returned from unconnected socket");
+			goto err;
+		}
+	} else if (dump_sockaddr(&address, &sk->src_port, sk->src_addr))
 		goto err;
 
+	sk->sd.ino = p->stat.st_ino;
+
 	if (proto == IPPROTO_TCP) {
 		struct tcp_info info;
 
@@ -654,11 +688,6 @@  err:
 	return -1;
 }
 
-union sockaddr_inet {
-	struct sockaddr_in v4;
-	struct sockaddr_in6 v6;
-};
-
 static int restore_sockaddr(union sockaddr_inet *sa,
 		int family, u32 pb_port, u32 *pb_addr, u32 ifindex)
 {