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