[PATCH nfs-utils v2 06/12] mount: AF_VSOCK address parsing

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



getaddrinfo(3) does not have AF_VSOCK support.  Parse the CID in the
hostname option and build a struct sockaddr_vm.

There is one tricky thing here: struct addrinfo is normally allocated by
getaddrinfo(3) and freed by freeaddrinfo(3).  The memory allocation of
the struct addrinfo and struct sockaddr are an implementation detail of
libc.  Therefore we must avoid freeaddrinfo(3) calls when the addrinfo
details were filled out by us for AF_VSOCK instead of by getaddrinfo(3).

Signed-off-by: Stefan Hajnoczi <stefanha@xxxxxxxxxx>
---
 utils/mount/stropts.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 58 insertions(+), 5 deletions(-)

diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
index 99656dd..3161609 100644
--- a/utils/mount/stropts.c
+++ b/utils/mount/stropts.c
@@ -898,6 +898,42 @@ fall_back:
 	return nfs_try_mount_v3v2(mi, FALSE);
 }
 
+#ifdef AF_VSOCK
+/* There are no guarantees on how getaddrinfo(3) allocates struct addrinfo so
+ * be sure to call free(3) on *address instead of freeaddrinfo(3).
+ */
+static int vsock_getaddrinfo(struct nfsmount_info *mi,
+			     struct addrinfo **address)
+{
+	struct {
+		struct addrinfo ai;
+		struct sockaddr_vm svm;
+	} *vai;
+	long cid;
+	char *endptr;
+
+	errno = 0;
+	cid = strtol(mi->hostname, &endptr, 10);
+	if (errno != 0 || *endptr != '\0' ||
+	    cid < 0 || cid > UINT_MAX)
+		return EAI_NONAME;
+
+	vai = calloc(1, sizeof(*vai));
+	if (!vai)
+		return EAI_MEMORY;
+
+	vai->ai.ai_family	= AF_VSOCK;
+	vai->ai.ai_socktype	= SOCK_STREAM;
+	vai->ai.ai_addrlen	= sizeof(vai->svm);
+	vai->ai.ai_addr		= (struct sockaddr *)&vai->svm;
+	vai->svm.svm_family	= AF_VSOCK;
+	vai->svm.svm_cid	= cid;
+
+	*address = &vai->ai;
+	return 0;
+}
+#endif /* AF_VSOCK */
+
 /*
  * This is a single pass through the fg/bg loop.
  *
@@ -909,12 +945,21 @@ static int nfs_try_mount(struct nfsmount_info *mi)
 	int result = 0;
 
 	if (mi->address == NULL) {
-		struct addrinfo hint = {};
-		int error;
-		struct addrinfo *address;
+		int error = 0;
+		struct addrinfo *address = NULL;
+
+#ifdef AF_VSOCK
+		if (mi->family == AF_VSOCK)
+			error = vsock_getaddrinfo(mi, &address);
+#endif
+
+		if (error == 0 && !address) {
+			struct addrinfo hint = {};
+
+			hint.ai_family = (int)mi->family;
+			error = getaddrinfo(mi->hostname, NULL, &hint, &address);
+		}
 
-		hint.ai_family = (int)mi->family;
-		error = getaddrinfo(mi->hostname, NULL, &hint, &address);
 		if (error != 0) {
 			if (error == EAI_AGAIN)
 				errno = EAGAIN;
@@ -1209,6 +1254,14 @@ int nfsmount_string(const char *spec, const char *node, const char *type,
 	} else
 		nfs_error(_("%s: internal option parsing error"), progname);
 
+#ifdef AF_VSOCK
+	/* See vsock_getaddrinfo() for why we cannot use freeaddrinfo(3) */
+	if (mi.address && mi.address->ai_family == AF_VSOCK) {
+		free(mi.address);
+		mi.address = NULL;
+	}
+#endif
+
 	freeaddrinfo(mi.address);
 	free(mi.hostname);
 	return retval;
-- 
2.9.4

--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux