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