1 /* $OpenBSD: bioctl.c,v 1.139 2016/09/21 17:50:05 jsing Exp $ */ 2 3 /* 4 * Copyright (c) 2004, 2005 Marco Peereboom 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR 20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 */ 29 30 #include <sys/param.h> /* NODEV */ 31 #include <sys/ioctl.h> 32 #include <sys/dkio.h> 33 #include <sys/stat.h> 34 #include <dev/softraidvar.h> 35 #include <dev/biovar.h> 36 37 #include <errno.h> 38 #include <err.h> 39 #include <fcntl.h> 40 #include <util.h> 41 #include <ctype.h> 42 #include <stdio.h> 43 #include <stdlib.h> 44 #include <string.h> 45 #include <time.h> 46 #include <unistd.h> 47 #include <limits.h> 48 #include <vis.h> 49 #include <readpassphrase.h> 50 51 struct locator { 52 int channel; 53 int target; 54 int lun; 55 }; 56 57 struct timing { 58 int interval; 59 int start; 60 }; 61 62 void usage(void); 63 const char *str2locator(const char *, struct locator *); 64 const char *str2patrol(const char *, struct timing *); 65 void bio_status(struct bio_status *); 66 int bio_parse_devlist(char *, dev_t *); 67 void bio_kdf_derive(struct sr_crypto_kdfinfo *, 68 struct sr_crypto_pbkdf *, char *, int); 69 void bio_kdf_generate(struct sr_crypto_kdfinfo *); 70 int bcrypt_pbkdf_autorounds(void); 71 void derive_key(u_int32_t, int, u_int8_t *, size_t, 72 u_int8_t *, size_t, char *, int); 73 74 void bio_inq(char *); 75 void bio_alarm(char *); 76 int bio_getvolbyname(char *); 77 void bio_setstate(char *, int, char *); 78 void bio_setblink(char *, char *, int); 79 void bio_blink(char *, int, int); 80 void bio_createraid(u_int16_t, char *, char *); 81 void bio_deleteraid(char *); 82 void bio_changepass(char *); 83 u_int32_t bio_createflags(char *); 84 char *bio_vis(char *); 85 void bio_diskinq(char *); 86 void bio_patrol(char *); 87 88 int devh = -1; 89 int human; 90 int verbose; 91 u_int32_t cflags = 0; 92 int rflag = 0; 93 char *password; 94 95 void *bio_cookie; 96 97 int rpp_flag = RPP_REQUIRE_TTY; 98 99 int 100 main(int argc, char *argv[]) 101 { 102 struct bio_locate bl; 103 extern char *optarg; 104 u_int64_t func = 0; 105 char *devicename = NULL; 106 char *realname = NULL, *al_arg = NULL; 107 char *bl_arg = NULL, *dev_list = NULL; 108 char *key_disk = NULL; 109 const char *errstr; 110 int ch, blink = 0, changepass = 0, diskinq = 0; 111 int ss_func = 0; 112 u_int16_t cr_level = 0; 113 int biodev = 0; 114 115 if (argc < 2) 116 usage(); 117 118 while ((ch = getopt(argc, argv, "a:b:C:c:dH:hik:l:O:Pp:qr:R:st:u:v")) != 119 -1) { 120 switch (ch) { 121 case 'a': /* alarm */ 122 func |= BIOC_ALARM; 123 al_arg = optarg; 124 break; 125 case 'b': /* blink */ 126 func |= BIOC_BLINK; 127 blink = BIOC_SBBLINK; 128 bl_arg = optarg; 129 break; 130 case 'C': /* creation flags */ 131 cflags = bio_createflags(optarg); 132 break; 133 case 'c': /* create */ 134 func |= BIOC_CREATERAID; 135 if (isdigit((unsigned char)*optarg)) { 136 cr_level = strtonum(optarg, 0, 10, &errstr); 137 if (errstr != NULL) 138 errx(1, "Invalid RAID level"); 139 } else 140 cr_level = *optarg; 141 break; 142 case 'd': 143 /* delete volume */ 144 func |= BIOC_DELETERAID; 145 break; 146 case 'u': /* unblink */ 147 func |= BIOC_BLINK; 148 blink = BIOC_SBUNBLINK; 149 bl_arg = optarg; 150 break; 151 case 'H': /* set hotspare */ 152 func |= BIOC_SETSTATE; 153 ss_func = BIOC_SSHOTSPARE; 154 al_arg = optarg; 155 break; 156 case 'h': 157 human = 1; 158 break; 159 case 'i': /* inquiry */ 160 func |= BIOC_INQ; 161 break; 162 case 'k': /* Key disk. */ 163 key_disk = optarg; 164 break; 165 case 'l': /* device list */ 166 func |= BIOC_DEVLIST; 167 dev_list = optarg; 168 break; 169 case 'P': 170 /* Change passphrase. */ 171 changepass = 1; 172 break; 173 case 'p': 174 password = optarg; 175 break; 176 case 'r': 177 if (strcmp(optarg, "auto") == 0) { 178 rflag = -1; 179 break; 180 } 181 rflag = strtonum(optarg, 4, 1<<30, &errstr); 182 if (errstr != NULL) 183 errx(1, "number of KDF rounds is %s: %s", 184 errstr, optarg); 185 break; 186 case 'O': 187 /* set a chunk to offline */ 188 func |= BIOC_SETSTATE; 189 ss_func = BIOC_SSOFFLINE; 190 al_arg = optarg; 191 break; 192 case 'R': 193 /* rebuild to provided chunk/CTL */ 194 func |= BIOC_SETSTATE; 195 ss_func = BIOC_SSREBUILD; 196 al_arg = optarg; 197 break; 198 case 's': 199 rpp_flag = RPP_STDIN; 200 break; 201 case 't': /* patrol */ 202 func |= BIOC_PATROL; 203 al_arg = optarg; 204 break; 205 case 'v': 206 verbose = 1; 207 break; 208 case 'q': 209 diskinq = 1; 210 break; 211 default: 212 usage(); 213 /* NOTREACHED */ 214 } 215 } 216 argc -= optind; 217 argv += optind; 218 219 if (argc != 1 || (changepass && func != 0)) 220 usage(); 221 222 if (func == 0) 223 func |= BIOC_INQ; 224 225 devicename = argv[0]; 226 if (devicename == NULL) 227 errx(1, "need device"); 228 229 devh = opendev(devicename, O_RDWR, OPENDEV_PART, &realname); 230 if (devh == -1) { 231 devh = open("/dev/bio", O_RDWR); 232 if (devh == -1) 233 err(1, "Can't open %s", "/dev/bio"); 234 235 bl.bl_name = devicename; 236 if (ioctl(devh, BIOCLOCATE, &bl)) 237 errx(1, "Can't locate %s device via %s", 238 bl.bl_name, "/dev/bio"); 239 240 bio_status(&bl.bl_bio.bio_status); 241 242 bio_cookie = bl.bl_bio.bio_cookie; 243 biodev = 1; 244 devicename = NULL; 245 } 246 247 if (diskinq) { 248 bio_diskinq(devicename); 249 } else if (changepass && !biodev) { 250 bio_changepass(devicename); 251 } else if (func & BIOC_INQ) { 252 bio_inq(devicename); 253 } else if (func == BIOC_ALARM) { 254 bio_alarm(al_arg); 255 } else if (func == BIOC_BLINK) { 256 bio_setblink(devicename, bl_arg, blink); 257 } else if (func == BIOC_PATROL) { 258 bio_patrol(al_arg); 259 } else if (func == BIOC_SETSTATE) { 260 bio_setstate(al_arg, ss_func, argv[0]); 261 } else if (func == BIOC_DELETERAID && !biodev) { 262 bio_deleteraid(devicename); 263 } else if (func & BIOC_CREATERAID || func & BIOC_DEVLIST) { 264 if (!(func & BIOC_CREATERAID)) 265 errx(1, "need -c parameter"); 266 if (!(func & BIOC_DEVLIST)) 267 errx(1, "need -l parameter"); 268 if (!biodev) 269 errx(1, "must use bio device"); 270 bio_createraid(cr_level, dev_list, key_disk); 271 } 272 273 return (0); 274 } 275 276 void 277 usage(void) 278 { 279 extern char *__progname; 280 281 fprintf(stderr, 282 "usage: %s [-hiqv] [-a alarm-function] " 283 "[-b channel:target[.lun]]\n" 284 "\t[-H channel:target[.lun]] " 285 "[-R device | channel:target[.lun]]\n" 286 "\t[-t patrol-function] " 287 "[-u channel:target[.lun]] " 288 "device\n" 289 " %s [-dhiPqsv] " 290 "[-C flag[,flag,...]] [-c raidlevel] [-k keydisk]\n" 291 "\t[-l special[,special,...]] " 292 "[-O device | channel:target[.lun]]\n" 293 "\t[-p passfile] [-R device | channel:target[.lun]]\n" 294 "\t[-r rounds] " 295 "device\n", __progname, __progname); 296 297 exit(1); 298 } 299 300 const char * 301 str2locator(const char *string, struct locator *location) 302 { 303 const char *errstr; 304 char parse[80], *targ, *lun; 305 306 strlcpy(parse, string, sizeof parse); 307 targ = strchr(parse, ':'); 308 if (targ == NULL) 309 return ("target not specified"); 310 *targ++ = '\0'; 311 312 lun = strchr(targ, '.'); 313 if (lun != NULL) { 314 *lun++ = '\0'; 315 location->lun = strtonum(lun, 0, 256, &errstr); 316 if (errstr) 317 return (errstr); 318 } else 319 location->lun = 0; 320 321 location->target = strtonum(targ, 0, 256, &errstr); 322 if (errstr) 323 return (errstr); 324 location->channel = strtonum(parse, 0, 256, &errstr); 325 if (errstr) 326 return (errstr); 327 return (NULL); 328 } 329 330 const char * 331 str2patrol(const char *string, struct timing *timing) 332 { 333 const char *errstr; 334 char parse[80], *interval = NULL, *start = NULL; 335 336 timing->interval = 0; 337 timing->start = 0; 338 339 strlcpy(parse, string, sizeof parse); 340 341 interval = strchr(parse, '.'); 342 if (interval != NULL) { 343 *interval++ = '\0'; 344 start = strchr(interval, '.'); 345 if (start != NULL) 346 *start++ = '\0'; 347 } 348 if (interval != NULL) { 349 /* -1 == continuously */ 350 timing->interval = strtonum(interval, -1, INT_MAX, &errstr); 351 if (errstr) 352 return (errstr); 353 } 354 if (start != NULL) { 355 timing->start = strtonum(start, 0, INT_MAX, &errstr); 356 if (errstr) 357 return (errstr); 358 } 359 360 return (NULL); 361 } 362 363 void 364 bio_status(struct bio_status *bs) 365 { 366 extern char *__progname; 367 char *prefix; 368 int i; 369 370 if (strlen(bs->bs_controller)) 371 prefix = bs->bs_controller; 372 else 373 prefix = __progname; 374 375 for (i = 0; i < bs->bs_msg_count; i++) 376 printf("%s: %s\n", prefix, bs->bs_msgs[i].bm_msg); 377 378 if (bs->bs_status == BIO_STATUS_ERROR) { 379 if (bs->bs_msg_count == 0) 380 errx(1, "unknown error"); 381 else 382 exit(1); 383 } 384 } 385 386 void 387 bio_inq(char *name) 388 { 389 char *status, *cache; 390 char size[64], scsiname[16], volname[32]; 391 char percent[20], seconds[20]; 392 int i, d, volheader, hotspare, unused; 393 char encname[16], serial[32]; 394 struct bioc_inq bi; 395 struct bioc_vol bv; 396 struct bioc_disk bd; 397 398 memset(&bi, 0, sizeof(bi)); 399 400 bi.bi_bio.bio_cookie = bio_cookie; 401 402 if (ioctl(devh, BIOCINQ, &bi)) { 403 if (errno == ENOTTY) 404 bio_diskinq(name); 405 else 406 err(1, "BIOCINQ"); 407 return; 408 } 409 410 bio_status(&bi.bi_bio.bio_status); 411 412 volheader = 0; 413 for (i = 0; i < bi.bi_novol; i++) { 414 memset(&bv, 0, sizeof(bv)); 415 bv.bv_bio.bio_cookie = bio_cookie; 416 bv.bv_volid = i; 417 bv.bv_percent = -1; 418 bv.bv_seconds = 0; 419 420 if (ioctl(devh, BIOCVOL, &bv)) 421 err(1, "BIOCVOL"); 422 423 bio_status(&bv.bv_bio.bio_status); 424 425 if (name && strcmp(name, bv.bv_dev) != 0) 426 continue; 427 428 if (!volheader) { 429 volheader = 1; 430 printf("%-11s %-10s %14s %-8s\n", 431 "Volume", "Status", "Size", "Device"); 432 } 433 434 percent[0] = '\0'; 435 seconds[0] = '\0'; 436 if (bv.bv_percent != -1) 437 snprintf(percent, sizeof percent, 438 " %d%% done", bv.bv_percent); 439 if (bv.bv_seconds) 440 snprintf(seconds, sizeof seconds, 441 " %u seconds", bv.bv_seconds); 442 switch (bv.bv_status) { 443 case BIOC_SVONLINE: 444 status = BIOC_SVONLINE_S; 445 break; 446 case BIOC_SVOFFLINE: 447 status = BIOC_SVOFFLINE_S; 448 break; 449 case BIOC_SVDEGRADED: 450 status = BIOC_SVDEGRADED_S; 451 break; 452 case BIOC_SVBUILDING: 453 status = BIOC_SVBUILDING_S; 454 break; 455 case BIOC_SVREBUILD: 456 status = BIOC_SVREBUILD_S; 457 break; 458 case BIOC_SVSCRUB: 459 status = BIOC_SVSCRUB_S; 460 break; 461 case BIOC_SVINVALID: 462 default: 463 status = BIOC_SVINVALID_S; 464 } 465 switch (bv.bv_cache) { 466 case BIOC_CVWRITEBACK: 467 cache = BIOC_CVWRITEBACK_S; 468 break; 469 case BIOC_CVWRITETHROUGH: 470 cache = BIOC_CVWRITETHROUGH_S; 471 break; 472 case BIOC_CVUNKNOWN: 473 default: 474 cache = BIOC_CVUNKNOWN_S; 475 } 476 477 snprintf(volname, sizeof volname, "%s %u", 478 bi.bi_dev, bv.bv_volid); 479 480 unused = 0; 481 hotspare = 0; 482 if (bv.bv_level == -1 && bv.bv_nodisk == 1) 483 hotspare = 1; 484 else if (bv.bv_level == -2 && bv.bv_nodisk == 1) 485 unused = 1; 486 else { 487 if (human) 488 fmt_scaled(bv.bv_size, size); 489 else 490 snprintf(size, sizeof size, "%14llu", 491 bv.bv_size); 492 switch (bv.bv_level) { 493 case 'C': 494 printf("%11s %-10s %14s %-7s CRYPTO%s%s\n", 495 volname, status, size, bv.bv_dev, 496 percent, seconds); 497 break; 498 case 'c': 499 printf("%11s %-10s %14s %-7s CONCAT%s%s\n", 500 volname, status, size, bv.bv_dev, 501 percent, seconds); 502 break; 503 default: 504 printf("%11s %-10s %14s %-7s RAID%u%s%s %s\n", 505 volname, status, size, bv.bv_dev, 506 bv.bv_level, percent, seconds, cache); 507 break; 508 } 509 510 } 511 512 for (d = 0; d < bv.bv_nodisk; d++) { 513 memset(&bd, 0, sizeof(bd)); 514 bd.bd_bio.bio_cookie = bio_cookie; 515 bd.bd_diskid = d; 516 bd.bd_volid = i; 517 bd.bd_patrol.bdp_percent = -1; 518 bd.bd_patrol.bdp_seconds = 0; 519 520 if (ioctl(devh, BIOCDISK, &bd)) 521 err(1, "BIOCDISK"); 522 523 bio_status(&bd.bd_bio.bio_status); 524 525 switch (bd.bd_status) { 526 case BIOC_SDONLINE: 527 status = BIOC_SDONLINE_S; 528 break; 529 case BIOC_SDOFFLINE: 530 status = BIOC_SDOFFLINE_S; 531 break; 532 case BIOC_SDFAILED: 533 status = BIOC_SDFAILED_S; 534 break; 535 case BIOC_SDREBUILD: 536 status = BIOC_SDREBUILD_S; 537 break; 538 case BIOC_SDHOTSPARE: 539 status = BIOC_SDHOTSPARE_S; 540 break; 541 case BIOC_SDUNUSED: 542 status = BIOC_SDUNUSED_S; 543 break; 544 case BIOC_SDSCRUB: 545 status = BIOC_SDSCRUB_S; 546 break; 547 case BIOC_SDINVALID: 548 default: 549 status = BIOC_SDINVALID_S; 550 } 551 552 if (hotspare || unused) 553 ; /* use volname from parent volume */ 554 else 555 snprintf(volname, sizeof volname, " %3u", 556 bd.bd_diskid); 557 558 if (bv.bv_level == 'C' && bd.bd_size == 0) 559 snprintf(size, sizeof size, "%14s", "key disk"); 560 else if (human) 561 fmt_scaled(bd.bd_size, size); 562 else 563 snprintf(size, sizeof size, "%14llu", 564 bd.bd_size); 565 snprintf(scsiname, sizeof scsiname, 566 "%u:%u.%u", 567 bd.bd_channel, bd.bd_target, bd.bd_lun); 568 if (bd.bd_procdev[0]) 569 strlcpy(encname, bd.bd_procdev, sizeof encname); 570 else 571 strlcpy(encname, "noencl", sizeof encname); 572 if (bd.bd_serial[0]) 573 strlcpy(serial, bd.bd_serial, sizeof serial); 574 else 575 strlcpy(serial, "unknown serial", sizeof serial); 576 577 percent[0] = '\0'; 578 seconds[0] = '\0'; 579 if (bd.bd_patrol.bdp_percent != -1) 580 snprintf(percent, sizeof percent, 581 " patrol %d%% done", bd.bd_patrol.bdp_percent); 582 if (bd.bd_patrol.bdp_seconds) 583 snprintf(seconds, sizeof seconds, 584 " %u seconds", bd.bd_patrol.bdp_seconds); 585 586 printf("%11s %-10s %14s %-7s %-6s <%s>\n", 587 volname, status, size, scsiname, encname, 588 bd.bd_vendor); 589 if (verbose) 590 printf("%11s %-10s %14s %-7s %-6s '%s'%s%s\n", 591 "", "", "", "", "", serial, percent, seconds); 592 } 593 } 594 } 595 596 void 597 bio_alarm(char *arg) 598 { 599 struct bioc_alarm ba; 600 601 memset(&ba, 0, sizeof(ba)); 602 ba.ba_bio.bio_cookie = bio_cookie; 603 604 switch (arg[0]) { 605 case 'q': /* silence alarm */ 606 /* FALLTHROUGH */ 607 case 's': 608 ba.ba_opcode = BIOC_SASILENCE; 609 break; 610 611 case 'e': /* enable alarm */ 612 ba.ba_opcode = BIOC_SAENABLE; 613 break; 614 615 case 'd': /* disable alarm */ 616 ba.ba_opcode = BIOC_SADISABLE; 617 break; 618 619 case 't': /* test alarm */ 620 ba.ba_opcode = BIOC_SATEST; 621 break; 622 623 case 'g': /* get alarm state */ 624 ba.ba_opcode = BIOC_GASTATUS; 625 break; 626 627 default: 628 errx(1, "invalid alarm function: %s", arg); 629 } 630 631 if (ioctl(devh, BIOCALARM, &ba)) 632 err(1, "BIOCALARM"); 633 634 bio_status(&ba.ba_bio.bio_status); 635 636 if (arg[0] == 'g') 637 printf("alarm is currently %s\n", 638 ba.ba_status ? "enabled" : "disabled"); 639 } 640 641 int 642 bio_getvolbyname(char *name) 643 { 644 int id = -1, i; 645 struct bioc_inq bi; 646 struct bioc_vol bv; 647 648 memset(&bi, 0, sizeof(bi)); 649 bi.bi_bio.bio_cookie = bio_cookie; 650 if (ioctl(devh, BIOCINQ, &bi)) 651 err(1, "BIOCINQ"); 652 653 bio_status(&bi.bi_bio.bio_status); 654 655 for (i = 0; i < bi.bi_novol; i++) { 656 memset(&bv, 0, sizeof(bv)); 657 bv.bv_bio.bio_cookie = bio_cookie; 658 bv.bv_volid = i; 659 if (ioctl(devh, BIOCVOL, &bv)) 660 err(1, "BIOCVOL"); 661 662 bio_status(&bv.bv_bio.bio_status); 663 664 if (name && strcmp(name, bv.bv_dev) != 0) 665 continue; 666 id = i; 667 break; 668 } 669 670 return (id); 671 } 672 673 void 674 bio_setstate(char *arg, int status, char *devicename) 675 { 676 struct bioc_setstate bs; 677 struct locator location; 678 struct stat sb; 679 const char *errstr; 680 681 memset(&bs, 0, sizeof(bs)); 682 if (stat(arg, &sb) == -1) { 683 /* use CTL */ 684 errstr = str2locator(arg, &location); 685 if (errstr) 686 errx(1, "Target %s: %s", arg, errstr); 687 bs.bs_channel = location.channel; 688 bs.bs_target = location.target; 689 bs.bs_lun = location.lun; 690 } else { 691 /* use other id */ 692 bs.bs_other_id = sb.st_rdev; 693 bs.bs_other_id_type = BIOC_SSOTHER_DEVT; 694 } 695 696 bs.bs_bio.bio_cookie = bio_cookie; 697 bs.bs_status = status; 698 699 if (status != BIOC_SSHOTSPARE) { 700 /* make sure user supplied a sd device */ 701 bs.bs_volid = bio_getvolbyname(devicename); 702 if (bs.bs_volid == -1) 703 errx(1, "invalid device %s", devicename); 704 } 705 706 if (ioctl(devh, BIOCSETSTATE, &bs)) 707 err(1, "BIOCSETSTATE"); 708 709 bio_status(&bs.bs_bio.bio_status); 710 } 711 712 void 713 bio_setblink(char *name, char *arg, int blink) 714 { 715 struct locator location; 716 struct bioc_blink bb; 717 struct bioc_inq bi; 718 struct bioc_vol bv; 719 struct bioc_disk bd; 720 const char *errstr; 721 int v, d, rv; 722 723 errstr = str2locator(arg, &location); 724 if (errstr) 725 errx(1, "Target %s: %s", arg, errstr); 726 727 /* try setting blink on the device directly */ 728 memset(&bb, 0, sizeof(bb)); 729 bb.bb_bio.bio_cookie = bio_cookie; 730 bb.bb_status = blink; 731 bb.bb_target = location.target; 732 bb.bb_channel = location.channel; 733 rv = ioctl(devh, BIOCBLINK, &bb); 734 735 if (rv == 0 && bb.bb_bio.bio_status.bs_status == BIO_STATUS_UNKNOWN) 736 return; 737 738 if (rv == 0 && bb.bb_bio.bio_status.bs_status == BIO_STATUS_SUCCESS) { 739 bio_status(&bb.bb_bio.bio_status); 740 return; 741 } 742 743 /* if the blink didn't work, try to find something that will */ 744 745 memset(&bi, 0, sizeof(bi)); 746 bi.bi_bio.bio_cookie = bio_cookie; 747 if (ioctl(devh, BIOCINQ, &bi)) 748 err(1, "BIOCINQ"); 749 750 bio_status(&bi.bi_bio.bio_status); 751 752 for (v = 0; v < bi.bi_novol; v++) { 753 memset(&bv, 0, sizeof(bv)); 754 bv.bv_bio.bio_cookie = bio_cookie; 755 bv.bv_volid = v; 756 if (ioctl(devh, BIOCVOL, &bv)) 757 err(1, "BIOCVOL"); 758 759 bio_status(&bv.bv_bio.bio_status); 760 761 if (name && strcmp(name, bv.bv_dev) != 0) 762 continue; 763 764 for (d = 0; d < bv.bv_nodisk; d++) { 765 memset(&bd, 0, sizeof(bd)); 766 bd.bd_bio.bio_cookie = bio_cookie; 767 bd.bd_volid = v; 768 bd.bd_diskid = d; 769 770 if (ioctl(devh, BIOCDISK, &bd)) 771 err(1, "BIOCDISK"); 772 773 bio_status(&bd.bd_bio.bio_status); 774 775 if (bd.bd_channel == location.channel && 776 bd.bd_target == location.target && 777 bd.bd_lun == location.lun) { 778 if (bd.bd_procdev[0] != '\0') 779 bio_blink(bd.bd_procdev, 780 location.target, blink); 781 else 782 warnx("Disk %s is not in an enclosure", 783 arg); 784 return; 785 } 786 } 787 } 788 789 warnx("Disk %s does not exist", arg); 790 791 return; 792 } 793 794 void 795 bio_blink(char *enclosure, int target, int blinktype) 796 { 797 int bioh; 798 struct bio_locate bl; 799 struct bioc_blink blink; 800 801 bioh = open("/dev/bio", O_RDWR); 802 if (bioh == -1) 803 err(1, "Can't open %s", "/dev/bio"); 804 805 memset(&bl, 0, sizeof(bl)); 806 bl.bl_name = enclosure; 807 if (ioctl(bioh, BIOCLOCATE, &bl)) 808 errx(1, "Can't locate %s device via %s", enclosure, "/dev/bio"); 809 810 bio_status(&bl.bl_bio.bio_status); 811 812 memset(&blink, 0, sizeof(blink)); 813 blink.bb_bio.bio_cookie = bio_cookie; 814 blink.bb_status = blinktype; 815 blink.bb_target = target; 816 817 if (ioctl(bioh, BIOCBLINK, &blink)) 818 err(1, "BIOCBLINK"); 819 820 bio_status(&blink.bb_bio.bio_status); 821 822 close(bioh); 823 } 824 825 void 826 bio_createraid(u_int16_t level, char *dev_list, char *key_disk) 827 { 828 struct bioc_createraid create; 829 struct sr_crypto_kdfinfo kdfinfo; 830 struct sr_crypto_pbkdf kdfhint; 831 struct stat sb; 832 int rv, no_dev, fd; 833 dev_t *dt; 834 u_int16_t min_disks = 0; 835 836 if (!dev_list) 837 errx(1, "no devices specified"); 838 839 dt = calloc(1, BIOC_CRMAXLEN); 840 if (!dt) 841 err(1, "not enough memory for dev_t list"); 842 843 no_dev = bio_parse_devlist(dev_list, dt); 844 845 switch (level) { 846 case 0: 847 min_disks = 2; 848 break; 849 case 1: 850 min_disks = 2; 851 break; 852 case 5: 853 min_disks = 3; 854 break; 855 case 'C': 856 min_disks = 1; 857 break; 858 case 'c': 859 min_disks = 2; 860 break; 861 default: 862 errx(1, "unsupported raid level"); 863 } 864 865 if (no_dev < min_disks) 866 errx(1, "not enough disks"); 867 868 /* for crypto raid we only allow one single chunk */ 869 if (level == 'C' && no_dev != min_disks) 870 errx(1, "not exactly one partition"); 871 872 memset(&create, 0, sizeof(create)); 873 create.bc_bio.bio_cookie = bio_cookie; 874 create.bc_level = level; 875 create.bc_dev_list_len = no_dev * sizeof(dev_t); 876 create.bc_dev_list = dt; 877 create.bc_flags = BIOC_SCDEVT | cflags; 878 create.bc_key_disk = NODEV; 879 880 if (level == 'C' && key_disk == NULL) { 881 882 memset(&kdfinfo, 0, sizeof(kdfinfo)); 883 memset(&kdfhint, 0, sizeof(kdfhint)); 884 885 create.bc_flags |= BIOC_SCNOAUTOASSEMBLE; 886 887 create.bc_opaque = &kdfhint; 888 create.bc_opaque_size = sizeof(kdfhint); 889 create.bc_opaque_flags = BIOC_SOOUT; 890 891 /* try to get KDF hint */ 892 if (ioctl(devh, BIOCCREATERAID, &create)) 893 err(1, "ioctl"); 894 895 bio_status(&create.bc_bio.bio_status); 896 897 if (create.bc_opaque_status == BIOC_SOINOUT_OK) { 898 bio_kdf_derive(&kdfinfo, &kdfhint, "Passphrase: ", 0); 899 memset(&kdfhint, 0, sizeof(kdfhint)); 900 } else { 901 bio_kdf_generate(&kdfinfo); 902 } 903 904 create.bc_opaque = &kdfinfo; 905 create.bc_opaque_size = sizeof(kdfinfo); 906 create.bc_opaque_flags = BIOC_SOIN; 907 908 } else if (level == 'C' && key_disk != NULL) { 909 910 /* Get device number for key disk. */ 911 fd = opendev(key_disk, O_RDONLY, OPENDEV_BLCK, NULL); 912 if (fd == -1) 913 err(1, "could not open %s", key_disk); 914 if (fstat(fd, &sb) == -1) { 915 int saved_errno = errno; 916 close(fd); 917 errc(1, saved_errno, "could not stat %s", key_disk); 918 } 919 close(fd); 920 create.bc_key_disk = sb.st_rdev; 921 922 memset(&kdfinfo, 0, sizeof(kdfinfo)); 923 924 kdfinfo.genkdf.len = sizeof(kdfinfo.genkdf); 925 kdfinfo.genkdf.type = SR_CRYPTOKDFT_KEYDISK; 926 kdfinfo.len = sizeof(kdfinfo); 927 kdfinfo.flags = SR_CRYPTOKDF_HINT; 928 929 create.bc_opaque = &kdfinfo; 930 create.bc_opaque_size = sizeof(kdfinfo); 931 create.bc_opaque_flags = BIOC_SOIN; 932 933 } 934 935 rv = ioctl(devh, BIOCCREATERAID, &create); 936 explicit_bzero(&kdfinfo, sizeof(kdfinfo)); 937 if (rv == -1) 938 err(1, "BIOCCREATERAID"); 939 940 bio_status(&create.bc_bio.bio_status); 941 942 free(dt); 943 } 944 945 void 946 bio_kdf_derive(struct sr_crypto_kdfinfo *kdfinfo, struct sr_crypto_pbkdf 947 *kdfhint, char* prompt, int verify) 948 { 949 if (!kdfinfo) 950 errx(1, "invalid KDF info"); 951 if (!kdfhint) 952 errx(1, "invalid KDF hint"); 953 954 if (kdfhint->generic.len != sizeof(*kdfhint)) 955 errx(1, "KDF hint has invalid size"); 956 957 kdfinfo->flags = SR_CRYPTOKDF_KEY; 958 kdfinfo->len = sizeof(*kdfinfo); 959 960 derive_key(kdfhint->generic.type, kdfhint->rounds, 961 kdfinfo->maskkey, sizeof(kdfinfo->maskkey), 962 kdfhint->salt, sizeof(kdfhint->salt), 963 prompt, verify); 964 } 965 966 void 967 bio_kdf_generate(struct sr_crypto_kdfinfo *kdfinfo) 968 { 969 if (!kdfinfo) 970 errx(1, "invalid KDF info"); 971 972 if (rflag == -1) 973 rflag = bcrypt_pbkdf_autorounds(); 974 975 kdfinfo->pbkdf.generic.len = sizeof(kdfinfo->pbkdf); 976 kdfinfo->pbkdf.generic.type = SR_CRYPTOKDFT_BCRYPT_PBKDF; 977 kdfinfo->pbkdf.rounds = rflag ? rflag : 16; 978 979 kdfinfo->flags = SR_CRYPTOKDF_KEY | SR_CRYPTOKDF_HINT; 980 kdfinfo->len = sizeof(*kdfinfo); 981 982 /* generate salt */ 983 arc4random_buf(kdfinfo->pbkdf.salt, sizeof(kdfinfo->pbkdf.salt)); 984 985 derive_key(kdfinfo->pbkdf.generic.type, kdfinfo->pbkdf.rounds, 986 kdfinfo->maskkey, sizeof(kdfinfo->maskkey), 987 kdfinfo->pbkdf.salt, sizeof(kdfinfo->pbkdf.salt), 988 "New passphrase: ", 1); 989 } 990 991 int 992 bio_parse_devlist(char *lst, dev_t *dt) 993 { 994 char *s, *e; 995 u_int32_t sz = 0; 996 int no_dev = 0, i, x; 997 struct stat sb; 998 char dev[PATH_MAX]; 999 int fd; 1000 1001 if (!lst) 1002 errx(1, "invalid device list"); 1003 1004 s = e = lst; 1005 /* make sure we have a valid device list like /dev/sdNa,/dev/sdNNa */ 1006 while (*e != '\0') { 1007 if (*e == ',') 1008 s = e + 1; 1009 else if (*(e + 1) == '\0' || *(e + 1) == ',') { 1010 /* got one */ 1011 sz = e - s + 1; 1012 strlcpy(dev, s, sz + 1); 1013 fd = opendev(dev, O_RDONLY, OPENDEV_BLCK, NULL); 1014 if (fd == -1) 1015 err(1, "could not open %s", dev); 1016 if (fstat(fd, &sb) == -1) { 1017 int saved_errno = errno; 1018 close(fd); 1019 errc(1, saved_errno, "could not stat %s", dev); 1020 } 1021 close(fd); 1022 dt[no_dev] = sb.st_rdev; 1023 no_dev++; 1024 if (no_dev > (int)(BIOC_CRMAXLEN / sizeof(dev_t))) 1025 errx(1, "too many devices on device list"); 1026 } 1027 e++; 1028 } 1029 1030 for (i = 0; i < no_dev; i++) 1031 for (x = 0; x < no_dev; x++) 1032 if (dt[i] == dt[x] && x != i) 1033 errx(1, "duplicate device in list"); 1034 1035 return (no_dev); 1036 } 1037 1038 u_int32_t 1039 bio_createflags(char *lst) 1040 { 1041 char *s, *e, fs[32]; 1042 u_int32_t sz = 0; 1043 u_int32_t flags = 0; 1044 1045 if (!lst) 1046 errx(1, "invalid flags list"); 1047 1048 s = e = lst; 1049 /* make sure we have a valid flags list like force,noassemeble */ 1050 while (*e != '\0') { 1051 if (*e == ',') 1052 s = e + 1; 1053 else if (*(e + 1) == '\0' || *(e + 1) == ',') { 1054 /* got one */ 1055 sz = e - s + 1; 1056 switch (s[0]) { 1057 case 'f': 1058 flags |= BIOC_SCFORCE; 1059 break; 1060 case 'n': 1061 flags |= BIOC_SCNOAUTOASSEMBLE; 1062 break; 1063 default: 1064 strlcpy(fs, s, sz + 1); 1065 errx(1, "invalid flag %s", fs); 1066 } 1067 } 1068 e++; 1069 } 1070 1071 return (flags); 1072 } 1073 1074 void 1075 bio_deleteraid(char *dev) 1076 { 1077 struct bioc_deleteraid bd; 1078 memset(&bd, 0, sizeof(bd)); 1079 1080 bd.bd_bio.bio_cookie = bio_cookie; 1081 /* XXX make this a dev_t instead of a string */ 1082 strlcpy(bd.bd_dev, dev, sizeof bd.bd_dev); 1083 if (ioctl(devh, BIOCDELETERAID, &bd)) 1084 err(1, "BIOCDELETERAID"); 1085 1086 bio_status(&bd.bd_bio.bio_status); 1087 } 1088 1089 void 1090 bio_changepass(char *dev) 1091 { 1092 struct bioc_discipline bd; 1093 struct sr_crypto_kdfpair kdfpair; 1094 struct sr_crypto_kdfinfo kdfinfo1, kdfinfo2; 1095 struct sr_crypto_pbkdf kdfhint; 1096 int rv; 1097 1098 memset(&bd, 0, sizeof(bd)); 1099 memset(&kdfhint, 0, sizeof(kdfhint)); 1100 memset(&kdfinfo1, 0, sizeof(kdfinfo1)); 1101 memset(&kdfinfo2, 0, sizeof(kdfinfo2)); 1102 1103 /* XXX use dev_t instead of string. */ 1104 strlcpy(bd.bd_dev, dev, sizeof(bd.bd_dev)); 1105 bd.bd_cmd = SR_IOCTL_GET_KDFHINT; 1106 bd.bd_size = sizeof(kdfhint); 1107 bd.bd_data = &kdfhint; 1108 1109 if (ioctl(devh, BIOCDISCIPLINE, &bd)) 1110 err(1, "BIOCDISCIPLINE"); 1111 1112 bio_status(&bd.bd_bio.bio_status); 1113 1114 /* Current passphrase. */ 1115 bio_kdf_derive(&kdfinfo1, &kdfhint, "Old passphrase: ", 0); 1116 1117 /* 1118 * Unless otherwise specified, keep the previous number of rounds as 1119 * long as we're using the same KDF. 1120 */ 1121 if (kdfhint.generic.type == SR_CRYPTOKDFT_BCRYPT_PBKDF && !rflag) 1122 rflag = kdfhint.rounds; 1123 1124 /* New passphrase. */ 1125 bio_kdf_generate(&kdfinfo2); 1126 1127 kdfpair.kdfinfo1 = &kdfinfo1; 1128 kdfpair.kdfsize1 = sizeof(kdfinfo1); 1129 kdfpair.kdfinfo2 = &kdfinfo2; 1130 kdfpair.kdfsize2 = sizeof(kdfinfo2); 1131 1132 bd.bd_cmd = SR_IOCTL_CHANGE_PASSPHRASE; 1133 bd.bd_size = sizeof(kdfpair); 1134 bd.bd_data = &kdfpair; 1135 1136 rv = ioctl(devh, BIOCDISCIPLINE, &bd); 1137 1138 memset(&kdfhint, 0, sizeof(kdfhint)); 1139 explicit_bzero(&kdfinfo1, sizeof(kdfinfo1)); 1140 explicit_bzero(&kdfinfo2, sizeof(kdfinfo2)); 1141 1142 if (rv) 1143 err(1, "BIOCDISCIPLINE"); 1144 1145 bio_status(&bd.bd_bio.bio_status); 1146 } 1147 1148 #define BIOCTL_VIS_NBUF 4 1149 #define BIOCTL_VIS_BUFLEN 80 1150 1151 char * 1152 bio_vis(char *s) 1153 { 1154 static char rbuf[BIOCTL_VIS_NBUF][BIOCTL_VIS_BUFLEN]; 1155 static uint idx = 0; 1156 char *buf; 1157 1158 buf = rbuf[idx++]; 1159 if (idx == BIOCTL_VIS_NBUF) 1160 idx = 0; 1161 1162 strnvis(buf, s, BIOCTL_VIS_BUFLEN, VIS_NL|VIS_CSTYLE); 1163 return (buf); 1164 } 1165 1166 void 1167 bio_diskinq(char *sd_dev) 1168 { 1169 struct dk_inquiry di; 1170 1171 if (ioctl(devh, DIOCINQ, &di) == -1) 1172 err(1, "DIOCINQ"); 1173 1174 printf("%s: <%s, %s, %s>, serial %s\n", sd_dev, bio_vis(di.vendor), 1175 bio_vis(di.product), bio_vis(di.revision), bio_vis(di.serial)); 1176 } 1177 1178 void 1179 bio_patrol(char *arg) 1180 { 1181 struct bioc_patrol bp; 1182 struct timing timing; 1183 const char *errstr; 1184 1185 memset(&bp, 0, sizeof(bp)); 1186 bp.bp_bio.bio_cookie = bio_cookie; 1187 1188 switch (arg[0]) { 1189 case 'a': 1190 bp.bp_opcode = BIOC_SPAUTO; 1191 break; 1192 1193 case 'm': 1194 bp.bp_opcode = BIOC_SPMANUAL; 1195 break; 1196 1197 case 'd': 1198 bp.bp_opcode = BIOC_SPDISABLE; 1199 break; 1200 1201 case 'g': /* get patrol state */ 1202 bp.bp_opcode = BIOC_GPSTATUS; 1203 break; 1204 1205 case 's': /* start/stop patrol */ 1206 if (strncmp("sta", arg, 3) == 0) 1207 bp.bp_opcode = BIOC_SPSTART; 1208 else 1209 bp.bp_opcode = BIOC_SPSTOP; 1210 break; 1211 1212 default: 1213 errx(1, "invalid patrol function: %s", arg); 1214 } 1215 1216 switch (arg[0]) { 1217 case 'a': 1218 errstr = str2patrol(arg, &timing); 1219 if (errstr) 1220 errx(1, "Patrol %s: %s", arg, errstr); 1221 bp.bp_autoival = timing.interval; 1222 bp.bp_autonext = timing.start; 1223 break; 1224 } 1225 1226 if (ioctl(devh, BIOCPATROL, &bp)) 1227 err(1, "BIOCPATROL"); 1228 1229 bio_status(&bp.bp_bio.bio_status); 1230 1231 if (arg[0] == 'g') { 1232 const char *mode, *status; 1233 char interval[40]; 1234 1235 interval[0] = '\0'; 1236 1237 switch (bp.bp_mode) { 1238 case BIOC_SPMAUTO: 1239 mode = "auto"; 1240 snprintf(interval, sizeof interval, 1241 " interval=%d next=%d", bp.bp_autoival, 1242 bp.bp_autonext - bp.bp_autonow); 1243 break; 1244 case BIOC_SPMMANUAL: 1245 mode = "manual"; 1246 break; 1247 case BIOC_SPMDISABLED: 1248 mode = "disabled"; 1249 break; 1250 default: 1251 mode = "unknown"; 1252 break; 1253 } 1254 switch (bp.bp_status) { 1255 case BIOC_SPSSTOPPED: 1256 status = "stopped"; 1257 break; 1258 case BIOC_SPSREADY: 1259 status = "ready"; 1260 break; 1261 case BIOC_SPSACTIVE: 1262 status = "active"; 1263 break; 1264 case BIOC_SPSABORTED: 1265 status = "aborted"; 1266 break; 1267 default: 1268 status = "unknown"; 1269 break; 1270 } 1271 printf("patrol mode: %s%s\n", mode, interval); 1272 printf("patrol status: %s\n", status); 1273 } 1274 } 1275 1276 /* 1277 * Measure this system's performance by measuring the time for 100 rounds. 1278 * We are aiming for something that takes around 1s. 1279 */ 1280 int 1281 bcrypt_pbkdf_autorounds(void) 1282 { 1283 struct timespec before, after; 1284 char buf[SR_CRYPTO_MAXKEYBYTES], salt[128]; 1285 int r = 100; 1286 int duration; 1287 1288 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &before); 1289 if (bcrypt_pbkdf("testpassword", strlen("testpassword"), 1290 salt, sizeof(salt), buf, sizeof(buf), r) != 0) 1291 errx(1, "bcrypt pbkdf failed"); 1292 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &after); 1293 1294 duration = after.tv_sec - before.tv_sec; 1295 duration *= 1000000; 1296 duration += (after.tv_nsec - before.tv_nsec) / 1000; 1297 1298 duration /= r; 1299 r = 1000000 / duration; 1300 1301 if (r < 16) 1302 r = 16; 1303 1304 return r; 1305 } 1306 1307 void 1308 derive_key(u_int32_t type, int rounds, u_int8_t *key, size_t keysz, 1309 u_int8_t *salt, size_t saltsz, char *prompt, int verify) 1310 { 1311 FILE *f; 1312 size_t pl; 1313 struct stat sb; 1314 char passphrase[1024], verifybuf[1024]; 1315 1316 if (!key) 1317 errx(1, "Invalid key"); 1318 if (!salt) 1319 errx(1, "Invalid salt"); 1320 1321 if (type != SR_CRYPTOKDFT_PKCS5_PBKDF2 && 1322 type != SR_CRYPTOKDFT_BCRYPT_PBKDF) 1323 errx(1, "unknown KDF type %d", type); 1324 1325 if (rounds < (type == SR_CRYPTOKDFT_PKCS5_PBKDF2 ? 1000 : 4)) 1326 errx(1, "number of KDF rounds is too small: %d", rounds); 1327 1328 /* get passphrase */ 1329 if (password) { 1330 if ((f = fopen(password, "r")) == NULL) 1331 err(1, "invalid passphrase file"); 1332 1333 if (fstat(fileno(f), &sb) == -1) 1334 err(1, "can't stat passphrase file"); 1335 if (sb.st_uid != 0) 1336 errx(1, "passphrase file must be owned by root"); 1337 if ((sb.st_mode & ~S_IFMT) != (S_IRUSR | S_IWUSR)) 1338 errx(1, "passphrase file has the wrong permissions"); 1339 1340 if (fgets(passphrase, sizeof(passphrase), f) == NULL) 1341 err(1, "can't read passphrase file"); 1342 pl = strlen(passphrase); 1343 if (pl > 0 && passphrase[pl - 1] == '\n') 1344 passphrase[pl - 1] = '\0'; 1345 else 1346 errx(1, "invalid passphrase length"); 1347 1348 fclose(f); 1349 } else { 1350 if (readpassphrase(prompt, passphrase, sizeof(passphrase), 1351 rpp_flag) == NULL) 1352 err(1, "unable to read passphrase"); 1353 } 1354 1355 if (verify && !password) { 1356 /* request user to re-type it */ 1357 if (readpassphrase("Re-type passphrase: ", verifybuf, 1358 sizeof(verifybuf), rpp_flag) == NULL) { 1359 explicit_bzero(passphrase, sizeof(passphrase)); 1360 err(1, "unable to read passphrase"); 1361 } 1362 if ((strlen(passphrase) != strlen(verifybuf)) || 1363 (strcmp(passphrase, verifybuf) != 0)) { 1364 explicit_bzero(passphrase, sizeof(passphrase)); 1365 explicit_bzero(verifybuf, sizeof(verifybuf)); 1366 errx(1, "Passphrases did not match"); 1367 } 1368 /* forget the re-typed one */ 1369 explicit_bzero(verifybuf, sizeof(verifybuf)); 1370 } 1371 1372 /* derive key from passphrase */ 1373 if (type == SR_CRYPTOKDFT_PKCS5_PBKDF2) { 1374 if (verbose) 1375 printf("Deriving key using PKCS#5 PBKDF2 with %i rounds...\n", 1376 rounds); 1377 if (pkcs5_pbkdf2(passphrase, strlen(passphrase), salt, saltsz, 1378 key, keysz, rounds) != 0) 1379 errx(1, "pkcs5_pbkdf2 failed"); 1380 } else if (type == SR_CRYPTOKDFT_BCRYPT_PBKDF) { 1381 if (verbose) 1382 printf("Deriving key using bcrypt PBKDF with %i rounds...\n", 1383 rounds); 1384 if (bcrypt_pbkdf(passphrase, strlen(passphrase), salt, saltsz, 1385 key, keysz, rounds) != 0) 1386 errx(1, "bcrypt_pbkdf failed"); 1387 } else { 1388 errx(1, "unknown KDF type %d", type); 1389 } 1390 1391 /* forget passphrase */ 1392 explicit_bzero(passphrase, sizeof(passphrase)); 1393 1394 return; 1395 } 1396