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-common.h" 25 #include "block/block_int.h" 26 #include <curl/curl.h> 27 28 // #define DEBUG 29 // #define DEBUG_VERBOSE 30 31 #ifdef DEBUG_CURL 32 #define DPRINTF(fmt, ...) do { printf(fmt, ## __VA_ARGS__); } while (0) 33 #else 34 #define DPRINTF(fmt, ...) do { } while (0) 35 #endif 36 37 #define PROTOCOLS (CURLPROTO_HTTP | CURLPROTO_HTTPS | \ 38 CURLPROTO_FTP | CURLPROTO_FTPS | \ 39 CURLPROTO_TFTP) 40 41 #define CURL_NUM_STATES 8 42 #define CURL_NUM_ACB 8 43 #define SECTOR_SIZE 512 44 #define READ_AHEAD_SIZE (256 * 1024) 45 46 #define FIND_RET_NONE 0 47 #define FIND_RET_OK 1 48 #define FIND_RET_WAIT 2 49 50 struct BDRVCURLState; 51 52 typedef struct CURLAIOCB { 53 BlockDriverAIOCB common; 54 QEMUBH *bh; 55 QEMUIOVector *qiov; 56 57 int64_t sector_num; 58 int nb_sectors; 59 60 size_t start; 61 size_t end; 62 } CURLAIOCB; 63 64 typedef struct CURLState 65 { 66 struct BDRVCURLState *s; 67 CURLAIOCB *acb[CURL_NUM_ACB]; 68 CURL *curl; 69 char *orig_buf; 70 size_t buf_start; 71 size_t buf_off; 72 size_t buf_len; 73 char range[128]; 74 char errmsg[CURL_ERROR_SIZE]; 75 char in_use; 76 } CURLState; 77 78 typedef struct BDRVCURLState { 79 CURLM *multi; 80 size_t len; 81 CURLState states[CURL_NUM_STATES]; 82 char *url; 83 size_t readahead_size; 84 bool accept_range; 85 } BDRVCURLState; 86 87 static void curl_clean_state(CURLState *s); 88 static void curl_multi_do(void *arg); 89 static int curl_aio_flush(void *opaque); 90 91 static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, 92 void *s, void *sp) 93 { 94 DPRINTF("CURL (AIO): Sock action %d on fd %d\n", action, fd); 95 switch (action) { 96 case CURL_POLL_IN: 97 qemu_aio_set_fd_handler(fd, curl_multi_do, NULL, curl_aio_flush, s); 98 break; 99 case CURL_POLL_OUT: 100 qemu_aio_set_fd_handler(fd, NULL, curl_multi_do, curl_aio_flush, s); 101 break; 102 case CURL_POLL_INOUT: 103 qemu_aio_set_fd_handler(fd, curl_multi_do, curl_multi_do, 104 curl_aio_flush, s); 105 break; 106 case CURL_POLL_REMOVE: 107 qemu_aio_set_fd_handler(fd, NULL, NULL, NULL, NULL); 108 break; 109 } 110 111 return 0; 112 } 113 114 static size_t curl_header_cb(void *ptr, size_t size, size_t nmemb, void *opaque) 115 { 116 BDRVCURLState *s = opaque; 117 size_t realsize = size * nmemb; 118 const char *accept_line = "Accept-Ranges: bytes"; 119 120 if (realsize >= strlen(accept_line) 121 && strncmp((char *)ptr, accept_line, strlen(accept_line)) == 0) { 122 s->accept_range = true; 123 } 124 125 return realsize; 126 } 127 128 static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque) 129 { 130 CURLState *s = ((CURLState*)opaque); 131 size_t realsize = size * nmemb; 132 int i; 133 134 DPRINTF("CURL: Just reading %zd bytes\n", realsize); 135 136 if (!s || !s->orig_buf) 137 goto read_end; 138 139 memcpy(s->orig_buf + s->buf_off, ptr, realsize); 140 s->buf_off += realsize; 141 142 for(i=0; i<CURL_NUM_ACB; i++) { 143 CURLAIOCB *acb = s->acb[i]; 144 145 if (!acb) 146 continue; 147 148 if ((s->buf_off >= acb->end)) { 149 qemu_iovec_from_buf(acb->qiov, 0, s->orig_buf + acb->start, 150 acb->end - acb->start); 151 acb->common.cb(acb->common.opaque, 0); 152 qemu_aio_release(acb); 153 s->acb[i] = NULL; 154 } 155 } 156 157 read_end: 158 return realsize; 159 } 160 161 static int curl_find_buf(BDRVCURLState *s, size_t start, size_t len, 162 CURLAIOCB *acb) 163 { 164 int i; 165 size_t end = start + len; 166 167 for (i=0; i<CURL_NUM_STATES; i++) { 168 CURLState *state = &s->states[i]; 169 size_t buf_end = (state->buf_start + state->buf_off); 170 size_t buf_fend = (state->buf_start + state->buf_len); 171 172 if (!state->orig_buf) 173 continue; 174 if (!state->buf_off) 175 continue; 176 177 // Does the existing buffer cover our section? 178 if ((start >= state->buf_start) && 179 (start <= buf_end) && 180 (end >= state->buf_start) && 181 (end <= buf_end)) 182 { 183 char *buf = state->orig_buf + (start - state->buf_start); 184 185 qemu_iovec_from_buf(acb->qiov, 0, buf, len); 186 acb->common.cb(acb->common.opaque, 0); 187 188 return FIND_RET_OK; 189 } 190 191 // Wait for unfinished chunks 192 if ((start >= state->buf_start) && 193 (start <= buf_fend) && 194 (end >= state->buf_start) && 195 (end <= buf_fend)) 196 { 197 int j; 198 199 acb->start = start - state->buf_start; 200 acb->end = acb->start + len; 201 202 for (j=0; j<CURL_NUM_ACB; j++) { 203 if (!state->acb[j]) { 204 state->acb[j] = acb; 205 return FIND_RET_WAIT; 206 } 207 } 208 } 209 } 210 211 return FIND_RET_NONE; 212 } 213 214 static void curl_multi_do(void *arg) 215 { 216 BDRVCURLState *s = (BDRVCURLState *)arg; 217 int running; 218 int r; 219 int msgs_in_queue; 220 221 if (!s->multi) 222 return; 223 224 do { 225 r = curl_multi_socket_all(s->multi, &running); 226 } while(r == CURLM_CALL_MULTI_PERFORM); 227 228 /* Try to find done transfers, so we can free the easy 229 * handle again. */ 230 do { 231 CURLMsg *msg; 232 msg = curl_multi_info_read(s->multi, &msgs_in_queue); 233 234 if (!msg) 235 break; 236 if (msg->msg == CURLMSG_NONE) 237 break; 238 239 switch (msg->msg) { 240 case CURLMSG_DONE: 241 { 242 CURLState *state = NULL; 243 curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, (char**)&state); 244 245 /* ACBs for successful messages get completed in curl_read_cb */ 246 if (msg->data.result != CURLE_OK) { 247 int i; 248 for (i = 0; i < CURL_NUM_ACB; i++) { 249 CURLAIOCB *acb = state->acb[i]; 250 251 if (acb == NULL) { 252 continue; 253 } 254 255 acb->common.cb(acb->common.opaque, -EIO); 256 qemu_aio_release(acb); 257 state->acb[i] = NULL; 258 } 259 } 260 261 curl_clean_state(state); 262 break; 263 } 264 default: 265 msgs_in_queue = 0; 266 break; 267 } 268 } while(msgs_in_queue); 269 } 270 271 static CURLState *curl_init_state(BDRVCURLState *s) 272 { 273 CURLState *state = NULL; 274 int i, j; 275 276 do { 277 for (i=0; i<CURL_NUM_STATES; i++) { 278 for (j=0; j<CURL_NUM_ACB; j++) 279 if (s->states[i].acb[j]) 280 continue; 281 if (s->states[i].in_use) 282 continue; 283 284 state = &s->states[i]; 285 state->in_use = 1; 286 break; 287 } 288 if (!state) { 289 g_usleep(100); 290 curl_multi_do(s); 291 } 292 } while(!state); 293 294 if (state->curl) 295 goto has_curl; 296 297 state->curl = curl_easy_init(); 298 if (!state->curl) 299 return NULL; 300 curl_easy_setopt(state->curl, CURLOPT_URL, s->url); 301 curl_easy_setopt(state->curl, CURLOPT_TIMEOUT, 5); 302 curl_easy_setopt(state->curl, CURLOPT_WRITEFUNCTION, (void *)curl_read_cb); 303 curl_easy_setopt(state->curl, CURLOPT_WRITEDATA, (void *)state); 304 curl_easy_setopt(state->curl, CURLOPT_PRIVATE, (void *)state); 305 curl_easy_setopt(state->curl, CURLOPT_AUTOREFERER, 1); 306 curl_easy_setopt(state->curl, CURLOPT_FOLLOWLOCATION, 1); 307 curl_easy_setopt(state->curl, CURLOPT_NOSIGNAL, 1); 308 curl_easy_setopt(state->curl, CURLOPT_ERRORBUFFER, state->errmsg); 309 curl_easy_setopt(state->curl, CURLOPT_FAILONERROR, 1); 310 311 /* Restrict supported protocols to avoid security issues in the more 312 * obscure protocols. For example, do not allow POP3/SMTP/IMAP see 313 * CVE-2013-0249. 314 * 315 * Restricting protocols is only supported from 7.19.4 upwards. 316 */ 317 #if LIBCURL_VERSION_NUM >= 0x071304 318 curl_easy_setopt(state->curl, CURLOPT_PROTOCOLS, PROTOCOLS); 319 curl_easy_setopt(state->curl, CURLOPT_REDIR_PROTOCOLS, PROTOCOLS); 320 #endif 321 322 #ifdef DEBUG_VERBOSE 323 curl_easy_setopt(state->curl, CURLOPT_VERBOSE, 1); 324 #endif 325 326 has_curl: 327 328 state->s = s; 329 330 return state; 331 } 332 333 static void curl_clean_state(CURLState *s) 334 { 335 if (s->s->multi) 336 curl_multi_remove_handle(s->s->multi, s->curl); 337 s->in_use = 0; 338 } 339 340 static void curl_parse_filename(const char *filename, QDict *options, 341 Error **errp) 342 { 343 344 #define RA_OPTSTR ":readahead=" 345 char *file; 346 char *ra; 347 const char *ra_val; 348 int parse_state = 0; 349 350 file = g_strdup(filename); 351 352 /* Parse a trailing ":readahead=#:" param, if present. */ 353 ra = file + strlen(file) - 1; 354 while (ra >= file) { 355 if (parse_state == 0) { 356 if (*ra == ':') { 357 parse_state++; 358 } else { 359 break; 360 } 361 } else if (parse_state == 1) { 362 if (*ra > '9' || *ra < '0') { 363 char *opt_start = ra - strlen(RA_OPTSTR) + 1; 364 if (opt_start > file && 365 strncmp(opt_start, RA_OPTSTR, strlen(RA_OPTSTR)) == 0) { 366 ra_val = ra + 1; 367 ra -= strlen(RA_OPTSTR) - 1; 368 *ra = '\0'; 369 qdict_put(options, "readahead", qstring_from_str(ra_val)); 370 } 371 break; 372 } 373 } 374 ra--; 375 } 376 377 qdict_put(options, "url", qstring_from_str(file)); 378 379 g_free(file); 380 } 381 382 static QemuOptsList runtime_opts = { 383 .name = "curl", 384 .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head), 385 .desc = { 386 { 387 .name = "url", 388 .type = QEMU_OPT_STRING, 389 .help = "URL to open", 390 }, 391 { 392 .name = "readahead", 393 .type = QEMU_OPT_SIZE, 394 .help = "Readahead size", 395 }, 396 { /* end of list */ } 397 }, 398 }; 399 400 static int curl_open(BlockDriverState *bs, QDict *options, int flags) 401 { 402 BDRVCURLState *s = bs->opaque; 403 CURLState *state = NULL; 404 QemuOpts *opts; 405 Error *local_err = NULL; 406 const char *file; 407 double d; 408 409 static int inited = 0; 410 411 if (flags & BDRV_O_RDWR) { 412 qerror_report(ERROR_CLASS_GENERIC_ERROR, 413 "curl block device does not support writes"); 414 return -EROFS; 415 } 416 417 opts = qemu_opts_create_nofail(&runtime_opts); 418 qemu_opts_absorb_qdict(opts, options, &local_err); 419 if (error_is_set(&local_err)) { 420 qerror_report_err(local_err); 421 error_free(local_err); 422 goto out_noclean; 423 } 424 425 s->readahead_size = qemu_opt_get_size(opts, "readahead", READ_AHEAD_SIZE); 426 if ((s->readahead_size & 0x1ff) != 0) { 427 fprintf(stderr, "HTTP_READAHEAD_SIZE %zd is not a multiple of 512\n", 428 s->readahead_size); 429 goto out_noclean; 430 } 431 432 file = qemu_opt_get(opts, "url"); 433 if (file == NULL) { 434 qerror_report(ERROR_CLASS_GENERIC_ERROR, "curl block driver requires " 435 "an 'url' option"); 436 goto out_noclean; 437 } 438 439 if (!inited) { 440 curl_global_init(CURL_GLOBAL_ALL); 441 inited = 1; 442 } 443 444 DPRINTF("CURL: Opening %s\n", file); 445 s->url = g_strdup(file); 446 state = curl_init_state(s); 447 if (!state) 448 goto out_noclean; 449 450 // Get file size 451 452 s->accept_range = false; 453 curl_easy_setopt(state->curl, CURLOPT_NOBODY, 1); 454 curl_easy_setopt(state->curl, CURLOPT_HEADERFUNCTION, 455 curl_header_cb); 456 curl_easy_setopt(state->curl, CURLOPT_HEADERDATA, s); 457 if (curl_easy_perform(state->curl)) 458 goto out; 459 curl_easy_getinfo(state->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d); 460 if (d) 461 s->len = (size_t)d; 462 else if(!s->len) 463 goto out; 464 if ((!strncasecmp(s->url, "http://", strlen("http://")) 465 || !strncasecmp(s->url, "https://", strlen("https://"))) 466 && !s->accept_range) { 467 pstrcpy(state->errmsg, CURL_ERROR_SIZE, 468 "Server does not support 'range' (byte ranges)."); 469 goto out; 470 } 471 DPRINTF("CURL: Size = %zd\n", s->len); 472 473 curl_clean_state(state); 474 curl_easy_cleanup(state->curl); 475 state->curl = NULL; 476 477 // Now we know the file exists and its size, so let's 478 // initialize the multi interface! 479 480 s->multi = curl_multi_init(); 481 curl_multi_setopt(s->multi, CURLMOPT_SOCKETDATA, s); 482 curl_multi_setopt(s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb); 483 curl_multi_do(s); 484 485 qemu_opts_del(opts); 486 return 0; 487 488 out: 489 fprintf(stderr, "CURL: Error opening file: %s\n", state->errmsg); 490 curl_easy_cleanup(state->curl); 491 state->curl = NULL; 492 out_noclean: 493 g_free(s->url); 494 qemu_opts_del(opts); 495 return -EINVAL; 496 } 497 498 static int curl_aio_flush(void *opaque) 499 { 500 BDRVCURLState *s = opaque; 501 int i, j; 502 503 for (i=0; i < CURL_NUM_STATES; i++) { 504 for(j=0; j < CURL_NUM_ACB; j++) { 505 if (s->states[i].acb[j]) { 506 return 1; 507 } 508 } 509 } 510 return 0; 511 } 512 513 static void curl_aio_cancel(BlockDriverAIOCB *blockacb) 514 { 515 // Do we have to implement canceling? Seems to work without... 516 } 517 518 static const AIOCBInfo curl_aiocb_info = { 519 .aiocb_size = sizeof(CURLAIOCB), 520 .cancel = curl_aio_cancel, 521 }; 522 523 524 static void curl_readv_bh_cb(void *p) 525 { 526 CURLState *state; 527 528 CURLAIOCB *acb = p; 529 BDRVCURLState *s = acb->common.bs->opaque; 530 531 qemu_bh_delete(acb->bh); 532 acb->bh = NULL; 533 534 size_t start = acb->sector_num * SECTOR_SIZE; 535 size_t end; 536 537 // In case we have the requested data already (e.g. read-ahead), 538 // we can just call the callback and be done. 539 switch (curl_find_buf(s, start, acb->nb_sectors * SECTOR_SIZE, acb)) { 540 case FIND_RET_OK: 541 qemu_aio_release(acb); 542 // fall through 543 case FIND_RET_WAIT: 544 return; 545 default: 546 break; 547 } 548 549 // No cache found, so let's start a new request 550 state = curl_init_state(s); 551 if (!state) { 552 acb->common.cb(acb->common.opaque, -EIO); 553 qemu_aio_release(acb); 554 return; 555 } 556 557 acb->start = 0; 558 acb->end = (acb->nb_sectors * SECTOR_SIZE); 559 560 state->buf_off = 0; 561 if (state->orig_buf) 562 g_free(state->orig_buf); 563 state->buf_start = start; 564 state->buf_len = acb->end + s->readahead_size; 565 end = MIN(start + state->buf_len, s->len) - 1; 566 state->orig_buf = g_malloc(state->buf_len); 567 state->acb[0] = acb; 568 569 snprintf(state->range, 127, "%zd-%zd", start, end); 570 DPRINTF("CURL (AIO): Reading %d at %zd (%s)\n", 571 (acb->nb_sectors * SECTOR_SIZE), start, state->range); 572 curl_easy_setopt(state->curl, CURLOPT_RANGE, state->range); 573 574 curl_multi_add_handle(s->multi, state->curl); 575 curl_multi_do(s); 576 577 } 578 579 static BlockDriverAIOCB *curl_aio_readv(BlockDriverState *bs, 580 int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, 581 BlockDriverCompletionFunc *cb, void *opaque) 582 { 583 CURLAIOCB *acb; 584 585 acb = qemu_aio_get(&curl_aiocb_info, bs, cb, opaque); 586 587 acb->qiov = qiov; 588 acb->sector_num = sector_num; 589 acb->nb_sectors = nb_sectors; 590 591 acb->bh = qemu_bh_new(curl_readv_bh_cb, acb); 592 593 if (!acb->bh) { 594 DPRINTF("CURL: qemu_bh_new failed\n"); 595 return NULL; 596 } 597 598 qemu_bh_schedule(acb->bh); 599 return &acb->common; 600 } 601 602 static void curl_close(BlockDriverState *bs) 603 { 604 BDRVCURLState *s = bs->opaque; 605 int i; 606 607 DPRINTF("CURL: Close\n"); 608 for (i=0; i<CURL_NUM_STATES; i++) { 609 if (s->states[i].in_use) 610 curl_clean_state(&s->states[i]); 611 if (s->states[i].curl) { 612 curl_easy_cleanup(s->states[i].curl); 613 s->states[i].curl = NULL; 614 } 615 if (s->states[i].orig_buf) { 616 g_free(s->states[i].orig_buf); 617 s->states[i].orig_buf = NULL; 618 } 619 } 620 if (s->multi) 621 curl_multi_cleanup(s->multi); 622 g_free(s->url); 623 } 624 625 static int64_t curl_getlength(BlockDriverState *bs) 626 { 627 BDRVCURLState *s = bs->opaque; 628 return s->len; 629 } 630 631 static BlockDriver bdrv_http = { 632 .format_name = "http", 633 .protocol_name = "http", 634 635 .instance_size = sizeof(BDRVCURLState), 636 .bdrv_parse_filename = curl_parse_filename, 637 .bdrv_file_open = curl_open, 638 .bdrv_close = curl_close, 639 .bdrv_getlength = curl_getlength, 640 641 .bdrv_aio_readv = curl_aio_readv, 642 }; 643 644 static BlockDriver bdrv_https = { 645 .format_name = "https", 646 .protocol_name = "https", 647 648 .instance_size = sizeof(BDRVCURLState), 649 .bdrv_parse_filename = curl_parse_filename, 650 .bdrv_file_open = curl_open, 651 .bdrv_close = curl_close, 652 .bdrv_getlength = curl_getlength, 653 654 .bdrv_aio_readv = curl_aio_readv, 655 }; 656 657 static BlockDriver bdrv_ftp = { 658 .format_name = "ftp", 659 .protocol_name = "ftp", 660 661 .instance_size = sizeof(BDRVCURLState), 662 .bdrv_parse_filename = curl_parse_filename, 663 .bdrv_file_open = curl_open, 664 .bdrv_close = curl_close, 665 .bdrv_getlength = curl_getlength, 666 667 .bdrv_aio_readv = curl_aio_readv, 668 }; 669 670 static BlockDriver bdrv_ftps = { 671 .format_name = "ftps", 672 .protocol_name = "ftps", 673 674 .instance_size = sizeof(BDRVCURLState), 675 .bdrv_parse_filename = curl_parse_filename, 676 .bdrv_file_open = curl_open, 677 .bdrv_close = curl_close, 678 .bdrv_getlength = curl_getlength, 679 680 .bdrv_aio_readv = curl_aio_readv, 681 }; 682 683 static BlockDriver bdrv_tftp = { 684 .format_name = "tftp", 685 .protocol_name = "tftp", 686 687 .instance_size = sizeof(BDRVCURLState), 688 .bdrv_parse_filename = curl_parse_filename, 689 .bdrv_file_open = curl_open, 690 .bdrv_close = curl_close, 691 .bdrv_getlength = curl_getlength, 692 693 .bdrv_aio_readv = curl_aio_readv, 694 }; 695 696 static void curl_block_init(void) 697 { 698 bdrv_register(&bdrv_http); 699 bdrv_register(&bdrv_https); 700 bdrv_register(&bdrv_ftp); 701 bdrv_register(&bdrv_ftps); 702 bdrv_register(&bdrv_tftp); 703 } 704 705 block_init(curl_block_init); 706