2 * Copyright (c) 2005-2011 Pawel Jakub Dawidek <pawel@dawidek.net>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/kernel.h>
33 #include <sys/module.h>
35 #include <sys/mutex.h>
37 #include <sys/sysctl.h>
38 #include <sys/malloc.h>
39 #include <sys/kthread.h>
41 #include <sys/sched.h>
46 #include <geom/geom.h>
47 #include <geom/eli/g_eli.h>
50 MALLOC_DECLARE(M_ELI);
54 g_eli_ctl_attach(struct gctl_req *req, struct g_class *mp)
56 struct g_eli_metadata md;
57 struct g_provider *pp;
59 u_char *key, mkey[G_ELI_DATAIVKEYLEN];
60 int *nargs, *detach, *readonly;
66 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
68 gctl_error(req, "No '%s' argument.", "nargs");
72 gctl_error(req, "Invalid number of arguments.");
76 detach = gctl_get_paraml(req, "detach", sizeof(*detach));
78 gctl_error(req, "No '%s' argument.", "detach");
82 readonly = gctl_get_paraml(req, "readonly", sizeof(*readonly));
83 if (readonly == NULL) {
84 gctl_error(req, "No '%s' argument.", "readonly");
88 name = gctl_get_asciiparam(req, "arg0");
90 gctl_error(req, "No 'arg%u' argument.", 0);
93 if (strncmp(name, "/dev/", strlen("/dev/")) == 0)
94 name += strlen("/dev/");
95 pp = g_provider_by_name(name);
97 gctl_error(req, "Provider %s is invalid.", name);
100 error = g_eli_read_metadata(mp, pp, &md);
102 gctl_error(req, "Cannot read metadata from %s (error=%d).",
106 if (md.md_keys == 0x00) {
107 bzero(&md, sizeof(md));
108 gctl_error(req, "No valid keys on %s.", pp->name);
112 key = gctl_get_param(req, "key", &keysize);
113 if (key == NULL || keysize != G_ELI_USERKEYLEN) {
114 bzero(&md, sizeof(md));
115 gctl_error(req, "No '%s' argument.", "key");
119 error = g_eli_mkey_decrypt(&md, key, mkey, &nkey);
122 bzero(&md, sizeof(md));
123 gctl_error(req, "Wrong key for %s.", pp->name);
125 } else if (error > 0) {
126 bzero(&md, sizeof(md));
127 gctl_error(req, "Cannot decrypt Master Key for %s (error=%d).",
131 G_ELI_DEBUG(1, "Using Master Key %u for %s.", nkey, pp->name);
133 if (*detach && *readonly) {
134 bzero(&md, sizeof(md));
135 gctl_error(req, "Options -d and -r are mutually exclusive.");
139 md.md_flags |= G_ELI_FLAG_WO_DETACH;
141 md.md_flags |= G_ELI_FLAG_RO;
142 g_eli_create(req, mp, pp, &md, mkey, nkey);
143 bzero(mkey, sizeof(mkey));
144 bzero(&md, sizeof(md));
147 static struct g_eli_softc *
148 g_eli_find_device(struct g_class *mp, const char *prov)
150 struct g_eli_softc *sc;
152 struct g_provider *pp;
153 struct g_consumer *cp;
155 if (strncmp(prov, "/dev/", strlen("/dev/")) == 0)
156 prov += strlen("/dev/");
157 LIST_FOREACH(gp, &mp->geom, geom) {
161 pp = LIST_FIRST(&gp->provider);
162 if (pp != NULL && strcmp(pp->name, prov) == 0)
164 cp = LIST_FIRST(&gp->consumer);
165 if (cp != NULL && cp->provider != NULL &&
166 strcmp(cp->provider->name, prov) == 0) {
174 g_eli_ctl_detach(struct gctl_req *req, struct g_class *mp)
176 struct g_eli_softc *sc;
177 int *force, *last, *nargs, error;
184 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
186 gctl_error(req, "No '%s' argument.", "nargs");
190 gctl_error(req, "Missing device(s).");
193 force = gctl_get_paraml(req, "force", sizeof(*force));
195 gctl_error(req, "No '%s' argument.", "force");
198 last = gctl_get_paraml(req, "last", sizeof(*last));
200 gctl_error(req, "No '%s' argument.", "last");
204 for (i = 0; i < *nargs; i++) {
205 snprintf(param, sizeof(param), "arg%d", i);
206 prov = gctl_get_asciiparam(req, param);
208 gctl_error(req, "No 'arg%d' argument.", i);
211 sc = g_eli_find_device(mp, prov);
213 gctl_error(req, "No such device: %s.", prov);
217 sc->sc_flags |= G_ELI_FLAG_RW_DETACH;
218 sc->sc_geom->access = g_eli_access;
220 error = g_eli_destroy(sc, *force ? TRUE : FALSE);
223 "Cannot destroy device %s (error=%d).",
232 g_eli_ctl_onetime(struct gctl_req *req, struct g_class *mp)
234 struct g_eli_metadata md;
235 struct g_provider *pp;
237 intmax_t *keylen, *sectorsize;
238 u_char mkey[G_ELI_DATAIVKEYLEN];
242 bzero(&md, sizeof(md));
244 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
246 gctl_error(req, "No '%s' argument.", "nargs");
250 gctl_error(req, "Invalid number of arguments.");
254 detach = gctl_get_paraml(req, "detach", sizeof(*detach));
255 if (detach == NULL) {
256 gctl_error(req, "No '%s' argument.", "detach");
260 strlcpy(md.md_magic, G_ELI_MAGIC, sizeof(md.md_magic));
261 md.md_version = G_ELI_VERSION;
262 md.md_flags |= G_ELI_FLAG_ONETIME;
264 md.md_flags |= G_ELI_FLAG_WO_DETACH;
266 md.md_ealgo = CRYPTO_ALGORITHM_MIN - 1;
267 name = gctl_get_asciiparam(req, "aalgo");
269 gctl_error(req, "No '%s' argument.", "aalgo");
273 md.md_aalgo = g_eli_str2aalgo(name);
274 if (md.md_aalgo >= CRYPTO_ALGORITHM_MIN &&
275 md.md_aalgo <= CRYPTO_ALGORITHM_MAX) {
276 md.md_flags |= G_ELI_FLAG_AUTH;
279 * For backward compatibility, check if the -a option
280 * was used to provide encryption algorithm.
282 md.md_ealgo = g_eli_str2ealgo(name);
283 if (md.md_ealgo < CRYPTO_ALGORITHM_MIN ||
284 md.md_ealgo > CRYPTO_ALGORITHM_MAX) {
286 "Invalid authentication algorithm.");
289 gctl_error(req, "warning: The -e option, not "
290 "the -a option is now used to specify "
291 "encryption algorithm to use.");
296 if (md.md_ealgo < CRYPTO_ALGORITHM_MIN ||
297 md.md_ealgo > CRYPTO_ALGORITHM_MAX) {
298 name = gctl_get_asciiparam(req, "ealgo");
300 gctl_error(req, "No '%s' argument.", "ealgo");
303 md.md_ealgo = g_eli_str2ealgo(name);
304 if (md.md_ealgo < CRYPTO_ALGORITHM_MIN ||
305 md.md_ealgo > CRYPTO_ALGORITHM_MAX) {
306 gctl_error(req, "Invalid encryption algorithm.");
311 keylen = gctl_get_paraml(req, "keylen", sizeof(*keylen));
312 if (keylen == NULL) {
313 gctl_error(req, "No '%s' argument.", "keylen");
316 md.md_keylen = g_eli_keylen(md.md_ealgo, *keylen);
317 if (md.md_keylen == 0) {
318 gctl_error(req, "Invalid '%s' argument.", "keylen");
322 /* Not important here. */
324 /* Not important here. */
325 bzero(md.md_salt, sizeof(md.md_salt));
328 arc4rand(mkey, sizeof(mkey), 0);
330 /* Not important here. */
331 bzero(md.md_hash, sizeof(md.md_hash));
333 name = gctl_get_asciiparam(req, "arg0");
335 gctl_error(req, "No 'arg%u' argument.", 0);
338 if (strncmp(name, "/dev/", strlen("/dev/")) == 0)
339 name += strlen("/dev/");
340 pp = g_provider_by_name(name);
342 gctl_error(req, "Provider %s is invalid.", name);
346 sectorsize = gctl_get_paraml(req, "sectorsize", sizeof(*sectorsize));
347 if (sectorsize == NULL) {
348 gctl_error(req, "No '%s' argument.", "sectorsize");
351 if (*sectorsize == 0)
352 md.md_sectorsize = pp->sectorsize;
354 if (*sectorsize < 0 || (*sectorsize % pp->sectorsize) != 0) {
355 gctl_error(req, "Invalid sector size.");
358 if (*sectorsize > PAGE_SIZE) {
359 gctl_error(req, "warning: Using sectorsize bigger than "
362 md.md_sectorsize = *sectorsize;
365 g_eli_create(req, mp, pp, &md, mkey, -1);
366 bzero(mkey, sizeof(mkey));
367 bzero(&md, sizeof(md));
371 g_eli_ctl_configure(struct gctl_req *req, struct g_class *mp)
373 struct g_eli_softc *sc;
374 struct g_eli_metadata md;
375 struct g_provider *pp;
376 struct g_consumer *cp;
380 int *nargs, *boot, *noboot;
386 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
388 gctl_error(req, "No '%s' argument.", "nargs");
392 gctl_error(req, "Missing device(s).");
396 boot = gctl_get_paraml(req, "boot", sizeof(*boot));
398 gctl_error(req, "No '%s' argument.", "boot");
401 noboot = gctl_get_paraml(req, "noboot", sizeof(*noboot));
402 if (noboot == NULL) {
403 gctl_error(req, "No '%s' argument.", "noboot");
406 if (*boot && *noboot) {
407 gctl_error(req, "Options -b and -B are mutually exclusive.");
410 if (!*boot && !*noboot) {
411 gctl_error(req, "No option given.");
415 for (i = 0; i < *nargs; i++) {
416 snprintf(param, sizeof(param), "arg%d", i);
417 prov = gctl_get_asciiparam(req, param);
419 gctl_error(req, "No 'arg%d' argument.", i);
422 sc = g_eli_find_device(mp, prov);
425 * We ignore not attached providers, userland part will
428 G_ELI_DEBUG(1, "Skipping configuration of not attached "
429 "provider %s.", prov);
432 if (*boot && (sc->sc_flags & G_ELI_FLAG_BOOT)) {
433 G_ELI_DEBUG(1, "BOOT flag already configured for %s.",
436 } else if (!*boot && !(sc->sc_flags & G_ELI_FLAG_BOOT)) {
437 G_ELI_DEBUG(1, "BOOT flag not configured for %s.",
441 if (sc->sc_flags & G_ELI_FLAG_RO) {
442 gctl_error(req, "Cannot change configuration of "
443 "read-only provider %s.", prov);
446 cp = LIST_FIRST(&sc->sc_geom->consumer);
448 error = g_eli_read_metadata(mp, pp, &md);
451 "Cannot read metadata from %s (error=%d).",
457 md.md_flags |= G_ELI_FLAG_BOOT;
458 sc->sc_flags |= G_ELI_FLAG_BOOT;
460 md.md_flags &= ~G_ELI_FLAG_BOOT;
461 sc->sc_flags &= ~G_ELI_FLAG_BOOT;
464 sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO);
465 eli_metadata_encode(&md, sector);
466 error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
470 "Cannot store metadata on %s (error=%d).",
473 bzero(&md, sizeof(md));
474 bzero(sector, sizeof(sector));
480 g_eli_ctl_setkey(struct gctl_req *req, struct g_class *mp)
482 struct g_eli_softc *sc;
483 struct g_eli_metadata md;
484 struct g_provider *pp;
485 struct g_consumer *cp;
487 u_char *key, *mkeydst, *sector;
489 int keysize, nkey, error;
493 name = gctl_get_asciiparam(req, "arg0");
495 gctl_error(req, "No 'arg%u' argument.", 0);
498 sc = g_eli_find_device(mp, name);
500 gctl_error(req, "Provider %s is invalid.", name);
503 if (sc->sc_flags & G_ELI_FLAG_RO) {
504 gctl_error(req, "Cannot change keys for read-only provider.");
507 cp = LIST_FIRST(&sc->sc_geom->consumer);
510 error = g_eli_read_metadata(mp, pp, &md);
512 gctl_error(req, "Cannot read metadata from %s (error=%d).",
517 valp = gctl_get_paraml(req, "keyno", sizeof(*valp));
519 gctl_error(req, "No '%s' argument.", "keyno");
526 if (nkey < 0 || nkey >= G_ELI_MAXMKEYS) {
527 gctl_error(req, "Invalid '%s' argument.", "keyno");
531 valp = gctl_get_paraml(req, "iterations", sizeof(*valp));
533 gctl_error(req, "No '%s' argument.", "iterations");
536 /* Check if iterations number should and can be changed. */
538 if (bitcount32(md.md_keys) != 1) {
539 gctl_error(req, "To be able to use '-i' option, only "
540 "one key can be defined.");
543 if (md.md_keys != (1 << nkey)) {
544 gctl_error(req, "Only already defined key can be "
545 "changed when '-i' option is used.");
548 md.md_iterations = *valp;
551 key = gctl_get_param(req, "key", &keysize);
552 if (key == NULL || keysize != G_ELI_USERKEYLEN) {
553 bzero(&md, sizeof(md));
554 gctl_error(req, "No '%s' argument.", "key");
558 mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN;
559 md.md_keys |= (1 << nkey);
561 bcopy(sc->sc_mkey, mkeydst, sizeof(sc->sc_mkey));
563 /* Encrypt Master Key with the new key. */
564 error = g_eli_mkey_encrypt(md.md_ealgo, key, md.md_keylen, mkeydst);
565 bzero(key, sizeof(key));
567 bzero(&md, sizeof(md));
568 gctl_error(req, "Cannot encrypt Master Key (error=%d).", error);
572 sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO);
573 /* Store metadata with fresh key. */
574 eli_metadata_encode(&md, sector);
575 bzero(&md, sizeof(md));
576 error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
578 bzero(sector, sizeof(sector));
581 gctl_error(req, "Cannot store metadata on %s (error=%d).",
585 G_ELI_DEBUG(1, "Key %u changed on %s.", nkey, pp->name);
589 g_eli_ctl_delkey(struct gctl_req *req, struct g_class *mp)
591 struct g_eli_softc *sc;
592 struct g_eli_metadata md;
593 struct g_provider *pp;
594 struct g_consumer *cp;
596 u_char *mkeydst, *sector;
599 int error, nkey, *all, *force;
604 nkey = 0; /* fixes causeless gcc warning */
606 name = gctl_get_asciiparam(req, "arg0");
608 gctl_error(req, "No 'arg%u' argument.", 0);
611 sc = g_eli_find_device(mp, name);
613 gctl_error(req, "Provider %s is invalid.", name);
616 if (sc->sc_flags & G_ELI_FLAG_RO) {
617 gctl_error(req, "Cannot delete keys for read-only provider.");
620 cp = LIST_FIRST(&sc->sc_geom->consumer);
623 error = g_eli_read_metadata(mp, pp, &md);
625 gctl_error(req, "Cannot read metadata from %s (error=%d).",
630 all = gctl_get_paraml(req, "all", sizeof(*all));
632 gctl_error(req, "No '%s' argument.", "all");
637 mkeydst = md.md_mkeys;
638 keysize = sizeof(md.md_mkeys);
640 force = gctl_get_paraml(req, "force", sizeof(*force));
642 gctl_error(req, "No '%s' argument.", "force");
646 valp = gctl_get_paraml(req, "keyno", sizeof(*valp));
648 gctl_error(req, "No '%s' argument.", "keyno");
655 if (nkey < 0 || nkey >= G_ELI_MAXMKEYS) {
656 gctl_error(req, "Invalid '%s' argument.", "keyno");
659 if (!(md.md_keys & (1 << nkey)) && !*force) {
660 gctl_error(req, "Master Key %u is not set.", nkey);
663 md.md_keys &= ~(1 << nkey);
664 if (md.md_keys == 0 && !*force) {
665 gctl_error(req, "This is the last Master Key. Use '-f' "
666 "flag if you really want to remove it.");
669 mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN;
670 keysize = G_ELI_MKEYLEN;
673 sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO);
674 for (i = 0; i <= g_eli_overwrites; i++) {
675 if (i == g_eli_overwrites)
676 bzero(mkeydst, keysize);
678 arc4rand(mkeydst, keysize, 0);
679 /* Store metadata with destroyed key. */
680 eli_metadata_encode(&md, sector);
681 error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
684 G_ELI_DEBUG(0, "Cannot store metadata on %s "
685 "(error=%d).", pp->name, error);
688 * Flush write cache so we don't overwrite data N times in cache
689 * and only once on disk.
691 (void)g_io_flush(cp);
693 bzero(&md, sizeof(md));
694 bzero(sector, sizeof(sector));
697 G_ELI_DEBUG(1, "All keys removed from %s.", pp->name);
699 G_ELI_DEBUG(1, "Key %d removed from %s.", nkey, pp->name);
703 g_eli_suspend_one(struct g_eli_softc *sc, struct gctl_req *req)
705 struct g_eli_worker *wr;
709 KASSERT(sc != NULL, ("NULL sc"));
711 if (sc->sc_flags & G_ELI_FLAG_ONETIME) {
713 "Device %s is using one-time key, suspend not supported.",
718 mtx_lock(&sc->sc_queue_mtx);
719 if (sc->sc_flags & G_ELI_FLAG_SUSPEND) {
720 mtx_unlock(&sc->sc_queue_mtx);
721 gctl_error(req, "Device %s already suspended.",
725 sc->sc_flags |= G_ELI_FLAG_SUSPEND;
728 LIST_FOREACH(wr, &sc->sc_workers, w_next) {
734 /* Not all threads suspended. */
735 msleep(&sc->sc_workers, &sc->sc_queue_mtx, PRIBIO,
739 * Clear sensitive data on suspend, they will be recovered on resume.
741 bzero(sc->sc_mkey, sizeof(sc->sc_mkey));
742 g_eli_key_destroy(sc);
743 bzero(sc->sc_akey, sizeof(sc->sc_akey));
744 bzero(&sc->sc_akeyctx, sizeof(sc->sc_akeyctx));
745 bzero(sc->sc_ivkey, sizeof(sc->sc_ivkey));
746 bzero(&sc->sc_ivctx, sizeof(sc->sc_ivctx));
747 mtx_unlock(&sc->sc_queue_mtx);
748 G_ELI_DEBUG(0, "Device %s has been suspended.", sc->sc_name);
752 g_eli_ctl_suspend(struct gctl_req *req, struct g_class *mp)
754 struct g_eli_softc *sc;
759 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
761 gctl_error(req, "No '%s' argument.", "nargs");
764 all = gctl_get_paraml(req, "all", sizeof(*all));
766 gctl_error(req, "No '%s' argument.", "all");
769 if (!*all && *nargs == 0) {
770 gctl_error(req, "Too few arguments.");
775 struct g_geom *gp, *gp2;
777 LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) {
779 if (sc->sc_flags & G_ELI_FLAG_ONETIME) {
781 "Device %s is using one-time key, suspend not supported, skipping.",
785 g_eli_suspend_one(sc, req);
792 for (i = 0; i < *nargs; i++) {
793 snprintf(param, sizeof(param), "arg%d", i);
794 prov = gctl_get_asciiparam(req, param);
796 G_ELI_DEBUG(0, "No 'arg%d' argument.", i);
800 sc = g_eli_find_device(mp, prov);
802 G_ELI_DEBUG(0, "No such provider: %s.", prov);
805 g_eli_suspend_one(sc, req);
811 g_eli_ctl_resume(struct gctl_req *req, struct g_class *mp)
813 struct g_eli_metadata md;
814 struct g_eli_softc *sc;
815 struct g_provider *pp;
816 struct g_consumer *cp;
818 u_char *key, mkey[G_ELI_DATAIVKEYLEN];
819 int *nargs, keysize, error;
824 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
826 gctl_error(req, "No '%s' argument.", "nargs");
830 gctl_error(req, "Invalid number of arguments.");
834 name = gctl_get_asciiparam(req, "arg0");
836 gctl_error(req, "No 'arg%u' argument.", 0);
839 sc = g_eli_find_device(mp, name);
841 gctl_error(req, "Provider %s is invalid.", name);
844 cp = LIST_FIRST(&sc->sc_geom->consumer);
846 error = g_eli_read_metadata(mp, pp, &md);
848 gctl_error(req, "Cannot read metadata from %s (error=%d).",
852 if (md.md_keys == 0x00) {
853 bzero(&md, sizeof(md));
854 gctl_error(req, "No valid keys on %s.", pp->name);
858 key = gctl_get_param(req, "key", &keysize);
859 if (key == NULL || keysize != G_ELI_USERKEYLEN) {
860 bzero(&md, sizeof(md));
861 gctl_error(req, "No '%s' argument.", "key");
865 error = g_eli_mkey_decrypt(&md, key, mkey, &nkey);
868 bzero(&md, sizeof(md));
869 gctl_error(req, "Wrong key for %s.", pp->name);
871 } else if (error > 0) {
872 bzero(&md, sizeof(md));
873 gctl_error(req, "Cannot decrypt Master Key for %s (error=%d).",
877 G_ELI_DEBUG(1, "Using Master Key %u for %s.", nkey, pp->name);
879 mtx_lock(&sc->sc_queue_mtx);
880 if (!(sc->sc_flags & G_ELI_FLAG_SUSPEND))
881 gctl_error(req, "Device %s is not suspended.", name);
883 /* Restore sc_mkey, sc_ekeys, sc_akey and sc_ivkey. */
884 g_eli_mkey_propagate(sc, mkey);
885 sc->sc_flags &= ~G_ELI_FLAG_SUSPEND;
886 G_ELI_DEBUG(1, "Resumed %s.", pp->name);
889 mtx_unlock(&sc->sc_queue_mtx);
890 bzero(mkey, sizeof(mkey));
891 bzero(&md, sizeof(md));
895 g_eli_kill_one(struct g_eli_softc *sc)
897 struct g_provider *pp;
898 struct g_consumer *cp;
906 pp = LIST_FIRST(&sc->sc_geom->provider);
907 g_error_provider(pp, ENXIO);
909 cp = LIST_FIRST(&sc->sc_geom->consumer);
912 if (sc->sc_flags & G_ELI_FLAG_RO) {
913 G_ELI_DEBUG(0, "WARNING: Metadata won't be erased on read-only "
914 "provider: %s.", pp->name);
920 sector = malloc(pp->sectorsize, M_ELI, M_WAITOK);
921 for (i = 0; i <= g_eli_overwrites; i++) {
922 if (i == g_eli_overwrites)
923 bzero(sector, pp->sectorsize);
925 arc4rand(sector, pp->sectorsize, 0);
926 err = g_write_data(cp, pp->mediasize - pp->sectorsize,
927 sector, pp->sectorsize);
929 G_ELI_DEBUG(0, "Cannot erase metadata on %s "
930 "(error=%d).", pp->name, err);
935 * Flush write cache so we don't overwrite data N times
936 * in cache and only once on disk.
938 (void)g_io_flush(cp);
943 G_ELI_DEBUG(0, "%s has been killed.", pp->name);
944 g_eli_destroy(sc, TRUE);
949 g_eli_ctl_kill(struct gctl_req *req, struct g_class *mp)
956 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
958 gctl_error(req, "No '%s' argument.", "nargs");
961 all = gctl_get_paraml(req, "all", sizeof(*all));
963 gctl_error(req, "No '%s' argument.", "all");
966 if (!*all && *nargs == 0) {
967 gctl_error(req, "Too few arguments.");
972 struct g_geom *gp, *gp2;
974 LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) {
975 error = g_eli_kill_one(gp->softc);
977 gctl_error(req, "Not fully done.");
980 struct g_eli_softc *sc;
985 for (i = 0; i < *nargs; i++) {
986 snprintf(param, sizeof(param), "arg%d", i);
987 prov = gctl_get_asciiparam(req, param);
989 G_ELI_DEBUG(0, "No 'arg%d' argument.", i);
993 sc = g_eli_find_device(mp, prov);
995 G_ELI_DEBUG(0, "No such provider: %s.", prov);
998 error = g_eli_kill_one(sc);
1000 gctl_error(req, "Not fully done.");
1006 g_eli_config(struct gctl_req *req, struct g_class *mp, const char *verb)
1010 g_topology_assert();
1012 version = gctl_get_paraml(req, "version", sizeof(*version));
1013 if (version == NULL) {
1014 gctl_error(req, "No '%s' argument.", "version");
1017 while (*version != G_ELI_VERSION) {
1018 if (G_ELI_VERSION == G_ELI_VERSION_06 &&
1019 *version == G_ELI_VERSION_05) {
1023 gctl_error(req, "Userland and kernel parts are out of sync.");
1027 if (strcmp(verb, "attach") == 0)
1028 g_eli_ctl_attach(req, mp);
1029 else if (strcmp(verb, "detach") == 0 || strcmp(verb, "stop") == 0)
1030 g_eli_ctl_detach(req, mp);
1031 else if (strcmp(verb, "onetime") == 0)
1032 g_eli_ctl_onetime(req, mp);
1033 else if (strcmp(verb, "configure") == 0)
1034 g_eli_ctl_configure(req, mp);
1035 else if (strcmp(verb, "setkey") == 0)
1036 g_eli_ctl_setkey(req, mp);
1037 else if (strcmp(verb, "delkey") == 0)
1038 g_eli_ctl_delkey(req, mp);
1039 else if (strcmp(verb, "suspend") == 0)
1040 g_eli_ctl_suspend(req, mp);
1041 else if (strcmp(verb, "resume") == 0)
1042 g_eli_ctl_resume(req, mp);
1043 else if (strcmp(verb, "kill") == 0)
1044 g_eli_ctl_kill(req, mp);
1046 gctl_error(req, "Unknown verb.");