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