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