2 * Secure Shell (ssh) backend for QEMU.
4 * Copyright (C) 2013 Red Hat Inc., Richard W.M. Jones <rjones@redhat.com>
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 #include "qemu/osdep.h"
28 #include <libssh2_sftp.h>
30 #include "block/block_int.h"
31 #include "qapi/error.h"
32 #include "qemu/error-report.h"
33 #include "qemu/cutils.h"
34 #include "qemu/sockets.h"
36 #include "qapi-visit.h"
37 #include "qapi/qmp/qint.h"
38 #include "qapi/qmp/qstring.h"
39 #include "qapi/qobject-input-visitor.h"
40 #include "qapi/qobject-output-visitor.h"
42 /* DEBUG_SSH=1 enables the DPRINTF (debugging printf) statements in
43 * this block driver code.
45 * TRACE_LIBSSH2=<bitmask> enables tracing in libssh2 itself. Note
46 * that this requires that libssh2 was specially compiled with the
47 * `./configure --enable-debug' option, so most likely you will have
48 * to compile it yourself. The meaning of <bitmask> is described
49 * here: http://www.libssh2.org/libssh2_trace.html
52 #define TRACE_LIBSSH2 0 /* or try: LIBSSH2_TRACE_SFTP */
54 #define DPRINTF(fmt, ...) \
57 fprintf(stderr, "ssh: %-15s " fmt "\n", \
58 __func__, ##__VA_ARGS__); \
62 typedef struct BDRVSSHState
{
67 int sock
; /* socket */
68 LIBSSH2_SESSION
*session
; /* ssh session */
69 LIBSSH2_SFTP
*sftp
; /* sftp session */
70 LIBSSH2_SFTP_HANDLE
*sftp_handle
; /* sftp remote file handle */
72 /* See ssh_seek() function below. */
76 /* File attributes at open. We try to keep the .filesize field
77 * updated if it changes (eg by writing at the end of the file).
79 LIBSSH2_SFTP_ATTRIBUTES attrs
;
81 InetSocketAddress
*inet
;
83 /* Used to warn if 'flush' is not supported. */
84 bool unsafe_flush_warning
;
87 static void ssh_state_init(BDRVSSHState
*s
)
89 memset(s
, 0, sizeof *s
);
92 qemu_co_mutex_init(&s
->lock
);
95 static void ssh_state_free(BDRVSSHState
*s
)
98 libssh2_sftp_close(s
->sftp_handle
);
101 libssh2_sftp_shutdown(s
->sftp
);
104 libssh2_session_disconnect(s
->session
,
105 "from qemu ssh client: "
106 "user closed the connection");
107 libssh2_session_free(s
->session
);
114 static void GCC_FMT_ATTR(3, 4)
115 session_error_setg(Error
**errp
, BDRVSSHState
*s
, const char *fs
, ...)
121 msg
= g_strdup_vprintf(fs
, args
);
128 /* This is not an errno. See <libssh2.h>. */
129 ssh_err_code
= libssh2_session_last_error(s
->session
,
131 error_setg(errp
, "%s: %s (libssh2 error code: %d)",
132 msg
, ssh_err
, ssh_err_code
);
134 error_setg(errp
, "%s", msg
);
139 static void GCC_FMT_ATTR(3, 4)
140 sftp_error_setg(Error
**errp
, BDRVSSHState
*s
, const char *fs
, ...)
146 msg
= g_strdup_vprintf(fs
, args
);
152 unsigned long sftp_err_code
;
154 /* This is not an errno. See <libssh2.h>. */
155 ssh_err_code
= libssh2_session_last_error(s
->session
,
157 /* See <libssh2_sftp.h>. */
158 sftp_err_code
= libssh2_sftp_last_error((s
)->sftp
);
161 "%s: %s (libssh2 error code: %d, sftp error code: %lu)",
162 msg
, ssh_err
, ssh_err_code
, sftp_err_code
);
164 error_setg(errp
, "%s", msg
);
169 static void GCC_FMT_ATTR(2, 3)
170 sftp_error_report(BDRVSSHState
*s
, const char *fs
, ...)
175 error_vprintf(fs
, args
);
180 unsigned long sftp_err_code
;
182 /* This is not an errno. See <libssh2.h>. */
183 ssh_err_code
= libssh2_session_last_error(s
->session
,
185 /* See <libssh2_sftp.h>. */
186 sftp_err_code
= libssh2_sftp_last_error((s
)->sftp
);
188 error_printf(": %s (libssh2 error code: %d, sftp error code: %lu)",
189 ssh_err
, ssh_err_code
, sftp_err_code
);
196 static int parse_uri(const char *filename
, QDict
*options
, Error
**errp
)
203 uri
= uri_parse(filename
);
208 if (strcmp(uri
->scheme
, "ssh") != 0) {
209 error_setg(errp
, "URI scheme must be 'ssh'");
213 if (!uri
->server
|| strcmp(uri
->server
, "") == 0) {
214 error_setg(errp
, "missing hostname in URI");
218 if (!uri
->path
|| strcmp(uri
->path
, "") == 0) {
219 error_setg(errp
, "missing remote path in URI");
223 qp
= query_params_parse(uri
->query
);
225 error_setg(errp
, "could not parse query parameters");
229 if(uri
->user
&& strcmp(uri
->user
, "") != 0) {
230 qdict_put_str(options
, "user", uri
->user
);
233 qdict_put_str(options
, "server.host", uri
->server
);
235 port_str
= g_strdup_printf("%d", uri
->port
?: 22);
236 qdict_put_str(options
, "server.port", port_str
);
239 qdict_put_str(options
, "path", uri
->path
);
241 /* Pick out any query parameters that we understand, and ignore
244 for (i
= 0; i
< qp
->n
; ++i
) {
245 if (strcmp(qp
->p
[i
].name
, "host_key_check") == 0) {
246 qdict_put_str(options
, "host_key_check", qp
->p
[i
].value
);
250 query_params_free(qp
);
261 static bool ssh_has_filename_options_conflict(QDict
*options
, Error
**errp
)
263 const QDictEntry
*qe
;
265 for (qe
= qdict_first(options
); qe
; qe
= qdict_next(options
, qe
)) {
266 if (!strcmp(qe
->key
, "host") ||
267 !strcmp(qe
->key
, "port") ||
268 !strcmp(qe
->key
, "path") ||
269 !strcmp(qe
->key
, "user") ||
270 !strcmp(qe
->key
, "host_key_check") ||
271 strstart(qe
->key
, "server.", NULL
))
273 error_setg(errp
, "Option '%s' cannot be used with a file name",
282 static void ssh_parse_filename(const char *filename
, QDict
*options
,
285 if (ssh_has_filename_options_conflict(options
, errp
)) {
289 parse_uri(filename
, options
, errp
);
292 static int check_host_key_knownhosts(BDRVSSHState
*s
,
293 const char *host
, int port
, Error
**errp
)
296 char *knh_file
= NULL
;
297 LIBSSH2_KNOWNHOSTS
*knh
= NULL
;
298 struct libssh2_knownhost
*found
;
304 hostkey
= libssh2_session_hostkey(s
->session
, &len
, &type
);
307 session_error_setg(errp
, s
, "failed to read remote host key");
311 knh
= libssh2_knownhost_init(s
->session
);
314 session_error_setg(errp
, s
,
315 "failed to initialize known hosts support");
319 home
= getenv("HOME");
321 knh_file
= g_strdup_printf("%s/.ssh/known_hosts", home
);
323 knh_file
= g_strdup_printf("/root/.ssh/known_hosts");
326 /* Read all known hosts from OpenSSH-style known_hosts file. */
327 libssh2_knownhost_readfile(knh
, knh_file
, LIBSSH2_KNOWNHOST_FILE_OPENSSH
);
329 r
= libssh2_knownhost_checkp(knh
, host
, port
, hostkey
, len
,
330 LIBSSH2_KNOWNHOST_TYPE_PLAIN
|
331 LIBSSH2_KNOWNHOST_KEYENC_RAW
,
334 case LIBSSH2_KNOWNHOST_CHECK_MATCH
:
336 DPRINTF("host key OK: %s", found
->key
);
338 case LIBSSH2_KNOWNHOST_CHECK_MISMATCH
:
340 session_error_setg(errp
, s
,
341 "host key does not match the one in known_hosts"
342 " (found key %s)", found
->key
);
344 case LIBSSH2_KNOWNHOST_CHECK_NOTFOUND
:
346 session_error_setg(errp
, s
, "no host key was found in known_hosts");
348 case LIBSSH2_KNOWNHOST_CHECK_FAILURE
:
350 session_error_setg(errp
, s
,
351 "failure matching the host key with known_hosts");
355 session_error_setg(errp
, s
, "unknown error matching the host key"
356 " with known_hosts (%d)", r
);
360 /* known_hosts checking successful. */
365 libssh2_knownhost_free(knh
);
371 static unsigned hex2decimal(char ch
)
373 if (ch
>= '0' && ch
<= '9') {
375 } else if (ch
>= 'a' && ch
<= 'f') {
376 return 10 + (ch
- 'a');
377 } else if (ch
>= 'A' && ch
<= 'F') {
378 return 10 + (ch
- 'A');
384 /* Compare the binary fingerprint (hash of host key) with the
385 * host_key_check parameter.
387 static int compare_fingerprint(const unsigned char *fingerprint
, size_t len
,
388 const char *host_key_check
)
393 while (*host_key_check
== ':')
395 if (!qemu_isxdigit(host_key_check
[0]) ||
396 !qemu_isxdigit(host_key_check
[1]))
398 c
= hex2decimal(host_key_check
[0]) * 16 +
399 hex2decimal(host_key_check
[1]);
400 if (c
- *fingerprint
!= 0)
401 return c
- *fingerprint
;
406 return *host_key_check
- '\0';
410 check_host_key_hash(BDRVSSHState
*s
, const char *hash
,
411 int hash_type
, size_t fingerprint_len
, Error
**errp
)
413 const char *fingerprint
;
415 fingerprint
= libssh2_hostkey_hash(s
->session
, hash_type
);
417 session_error_setg(errp
, s
, "failed to read remote host key");
421 if(compare_fingerprint((unsigned char *) fingerprint
, fingerprint_len
,
423 error_setg(errp
, "remote host key does not match host_key_check '%s'",
431 static int check_host_key(BDRVSSHState
*s
, const char *host
, int port
,
432 const char *host_key_check
, Error
**errp
)
434 /* host_key_check=no */
435 if (strcmp(host_key_check
, "no") == 0) {
439 /* host_key_check=md5:xx:yy:zz:... */
440 if (strncmp(host_key_check
, "md5:", 4) == 0) {
441 return check_host_key_hash(s
, &host_key_check
[4],
442 LIBSSH2_HOSTKEY_HASH_MD5
, 16, errp
);
445 /* host_key_check=sha1:xx:yy:zz:... */
446 if (strncmp(host_key_check
, "sha1:", 5) == 0) {
447 return check_host_key_hash(s
, &host_key_check
[5],
448 LIBSSH2_HOSTKEY_HASH_SHA1
, 20, errp
);
451 /* host_key_check=yes */
452 if (strcmp(host_key_check
, "yes") == 0) {
453 return check_host_key_knownhosts(s
, host
, port
, errp
);
456 error_setg(errp
, "unknown host_key_check setting (%s)", host_key_check
);
460 static int authenticate(BDRVSSHState
*s
, const char *user
, Error
**errp
)
463 const char *userauthlist
;
464 LIBSSH2_AGENT
*agent
= NULL
;
465 struct libssh2_agent_publickey
*identity
;
466 struct libssh2_agent_publickey
*prev_identity
= NULL
;
468 userauthlist
= libssh2_userauth_list(s
->session
, user
, strlen(user
));
469 if (strstr(userauthlist
, "publickey") == NULL
) {
472 "remote server does not support \"publickey\" authentication");
476 /* Connect to ssh-agent and try each identity in turn. */
477 agent
= libssh2_agent_init(s
->session
);
480 session_error_setg(errp
, s
, "failed to initialize ssh-agent support");
483 if (libssh2_agent_connect(agent
)) {
485 session_error_setg(errp
, s
, "failed to connect to ssh-agent");
488 if (libssh2_agent_list_identities(agent
)) {
490 session_error_setg(errp
, s
,
491 "failed requesting identities from ssh-agent");
496 r
= libssh2_agent_get_identity(agent
, &identity
, prev_identity
);
497 if (r
== 1) { /* end of list */
502 session_error_setg(errp
, s
,
503 "failed to obtain identity from ssh-agent");
506 r
= libssh2_agent_userauth(agent
, user
, identity
);
512 /* Failed to authenticate with this identity, try the next one. */
513 prev_identity
= identity
;
517 error_setg(errp
, "failed to authenticate using publickey authentication "
518 "and the identities held by your ssh-agent");
522 /* Note: libssh2 implementation implicitly calls
523 * libssh2_agent_disconnect if necessary.
525 libssh2_agent_free(agent
);
531 static QemuOptsList ssh_runtime_opts
= {
533 .head
= QTAILQ_HEAD_INITIALIZER(ssh_runtime_opts
.head
),
537 .type
= QEMU_OPT_STRING
,
538 .help
= "Host to connect to",
542 .type
= QEMU_OPT_NUMBER
,
543 .help
= "Port to connect to",
547 .type
= QEMU_OPT_STRING
,
548 .help
= "Path of the image on the host",
552 .type
= QEMU_OPT_STRING
,
553 .help
= "User as which to connect",
556 .name
= "host_key_check",
557 .type
= QEMU_OPT_STRING
,
558 .help
= "Defines how and what to check the host key against",
563 static bool ssh_process_legacy_socket_options(QDict
*output_opts
,
564 QemuOpts
*legacy_opts
,
567 const char *host
= qemu_opt_get(legacy_opts
, "host");
568 const char *port
= qemu_opt_get(legacy_opts
, "port");
571 error_setg(errp
, "port may not be used without host");
576 qdict_put_str(output_opts
, "server.host", host
);
577 qdict_put_str(output_opts
, "server.port", port
?: stringify(22));
583 static InetSocketAddress
*ssh_config(QDict
*options
, Error
**errp
)
585 InetSocketAddress
*inet
= NULL
;
587 QObject
*crumpled_addr
= NULL
;
589 Error
*local_error
= NULL
;
591 qdict_extract_subqdict(options
, &addr
, "server.");
592 if (!qdict_size(addr
)) {
593 error_setg(errp
, "SSH server address missing");
597 crumpled_addr
= qdict_crumple(addr
, errp
);
598 if (!crumpled_addr
) {
603 * FIXME .numeric, .to, .ipv4 or .ipv6 don't work with -drive.
604 * .to doesn't matter, it's ignored anyway.
605 * That's because when @options come from -blockdev or
606 * blockdev_add, members are typed according to the QAPI schema,
607 * but when they come from -drive, they're all QString. The
608 * visitor expects the former.
610 iv
= qobject_input_visitor_new(crumpled_addr
);
611 visit_type_InetSocketAddress(iv
, NULL
, &inet
, &local_error
);
613 error_propagate(errp
, local_error
);
619 qobject_decref(crumpled_addr
);
624 static int connect_to_ssh(BDRVSSHState
*s
, QDict
*options
,
625 int ssh_flags
, int creat_mode
, Error
**errp
)
628 QemuOpts
*opts
= NULL
;
629 Error
*local_err
= NULL
;
630 const char *user
, *path
, *host_key_check
;
633 opts
= qemu_opts_create(&ssh_runtime_opts
, NULL
, 0, &error_abort
);
634 qemu_opts_absorb_qdict(opts
, options
, &local_err
);
637 error_propagate(errp
, local_err
);
641 if (!ssh_process_legacy_socket_options(options
, opts
, errp
)) {
646 path
= qemu_opt_get(opts
, "path");
649 error_setg(errp
, "No path was specified");
653 user
= qemu_opt_get(opts
, "user");
655 user
= g_get_user_name();
657 error_setg_errno(errp
, errno
, "Can't get user name");
663 host_key_check
= qemu_opt_get(opts
, "host_key_check");
664 if (!host_key_check
) {
665 host_key_check
= "yes";
668 /* Pop the config into our state object, Exit if invalid */
669 s
->inet
= ssh_config(options
, errp
);
675 if (qemu_strtol(s
->inet
->port
, NULL
, 10, &port
) < 0) {
676 error_setg(errp
, "Use only numeric port value");
681 /* Open the socket and connect. */
682 s
->sock
= inet_connect_saddr(s
->inet
, NULL
, NULL
, errp
);
688 /* Create SSH session. */
689 s
->session
= libssh2_session_init();
692 session_error_setg(errp
, s
, "failed to initialize libssh2 session");
696 #if TRACE_LIBSSH2 != 0
697 libssh2_trace(s
->session
, TRACE_LIBSSH2
);
700 r
= libssh2_session_handshake(s
->session
, s
->sock
);
703 session_error_setg(errp
, s
, "failed to establish SSH session");
707 /* Check the remote host's key against known_hosts. */
708 ret
= check_host_key(s
, s
->inet
->host
, port
, host_key_check
,
715 ret
= authenticate(s
, user
, errp
);
721 s
->sftp
= libssh2_sftp_init(s
->session
);
723 session_error_setg(errp
, s
, "failed to initialize sftp handle");
728 /* Open the remote file. */
729 DPRINTF("opening file %s flags=0x%x creat_mode=0%o",
730 path
, ssh_flags
, creat_mode
);
731 s
->sftp_handle
= libssh2_sftp_open(s
->sftp
, path
, ssh_flags
, creat_mode
);
732 if (!s
->sftp_handle
) {
733 session_error_setg(errp
, s
, "failed to open remote file '%s'", path
);
740 r
= libssh2_sftp_fstat(s
->sftp_handle
, &s
->attrs
);
742 sftp_error_setg(errp
, s
, "failed to read file attributes");
749 if (s
->sftp_handle
) {
750 libssh2_sftp_close(s
->sftp_handle
);
752 s
->sftp_handle
= NULL
;
754 libssh2_sftp_shutdown(s
->sftp
);
758 libssh2_session_disconnect(s
->session
,
759 "from qemu ssh client: "
760 "error opening connection");
761 libssh2_session_free(s
->session
);
770 static int ssh_file_open(BlockDriverState
*bs
, QDict
*options
, int bdrv_flags
,
773 BDRVSSHState
*s
= bs
->opaque
;
779 ssh_flags
= LIBSSH2_FXF_READ
;
780 if (bdrv_flags
& BDRV_O_RDWR
) {
781 ssh_flags
|= LIBSSH2_FXF_WRITE
;
785 ret
= connect_to_ssh(s
, options
, ssh_flags
, 0, errp
);
790 /* Go non-blocking. */
791 libssh2_session_set_blocking(s
->session
, 0);
804 static QemuOptsList ssh_create_opts
= {
805 .name
= "ssh-create-opts",
806 .head
= QTAILQ_HEAD_INITIALIZER(ssh_create_opts
.head
),
809 .name
= BLOCK_OPT_SIZE
,
810 .type
= QEMU_OPT_SIZE
,
811 .help
= "Virtual disk size"
813 { /* end of list */ }
817 static int ssh_create(const char *filename
, QemuOpts
*opts
, Error
**errp
)
820 int64_t total_size
= 0;
821 QDict
*uri_options
= NULL
;
824 char c
[1] = { '\0' };
828 /* Get desired file size. */
829 total_size
= ROUND_UP(qemu_opt_get_size_del(opts
, BLOCK_OPT_SIZE
, 0),
831 DPRINTF("total_size=%" PRIi64
, total_size
);
833 uri_options
= qdict_new();
834 r
= parse_uri(filename
, uri_options
, errp
);
840 r
= connect_to_ssh(&s
, uri_options
,
841 LIBSSH2_FXF_READ
|LIBSSH2_FXF_WRITE
|
842 LIBSSH2_FXF_CREAT
|LIBSSH2_FXF_TRUNC
,
849 if (total_size
> 0) {
850 libssh2_sftp_seek64(s
.sftp_handle
, total_size
-1);
851 r2
= libssh2_sftp_write(s
.sftp_handle
, c
, 1);
853 sftp_error_setg(errp
, &s
, "truncate failed");
857 s
.attrs
.filesize
= total_size
;
864 if (uri_options
!= NULL
) {
865 QDECREF(uri_options
);
870 static void ssh_close(BlockDriverState
*bs
)
872 BDRVSSHState
*s
= bs
->opaque
;
877 static int ssh_has_zero_init(BlockDriverState
*bs
)
879 BDRVSSHState
*s
= bs
->opaque
;
880 /* Assume false, unless we can positively prove it's true. */
881 int has_zero_init
= 0;
883 if (s
->attrs
.flags
& LIBSSH2_SFTP_ATTR_PERMISSIONS
) {
884 if (s
->attrs
.permissions
& LIBSSH2_SFTP_S_IFREG
) {
889 return has_zero_init
;
892 static void restart_coroutine(void *opaque
)
894 Coroutine
*co
= opaque
;
896 DPRINTF("co=%p", co
);
901 /* A non-blocking call returned EAGAIN, so yield, ensuring the
902 * handlers are set up so that we'll be rescheduled when there is an
903 * interesting event on the socket.
905 static coroutine_fn
void co_yield(BDRVSSHState
*s
, BlockDriverState
*bs
)
908 IOHandler
*rd_handler
= NULL
, *wr_handler
= NULL
;
909 Coroutine
*co
= qemu_coroutine_self();
911 r
= libssh2_session_block_directions(s
->session
);
913 if (r
& LIBSSH2_SESSION_BLOCK_INBOUND
) {
914 rd_handler
= restart_coroutine
;
916 if (r
& LIBSSH2_SESSION_BLOCK_OUTBOUND
) {
917 wr_handler
= restart_coroutine
;
920 DPRINTF("s->sock=%d rd_handler=%p wr_handler=%p", s
->sock
,
921 rd_handler
, wr_handler
);
923 aio_set_fd_handler(bdrv_get_aio_context(bs
), s
->sock
,
924 false, rd_handler
, wr_handler
, NULL
, co
);
925 qemu_coroutine_yield();
926 DPRINTF("s->sock=%d - back", s
->sock
);
927 aio_set_fd_handler(bdrv_get_aio_context(bs
), s
->sock
, false,
928 NULL
, NULL
, NULL
, NULL
);
931 /* SFTP has a function `libssh2_sftp_seek64' which seeks to a position
932 * in the remote file. Notice that it just updates a field in the
933 * sftp_handle structure, so there is no network traffic and it cannot
936 * However, `libssh2_sftp_seek64' does have a catastrophic effect on
937 * performance since it causes the handle to throw away all in-flight
938 * reads and buffered readahead data. Therefore this function tries
939 * to be intelligent about when to call the underlying libssh2 function.
941 #define SSH_SEEK_WRITE 0
942 #define SSH_SEEK_READ 1
943 #define SSH_SEEK_FORCE 2
945 static void ssh_seek(BDRVSSHState
*s
, int64_t offset
, int flags
)
947 bool op_read
= (flags
& SSH_SEEK_READ
) != 0;
948 bool force
= (flags
& SSH_SEEK_FORCE
) != 0;
950 if (force
|| op_read
!= s
->offset_op_read
|| offset
!= s
->offset
) {
951 DPRINTF("seeking to offset=%" PRIi64
, offset
);
952 libssh2_sftp_seek64(s
->sftp_handle
, offset
);
954 s
->offset_op_read
= op_read
;
958 static coroutine_fn
int ssh_read(BDRVSSHState
*s
, BlockDriverState
*bs
,
959 int64_t offset
, size_t size
,
964 char *buf
, *end_of_vec
;
967 DPRINTF("offset=%" PRIi64
" size=%zu", offset
, size
);
969 ssh_seek(s
, offset
, SSH_SEEK_READ
);
971 /* This keeps track of the current iovec element ('i'), where we
972 * will write to next ('buf'), and the end of the current iovec
977 end_of_vec
= i
->iov_base
+ i
->iov_len
;
979 /* libssh2 has a hard-coded limit of 2000 bytes per request,
980 * although it will also do readahead behind our backs. Therefore
981 * we may have to do repeated reads here until we have read 'size'
984 for (got
= 0; got
< size
; ) {
986 DPRINTF("sftp_read buf=%p size=%zu", buf
, end_of_vec
- buf
);
987 r
= libssh2_sftp_read(s
->sftp_handle
, buf
, end_of_vec
- buf
);
988 DPRINTF("sftp_read returned %zd", r
);
990 if (r
== LIBSSH2_ERROR_EAGAIN
|| r
== LIBSSH2_ERROR_TIMEOUT
) {
995 sftp_error_report(s
, "read failed");
1000 /* EOF: Short read so pad the buffer with zeroes and return it. */
1001 qemu_iovec_memset(qiov
, got
, 0, size
- got
);
1008 if (buf
>= end_of_vec
&& got
< size
) {
1011 end_of_vec
= i
->iov_base
+ i
->iov_len
;
1018 static coroutine_fn
int ssh_co_readv(BlockDriverState
*bs
,
1020 int nb_sectors
, QEMUIOVector
*qiov
)
1022 BDRVSSHState
*s
= bs
->opaque
;
1025 qemu_co_mutex_lock(&s
->lock
);
1026 ret
= ssh_read(s
, bs
, sector_num
* BDRV_SECTOR_SIZE
,
1027 nb_sectors
* BDRV_SECTOR_SIZE
, qiov
);
1028 qemu_co_mutex_unlock(&s
->lock
);
1033 static int ssh_write(BDRVSSHState
*s
, BlockDriverState
*bs
,
1034 int64_t offset
, size_t size
,
1039 char *buf
, *end_of_vec
;
1042 DPRINTF("offset=%" PRIi64
" size=%zu", offset
, size
);
1044 ssh_seek(s
, offset
, SSH_SEEK_WRITE
);
1046 /* This keeps track of the current iovec element ('i'), where we
1047 * will read from next ('buf'), and the end of the current iovec
1052 end_of_vec
= i
->iov_base
+ i
->iov_len
;
1054 for (written
= 0; written
< size
; ) {
1056 DPRINTF("sftp_write buf=%p size=%zu", buf
, end_of_vec
- buf
);
1057 r
= libssh2_sftp_write(s
->sftp_handle
, buf
, end_of_vec
- buf
);
1058 DPRINTF("sftp_write returned %zd", r
);
1060 if (r
== LIBSSH2_ERROR_EAGAIN
|| r
== LIBSSH2_ERROR_TIMEOUT
) {
1065 sftp_error_report(s
, "write failed");
1069 /* The libssh2 API is very unclear about this. A comment in
1070 * the code says "nothing was acked, and no EAGAIN was
1071 * received!" which apparently means that no data got sent
1072 * out, and the underlying channel didn't return any EAGAIN
1073 * indication. I think this is a bug in either libssh2 or
1074 * OpenSSH (server-side). In any case, forcing a seek (to
1075 * discard libssh2 internal buffers), and then trying again
1079 ssh_seek(s
, offset
+ written
, SSH_SEEK_WRITE
|SSH_SEEK_FORCE
);
1087 if (buf
>= end_of_vec
&& written
< size
) {
1090 end_of_vec
= i
->iov_base
+ i
->iov_len
;
1093 if (offset
+ written
> s
->attrs
.filesize
)
1094 s
->attrs
.filesize
= offset
+ written
;
1100 static coroutine_fn
int ssh_co_writev(BlockDriverState
*bs
,
1102 int nb_sectors
, QEMUIOVector
*qiov
)
1104 BDRVSSHState
*s
= bs
->opaque
;
1107 qemu_co_mutex_lock(&s
->lock
);
1108 ret
= ssh_write(s
, bs
, sector_num
* BDRV_SECTOR_SIZE
,
1109 nb_sectors
* BDRV_SECTOR_SIZE
, qiov
);
1110 qemu_co_mutex_unlock(&s
->lock
);
1115 static void unsafe_flush_warning(BDRVSSHState
*s
, const char *what
)
1117 if (!s
->unsafe_flush_warning
) {
1118 error_report("warning: ssh server %s does not support fsync",
1121 error_report("to support fsync, you need %s", what
);
1123 s
->unsafe_flush_warning
= true;
1127 #ifdef HAS_LIBSSH2_SFTP_FSYNC
1129 static coroutine_fn
int ssh_flush(BDRVSSHState
*s
, BlockDriverState
*bs
)
1135 r
= libssh2_sftp_fsync(s
->sftp_handle
);
1136 if (r
== LIBSSH2_ERROR_EAGAIN
|| r
== LIBSSH2_ERROR_TIMEOUT
) {
1140 if (r
== LIBSSH2_ERROR_SFTP_PROTOCOL
&&
1141 libssh2_sftp_last_error(s
->sftp
) == LIBSSH2_FX_OP_UNSUPPORTED
) {
1142 unsafe_flush_warning(s
, "OpenSSH >= 6.3");
1146 sftp_error_report(s
, "fsync failed");
1153 static coroutine_fn
int ssh_co_flush(BlockDriverState
*bs
)
1155 BDRVSSHState
*s
= bs
->opaque
;
1158 qemu_co_mutex_lock(&s
->lock
);
1159 ret
= ssh_flush(s
, bs
);
1160 qemu_co_mutex_unlock(&s
->lock
);
1165 #else /* !HAS_LIBSSH2_SFTP_FSYNC */
1167 static coroutine_fn
int ssh_co_flush(BlockDriverState
*bs
)
1169 BDRVSSHState
*s
= bs
->opaque
;
1171 unsafe_flush_warning(s
, "libssh2 >= 1.4.4");
1175 #endif /* !HAS_LIBSSH2_SFTP_FSYNC */
1177 static int64_t ssh_getlength(BlockDriverState
*bs
)
1179 BDRVSSHState
*s
= bs
->opaque
;
1182 /* Note we cannot make a libssh2 call here. */
1183 length
= (int64_t) s
->attrs
.filesize
;
1184 DPRINTF("length=%" PRIi64
, length
);
1189 static BlockDriver bdrv_ssh
= {
1190 .format_name
= "ssh",
1191 .protocol_name
= "ssh",
1192 .instance_size
= sizeof(BDRVSSHState
),
1193 .bdrv_parse_filename
= ssh_parse_filename
,
1194 .bdrv_file_open
= ssh_file_open
,
1195 .bdrv_create
= ssh_create
,
1196 .bdrv_close
= ssh_close
,
1197 .bdrv_has_zero_init
= ssh_has_zero_init
,
1198 .bdrv_co_readv
= ssh_co_readv
,
1199 .bdrv_co_writev
= ssh_co_writev
,
1200 .bdrv_getlength
= ssh_getlength
,
1201 .bdrv_co_flush_to_disk
= ssh_co_flush
,
1202 .create_opts
= &ssh_create_opts
,
1205 static void bdrv_ssh_init(void)
1209 r
= libssh2_init(0);
1211 fprintf(stderr
, "libssh2 initialization failed, %d\n", r
);
1215 bdrv_register(&bdrv_ssh
);
1218 block_init(bdrv_ssh_init
);