Deleted Added
full compact
g_eli_ctl.c (214118) g_eli_ctl.c (214225)
1/*-
2 * Copyright (c) 2005-2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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.
13 *
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
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2005-2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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.
13 *
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
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/geom/eli/g_eli_ctl.c 214118 2010-10-20 20:50:55Z pjd $");
28__FBSDID("$FreeBSD: head/sys/geom/eli/g_eli_ctl.c 214225 2010-10-22 22:13:11Z pjd $");
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/kernel.h>
33#include <sys/module.h>
34#include <sys/lock.h>
35#include <sys/mutex.h>
36#include <sys/bio.h>
37#include <sys/sysctl.h>
38#include <sys/malloc.h>
39#include <sys/kthread.h>
40#include <sys/proc.h>
41#include <sys/sched.h>
42#include <sys/uio.h>
43
44#include <vm/uma.h>
45
46#include <geom/geom.h>
47#include <geom/eli/g_eli.h>
48
49
50MALLOC_DECLARE(M_ELI);
51
52
53static void
54g_eli_ctl_attach(struct gctl_req *req, struct g_class *mp)
55{
56 struct g_eli_metadata md;
57 struct g_provider *pp;
58 const char *name;
59 u_char *key, mkey[G_ELI_DATAIVKEYLEN];
60 int *nargs, *detach, *readonly;
61 int keysize, error;
62 u_int nkey;
63
64 g_topology_assert();
65
66 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
67 if (nargs == NULL) {
68 gctl_error(req, "No '%s' argument.", "nargs");
69 return;
70 }
71 if (*nargs != 1) {
72 gctl_error(req, "Invalid number of arguments.");
73 return;
74 }
75
76 detach = gctl_get_paraml(req, "detach", sizeof(*detach));
77 if (detach == NULL) {
78 gctl_error(req, "No '%s' argument.", "detach");
79 return;
80 }
81
82 readonly = gctl_get_paraml(req, "readonly", sizeof(*readonly));
83 if (readonly == NULL) {
84 gctl_error(req, "No '%s' argument.", "readonly");
85 return;
86 }
87
88 name = gctl_get_asciiparam(req, "arg0");
89 if (name == NULL) {
90 gctl_error(req, "No 'arg%u' argument.", 0);
91 return;
92 }
93 if (strncmp(name, "/dev/", strlen("/dev/")) == 0)
94 name += strlen("/dev/");
95 pp = g_provider_by_name(name);
96 if (pp == NULL) {
97 gctl_error(req, "Provider %s is invalid.", name);
98 return;
99 }
100 error = g_eli_read_metadata(mp, pp, &md);
101 if (error != 0) {
102 gctl_error(req, "Cannot read metadata from %s (error=%d).",
103 name, error);
104 return;
105 }
106 if (md.md_keys == 0x00) {
107 bzero(&md, sizeof(md));
108 gctl_error(req, "No valid keys on %s.", pp->name);
109 return;
110 }
111
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");
116 return;
117 }
118
119 error = g_eli_mkey_decrypt(&md, key, mkey, &nkey);
120 bzero(key, keysize);
121 if (error == -1) {
122 bzero(&md, sizeof(md));
123 gctl_error(req, "Wrong key for %s.", pp->name);
124 return;
125 } else if (error > 0) {
126 bzero(&md, sizeof(md));
127 gctl_error(req, "Cannot decrypt Master Key for %s (error=%d).",
128 pp->name, error);
129 return;
130 }
131 G_ELI_DEBUG(1, "Using Master Key %u for %s.", nkey, pp->name);
132
133 if (*detach && *readonly) {
134 bzero(&md, sizeof(md));
135 gctl_error(req, "Options -d and -r are mutually exclusive.");
136 return;
137 }
138 if (*detach)
139 md.md_flags |= G_ELI_FLAG_WO_DETACH;
140 if (*readonly)
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));
145}
146
147static struct g_eli_softc *
148g_eli_find_device(struct g_class *mp, const char *prov)
149{
150 struct g_eli_softc *sc;
151 struct g_geom *gp;
152 struct g_provider *pp;
153 struct g_consumer *cp;
154
155 if (strncmp(prov, "/dev/", strlen("/dev/")) == 0)
156 prov += strlen("/dev/");
157 LIST_FOREACH(gp, &mp->geom, geom) {
158 sc = gp->softc;
159 if (sc == NULL)
160 continue;
161 pp = LIST_FIRST(&gp->provider);
162 if (pp != NULL && strcmp(pp->name, prov) == 0)
163 return (sc);
164 cp = LIST_FIRST(&gp->consumer);
165 if (cp != NULL && cp->provider != NULL &&
166 strcmp(cp->provider->name, prov) == 0) {
167 return (sc);
168 }
169 }
170 return (NULL);
171}
172
173static void
174g_eli_ctl_detach(struct gctl_req *req, struct g_class *mp)
175{
176 struct g_eli_softc *sc;
177 int *force, *last, *nargs, error;
178 const char *prov;
179 char param[16];
180 int i;
181
182 g_topology_assert();
183
184 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
185 if (nargs == NULL) {
186 gctl_error(req, "No '%s' argument.", "nargs");
187 return;
188 }
189 if (*nargs <= 0) {
190 gctl_error(req, "Missing device(s).");
191 return;
192 }
193 force = gctl_get_paraml(req, "force", sizeof(*force));
194 if (force == NULL) {
195 gctl_error(req, "No '%s' argument.", "force");
196 return;
197 }
198 last = gctl_get_paraml(req, "last", sizeof(*last));
199 if (last == NULL) {
200 gctl_error(req, "No '%s' argument.", "last");
201 return;
202 }
203
204 for (i = 0; i < *nargs; i++) {
205 snprintf(param, sizeof(param), "arg%d", i);
206 prov = gctl_get_asciiparam(req, param);
207 if (prov == NULL) {
208 gctl_error(req, "No 'arg%d' argument.", i);
209 return;
210 }
211 sc = g_eli_find_device(mp, prov);
212 if (sc == NULL) {
213 gctl_error(req, "No such device: %s.", prov);
214 return;
215 }
216 if (*last) {
217 sc->sc_flags |= G_ELI_FLAG_RW_DETACH;
218 sc->sc_geom->access = g_eli_access;
219 } else {
220 error = g_eli_destroy(sc, *force ? TRUE : FALSE);
221 if (error != 0) {
222 gctl_error(req,
223 "Cannot destroy device %s (error=%d).",
224 sc->sc_name, error);
225 return;
226 }
227 }
228 }
229}
230
231static void
232g_eli_ctl_onetime(struct gctl_req *req, struct g_class *mp)
233{
234 struct g_eli_metadata md;
235 struct g_provider *pp;
236 const char *name;
237 intmax_t *keylen, *sectorsize;
238 u_char mkey[G_ELI_DATAIVKEYLEN];
239 int *nargs, *detach;
240
241 g_topology_assert();
242 bzero(&md, sizeof(md));
243
244 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
245 if (nargs == NULL) {
246 gctl_error(req, "No '%s' argument.", "nargs");
247 return;
248 }
249 if (*nargs != 1) {
250 gctl_error(req, "Invalid number of arguments.");
251 return;
252 }
253
254 detach = gctl_get_paraml(req, "detach", sizeof(*detach));
255 if (detach == NULL) {
256 gctl_error(req, "No '%s' argument.", "detach");
257 return;
258 }
259
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;
263 if (*detach)
264 md.md_flags |= G_ELI_FLAG_WO_DETACH;
265
266 md.md_ealgo = CRYPTO_ALGORITHM_MIN - 1;
267 name = gctl_get_asciiparam(req, "aalgo");
268 if (name == NULL) {
269 gctl_error(req, "No '%s' argument.", "aalgo");
270 return;
271 }
272 if (*name != '\0') {
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;
277 } else {
278 /*
279 * For backward compatibility, check if the -a option
280 * was used to provide encryption algorithm.
281 */
282 md.md_ealgo = g_eli_str2ealgo(name);
283 if (md.md_ealgo < CRYPTO_ALGORITHM_MIN ||
284 md.md_ealgo > CRYPTO_ALGORITHM_MAX) {
285 gctl_error(req,
286 "Invalid authentication algorithm.");
287 return;
288 } else {
289 gctl_error(req, "warning: The -e option, not "
290 "the -a option is now used to specify "
291 "encryption algorithm to use.");
292 }
293 }
294 }
295
296 if (md.md_ealgo < CRYPTO_ALGORITHM_MIN ||
297 md.md_ealgo > CRYPTO_ALGORITHM_MAX) {
298 name = gctl_get_asciiparam(req, "ealgo");
299 if (name == NULL) {
300 gctl_error(req, "No '%s' argument.", "ealgo");
301 return;
302 }
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.");
307 return;
308 }
309 }
310
311 keylen = gctl_get_paraml(req, "keylen", sizeof(*keylen));
312 if (keylen == NULL) {
313 gctl_error(req, "No '%s' argument.", "keylen");
314 return;
315 }
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");
319 return;
320 }
321
322 /* Not important here. */
323 md.md_provsize = 0;
324 /* Not important here. */
325 bzero(md.md_salt, sizeof(md.md_salt));
326
327 md.md_keys = 0x01;
328 arc4rand(mkey, sizeof(mkey), 0);
329
330 /* Not important here. */
331 bzero(md.md_hash, sizeof(md.md_hash));
332
333 name = gctl_get_asciiparam(req, "arg0");
334 if (name == NULL) {
335 gctl_error(req, "No 'arg%u' argument.", 0);
336 return;
337 }
338 if (strncmp(name, "/dev/", strlen("/dev/")) == 0)
339 name += strlen("/dev/");
340 pp = g_provider_by_name(name);
341 if (pp == NULL) {
342 gctl_error(req, "Provider %s is invalid.", name);
343 return;
344 }
345
346 sectorsize = gctl_get_paraml(req, "sectorsize", sizeof(*sectorsize));
347 if (sectorsize == NULL) {
348 gctl_error(req, "No '%s' argument.", "sectorsize");
349 return;
350 }
351 if (*sectorsize == 0)
352 md.md_sectorsize = pp->sectorsize;
353 else {
354 if (*sectorsize < 0 || (*sectorsize % pp->sectorsize) != 0) {
355 gctl_error(req, "Invalid sector size.");
356 return;
357 }
358 if (*sectorsize > PAGE_SIZE) {
359 gctl_error(req, "warning: Using sectorsize bigger than "
360 "the page size!");
361 }
362 md.md_sectorsize = *sectorsize;
363 }
364
365 g_eli_create(req, mp, pp, &md, mkey, -1);
366 bzero(mkey, sizeof(mkey));
367 bzero(&md, sizeof(md));
368}
369
370static void
371g_eli_ctl_configure(struct gctl_req *req, struct g_class *mp)
372{
373 struct g_eli_softc *sc;
374 struct g_eli_metadata md;
375 struct g_provider *pp;
376 struct g_consumer *cp;
377 char param[16];
378 const char *prov;
379 u_char *sector;
380 int *nargs, *boot, *noboot;
381 int error;
382 u_int i;
383
384 g_topology_assert();
385
386 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
387 if (nargs == NULL) {
388 gctl_error(req, "No '%s' argument.", "nargs");
389 return;
390 }
391 if (*nargs <= 0) {
392 gctl_error(req, "Missing device(s).");
393 return;
394 }
395
396 boot = gctl_get_paraml(req, "boot", sizeof(*boot));
397 if (boot == NULL) {
398 gctl_error(req, "No '%s' argument.", "boot");
399 return;
400 }
401 noboot = gctl_get_paraml(req, "noboot", sizeof(*noboot));
402 if (noboot == NULL) {
403 gctl_error(req, "No '%s' argument.", "noboot");
404 return;
405 }
406 if (*boot && *noboot) {
407 gctl_error(req, "Options -b and -B are mutually exclusive.");
408 return;
409 }
410 if (!*boot && !*noboot) {
411 gctl_error(req, "No option given.");
412 return;
413 }
414
415 for (i = 0; i < *nargs; i++) {
416 snprintf(param, sizeof(param), "arg%d", i);
417 prov = gctl_get_asciiparam(req, param);
418 if (prov == NULL) {
419 gctl_error(req, "No 'arg%d' argument.", i);
420 return;
421 }
422 sc = g_eli_find_device(mp, prov);
423 if (sc == NULL) {
424 /*
425 * We ignore not attached providers, userland part will
426 * take care of them.
427 */
428 G_ELI_DEBUG(1, "Skipping configuration of not attached "
429 "provider %s.", prov);
430 continue;
431 }
432 if (*boot && (sc->sc_flags & G_ELI_FLAG_BOOT)) {
433 G_ELI_DEBUG(1, "BOOT flag already configured for %s.",
434 prov);
435 continue;
436 } else if (!*boot && !(sc->sc_flags & G_ELI_FLAG_BOOT)) {
437 G_ELI_DEBUG(1, "BOOT flag not configured for %s.",
438 prov);
439 continue;
440 }
441 if (sc->sc_flags & G_ELI_FLAG_RO) {
442 gctl_error(req, "Cannot change configuration of "
443 "read-only provider %s.", prov);
444 continue;
445 }
446 cp = LIST_FIRST(&sc->sc_geom->consumer);
447 pp = cp->provider;
448 error = g_eli_read_metadata(mp, pp, &md);
449 if (error != 0) {
450 gctl_error(req,
451 "Cannot read metadata from %s (error=%d).",
452 prov, error);
453 continue;
454 }
455
456 if (*boot) {
457 md.md_flags |= G_ELI_FLAG_BOOT;
458 sc->sc_flags |= G_ELI_FLAG_BOOT;
459 } else {
460 md.md_flags &= ~G_ELI_FLAG_BOOT;
461 sc->sc_flags &= ~G_ELI_FLAG_BOOT;
462 }
463
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,
467 pp->sectorsize);
468 if (error != 0) {
469 gctl_error(req,
470 "Cannot store metadata on %s (error=%d).",
471 prov, error);
472 }
473 bzero(&md, sizeof(md));
474 bzero(sector, sizeof(sector));
475 free(sector, M_ELI);
476 }
477}
478
479static void
480g_eli_ctl_setkey(struct gctl_req *req, struct g_class *mp)
481{
482 struct g_eli_softc *sc;
483 struct g_eli_metadata md;
484 struct g_provider *pp;
485 struct g_consumer *cp;
486 const char *name;
487 u_char *key, *mkeydst, *sector;
488 intmax_t *valp;
489 int keysize, nkey, error;
490
491 g_topology_assert();
492
493 name = gctl_get_asciiparam(req, "arg0");
494 if (name == NULL) {
495 gctl_error(req, "No 'arg%u' argument.", 0);
496 return;
497 }
498 sc = g_eli_find_device(mp, name);
499 if (sc == NULL) {
500 gctl_error(req, "Provider %s is invalid.", name);
501 return;
502 }
503 if (sc->sc_flags & G_ELI_FLAG_RO) {
504 gctl_error(req, "Cannot change keys for read-only provider.");
505 return;
506 }
507 cp = LIST_FIRST(&sc->sc_geom->consumer);
508 pp = cp->provider;
509
510 error = g_eli_read_metadata(mp, pp, &md);
511 if (error != 0) {
512 gctl_error(req, "Cannot read metadata from %s (error=%d).",
513 name, error);
514 return;
515 }
516
517 valp = gctl_get_paraml(req, "keyno", sizeof(*valp));
518 if (valp == NULL) {
519 gctl_error(req, "No '%s' argument.", "keyno");
520 return;
521 }
522 if (*valp != -1)
523 nkey = *valp;
524 else
525 nkey = sc->sc_nkey;
526 if (nkey < 0 || nkey >= G_ELI_MAXMKEYS) {
527 gctl_error(req, "Invalid '%s' argument.", "keyno");
528 return;
529 }
530
531 valp = gctl_get_paraml(req, "iterations", sizeof(*valp));
532 if (valp == NULL) {
533 gctl_error(req, "No '%s' argument.", "iterations");
534 return;
535 }
536 /* Check if iterations number should and can be changed. */
537 if (*valp != -1) {
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.");
541 return;
542 }
543 if (md.md_keys != (1 << nkey)) {
544 gctl_error(req, "Only already defined key can be "
545 "changed when '-i' option is used.");
546 return;
547 }
548 md.md_iterations = *valp;
549 }
550
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");
555 return;
556 }
557
558 mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN;
559 md.md_keys |= (1 << nkey);
560
561 bcopy(sc->sc_mkey, mkeydst, sizeof(sc->sc_mkey));
562
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));
566 if (error != 0) {
567 bzero(&md, sizeof(md));
568 gctl_error(req, "Cannot encrypt Master Key (error=%d).", error);
569 return;
570 }
571
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,
577 pp->sectorsize);
578 bzero(sector, sizeof(sector));
579 free(sector, M_ELI);
580 if (error != 0) {
581 gctl_error(req, "Cannot store metadata on %s (error=%d).",
582 pp->name, error);
583 return;
584 }
585 G_ELI_DEBUG(1, "Key %u changed on %s.", nkey, pp->name);
586}
587
588static void
589g_eli_ctl_delkey(struct gctl_req *req, struct g_class *mp)
590{
591 struct g_eli_softc *sc;
592 struct g_eli_metadata md;
593 struct g_provider *pp;
594 struct g_consumer *cp;
595 const char *name;
596 u_char *mkeydst, *sector;
597 intmax_t *valp;
598 size_t keysize;
599 int error, nkey, *all, *force;
600 u_int i;
601
602 g_topology_assert();
603
604 nkey = 0; /* fixes causeless gcc warning */
605
606 name = gctl_get_asciiparam(req, "arg0");
607 if (name == NULL) {
608 gctl_error(req, "No 'arg%u' argument.", 0);
609 return;
610 }
611 sc = g_eli_find_device(mp, name);
612 if (sc == NULL) {
613 gctl_error(req, "Provider %s is invalid.", name);
614 return;
615 }
616 if (sc->sc_flags & G_ELI_FLAG_RO) {
617 gctl_error(req, "Cannot delete keys for read-only provider.");
618 return;
619 }
620 cp = LIST_FIRST(&sc->sc_geom->consumer);
621 pp = cp->provider;
622
623 error = g_eli_read_metadata(mp, pp, &md);
624 if (error != 0) {
625 gctl_error(req, "Cannot read metadata from %s (error=%d).",
626 name, error);
627 return;
628 }
629
630 all = gctl_get_paraml(req, "all", sizeof(*all));
631 if (all == NULL) {
632 gctl_error(req, "No '%s' argument.", "all");
633 return;
634 }
635
636 if (*all) {
637 mkeydst = md.md_mkeys;
638 keysize = sizeof(md.md_mkeys);
639 } else {
640 force = gctl_get_paraml(req, "force", sizeof(*force));
641 if (force == NULL) {
642 gctl_error(req, "No '%s' argument.", "force");
643 return;
644 }
645
646 valp = gctl_get_paraml(req, "keyno", sizeof(*valp));
647 if (valp == NULL) {
648 gctl_error(req, "No '%s' argument.", "keyno");
649 return;
650 }
651 if (*valp != -1)
652 nkey = *valp;
653 else
654 nkey = sc->sc_nkey;
655 if (nkey < 0 || nkey >= G_ELI_MAXMKEYS) {
656 gctl_error(req, "Invalid '%s' argument.", "keyno");
657 return;
658 }
659 if (!(md.md_keys & (1 << nkey)) && !*force) {
660 gctl_error(req, "Master Key %u is not set.", nkey);
661 return;
662 }
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.");
667 return;
668 }
669 mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN;
670 keysize = G_ELI_MKEYLEN;
671 }
672
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);
677 else
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,
682 pp->sectorsize);
683 if (error != 0) {
684 G_ELI_DEBUG(0, "Cannot store metadata on %s "
685 "(error=%d).", pp->name, error);
686 }
687 /*
688 * Flush write cache so we don't overwrite data N times in cache
689 * and only once on disk.
690 */
691 (void)g_io_flush(cp);
692 }
693 bzero(&md, sizeof(md));
694 bzero(sector, sizeof(sector));
695 free(sector, M_ELI);
696 if (*all)
697 G_ELI_DEBUG(1, "All keys removed from %s.", pp->name);
698 else
699 G_ELI_DEBUG(1, "Key %d removed from %s.", nkey, pp->name);
700}
701
702static int
703g_eli_suspend_one(struct g_eli_softc *sc)
704{
705 struct g_eli_worker *wr;
706
707 g_topology_assert();
708
709 if (sc == NULL)
710 return (ENOENT);
711 if (sc->sc_flags & G_ELI_FLAG_ONETIME)
712 return (EOPNOTSUPP);
713
714 mtx_lock(&sc->sc_queue_mtx);
715 if (sc->sc_flags & G_ELI_FLAG_SUSPEND) {
716 mtx_unlock(&sc->sc_queue_mtx);
717 return (EALREADY);
718 }
719 sc->sc_flags |= G_ELI_FLAG_SUSPEND;
720 wakeup(sc);
721 for (;;) {
722 LIST_FOREACH(wr, &sc->sc_workers, w_next) {
723 if (wr->w_active)
724 break;
725 }
726 if (wr == NULL)
727 break;
728 /* Not all threads suspended. */
729 msleep(&sc->sc_workers, &sc->sc_queue_mtx, PRIBIO,
730 "geli:suspend", 0);
731 }
732 /*
733 * Clear sensitive data on suspend, they will be recovered on resume.
734 */
735 bzero(sc->sc_mkey, sizeof(sc->sc_mkey));
736 bzero(sc->sc_ekeys,
737 sc->sc_nekeys * (sizeof(uint8_t *) + G_ELI_DATAKEYLEN));
738 free(sc->sc_ekeys, M_ELI);
739 sc->sc_ekeys = NULL;
740 bzero(sc->sc_akey, sizeof(sc->sc_akey));
741 bzero(&sc->sc_akeyctx, sizeof(sc->sc_akeyctx));
742 bzero(sc->sc_ivkey, sizeof(sc->sc_ivkey));
743 bzero(&sc->sc_ivctx, sizeof(sc->sc_ivctx));
744 mtx_unlock(&sc->sc_queue_mtx);
745 G_ELI_DEBUG(0, "%s has been suspended.", sc->sc_name);
746 return (0);
747}
748
749static void
750g_eli_ctl_suspend(struct gctl_req *req, struct g_class *mp)
751{
752 struct g_eli_softc *sc;
753 int *all, *nargs;
754 int error;
755
756 g_topology_assert();
757
758 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
759 if (nargs == NULL) {
760 gctl_error(req, "No '%s' argument.", "nargs");
761 return;
762 }
763 all = gctl_get_paraml(req, "all", sizeof(*all));
764 if (all == NULL) {
765 gctl_error(req, "No '%s' argument.", "all");
766 return;
767 }
768 if (!*all && *nargs == 0) {
769 gctl_error(req, "Too few arguments.");
770 return;
771 }
772
773 if (*all) {
774 struct g_geom *gp, *gp2;
775
776 LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) {
777 sc = gp->softc;
778 if (sc->sc_flags & G_ELI_FLAG_ONETIME)
779 continue;
780 error = g_eli_suspend_one(sc);
781 if (error != 0)
782 gctl_error(req, "Not fully done.");
783 }
784 } else {
785 const char *prov;
786 char param[16];
787 int i;
788
789 for (i = 0; i < *nargs; i++) {
790 snprintf(param, sizeof(param), "arg%d", i);
791 prov = gctl_get_asciiparam(req, param);
792 if (prov == NULL) {
793 G_ELI_DEBUG(0, "No 'arg%d' argument.", i);
794 continue;
795 }
796
797 sc = g_eli_find_device(mp, prov);
798 if (sc == NULL) {
799 G_ELI_DEBUG(0, "No such provider: %s.", prov);
800 continue;
801 }
802 error = g_eli_suspend_one(sc);
803 if (error != 0)
804 gctl_error(req, "Not fully done.");
805 }
806 }
807}
808
809static void
810g_eli_ctl_resume(struct gctl_req *req, struct g_class *mp)
811{
812 struct g_eli_metadata md;
813 struct g_eli_softc *sc;
814 struct g_provider *pp;
815 struct g_consumer *cp;
816 const char *name;
817 u_char *key, mkey[G_ELI_DATAIVKEYLEN];
818 int *nargs, keysize, error;
819 u_int nkey;
820
821 g_topology_assert();
822
823 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
824 if (nargs == NULL) {
825 gctl_error(req, "No '%s' argument.", "nargs");
826 return;
827 }
828 if (*nargs != 1) {
829 gctl_error(req, "Invalid number of arguments.");
830 return;
831 }
832
833 name = gctl_get_asciiparam(req, "arg0");
834 if (name == NULL) {
835 gctl_error(req, "No 'arg%u' argument.", 0);
836 return;
837 }
838 sc = g_eli_find_device(mp, name);
839 if (sc == NULL) {
840 gctl_error(req, "Provider %s is invalid.", name);
841 return;
842 }
843 if (!(sc->sc_flags & G_ELI_FLAG_SUSPEND)) {
844 gctl_error(req, "Provider %s not suspended.", name);
845 return;
846 }
847 cp = LIST_FIRST(&sc->sc_geom->consumer);
848 pp = cp->provider;
849 error = g_eli_read_metadata(mp, pp, &md);
850 if (error != 0) {
851 gctl_error(req, "Cannot read metadata from %s (error=%d).",
852 name, error);
853 return;
854 }
855 if (md.md_keys == 0x00) {
856 bzero(&md, sizeof(md));
857 gctl_error(req, "No valid keys on %s.", pp->name);
858 return;
859 }
860
861 key = gctl_get_param(req, "key", &keysize);
862 if (key == NULL || keysize != G_ELI_USERKEYLEN) {
863 bzero(&md, sizeof(md));
864 gctl_error(req, "No '%s' argument.", "key");
865 return;
866 }
867
868 error = g_eli_mkey_decrypt(&md, key, mkey, &nkey);
869 bzero(key, keysize);
870 if (error == -1) {
871 bzero(&md, sizeof(md));
872 gctl_error(req, "Wrong key for %s.", pp->name);
873 return;
874 } else if (error > 0) {
875 bzero(&md, sizeof(md));
876 gctl_error(req, "Cannot decrypt Master Key for %s (error=%d).",
877 pp->name, error);
878 return;
879 }
880 G_ELI_DEBUG(1, "Using Master Key %u for %s.", nkey, pp->name);
881
882 mtx_lock(&sc->sc_queue_mtx);
883 /* Restore sc_mkey, sc_ekeys, sc_akey and sc_ivkey. */
884 g_eli_mkey_propagate(sc, mkey);
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/kernel.h>
33#include <sys/module.h>
34#include <sys/lock.h>
35#include <sys/mutex.h>
36#include <sys/bio.h>
37#include <sys/sysctl.h>
38#include <sys/malloc.h>
39#include <sys/kthread.h>
40#include <sys/proc.h>
41#include <sys/sched.h>
42#include <sys/uio.h>
43
44#include <vm/uma.h>
45
46#include <geom/geom.h>
47#include <geom/eli/g_eli.h>
48
49
50MALLOC_DECLARE(M_ELI);
51
52
53static void
54g_eli_ctl_attach(struct gctl_req *req, struct g_class *mp)
55{
56 struct g_eli_metadata md;
57 struct g_provider *pp;
58 const char *name;
59 u_char *key, mkey[G_ELI_DATAIVKEYLEN];
60 int *nargs, *detach, *readonly;
61 int keysize, error;
62 u_int nkey;
63
64 g_topology_assert();
65
66 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
67 if (nargs == NULL) {
68 gctl_error(req, "No '%s' argument.", "nargs");
69 return;
70 }
71 if (*nargs != 1) {
72 gctl_error(req, "Invalid number of arguments.");
73 return;
74 }
75
76 detach = gctl_get_paraml(req, "detach", sizeof(*detach));
77 if (detach == NULL) {
78 gctl_error(req, "No '%s' argument.", "detach");
79 return;
80 }
81
82 readonly = gctl_get_paraml(req, "readonly", sizeof(*readonly));
83 if (readonly == NULL) {
84 gctl_error(req, "No '%s' argument.", "readonly");
85 return;
86 }
87
88 name = gctl_get_asciiparam(req, "arg0");
89 if (name == NULL) {
90 gctl_error(req, "No 'arg%u' argument.", 0);
91 return;
92 }
93 if (strncmp(name, "/dev/", strlen("/dev/")) == 0)
94 name += strlen("/dev/");
95 pp = g_provider_by_name(name);
96 if (pp == NULL) {
97 gctl_error(req, "Provider %s is invalid.", name);
98 return;
99 }
100 error = g_eli_read_metadata(mp, pp, &md);
101 if (error != 0) {
102 gctl_error(req, "Cannot read metadata from %s (error=%d).",
103 name, error);
104 return;
105 }
106 if (md.md_keys == 0x00) {
107 bzero(&md, sizeof(md));
108 gctl_error(req, "No valid keys on %s.", pp->name);
109 return;
110 }
111
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");
116 return;
117 }
118
119 error = g_eli_mkey_decrypt(&md, key, mkey, &nkey);
120 bzero(key, keysize);
121 if (error == -1) {
122 bzero(&md, sizeof(md));
123 gctl_error(req, "Wrong key for %s.", pp->name);
124 return;
125 } else if (error > 0) {
126 bzero(&md, sizeof(md));
127 gctl_error(req, "Cannot decrypt Master Key for %s (error=%d).",
128 pp->name, error);
129 return;
130 }
131 G_ELI_DEBUG(1, "Using Master Key %u for %s.", nkey, pp->name);
132
133 if (*detach && *readonly) {
134 bzero(&md, sizeof(md));
135 gctl_error(req, "Options -d and -r are mutually exclusive.");
136 return;
137 }
138 if (*detach)
139 md.md_flags |= G_ELI_FLAG_WO_DETACH;
140 if (*readonly)
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));
145}
146
147static struct g_eli_softc *
148g_eli_find_device(struct g_class *mp, const char *prov)
149{
150 struct g_eli_softc *sc;
151 struct g_geom *gp;
152 struct g_provider *pp;
153 struct g_consumer *cp;
154
155 if (strncmp(prov, "/dev/", strlen("/dev/")) == 0)
156 prov += strlen("/dev/");
157 LIST_FOREACH(gp, &mp->geom, geom) {
158 sc = gp->softc;
159 if (sc == NULL)
160 continue;
161 pp = LIST_FIRST(&gp->provider);
162 if (pp != NULL && strcmp(pp->name, prov) == 0)
163 return (sc);
164 cp = LIST_FIRST(&gp->consumer);
165 if (cp != NULL && cp->provider != NULL &&
166 strcmp(cp->provider->name, prov) == 0) {
167 return (sc);
168 }
169 }
170 return (NULL);
171}
172
173static void
174g_eli_ctl_detach(struct gctl_req *req, struct g_class *mp)
175{
176 struct g_eli_softc *sc;
177 int *force, *last, *nargs, error;
178 const char *prov;
179 char param[16];
180 int i;
181
182 g_topology_assert();
183
184 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
185 if (nargs == NULL) {
186 gctl_error(req, "No '%s' argument.", "nargs");
187 return;
188 }
189 if (*nargs <= 0) {
190 gctl_error(req, "Missing device(s).");
191 return;
192 }
193 force = gctl_get_paraml(req, "force", sizeof(*force));
194 if (force == NULL) {
195 gctl_error(req, "No '%s' argument.", "force");
196 return;
197 }
198 last = gctl_get_paraml(req, "last", sizeof(*last));
199 if (last == NULL) {
200 gctl_error(req, "No '%s' argument.", "last");
201 return;
202 }
203
204 for (i = 0; i < *nargs; i++) {
205 snprintf(param, sizeof(param), "arg%d", i);
206 prov = gctl_get_asciiparam(req, param);
207 if (prov == NULL) {
208 gctl_error(req, "No 'arg%d' argument.", i);
209 return;
210 }
211 sc = g_eli_find_device(mp, prov);
212 if (sc == NULL) {
213 gctl_error(req, "No such device: %s.", prov);
214 return;
215 }
216 if (*last) {
217 sc->sc_flags |= G_ELI_FLAG_RW_DETACH;
218 sc->sc_geom->access = g_eli_access;
219 } else {
220 error = g_eli_destroy(sc, *force ? TRUE : FALSE);
221 if (error != 0) {
222 gctl_error(req,
223 "Cannot destroy device %s (error=%d).",
224 sc->sc_name, error);
225 return;
226 }
227 }
228 }
229}
230
231static void
232g_eli_ctl_onetime(struct gctl_req *req, struct g_class *mp)
233{
234 struct g_eli_metadata md;
235 struct g_provider *pp;
236 const char *name;
237 intmax_t *keylen, *sectorsize;
238 u_char mkey[G_ELI_DATAIVKEYLEN];
239 int *nargs, *detach;
240
241 g_topology_assert();
242 bzero(&md, sizeof(md));
243
244 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
245 if (nargs == NULL) {
246 gctl_error(req, "No '%s' argument.", "nargs");
247 return;
248 }
249 if (*nargs != 1) {
250 gctl_error(req, "Invalid number of arguments.");
251 return;
252 }
253
254 detach = gctl_get_paraml(req, "detach", sizeof(*detach));
255 if (detach == NULL) {
256 gctl_error(req, "No '%s' argument.", "detach");
257 return;
258 }
259
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;
263 if (*detach)
264 md.md_flags |= G_ELI_FLAG_WO_DETACH;
265
266 md.md_ealgo = CRYPTO_ALGORITHM_MIN - 1;
267 name = gctl_get_asciiparam(req, "aalgo");
268 if (name == NULL) {
269 gctl_error(req, "No '%s' argument.", "aalgo");
270 return;
271 }
272 if (*name != '\0') {
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;
277 } else {
278 /*
279 * For backward compatibility, check if the -a option
280 * was used to provide encryption algorithm.
281 */
282 md.md_ealgo = g_eli_str2ealgo(name);
283 if (md.md_ealgo < CRYPTO_ALGORITHM_MIN ||
284 md.md_ealgo > CRYPTO_ALGORITHM_MAX) {
285 gctl_error(req,
286 "Invalid authentication algorithm.");
287 return;
288 } else {
289 gctl_error(req, "warning: The -e option, not "
290 "the -a option is now used to specify "
291 "encryption algorithm to use.");
292 }
293 }
294 }
295
296 if (md.md_ealgo < CRYPTO_ALGORITHM_MIN ||
297 md.md_ealgo > CRYPTO_ALGORITHM_MAX) {
298 name = gctl_get_asciiparam(req, "ealgo");
299 if (name == NULL) {
300 gctl_error(req, "No '%s' argument.", "ealgo");
301 return;
302 }
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.");
307 return;
308 }
309 }
310
311 keylen = gctl_get_paraml(req, "keylen", sizeof(*keylen));
312 if (keylen == NULL) {
313 gctl_error(req, "No '%s' argument.", "keylen");
314 return;
315 }
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");
319 return;
320 }
321
322 /* Not important here. */
323 md.md_provsize = 0;
324 /* Not important here. */
325 bzero(md.md_salt, sizeof(md.md_salt));
326
327 md.md_keys = 0x01;
328 arc4rand(mkey, sizeof(mkey), 0);
329
330 /* Not important here. */
331 bzero(md.md_hash, sizeof(md.md_hash));
332
333 name = gctl_get_asciiparam(req, "arg0");
334 if (name == NULL) {
335 gctl_error(req, "No 'arg%u' argument.", 0);
336 return;
337 }
338 if (strncmp(name, "/dev/", strlen("/dev/")) == 0)
339 name += strlen("/dev/");
340 pp = g_provider_by_name(name);
341 if (pp == NULL) {
342 gctl_error(req, "Provider %s is invalid.", name);
343 return;
344 }
345
346 sectorsize = gctl_get_paraml(req, "sectorsize", sizeof(*sectorsize));
347 if (sectorsize == NULL) {
348 gctl_error(req, "No '%s' argument.", "sectorsize");
349 return;
350 }
351 if (*sectorsize == 0)
352 md.md_sectorsize = pp->sectorsize;
353 else {
354 if (*sectorsize < 0 || (*sectorsize % pp->sectorsize) != 0) {
355 gctl_error(req, "Invalid sector size.");
356 return;
357 }
358 if (*sectorsize > PAGE_SIZE) {
359 gctl_error(req, "warning: Using sectorsize bigger than "
360 "the page size!");
361 }
362 md.md_sectorsize = *sectorsize;
363 }
364
365 g_eli_create(req, mp, pp, &md, mkey, -1);
366 bzero(mkey, sizeof(mkey));
367 bzero(&md, sizeof(md));
368}
369
370static void
371g_eli_ctl_configure(struct gctl_req *req, struct g_class *mp)
372{
373 struct g_eli_softc *sc;
374 struct g_eli_metadata md;
375 struct g_provider *pp;
376 struct g_consumer *cp;
377 char param[16];
378 const char *prov;
379 u_char *sector;
380 int *nargs, *boot, *noboot;
381 int error;
382 u_int i;
383
384 g_topology_assert();
385
386 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
387 if (nargs == NULL) {
388 gctl_error(req, "No '%s' argument.", "nargs");
389 return;
390 }
391 if (*nargs <= 0) {
392 gctl_error(req, "Missing device(s).");
393 return;
394 }
395
396 boot = gctl_get_paraml(req, "boot", sizeof(*boot));
397 if (boot == NULL) {
398 gctl_error(req, "No '%s' argument.", "boot");
399 return;
400 }
401 noboot = gctl_get_paraml(req, "noboot", sizeof(*noboot));
402 if (noboot == NULL) {
403 gctl_error(req, "No '%s' argument.", "noboot");
404 return;
405 }
406 if (*boot && *noboot) {
407 gctl_error(req, "Options -b and -B are mutually exclusive.");
408 return;
409 }
410 if (!*boot && !*noboot) {
411 gctl_error(req, "No option given.");
412 return;
413 }
414
415 for (i = 0; i < *nargs; i++) {
416 snprintf(param, sizeof(param), "arg%d", i);
417 prov = gctl_get_asciiparam(req, param);
418 if (prov == NULL) {
419 gctl_error(req, "No 'arg%d' argument.", i);
420 return;
421 }
422 sc = g_eli_find_device(mp, prov);
423 if (sc == NULL) {
424 /*
425 * We ignore not attached providers, userland part will
426 * take care of them.
427 */
428 G_ELI_DEBUG(1, "Skipping configuration of not attached "
429 "provider %s.", prov);
430 continue;
431 }
432 if (*boot && (sc->sc_flags & G_ELI_FLAG_BOOT)) {
433 G_ELI_DEBUG(1, "BOOT flag already configured for %s.",
434 prov);
435 continue;
436 } else if (!*boot && !(sc->sc_flags & G_ELI_FLAG_BOOT)) {
437 G_ELI_DEBUG(1, "BOOT flag not configured for %s.",
438 prov);
439 continue;
440 }
441 if (sc->sc_flags & G_ELI_FLAG_RO) {
442 gctl_error(req, "Cannot change configuration of "
443 "read-only provider %s.", prov);
444 continue;
445 }
446 cp = LIST_FIRST(&sc->sc_geom->consumer);
447 pp = cp->provider;
448 error = g_eli_read_metadata(mp, pp, &md);
449 if (error != 0) {
450 gctl_error(req,
451 "Cannot read metadata from %s (error=%d).",
452 prov, error);
453 continue;
454 }
455
456 if (*boot) {
457 md.md_flags |= G_ELI_FLAG_BOOT;
458 sc->sc_flags |= G_ELI_FLAG_BOOT;
459 } else {
460 md.md_flags &= ~G_ELI_FLAG_BOOT;
461 sc->sc_flags &= ~G_ELI_FLAG_BOOT;
462 }
463
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,
467 pp->sectorsize);
468 if (error != 0) {
469 gctl_error(req,
470 "Cannot store metadata on %s (error=%d).",
471 prov, error);
472 }
473 bzero(&md, sizeof(md));
474 bzero(sector, sizeof(sector));
475 free(sector, M_ELI);
476 }
477}
478
479static void
480g_eli_ctl_setkey(struct gctl_req *req, struct g_class *mp)
481{
482 struct g_eli_softc *sc;
483 struct g_eli_metadata md;
484 struct g_provider *pp;
485 struct g_consumer *cp;
486 const char *name;
487 u_char *key, *mkeydst, *sector;
488 intmax_t *valp;
489 int keysize, nkey, error;
490
491 g_topology_assert();
492
493 name = gctl_get_asciiparam(req, "arg0");
494 if (name == NULL) {
495 gctl_error(req, "No 'arg%u' argument.", 0);
496 return;
497 }
498 sc = g_eli_find_device(mp, name);
499 if (sc == NULL) {
500 gctl_error(req, "Provider %s is invalid.", name);
501 return;
502 }
503 if (sc->sc_flags & G_ELI_FLAG_RO) {
504 gctl_error(req, "Cannot change keys for read-only provider.");
505 return;
506 }
507 cp = LIST_FIRST(&sc->sc_geom->consumer);
508 pp = cp->provider;
509
510 error = g_eli_read_metadata(mp, pp, &md);
511 if (error != 0) {
512 gctl_error(req, "Cannot read metadata from %s (error=%d).",
513 name, error);
514 return;
515 }
516
517 valp = gctl_get_paraml(req, "keyno", sizeof(*valp));
518 if (valp == NULL) {
519 gctl_error(req, "No '%s' argument.", "keyno");
520 return;
521 }
522 if (*valp != -1)
523 nkey = *valp;
524 else
525 nkey = sc->sc_nkey;
526 if (nkey < 0 || nkey >= G_ELI_MAXMKEYS) {
527 gctl_error(req, "Invalid '%s' argument.", "keyno");
528 return;
529 }
530
531 valp = gctl_get_paraml(req, "iterations", sizeof(*valp));
532 if (valp == NULL) {
533 gctl_error(req, "No '%s' argument.", "iterations");
534 return;
535 }
536 /* Check if iterations number should and can be changed. */
537 if (*valp != -1) {
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.");
541 return;
542 }
543 if (md.md_keys != (1 << nkey)) {
544 gctl_error(req, "Only already defined key can be "
545 "changed when '-i' option is used.");
546 return;
547 }
548 md.md_iterations = *valp;
549 }
550
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");
555 return;
556 }
557
558 mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN;
559 md.md_keys |= (1 << nkey);
560
561 bcopy(sc->sc_mkey, mkeydst, sizeof(sc->sc_mkey));
562
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));
566 if (error != 0) {
567 bzero(&md, sizeof(md));
568 gctl_error(req, "Cannot encrypt Master Key (error=%d).", error);
569 return;
570 }
571
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,
577 pp->sectorsize);
578 bzero(sector, sizeof(sector));
579 free(sector, M_ELI);
580 if (error != 0) {
581 gctl_error(req, "Cannot store metadata on %s (error=%d).",
582 pp->name, error);
583 return;
584 }
585 G_ELI_DEBUG(1, "Key %u changed on %s.", nkey, pp->name);
586}
587
588static void
589g_eli_ctl_delkey(struct gctl_req *req, struct g_class *mp)
590{
591 struct g_eli_softc *sc;
592 struct g_eli_metadata md;
593 struct g_provider *pp;
594 struct g_consumer *cp;
595 const char *name;
596 u_char *mkeydst, *sector;
597 intmax_t *valp;
598 size_t keysize;
599 int error, nkey, *all, *force;
600 u_int i;
601
602 g_topology_assert();
603
604 nkey = 0; /* fixes causeless gcc warning */
605
606 name = gctl_get_asciiparam(req, "arg0");
607 if (name == NULL) {
608 gctl_error(req, "No 'arg%u' argument.", 0);
609 return;
610 }
611 sc = g_eli_find_device(mp, name);
612 if (sc == NULL) {
613 gctl_error(req, "Provider %s is invalid.", name);
614 return;
615 }
616 if (sc->sc_flags & G_ELI_FLAG_RO) {
617 gctl_error(req, "Cannot delete keys for read-only provider.");
618 return;
619 }
620 cp = LIST_FIRST(&sc->sc_geom->consumer);
621 pp = cp->provider;
622
623 error = g_eli_read_metadata(mp, pp, &md);
624 if (error != 0) {
625 gctl_error(req, "Cannot read metadata from %s (error=%d).",
626 name, error);
627 return;
628 }
629
630 all = gctl_get_paraml(req, "all", sizeof(*all));
631 if (all == NULL) {
632 gctl_error(req, "No '%s' argument.", "all");
633 return;
634 }
635
636 if (*all) {
637 mkeydst = md.md_mkeys;
638 keysize = sizeof(md.md_mkeys);
639 } else {
640 force = gctl_get_paraml(req, "force", sizeof(*force));
641 if (force == NULL) {
642 gctl_error(req, "No '%s' argument.", "force");
643 return;
644 }
645
646 valp = gctl_get_paraml(req, "keyno", sizeof(*valp));
647 if (valp == NULL) {
648 gctl_error(req, "No '%s' argument.", "keyno");
649 return;
650 }
651 if (*valp != -1)
652 nkey = *valp;
653 else
654 nkey = sc->sc_nkey;
655 if (nkey < 0 || nkey >= G_ELI_MAXMKEYS) {
656 gctl_error(req, "Invalid '%s' argument.", "keyno");
657 return;
658 }
659 if (!(md.md_keys & (1 << nkey)) && !*force) {
660 gctl_error(req, "Master Key %u is not set.", nkey);
661 return;
662 }
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.");
667 return;
668 }
669 mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN;
670 keysize = G_ELI_MKEYLEN;
671 }
672
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);
677 else
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,
682 pp->sectorsize);
683 if (error != 0) {
684 G_ELI_DEBUG(0, "Cannot store metadata on %s "
685 "(error=%d).", pp->name, error);
686 }
687 /*
688 * Flush write cache so we don't overwrite data N times in cache
689 * and only once on disk.
690 */
691 (void)g_io_flush(cp);
692 }
693 bzero(&md, sizeof(md));
694 bzero(sector, sizeof(sector));
695 free(sector, M_ELI);
696 if (*all)
697 G_ELI_DEBUG(1, "All keys removed from %s.", pp->name);
698 else
699 G_ELI_DEBUG(1, "Key %d removed from %s.", nkey, pp->name);
700}
701
702static int
703g_eli_suspend_one(struct g_eli_softc *sc)
704{
705 struct g_eli_worker *wr;
706
707 g_topology_assert();
708
709 if (sc == NULL)
710 return (ENOENT);
711 if (sc->sc_flags & G_ELI_FLAG_ONETIME)
712 return (EOPNOTSUPP);
713
714 mtx_lock(&sc->sc_queue_mtx);
715 if (sc->sc_flags & G_ELI_FLAG_SUSPEND) {
716 mtx_unlock(&sc->sc_queue_mtx);
717 return (EALREADY);
718 }
719 sc->sc_flags |= G_ELI_FLAG_SUSPEND;
720 wakeup(sc);
721 for (;;) {
722 LIST_FOREACH(wr, &sc->sc_workers, w_next) {
723 if (wr->w_active)
724 break;
725 }
726 if (wr == NULL)
727 break;
728 /* Not all threads suspended. */
729 msleep(&sc->sc_workers, &sc->sc_queue_mtx, PRIBIO,
730 "geli:suspend", 0);
731 }
732 /*
733 * Clear sensitive data on suspend, they will be recovered on resume.
734 */
735 bzero(sc->sc_mkey, sizeof(sc->sc_mkey));
736 bzero(sc->sc_ekeys,
737 sc->sc_nekeys * (sizeof(uint8_t *) + G_ELI_DATAKEYLEN));
738 free(sc->sc_ekeys, M_ELI);
739 sc->sc_ekeys = NULL;
740 bzero(sc->sc_akey, sizeof(sc->sc_akey));
741 bzero(&sc->sc_akeyctx, sizeof(sc->sc_akeyctx));
742 bzero(sc->sc_ivkey, sizeof(sc->sc_ivkey));
743 bzero(&sc->sc_ivctx, sizeof(sc->sc_ivctx));
744 mtx_unlock(&sc->sc_queue_mtx);
745 G_ELI_DEBUG(0, "%s has been suspended.", sc->sc_name);
746 return (0);
747}
748
749static void
750g_eli_ctl_suspend(struct gctl_req *req, struct g_class *mp)
751{
752 struct g_eli_softc *sc;
753 int *all, *nargs;
754 int error;
755
756 g_topology_assert();
757
758 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
759 if (nargs == NULL) {
760 gctl_error(req, "No '%s' argument.", "nargs");
761 return;
762 }
763 all = gctl_get_paraml(req, "all", sizeof(*all));
764 if (all == NULL) {
765 gctl_error(req, "No '%s' argument.", "all");
766 return;
767 }
768 if (!*all && *nargs == 0) {
769 gctl_error(req, "Too few arguments.");
770 return;
771 }
772
773 if (*all) {
774 struct g_geom *gp, *gp2;
775
776 LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) {
777 sc = gp->softc;
778 if (sc->sc_flags & G_ELI_FLAG_ONETIME)
779 continue;
780 error = g_eli_suspend_one(sc);
781 if (error != 0)
782 gctl_error(req, "Not fully done.");
783 }
784 } else {
785 const char *prov;
786 char param[16];
787 int i;
788
789 for (i = 0; i < *nargs; i++) {
790 snprintf(param, sizeof(param), "arg%d", i);
791 prov = gctl_get_asciiparam(req, param);
792 if (prov == NULL) {
793 G_ELI_DEBUG(0, "No 'arg%d' argument.", i);
794 continue;
795 }
796
797 sc = g_eli_find_device(mp, prov);
798 if (sc == NULL) {
799 G_ELI_DEBUG(0, "No such provider: %s.", prov);
800 continue;
801 }
802 error = g_eli_suspend_one(sc);
803 if (error != 0)
804 gctl_error(req, "Not fully done.");
805 }
806 }
807}
808
809static void
810g_eli_ctl_resume(struct gctl_req *req, struct g_class *mp)
811{
812 struct g_eli_metadata md;
813 struct g_eli_softc *sc;
814 struct g_provider *pp;
815 struct g_consumer *cp;
816 const char *name;
817 u_char *key, mkey[G_ELI_DATAIVKEYLEN];
818 int *nargs, keysize, error;
819 u_int nkey;
820
821 g_topology_assert();
822
823 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
824 if (nargs == NULL) {
825 gctl_error(req, "No '%s' argument.", "nargs");
826 return;
827 }
828 if (*nargs != 1) {
829 gctl_error(req, "Invalid number of arguments.");
830 return;
831 }
832
833 name = gctl_get_asciiparam(req, "arg0");
834 if (name == NULL) {
835 gctl_error(req, "No 'arg%u' argument.", 0);
836 return;
837 }
838 sc = g_eli_find_device(mp, name);
839 if (sc == NULL) {
840 gctl_error(req, "Provider %s is invalid.", name);
841 return;
842 }
843 if (!(sc->sc_flags & G_ELI_FLAG_SUSPEND)) {
844 gctl_error(req, "Provider %s not suspended.", name);
845 return;
846 }
847 cp = LIST_FIRST(&sc->sc_geom->consumer);
848 pp = cp->provider;
849 error = g_eli_read_metadata(mp, pp, &md);
850 if (error != 0) {
851 gctl_error(req, "Cannot read metadata from %s (error=%d).",
852 name, error);
853 return;
854 }
855 if (md.md_keys == 0x00) {
856 bzero(&md, sizeof(md));
857 gctl_error(req, "No valid keys on %s.", pp->name);
858 return;
859 }
860
861 key = gctl_get_param(req, "key", &keysize);
862 if (key == NULL || keysize != G_ELI_USERKEYLEN) {
863 bzero(&md, sizeof(md));
864 gctl_error(req, "No '%s' argument.", "key");
865 return;
866 }
867
868 error = g_eli_mkey_decrypt(&md, key, mkey, &nkey);
869 bzero(key, keysize);
870 if (error == -1) {
871 bzero(&md, sizeof(md));
872 gctl_error(req, "Wrong key for %s.", pp->name);
873 return;
874 } else if (error > 0) {
875 bzero(&md, sizeof(md));
876 gctl_error(req, "Cannot decrypt Master Key for %s (error=%d).",
877 pp->name, error);
878 return;
879 }
880 G_ELI_DEBUG(1, "Using Master Key %u for %s.", nkey, pp->name);
881
882 mtx_lock(&sc->sc_queue_mtx);
883 /* Restore sc_mkey, sc_ekeys, sc_akey and sc_ivkey. */
884 g_eli_mkey_propagate(sc, mkey);
885 bzero(mkey, sizeof(mkey));
886 bzero(&md, sizeof(md));
887 /* Restore sc_akeyctx. */
888 if (sc->sc_flags & G_ELI_FLAG_AUTH) {
889 SHA256_Init(&sc->sc_akeyctx);
890 SHA256_Update(&sc->sc_akeyctx, sc->sc_akey,
891 sizeof(sc->sc_akey));
892 }
893 /* Restore sc_ivctx. */
894 switch (sc->sc_ealgo) {
895 case CRYPTO_AES_XTS:
896 break;
897 default:
898 SHA256_Init(&sc->sc_ivctx);
899 SHA256_Update(&sc->sc_ivctx, sc->sc_ivkey,
900 sizeof(sc->sc_ivkey));
901 break;
902 }
903 sc->sc_flags &= ~G_ELI_FLAG_SUSPEND;
904 mtx_unlock(&sc->sc_queue_mtx);
885 sc->sc_flags &= ~G_ELI_FLAG_SUSPEND;
886 mtx_unlock(&sc->sc_queue_mtx);
887 bzero(mkey, sizeof(mkey));
888 bzero(&md, sizeof(md));
905 G_ELI_DEBUG(1, "Resumed %s.", pp->name);
906 wakeup(sc);
907}
908
909static int
910g_eli_kill_one(struct g_eli_softc *sc)
911{
912 struct g_provider *pp;
913 struct g_consumer *cp;
914 int error = 0;
915
916 g_topology_assert();
917
918 if (sc == NULL)
919 return (ENOENT);
920
921 pp = LIST_FIRST(&sc->sc_geom->provider);
922 g_error_provider(pp, ENXIO);
923
924 cp = LIST_FIRST(&sc->sc_geom->consumer);
925 pp = cp->provider;
926
927 if (sc->sc_flags & G_ELI_FLAG_RO) {
928 G_ELI_DEBUG(0, "WARNING: Metadata won't be erased on read-only "
929 "provider: %s.", pp->name);
930 } else {
931 u_char *sector;
932 u_int i;
933 int err;
934
935 sector = malloc(pp->sectorsize, M_ELI, M_WAITOK);
936 for (i = 0; i <= g_eli_overwrites; i++) {
937 if (i == g_eli_overwrites)
938 bzero(sector, pp->sectorsize);
939 else
940 arc4rand(sector, pp->sectorsize, 0);
941 err = g_write_data(cp, pp->mediasize - pp->sectorsize,
942 sector, pp->sectorsize);
943 if (err != 0) {
944 G_ELI_DEBUG(0, "Cannot erase metadata on %s "
945 "(error=%d).", pp->name, err);
946 if (error == 0)
947 error = err;
948 }
949 /*
950 * Flush write cache so we don't overwrite data N times
951 * in cache and only once on disk.
952 */
953 (void)g_io_flush(cp);
954 }
955 free(sector, M_ELI);
956 }
957 if (error == 0)
958 G_ELI_DEBUG(0, "%s has been killed.", pp->name);
959 g_eli_destroy(sc, TRUE);
960 return (error);
961}
962
963static void
964g_eli_ctl_kill(struct gctl_req *req, struct g_class *mp)
965{
966 int *all, *nargs;
967 int error;
968
969 g_topology_assert();
970
971 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
972 if (nargs == NULL) {
973 gctl_error(req, "No '%s' argument.", "nargs");
974 return;
975 }
976 all = gctl_get_paraml(req, "all", sizeof(*all));
977 if (all == NULL) {
978 gctl_error(req, "No '%s' argument.", "all");
979 return;
980 }
981 if (!*all && *nargs == 0) {
982 gctl_error(req, "Too few arguments.");
983 return;
984 }
985
986 if (*all) {
987 struct g_geom *gp, *gp2;
988
989 LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) {
990 error = g_eli_kill_one(gp->softc);
991 if (error != 0)
992 gctl_error(req, "Not fully done.");
993 }
994 } else {
995 struct g_eli_softc *sc;
996 const char *prov;
997 char param[16];
998 int i;
999
1000 for (i = 0; i < *nargs; i++) {
1001 snprintf(param, sizeof(param), "arg%d", i);
1002 prov = gctl_get_asciiparam(req, param);
1003 if (prov == NULL) {
1004 G_ELI_DEBUG(0, "No 'arg%d' argument.", i);
1005 continue;
1006 }
1007
1008 sc = g_eli_find_device(mp, prov);
1009 if (sc == NULL) {
1010 G_ELI_DEBUG(0, "No such provider: %s.", prov);
1011 continue;
1012 }
1013 error = g_eli_kill_one(sc);
1014 if (error != 0)
1015 gctl_error(req, "Not fully done.");
1016 }
1017 }
1018}
1019
1020void
1021g_eli_config(struct gctl_req *req, struct g_class *mp, const char *verb)
1022{
1023 uint32_t *version;
1024
1025 g_topology_assert();
1026
1027 version = gctl_get_paraml(req, "version", sizeof(*version));
1028 if (version == NULL) {
1029 gctl_error(req, "No '%s' argument.", "version");
1030 return;
1031 }
1032 if (*version != G_ELI_VERSION) {
1033 gctl_error(req, "Userland and kernel parts are out of sync.");
1034 return;
1035 }
1036
1037 if (strcmp(verb, "attach") == 0)
1038 g_eli_ctl_attach(req, mp);
1039 else if (strcmp(verb, "detach") == 0 || strcmp(verb, "stop") == 0)
1040 g_eli_ctl_detach(req, mp);
1041 else if (strcmp(verb, "onetime") == 0)
1042 g_eli_ctl_onetime(req, mp);
1043 else if (strcmp(verb, "configure") == 0)
1044 g_eli_ctl_configure(req, mp);
1045 else if (strcmp(verb, "setkey") == 0)
1046 g_eli_ctl_setkey(req, mp);
1047 else if (strcmp(verb, "delkey") == 0)
1048 g_eli_ctl_delkey(req, mp);
1049 else if (strcmp(verb, "suspend") == 0)
1050 g_eli_ctl_suspend(req, mp);
1051 else if (strcmp(verb, "resume") == 0)
1052 g_eli_ctl_resume(req, mp);
1053 else if (strcmp(verb, "kill") == 0)
1054 g_eli_ctl_kill(req, mp);
1055 else
1056 gctl_error(req, "Unknown verb.");
1057}
889 G_ELI_DEBUG(1, "Resumed %s.", pp->name);
890 wakeup(sc);
891}
892
893static int
894g_eli_kill_one(struct g_eli_softc *sc)
895{
896 struct g_provider *pp;
897 struct g_consumer *cp;
898 int error = 0;
899
900 g_topology_assert();
901
902 if (sc == NULL)
903 return (ENOENT);
904
905 pp = LIST_FIRST(&sc->sc_geom->provider);
906 g_error_provider(pp, ENXIO);
907
908 cp = LIST_FIRST(&sc->sc_geom->consumer);
909 pp = cp->provider;
910
911 if (sc->sc_flags & G_ELI_FLAG_RO) {
912 G_ELI_DEBUG(0, "WARNING: Metadata won't be erased on read-only "
913 "provider: %s.", pp->name);
914 } else {
915 u_char *sector;
916 u_int i;
917 int err;
918
919 sector = malloc(pp->sectorsize, M_ELI, M_WAITOK);
920 for (i = 0; i <= g_eli_overwrites; i++) {
921 if (i == g_eli_overwrites)
922 bzero(sector, pp->sectorsize);
923 else
924 arc4rand(sector, pp->sectorsize, 0);
925 err = g_write_data(cp, pp->mediasize - pp->sectorsize,
926 sector, pp->sectorsize);
927 if (err != 0) {
928 G_ELI_DEBUG(0, "Cannot erase metadata on %s "
929 "(error=%d).", pp->name, err);
930 if (error == 0)
931 error = err;
932 }
933 /*
934 * Flush write cache so we don't overwrite data N times
935 * in cache and only once on disk.
936 */
937 (void)g_io_flush(cp);
938 }
939 free(sector, M_ELI);
940 }
941 if (error == 0)
942 G_ELI_DEBUG(0, "%s has been killed.", pp->name);
943 g_eli_destroy(sc, TRUE);
944 return (error);
945}
946
947static void
948g_eli_ctl_kill(struct gctl_req *req, struct g_class *mp)
949{
950 int *all, *nargs;
951 int error;
952
953 g_topology_assert();
954
955 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
956 if (nargs == NULL) {
957 gctl_error(req, "No '%s' argument.", "nargs");
958 return;
959 }
960 all = gctl_get_paraml(req, "all", sizeof(*all));
961 if (all == NULL) {
962 gctl_error(req, "No '%s' argument.", "all");
963 return;
964 }
965 if (!*all && *nargs == 0) {
966 gctl_error(req, "Too few arguments.");
967 return;
968 }
969
970 if (*all) {
971 struct g_geom *gp, *gp2;
972
973 LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) {
974 error = g_eli_kill_one(gp->softc);
975 if (error != 0)
976 gctl_error(req, "Not fully done.");
977 }
978 } else {
979 struct g_eli_softc *sc;
980 const char *prov;
981 char param[16];
982 int i;
983
984 for (i = 0; i < *nargs; i++) {
985 snprintf(param, sizeof(param), "arg%d", i);
986 prov = gctl_get_asciiparam(req, param);
987 if (prov == NULL) {
988 G_ELI_DEBUG(0, "No 'arg%d' argument.", i);
989 continue;
990 }
991
992 sc = g_eli_find_device(mp, prov);
993 if (sc == NULL) {
994 G_ELI_DEBUG(0, "No such provider: %s.", prov);
995 continue;
996 }
997 error = g_eli_kill_one(sc);
998 if (error != 0)
999 gctl_error(req, "Not fully done.");
1000 }
1001 }
1002}
1003
1004void
1005g_eli_config(struct gctl_req *req, struct g_class *mp, const char *verb)
1006{
1007 uint32_t *version;
1008
1009 g_topology_assert();
1010
1011 version = gctl_get_paraml(req, "version", sizeof(*version));
1012 if (version == NULL) {
1013 gctl_error(req, "No '%s' argument.", "version");
1014 return;
1015 }
1016 if (*version != G_ELI_VERSION) {
1017 gctl_error(req, "Userland and kernel parts are out of sync.");
1018 return;
1019 }
1020
1021 if (strcmp(verb, "attach") == 0)
1022 g_eli_ctl_attach(req, mp);
1023 else if (strcmp(verb, "detach") == 0 || strcmp(verb, "stop") == 0)
1024 g_eli_ctl_detach(req, mp);
1025 else if (strcmp(verb, "onetime") == 0)
1026 g_eli_ctl_onetime(req, mp);
1027 else if (strcmp(verb, "configure") == 0)
1028 g_eli_ctl_configure(req, mp);
1029 else if (strcmp(verb, "setkey") == 0)
1030 g_eli_ctl_setkey(req, mp);
1031 else if (strcmp(verb, "delkey") == 0)
1032 g_eli_ctl_delkey(req, mp);
1033 else if (strcmp(verb, "suspend") == 0)
1034 g_eli_ctl_suspend(req, mp);
1035 else if (strcmp(verb, "resume") == 0)
1036 g_eli_ctl_resume(req, mp);
1037 else if (strcmp(verb, "kill") == 0)
1038 g_eli_ctl_kill(req, mp);
1039 else
1040 gctl_error(req, "Unknown verb.");
1041}