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