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 25 #include "qemu/osdep.h" 26 #include "qapi/error.h" 27 #include "qemu/error-report.h" 28 #include "qemu/option.h" 29 #include "block/block_int.h" 30 #include "qapi/qmp/qdict.h" 31 #include "qapi/qmp/qstring.h" 32 #include "crypto/secret.h" 33 #include <curl/curl.h> 34 #include "qemu/cutils.h" 35 #include "trace.h" 36 37 // #define DEBUG_VERBOSE 38 39 #if LIBCURL_VERSION_NUM >= 0x071000 40 /* The multi interface timer callback was introduced in 7.16.0 */ 41 #define NEED_CURL_TIMER_CALLBACK 42 #define HAVE_SOCKET_ACTION 43 #endif 44 45 #ifndef HAVE_SOCKET_ACTION 46 /* If curl_multi_socket_action isn't available, define it statically here in 47 * terms of curl_multi_socket. Note that ev_bitmask will be ignored, which is 48 * less efficient but still safe. */ 49 static CURLMcode __curl_multi_socket_action(CURLM *multi_handle, 50 curl_socket_t sockfd, 51 int ev_bitmask, 52 int *running_handles) 53 { 54 return curl_multi_socket(multi_handle, sockfd, running_handles); 55 } 56 #define curl_multi_socket_action __curl_multi_socket_action 57 #endif 58 59 #define PROTOCOLS (CURLPROTO_HTTP | CURLPROTO_HTTPS | \ 60 CURLPROTO_FTP | CURLPROTO_FTPS) 61 62 #define CURL_NUM_STATES 8 63 #define CURL_NUM_ACB 8 64 #define CURL_TIMEOUT_MAX 10000 65 66 #define CURL_BLOCK_OPT_URL "url" 67 #define CURL_BLOCK_OPT_READAHEAD "readahead" 68 #define CURL_BLOCK_OPT_SSLVERIFY "sslverify" 69 #define CURL_BLOCK_OPT_TIMEOUT "timeout" 70 #define CURL_BLOCK_OPT_COOKIE "cookie" 71 #define CURL_BLOCK_OPT_COOKIE_SECRET "cookie-secret" 72 #define CURL_BLOCK_OPT_USERNAME "username" 73 #define CURL_BLOCK_OPT_PASSWORD_SECRET "password-secret" 74 #define CURL_BLOCK_OPT_PROXY_USERNAME "proxy-username" 75 #define CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET "proxy-password-secret" 76 77 #define CURL_BLOCK_OPT_READAHEAD_DEFAULT (256 * 1024) 78 #define CURL_BLOCK_OPT_SSLVERIFY_DEFAULT true 79 #define CURL_BLOCK_OPT_TIMEOUT_DEFAULT 5 80 81 struct BDRVCURLState; 82 83 static bool libcurl_initialized; 84 85 typedef struct CURLAIOCB { 86 Coroutine *co; 87 QEMUIOVector *qiov; 88 89 uint64_t offset; 90 uint64_t bytes; 91 int ret; 92 93 size_t start; 94 size_t end; 95 } CURLAIOCB; 96 97 typedef struct CURLSocket { 98 int fd; 99 QLIST_ENTRY(CURLSocket) next; 100 } CURLSocket; 101 102 typedef struct CURLState 103 { 104 struct BDRVCURLState *s; 105 CURLAIOCB *acb[CURL_NUM_ACB]; 106 CURL *curl; 107 QLIST_HEAD(, CURLSocket) sockets; 108 char *orig_buf; 109 uint64_t buf_start; 110 size_t buf_off; 111 size_t buf_len; 112 char range[128]; 113 char errmsg[CURL_ERROR_SIZE]; 114 char in_use; 115 } CURLState; 116 117 typedef struct BDRVCURLState { 118 CURLM *multi; 119 QEMUTimer timer; 120 uint64_t len; 121 CURLState states[CURL_NUM_STATES]; 122 char *url; 123 size_t readahead_size; 124 bool sslverify; 125 uint64_t timeout; 126 char *cookie; 127 bool accept_range; 128 AioContext *aio_context; 129 QemuMutex mutex; 130 CoQueue free_state_waitq; 131 char *username; 132 char *password; 133 char *proxyusername; 134 char *proxypassword; 135 } BDRVCURLState; 136 137 static void curl_clean_state(CURLState *s); 138 static void curl_multi_do(void *arg); 139 static void curl_multi_read(void *arg); 140 141 #ifdef NEED_CURL_TIMER_CALLBACK 142 /* Called from curl_multi_do_locked, with s->mutex held. */ 143 static int curl_timer_cb(CURLM *multi, long timeout_ms, void *opaque) 144 { 145 BDRVCURLState *s = opaque; 146 147 trace_curl_timer_cb(timeout_ms); 148 if (timeout_ms == -1) { 149 timer_del(&s->timer); 150 } else { 151 int64_t timeout_ns = (int64_t)timeout_ms * 1000 * 1000; 152 timer_mod(&s->timer, 153 qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + timeout_ns); 154 } 155 return 0; 156 } 157 #endif 158 159 /* Called from curl_multi_do_locked, with s->mutex held. */ 160 static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, 161 void *userp, void *sp) 162 { 163 BDRVCURLState *s; 164 CURLState *state = NULL; 165 CURLSocket *socket; 166 167 curl_easy_getinfo(curl, CURLINFO_PRIVATE, (char **)&state); 168 s = state->s; 169 170 QLIST_FOREACH(socket, &state->sockets, next) { 171 if (socket->fd == fd) { 172 if (action == CURL_POLL_REMOVE) { 173 QLIST_REMOVE(socket, next); 174 g_free(socket); 175 } 176 break; 177 } 178 } 179 if (!socket) { 180 socket = g_new0(CURLSocket, 1); 181 socket->fd = fd; 182 QLIST_INSERT_HEAD(&state->sockets, socket, next); 183 } 184 socket = NULL; 185 186 trace_curl_sock_cb(action, (int)fd); 187 switch (action) { 188 case CURL_POLL_IN: 189 aio_set_fd_handler(s->aio_context, fd, false, 190 curl_multi_read, NULL, NULL, state); 191 break; 192 case CURL_POLL_OUT: 193 aio_set_fd_handler(s->aio_context, fd, false, 194 NULL, curl_multi_do, NULL, state); 195 break; 196 case CURL_POLL_INOUT: 197 aio_set_fd_handler(s->aio_context, fd, false, 198 curl_multi_read, curl_multi_do, NULL, state); 199 break; 200 case CURL_POLL_REMOVE: 201 aio_set_fd_handler(s->aio_context, fd, false, 202 NULL, NULL, NULL, NULL); 203 break; 204 } 205 206 return 0; 207 } 208 209 /* Called from curl_multi_do_locked, with s->mutex held. */ 210 static size_t curl_header_cb(void *ptr, size_t size, size_t nmemb, void *opaque) 211 { 212 BDRVCURLState *s = opaque; 213 size_t realsize = size * nmemb; 214 const char *accept_line = "Accept-Ranges: bytes"; 215 216 if (realsize >= strlen(accept_line) 217 && strncmp((char *)ptr, accept_line, strlen(accept_line)) == 0) { 218 s->accept_range = true; 219 } 220 221 return realsize; 222 } 223 224 /* Called from curl_multi_do_locked, with s->mutex held. */ 225 static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque) 226 { 227 CURLState *s = ((CURLState*)opaque); 228 size_t realsize = size * nmemb; 229 int i; 230 231 trace_curl_read_cb(realsize); 232 233 if (!s || !s->orig_buf) { 234 goto read_end; 235 } 236 237 if (s->buf_off >= s->buf_len) { 238 /* buffer full, read nothing */ 239 goto read_end; 240 } 241 realsize = MIN(realsize, s->buf_len - s->buf_off); 242 memcpy(s->orig_buf + s->buf_off, ptr, realsize); 243 s->buf_off += realsize; 244 245 for(i=0; i<CURL_NUM_ACB; i++) { 246 CURLAIOCB *acb = s->acb[i]; 247 248 if (!acb) 249 continue; 250 251 if ((s->buf_off >= acb->end)) { 252 size_t request_length = acb->bytes; 253 254 qemu_iovec_from_buf(acb->qiov, 0, s->orig_buf + acb->start, 255 acb->end - acb->start); 256 257 if (acb->end - acb->start < request_length) { 258 size_t offset = acb->end - acb->start; 259 qemu_iovec_memset(acb->qiov, offset, 0, 260 request_length - offset); 261 } 262 263 acb->ret = 0; 264 s->acb[i] = NULL; 265 qemu_mutex_unlock(&s->s->mutex); 266 aio_co_wake(acb->co); 267 qemu_mutex_lock(&s->s->mutex); 268 } 269 } 270 271 read_end: 272 /* curl will error out if we do not return this value */ 273 return size * nmemb; 274 } 275 276 /* Called with s->mutex held. */ 277 static bool curl_find_buf(BDRVCURLState *s, uint64_t start, uint64_t len, 278 CURLAIOCB *acb) 279 { 280 int i; 281 uint64_t end = start + len; 282 uint64_t clamped_end = MIN(end, s->len); 283 uint64_t clamped_len = clamped_end - start; 284 285 for (i=0; i<CURL_NUM_STATES; i++) { 286 CURLState *state = &s->states[i]; 287 uint64_t buf_end = (state->buf_start + state->buf_off); 288 uint64_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->ret = 0; 308 return true; 309 } 310 311 // Wait for unfinished chunks 312 if (state->in_use && 313 (start >= state->buf_start) && 314 (start <= buf_fend) && 315 (clamped_end >= state->buf_start) && 316 (clamped_end <= buf_fend)) 317 { 318 int j; 319 320 acb->start = start - state->buf_start; 321 acb->end = acb->start + clamped_len; 322 323 for (j=0; j<CURL_NUM_ACB; j++) { 324 if (!state->acb[j]) { 325 state->acb[j] = acb; 326 return true; 327 } 328 } 329 } 330 } 331 332 return false; 333 } 334 335 /* Called with s->mutex held. */ 336 static 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->ret = -EIO; 378 state->acb[i] = NULL; 379 qemu_mutex_unlock(&s->mutex); 380 aio_co_wake(acb->co); 381 qemu_mutex_lock(&s->mutex); 382 } 383 } 384 385 curl_clean_state(state); 386 break; 387 } 388 } 389 } 390 391 /* Called with s->mutex held. */ 392 static void curl_multi_do_locked(CURLState *s) 393 { 394 CURLSocket *socket, *next_socket; 395 int running; 396 int r; 397 398 if (!s->s->multi) { 399 return; 400 } 401 402 /* Need to use _SAFE because curl_multi_socket_action() may trigger 403 * curl_sock_cb() which might modify this list */ 404 QLIST_FOREACH_SAFE(socket, &s->sockets, next, next_socket) { 405 do { 406 r = curl_multi_socket_action(s->s->multi, socket->fd, 0, &running); 407 } while (r == CURLM_CALL_MULTI_PERFORM); 408 } 409 } 410 411 static void curl_multi_do(void *arg) 412 { 413 CURLState *s = (CURLState *)arg; 414 415 qemu_mutex_lock(&s->s->mutex); 416 curl_multi_do_locked(s); 417 qemu_mutex_unlock(&s->s->mutex); 418 } 419 420 static void curl_multi_read(void *arg) 421 { 422 CURLState *s = (CURLState *)arg; 423 424 qemu_mutex_lock(&s->s->mutex); 425 curl_multi_do_locked(s); 426 curl_multi_check_completion(s->s); 427 qemu_mutex_unlock(&s->s->mutex); 428 } 429 430 static void curl_multi_timeout_do(void *arg) 431 { 432 #ifdef NEED_CURL_TIMER_CALLBACK 433 BDRVCURLState *s = (BDRVCURLState *)arg; 434 int running; 435 436 if (!s->multi) { 437 return; 438 } 439 440 qemu_mutex_lock(&s->mutex); 441 curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running); 442 443 curl_multi_check_completion(s); 444 qemu_mutex_unlock(&s->mutex); 445 #else 446 abort(); 447 #endif 448 } 449 450 /* Called with s->mutex held. */ 451 static CURLState *curl_find_state(BDRVCURLState *s) 452 { 453 CURLState *state = NULL; 454 int i; 455 456 for (i = 0; i < CURL_NUM_STATES; i++) { 457 if (!s->states[i].in_use) { 458 state = &s->states[i]; 459 state->in_use = 1; 460 break; 461 } 462 } 463 return state; 464 } 465 466 static int curl_init_state(BDRVCURLState *s, CURLState *state) 467 { 468 if (!state->curl) { 469 state->curl = curl_easy_init(); 470 if (!state->curl) { 471 return -EIO; 472 } 473 curl_easy_setopt(state->curl, CURLOPT_URL, s->url); 474 curl_easy_setopt(state->curl, CURLOPT_SSL_VERIFYPEER, 475 (long) s->sslverify); 476 curl_easy_setopt(state->curl, CURLOPT_SSL_VERIFYHOST, 477 s->sslverify ? 2L : 0L); 478 if (s->cookie) { 479 curl_easy_setopt(state->curl, CURLOPT_COOKIE, s->cookie); 480 } 481 curl_easy_setopt(state->curl, CURLOPT_TIMEOUT, (long)s->timeout); 482 curl_easy_setopt(state->curl, CURLOPT_WRITEFUNCTION, 483 (void *)curl_read_cb); 484 curl_easy_setopt(state->curl, CURLOPT_WRITEDATA, (void *)state); 485 curl_easy_setopt(state->curl, CURLOPT_PRIVATE, (void *)state); 486 curl_easy_setopt(state->curl, CURLOPT_AUTOREFERER, 1); 487 curl_easy_setopt(state->curl, CURLOPT_FOLLOWLOCATION, 1); 488 curl_easy_setopt(state->curl, CURLOPT_NOSIGNAL, 1); 489 curl_easy_setopt(state->curl, CURLOPT_ERRORBUFFER, state->errmsg); 490 curl_easy_setopt(state->curl, CURLOPT_FAILONERROR, 1); 491 492 if (s->username) { 493 curl_easy_setopt(state->curl, CURLOPT_USERNAME, s->username); 494 } 495 if (s->password) { 496 curl_easy_setopt(state->curl, CURLOPT_PASSWORD, s->password); 497 } 498 if (s->proxyusername) { 499 curl_easy_setopt(state->curl, 500 CURLOPT_PROXYUSERNAME, s->proxyusername); 501 } 502 if (s->proxypassword) { 503 curl_easy_setopt(state->curl, 504 CURLOPT_PROXYPASSWORD, s->proxypassword); 505 } 506 507 /* Restrict supported protocols to avoid security issues in the more 508 * obscure protocols. For example, do not allow POP3/SMTP/IMAP see 509 * CVE-2013-0249. 510 * 511 * Restricting protocols is only supported from 7.19.4 upwards. 512 */ 513 #if LIBCURL_VERSION_NUM >= 0x071304 514 curl_easy_setopt(state->curl, CURLOPT_PROTOCOLS, PROTOCOLS); 515 curl_easy_setopt(state->curl, CURLOPT_REDIR_PROTOCOLS, PROTOCOLS); 516 #endif 517 518 #ifdef DEBUG_VERBOSE 519 curl_easy_setopt(state->curl, CURLOPT_VERBOSE, 1); 520 #endif 521 } 522 523 QLIST_INIT(&state->sockets); 524 state->s = s; 525 526 return 0; 527 } 528 529 /* Called with s->mutex held. */ 530 static void curl_clean_state(CURLState *s) 531 { 532 int j; 533 for (j = 0; j < CURL_NUM_ACB; j++) { 534 assert(!s->acb[j]); 535 } 536 537 if (s->s->multi) 538 curl_multi_remove_handle(s->s->multi, s->curl); 539 540 while (!QLIST_EMPTY(&s->sockets)) { 541 CURLSocket *socket = QLIST_FIRST(&s->sockets); 542 543 QLIST_REMOVE(socket, next); 544 g_free(socket); 545 } 546 547 s->in_use = 0; 548 549 qemu_co_enter_next(&s->s->free_state_waitq, &s->s->mutex); 550 } 551 552 static void curl_parse_filename(const char *filename, QDict *options, 553 Error **errp) 554 { 555 qdict_put_str(options, CURL_BLOCK_OPT_URL, filename); 556 } 557 558 static void curl_detach_aio_context(BlockDriverState *bs) 559 { 560 BDRVCURLState *s = bs->opaque; 561 int i; 562 563 qemu_mutex_lock(&s->mutex); 564 for (i = 0; i < CURL_NUM_STATES; i++) { 565 if (s->states[i].in_use) { 566 curl_clean_state(&s->states[i]); 567 } 568 if (s->states[i].curl) { 569 curl_easy_cleanup(s->states[i].curl); 570 s->states[i].curl = NULL; 571 } 572 g_free(s->states[i].orig_buf); 573 s->states[i].orig_buf = NULL; 574 } 575 if (s->multi) { 576 curl_multi_cleanup(s->multi); 577 s->multi = NULL; 578 } 579 qemu_mutex_unlock(&s->mutex); 580 581 timer_del(&s->timer); 582 } 583 584 static void curl_attach_aio_context(BlockDriverState *bs, 585 AioContext *new_context) 586 { 587 BDRVCURLState *s = bs->opaque; 588 589 aio_timer_init(new_context, &s->timer, 590 QEMU_CLOCK_REALTIME, SCALE_NS, 591 curl_multi_timeout_do, s); 592 593 assert(!s->multi); 594 s->multi = curl_multi_init(); 595 s->aio_context = new_context; 596 curl_multi_setopt(s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb); 597 #ifdef NEED_CURL_TIMER_CALLBACK 598 curl_multi_setopt(s->multi, CURLMOPT_TIMERDATA, s); 599 curl_multi_setopt(s->multi, CURLMOPT_TIMERFUNCTION, curl_timer_cb); 600 #endif 601 } 602 603 static QemuOptsList runtime_opts = { 604 .name = "curl", 605 .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head), 606 .desc = { 607 { 608 .name = CURL_BLOCK_OPT_URL, 609 .type = QEMU_OPT_STRING, 610 .help = "URL to open", 611 }, 612 { 613 .name = CURL_BLOCK_OPT_READAHEAD, 614 .type = QEMU_OPT_SIZE, 615 .help = "Readahead size", 616 }, 617 { 618 .name = CURL_BLOCK_OPT_SSLVERIFY, 619 .type = QEMU_OPT_BOOL, 620 .help = "Verify SSL certificate" 621 }, 622 { 623 .name = CURL_BLOCK_OPT_TIMEOUT, 624 .type = QEMU_OPT_NUMBER, 625 .help = "Curl timeout" 626 }, 627 { 628 .name = CURL_BLOCK_OPT_COOKIE, 629 .type = QEMU_OPT_STRING, 630 .help = "Pass the cookie or list of cookies with each request" 631 }, 632 { 633 .name = CURL_BLOCK_OPT_COOKIE_SECRET, 634 .type = QEMU_OPT_STRING, 635 .help = "ID of secret used as cookie passed with each request" 636 }, 637 { 638 .name = CURL_BLOCK_OPT_USERNAME, 639 .type = QEMU_OPT_STRING, 640 .help = "Username for HTTP auth" 641 }, 642 { 643 .name = CURL_BLOCK_OPT_PASSWORD_SECRET, 644 .type = QEMU_OPT_STRING, 645 .help = "ID of secret used as password for HTTP auth", 646 }, 647 { 648 .name = CURL_BLOCK_OPT_PROXY_USERNAME, 649 .type = QEMU_OPT_STRING, 650 .help = "Username for HTTP proxy auth" 651 }, 652 { 653 .name = CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET, 654 .type = QEMU_OPT_STRING, 655 .help = "ID of secret used as password for HTTP proxy auth", 656 }, 657 { /* end of list */ } 658 }, 659 }; 660 661 662 static int curl_open(BlockDriverState *bs, QDict *options, int flags, 663 Error **errp) 664 { 665 BDRVCURLState *s = bs->opaque; 666 CURLState *state = NULL; 667 QemuOpts *opts; 668 Error *local_err = NULL; 669 const char *file; 670 const char *cookie; 671 const char *cookie_secret; 672 double d; 673 const char *secretid; 674 const char *protocol_delimiter; 675 int ret; 676 677 ret = bdrv_apply_auto_read_only(bs, "curl driver does not support writes", 678 errp); 679 if (ret < 0) { 680 return ret; 681 } 682 683 if (!libcurl_initialized) { 684 ret = curl_global_init(CURL_GLOBAL_ALL); 685 if (ret) { 686 error_setg(errp, "libcurl initialization failed with %d", ret); 687 return -EIO; 688 } 689 libcurl_initialized = true; 690 } 691 692 qemu_mutex_init(&s->mutex); 693 opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); 694 qemu_opts_absorb_qdict(opts, options, &local_err); 695 if (local_err) { 696 error_propagate(errp, local_err); 697 goto out_noclean; 698 } 699 700 s->readahead_size = qemu_opt_get_size(opts, CURL_BLOCK_OPT_READAHEAD, 701 CURL_BLOCK_OPT_READAHEAD_DEFAULT); 702 if ((s->readahead_size & 0x1ff) != 0) { 703 error_setg(errp, "HTTP_READAHEAD_SIZE %zd is not a multiple of 512", 704 s->readahead_size); 705 goto out_noclean; 706 } 707 708 s->timeout = qemu_opt_get_number(opts, CURL_BLOCK_OPT_TIMEOUT, 709 CURL_BLOCK_OPT_TIMEOUT_DEFAULT); 710 if (s->timeout > CURL_TIMEOUT_MAX) { 711 error_setg(errp, "timeout parameter is too large or negative"); 712 goto out_noclean; 713 } 714 715 s->sslverify = qemu_opt_get_bool(opts, CURL_BLOCK_OPT_SSLVERIFY, 716 CURL_BLOCK_OPT_SSLVERIFY_DEFAULT); 717 718 cookie = qemu_opt_get(opts, CURL_BLOCK_OPT_COOKIE); 719 cookie_secret = qemu_opt_get(opts, CURL_BLOCK_OPT_COOKIE_SECRET); 720 721 if (cookie && cookie_secret) { 722 error_setg(errp, 723 "curl driver cannot handle both cookie and cookie secret"); 724 goto out_noclean; 725 } 726 727 if (cookie_secret) { 728 s->cookie = qcrypto_secret_lookup_as_utf8(cookie_secret, errp); 729 if (!s->cookie) { 730 goto out_noclean; 731 } 732 } else { 733 s->cookie = g_strdup(cookie); 734 } 735 736 file = qemu_opt_get(opts, CURL_BLOCK_OPT_URL); 737 if (file == NULL) { 738 error_setg(errp, "curl block driver requires an 'url' option"); 739 goto out_noclean; 740 } 741 742 if (!strstart(file, bs->drv->protocol_name, &protocol_delimiter) || 743 !strstart(protocol_delimiter, "://", NULL)) 744 { 745 error_setg(errp, "%s curl driver cannot handle the URL '%s' (does not " 746 "start with '%s://')", bs->drv->protocol_name, file, 747 bs->drv->protocol_name); 748 goto out_noclean; 749 } 750 751 s->username = g_strdup(qemu_opt_get(opts, CURL_BLOCK_OPT_USERNAME)); 752 secretid = qemu_opt_get(opts, CURL_BLOCK_OPT_PASSWORD_SECRET); 753 754 if (secretid) { 755 s->password = qcrypto_secret_lookup_as_utf8(secretid, errp); 756 if (!s->password) { 757 goto out_noclean; 758 } 759 } 760 761 s->proxyusername = g_strdup( 762 qemu_opt_get(opts, CURL_BLOCK_OPT_PROXY_USERNAME)); 763 secretid = qemu_opt_get(opts, CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET); 764 if (secretid) { 765 s->proxypassword = qcrypto_secret_lookup_as_utf8(secretid, errp); 766 if (!s->proxypassword) { 767 goto out_noclean; 768 } 769 } 770 771 trace_curl_open(file); 772 qemu_co_queue_init(&s->free_state_waitq); 773 s->aio_context = bdrv_get_aio_context(bs); 774 s->url = g_strdup(file); 775 qemu_mutex_lock(&s->mutex); 776 state = curl_find_state(s); 777 qemu_mutex_unlock(&s->mutex); 778 if (!state) { 779 goto out_noclean; 780 } 781 782 // Get file size 783 784 if (curl_init_state(s, state) < 0) { 785 goto out; 786 } 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 really 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 = 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 trace_curl_open_size(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 g_free(s->username); 846 g_free(s->proxyusername); 847 g_free(s->proxypassword); 848 qemu_opts_del(opts); 849 return -EINVAL; 850 } 851 852 static void curl_setup_preadv(BlockDriverState *bs, CURLAIOCB *acb) 853 { 854 CURLState *state; 855 int running; 856 857 BDRVCURLState *s = bs->opaque; 858 859 uint64_t start = acb->offset; 860 uint64_t end; 861 862 qemu_mutex_lock(&s->mutex); 863 864 // In case we have the requested data already (e.g. read-ahead), 865 // we can just call the callback and be done. 866 if (curl_find_buf(s, start, acb->bytes, acb)) { 867 goto out; 868 } 869 870 // No cache found, so let's start a new request 871 for (;;) { 872 state = curl_find_state(s); 873 if (state) { 874 break; 875 } 876 qemu_co_queue_wait(&s->free_state_waitq, &s->mutex); 877 } 878 879 if (curl_init_state(s, state) < 0) { 880 curl_clean_state(state); 881 acb->ret = -EIO; 882 goto out; 883 } 884 885 acb->start = 0; 886 acb->end = MIN(acb->bytes, s->len - start); 887 888 state->buf_off = 0; 889 g_free(state->orig_buf); 890 state->buf_start = start; 891 state->buf_len = MIN(acb->end + s->readahead_size, s->len - start); 892 end = start + state->buf_len - 1; 893 state->orig_buf = g_try_malloc(state->buf_len); 894 if (state->buf_len && state->orig_buf == NULL) { 895 curl_clean_state(state); 896 acb->ret = -ENOMEM; 897 goto out; 898 } 899 state->acb[0] = acb; 900 901 snprintf(state->range, 127, "%" PRIu64 "-%" PRIu64, start, end); 902 trace_curl_setup_preadv(acb->bytes, start, state->range); 903 curl_easy_setopt(state->curl, CURLOPT_RANGE, state->range); 904 905 curl_multi_add_handle(s->multi, state->curl); 906 907 /* Tell curl it needs to kick things off */ 908 curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running); 909 910 out: 911 qemu_mutex_unlock(&s->mutex); 912 } 913 914 static int coroutine_fn curl_co_preadv(BlockDriverState *bs, 915 uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags) 916 { 917 CURLAIOCB acb = { 918 .co = qemu_coroutine_self(), 919 .ret = -EINPROGRESS, 920 .qiov = qiov, 921 .offset = offset, 922 .bytes = bytes 923 }; 924 925 curl_setup_preadv(bs, &acb); 926 while (acb.ret == -EINPROGRESS) { 927 qemu_coroutine_yield(); 928 } 929 return acb.ret; 930 } 931 932 static void curl_close(BlockDriverState *bs) 933 { 934 BDRVCURLState *s = bs->opaque; 935 936 trace_curl_close(); 937 curl_detach_aio_context(bs); 938 qemu_mutex_destroy(&s->mutex); 939 940 g_free(s->cookie); 941 g_free(s->url); 942 g_free(s->username); 943 g_free(s->proxyusername); 944 g_free(s->proxypassword); 945 } 946 947 static int64_t curl_getlength(BlockDriverState *bs) 948 { 949 BDRVCURLState *s = bs->opaque; 950 return s->len; 951 } 952 953 static void curl_refresh_filename(BlockDriverState *bs) 954 { 955 BDRVCURLState *s = bs->opaque; 956 957 /* "readahead" and "timeout" do not change the guest-visible data, 958 * so ignore them */ 959 if (s->sslverify != CURL_BLOCK_OPT_SSLVERIFY_DEFAULT || 960 s->cookie || s->username || s->password || s->proxyusername || 961 s->proxypassword) 962 { 963 return; 964 } 965 966 pstrcpy(bs->exact_filename, sizeof(bs->exact_filename), s->url); 967 } 968 969 970 static const char *const curl_strong_runtime_opts[] = { 971 CURL_BLOCK_OPT_URL, 972 CURL_BLOCK_OPT_SSLVERIFY, 973 CURL_BLOCK_OPT_COOKIE, 974 CURL_BLOCK_OPT_COOKIE_SECRET, 975 CURL_BLOCK_OPT_USERNAME, 976 CURL_BLOCK_OPT_PASSWORD_SECRET, 977 CURL_BLOCK_OPT_PROXY_USERNAME, 978 CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET, 979 980 NULL 981 }; 982 983 static BlockDriver bdrv_http = { 984 .format_name = "http", 985 .protocol_name = "http", 986 987 .instance_size = sizeof(BDRVCURLState), 988 .bdrv_parse_filename = curl_parse_filename, 989 .bdrv_file_open = curl_open, 990 .bdrv_close = curl_close, 991 .bdrv_getlength = curl_getlength, 992 993 .bdrv_co_preadv = curl_co_preadv, 994 995 .bdrv_detach_aio_context = curl_detach_aio_context, 996 .bdrv_attach_aio_context = curl_attach_aio_context, 997 998 .bdrv_refresh_filename = curl_refresh_filename, 999 .strong_runtime_opts = curl_strong_runtime_opts, 1000 }; 1001 1002 static BlockDriver bdrv_https = { 1003 .format_name = "https", 1004 .protocol_name = "https", 1005 1006 .instance_size = sizeof(BDRVCURLState), 1007 .bdrv_parse_filename = curl_parse_filename, 1008 .bdrv_file_open = curl_open, 1009 .bdrv_close = curl_close, 1010 .bdrv_getlength = curl_getlength, 1011 1012 .bdrv_co_preadv = curl_co_preadv, 1013 1014 .bdrv_detach_aio_context = curl_detach_aio_context, 1015 .bdrv_attach_aio_context = curl_attach_aio_context, 1016 1017 .bdrv_refresh_filename = curl_refresh_filename, 1018 .strong_runtime_opts = curl_strong_runtime_opts, 1019 }; 1020 1021 static BlockDriver bdrv_ftp = { 1022 .format_name = "ftp", 1023 .protocol_name = "ftp", 1024 1025 .instance_size = sizeof(BDRVCURLState), 1026 .bdrv_parse_filename = curl_parse_filename, 1027 .bdrv_file_open = curl_open, 1028 .bdrv_close = curl_close, 1029 .bdrv_getlength = curl_getlength, 1030 1031 .bdrv_co_preadv = curl_co_preadv, 1032 1033 .bdrv_detach_aio_context = curl_detach_aio_context, 1034 .bdrv_attach_aio_context = curl_attach_aio_context, 1035 1036 .bdrv_refresh_filename = curl_refresh_filename, 1037 .strong_runtime_opts = curl_strong_runtime_opts, 1038 }; 1039 1040 static BlockDriver bdrv_ftps = { 1041 .format_name = "ftps", 1042 .protocol_name = "ftps", 1043 1044 .instance_size = sizeof(BDRVCURLState), 1045 .bdrv_parse_filename = curl_parse_filename, 1046 .bdrv_file_open = curl_open, 1047 .bdrv_close = curl_close, 1048 .bdrv_getlength = curl_getlength, 1049 1050 .bdrv_co_preadv = curl_co_preadv, 1051 1052 .bdrv_detach_aio_context = curl_detach_aio_context, 1053 .bdrv_attach_aio_context = curl_attach_aio_context, 1054 1055 .bdrv_refresh_filename = curl_refresh_filename, 1056 .strong_runtime_opts = curl_strong_runtime_opts, 1057 }; 1058 1059 static void curl_block_init(void) 1060 { 1061 bdrv_register(&bdrv_http); 1062 bdrv_register(&bdrv_https); 1063 bdrv_register(&bdrv_ftp); 1064 bdrv_register(&bdrv_ftps); 1065 } 1066 1067 block_init(curl_block_init); 1068