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