qemu/block/curl.c
<<
>>
Prefs
   1/*
   2 * QEMU Block driver for CURL images
   3 *
   4 * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
   5 *
   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:
  12 *
  13 * The above copyright notice and this permission notice shall be included in
  14 * all copies or substantial portions of the Software.
  15 *
  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
  22 * THE SOFTWARE.
  23 */
  24#include "qemu/osdep.h"
  25#include "qapi/error.h"
  26#include "qemu-common.h"
  27#include "qemu/error-report.h"
  28#include "block/block_int.h"
  29#include "qapi/qmp/qbool.h"
  30#include "qapi/qmp/qstring.h"
  31#include "crypto/secret.h"
  32#include <curl/curl.h>
  33#include "qemu/cutils.h"
  34
  35// #define DEBUG_CURL
  36// #define DEBUG_VERBOSE
  37
  38#ifdef DEBUG_CURL
  39#define DEBUG_CURL_PRINT 1
  40#else
  41#define DEBUG_CURL_PRINT 0
  42#endif
  43#define DPRINTF(fmt, ...)                                            \
  44    do {                                                             \
  45        if (DEBUG_CURL_PRINT) {                                      \
  46            fprintf(stderr, fmt, ## __VA_ARGS__);                    \
  47        }                                                            \
  48    } while (0)
  49
  50#if LIBCURL_VERSION_NUM >= 0x071000
  51/* The multi interface timer callback was introduced in 7.16.0 */
  52#define NEED_CURL_TIMER_CALLBACK
  53#define HAVE_SOCKET_ACTION
  54#endif
  55
  56#ifndef HAVE_SOCKET_ACTION
  57/* If curl_multi_socket_action isn't available, define it statically here in
  58 * terms of curl_multi_socket. Note that ev_bitmask will be ignored, which is
  59 * less efficient but still safe. */
  60static CURLMcode __curl_multi_socket_action(CURLM *multi_handle,
  61                                            curl_socket_t sockfd,
  62                                            int ev_bitmask,
  63                                            int *running_handles)
  64{
  65    return curl_multi_socket(multi_handle, sockfd, running_handles);
  66}
  67#define curl_multi_socket_action __curl_multi_socket_action
  68#endif
  69
  70#define PROTOCOLS (CURLPROTO_HTTP | CURLPROTO_HTTPS | \
  71                   CURLPROTO_FTP | CURLPROTO_FTPS)
  72
  73#define CURL_NUM_STATES 8
  74#define CURL_NUM_ACB    8
  75#define READ_AHEAD_DEFAULT (256 * 1024)
  76#define CURL_TIMEOUT_DEFAULT 5
  77#define CURL_TIMEOUT_MAX 10000
  78
  79#define FIND_RET_NONE   0
  80#define FIND_RET_OK     1
  81#define FIND_RET_WAIT   2
  82
  83#define CURL_BLOCK_OPT_URL       "url"
  84#define CURL_BLOCK_OPT_READAHEAD "readahead"
  85#define CURL_BLOCK_OPT_SSLVERIFY "sslverify"
  86#define CURL_BLOCK_OPT_TIMEOUT "timeout"
  87#define CURL_BLOCK_OPT_COOKIE    "cookie"
  88#define CURL_BLOCK_OPT_USERNAME "username"
  89#define CURL_BLOCK_OPT_PASSWORD_SECRET "password-secret"
  90#define CURL_BLOCK_OPT_PROXY_USERNAME "proxy-username"
  91#define CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET "proxy-password-secret"
  92
  93struct BDRVCURLState;
  94
  95typedef struct CURLAIOCB {
  96    BlockAIOCB common;
  97    QEMUIOVector *qiov;
  98
  99    int64_t sector_num;
 100    int nb_sectors;
 101
 102    size_t start;
 103    size_t end;
 104} CURLAIOCB;
 105
 106typedef struct CURLSocket {
 107    int fd;
 108    QLIST_ENTRY(CURLSocket) next;
 109} CURLSocket;
 110
 111typedef struct CURLState
 112{
 113    struct BDRVCURLState *s;
 114    CURLAIOCB *acb[CURL_NUM_ACB];
 115    CURL *curl;
 116    QLIST_HEAD(, CURLSocket) sockets;
 117    char *orig_buf;
 118    size_t buf_start;
 119    size_t buf_off;
 120    size_t buf_len;
 121    char range[128];
 122    char errmsg[CURL_ERROR_SIZE];
 123    char in_use;
 124} CURLState;
 125
 126typedef struct BDRVCURLState {
 127    CURLM *multi;
 128    QEMUTimer timer;
 129    size_t len;
 130    CURLState states[CURL_NUM_STATES];
 131    char *url;
 132    size_t readahead_size;
 133    bool sslverify;
 134    uint64_t timeout;
 135    char *cookie;
 136    bool accept_range;
 137    AioContext *aio_context;
 138    char *username;
 139    char *password;
 140    char *proxyusername;
 141    char *proxypassword;
 142} BDRVCURLState;
 143
 144static void curl_clean_state(CURLState *s);
 145static void curl_multi_do(void *arg);
 146static void curl_multi_read(void *arg);
 147
 148#ifdef NEED_CURL_TIMER_CALLBACK
 149static int curl_timer_cb(CURLM *multi, long timeout_ms, void *opaque)
 150{
 151    BDRVCURLState *s = opaque;
 152
 153    DPRINTF("CURL: timer callback timeout_ms %ld\n", timeout_ms);
 154    if (timeout_ms == -1) {
 155        timer_del(&s->timer);
 156    } else {
 157        int64_t timeout_ns = (int64_t)timeout_ms * 1000 * 1000;
 158        timer_mod(&s->timer,
 159                  qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + timeout_ns);
 160    }
 161    return 0;
 162}
 163#endif
 164
 165static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
 166                        void *userp, void *sp)
 167{
 168    BDRVCURLState *s;
 169    CURLState *state = NULL;
 170    CURLSocket *socket;
 171
 172    curl_easy_getinfo(curl, CURLINFO_PRIVATE, (char **)&state);
 173    s = state->s;
 174
 175    QLIST_FOREACH(socket, &state->sockets, next) {
 176        if (socket->fd == fd) {
 177            if (action == CURL_POLL_REMOVE) {
 178                QLIST_REMOVE(socket, next);
 179                g_free(socket);
 180            }
 181            break;
 182        }
 183    }
 184    if (!socket) {
 185        socket = g_new0(CURLSocket, 1);
 186        socket->fd = fd;
 187        QLIST_INSERT_HEAD(&state->sockets, socket, next);
 188    }
 189    socket = NULL;
 190
 191    DPRINTF("CURL (AIO): Sock action %d on fd %d\n", action, (int)fd);
 192    switch (action) {
 193        case CURL_POLL_IN:
 194            aio_set_fd_handler(s->aio_context, fd, false,
 195                               curl_multi_read, NULL, state);
 196            break;
 197        case CURL_POLL_OUT:
 198            aio_set_fd_handler(s->aio_context, fd, false,
 199                               NULL, curl_multi_do, state);
 200            break;
 201        case CURL_POLL_INOUT:
 202            aio_set_fd_handler(s->aio_context, fd, false,
 203                               curl_multi_read, curl_multi_do, state);
 204            break;
 205        case CURL_POLL_REMOVE:
 206            aio_set_fd_handler(s->aio_context, fd, false,
 207                               NULL, NULL, NULL);
 208            break;
 209    }
 210
 211    return 0;
 212}
 213
 214static size_t curl_header_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
 215{
 216    BDRVCURLState *s = opaque;
 217    size_t realsize = size * nmemb;
 218    const char *accept_line = "Accept-Ranges: bytes";
 219
 220    if (realsize >= strlen(accept_line)
 221        && strncmp((char *)ptr, accept_line, strlen(accept_line)) == 0) {
 222        s->accept_range = true;
 223    }
 224
 225    return realsize;
 226}
 227
 228static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
 229{
 230    CURLState *s = ((CURLState*)opaque);
 231    size_t realsize = size * nmemb;
 232    int i;
 233
 234    DPRINTF("CURL: Just reading %zd bytes\n", realsize);
 235
 236    if (!s || !s->orig_buf) {
 237        goto read_end;
 238    }
 239
 240    if (s->buf_off >= s->buf_len) {
 241        /* buffer full, read nothing */
 242        goto read_end;
 243    }
 244    realsize = MIN(realsize, s->buf_len - s->buf_off);
 245    memcpy(s->orig_buf + s->buf_off, ptr, realsize);
 246    s->buf_off += realsize;
 247
 248    for(i=0; i<CURL_NUM_ACB; i++) {
 249        CURLAIOCB *acb = s->acb[i];
 250
 251        if (!acb)
 252            continue;
 253
 254        if ((s->buf_off >= acb->end)) {
 255            size_t request_length = acb->nb_sectors * BDRV_SECTOR_SIZE;
 256
 257            qemu_iovec_from_buf(acb->qiov, 0, s->orig_buf + acb->start,
 258                                acb->end - acb->start);
 259
 260            if (acb->end - acb->start < request_length) {
 261                size_t offset = acb->end - acb->start;
 262                qemu_iovec_memset(acb->qiov, offset, 0,
 263                                  request_length - offset);
 264            }
 265
 266            acb->common.cb(acb->common.opaque, 0);
 267            qemu_aio_unref(acb);
 268            s->acb[i] = NULL;
 269        }
 270    }
 271
 272read_end:
 273    /* curl will error out if we do not return this value */
 274    return size * nmemb;
 275}
 276
 277static int curl_find_buf(BDRVCURLState *s, size_t start, size_t len,
 278                         CURLAIOCB *acb)
 279{
 280    int i;
 281    size_t end = start + len;
 282    size_t clamped_end = MIN(end, s->len);
 283    size_t clamped_len = clamped_end - start;
 284
 285    for (i=0; i<CURL_NUM_STATES; i++) {
 286        CURLState *state = &s->states[i];
 287        size_t buf_end = (state->buf_start + state->buf_off);
 288        size_t buf_fend = (state->buf_start + state->buf_len);
 289
 290        if (!state->orig_buf)
 291            continue;
 292        if (!state->buf_off)
 293            continue;
 294
 295        // Does the existing buffer cover our section?
 296        if ((start >= state->buf_start) &&
 297            (start <= buf_end) &&
 298            (clamped_end >= state->buf_start) &&
 299            (clamped_end <= buf_end))
 300        {
 301            char *buf = state->orig_buf + (start - state->buf_start);
 302
 303            qemu_iovec_from_buf(acb->qiov, 0, buf, clamped_len);
 304            if (clamped_len < len) {
 305                qemu_iovec_memset(acb->qiov, clamped_len, 0, len - clamped_len);
 306            }
 307            acb->common.cb(acb->common.opaque, 0);
 308
 309            return FIND_RET_OK;
 310        }
 311
 312        // Wait for unfinished chunks
 313        if (state->in_use &&
 314            (start >= state->buf_start) &&
 315            (start <= buf_fend) &&
 316            (clamped_end >= state->buf_start) &&
 317            (clamped_end <= buf_fend))
 318        {
 319            int j;
 320
 321            acb->start = start - state->buf_start;
 322            acb->end = acb->start + clamped_len;
 323
 324            for (j=0; j<CURL_NUM_ACB; j++) {
 325                if (!state->acb[j]) {
 326                    state->acb[j] = acb;
 327                    return FIND_RET_WAIT;
 328                }
 329            }
 330        }
 331    }
 332
 333    return FIND_RET_NONE;
 334}
 335
 336static void curl_multi_check_completion(BDRVCURLState *s)
 337{
 338    int msgs_in_queue;
 339
 340    /* Try to find done transfers, so we can free the easy
 341     * handle again. */
 342    for (;;) {
 343        CURLMsg *msg;
 344        msg = curl_multi_info_read(s->multi, &msgs_in_queue);
 345
 346        /* Quit when there are no more completions */
 347        if (!msg)
 348            break;
 349
 350        if (msg->msg == CURLMSG_DONE) {
 351            CURLState *state = NULL;
 352            curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE,
 353                              (char **)&state);
 354
 355            /* ACBs for successful messages get completed in curl_read_cb */
 356            if (msg->data.result != CURLE_OK) {
 357                int i;
 358                static int errcount = 100;
 359
 360                /* Don't lose the original error message from curl, since
 361                 * it contains extra data.
 362                 */
 363                if (errcount > 0) {
 364                    error_report("curl: %s", state->errmsg);
 365                    if (--errcount == 0) {
 366                        error_report("curl: further errors suppressed");
 367                    }
 368                }
 369
 370                for (i = 0; i < CURL_NUM_ACB; i++) {
 371                    CURLAIOCB *acb = state->acb[i];
 372
 373                    if (acb == NULL) {
 374                        continue;
 375                    }
 376
 377                    acb->common.cb(acb->common.opaque, -EPROTO);
 378                    qemu_aio_unref(acb);
 379                    state->acb[i] = NULL;
 380                }
 381            }
 382
 383            curl_clean_state(state);
 384            break;
 385        }
 386    }
 387}
 388
 389static void curl_multi_do(void *arg)
 390{
 391    CURLState *s = (CURLState *)arg;
 392    CURLSocket *socket, *next_socket;
 393    int running;
 394    int r;
 395
 396    if (!s->s->multi) {
 397        return;
 398    }
 399
 400    /* Need to use _SAFE because curl_multi_socket_action() may trigger
 401     * curl_sock_cb() which might modify this list */
 402    QLIST_FOREACH_SAFE(socket, &s->sockets, next, next_socket) {
 403        do {
 404            r = curl_multi_socket_action(s->s->multi, socket->fd, 0, &running);
 405        } while (r == CURLM_CALL_MULTI_PERFORM);
 406    }
 407}
 408
 409static void curl_multi_read(void *arg)
 410{
 411    CURLState *s = (CURLState *)arg;
 412
 413    curl_multi_do(arg);
 414    curl_multi_check_completion(s->s);
 415}
 416
 417static void curl_multi_timeout_do(void *arg)
 418{
 419#ifdef NEED_CURL_TIMER_CALLBACK
 420    BDRVCURLState *s = (BDRVCURLState *)arg;
 421    int running;
 422
 423    if (!s->multi) {
 424        return;
 425    }
 426
 427    curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running);
 428
 429    curl_multi_check_completion(s);
 430#else
 431    abort();
 432#endif
 433}
 434
 435static CURLState *curl_init_state(BlockDriverState *bs, BDRVCURLState *s)
 436{
 437    CURLState *state = NULL;
 438    int i, j;
 439
 440    do {
 441        for (i=0; i<CURL_NUM_STATES; i++) {
 442            for (j=0; j<CURL_NUM_ACB; j++)
 443                if (s->states[i].acb[j])
 444                    continue;
 445            if (s->states[i].in_use)
 446                continue;
 447
 448            state = &s->states[i];
 449            state->in_use = 1;
 450            break;
 451        }
 452        if (!state) {
 453            aio_poll(bdrv_get_aio_context(bs), true);
 454        }
 455    } while(!state);
 456
 457    if (!state->curl) {
 458        state->curl = curl_easy_init();
 459        if (!state->curl) {
 460            return NULL;
 461        }
 462        curl_easy_setopt(state->curl, CURLOPT_URL, s->url);
 463        curl_easy_setopt(state->curl, CURLOPT_SSL_VERIFYPEER,
 464                         (long) s->sslverify);
 465        if (s->cookie) {
 466            curl_easy_setopt(state->curl, CURLOPT_COOKIE, s->cookie);
 467        }
 468        curl_easy_setopt(state->curl, CURLOPT_TIMEOUT, (long)s->timeout);
 469        curl_easy_setopt(state->curl, CURLOPT_WRITEFUNCTION,
 470                         (void *)curl_read_cb);
 471        curl_easy_setopt(state->curl, CURLOPT_WRITEDATA, (void *)state);
 472        curl_easy_setopt(state->curl, CURLOPT_PRIVATE, (void *)state);
 473        curl_easy_setopt(state->curl, CURLOPT_AUTOREFERER, 1);
 474        curl_easy_setopt(state->curl, CURLOPT_FOLLOWLOCATION, 1);
 475        curl_easy_setopt(state->curl, CURLOPT_NOSIGNAL, 1);
 476        curl_easy_setopt(state->curl, CURLOPT_ERRORBUFFER, state->errmsg);
 477        curl_easy_setopt(state->curl, CURLOPT_FAILONERROR, 1);
 478
 479        if (s->username) {
 480            curl_easy_setopt(state->curl, CURLOPT_USERNAME, s->username);
 481        }
 482        if (s->password) {
 483            curl_easy_setopt(state->curl, CURLOPT_PASSWORD, s->password);
 484        }
 485        if (s->proxyusername) {
 486            curl_easy_setopt(state->curl,
 487                             CURLOPT_PROXYUSERNAME, s->proxyusername);
 488        }
 489        if (s->proxypassword) {
 490            curl_easy_setopt(state->curl,
 491                             CURLOPT_PROXYPASSWORD, s->proxypassword);
 492        }
 493
 494        /* Restrict supported protocols to avoid security issues in the more
 495         * obscure protocols.  For example, do not allow POP3/SMTP/IMAP see
 496         * CVE-2013-0249.
 497         *
 498         * Restricting protocols is only supported from 7.19.4 upwards.
 499         */
 500#if LIBCURL_VERSION_NUM >= 0x071304
 501        curl_easy_setopt(state->curl, CURLOPT_PROTOCOLS, PROTOCOLS);
 502        curl_easy_setopt(state->curl, CURLOPT_REDIR_PROTOCOLS, PROTOCOLS);
 503#endif
 504
 505#ifdef DEBUG_VERBOSE
 506        curl_easy_setopt(state->curl, CURLOPT_VERBOSE, 1);
 507#endif
 508    }
 509
 510    QLIST_INIT(&state->sockets);
 511    state->s = s;
 512
 513    return state;
 514}
 515
 516static void curl_clean_state(CURLState *s)
 517{
 518    if (s->s->multi)
 519        curl_multi_remove_handle(s->s->multi, s->curl);
 520
 521    while (!QLIST_EMPTY(&s->sockets)) {
 522        CURLSocket *socket = QLIST_FIRST(&s->sockets);
 523
 524        QLIST_REMOVE(socket, next);
 525        g_free(socket);
 526    }
 527
 528    s->in_use = 0;
 529}
 530
 531static void curl_parse_filename(const char *filename, QDict *options,
 532                                Error **errp)
 533{
 534    qdict_put(options, CURL_BLOCK_OPT_URL, qstring_from_str(filename));
 535}
 536
 537static void curl_detach_aio_context(BlockDriverState *bs)
 538{
 539    BDRVCURLState *s = bs->opaque;
 540    int i;
 541
 542    for (i = 0; i < CURL_NUM_STATES; i++) {
 543        if (s->states[i].in_use) {
 544            curl_clean_state(&s->states[i]);
 545        }
 546        if (s->states[i].curl) {
 547            curl_easy_cleanup(s->states[i].curl);
 548            s->states[i].curl = NULL;
 549        }
 550        g_free(s->states[i].orig_buf);
 551        s->states[i].orig_buf = NULL;
 552    }
 553    if (s->multi) {
 554        curl_multi_cleanup(s->multi);
 555        s->multi = NULL;
 556    }
 557
 558    timer_del(&s->timer);
 559}
 560
 561static void curl_attach_aio_context(BlockDriverState *bs,
 562                                    AioContext *new_context)
 563{
 564    BDRVCURLState *s = bs->opaque;
 565
 566    aio_timer_init(new_context, &s->timer,
 567                   QEMU_CLOCK_REALTIME, SCALE_NS,
 568                   curl_multi_timeout_do, s);
 569
 570    assert(!s->multi);
 571    s->multi = curl_multi_init();
 572    s->aio_context = new_context;
 573    curl_multi_setopt(s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb);
 574#ifdef NEED_CURL_TIMER_CALLBACK
 575    curl_multi_setopt(s->multi, CURLMOPT_TIMERDATA, s);
 576    curl_multi_setopt(s->multi, CURLMOPT_TIMERFUNCTION, curl_timer_cb);
 577#endif
 578}
 579
 580static QemuOptsList runtime_opts = {
 581    .name = "curl",
 582    .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
 583    .desc = {
 584        {
 585            .name = CURL_BLOCK_OPT_URL,
 586            .type = QEMU_OPT_STRING,
 587            .help = "URL to open",
 588        },
 589        {
 590            .name = CURL_BLOCK_OPT_READAHEAD,
 591            .type = QEMU_OPT_SIZE,
 592            .help = "Readahead size",
 593        },
 594        {
 595            .name = CURL_BLOCK_OPT_SSLVERIFY,
 596            .type = QEMU_OPT_BOOL,
 597            .help = "Verify SSL certificate"
 598        },
 599        {
 600            .name = CURL_BLOCK_OPT_TIMEOUT,
 601            .type = QEMU_OPT_NUMBER,
 602            .help = "Curl timeout"
 603        },
 604        {
 605            .name = CURL_BLOCK_OPT_COOKIE,
 606            .type = QEMU_OPT_STRING,
 607            .help = "Pass the cookie or list of cookies with each request"
 608        },
 609        {
 610            .name = CURL_BLOCK_OPT_USERNAME,
 611            .type = QEMU_OPT_STRING,
 612            .help = "Username for HTTP auth"
 613        },
 614        {
 615            .name = CURL_BLOCK_OPT_PASSWORD_SECRET,
 616            .type = QEMU_OPT_STRING,
 617            .help = "ID of secret used as password for HTTP auth",
 618        },
 619        {
 620            .name = CURL_BLOCK_OPT_PROXY_USERNAME,
 621            .type = QEMU_OPT_STRING,
 622            .help = "Username for HTTP proxy auth"
 623        },
 624        {
 625            .name = CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET,
 626            .type = QEMU_OPT_STRING,
 627            .help = "ID of secret used as password for HTTP proxy auth",
 628        },
 629        { /* end of list */ }
 630    },
 631};
 632
 633
 634static int curl_open(BlockDriverState *bs, QDict *options, int flags,
 635                     Error **errp)
 636{
 637    BDRVCURLState *s = bs->opaque;
 638    CURLState *state = NULL;
 639    QemuOpts *opts;
 640    Error *local_err = NULL;
 641    const char *file;
 642    const char *cookie;
 643    double d;
 644    const char *secretid;
 645
 646    static int inited = 0;
 647
 648    if (flags & BDRV_O_RDWR) {
 649        error_setg(errp, "curl block device does not support writes");
 650        return -EROFS;
 651    }
 652
 653    opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
 654    qemu_opts_absorb_qdict(opts, options, &local_err);
 655    if (local_err) {
 656        error_propagate(errp, local_err);
 657        goto out_noclean;
 658    }
 659
 660    s->readahead_size = qemu_opt_get_size(opts, CURL_BLOCK_OPT_READAHEAD,
 661                                          READ_AHEAD_DEFAULT);
 662    if ((s->readahead_size & 0x1ff) != 0) {
 663        error_setg(errp, "HTTP_READAHEAD_SIZE %zd is not a multiple of 512",
 664                   s->readahead_size);
 665        goto out_noclean;
 666    }
 667
 668    s->timeout = qemu_opt_get_number(opts, CURL_BLOCK_OPT_TIMEOUT,
 669                                     CURL_TIMEOUT_DEFAULT);
 670    if (s->timeout > CURL_TIMEOUT_MAX) {
 671        error_setg(errp, "timeout parameter is too large or negative");
 672        goto out_noclean;
 673    }
 674
 675    s->sslverify = qemu_opt_get_bool(opts, CURL_BLOCK_OPT_SSLVERIFY, true);
 676
 677    cookie = qemu_opt_get(opts, CURL_BLOCK_OPT_COOKIE);
 678    s->cookie = g_strdup(cookie);
 679
 680    file = qemu_opt_get(opts, CURL_BLOCK_OPT_URL);
 681    if (file == NULL) {
 682        error_setg(errp, "curl block driver requires an 'url' option");
 683        goto out_noclean;
 684    }
 685
 686    s->username = g_strdup(qemu_opt_get(opts, CURL_BLOCK_OPT_USERNAME));
 687    secretid = qemu_opt_get(opts, CURL_BLOCK_OPT_PASSWORD_SECRET);
 688
 689    if (secretid) {
 690        s->password = qcrypto_secret_lookup_as_utf8(secretid, errp);
 691        if (!s->password) {
 692            goto out_noclean;
 693        }
 694    }
 695
 696    s->proxyusername = g_strdup(
 697        qemu_opt_get(opts, CURL_BLOCK_OPT_PROXY_USERNAME));
 698    secretid = qemu_opt_get(opts, CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET);
 699    if (secretid) {
 700        s->proxypassword = qcrypto_secret_lookup_as_utf8(secretid, errp);
 701        if (!s->proxypassword) {
 702            goto out_noclean;
 703        }
 704    }
 705
 706    if (!inited) {
 707        curl_global_init(CURL_GLOBAL_ALL);
 708        inited = 1;
 709    }
 710
 711    DPRINTF("CURL: Opening %s\n", file);
 712    s->aio_context = bdrv_get_aio_context(bs);
 713    s->url = g_strdup(file);
 714    state = curl_init_state(bs, s);
 715    if (!state)
 716        goto out_noclean;
 717
 718    // Get file size
 719
 720    s->accept_range = false;
 721    curl_easy_setopt(state->curl, CURLOPT_NOBODY, 1);
 722    curl_easy_setopt(state->curl, CURLOPT_HEADERFUNCTION,
 723                     curl_header_cb);
 724    curl_easy_setopt(state->curl, CURLOPT_HEADERDATA, s);
 725    if (curl_easy_perform(state->curl))
 726        goto out;
 727    if (curl_easy_getinfo(state->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d)) {
 728        goto out;
 729    }
 730    /* Prior CURL 7.19.4 return value of 0 could mean that the file size is not
 731     * know or the size is zero. From 7.19.4 CURL returns -1 if size is not
 732     * known and zero if it is realy zero-length file. */
 733#if LIBCURL_VERSION_NUM >= 0x071304
 734    if (d < 0) {
 735        pstrcpy(state->errmsg, CURL_ERROR_SIZE,
 736                "Server didn't report file size.");
 737        goto out;
 738    }
 739#else
 740    if (d <= 0) {
 741        pstrcpy(state->errmsg, CURL_ERROR_SIZE,
 742                "Unknown file size or zero-length file.");
 743        goto out;
 744    }
 745#endif
 746
 747    s->len = (size_t)d;
 748
 749    if ((!strncasecmp(s->url, "http://", strlen("http://"))
 750        || !strncasecmp(s->url, "https://", strlen("https://")))
 751        && !s->accept_range) {
 752        pstrcpy(state->errmsg, CURL_ERROR_SIZE,
 753                "Server does not support 'range' (byte ranges).");
 754        goto out;
 755    }
 756    DPRINTF("CURL: Size = %zd\n", s->len);
 757
 758    curl_clean_state(state);
 759    curl_easy_cleanup(state->curl);
 760    state->curl = NULL;
 761
 762    curl_attach_aio_context(bs, bdrv_get_aio_context(bs));
 763
 764    qemu_opts_del(opts);
 765    return 0;
 766
 767out:
 768    error_setg(errp, "CURL: Error opening file: %s", state->errmsg);
 769    curl_easy_cleanup(state->curl);
 770    state->curl = NULL;
 771out_noclean:
 772    g_free(s->cookie);
 773    g_free(s->url);
 774    qemu_opts_del(opts);
 775    return -EINVAL;
 776}
 777
 778static const AIOCBInfo curl_aiocb_info = {
 779    .aiocb_size         = sizeof(CURLAIOCB),
 780};
 781
 782
 783static void curl_readv_bh_cb(void *p)
 784{
 785    CURLState *state;
 786    int running;
 787
 788    CURLAIOCB *acb = p;
 789    BDRVCURLState *s = acb->common.bs->opaque;
 790
 791    size_t start = acb->sector_num * BDRV_SECTOR_SIZE;
 792    size_t end;
 793
 794    // In case we have the requested data already (e.g. read-ahead),
 795    // we can just call the callback and be done.
 796    switch (curl_find_buf(s, start, acb->nb_sectors * BDRV_SECTOR_SIZE, acb)) {
 797        case FIND_RET_OK:
 798            qemu_aio_unref(acb);
 799            // fall through
 800        case FIND_RET_WAIT:
 801            return;
 802        default:
 803            break;
 804    }
 805
 806    // No cache found, so let's start a new request
 807    state = curl_init_state(acb->common.bs, s);
 808    if (!state) {
 809        acb->common.cb(acb->common.opaque, -EIO);
 810        qemu_aio_unref(acb);
 811        return;
 812    }
 813
 814    acb->start = 0;
 815    acb->end = MIN(acb->nb_sectors * BDRV_SECTOR_SIZE, s->len - start);
 816
 817    state->buf_off = 0;
 818    g_free(state->orig_buf);
 819    state->buf_start = start;
 820    state->buf_len = MIN(acb->end + s->readahead_size, s->len - start);
 821    end = start + state->buf_len - 1;
 822    state->orig_buf = g_try_malloc(state->buf_len);
 823    if (state->buf_len && state->orig_buf == NULL) {
 824        curl_clean_state(state);
 825        acb->common.cb(acb->common.opaque, -ENOMEM);
 826        qemu_aio_unref(acb);
 827        return;
 828    }
 829    state->acb[0] = acb;
 830
 831    snprintf(state->range, 127, "%zd-%zd", start, end);
 832    DPRINTF("CURL (AIO): Reading %llu at %zd (%s)\n",
 833            (acb->nb_sectors * BDRV_SECTOR_SIZE), start, state->range);
 834    curl_easy_setopt(state->curl, CURLOPT_RANGE, state->range);
 835
 836    curl_multi_add_handle(s->multi, state->curl);
 837
 838    /* Tell curl it needs to kick things off */
 839    curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running);
 840}
 841
 842static BlockAIOCB *curl_aio_readv(BlockDriverState *bs,
 843        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
 844        BlockCompletionFunc *cb, void *opaque)
 845{
 846    CURLAIOCB *acb;
 847
 848    acb = qemu_aio_get(&curl_aiocb_info, bs, cb, opaque);
 849
 850    acb->qiov = qiov;
 851    acb->sector_num = sector_num;
 852    acb->nb_sectors = nb_sectors;
 853
 854    aio_bh_schedule_oneshot(bdrv_get_aio_context(bs), curl_readv_bh_cb, acb);
 855    return &acb->common;
 856}
 857
 858static void curl_close(BlockDriverState *bs)
 859{
 860    BDRVCURLState *s = bs->opaque;
 861
 862    DPRINTF("CURL: Close\n");
 863    curl_detach_aio_context(bs);
 864
 865    g_free(s->cookie);
 866    g_free(s->url);
 867}
 868
 869static int64_t curl_getlength(BlockDriverState *bs)
 870{
 871    BDRVCURLState *s = bs->opaque;
 872    return s->len;
 873}
 874
 875static BlockDriver bdrv_http = {
 876    .format_name                = "http",
 877    .protocol_name              = "http",
 878
 879    .instance_size              = sizeof(BDRVCURLState),
 880    .bdrv_parse_filename        = curl_parse_filename,
 881    .bdrv_file_open             = curl_open,
 882    .bdrv_close                 = curl_close,
 883    .bdrv_getlength             = curl_getlength,
 884
 885    .bdrv_aio_readv             = curl_aio_readv,
 886
 887    .bdrv_detach_aio_context    = curl_detach_aio_context,
 888    .bdrv_attach_aio_context    = curl_attach_aio_context,
 889};
 890
 891static BlockDriver bdrv_https = {
 892    .format_name                = "https",
 893    .protocol_name              = "https",
 894
 895    .instance_size              = sizeof(BDRVCURLState),
 896    .bdrv_parse_filename        = curl_parse_filename,
 897    .bdrv_file_open             = curl_open,
 898    .bdrv_close                 = curl_close,
 899    .bdrv_getlength             = curl_getlength,
 900
 901    .bdrv_aio_readv             = curl_aio_readv,
 902
 903    .bdrv_detach_aio_context    = curl_detach_aio_context,
 904    .bdrv_attach_aio_context    = curl_attach_aio_context,
 905};
 906
 907static BlockDriver bdrv_ftp = {
 908    .format_name                = "ftp",
 909    .protocol_name              = "ftp",
 910
 911    .instance_size              = sizeof(BDRVCURLState),
 912    .bdrv_parse_filename        = curl_parse_filename,
 913    .bdrv_file_open             = curl_open,
 914    .bdrv_close                 = curl_close,
 915    .bdrv_getlength             = curl_getlength,
 916
 917    .bdrv_aio_readv             = curl_aio_readv,
 918
 919    .bdrv_detach_aio_context    = curl_detach_aio_context,
 920    .bdrv_attach_aio_context    = curl_attach_aio_context,
 921};
 922
 923static BlockDriver bdrv_ftps = {
 924    .format_name                = "ftps",
 925    .protocol_name              = "ftps",
 926
 927    .instance_size              = sizeof(BDRVCURLState),
 928    .bdrv_parse_filename        = curl_parse_filename,
 929    .bdrv_file_open             = curl_open,
 930    .bdrv_close                 = curl_close,
 931    .bdrv_getlength             = curl_getlength,
 932
 933    .bdrv_aio_readv             = curl_aio_readv,
 934
 935    .bdrv_detach_aio_context    = curl_detach_aio_context,
 936    .bdrv_attach_aio_context    = curl_attach_aio_context,
 937};
 938
 939static void curl_block_init(void)
 940{
 941    bdrv_register(&bdrv_http);
 942    bdrv_register(&bdrv_https);
 943    bdrv_register(&bdrv_ftp);
 944    bdrv_register(&bdrv_ftps);
 945}
 946
 947block_init(curl_block_init);
 948