g_eli_ctl.c revision 154462
1131377Stjr/*- 2131377Stjr * Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3131377Stjr * All rights reserved. 4131377Stjr * 5131377Stjr * Redistribution and use in source and binary forms, with or without 6131377Stjr * modification, are permitted provided that the following conditions 7131377Stjr * are met: 8131377Stjr * 1. Redistributions of source code must retain the above copyright 9131377Stjr * notice, this list of conditions and the following disclaimer. 10131377Stjr * 2. Redistributions in binary form must reproduce the above copyright 11131377Stjr * notice, this list of conditions and the following disclaimer in the 12131377Stjr * documentation and/or other materials provided with the distribution. 13131377Stjr * 14131377Stjr * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15131377Stjr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16131377Stjr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17131377Stjr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18131377Stjr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19131377Stjr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20131377Stjr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21131377Stjr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22131377Stjr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23131377Stjr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24131377Stjr * SUCH DAMAGE. 25131377Stjr */ 26131377Stjr 27131377Stjr#include <sys/cdefs.h> 28131377Stjr__FBSDID("$FreeBSD: head/sys/geom/eli/g_eli_ctl.c 154462 2006-01-17 07:30:34Z pjd $"); 29131377Stjr 30131377Stjr#include <sys/param.h> 31131377Stjr#include <sys/systm.h> 32131377Stjr#include <sys/kernel.h> 33131377Stjr#include <sys/module.h> 34131377Stjr#include <sys/lock.h> 35131377Stjr#include <sys/mutex.h> 36131377Stjr#include <sys/bio.h> 37131377Stjr#include <sys/sysctl.h> 38131377Stjr#include <sys/malloc.h> 39131377Stjr#include <sys/kthread.h> 40131377Stjr#include <sys/proc.h> 41131377Stjr#include <sys/sched.h> 42131377Stjr#include <sys/uio.h> 43131377Stjr 44131377Stjr#include <vm/uma.h> 45131377Stjr 46131377Stjr#include <geom/geom.h> 47131377Stjr#include <geom/eli/g_eli.h> 48131377Stjr 49131377Stjr 50131377StjrMALLOC_DECLARE(M_ELI); 51131377Stjr 52131377Stjr 53131377Stjrstatic void 54131377Stjrg_eli_ctl_attach(struct gctl_req *req, struct g_class *mp) 55131377Stjr{ 56131377Stjr struct g_eli_metadata md; 57131377Stjr struct g_provider *pp; 58131377Stjr const char *name; 59131377Stjr u_char *key, mkey[G_ELI_DATAIVKEYLEN]; 60131377Stjr int *nargs, *detach; 61131377Stjr int keysize, error; 62131377Stjr u_int nkey; 63131377Stjr 64131377Stjr g_topology_assert(); 65131377Stjr 66131377Stjr nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 67131377Stjr if (nargs == NULL) { 68131377Stjr gctl_error(req, "No '%s' argument.", "nargs"); 69131377Stjr return; 70131377Stjr } 71131377Stjr if (*nargs != 1) { 72131377Stjr gctl_error(req, "Invalid number of arguments."); 73131377Stjr return; 74131377Stjr } 75131377Stjr 76131377Stjr detach = gctl_get_paraml(req, "detach", sizeof(*detach)); 77131377Stjr if (detach == NULL) { 78131377Stjr gctl_error(req, "No '%s' argument.", "detach"); 79131377Stjr return; 80131377Stjr } 81131377Stjr 82131377Stjr name = gctl_get_asciiparam(req, "arg0"); 83131377Stjr if (name == NULL) { 84131377Stjr gctl_error(req, "No 'arg%u' argument.", 0); 85131377Stjr return; 86131377Stjr } 87131377Stjr if (strncmp(name, "/dev/", strlen("/dev/")) == 0) 88131377Stjr name += strlen("/dev/"); 89131377Stjr pp = g_provider_by_name(name); 90131377Stjr if (pp == NULL) { 91131377Stjr gctl_error(req, "Provider %s is invalid.", name); 92131377Stjr return; 93131377Stjr } 94131377Stjr error = g_eli_read_metadata(mp, pp, &md); 95131377Stjr if (error != 0) { 96131377Stjr gctl_error(req, "Cannot read metadata from %s (error=%d).", 97131377Stjr name, error); 98131377Stjr return; 99131377Stjr } 100131377Stjr if (md.md_keys == 0x00) { 101131377Stjr bzero(&md, sizeof(md)); 102131377Stjr gctl_error(req, "No valid keys on %s.", pp->name); 103131377Stjr return; 104131377Stjr } 105131377Stjr 106131377Stjr key = gctl_get_param(req, "key", &keysize); 107131377Stjr if (key == NULL || keysize != G_ELI_USERKEYLEN) { 108131377Stjr bzero(&md, sizeof(md)); 109131377Stjr gctl_error(req, "No '%s' argument.", "key"); 110131377Stjr return; 111131377Stjr } 112131377Stjr 113131377Stjr error = g_eli_mkey_decrypt(&md, key, mkey, &nkey); 114131377Stjr bzero(key, keysize); 115131377Stjr if (error == -1) { 116131377Stjr bzero(&md, sizeof(md)); 117131377Stjr gctl_error(req, "Wrong key for %s.", pp->name); 118131377Stjr return; 119131377Stjr } else if (error > 0) { 120131377Stjr bzero(&md, sizeof(md)); 121131377Stjr gctl_error(req, "Cannot decrypt Master Key for %s (error=%d).", 122131377Stjr pp->name, error); 123131377Stjr return; 124131377Stjr } 125131377Stjr G_ELI_DEBUG(1, "Using Master Key %u for %s.", nkey, pp->name); 126131377Stjr 127131377Stjr if (*detach) 128131377Stjr md.md_flags |= G_ELI_FLAG_WO_DETACH; 129131377Stjr g_eli_create(req, mp, pp, &md, mkey, nkey); 130131377Stjr bzero(mkey, sizeof(mkey)); 131131377Stjr bzero(&md, sizeof(md)); 132131377Stjr} 133131377Stjr 134131377Stjrstatic struct g_eli_softc * 135131377Stjrg_eli_find_device(struct g_class *mp, const char *prov) 136131377Stjr{ 137131377Stjr struct g_eli_softc *sc; 138131377Stjr struct g_geom *gp; 139131377Stjr struct g_provider *pp; 140131377Stjr struct g_consumer *cp; 141131377Stjr 142131377Stjr if (strncmp(prov, "/dev/", strlen("/dev/")) == 0) 143131377Stjr prov += strlen("/dev/"); 144131377Stjr LIST_FOREACH(gp, &mp->geom, geom) { 145131377Stjr sc = gp->softc; 146131377Stjr if (sc == NULL) 147131377Stjr continue; 148131377Stjr pp = LIST_FIRST(&gp->provider); 149131377Stjr if (pp != NULL && strcmp(pp->name, prov) == 0) 150131377Stjr return (sc); 151131377Stjr cp = LIST_FIRST(&gp->consumer); 152131377Stjr if (cp != NULL && cp->provider != NULL && 153131377Stjr strcmp(cp->provider->name, prov) == 0) { 154131377Stjr return (sc); 155131377Stjr } 156131377Stjr } 157131377Stjr return (NULL); 158131377Stjr} 159131377Stjr 160131377Stjrstatic void 161131377Stjrg_eli_ctl_detach(struct gctl_req *req, struct g_class *mp) 162131377Stjr{ 163131377Stjr struct g_eli_softc *sc; 164131377Stjr int *force, *last, *nargs, error; 165131377Stjr const char *prov; 166131377Stjr char param[16]; 167131377Stjr u_int i; 168131377Stjr 169131377Stjr g_topology_assert(); 170131377Stjr 171131377Stjr nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 172131377Stjr if (nargs == NULL) { 173131377Stjr gctl_error(req, "No '%s' argument.", "nargs"); 174131377Stjr return; 175131377Stjr } 176131377Stjr if (*nargs <= 0) { 177131377Stjr gctl_error(req, "Missing device(s)."); 178131377Stjr return; 179131377Stjr } 180131377Stjr force = gctl_get_paraml(req, "force", sizeof(*force)); 181131377Stjr if (force == NULL) { 182131377Stjr gctl_error(req, "No '%s' argument.", "force"); 183131377Stjr return; 184131377Stjr } 185131377Stjr last = gctl_get_paraml(req, "last", sizeof(*last)); 186131377Stjr if (last == NULL) { 187131377Stjr gctl_error(req, "No '%s' argument.", "last"); 188131377Stjr return; 189131377Stjr } 190131377Stjr 191131377Stjr for (i = 0; i < (u_int)*nargs; i++) { 192131377Stjr snprintf(param, sizeof(param), "arg%u", i); 193131377Stjr prov = gctl_get_asciiparam(req, param); 194131377Stjr if (prov == NULL) { 195131377Stjr gctl_error(req, "No 'arg%u' argument.", i); 196131377Stjr return; 197131377Stjr } 198131377Stjr sc = g_eli_find_device(mp, prov); 199131377Stjr if (sc == NULL) { 200131377Stjr gctl_error(req, "No such device: %s.", prov); 201131377Stjr return; 202131377Stjr } 203131377Stjr if (*last) { 204131377Stjr sc->sc_flags |= G_ELI_FLAG_RW_DETACH; 205131377Stjr sc->sc_geom->access = g_eli_access; 206131377Stjr } else { 207131377Stjr error = g_eli_destroy(sc, *force); 208131377Stjr if (error != 0) { 209131377Stjr gctl_error(req, 210131377Stjr "Cannot destroy device %s (error=%d).", 211131377Stjr sc->sc_name, error); 212131377Stjr return; 213131377Stjr } 214131377Stjr } 215131377Stjr } 216131377Stjr} 217131377Stjr 218131377Stjrstatic void 219131377Stjrg_eli_ctl_onetime(struct gctl_req *req, struct g_class *mp) 220131377Stjr{ 221131377Stjr struct g_eli_metadata md; 222131377Stjr struct g_provider *pp; 223131377Stjr const char *name; 224131377Stjr intmax_t *keylen, *sectorsize; 225131377Stjr u_char mkey[G_ELI_DATAIVKEYLEN]; 226131377Stjr int *nargs, *detach; 227131377Stjr 228131377Stjr g_topology_assert(); 229131377Stjr bzero(&md, sizeof(md)); 230131377Stjr 231131377Stjr nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 232131377Stjr if (nargs == NULL) { 233131377Stjr gctl_error(req, "No '%s' argument.", "nargs"); 234131377Stjr return; 235131377Stjr } 236131377Stjr if (*nargs != 1) { 237131377Stjr gctl_error(req, "Invalid number of arguments."); 238131377Stjr return; 239131377Stjr } 240131377Stjr 241131377Stjr detach = gctl_get_paraml(req, "detach", sizeof(*detach)); 242131377Stjr if (detach == NULL) { 243131377Stjr gctl_error(req, "No '%s' argument.", "detach"); 244131377Stjr return; 245131377Stjr } 246131377Stjr 247131377Stjr strlcpy(md.md_magic, G_ELI_MAGIC, sizeof(md.md_magic)); 248131377Stjr md.md_version = G_ELI_VERSION; 249131377Stjr md.md_flags |= G_ELI_FLAG_ONETIME; 250131377Stjr if (*detach) 251131377Stjr md.md_flags |= G_ELI_FLAG_WO_DETACH; 252131377Stjr 253131377Stjr name = gctl_get_asciiparam(req, "algo"); 254131377Stjr if (name == NULL) { 255131377Stjr gctl_error(req, "No '%s' argument.", "algo"); 256131377Stjr return; 257131377Stjr } 258131377Stjr md.md_algo = g_eli_str2algo(name); 259131377Stjr if (md.md_algo < CRYPTO_ALGORITHM_MIN || 260131377Stjr md.md_algo > CRYPTO_ALGORITHM_MAX) { 261131377Stjr gctl_error(req, "Invalid '%s' argument.", "algo"); 262131377Stjr return; 263131377Stjr } 264131377Stjr 265131377Stjr keylen = gctl_get_paraml(req, "keylen", sizeof(*keylen)); 266131377Stjr if (keylen == NULL) { 267131377Stjr gctl_error(req, "No '%s' argument.", "keylen"); 268131377Stjr return; 269131377Stjr } 270131377Stjr md.md_keylen = g_eli_keylen(md.md_algo, *keylen); 271131377Stjr if (md.md_keylen == 0) { 272131377Stjr gctl_error(req, "Invalid '%s' argument.", "keylen"); 273131377Stjr return; 274131377Stjr } 275131377Stjr 276131377Stjr /* Not important here. */ 277131377Stjr md.md_provsize = 0; 278131377Stjr /* Not important here. */ 279131377Stjr bzero(md.md_salt, sizeof(md.md_salt)); 280131377Stjr 281131377Stjr md.md_keys = 0x01; 282131377Stjr arc4rand(mkey, sizeof(mkey), 0); 283131377Stjr 284131377Stjr /* Not important here. */ 285131377Stjr bzero(md.md_hash, sizeof(md.md_hash)); 286131377Stjr 287131377Stjr name = gctl_get_asciiparam(req, "arg0"); 288131377Stjr if (name == NULL) { 289131377Stjr gctl_error(req, "No 'arg%u' argument.", 0); 290131377Stjr return; 291131377Stjr } 292131377Stjr if (strncmp(name, "/dev/", strlen("/dev/")) == 0) 293131377Stjr name += strlen("/dev/"); 294131377Stjr pp = g_provider_by_name(name); 295131377Stjr if (pp == NULL) { 296131377Stjr gctl_error(req, "Provider %s is invalid.", name); 297131377Stjr return; 298131377Stjr } 299131377Stjr 300131377Stjr sectorsize = gctl_get_paraml(req, "sectorsize", sizeof(*sectorsize)); 301131377Stjr if (sectorsize == NULL) { 302131377Stjr gctl_error(req, "No '%s' argument.", "sectorsize"); 303131377Stjr return; 304131377Stjr } 305131377Stjr if (*sectorsize == 0) 306131377Stjr md.md_sectorsize = pp->sectorsize; 307131377Stjr else { 308131377Stjr if (*sectorsize < 0 || (*sectorsize % pp->sectorsize) != 0) { 309131377Stjr gctl_error(req, "Invalid sector size."); 310131377Stjr return; 311131377Stjr } 312131377Stjr md.md_sectorsize = *sectorsize; 313131377Stjr } 314131377Stjr 315131377Stjr g_eli_create(req, mp, pp, &md, mkey, -1); 316131377Stjr bzero(mkey, sizeof(mkey)); 317131377Stjr bzero(&md, sizeof(md)); 318131377Stjr} 319131377Stjr 320131377Stjrstatic void 321131377Stjrg_eli_ctl_setkey(struct gctl_req *req, struct g_class *mp) 322131377Stjr{ 323131377Stjr struct g_eli_softc *sc; 324131377Stjr struct g_eli_metadata md; 325131377Stjr struct g_provider *pp; 326131377Stjr struct g_consumer *cp; 327131377Stjr const char *name; 328131377Stjr u_char *key, *mkeydst, *sector; 329131377Stjr intmax_t *valp; 330131377Stjr int keysize, nkey, error; 331131377Stjr 332131377Stjr g_topology_assert(); 333131377Stjr 334131377Stjr name = gctl_get_asciiparam(req, "arg0"); 335131377Stjr if (name == NULL) { 336131377Stjr gctl_error(req, "No 'arg%u' argument.", 0); 337131377Stjr return; 338131377Stjr } 339131377Stjr sc = g_eli_find_device(mp, name); 340131377Stjr if (sc == NULL) { 341131377Stjr gctl_error(req, "Provider %s is invalid.", name); 342131377Stjr return; 343131377Stjr } 344131377Stjr cp = LIST_FIRST(&sc->sc_geom->consumer); 345131377Stjr pp = cp->provider; 346131377Stjr 347131377Stjr error = g_eli_read_metadata(mp, pp, &md); 348131377Stjr if (error != 0) { 349131377Stjr gctl_error(req, "Cannot read metadata from %s (error=%d).", 350131377Stjr name, error); 351131377Stjr return; 352131377Stjr } 353131377Stjr 354131377Stjr valp = gctl_get_paraml(req, "keyno", sizeof(*valp)); 355131377Stjr if (valp == NULL) { 356131377Stjr gctl_error(req, "No '%s' argument.", "keyno"); 357131377Stjr return; 358131377Stjr } 359131377Stjr if (*valp != -1) 360131377Stjr nkey = *valp; 361131377Stjr else 362131377Stjr nkey = sc->sc_nkey; 363131377Stjr if (nkey < 0 || nkey >= G_ELI_MAXMKEYS) { 364131377Stjr gctl_error(req, "Invalid '%s' argument.", "keyno"); 365131377Stjr return; 366131377Stjr } 367131377Stjr 368131377Stjr valp = gctl_get_paraml(req, "iterations", sizeof(*valp)); 369131377Stjr if (valp == NULL) { 370131377Stjr gctl_error(req, "No '%s' argument.", "iterations"); 371131377Stjr return; 372131377Stjr } 373131377Stjr /* Check if iterations number should and can be changed. */ 374131377Stjr if (*valp != -1) { 375131377Stjr if (bitcount32(md.md_keys) != 1) { 376131377Stjr gctl_error(req, "To be able to use '-i' option, only " 377131377Stjr "one key can be defined."); 378131377Stjr return; 379131377Stjr } 380131377Stjr if (md.md_keys != (1 << nkey)) { 381131377Stjr gctl_error(req, "Only already defined key can be " 382131377Stjr "changed when '-i' option is used."); 383131377Stjr return; 384131377Stjr } 385131377Stjr md.md_iterations = *valp; 386131377Stjr } 387131377Stjr 388131377Stjr key = gctl_get_param(req, "key", &keysize); 389131377Stjr if (key == NULL || keysize != G_ELI_USERKEYLEN) { 390131377Stjr bzero(&md, sizeof(md)); 391131377Stjr gctl_error(req, "No '%s' argument.", "key"); 392131377Stjr return; 393131377Stjr } 394131377Stjr 395131377Stjr mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN; 396131377Stjr md.md_keys |= (1 << nkey); 397131377Stjr 398131377Stjr bcopy(sc->sc_ivkey, mkeydst, sizeof(sc->sc_ivkey)); 399131377Stjr bcopy(sc->sc_datakey, mkeydst + sizeof(sc->sc_ivkey), 400131377Stjr sizeof(sc->sc_datakey)); 401131377Stjr 402131377Stjr /* Encrypt Master Key with the new key. */ 403131377Stjr error = g_eli_mkey_encrypt(md.md_algo, key, md.md_keylen, mkeydst); 404131377Stjr bzero(key, sizeof(key)); 405131377Stjr if (error != 0) { 406131377Stjr bzero(&md, sizeof(md)); 407131377Stjr gctl_error(req, "Cannot encrypt Master Key (error=%d).", error); 408131377Stjr return; 409131377Stjr } 410131377Stjr 411131377Stjr sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO); 412131377Stjr /* Store metadata with fresh key. */ 413131377Stjr eli_metadata_encode(&md, sector); 414131377Stjr bzero(&md, sizeof(md)); 415131377Stjr error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector, 416131377Stjr pp->sectorsize); 417131377Stjr bzero(sector, sizeof(sector)); 418131377Stjr free(sector, M_ELI); 419131377Stjr if (error != 0) { 420131377Stjr gctl_error(req, "Cannot store metadata on %s (error=%d).", 421131377Stjr pp->name, error); 422131377Stjr return; 423131377Stjr } 424131377Stjr G_ELI_DEBUG(1, "Key %u changed on %s.", nkey, pp->name); 425131377Stjr} 426131377Stjr 427131377Stjrstatic void 428131377Stjrg_eli_ctl_delkey(struct gctl_req *req, struct g_class *mp) 429131377Stjr{ 430131377Stjr struct g_eli_softc *sc; 431131377Stjr struct g_eli_metadata md; 432131377Stjr struct g_provider *pp; 433131377Stjr struct g_consumer *cp; 434131377Stjr const char *name; 435131377Stjr u_char *mkeydst, *sector; 436131377Stjr intmax_t *valp; 437131377Stjr size_t keysize; 438131377Stjr int error, nkey, *all, *force; 439131377Stjr u_int i; 440131377Stjr 441131377Stjr g_topology_assert(); 442 443 nkey = 0; /* fixes causeless gcc warning */ 444 445 name = gctl_get_asciiparam(req, "arg0"); 446 if (name == NULL) { 447 gctl_error(req, "No 'arg%u' argument.", 0); 448 return; 449 } 450 sc = g_eli_find_device(mp, name); 451 if (sc == NULL) { 452 gctl_error(req, "Provider %s is invalid.", name); 453 return; 454 } 455 cp = LIST_FIRST(&sc->sc_geom->consumer); 456 pp = cp->provider; 457 458 error = g_eli_read_metadata(mp, pp, &md); 459 if (error != 0) { 460 gctl_error(req, "Cannot read metadata from %s (error=%d).", 461 name, error); 462 return; 463 } 464 465 all = gctl_get_paraml(req, "all", sizeof(*all)); 466 if (all == NULL) { 467 gctl_error(req, "No '%s' argument.", "all"); 468 return; 469 } 470 471 if (*all) { 472 mkeydst = md.md_mkeys; 473 keysize = sizeof(md.md_mkeys); 474 } else { 475 force = gctl_get_paraml(req, "force", sizeof(*force)); 476 if (force == NULL) { 477 gctl_error(req, "No '%s' argument.", "force"); 478 return; 479 } 480 481 valp = gctl_get_paraml(req, "keyno", sizeof(*valp)); 482 if (valp == NULL) { 483 gctl_error(req, "No '%s' argument.", "keyno"); 484 return; 485 } 486 if (*valp != -1) 487 nkey = *valp; 488 else 489 nkey = sc->sc_nkey; 490 if (nkey < 0 || nkey >= G_ELI_MAXMKEYS) { 491 gctl_error(req, "Invalid '%s' argument.", "keyno"); 492 return; 493 } 494 if (!(md.md_keys & (1 << nkey)) && !*force) { 495 gctl_error(req, "Master Key %u is not set.", nkey); 496 return; 497 } 498 md.md_keys &= ~(1 << nkey); 499 if (md.md_keys == 0 && !*force) { 500 gctl_error(req, "This is the last Master Key. Use '-f' " 501 "flag if you really want to remove it."); 502 return; 503 } 504 mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN; 505 keysize = G_ELI_MKEYLEN; 506 } 507 508 sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO); 509 for (i = 0; i <= g_eli_overwrites; i++) { 510 if (i == g_eli_overwrites) 511 bzero(mkeydst, keysize); 512 else 513 arc4rand(mkeydst, keysize, 0); 514 /* Store metadata with destroyed key. */ 515 eli_metadata_encode(&md, sector); 516 error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector, 517 pp->sectorsize); 518 if (error != 0) { 519 G_ELI_DEBUG(0, "Cannot store metadata on %s " 520 "(error=%d).", pp->name, error); 521 } 522 } 523 bzero(&md, sizeof(md)); 524 bzero(sector, sizeof(sector)); 525 free(sector, M_ELI); 526 if (*all) 527 G_ELI_DEBUG(1, "All keys removed from %s.", pp->name); 528 else 529 G_ELI_DEBUG(1, "Key %d removed from %s.", nkey, pp->name); 530} 531 532static int 533g_eli_kill_one(struct g_eli_softc *sc) 534{ 535 struct g_provider *pp; 536 struct g_consumer *cp; 537 u_char *sector; 538 int err, error = 0; 539 u_int i; 540 541 g_topology_assert(); 542 543 if (sc == NULL) 544 return (ENOENT); 545 546 pp = LIST_FIRST(&sc->sc_geom->provider); 547 g_error_provider(pp, ENXIO); 548 549 cp = LIST_FIRST(&sc->sc_geom->consumer); 550 pp = cp->provider; 551 552 sector = malloc(pp->sectorsize, M_ELI, M_WAITOK); 553 for (i = 0; i <= g_eli_overwrites; i++) { 554 if (i == g_eli_overwrites) 555 bzero(sector, pp->sectorsize); 556 else 557 arc4rand(sector, pp->sectorsize, 0); 558 err = g_write_data(cp, pp->mediasize - pp->sectorsize, sector, 559 pp->sectorsize); 560 if (err != 0) { 561 G_ELI_DEBUG(0, "Cannot erase metadata on %s " 562 "(error=%d).", pp->name, err); 563 if (error == 0) 564 error = err; 565 } 566 } 567 free(sector, M_ELI); 568 if (error == 0) 569 G_ELI_DEBUG(0, "%s has been killed.", pp->name); 570 g_eli_destroy(sc, 1); 571 return (error); 572} 573 574static void 575g_eli_ctl_kill(struct gctl_req *req, struct g_class *mp) 576{ 577 int *all, *nargs; 578 int error; 579 580 g_topology_assert(); 581 582 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 583 if (nargs == NULL) { 584 gctl_error(req, "No '%s' argument.", "nargs"); 585 return; 586 } 587 all = gctl_get_paraml(req, "all", sizeof(*all)); 588 if (all == NULL) { 589 gctl_error(req, "No '%s' argument.", "all"); 590 return; 591 } 592 if (!*all && *nargs == 0) { 593 gctl_error(req, "Too few arguments."); 594 return; 595 } 596 597 if (*all) { 598 struct g_geom *gp, *gp2; 599 600 LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) { 601 error = g_eli_kill_one(gp->softc); 602 if (error != 0) 603 gctl_error(req, "Not fully done."); 604 } 605 } else { 606 struct g_eli_softc *sc; 607 const char *prov; 608 char param[16]; 609 int i; 610 611 for (i = 0; i < *nargs; i++) { 612 snprintf(param, sizeof(param), "arg%u", i); 613 prov = gctl_get_asciiparam(req, param); 614 if (prov == NULL) { 615 G_ELI_DEBUG(0, "No 'arg%d' argument.", i); 616 continue; 617 } 618 619 sc = g_eli_find_device(mp, prov); 620 if (sc == NULL) { 621 G_ELI_DEBUG(1, "No such provider: %s.", prov); 622 continue; 623 } 624 error = g_eli_kill_one(sc); 625 if (error != 0) 626 gctl_error(req, "Not fully done."); 627 } 628 } 629} 630 631void 632g_eli_config(struct gctl_req *req, struct g_class *mp, const char *verb) 633{ 634 uint32_t *version; 635 636 g_topology_assert(); 637 638 version = gctl_get_paraml(req, "version", sizeof(*version)); 639 if (version == NULL) { 640 gctl_error(req, "No '%s' argument.", "version"); 641 return; 642 } 643 if (*version != G_ELI_VERSION) { 644 gctl_error(req, "Userland and kernel parts are out of sync."); 645 return; 646 } 647 648 if (strcmp(verb, "attach") == 0) 649 g_eli_ctl_attach(req, mp); 650 else if (strcmp(verb, "detach") == 0 || strcmp(verb, "stop") == 0) 651 g_eli_ctl_detach(req, mp); 652 else if (strcmp(verb, "onetime") == 0) 653 g_eli_ctl_onetime(req, mp); 654 else if (strcmp(verb, "setkey") == 0) 655 g_eli_ctl_setkey(req, mp); 656 else if (strcmp(verb, "delkey") == 0) 657 g_eli_ctl_delkey(req, mp); 658 else if (strcmp(verb, "kill") == 0) 659 g_eli_ctl_kill(req, mp); 660 else 661 gctl_error(req, "Unknown verb."); 662} 663