[libvirt] [PATCHv2 1/5] api: Add API to allow TCP tunneling through streams to the host

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


This patch adds API that will allow to use streams to connect to TCP
sockets from the point of view of the host. This API is intended to
allow remote display (SPICE/VNC) sessions to managed hosts that prefer
not to expose the ports to outer networks and without the need to
configure TCP tunneling through ssh or firewalls.

The API takes the remote hostname and port as arguments and is
configurable using flags. The user may specify to use IPv4 or IPv6 using
them.
---
 include/libvirt/libvirt.h.in | 11 ++++++++
 src/driver.h                 |  8 ++++++
 src/libvirt.c                | 67 ++++++++++++++++++++++++++++++++++++++++++++
 src/libvirt_public.syms      |  1 +
 src/remote/remote_driver.c   |  1 +
 src/remote/remote_protocol.x |  9 +++++-
 src/remote_protocol-structs  |  6 ++++
 src/rpc/gendispatch.pl       |  1 +
 8 files changed, 103 insertions(+), 1 deletion(-)

diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 17804ca..afc5b42 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -3734,6 +3734,17 @@ int virConnectIsEncrypted(virConnectPtr conn);
 int virConnectIsSecure(virConnectPtr conn);
 int virConnectIsAlive(virConnectPtr conn);

+typedef enum {
+    VIR_NODE_TUNNEL_TCP_IPV4 = (1 << 0), /* use the IPv4 protocol */
+    VIR_NODE_TUNNEL_TCP_IPV6 = (1 << 1), /* use the IPv6 protocol */
+} virNodeTunnelTCPFlags;
+
+int virNodeTunnelTCP(virConnectPtr conn,
+                     virStreamPtr stream,
+                     const char *address,
+                     const char *service,
+                     unsigned int flags);
+
 /*
  * CPU specification API
  */
diff --git a/src/driver.h b/src/driver.h
index 64d652f..7c3c5b2 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -915,6 +915,13 @@ typedef int
                           unsigned long long minimum,
                           unsigned int flags);

