[libvirt] [PATCHv2 2/5] fdstream: Add support for TCP connections of streams

Peter Krempa pkrempa at redhat.com
Mon Dec 10 08:29:41 UTC 2012


This patch adds the backend stuff to enable connecting virStreams to TCP
sockets. This patch adds a helper virFDStreamConnectTCP() that does the
hostname resolution and prepares the filedescriptor for the stream.
---
 src/fdstream.c           | 73 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/fdstream.h           |  5 ++++
 src/libvirt_private.syms |  1 +
 3 files changed, 79 insertions(+)

diff --git a/src/fdstream.c b/src/fdstream.c
index d1eb04c..f026485 100644
--- a/src/fdstream.c
+++ b/src/fdstream.c
@@ -31,6 +31,7 @@
 # include <sys/un.h>
 #endif
 #include <netinet/in.h>
+#include <netdb.h>

 #include "fdstream.h"
 #include "virterror_internal.h"
@@ -565,6 +566,78 @@ int virFDStreamConnectUNIX(virStreamPtr st ATTRIBUTE_UNUSED,
 }
 #endif

+int
+virFDStreamConnectTCP(virStreamPtr st,
+                      const char *address,
+                      const char *service,
+                      unsigned int flags)
+{
+    struct addrinfo hints;
+    struct addrinfo *res = NULL;
+    struct addrinfo *rp;
+    struct sockaddr_in sa;
+
+    int fd = -1;
+    int ret = -1;
+    int rc;
+    int err = 0;
+
+    memset(&sa, 0, sizeof(sa));
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_socktype = SOCK_STREAM; /* TCP connections */
+    hints.ai_family = AF_UNSPEC; /* allow IPv4 and IPv6 */
+
+    if (flags & VIR_NODE_TUNNEL_TCP_IPV4 &&
+        !(flags & VIR_NODE_TUNNEL_TCP_IPV6))
+        hints.ai_family = AF_INET;
+
+    if (flags & VIR_NODE_TUNNEL_TCP_IPV6 &&
+        !(flags & VIR_NODE_TUNNEL_TCP_IPV4))
+        hints.ai_family = AF_INET6;
+
+    if ((rc = getaddrinfo(address, service, &hints, &res)) != 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Failed to reslove address '%s' and service '%s': %s"),
+                       address, service, gai_strerror(rc));
+        goto cleanup;
+    }
+
+    /* try to connect to the remote service */
+   for (rp = res; rp != NULL; rp = rp->ai_next) {
+       fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
+       if (fd == -1) {
+           err = errno;
+           continue;
+       }
+
+       if (connect(fd, rp->ai_addr, rp->ai_addrlen) == 0) {
+           /* success */
+           break;
+       }
+
+       err = errno;
+       VIR_FORCE_CLOSE(fd);
+   }
+
+   if (rp == NULL && fd == -1) {
+       virReportSystemError(err, _("Failed to connect to service '%s' "
+                                   "at node '%s'"), service, address);
+       goto cleanup;
+   }
+
+   if (virFDStreamOpenInternal(st, fd, NULL, -1, 0) < 0) {
+       VIR_FORCE_CLOSE(fd);
+       goto cleanup;
+   }
+
+   ret = 0;
+
+cleanup:
+    freeaddrinfo(res);
+
+    return ret;
+}
+
 static int
 virFDStreamOpenFileInternal(virStreamPtr st,
                             const char *path,
diff --git a/src/fdstream.h b/src/fdstream.h
index 65457d8..296b53f 100644
--- a/src/fdstream.h
+++ b/src/fdstream.h
@@ -40,6 +40,11 @@ int virFDStreamConnectUNIX(virStreamPtr st,
                            const char *path,
                            bool abstract);

+int virFDStreamConnectTCP(virStreamPtr stream,
+                          const char *address,
+                          const char *service,
+                          unsigned int flags);
+
 int virFDStreamOpenFile(virStreamPtr st,
                         const char *path,
                         unsigned long long offset,
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 499ab3b..88b4338 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -636,6 +636,7 @@ virEventPollUpdateTimeout;

 # fdstream.h
 virFDStreamOpen;
+virFDStreamConnectTCP;
 virFDStreamConnectUNIX;
 virFDStreamOpenFile;
 virFDStreamCreateFile;
-- 
1.8.0




More information about the libvir-list mailing list