From patchwork Tue Oct 25 13:03:59 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ashijeet Acharya X-Patchwork-Id: 9394503 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id E9A9260762 for ; Tue, 25 Oct 2016 13:07:43 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DA7022959A for ; Tue, 25 Oct 2016 13:07:43 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CD4552959E; Tue, 25 Oct 2016 13:07:43 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 3DD582959A for ; Tue, 25 Oct 2016 13:07:43 +0000 (UTC) Received: from localhost ([::1]:54357 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bz1SA-00085d-D4 for patchwork-qemu-devel@patchwork.kernel.org; Tue, 25 Oct 2016 09:07:42 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52536) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bz1Rg-00084T-19 for qemu-devel@nongnu.org; Tue, 25 Oct 2016 09:07:13 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bz1Rb-0001nK-2v for qemu-devel@nongnu.org; Tue, 25 Oct 2016 09:07:11 -0400 Received: from mail-pf0-x241.google.com ([2607:f8b0:400e:c00::241]:34672) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1bz1Ra-0001nE-QQ; Tue, 25 Oct 2016 09:07:07 -0400 Received: by mail-pf0-x241.google.com with SMTP id 128so19613007pfz.1; Tue, 25 Oct 2016 06:07:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=tgKTobiaiqgLkrN6u2rOAleNtTHna5u8tLD5YDLrd2c=; b=plXjj/HmVElN0uY55o/r46l5DWfKBn4/e2kH7tfgAtrujgbP+co+oPe54cZNICHNp2 b9HnIP8kcu4Ten9tqnyVlkBephcMb5CHyxfEgjcEi43TzbofJUgb6TBsB4pzq/pRsVQ6 Mw65ltg3etEI0CMN+AAtw/INoAc2lY4NIwP/zz38yMwJjuD48aFQ5spp+jEFWTDSpoXR VBLNMCPixfhs42xIDzP1FG7oi/n9NRYcsSh9bnp43dS9Jhae8y9n0JuyEDqDgdwBwjsD adeEVg2UnUzWXLqKJHiwx4y4SpjiHMpqmLfeL7reU1tAwAaYW2kQx1kGqATBzACaaD/F FQWg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=tgKTobiaiqgLkrN6u2rOAleNtTHna5u8tLD5YDLrd2c=; b=NWmMxlVPyZ6G8LF3t8tTUrM6aRFlXGPJr8Sj1byp4s/Gi+rF/ih5ad4yCFISe+u6Zw lh1wDJE4vr5HU8RfDf88NEnx6D591aD+rsEM2ivBjOcXS06/VCBvLVwWKFky6yL4OvTB C6xF5ktC6JNFZLVoa2e8T5Qnf0np8WEa13anMzn7ft1cPmt81bnAT04g5DsKhzCW/t0Z OYEL0L8eePVbUG3edQXIeKPzlI0lO7g5Fpd6ct/tNzATWp11L/FeHNNq2I5An5Gl2YRe /FN4gk8ovjKkZ+LiFZ1WiaQc2iUhu9vIZkk6FCv0TEIm+ie8ubheO19KMvN21FPC7yaV Nb5Q== X-Gm-Message-State: ABUngvegSxWVZR8Rn3VWkQn+Xo+LzKRF4g/vQ/vxq2f4tOrBg/ga+WgJW8JNrn/NwCm2/w== X-Received: by 10.98.35.9 with SMTP id j9mr39015113pfj.173.1477400825865; Tue, 25 Oct 2016 06:07:05 -0700 (PDT) Received: from linux.local ([106.208.9.126]) by smtp.gmail.com with ESMTPSA id u17sm33461160pfi.1.2016.10.25.06.07.01 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 25 Oct 2016 06:07:05 -0700 (PDT) From: Ashijeet Acharya To: kwolf@redhat.com Date: Tue, 25 Oct 2016 18:33:59 +0530 Message-Id: <1477400641-7750-4-git-send-email-ashijeetacharya@gmail.com> X-Mailer: git-send-email 2.6.2 In-Reply-To: <1477400641-7750-1-git-send-email-ashijeetacharya@gmail.com> References: <1477400641-7750-1-git-send-email-ashijeetacharya@gmail.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2607:f8b0:400e:c00::241 Subject: [Qemu-devel] [PATCH v4 3/5] block/ssh: Add InetSocketAddress and accept it X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-block@nongnu.org, qemu-devel@nongnu.org, jcody@redhat.com, rjones@redhat.com, mreitz@redhat.com, Ashijeet Acharya , pbonzini@redhat.com Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP Add InetSocketAddress compatibility to SSH driver. Add a new option "server" to the SSH block driver which then accepts a InetSocketAddress. "host" and "port" are supported as legacy options and are mapped to their InetSocketAddress representation. Signed-off-by: Ashijeet Acharya --- block/ssh.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 82 insertions(+), 16 deletions(-) diff --git a/block/ssh.c b/block/ssh.c index 75cb7bc..d814006 100644 --- a/block/ssh.c +++ b/block/ssh.c @@ -30,10 +30,14 @@ #include "block/block_int.h" #include "qapi/error.h" #include "qemu/error-report.h" +#include "qemu/cutils.h" #include "qemu/sockets.h" #include "qemu/uri.h" +#include "qapi-visit.h" #include "qapi/qmp/qint.h" #include "qapi/qmp/qstring.h" +#include "qapi/qobject-input-visitor.h" +#include "qapi/qobject-output-visitor.h" /* DEBUG_SSH=1 enables the DPRINTF (debugging printf) statements in * this block driver code. @@ -74,8 +78,9 @@ typedef struct BDRVSSHState { */ LIBSSH2_SFTP_ATTRIBUTES attrs; + InetSocketAddress *inet; + /* Used to warn if 'flush' is not supported. */ - char *hostport; bool unsafe_flush_warning; } BDRVSSHState; @@ -89,7 +94,6 @@ static void ssh_state_init(BDRVSSHState *s) static void ssh_state_free(BDRVSSHState *s) { - g_free(s->hostport); if (s->sftp_handle) { libssh2_sftp_close(s->sftp_handle); } @@ -263,7 +267,8 @@ static bool ssh_has_filename_options_conflict(QDict *options, Error **errp) !strcmp(qe->key, "port") || !strcmp(qe->key, "path") || !strcmp(qe->key, "user") || - !strcmp(qe->key, "host_key_check")) + !strcmp(qe->key, "host_key_check") || + strstart(qe->key, "server.", NULL)) { error_setg(errp, "Option '%s' cannot be used with a file name", qe->key); @@ -555,14 +560,69 @@ static QemuOptsList ssh_runtime_opts = { }, }; +static bool ssh_process_legacy_socket_options(QDict *output_opts, + QemuOpts *legacy_opts, + Error **errp) +{ + const char *host = qemu_opt_get(legacy_opts, "host"); + const char *port = qemu_opt_get(legacy_opts, "port"); + + if (!host && port) { + error_setg(errp, "port may not be used without host"); + return false; + } + + if (host) { + qdict_put(output_opts, "server.host", qstring_from_str(host)); + qdict_put(output_opts, "server.port", + qstring_from_str(port ?: stringify(22))); + } + + return true; +} + +static InetSocketAddress *ssh_config(BDRVSSHState *s, QDict *options, + Error **errp) +{ + InetSocketAddress *inet = NULL; + QDict *addr = NULL; + QObject *crumpled_addr = NULL; + Visitor *iv = NULL; + Error *local_error = NULL; + + qdict_extract_subqdict(options, &addr, "server."); + if (!qdict_size(addr)) { + error_setg(errp, "SSH server address missing"); + goto out; + } + + crumpled_addr = qdict_crumple(addr, true, errp); + if (!crumpled_addr) { + goto out; + } + + iv = qobject_input_visitor_new(crumpled_addr, true); + visit_type_InetSocketAddress(iv, NULL, &inet, &local_error); + if (local_error) { + error_propagate(errp, local_error); + goto out; + } + +out: + QDECREF(addr); + qobject_decref(crumpled_addr); + visit_free(iv); + return inet; +} + static int connect_to_ssh(BDRVSSHState *s, QDict *options, int ssh_flags, int creat_mode, Error **errp) { int r, ret; QemuOpts *opts = NULL; Error *local_err = NULL; - const char *host, *user, *path, *host_key_check; - int port; + const char *user, *path, *host_key_check; + long port = 0; opts = qemu_opts_create(&ssh_runtime_opts, NULL, 0, &error_abort); qemu_opts_absorb_qdict(opts, options, &local_err); @@ -572,15 +632,11 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options, goto err; } - host = qemu_opt_get(opts, "host"); - if (!host) { + if (!ssh_process_legacy_socket_options(options, opts, errp)) { ret = -EINVAL; - error_setg(errp, "No hostname was specified"); goto err; } - port = qemu_opt_get_number(opts, "port", 22); - path = qemu_opt_get(opts, "path"); if (!path) { ret = -EINVAL; @@ -603,12 +659,21 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options, host_key_check = "yes"; } - /* Construct the host:port name for inet_connect. */ - g_free(s->hostport); - s->hostport = g_strdup_printf("%s:%d", host, port); + /* Pop the config into our state object, Exit if invalid */ + s->inet = ssh_config(s, options, errp); + if (!s->inet) { + ret = -EINVAL; + goto err; + } + + if (qemu_strtol(s->inet->port, NULL, 10, &port) < 0) { + error_setg(errp, "Use only numeric port value"); + ret = -EINVAL; + goto err; + } /* Open the socket and connect. */ - s->sock = inet_connect(s->hostport, errp); + s->sock = inet_connect_saddr(s->inet, errp, NULL, NULL); if (s->sock < 0) { ret = -EIO; goto err; @@ -634,7 +699,8 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options, } /* Check the remote host's key against known_hosts. */ - ret = check_host_key(s, host, port, host_key_check, errp); + ret = check_host_key(s, s->inet->host, port, host_key_check, + errp); if (ret < 0) { goto err; } @@ -1055,7 +1121,7 @@ static void unsafe_flush_warning(BDRVSSHState *s, const char *what) { if (!s->unsafe_flush_warning) { error_report("warning: ssh server %s does not support fsync", - s->hostport); + s->inet->host); if (what) { error_report("to support fsync, you need %s", what); }