On 06.12.2012 19:36, Peter Krempa wrote:
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..d35308e 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(errno, _("Failed to connect to service '%s'
"
+ "at node '%s'"), service,
address);\
I believe this wants to be s/errno/err/.
+ 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 bc01fe5..911f441 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -636,6 +636,7 @@ virEventPollUpdateTimeout;
# fdstream.h
virFDStreamOpen;
+virFDStreamConnectTCP;
virFDStreamConnectUNIX;
virFDStreamOpenFile;
virFDStreamCreateFile;