+typedef int
+    (*virDrvNodeTunnelTCP)(virConnectPtr conn,
+                           virStreamPtr stream,
+                           const char *address,
+                           const char *service,
+                           unsigned int flags);
+
 /**
  * _virDriver:
  *
@@ -1107,6 +1114,7 @@ struct _virDriver {
     virDrvNodeGetCPUMap                 nodeGetCPUMap;
     virDrvDomainFSTrim                  domainFSTrim;
     virDrvDomainSendProcessSignal       domainSendProcessSignal;
+    virDrvNodeTunnelTCP                 nodeTunnelTCP;
 };

 typedef int
diff --git a/src/libvirt.c b/src/libvirt.c
index 6a7a817..bd4cca9 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -20373,3 +20373,70 @@ error:
     virDispatchError(dom->conn);
     return -1;
 }
+
+/**
+ * virNodeTunnelTCP:
+ * @conn: pointer to the connection object
+ * @stream: pointer to a stream object
+ * @address: pointer to a string containing address to connect to
+ * @service: pointer to a string containing port number or service name
+ * @flags: bitwise-OR of virNodeTunnelTCPFlags
+ *
+ * Creates a TCP connection to the desired host and port and connects
+ * the virStream to the connection
+ *
+ * If @address is NULL the connection is attempted to the "localhost"
+ * address.
+ *
+ * @service may contain a numeric port ID or a service name as in
+ * /etc/services.
+ *
+ * Restrictions:
+ * This functionality may be disabled in the hypervisor driver.
+ * Only connections to the host itself may be allowed.
+ * This functionality may be disabled for readonly connections.
+ *
+ * @flags may contain VIR_NODE_TUNNEL_TCP_IPV4 or VIR_NODE_TUNNEL_TCP_IPV6
+ * to denote the desired protocol. If none or both of those are specified
+ * the selected protocol depends on resolution of the host address.
+ *
+ * Returns 0 if the connection succeeds; -1 on failure.
+ */
+int
+virNodeTunnelTCP(virConnectPtr conn,
+                 virStreamPtr stream,
+                 const char *address,
+                 const char *service,
+                 unsigned int flags)
+{
+    int ret = -1;
+    VIR_DEBUG("conn=%p stream=%p address=(%p)'%s' service=(%p)'%s' flags=%x",
+              conn, stream, address, NULLSTR(address),
+              service, NULLSTR(service), flags);
+
+    virCheckNonNullArgGoto(stream, error);
+    virCheckNonNullArgGoto(service, error);
+
+    virResetLastError();
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__);
+        virDispatchError(NULL);
+        return -1;
+    }
+
+    if (conn->driver->nodeTunnelTCP) {
+        ret = conn->driver->nodeTunnelTCP(conn, stream, address,
+                                          service, flags);
+        if (ret < 0)
+            goto error;
+
+        return ret;
+    }
+
+    virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    virDispatchError(conn);
+    return ret;
+}
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index e3d63d3..c8a7f1c 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -578,6 +578,7 @@ LIBVIRT_1.0.1 {
     global:
         virDomainFSTrim;
         virDomainSendProcessSignal;
+        virNodeTunnelTCP;
 } LIBVIRT_1.0.0;

 # .... define new API here using predicted next version number ....
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 5cc7e32..ef96f51 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -6153,6 +6153,7 @@ static virDriver remote_driver = {
     .nodeGetMemoryParameters = remoteNodeGetMemoryParameters, /* 0.10.2 */
     .nodeGetCPUMap = remoteNodeGetCPUMap, /* 1.0.0 */
     .domainFSTrim = remoteDomainFSTrim, /* 1.0.1 */
+    .nodeTunnelTCP = remoteNodeTunnelTCP, /* 1.0.1 */
 };

 static virNetworkDriver network_driver = {
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index bdad9f0..0a64d56 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -2696,6 +2696,12 @@ struct remote_domain_fstrim_args {
     unsigned int flags;
 };

+struct remote_node_tunnel_tcp_args {
+    remote_string address;
+    remote_nonnull_string service;
+    unsigned int flags;
+};
+
 /*----- Protocol. -----*/

 /* Define the program number, protocol version and procedure numbers here. */
@@ -3042,7 +3048,8 @@ enum remote_procedure {
     REMOTE_PROC_DOMAIN_EVENT_PMSUSPEND_DISK = 292, /* autogen autogen */
     REMOTE_PROC_NODE_GET_CPU_MAP = 293, /* skipgen skipgen */
     REMOTE_PROC_DOMAIN_FSTRIM = 294, /* autogen autogen */
-    REMOTE_PROC_DOMAIN_SEND_PROCESS_SIGNAL = 295 /* autogen autogen */
+    REMOTE_PROC_DOMAIN_SEND_PROCESS_SIGNAL = 295, /* autogen autogen */
+    REMOTE_PROC_NODE_TUNNEL_TCP = 296 /* autogen autogen | readstream at 1 */

     /*
      * Notice how the entries are grouped in sets of 10 ?
diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
index e7d05b8..5e04bd3 100644
--- a/src/remote_protocol-structs
+++ b/src/remote_protocol-structs
@@ -2151,6 +2151,11 @@ struct remote_domain_fstrim_args {
         uint64_t                   minimum;
         u_int                      flags;
 };
+struct remote_node_tunnel_tcp_args {
+        remote_string              address;
+        remote_nonnull_string      service;
+        u_int                      flags;
+};
 enum remote_procedure {
         REMOTE_PROC_OPEN = 1,
         REMOTE_PROC_CLOSE = 2,
@@ -2447,4 +2452,5 @@ enum remote_procedure {
         REMOTE_PROC_NODE_GET_CPU_MAP = 293,
         REMOTE_PROC_DOMAIN_FSTRIM = 294,
         REMOTE_PROC_DOMAIN_SEND_PROCESS_SIGNAL = 295,
+        REMOTE_PROC_NODE_TUNNEL_TCP = 296,
 };
diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl
index 899f4bc..902acd8 100755
--- a/src/rpc/gendispatch.pl
+++ b/src/rpc/gendispatch.pl
@@ -45,6 +45,7 @@ sub fixup_name {
     $name =~ s/Nmi$/NMI/;
     $name =~ s/Pm/PM/;
     $name =~ s/Fstrim$/FSTrim/;
+    $name =~ s/Tcp$/TCP/;

     return $name;
 }
-- 
1.8.0




More information about the libvir-list mailing list