xref: /freebsd/sys/geom/eli/g_eli_ctl.c (revision fdafd315ad0d0f28a11b9fb4476a9ab059c62b92)
1c58794deSPawel Jakub Dawidek /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
33728855aSPedro F. Giffuni  *
41e09ff3dSPawel Jakub Dawidek  * Copyright (c) 2005-2011 Pawel Jakub Dawidek <pawel@dawidek.net>
5c58794deSPawel Jakub Dawidek  * All rights reserved.
6c58794deSPawel Jakub Dawidek  *
7c58794deSPawel Jakub Dawidek  * Redistribution and use in source and binary forms, with or without
8c58794deSPawel Jakub Dawidek  * modification, are permitted provided that the following conditions
9c58794deSPawel Jakub Dawidek  * are met:
10c58794deSPawel Jakub Dawidek  * 1. Redistributions of source code must retain the above copyright
11c58794deSPawel Jakub Dawidek  *    notice, this list of conditions and the following disclaimer.
12c58794deSPawel Jakub Dawidek  * 2. Redistributions in binary form must reproduce the above copyright
13c58794deSPawel Jakub Dawidek  *    notice, this list of conditions and the following disclaimer in the
14c58794deSPawel Jakub Dawidek  *    documentation and/or other materials provided with the distribution.
15c58794deSPawel Jakub Dawidek  *
16c58794deSPawel Jakub Dawidek  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
17c58794deSPawel Jakub Dawidek  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18c58794deSPawel Jakub Dawidek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19c58794deSPawel Jakub Dawidek  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
20c58794deSPawel Jakub Dawidek  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21c58794deSPawel Jakub Dawidek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22c58794deSPawel Jakub Dawidek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23c58794deSPawel Jakub Dawidek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24c58794deSPawel Jakub Dawidek  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25c58794deSPawel Jakub Dawidek  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26c58794deSPawel Jakub Dawidek  * SUCH DAMAGE.
27c58794deSPawel Jakub Dawidek  */
28c58794deSPawel Jakub Dawidek 
29c58794deSPawel Jakub Dawidek #include <sys/param.h>
30c58794deSPawel Jakub Dawidek #include <sys/systm.h>
31c58794deSPawel Jakub Dawidek #include <sys/kernel.h>
32c58794deSPawel Jakub Dawidek #include <sys/module.h>
33c58794deSPawel Jakub Dawidek #include <sys/lock.h>
34c58794deSPawel Jakub Dawidek #include <sys/mutex.h>
35c58794deSPawel Jakub Dawidek #include <sys/bio.h>
36c58794deSPawel Jakub Dawidek #include <sys/sysctl.h>
37c58794deSPawel Jakub Dawidek #include <sys/malloc.h>
38c58794deSPawel Jakub Dawidek #include <sys/kthread.h>
39c58794deSPawel Jakub Dawidek #include <sys/proc.h>
40c58794deSPawel Jakub Dawidek #include <sys/sched.h>
41c58794deSPawel Jakub Dawidek #include <sys/uio.h>
42c58794deSPawel Jakub Dawidek 
43c58794deSPawel Jakub Dawidek #include <vm/uma.h>
44c58794deSPawel Jakub Dawidek 
45c58794deSPawel Jakub Dawidek #include <geom/geom.h>
46ac03832eSConrad Meyer #include <geom/geom_dbg.h>
47c58794deSPawel Jakub Dawidek #include <geom/eli/g_eli.h>
48c58794deSPawel Jakub Dawidek 
49c58794deSPawel Jakub Dawidek MALLOC_DECLARE(M_ELI);
50c58794deSPawel Jakub Dawidek 
51c58794deSPawel Jakub Dawidek static void
g_eli_ctl_attach(struct gctl_req * req,struct g_class * mp)52c58794deSPawel Jakub Dawidek g_eli_ctl_attach(struct gctl_req *req, struct g_class *mp)
53c58794deSPawel Jakub Dawidek {
54c58794deSPawel Jakub Dawidek 	struct g_eli_metadata md;
55c58794deSPawel Jakub Dawidek 	struct g_provider *pp;
56c58794deSPawel Jakub Dawidek 	u_char *key, mkey[G_ELI_DATAIVKEYLEN];
570db665bbSXin LI 	int *nargs, *detach, *readonly, *dryrunp;
580db665bbSXin LI 	int keysize, error, nkey, dryrun, dummy;
5931f7586dSMariusz Zaborski 	intmax_t *valp;
60c58794deSPawel Jakub Dawidek 
61c58794deSPawel Jakub Dawidek 	g_topology_assert();
62c58794deSPawel Jakub Dawidek 
63c58794deSPawel Jakub Dawidek 	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
64c58794deSPawel Jakub Dawidek 	if (nargs == NULL) {
65c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "nargs");
66c58794deSPawel Jakub Dawidek 		return;
67c58794deSPawel Jakub Dawidek 	}
68c58794deSPawel Jakub Dawidek 	if (*nargs != 1) {
69c58794deSPawel Jakub Dawidek 		gctl_error(req, "Invalid number of arguments.");
70c58794deSPawel Jakub Dawidek 		return;
71c58794deSPawel Jakub Dawidek 	}
72c58794deSPawel Jakub Dawidek 
73c58794deSPawel Jakub Dawidek 	detach = gctl_get_paraml(req, "detach", sizeof(*detach));
74c58794deSPawel Jakub Dawidek 	if (detach == NULL) {
75c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "detach");
76c58794deSPawel Jakub Dawidek 		return;
77c58794deSPawel Jakub Dawidek 	}
78c58794deSPawel Jakub Dawidek 
790db665bbSXin LI 	/* "keyno" is optional for backward compatibility */
800db665bbSXin LI 	nkey = -1;
810db665bbSXin LI 	valp = gctl_get_param(req, "keyno", &dummy);
820db665bbSXin LI 	if (valp != NULL) {
8331f7586dSMariusz Zaborski 		valp = gctl_get_paraml(req, "keyno", sizeof(*valp));
840db665bbSXin LI 		if (valp != NULL)
8531f7586dSMariusz Zaborski 			nkey = *valp;
860db665bbSXin LI 	}
8731f7586dSMariusz Zaborski 	if (nkey < -1 || nkey >= G_ELI_MAXMKEYS) {
8831f7586dSMariusz Zaborski 		gctl_error(req, "Invalid '%s' argument.", "keyno");
8931f7586dSMariusz Zaborski 		return;
9031f7586dSMariusz Zaborski 	}
9131f7586dSMariusz Zaborski 
9285059016SPawel Jakub Dawidek 	readonly = gctl_get_paraml(req, "readonly", sizeof(*readonly));
9385059016SPawel Jakub Dawidek 	if (readonly == NULL) {
9485059016SPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "readonly");
9585059016SPawel Jakub Dawidek 		return;
9685059016SPawel Jakub Dawidek 	}
9785059016SPawel Jakub Dawidek 
980db665bbSXin LI 	/* "dryrun" is optional for backward compatibility */
990db665bbSXin LI 	dryrun = 0;
1000db665bbSXin LI 	dryrunp = gctl_get_param(req, "dryrun", &dummy);
1010db665bbSXin LI 	if (dryrunp != NULL) {
1020db665bbSXin LI 		dryrunp = gctl_get_paraml(req, "dryrun", sizeof(*dryrunp));
1030db665bbSXin LI 		if (dryrunp != NULL)
1040db665bbSXin LI 			dryrun = *dryrunp;
1058f1c45c2SMariusz Zaborski 	}
1068f1c45c2SMariusz Zaborski 
10739b7ca45SAllan Jude 	if (*detach && *readonly) {
10839b7ca45SAllan Jude 		gctl_error(req, "Options -d and -r are mutually exclusive.");
10939b7ca45SAllan Jude 		return;
11039b7ca45SAllan Jude 	}
11139b7ca45SAllan Jude 
112fcf69f3dSXin LI 	pp = gctl_get_provider(req, "arg0");
113fcf69f3dSXin LI 	if (pp == NULL)
114c58794deSPawel Jakub Dawidek 		return;
115c58794deSPawel Jakub Dawidek 	error = g_eli_read_metadata(mp, pp, &md);
116c58794deSPawel Jakub Dawidek 	if (error != 0) {
117c58794deSPawel Jakub Dawidek 		gctl_error(req, "Cannot read metadata from %s (error=%d).",
118fcf69f3dSXin LI 		    pp->name, error);
119c58794deSPawel Jakub Dawidek 		return;
120c58794deSPawel Jakub Dawidek 	}
121c58794deSPawel Jakub Dawidek 	if (md.md_keys == 0x00) {
12239b7ca45SAllan Jude 		explicit_bzero(&md, sizeof(md));
123c58794deSPawel Jakub Dawidek 		gctl_error(req, "No valid keys on %s.", pp->name);
124c58794deSPawel Jakub Dawidek 		return;
125c58794deSPawel Jakub Dawidek 	}
126e2b99193SJohn Baldwin 	if (!eli_metadata_crypto_supported(&md)) {
127e2b99193SJohn Baldwin 		explicit_bzero(&md, sizeof(md));
128e2b99193SJohn Baldwin 		gctl_error(req, "Invalid or unsupported algorithms.");
129e2b99193SJohn Baldwin 		return;
130e2b99193SJohn Baldwin 	}
131c58794deSPawel Jakub Dawidek 
132c58794deSPawel Jakub Dawidek 	key = gctl_get_param(req, "key", &keysize);
133c58794deSPawel Jakub Dawidek 	if (key == NULL || keysize != G_ELI_USERKEYLEN) {
13439b7ca45SAllan Jude 		explicit_bzero(&md, sizeof(md));
135c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "key");
136c58794deSPawel Jakub Dawidek 		return;
137c58794deSPawel Jakub Dawidek 	}
138c58794deSPawel Jakub Dawidek 
13931f7586dSMariusz Zaborski 	if (nkey == -1)
14031f7586dSMariusz Zaborski 		error = g_eli_mkey_decrypt_any(&md, key, mkey, &nkey);
14131f7586dSMariusz Zaborski 	else
14231f7586dSMariusz Zaborski 		error = g_eli_mkey_decrypt(&md, key, mkey, nkey);
14339b7ca45SAllan Jude 	explicit_bzero(key, keysize);
144c58794deSPawel Jakub Dawidek 	if (error == -1) {
14539b7ca45SAllan Jude 		explicit_bzero(&md, sizeof(md));
146c58794deSPawel Jakub Dawidek 		gctl_error(req, "Wrong key for %s.", pp->name);
147c58794deSPawel Jakub Dawidek 		return;
148c58794deSPawel Jakub Dawidek 	} else if (error > 0) {
14939b7ca45SAllan Jude 		explicit_bzero(&md, sizeof(md));
150c58794deSPawel Jakub Dawidek 		gctl_error(req, "Cannot decrypt Master Key for %s (error=%d).",
151c58794deSPawel Jakub Dawidek 		    pp->name, error);
152c58794deSPawel Jakub Dawidek 		return;
153c58794deSPawel Jakub Dawidek 	}
154c58794deSPawel Jakub Dawidek 	G_ELI_DEBUG(1, "Using Master Key %u for %s.", nkey, pp->name);
155c58794deSPawel Jakub Dawidek 
156c58794deSPawel Jakub Dawidek 	if (*detach)
157c58794deSPawel Jakub Dawidek 		md.md_flags |= G_ELI_FLAG_WO_DETACH;
15885059016SPawel Jakub Dawidek 	if (*readonly)
15985059016SPawel Jakub Dawidek 		md.md_flags |= G_ELI_FLAG_RO;
1600db665bbSXin LI 	if (!dryrun)
161c58794deSPawel Jakub Dawidek 		g_eli_create(req, mp, pp, &md, mkey, nkey);
16239b7ca45SAllan Jude 	explicit_bzero(mkey, sizeof(mkey));
16339b7ca45SAllan Jude 	explicit_bzero(&md, sizeof(md));
164c58794deSPawel Jakub Dawidek }
165c58794deSPawel Jakub Dawidek 
166c58794deSPawel Jakub Dawidek static struct g_eli_softc *
g_eli_find_device(struct g_class * mp,const char * prov)167c58794deSPawel Jakub Dawidek g_eli_find_device(struct g_class *mp, const char *prov)
168c58794deSPawel Jakub Dawidek {
169c58794deSPawel Jakub Dawidek 	struct g_eli_softc *sc;
170c58794deSPawel Jakub Dawidek 	struct g_geom *gp;
171c58794deSPawel Jakub Dawidek 	struct g_provider *pp;
172c58794deSPawel Jakub Dawidek 	struct g_consumer *cp;
173c58794deSPawel Jakub Dawidek 
1748510f61aSXin LI 	if (strncmp(prov, _PATH_DEV, strlen(_PATH_DEV)) == 0)
1758510f61aSXin LI 		prov += strlen(_PATH_DEV);
176c58794deSPawel Jakub Dawidek 	LIST_FOREACH(gp, &mp->geom, geom) {
177c58794deSPawel Jakub Dawidek 		sc = gp->softc;
178c58794deSPawel Jakub Dawidek 		if (sc == NULL)
179c58794deSPawel Jakub Dawidek 			continue;
180c58794deSPawel Jakub Dawidek 		pp = LIST_FIRST(&gp->provider);
181c58794deSPawel Jakub Dawidek 		if (pp != NULL && strcmp(pp->name, prov) == 0)
182c58794deSPawel Jakub Dawidek 			return (sc);
183c58794deSPawel Jakub Dawidek 		cp = LIST_FIRST(&gp->consumer);
184c58794deSPawel Jakub Dawidek 		if (cp != NULL && cp->provider != NULL &&
185c58794deSPawel Jakub Dawidek 		    strcmp(cp->provider->name, prov) == 0) {
186c58794deSPawel Jakub Dawidek 			return (sc);
187c58794deSPawel Jakub Dawidek 		}
188c58794deSPawel Jakub Dawidek 	}
189c58794deSPawel Jakub Dawidek 	return (NULL);
190c58794deSPawel Jakub Dawidek }
191c58794deSPawel Jakub Dawidek 
192c58794deSPawel Jakub Dawidek static void
g_eli_ctl_detach(struct gctl_req * req,struct g_class * mp)193c58794deSPawel Jakub Dawidek g_eli_ctl_detach(struct gctl_req *req, struct g_class *mp)
194c58794deSPawel Jakub Dawidek {
195c58794deSPawel Jakub Dawidek 	struct g_eli_softc *sc;
196c58794deSPawel Jakub Dawidek 	int *force, *last, *nargs, error;
197c58794deSPawel Jakub Dawidek 	const char *prov;
198c58794deSPawel Jakub Dawidek 	char param[16];
1997d54b385SPawel Jakub Dawidek 	int i;
200c58794deSPawel Jakub Dawidek 
201c58794deSPawel Jakub Dawidek 	g_topology_assert();
202c58794deSPawel Jakub Dawidek 
203c58794deSPawel Jakub Dawidek 	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
204c58794deSPawel Jakub Dawidek 	if (nargs == NULL) {
205c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "nargs");
206c58794deSPawel Jakub Dawidek 		return;
207c58794deSPawel Jakub Dawidek 	}
208c58794deSPawel Jakub Dawidek 	if (*nargs <= 0) {
209c58794deSPawel Jakub Dawidek 		gctl_error(req, "Missing device(s).");
210c58794deSPawel Jakub Dawidek 		return;
211c58794deSPawel Jakub Dawidek 	}
212c58794deSPawel Jakub Dawidek 	force = gctl_get_paraml(req, "force", sizeof(*force));
213c58794deSPawel Jakub Dawidek 	if (force == NULL) {
214c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "force");
215c58794deSPawel Jakub Dawidek 		return;
216c58794deSPawel Jakub Dawidek 	}
217c58794deSPawel Jakub Dawidek 	last = gctl_get_paraml(req, "last", sizeof(*last));
218c58794deSPawel Jakub Dawidek 	if (last == NULL) {
219c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "last");
220c58794deSPawel Jakub Dawidek 		return;
221c58794deSPawel Jakub Dawidek 	}
222c58794deSPawel Jakub Dawidek 
2237d54b385SPawel Jakub Dawidek 	for (i = 0; i < *nargs; i++) {
2247d54b385SPawel Jakub Dawidek 		snprintf(param, sizeof(param), "arg%d", i);
225c58794deSPawel Jakub Dawidek 		prov = gctl_get_asciiparam(req, param);
226c58794deSPawel Jakub Dawidek 		if (prov == NULL) {
2277d54b385SPawel Jakub Dawidek 			gctl_error(req, "No 'arg%d' argument.", i);
228c58794deSPawel Jakub Dawidek 			return;
229c58794deSPawel Jakub Dawidek 		}
230c58794deSPawel Jakub Dawidek 		sc = g_eli_find_device(mp, prov);
231c58794deSPawel Jakub Dawidek 		if (sc == NULL) {
232c58794deSPawel Jakub Dawidek 			gctl_error(req, "No such device: %s.", prov);
233c58794deSPawel Jakub Dawidek 			return;
234c58794deSPawel Jakub Dawidek 		}
235c58794deSPawel Jakub Dawidek 		if (*last) {
236c58794deSPawel Jakub Dawidek 			sc->sc_flags |= G_ELI_FLAG_RW_DETACH;
237c58794deSPawel Jakub Dawidek 			sc->sc_geom->access = g_eli_access;
238c58794deSPawel Jakub Dawidek 		} else {
2395ad4a7c7SPawel Jakub Dawidek 			error = g_eli_destroy(sc, *force ? TRUE : FALSE);
240c58794deSPawel Jakub Dawidek 			if (error != 0) {
241c58794deSPawel Jakub Dawidek 				gctl_error(req,
242c58794deSPawel Jakub Dawidek 				    "Cannot destroy device %s (error=%d).",
243c58794deSPawel Jakub Dawidek 				    sc->sc_name, error);
244c58794deSPawel Jakub Dawidek 				return;
245c58794deSPawel Jakub Dawidek 			}
246c58794deSPawel Jakub Dawidek 		}
247c58794deSPawel Jakub Dawidek 	}
248c58794deSPawel Jakub Dawidek }
249c58794deSPawel Jakub Dawidek 
250c58794deSPawel Jakub Dawidek static void
g_eli_ctl_onetime(struct gctl_req * req,struct g_class * mp)251c58794deSPawel Jakub Dawidek g_eli_ctl_onetime(struct gctl_req *req, struct g_class *mp)
252c58794deSPawel Jakub Dawidek {
253c58794deSPawel Jakub Dawidek 	struct g_eli_metadata md;
254c58794deSPawel Jakub Dawidek 	struct g_provider *pp;
255c58794deSPawel Jakub Dawidek 	const char *name;
256c58794deSPawel Jakub Dawidek 	intmax_t *keylen, *sectorsize;
257c58794deSPawel Jakub Dawidek 	u_char mkey[G_ELI_DATAIVKEYLEN];
2582f07cdf8SPawel Jakub Dawidek 	int *nargs, *detach, *noautoresize, *notrim;
259c58794deSPawel Jakub Dawidek 
260c58794deSPawel Jakub Dawidek 	g_topology_assert();
261c58794deSPawel Jakub Dawidek 	bzero(&md, sizeof(md));
262c58794deSPawel Jakub Dawidek 
263c58794deSPawel Jakub Dawidek 	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
264c58794deSPawel Jakub Dawidek 	if (nargs == NULL) {
265c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "nargs");
266c58794deSPawel Jakub Dawidek 		return;
267c58794deSPawel Jakub Dawidek 	}
268c58794deSPawel Jakub Dawidek 	if (*nargs != 1) {
269c58794deSPawel Jakub Dawidek 		gctl_error(req, "Invalid number of arguments.");
270c58794deSPawel Jakub Dawidek 		return;
271c58794deSPawel Jakub Dawidek 	}
272c58794deSPawel Jakub Dawidek 
273c58794deSPawel Jakub Dawidek 	strlcpy(md.md_magic, G_ELI_MAGIC, sizeof(md.md_magic));
274c58794deSPawel Jakub Dawidek 	md.md_version = G_ELI_VERSION;
275c58794deSPawel Jakub Dawidek 	md.md_flags |= G_ELI_FLAG_ONETIME;
2762f07cdf8SPawel Jakub Dawidek 	md.md_flags |= G_ELI_FLAG_AUTORESIZE;
27746e34470SPawel Jakub Dawidek 
27846e34470SPawel Jakub Dawidek 	detach = gctl_get_paraml(req, "detach", sizeof(*detach));
27946e34470SPawel Jakub Dawidek 	if (detach != NULL && *detach)
280c58794deSPawel Jakub Dawidek 		md.md_flags |= G_ELI_FLAG_WO_DETACH;
2812f07cdf8SPawel Jakub Dawidek 	noautoresize = gctl_get_paraml(req, "noautoresize",
2822f07cdf8SPawel Jakub Dawidek 	    sizeof(*noautoresize));
2832f07cdf8SPawel Jakub Dawidek 	if (noautoresize != NULL && *noautoresize)
2842f07cdf8SPawel Jakub Dawidek 		md.md_flags &= ~G_ELI_FLAG_AUTORESIZE;
28546e34470SPawel Jakub Dawidek 	notrim = gctl_get_paraml(req, "notrim", sizeof(*notrim));
28646e34470SPawel Jakub Dawidek 	if (notrim != NULL && *notrim)
28746e34470SPawel Jakub Dawidek 		md.md_flags |= G_ELI_FLAG_NODELETE;
288c58794deSPawel Jakub Dawidek 
289c84efdcaSPawel Jakub Dawidek 	md.md_ealgo = CRYPTO_ALGORITHM_MIN - 1;
290eaa3b919SPawel Jakub Dawidek 	name = gctl_get_asciiparam(req, "aalgo");
291c58794deSPawel Jakub Dawidek 	if (name == NULL) {
292eaa3b919SPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "aalgo");
293c58794deSPawel Jakub Dawidek 		return;
294c58794deSPawel Jakub Dawidek 	}
295a478ea74SPawel Jakub Dawidek 	if (*name != '\0') {
296eaa3b919SPawel Jakub Dawidek 		md.md_aalgo = g_eli_str2aalgo(name);
297c84efdcaSPawel Jakub Dawidek 		if (md.md_aalgo >= CRYPTO_ALGORITHM_MIN &&
298c84efdcaSPawel Jakub Dawidek 		    md.md_aalgo <= CRYPTO_ALGORITHM_MAX) {
299eaa3b919SPawel Jakub Dawidek 			md.md_flags |= G_ELI_FLAG_AUTH;
300c84efdcaSPawel Jakub Dawidek 		} else {
301c84efdcaSPawel Jakub Dawidek 			/*
302c84efdcaSPawel Jakub Dawidek 			 * For backward compatibility, check if the -a option
303c84efdcaSPawel Jakub Dawidek 			 * was used to provide encryption algorithm.
304c84efdcaSPawel Jakub Dawidek 			 */
305c84efdcaSPawel Jakub Dawidek 			md.md_ealgo = g_eli_str2ealgo(name);
306c84efdcaSPawel Jakub Dawidek 			if (md.md_ealgo < CRYPTO_ALGORITHM_MIN ||
307c84efdcaSPawel Jakub Dawidek 			    md.md_ealgo > CRYPTO_ALGORITHM_MAX) {
308c84efdcaSPawel Jakub Dawidek 				gctl_error(req,
309c84efdcaSPawel Jakub Dawidek 				    "Invalid authentication algorithm.");
310c84efdcaSPawel Jakub Dawidek 				return;
311c84efdcaSPawel Jakub Dawidek 			} else {
312c84efdcaSPawel Jakub Dawidek 				gctl_error(req, "warning: The -e option, not "
313c84efdcaSPawel Jakub Dawidek 				    "the -a option is now used to specify "
314c84efdcaSPawel Jakub Dawidek 				    "encryption algorithm to use.");
315c84efdcaSPawel Jakub Dawidek 			}
316c84efdcaSPawel Jakub Dawidek 		}
317eaa3b919SPawel Jakub Dawidek 	}
318eaa3b919SPawel Jakub Dawidek 
319c84efdcaSPawel Jakub Dawidek 	if (md.md_ealgo < CRYPTO_ALGORITHM_MIN ||
320c84efdcaSPawel Jakub Dawidek 	    md.md_ealgo > CRYPTO_ALGORITHM_MAX) {
321eaa3b919SPawel Jakub Dawidek 		name = gctl_get_asciiparam(req, "ealgo");
322eaa3b919SPawel Jakub Dawidek 		if (name == NULL) {
323eaa3b919SPawel Jakub Dawidek 			gctl_error(req, "No '%s' argument.", "ealgo");
324eaa3b919SPawel Jakub Dawidek 			return;
325eaa3b919SPawel Jakub Dawidek 		}
326eaa3b919SPawel Jakub Dawidek 		md.md_ealgo = g_eli_str2ealgo(name);
327eaa3b919SPawel Jakub Dawidek 		if (md.md_ealgo < CRYPTO_ALGORITHM_MIN ||
328eaa3b919SPawel Jakub Dawidek 		    md.md_ealgo > CRYPTO_ALGORITHM_MAX) {
329eaa3b919SPawel Jakub Dawidek 			gctl_error(req, "Invalid encryption algorithm.");
330c58794deSPawel Jakub Dawidek 			return;
331c58794deSPawel Jakub Dawidek 		}
332c84efdcaSPawel Jakub Dawidek 	}
333c58794deSPawel Jakub Dawidek 
334c58794deSPawel Jakub Dawidek 	keylen = gctl_get_paraml(req, "keylen", sizeof(*keylen));
335c58794deSPawel Jakub Dawidek 	if (keylen == NULL) {
336c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "keylen");
337c58794deSPawel Jakub Dawidek 		return;
338c58794deSPawel Jakub Dawidek 	}
339eaa3b919SPawel Jakub Dawidek 	md.md_keylen = g_eli_keylen(md.md_ealgo, *keylen);
340c58794deSPawel Jakub Dawidek 	if (md.md_keylen == 0) {
341c58794deSPawel Jakub Dawidek 		gctl_error(req, "Invalid '%s' argument.", "keylen");
342c58794deSPawel Jakub Dawidek 		return;
343c58794deSPawel Jakub Dawidek 	}
344c58794deSPawel Jakub Dawidek 
345c58794deSPawel Jakub Dawidek 	/* Not important here. */
346c58794deSPawel Jakub Dawidek 	md.md_provsize = 0;
347c58794deSPawel Jakub Dawidek 	/* Not important here. */
348c58794deSPawel Jakub Dawidek 	bzero(md.md_salt, sizeof(md.md_salt));
349c58794deSPawel Jakub Dawidek 
350c58794deSPawel Jakub Dawidek 	md.md_keys = 0x01;
351c58794deSPawel Jakub Dawidek 	arc4rand(mkey, sizeof(mkey), 0);
352c58794deSPawel Jakub Dawidek 
353c58794deSPawel Jakub Dawidek 	/* Not important here. */
354c58794deSPawel Jakub Dawidek 	bzero(md.md_hash, sizeof(md.md_hash));
355c58794deSPawel Jakub Dawidek 
356fcf69f3dSXin LI 	pp = gctl_get_provider(req, "arg0");
357fcf69f3dSXin LI 	if (pp == NULL)
358c58794deSPawel Jakub Dawidek 		return;
359c58794deSPawel Jakub Dawidek 
360c58794deSPawel Jakub Dawidek 	sectorsize = gctl_get_paraml(req, "sectorsize", sizeof(*sectorsize));
361c58794deSPawel Jakub Dawidek 	if (sectorsize == NULL) {
362c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "sectorsize");
363c58794deSPawel Jakub Dawidek 		return;
364c58794deSPawel Jakub Dawidek 	}
365c58794deSPawel Jakub Dawidek 	if (*sectorsize == 0)
366c58794deSPawel Jakub Dawidek 		md.md_sectorsize = pp->sectorsize;
367c58794deSPawel Jakub Dawidek 	else {
368c58794deSPawel Jakub Dawidek 		if (*sectorsize < 0 || (*sectorsize % pp->sectorsize) != 0) {
369c58794deSPawel Jakub Dawidek 			gctl_error(req, "Invalid sector size.");
370c58794deSPawel Jakub Dawidek 			return;
371c58794deSPawel Jakub Dawidek 		}
37297a669a3SPawel Jakub Dawidek 		if (*sectorsize > PAGE_SIZE) {
37397a669a3SPawel Jakub Dawidek 			gctl_error(req, "warning: Using sectorsize bigger than "
37497a669a3SPawel Jakub Dawidek 			    "the page size!");
37597a669a3SPawel Jakub Dawidek 		}
376c58794deSPawel Jakub Dawidek 		md.md_sectorsize = *sectorsize;
377c58794deSPawel Jakub Dawidek 	}
378c58794deSPawel Jakub Dawidek 
379c58794deSPawel Jakub Dawidek 	g_eli_create(req, mp, pp, &md, mkey, -1);
38039b7ca45SAllan Jude 	explicit_bzero(mkey, sizeof(mkey));
38139b7ca45SAllan Jude 	explicit_bzero(&md, sizeof(md));
382c58794deSPawel Jakub Dawidek }
383c58794deSPawel Jakub Dawidek 
384c58794deSPawel Jakub Dawidek static void
g_eli_ctl_configure(struct gctl_req * req,struct g_class * mp)3858abd1ad1SPawel Jakub Dawidek g_eli_ctl_configure(struct gctl_req *req, struct g_class *mp)
3868abd1ad1SPawel Jakub Dawidek {
3878abd1ad1SPawel Jakub Dawidek 	struct g_eli_softc *sc;
3888abd1ad1SPawel Jakub Dawidek 	struct g_eli_metadata md;
3898abd1ad1SPawel Jakub Dawidek 	struct g_provider *pp;
3908abd1ad1SPawel Jakub Dawidek 	struct g_consumer *cp;
3918abd1ad1SPawel Jakub Dawidek 	char param[16];
3928abd1ad1SPawel Jakub Dawidek 	const char *prov;
3938abd1ad1SPawel Jakub Dawidek 	u_char *sector;
394d8736625SAllan Jude 	int *nargs, *boot, *noboot, *trim, *notrim, *geliboot, *nogeliboot;
3952f07cdf8SPawel Jakub Dawidek 	int *displaypass, *nodisplaypass, *autoresize, *noautoresize;
39646e34470SPawel Jakub Dawidek 	int zero, error, changed;
3978abd1ad1SPawel Jakub Dawidek 	u_int i;
3988abd1ad1SPawel Jakub Dawidek 
3998abd1ad1SPawel Jakub Dawidek 	g_topology_assert();
4008abd1ad1SPawel Jakub Dawidek 
40146e34470SPawel Jakub Dawidek 	changed = 0;
40246e34470SPawel Jakub Dawidek 	zero = 0;
40346e34470SPawel Jakub Dawidek 
4048abd1ad1SPawel Jakub Dawidek 	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
4058abd1ad1SPawel Jakub Dawidek 	if (nargs == NULL) {
4068abd1ad1SPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "nargs");
4078abd1ad1SPawel Jakub Dawidek 		return;
4088abd1ad1SPawel Jakub Dawidek 	}
4098abd1ad1SPawel Jakub Dawidek 	if (*nargs <= 0) {
4108abd1ad1SPawel Jakub Dawidek 		gctl_error(req, "Missing device(s).");
4118abd1ad1SPawel Jakub Dawidek 		return;
4128abd1ad1SPawel Jakub Dawidek 	}
4138abd1ad1SPawel Jakub Dawidek 
4148abd1ad1SPawel Jakub Dawidek 	boot = gctl_get_paraml(req, "boot", sizeof(*boot));
41546e34470SPawel Jakub Dawidek 	if (boot == NULL)
41646e34470SPawel Jakub Dawidek 		boot = &zero;
4178abd1ad1SPawel Jakub Dawidek 	noboot = gctl_get_paraml(req, "noboot", sizeof(*noboot));
41846e34470SPawel Jakub Dawidek 	if (noboot == NULL)
41946e34470SPawel Jakub Dawidek 		noboot = &zero;
4208abd1ad1SPawel Jakub Dawidek 	if (*boot && *noboot) {
4218abd1ad1SPawel Jakub Dawidek 		gctl_error(req, "Options -b and -B are mutually exclusive.");
4228abd1ad1SPawel Jakub Dawidek 		return;
4238abd1ad1SPawel Jakub Dawidek 	}
42446e34470SPawel Jakub Dawidek 	if (*boot || *noboot)
42546e34470SPawel Jakub Dawidek 		changed = 1;
42646e34470SPawel Jakub Dawidek 
42746e34470SPawel Jakub Dawidek 	trim = gctl_get_paraml(req, "trim", sizeof(*trim));
42846e34470SPawel Jakub Dawidek 	if (trim == NULL)
42946e34470SPawel Jakub Dawidek 		trim = &zero;
43046e34470SPawel Jakub Dawidek 	notrim = gctl_get_paraml(req, "notrim", sizeof(*notrim));
43146e34470SPawel Jakub Dawidek 	if (notrim == NULL)
43246e34470SPawel Jakub Dawidek 		notrim = &zero;
43346e34470SPawel Jakub Dawidek 	if (*trim && *notrim) {
43446e34470SPawel Jakub Dawidek 		gctl_error(req, "Options -t and -T are mutually exclusive.");
43546e34470SPawel Jakub Dawidek 		return;
43646e34470SPawel Jakub Dawidek 	}
43746e34470SPawel Jakub Dawidek 	if (*trim || *notrim)
43846e34470SPawel Jakub Dawidek 		changed = 1;
43946e34470SPawel Jakub Dawidek 
440d8736625SAllan Jude 	geliboot = gctl_get_paraml(req, "geliboot", sizeof(*geliboot));
441d8736625SAllan Jude 	if (geliboot == NULL)
442d8736625SAllan Jude 		geliboot = &zero;
443d8736625SAllan Jude 	nogeliboot = gctl_get_paraml(req, "nogeliboot", sizeof(*nogeliboot));
444d8736625SAllan Jude 	if (nogeliboot == NULL)
445d8736625SAllan Jude 		nogeliboot = &zero;
446d8736625SAllan Jude 	if (*geliboot && *nogeliboot) {
447d8736625SAllan Jude 		gctl_error(req, "Options -g and -G are mutually exclusive.");
448d8736625SAllan Jude 		return;
449d8736625SAllan Jude 	}
450d8736625SAllan Jude 	if (*geliboot || *nogeliboot)
451d8736625SAllan Jude 		changed = 1;
452d8736625SAllan Jude 
4533453dc72SMariusz Zaborski 	displaypass = gctl_get_paraml(req, "displaypass", sizeof(*displaypass));
4543453dc72SMariusz Zaborski 	if (displaypass == NULL)
4553453dc72SMariusz Zaborski 		displaypass = &zero;
4563453dc72SMariusz Zaborski 	nodisplaypass = gctl_get_paraml(req, "nodisplaypass", sizeof(*nodisplaypass));
4573453dc72SMariusz Zaborski 	if (nodisplaypass == NULL)
4583453dc72SMariusz Zaborski 		nodisplaypass = &zero;
4593453dc72SMariusz Zaborski 	if (*displaypass && *nodisplaypass) {
4603453dc72SMariusz Zaborski 		gctl_error(req, "Options -d and -D are mutually exclusive.");
4613453dc72SMariusz Zaborski 		return;
4623453dc72SMariusz Zaborski 	}
4633453dc72SMariusz Zaborski 	if (*displaypass || *nodisplaypass)
4643453dc72SMariusz Zaborski 		changed = 1;
4653453dc72SMariusz Zaborski 
4662f07cdf8SPawel Jakub Dawidek 	autoresize = gctl_get_paraml(req, "autoresize", sizeof(*autoresize));
4672f07cdf8SPawel Jakub Dawidek 	if (autoresize == NULL)
4682f07cdf8SPawel Jakub Dawidek 		autoresize = &zero;
4692f07cdf8SPawel Jakub Dawidek 	noautoresize = gctl_get_paraml(req, "noautoresize",
4702f07cdf8SPawel Jakub Dawidek 	    sizeof(*noautoresize));
4712f07cdf8SPawel Jakub Dawidek 	if (noautoresize == NULL)
4722f07cdf8SPawel Jakub Dawidek 		noautoresize = &zero;
4732f07cdf8SPawel Jakub Dawidek 	if (*autoresize && *noautoresize) {
4742f07cdf8SPawel Jakub Dawidek 		gctl_error(req, "Options -r and -R are mutually exclusive.");
4752f07cdf8SPawel Jakub Dawidek 		return;
4762f07cdf8SPawel Jakub Dawidek 	}
4772f07cdf8SPawel Jakub Dawidek 	if (*autoresize || *noautoresize)
4782f07cdf8SPawel Jakub Dawidek 		changed = 1;
4792f07cdf8SPawel Jakub Dawidek 
48046e34470SPawel Jakub Dawidek 	if (!changed) {
4818abd1ad1SPawel Jakub Dawidek 		gctl_error(req, "No option given.");
4828abd1ad1SPawel Jakub Dawidek 		return;
4838abd1ad1SPawel Jakub Dawidek 	}
4848abd1ad1SPawel Jakub Dawidek 
4858abd1ad1SPawel Jakub Dawidek 	for (i = 0; i < *nargs; i++) {
4868abd1ad1SPawel Jakub Dawidek 		snprintf(param, sizeof(param), "arg%d", i);
4878abd1ad1SPawel Jakub Dawidek 		prov = gctl_get_asciiparam(req, param);
4888abd1ad1SPawel Jakub Dawidek 		if (prov == NULL) {
4898abd1ad1SPawel Jakub Dawidek 			gctl_error(req, "No 'arg%d' argument.", i);
4908abd1ad1SPawel Jakub Dawidek 			return;
4918abd1ad1SPawel Jakub Dawidek 		}
4928abd1ad1SPawel Jakub Dawidek 		sc = g_eli_find_device(mp, prov);
4938abd1ad1SPawel Jakub Dawidek 		if (sc == NULL) {
4948abd1ad1SPawel Jakub Dawidek 			/*
4958abd1ad1SPawel Jakub Dawidek 			 * We ignore not attached providers, userland part will
4968abd1ad1SPawel Jakub Dawidek 			 * take care of them.
4978abd1ad1SPawel Jakub Dawidek 			 */
4988abd1ad1SPawel Jakub Dawidek 			G_ELI_DEBUG(1, "Skipping configuration of not attached "
4998abd1ad1SPawel Jakub Dawidek 			    "provider %s.", prov);
5008abd1ad1SPawel Jakub Dawidek 			continue;
5018abd1ad1SPawel Jakub Dawidek 		}
5028abd1ad1SPawel Jakub Dawidek 		if (sc->sc_flags & G_ELI_FLAG_RO) {
5038abd1ad1SPawel Jakub Dawidek 			gctl_error(req, "Cannot change configuration of "
5048abd1ad1SPawel Jakub Dawidek 			    "read-only provider %s.", prov);
5058abd1ad1SPawel Jakub Dawidek 			continue;
5068abd1ad1SPawel Jakub Dawidek 		}
50746e34470SPawel Jakub Dawidek 
50846e34470SPawel Jakub Dawidek 		if (*boot && (sc->sc_flags & G_ELI_FLAG_BOOT)) {
50946e34470SPawel Jakub Dawidek 			G_ELI_DEBUG(1, "BOOT flag already configured for %s.",
51046e34470SPawel Jakub Dawidek 			    prov);
51146e34470SPawel Jakub Dawidek 			continue;
51246e34470SPawel Jakub Dawidek 		} else if (*noboot && !(sc->sc_flags & G_ELI_FLAG_BOOT)) {
51346e34470SPawel Jakub Dawidek 			G_ELI_DEBUG(1, "BOOT flag not configured for %s.",
51446e34470SPawel Jakub Dawidek 			    prov);
51546e34470SPawel Jakub Dawidek 			continue;
51646e34470SPawel Jakub Dawidek 		}
51746e34470SPawel Jakub Dawidek 
51846e34470SPawel Jakub Dawidek 		if (*notrim && (sc->sc_flags & G_ELI_FLAG_NODELETE)) {
51946e34470SPawel Jakub Dawidek 			G_ELI_DEBUG(1, "TRIM disable flag already configured for %s.",
52046e34470SPawel Jakub Dawidek 			    prov);
52146e34470SPawel Jakub Dawidek 			continue;
52246e34470SPawel Jakub Dawidek 		} else if (*trim && !(sc->sc_flags & G_ELI_FLAG_NODELETE)) {
52346e34470SPawel Jakub Dawidek 			G_ELI_DEBUG(1, "TRIM disable flag not configured for %s.",
52446e34470SPawel Jakub Dawidek 			    prov);
52546e34470SPawel Jakub Dawidek 			continue;
52646e34470SPawel Jakub Dawidek 		}
52746e34470SPawel Jakub Dawidek 
528d8736625SAllan Jude 		if (*geliboot && (sc->sc_flags & G_ELI_FLAG_GELIBOOT)) {
529d8736625SAllan Jude 			G_ELI_DEBUG(1, "GELIBOOT flag already configured for %s.",
530d8736625SAllan Jude 			    prov);
531d8736625SAllan Jude 			continue;
532d8736625SAllan Jude 		} else if (*nogeliboot && !(sc->sc_flags & G_ELI_FLAG_GELIBOOT)) {
533d8736625SAllan Jude 			G_ELI_DEBUG(1, "GELIBOOT flag not configured for %s.",
534d8736625SAllan Jude 			    prov);
535d8736625SAllan Jude 			continue;
536d8736625SAllan Jude 		}
537d8736625SAllan Jude 
5383453dc72SMariusz Zaborski 		if (*displaypass && (sc->sc_flags & G_ELI_FLAG_GELIDISPLAYPASS)) {
5393453dc72SMariusz Zaborski 			G_ELI_DEBUG(1, "GELIDISPLAYPASS flag already configured for %s.",
5403453dc72SMariusz Zaborski 			    prov);
5413453dc72SMariusz Zaborski 			continue;
5423453dc72SMariusz Zaborski 		} else if (*nodisplaypass &&
5433453dc72SMariusz Zaborski 		    !(sc->sc_flags & G_ELI_FLAG_GELIDISPLAYPASS)) {
5443453dc72SMariusz Zaborski 			G_ELI_DEBUG(1, "GELIDISPLAYPASS flag not configured for %s.",
5453453dc72SMariusz Zaborski 			    prov);
5463453dc72SMariusz Zaborski 			continue;
5473453dc72SMariusz Zaborski 		}
5483453dc72SMariusz Zaborski 
5492f07cdf8SPawel Jakub Dawidek 		if (*autoresize && (sc->sc_flags & G_ELI_FLAG_AUTORESIZE)) {
5502f07cdf8SPawel Jakub Dawidek 			G_ELI_DEBUG(1, "AUTORESIZE flag already configured for %s.",
5512f07cdf8SPawel Jakub Dawidek 			    prov);
5522f07cdf8SPawel Jakub Dawidek 			continue;
5532f07cdf8SPawel Jakub Dawidek 		} else if (*noautoresize &&
5542f07cdf8SPawel Jakub Dawidek 		    !(sc->sc_flags & G_ELI_FLAG_AUTORESIZE)) {
5552f07cdf8SPawel Jakub Dawidek 			G_ELI_DEBUG(1, "AUTORESIZE flag not configured for %s.",
5562f07cdf8SPawel Jakub Dawidek 			    prov);
5572f07cdf8SPawel Jakub Dawidek 			continue;
5582f07cdf8SPawel Jakub Dawidek 		}
5592f07cdf8SPawel Jakub Dawidek 
56046e34470SPawel Jakub Dawidek 		if (!(sc->sc_flags & G_ELI_FLAG_ONETIME)) {
56146e34470SPawel Jakub Dawidek 			/*
56246e34470SPawel Jakub Dawidek 			 * ONETIME providers don't write metadata to
56346e34470SPawel Jakub Dawidek 			 * disk, so don't try reading it.  This means
56446e34470SPawel Jakub Dawidek 			 * we're bit-flipping uninitialized memory in md
56546e34470SPawel Jakub Dawidek 			 * below, but that's OK; we don't do anything
56646e34470SPawel Jakub Dawidek 			 * with it later.
56746e34470SPawel Jakub Dawidek 			 */
5688abd1ad1SPawel Jakub Dawidek 			cp = LIST_FIRST(&sc->sc_geom->consumer);
5698abd1ad1SPawel Jakub Dawidek 			pp = cp->provider;
5708abd1ad1SPawel Jakub Dawidek 			error = g_eli_read_metadata(mp, pp, &md);
5718abd1ad1SPawel Jakub Dawidek 			if (error != 0) {
5728abd1ad1SPawel Jakub Dawidek 			    gctl_error(req,
5738abd1ad1SPawel Jakub Dawidek 				"Cannot read metadata from %s (error=%d).",
5748abd1ad1SPawel Jakub Dawidek 				prov, error);
5758abd1ad1SPawel Jakub Dawidek 			    continue;
5768abd1ad1SPawel Jakub Dawidek 			}
57746e34470SPawel Jakub Dawidek 		}
5788abd1ad1SPawel Jakub Dawidek 
5798abd1ad1SPawel Jakub Dawidek 		if (*boot) {
5808abd1ad1SPawel Jakub Dawidek 			md.md_flags |= G_ELI_FLAG_BOOT;
5818abd1ad1SPawel Jakub Dawidek 			sc->sc_flags |= G_ELI_FLAG_BOOT;
58246e34470SPawel Jakub Dawidek 		} else if (*noboot) {
5838abd1ad1SPawel Jakub Dawidek 			md.md_flags &= ~G_ELI_FLAG_BOOT;
5848abd1ad1SPawel Jakub Dawidek 			sc->sc_flags &= ~G_ELI_FLAG_BOOT;
5858abd1ad1SPawel Jakub Dawidek 		}
5868abd1ad1SPawel Jakub Dawidek 
58746e34470SPawel Jakub Dawidek 		if (*notrim) {
58846e34470SPawel Jakub Dawidek 			md.md_flags |= G_ELI_FLAG_NODELETE;
58946e34470SPawel Jakub Dawidek 			sc->sc_flags |= G_ELI_FLAG_NODELETE;
59046e34470SPawel Jakub Dawidek 		} else if (*trim) {
59146e34470SPawel Jakub Dawidek 			md.md_flags &= ~G_ELI_FLAG_NODELETE;
59246e34470SPawel Jakub Dawidek 			sc->sc_flags &= ~G_ELI_FLAG_NODELETE;
59346e34470SPawel Jakub Dawidek 		}
59446e34470SPawel Jakub Dawidek 
595d8736625SAllan Jude 		if (*geliboot) {
596d8736625SAllan Jude 			md.md_flags |= G_ELI_FLAG_GELIBOOT;
597d8736625SAllan Jude 			sc->sc_flags |= G_ELI_FLAG_GELIBOOT;
598d8736625SAllan Jude 		} else if (*nogeliboot) {
599d8736625SAllan Jude 			md.md_flags &= ~G_ELI_FLAG_GELIBOOT;
600d8736625SAllan Jude 			sc->sc_flags &= ~G_ELI_FLAG_GELIBOOT;
601d8736625SAllan Jude 		}
602d8736625SAllan Jude 
6033453dc72SMariusz Zaborski 		if (*displaypass) {
6043453dc72SMariusz Zaborski 			md.md_flags |= G_ELI_FLAG_GELIDISPLAYPASS;
6053453dc72SMariusz Zaborski 			sc->sc_flags |= G_ELI_FLAG_GELIDISPLAYPASS;
6063453dc72SMariusz Zaborski 		} else if (*nodisplaypass) {
6073453dc72SMariusz Zaborski 			md.md_flags &= ~G_ELI_FLAG_GELIDISPLAYPASS;
6083453dc72SMariusz Zaborski 			sc->sc_flags &= ~G_ELI_FLAG_GELIDISPLAYPASS;
6093453dc72SMariusz Zaborski 		}
6103453dc72SMariusz Zaborski 
6112f07cdf8SPawel Jakub Dawidek 		if (*autoresize) {
6122f07cdf8SPawel Jakub Dawidek 			md.md_flags |= G_ELI_FLAG_AUTORESIZE;
6132f07cdf8SPawel Jakub Dawidek 			sc->sc_flags |= G_ELI_FLAG_AUTORESIZE;
6142f07cdf8SPawel Jakub Dawidek 		} else if (*noautoresize) {
6152f07cdf8SPawel Jakub Dawidek 			md.md_flags &= ~G_ELI_FLAG_AUTORESIZE;
6162f07cdf8SPawel Jakub Dawidek 			sc->sc_flags &= ~G_ELI_FLAG_AUTORESIZE;
6172f07cdf8SPawel Jakub Dawidek 		}
6182f07cdf8SPawel Jakub Dawidek 
61946e34470SPawel Jakub Dawidek 		if (sc->sc_flags & G_ELI_FLAG_ONETIME) {
62046e34470SPawel Jakub Dawidek 			/* There's no metadata on disk so we are done here. */
62146e34470SPawel Jakub Dawidek 			continue;
62246e34470SPawel Jakub Dawidek 		}
62346e34470SPawel Jakub Dawidek 
6248abd1ad1SPawel Jakub Dawidek 		sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO);
6258abd1ad1SPawel Jakub Dawidek 		eli_metadata_encode(&md, sector);
6268abd1ad1SPawel Jakub Dawidek 		error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
6278abd1ad1SPawel Jakub Dawidek 		    pp->sectorsize);
6288abd1ad1SPawel Jakub Dawidek 		if (error != 0) {
6298abd1ad1SPawel Jakub Dawidek 			gctl_error(req,
6308abd1ad1SPawel Jakub Dawidek 			    "Cannot store metadata on %s (error=%d).",
6318abd1ad1SPawel Jakub Dawidek 			    prov, error);
6328abd1ad1SPawel Jakub Dawidek 		}
63339b7ca45SAllan Jude 		explicit_bzero(&md, sizeof(md));
6344a711b8dSJohn Baldwin 		zfree(sector, M_ELI);
6358abd1ad1SPawel Jakub Dawidek 	}
6368abd1ad1SPawel Jakub Dawidek }
6378abd1ad1SPawel Jakub Dawidek 
6388abd1ad1SPawel Jakub Dawidek static void
g_eli_ctl_setkey(struct gctl_req * req,struct g_class * mp)639c58794deSPawel Jakub Dawidek g_eli_ctl_setkey(struct gctl_req *req, struct g_class *mp)
640c58794deSPawel Jakub Dawidek {
641c58794deSPawel Jakub Dawidek 	struct g_eli_softc *sc;
642c58794deSPawel Jakub Dawidek 	struct g_eli_metadata md;
643c58794deSPawel Jakub Dawidek 	struct g_provider *pp;
644c58794deSPawel Jakub Dawidek 	struct g_consumer *cp;
645c58794deSPawel Jakub Dawidek 	const char *name;
646c58794deSPawel Jakub Dawidek 	u_char *key, *mkeydst, *sector;
647c58794deSPawel Jakub Dawidek 	intmax_t *valp;
6487a5c26fcSPawel Jakub Dawidek 	int keysize, nkey, error;
649c58794deSPawel Jakub Dawidek 
650c58794deSPawel Jakub Dawidek 	g_topology_assert();
651c58794deSPawel Jakub Dawidek 
652c58794deSPawel Jakub Dawidek 	name = gctl_get_asciiparam(req, "arg0");
653c58794deSPawel Jakub Dawidek 	if (name == NULL) {
654c58794deSPawel Jakub Dawidek 		gctl_error(req, "No 'arg%u' argument.", 0);
655c58794deSPawel Jakub Dawidek 		return;
656c58794deSPawel Jakub Dawidek 	}
65739b7ca45SAllan Jude 	key = gctl_get_param(req, "key", &keysize);
65839b7ca45SAllan Jude 	if (key == NULL || keysize != G_ELI_USERKEYLEN) {
65939b7ca45SAllan Jude 		gctl_error(req, "No '%s' argument.", "key");
66039b7ca45SAllan Jude 		return;
66139b7ca45SAllan Jude 	}
662c58794deSPawel Jakub Dawidek 	sc = g_eli_find_device(mp, name);
663c58794deSPawel Jakub Dawidek 	if (sc == NULL) {
664c58794deSPawel Jakub Dawidek 		gctl_error(req, "Provider %s is invalid.", name);
665c58794deSPawel Jakub Dawidek 		return;
666c58794deSPawel Jakub Dawidek 	}
66785059016SPawel Jakub Dawidek 	if (sc->sc_flags & G_ELI_FLAG_RO) {
66885059016SPawel Jakub Dawidek 		gctl_error(req, "Cannot change keys for read-only provider.");
66985059016SPawel Jakub Dawidek 		return;
67085059016SPawel Jakub Dawidek 	}
671c58794deSPawel Jakub Dawidek 	cp = LIST_FIRST(&sc->sc_geom->consumer);
672c58794deSPawel Jakub Dawidek 	pp = cp->provider;
673c58794deSPawel Jakub Dawidek 
674c58794deSPawel Jakub Dawidek 	error = g_eli_read_metadata(mp, pp, &md);
675c58794deSPawel Jakub Dawidek 	if (error != 0) {
676c58794deSPawel Jakub Dawidek 		gctl_error(req, "Cannot read metadata from %s (error=%d).",
677c58794deSPawel Jakub Dawidek 		    name, error);
678c58794deSPawel Jakub Dawidek 		return;
679c58794deSPawel Jakub Dawidek 	}
680c58794deSPawel Jakub Dawidek 
681c58794deSPawel Jakub Dawidek 	valp = gctl_get_paraml(req, "keyno", sizeof(*valp));
682c58794deSPawel Jakub Dawidek 	if (valp == NULL) {
683c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "keyno");
684c58794deSPawel Jakub Dawidek 		return;
685c58794deSPawel Jakub Dawidek 	}
686c58794deSPawel Jakub Dawidek 	if (*valp != -1)
687c58794deSPawel Jakub Dawidek 		nkey = *valp;
688c58794deSPawel Jakub Dawidek 	else
689c58794deSPawel Jakub Dawidek 		nkey = sc->sc_nkey;
690c58794deSPawel Jakub Dawidek 	if (nkey < 0 || nkey >= G_ELI_MAXMKEYS) {
691c58794deSPawel Jakub Dawidek 		gctl_error(req, "Invalid '%s' argument.", "keyno");
692c58794deSPawel Jakub Dawidek 		return;
693c58794deSPawel Jakub Dawidek 	}
694c58794deSPawel Jakub Dawidek 
6957a5c26fcSPawel Jakub Dawidek 	valp = gctl_get_paraml(req, "iterations", sizeof(*valp));
6967a5c26fcSPawel Jakub Dawidek 	if (valp == NULL) {
6977a5c26fcSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "iterations");
6987a5c26fcSPawel Jakub Dawidek 		return;
6997a5c26fcSPawel Jakub Dawidek 	}
7007a5c26fcSPawel Jakub Dawidek 	/* Check if iterations number should and can be changed. */
701d8880fd4SAlexander Motin 	if (*valp != -1 && md.md_iterations == -1) {
702d8880fd4SAlexander Motin 		md.md_iterations = *valp;
703d8880fd4SAlexander Motin 	} else if (*valp != -1 && *valp != md.md_iterations) {
7047a5c26fcSPawel Jakub Dawidek 		if (bitcount32(md.md_keys) != 1) {
7057a5c26fcSPawel Jakub Dawidek 			gctl_error(req, "To be able to use '-i' option, only "
7067a5c26fcSPawel Jakub Dawidek 			    "one key can be defined.");
7077a5c26fcSPawel Jakub Dawidek 			return;
7087a5c26fcSPawel Jakub Dawidek 		}
7097a5c26fcSPawel Jakub Dawidek 		if (md.md_keys != (1 << nkey)) {
7107a5c26fcSPawel Jakub Dawidek 			gctl_error(req, "Only already defined key can be "
7117a5c26fcSPawel Jakub Dawidek 			    "changed when '-i' option is used.");
7127a5c26fcSPawel Jakub Dawidek 			return;
7137a5c26fcSPawel Jakub Dawidek 		}
7147a5c26fcSPawel Jakub Dawidek 		md.md_iterations = *valp;
7157a5c26fcSPawel Jakub Dawidek 	}
7167a5c26fcSPawel Jakub Dawidek 
717c58794deSPawel Jakub Dawidek 	mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN;
718c58794deSPawel Jakub Dawidek 	md.md_keys |= (1 << nkey);
719c58794deSPawel Jakub Dawidek 
720eaa3b919SPawel Jakub Dawidek 	bcopy(sc->sc_mkey, mkeydst, sizeof(sc->sc_mkey));
721c58794deSPawel Jakub Dawidek 
722c58794deSPawel Jakub Dawidek 	/* Encrypt Master Key with the new key. */
723eaa3b919SPawel Jakub Dawidek 	error = g_eli_mkey_encrypt(md.md_ealgo, key, md.md_keylen, mkeydst);
72439b7ca45SAllan Jude 	explicit_bzero(key, keysize);
725c58794deSPawel Jakub Dawidek 	if (error != 0) {
72639b7ca45SAllan Jude 		explicit_bzero(&md, sizeof(md));
727c58794deSPawel Jakub Dawidek 		gctl_error(req, "Cannot encrypt Master Key (error=%d).", error);
728c58794deSPawel Jakub Dawidek 		return;
729c58794deSPawel Jakub Dawidek 	}
730c58794deSPawel Jakub Dawidek 
731c58794deSPawel Jakub Dawidek 	sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO);
732c58794deSPawel Jakub Dawidek 	/* Store metadata with fresh key. */
733c58794deSPawel Jakub Dawidek 	eli_metadata_encode(&md, sector);
73439b7ca45SAllan Jude 	explicit_bzero(&md, sizeof(md));
735c58794deSPawel Jakub Dawidek 	error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
736c58794deSPawel Jakub Dawidek 	    pp->sectorsize);
7374a711b8dSJohn Baldwin 	zfree(sector, M_ELI);
738c58794deSPawel Jakub Dawidek 	if (error != 0) {
739c58794deSPawel Jakub Dawidek 		gctl_error(req, "Cannot store metadata on %s (error=%d).",
740c58794deSPawel Jakub Dawidek 		    pp->name, error);
741c58794deSPawel Jakub Dawidek 		return;
742c58794deSPawel Jakub Dawidek 	}
743c58794deSPawel Jakub Dawidek 	G_ELI_DEBUG(1, "Key %u changed on %s.", nkey, pp->name);
744c58794deSPawel Jakub Dawidek }
745c58794deSPawel Jakub Dawidek 
746c58794deSPawel Jakub Dawidek static void
g_eli_ctl_delkey(struct gctl_req * req,struct g_class * mp)747c58794deSPawel Jakub Dawidek g_eli_ctl_delkey(struct gctl_req *req, struct g_class *mp)
748c58794deSPawel Jakub Dawidek {
749c58794deSPawel Jakub Dawidek 	struct g_eli_softc *sc;
750c58794deSPawel Jakub Dawidek 	struct g_eli_metadata md;
751c58794deSPawel Jakub Dawidek 	struct g_provider *pp;
752c58794deSPawel Jakub Dawidek 	struct g_consumer *cp;
753c58794deSPawel Jakub Dawidek 	const char *name;
754c58794deSPawel Jakub Dawidek 	u_char *mkeydst, *sector;
755c58794deSPawel Jakub Dawidek 	intmax_t *valp;
756c58794deSPawel Jakub Dawidek 	size_t keysize;
757c58794deSPawel Jakub Dawidek 	int error, nkey, *all, *force;
758c58794deSPawel Jakub Dawidek 	u_int i;
759c58794deSPawel Jakub Dawidek 
760c58794deSPawel Jakub Dawidek 	g_topology_assert();
761c58794deSPawel Jakub Dawidek 
762c58794deSPawel Jakub Dawidek 	nkey = 0;	/* fixes causeless gcc warning */
763c58794deSPawel Jakub Dawidek 
764c58794deSPawel Jakub Dawidek 	name = gctl_get_asciiparam(req, "arg0");
765c58794deSPawel Jakub Dawidek 	if (name == NULL) {
766c58794deSPawel Jakub Dawidek 		gctl_error(req, "No 'arg%u' argument.", 0);
767c58794deSPawel Jakub Dawidek 		return;
768c58794deSPawel Jakub Dawidek 	}
769c58794deSPawel Jakub Dawidek 	sc = g_eli_find_device(mp, name);
770c58794deSPawel Jakub Dawidek 	if (sc == NULL) {
771c58794deSPawel Jakub Dawidek 		gctl_error(req, "Provider %s is invalid.", name);
772c58794deSPawel Jakub Dawidek 		return;
773c58794deSPawel Jakub Dawidek 	}
77485059016SPawel Jakub Dawidek 	if (sc->sc_flags & G_ELI_FLAG_RO) {
77585059016SPawel Jakub Dawidek 		gctl_error(req, "Cannot delete keys for read-only provider.");
77685059016SPawel Jakub Dawidek 		return;
77785059016SPawel Jakub Dawidek 	}
778c58794deSPawel Jakub Dawidek 	cp = LIST_FIRST(&sc->sc_geom->consumer);
779c58794deSPawel Jakub Dawidek 	pp = cp->provider;
780c58794deSPawel Jakub Dawidek 
781c58794deSPawel Jakub Dawidek 	error = g_eli_read_metadata(mp, pp, &md);
782c58794deSPawel Jakub Dawidek 	if (error != 0) {
783c58794deSPawel Jakub Dawidek 		gctl_error(req, "Cannot read metadata from %s (error=%d).",
784c58794deSPawel Jakub Dawidek 		    name, error);
785c58794deSPawel Jakub Dawidek 		return;
786c58794deSPawel Jakub Dawidek 	}
787c58794deSPawel Jakub Dawidek 
788c58794deSPawel Jakub Dawidek 	all = gctl_get_paraml(req, "all", sizeof(*all));
789c58794deSPawel Jakub Dawidek 	if (all == NULL) {
790c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "all");
791c58794deSPawel Jakub Dawidek 		return;
792c58794deSPawel Jakub Dawidek 	}
793c58794deSPawel Jakub Dawidek 
794c58794deSPawel Jakub Dawidek 	if (*all) {
795c58794deSPawel Jakub Dawidek 		mkeydst = md.md_mkeys;
796c58794deSPawel Jakub Dawidek 		keysize = sizeof(md.md_mkeys);
797c58794deSPawel Jakub Dawidek 	} else {
798c58794deSPawel Jakub Dawidek 		force = gctl_get_paraml(req, "force", sizeof(*force));
799c58794deSPawel Jakub Dawidek 		if (force == NULL) {
800c58794deSPawel Jakub Dawidek 			gctl_error(req, "No '%s' argument.", "force");
801c58794deSPawel Jakub Dawidek 			return;
802c58794deSPawel Jakub Dawidek 		}
803c58794deSPawel Jakub Dawidek 
804c58794deSPawel Jakub Dawidek 		valp = gctl_get_paraml(req, "keyno", sizeof(*valp));
805c58794deSPawel Jakub Dawidek 		if (valp == NULL) {
806c58794deSPawel Jakub Dawidek 			gctl_error(req, "No '%s' argument.", "keyno");
807c58794deSPawel Jakub Dawidek 			return;
808c58794deSPawel Jakub Dawidek 		}
809c58794deSPawel Jakub Dawidek 		if (*valp != -1)
810c58794deSPawel Jakub Dawidek 			nkey = *valp;
811c58794deSPawel Jakub Dawidek 		else
812c58794deSPawel Jakub Dawidek 			nkey = sc->sc_nkey;
813c58794deSPawel Jakub Dawidek 		if (nkey < 0 || nkey >= G_ELI_MAXMKEYS) {
814c58794deSPawel Jakub Dawidek 			gctl_error(req, "Invalid '%s' argument.", "keyno");
815c58794deSPawel Jakub Dawidek 			return;
816c58794deSPawel Jakub Dawidek 		}
817c58794deSPawel Jakub Dawidek 		if (!(md.md_keys & (1 << nkey)) && !*force) {
818c58794deSPawel Jakub Dawidek 			gctl_error(req, "Master Key %u is not set.", nkey);
819c58794deSPawel Jakub Dawidek 			return;
820c58794deSPawel Jakub Dawidek 		}
821c58794deSPawel Jakub Dawidek 		md.md_keys &= ~(1 << nkey);
822c58794deSPawel Jakub Dawidek 		if (md.md_keys == 0 && !*force) {
823c58794deSPawel Jakub Dawidek 			gctl_error(req, "This is the last Master Key. Use '-f' "
824c58794deSPawel Jakub Dawidek 			    "flag if you really want to remove it.");
825c58794deSPawel Jakub Dawidek 			return;
826c58794deSPawel Jakub Dawidek 		}
827c58794deSPawel Jakub Dawidek 		mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN;
828c58794deSPawel Jakub Dawidek 		keysize = G_ELI_MKEYLEN;
829c58794deSPawel Jakub Dawidek 	}
830c58794deSPawel Jakub Dawidek 
831c58794deSPawel Jakub Dawidek 	sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO);
832c58794deSPawel Jakub Dawidek 	for (i = 0; i <= g_eli_overwrites; i++) {
833c58794deSPawel Jakub Dawidek 		if (i == g_eli_overwrites)
83439b7ca45SAllan Jude 			explicit_bzero(mkeydst, keysize);
835c58794deSPawel Jakub Dawidek 		else
836c58794deSPawel Jakub Dawidek 			arc4rand(mkeydst, keysize, 0);
837c58794deSPawel Jakub Dawidek 		/* Store metadata with destroyed key. */
838c58794deSPawel Jakub Dawidek 		eli_metadata_encode(&md, sector);
839c58794deSPawel Jakub Dawidek 		error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
840c58794deSPawel Jakub Dawidek 		    pp->sectorsize);
841c58794deSPawel Jakub Dawidek 		if (error != 0) {
842c58794deSPawel Jakub Dawidek 			G_ELI_DEBUG(0, "Cannot store metadata on %s "
843c58794deSPawel Jakub Dawidek 			    "(error=%d).", pp->name, error);
844c58794deSPawel Jakub Dawidek 		}
845f0256e71SPawel Jakub Dawidek 		/*
846f0256e71SPawel Jakub Dawidek 		 * Flush write cache so we don't overwrite data N times in cache
847f0256e71SPawel Jakub Dawidek 		 * and only once on disk.
848f0256e71SPawel Jakub Dawidek 		 */
849350e8df8SPawel Jakub Dawidek 		(void)g_io_flush(cp);
850c58794deSPawel Jakub Dawidek 	}
85139b7ca45SAllan Jude 	explicit_bzero(&md, sizeof(md));
8524a711b8dSJohn Baldwin 	zfree(sector, M_ELI);
853c58794deSPawel Jakub Dawidek 	if (*all)
854c58794deSPawel Jakub Dawidek 		G_ELI_DEBUG(1, "All keys removed from %s.", pp->name);
855c58794deSPawel Jakub Dawidek 	else
856c58794deSPawel Jakub Dawidek 		G_ELI_DEBUG(1, "Key %d removed from %s.", nkey, pp->name);
857c58794deSPawel Jakub Dawidek }
858c58794deSPawel Jakub Dawidek 
8590d2f5a4eSPawel Jakub Dawidek static void
g_eli_suspend_one(struct g_eli_softc * sc,struct gctl_req * req)8600d2f5a4eSPawel Jakub Dawidek g_eli_suspend_one(struct g_eli_softc *sc, struct gctl_req *req)
8615ad4a7c7SPawel Jakub Dawidek {
8625ad4a7c7SPawel Jakub Dawidek 	struct g_eli_worker *wr;
8635ad4a7c7SPawel Jakub Dawidek 
8645ad4a7c7SPawel Jakub Dawidek 	g_topology_assert();
8655ad4a7c7SPawel Jakub Dawidek 
8660d2f5a4eSPawel Jakub Dawidek 	KASSERT(sc != NULL, ("NULL sc"));
8670d2f5a4eSPawel Jakub Dawidek 
8680d2f5a4eSPawel Jakub Dawidek 	if (sc->sc_flags & G_ELI_FLAG_ONETIME) {
8690d2f5a4eSPawel Jakub Dawidek 		gctl_error(req,
8700d2f5a4eSPawel Jakub Dawidek 		    "Device %s is using one-time key, suspend not supported.",
8710d2f5a4eSPawel Jakub Dawidek 		    sc->sc_name);
8720d2f5a4eSPawel Jakub Dawidek 		return;
8730d2f5a4eSPawel Jakub Dawidek 	}
8745ad4a7c7SPawel Jakub Dawidek 
8755ad4a7c7SPawel Jakub Dawidek 	mtx_lock(&sc->sc_queue_mtx);
8765ad4a7c7SPawel Jakub Dawidek 	if (sc->sc_flags & G_ELI_FLAG_SUSPEND) {
8775ad4a7c7SPawel Jakub Dawidek 		mtx_unlock(&sc->sc_queue_mtx);
8780d2f5a4eSPawel Jakub Dawidek 		gctl_error(req, "Device %s already suspended.",
8790d2f5a4eSPawel Jakub Dawidek 		    sc->sc_name);
8800d2f5a4eSPawel Jakub Dawidek 		return;
8815ad4a7c7SPawel Jakub Dawidek 	}
8825ad4a7c7SPawel Jakub Dawidek 	sc->sc_flags |= G_ELI_FLAG_SUSPEND;
8835ad4a7c7SPawel Jakub Dawidek 	wakeup(sc);
8845ad4a7c7SPawel Jakub Dawidek 	for (;;) {
8855ad4a7c7SPawel Jakub Dawidek 		LIST_FOREACH(wr, &sc->sc_workers, w_next) {
8865ad4a7c7SPawel Jakub Dawidek 			if (wr->w_active)
8875ad4a7c7SPawel Jakub Dawidek 				break;
8885ad4a7c7SPawel Jakub Dawidek 		}
8895ad4a7c7SPawel Jakub Dawidek 		if (wr == NULL)
8905ad4a7c7SPawel Jakub Dawidek 			break;
8915ad4a7c7SPawel Jakub Dawidek 		/* Not all threads suspended. */
8925ad4a7c7SPawel Jakub Dawidek 		msleep(&sc->sc_workers, &sc->sc_queue_mtx, PRIBIO,
8935ad4a7c7SPawel Jakub Dawidek 		    "geli:suspend", 0);
8945ad4a7c7SPawel Jakub Dawidek 	}
8955ad4a7c7SPawel Jakub Dawidek 	/*
8965ad4a7c7SPawel Jakub Dawidek 	 * Clear sensitive data on suspend, they will be recovered on resume.
8975ad4a7c7SPawel Jakub Dawidek 	 */
89839b7ca45SAllan Jude 	explicit_bzero(sc->sc_mkey, sizeof(sc->sc_mkey));
8991e09ff3dSPawel Jakub Dawidek 	g_eli_key_destroy(sc);
90039b7ca45SAllan Jude 	explicit_bzero(sc->sc_akey, sizeof(sc->sc_akey));
90139b7ca45SAllan Jude 	explicit_bzero(&sc->sc_akeyctx, sizeof(sc->sc_akeyctx));
90239b7ca45SAllan Jude 	explicit_bzero(sc->sc_ivkey, sizeof(sc->sc_ivkey));
90339b7ca45SAllan Jude 	explicit_bzero(&sc->sc_ivctx, sizeof(sc->sc_ivctx));
9045ad4a7c7SPawel Jakub Dawidek 	mtx_unlock(&sc->sc_queue_mtx);
9050d2f5a4eSPawel Jakub Dawidek 	G_ELI_DEBUG(0, "Device %s has been suspended.", sc->sc_name);
9065ad4a7c7SPawel Jakub Dawidek }
9075ad4a7c7SPawel Jakub Dawidek 
9085ad4a7c7SPawel Jakub Dawidek static void
g_eli_ctl_suspend(struct gctl_req * req,struct g_class * mp)9095ad4a7c7SPawel Jakub Dawidek g_eli_ctl_suspend(struct gctl_req *req, struct g_class *mp)
9105ad4a7c7SPawel Jakub Dawidek {
9115ad4a7c7SPawel Jakub Dawidek 	struct g_eli_softc *sc;
9125ad4a7c7SPawel Jakub Dawidek 	int *all, *nargs;
9135ad4a7c7SPawel Jakub Dawidek 
9145ad4a7c7SPawel Jakub Dawidek 	g_topology_assert();
9155ad4a7c7SPawel Jakub Dawidek 
9165ad4a7c7SPawel Jakub Dawidek 	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
9175ad4a7c7SPawel Jakub Dawidek 	if (nargs == NULL) {
9185ad4a7c7SPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "nargs");
9195ad4a7c7SPawel Jakub Dawidek 		return;
9205ad4a7c7SPawel Jakub Dawidek 	}
9215ad4a7c7SPawel Jakub Dawidek 	all = gctl_get_paraml(req, "all", sizeof(*all));
9225ad4a7c7SPawel Jakub Dawidek 	if (all == NULL) {
9235ad4a7c7SPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "all");
9245ad4a7c7SPawel Jakub Dawidek 		return;
9255ad4a7c7SPawel Jakub Dawidek 	}
9265ad4a7c7SPawel Jakub Dawidek 	if (!*all && *nargs == 0) {
9275ad4a7c7SPawel Jakub Dawidek 		gctl_error(req, "Too few arguments.");
9285ad4a7c7SPawel Jakub Dawidek 		return;
9295ad4a7c7SPawel Jakub Dawidek 	}
9305ad4a7c7SPawel Jakub Dawidek 
9315ad4a7c7SPawel Jakub Dawidek 	if (*all) {
9325ad4a7c7SPawel Jakub Dawidek 		struct g_geom *gp, *gp2;
9335ad4a7c7SPawel Jakub Dawidek 
9345ad4a7c7SPawel Jakub Dawidek 		LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) {
9355ad4a7c7SPawel Jakub Dawidek 			sc = gp->softc;
9360d2f5a4eSPawel Jakub Dawidek 			if (sc->sc_flags & G_ELI_FLAG_ONETIME) {
9370d2f5a4eSPawel Jakub Dawidek 				G_ELI_DEBUG(0,
9380d2f5a4eSPawel Jakub Dawidek 				    "Device %s is using one-time key, suspend not supported, skipping.",
9390d2f5a4eSPawel Jakub Dawidek 				    sc->sc_name);
9405ad4a7c7SPawel Jakub Dawidek 				continue;
9410d2f5a4eSPawel Jakub Dawidek 			}
9420d2f5a4eSPawel Jakub Dawidek 			g_eli_suspend_one(sc, req);
9435ad4a7c7SPawel Jakub Dawidek 		}
9445ad4a7c7SPawel Jakub Dawidek 	} else {
9455ad4a7c7SPawel Jakub Dawidek 		const char *prov;
9465ad4a7c7SPawel Jakub Dawidek 		char param[16];
9475ad4a7c7SPawel Jakub Dawidek 		int i;
9485ad4a7c7SPawel Jakub Dawidek 
9495ad4a7c7SPawel Jakub Dawidek 		for (i = 0; i < *nargs; i++) {
9505ad4a7c7SPawel Jakub Dawidek 			snprintf(param, sizeof(param), "arg%d", i);
9515ad4a7c7SPawel Jakub Dawidek 			prov = gctl_get_asciiparam(req, param);
9525ad4a7c7SPawel Jakub Dawidek 			if (prov == NULL) {
9535ad4a7c7SPawel Jakub Dawidek 				G_ELI_DEBUG(0, "No 'arg%d' argument.", i);
9545ad4a7c7SPawel Jakub Dawidek 				continue;
9555ad4a7c7SPawel Jakub Dawidek 			}
9565ad4a7c7SPawel Jakub Dawidek 
9575ad4a7c7SPawel Jakub Dawidek 			sc = g_eli_find_device(mp, prov);
9585ad4a7c7SPawel Jakub Dawidek 			if (sc == NULL) {
9595ad4a7c7SPawel Jakub Dawidek 				G_ELI_DEBUG(0, "No such provider: %s.", prov);
9605ad4a7c7SPawel Jakub Dawidek 				continue;
9615ad4a7c7SPawel Jakub Dawidek 			}
9620d2f5a4eSPawel Jakub Dawidek 			g_eli_suspend_one(sc, req);
9635ad4a7c7SPawel Jakub Dawidek 		}
9645ad4a7c7SPawel Jakub Dawidek 	}
9655ad4a7c7SPawel Jakub Dawidek }
9665ad4a7c7SPawel Jakub Dawidek 
9675ad4a7c7SPawel Jakub Dawidek static void
g_eli_ctl_resume(struct gctl_req * req,struct g_class * mp)9685ad4a7c7SPawel Jakub Dawidek g_eli_ctl_resume(struct gctl_req *req, struct g_class *mp)
9695ad4a7c7SPawel Jakub Dawidek {
9705ad4a7c7SPawel Jakub Dawidek 	struct g_eli_metadata md;
9715ad4a7c7SPawel Jakub Dawidek 	struct g_eli_softc *sc;
9725ad4a7c7SPawel Jakub Dawidek 	struct g_provider *pp;
9735ad4a7c7SPawel Jakub Dawidek 	struct g_consumer *cp;
9745ad4a7c7SPawel Jakub Dawidek 	const char *name;
9755ad4a7c7SPawel Jakub Dawidek 	u_char *key, mkey[G_ELI_DATAIVKEYLEN];
9765ad4a7c7SPawel Jakub Dawidek 	int *nargs, keysize, error;
9775ad4a7c7SPawel Jakub Dawidek 	u_int nkey;
9785ad4a7c7SPawel Jakub Dawidek 
9795ad4a7c7SPawel Jakub Dawidek 	g_topology_assert();
9805ad4a7c7SPawel Jakub Dawidek 
9815ad4a7c7SPawel Jakub Dawidek 	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
9825ad4a7c7SPawel Jakub Dawidek 	if (nargs == NULL) {
9835ad4a7c7SPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "nargs");
9845ad4a7c7SPawel Jakub Dawidek 		return;
9855ad4a7c7SPawel Jakub Dawidek 	}
9865ad4a7c7SPawel Jakub Dawidek 	if (*nargs != 1) {
9875ad4a7c7SPawel Jakub Dawidek 		gctl_error(req, "Invalid number of arguments.");
9885ad4a7c7SPawel Jakub Dawidek 		return;
9895ad4a7c7SPawel Jakub Dawidek 	}
9905ad4a7c7SPawel Jakub Dawidek 
9915ad4a7c7SPawel Jakub Dawidek 	name = gctl_get_asciiparam(req, "arg0");
9925ad4a7c7SPawel Jakub Dawidek 	if (name == NULL) {
9935ad4a7c7SPawel Jakub Dawidek 		gctl_error(req, "No 'arg%u' argument.", 0);
9945ad4a7c7SPawel Jakub Dawidek 		return;
9955ad4a7c7SPawel Jakub Dawidek 	}
99639b7ca45SAllan Jude 	key = gctl_get_param(req, "key", &keysize);
99739b7ca45SAllan Jude 	if (key == NULL || keysize != G_ELI_USERKEYLEN) {
99839b7ca45SAllan Jude 		gctl_error(req, "No '%s' argument.", "key");
99939b7ca45SAllan Jude 		return;
100039b7ca45SAllan Jude 	}
10015ad4a7c7SPawel Jakub Dawidek 	sc = g_eli_find_device(mp, name);
10025ad4a7c7SPawel Jakub Dawidek 	if (sc == NULL) {
10035ad4a7c7SPawel Jakub Dawidek 		gctl_error(req, "Provider %s is invalid.", name);
10045ad4a7c7SPawel Jakub Dawidek 		return;
10055ad4a7c7SPawel Jakub Dawidek 	}
10065ad4a7c7SPawel Jakub Dawidek 	cp = LIST_FIRST(&sc->sc_geom->consumer);
10075ad4a7c7SPawel Jakub Dawidek 	pp = cp->provider;
10085ad4a7c7SPawel Jakub Dawidek 	error = g_eli_read_metadata(mp, pp, &md);
10095ad4a7c7SPawel Jakub Dawidek 	if (error != 0) {
10105ad4a7c7SPawel Jakub Dawidek 		gctl_error(req, "Cannot read metadata from %s (error=%d).",
10115ad4a7c7SPawel Jakub Dawidek 		    name, error);
10125ad4a7c7SPawel Jakub Dawidek 		return;
10135ad4a7c7SPawel Jakub Dawidek 	}
10145ad4a7c7SPawel Jakub Dawidek 	if (md.md_keys == 0x00) {
101539b7ca45SAllan Jude 		explicit_bzero(&md, sizeof(md));
10165ad4a7c7SPawel Jakub Dawidek 		gctl_error(req, "No valid keys on %s.", pp->name);
10175ad4a7c7SPawel Jakub Dawidek 		return;
10185ad4a7c7SPawel Jakub Dawidek 	}
10195ad4a7c7SPawel Jakub Dawidek 
102031f7586dSMariusz Zaborski 	error = g_eli_mkey_decrypt_any(&md, key, mkey, &nkey);
102139b7ca45SAllan Jude 	explicit_bzero(key, keysize);
10225ad4a7c7SPawel Jakub Dawidek 	if (error == -1) {
102339b7ca45SAllan Jude 		explicit_bzero(&md, sizeof(md));
10245ad4a7c7SPawel Jakub Dawidek 		gctl_error(req, "Wrong key for %s.", pp->name);
10255ad4a7c7SPawel Jakub Dawidek 		return;
10265ad4a7c7SPawel Jakub Dawidek 	} else if (error > 0) {
102739b7ca45SAllan Jude 		explicit_bzero(&md, sizeof(md));
10285ad4a7c7SPawel Jakub Dawidek 		gctl_error(req, "Cannot decrypt Master Key for %s (error=%d).",
10295ad4a7c7SPawel Jakub Dawidek 		    pp->name, error);
10305ad4a7c7SPawel Jakub Dawidek 		return;
10315ad4a7c7SPawel Jakub Dawidek 	}
10325ad4a7c7SPawel Jakub Dawidek 	G_ELI_DEBUG(1, "Using Master Key %u for %s.", nkey, pp->name);
10335ad4a7c7SPawel Jakub Dawidek 
10345ad4a7c7SPawel Jakub Dawidek 	mtx_lock(&sc->sc_queue_mtx);
10352f2d7830SPawel Jakub Dawidek 	if (!(sc->sc_flags & G_ELI_FLAG_SUSPEND))
10362f2d7830SPawel Jakub Dawidek 		gctl_error(req, "Device %s is not suspended.", name);
10372f2d7830SPawel Jakub Dawidek 	else {
10385ad4a7c7SPawel Jakub Dawidek 		/* Restore sc_mkey, sc_ekeys, sc_akey and sc_ivkey. */
10395ad4a7c7SPawel Jakub Dawidek 		g_eli_mkey_propagate(sc, mkey);
10405ad4a7c7SPawel Jakub Dawidek 		sc->sc_flags &= ~G_ELI_FLAG_SUSPEND;
10412f2d7830SPawel Jakub Dawidek 		G_ELI_DEBUG(1, "Resumed %s.", pp->name);
10422f2d7830SPawel Jakub Dawidek 		wakeup(sc);
10432f2d7830SPawel Jakub Dawidek 	}
10445ad4a7c7SPawel Jakub Dawidek 	mtx_unlock(&sc->sc_queue_mtx);
104539b7ca45SAllan Jude 	explicit_bzero(mkey, sizeof(mkey));
104639b7ca45SAllan Jude 	explicit_bzero(&md, sizeof(md));
10475ad4a7c7SPawel Jakub Dawidek }
10485ad4a7c7SPawel Jakub Dawidek 
10495ad4a7c7SPawel Jakub Dawidek static int
g_eli_kill_one(struct g_eli_softc * sc)1050c58794deSPawel Jakub Dawidek g_eli_kill_one(struct g_eli_softc *sc)
1051c58794deSPawel Jakub Dawidek {
1052c58794deSPawel Jakub Dawidek 	struct g_provider *pp;
1053c58794deSPawel Jakub Dawidek 	struct g_consumer *cp;
105485059016SPawel Jakub Dawidek 	int error = 0;
1055c58794deSPawel Jakub Dawidek 
1056c58794deSPawel Jakub Dawidek 	g_topology_assert();
1057c58794deSPawel Jakub Dawidek 
1058c58794deSPawel Jakub Dawidek 	if (sc == NULL)
1059c58794deSPawel Jakub Dawidek 		return (ENOENT);
1060c58794deSPawel Jakub Dawidek 
1061c58794deSPawel Jakub Dawidek 	pp = LIST_FIRST(&sc->sc_geom->provider);
1062c58794deSPawel Jakub Dawidek 	g_error_provider(pp, ENXIO);
1063c58794deSPawel Jakub Dawidek 
1064c58794deSPawel Jakub Dawidek 	cp = LIST_FIRST(&sc->sc_geom->consumer);
1065c58794deSPawel Jakub Dawidek 	pp = cp->provider;
1066c58794deSPawel Jakub Dawidek 
106785059016SPawel Jakub Dawidek 	if (sc->sc_flags & G_ELI_FLAG_RO) {
106885059016SPawel Jakub Dawidek 		G_ELI_DEBUG(0, "WARNING: Metadata won't be erased on read-only "
106985059016SPawel Jakub Dawidek 		    "provider: %s.", pp->name);
107085059016SPawel Jakub Dawidek 	} else {
107185059016SPawel Jakub Dawidek 		u_char *sector;
107285059016SPawel Jakub Dawidek 		u_int i;
107385059016SPawel Jakub Dawidek 		int err;
107485059016SPawel Jakub Dawidek 
1075c58794deSPawel Jakub Dawidek 		sector = malloc(pp->sectorsize, M_ELI, M_WAITOK);
1076c58794deSPawel Jakub Dawidek 		for (i = 0; i <= g_eli_overwrites; i++) {
1077c58794deSPawel Jakub Dawidek 			if (i == g_eli_overwrites)
1078c58794deSPawel Jakub Dawidek 				bzero(sector, pp->sectorsize);
1079c58794deSPawel Jakub Dawidek 			else
1080c58794deSPawel Jakub Dawidek 				arc4rand(sector, pp->sectorsize, 0);
108185059016SPawel Jakub Dawidek 			err = g_write_data(cp, pp->mediasize - pp->sectorsize,
108285059016SPawel Jakub Dawidek 			    sector, pp->sectorsize);
1083c58794deSPawel Jakub Dawidek 			if (err != 0) {
1084c58794deSPawel Jakub Dawidek 				G_ELI_DEBUG(0, "Cannot erase metadata on %s "
1085c58794deSPawel Jakub Dawidek 				    "(error=%d).", pp->name, err);
1086c58794deSPawel Jakub Dawidek 				if (error == 0)
1087c58794deSPawel Jakub Dawidek 					error = err;
1088c58794deSPawel Jakub Dawidek 			}
1089350e8df8SPawel Jakub Dawidek 			/*
1090350e8df8SPawel Jakub Dawidek 			 * Flush write cache so we don't overwrite data N times
1091350e8df8SPawel Jakub Dawidek 			 * in cache and only once on disk.
1092350e8df8SPawel Jakub Dawidek 			 */
1093350e8df8SPawel Jakub Dawidek 			(void)g_io_flush(cp);
1094c58794deSPawel Jakub Dawidek 		}
1095c58794deSPawel Jakub Dawidek 		free(sector, M_ELI);
109685059016SPawel Jakub Dawidek 	}
1097c58794deSPawel Jakub Dawidek 	if (error == 0)
1098c58794deSPawel Jakub Dawidek 		G_ELI_DEBUG(0, "%s has been killed.", pp->name);
10995ad4a7c7SPawel Jakub Dawidek 	g_eli_destroy(sc, TRUE);
1100c58794deSPawel Jakub Dawidek 	return (error);
1101c58794deSPawel Jakub Dawidek }
1102c58794deSPawel Jakub Dawidek 
1103c58794deSPawel Jakub Dawidek static void
g_eli_ctl_kill(struct gctl_req * req,struct g_class * mp)1104c58794deSPawel Jakub Dawidek g_eli_ctl_kill(struct gctl_req *req, struct g_class *mp)
1105c58794deSPawel Jakub Dawidek {
1106c58794deSPawel Jakub Dawidek 	int *all, *nargs;
1107c58794deSPawel Jakub Dawidek 	int error;
1108c58794deSPawel Jakub Dawidek 
1109c58794deSPawel Jakub Dawidek 	g_topology_assert();
1110c58794deSPawel Jakub Dawidek 
1111c58794deSPawel Jakub Dawidek 	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
1112c58794deSPawel Jakub Dawidek 	if (nargs == NULL) {
1113c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "nargs");
1114c58794deSPawel Jakub Dawidek 		return;
1115c58794deSPawel Jakub Dawidek 	}
1116c58794deSPawel Jakub Dawidek 	all = gctl_get_paraml(req, "all", sizeof(*all));
1117c58794deSPawel Jakub Dawidek 	if (all == NULL) {
1118c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "all");
1119c58794deSPawel Jakub Dawidek 		return;
1120c58794deSPawel Jakub Dawidek 	}
1121c58794deSPawel Jakub Dawidek 	if (!*all && *nargs == 0) {
1122c58794deSPawel Jakub Dawidek 		gctl_error(req, "Too few arguments.");
1123c58794deSPawel Jakub Dawidek 		return;
1124c58794deSPawel Jakub Dawidek 	}
1125c58794deSPawel Jakub Dawidek 
1126c58794deSPawel Jakub Dawidek 	if (*all) {
1127c58794deSPawel Jakub Dawidek 		struct g_geom *gp, *gp2;
1128c58794deSPawel Jakub Dawidek 
1129c58794deSPawel Jakub Dawidek 		LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) {
1130c58794deSPawel Jakub Dawidek 			error = g_eli_kill_one(gp->softc);
1131c58794deSPawel Jakub Dawidek 			if (error != 0)
1132c58794deSPawel Jakub Dawidek 				gctl_error(req, "Not fully done.");
1133c58794deSPawel Jakub Dawidek 		}
1134c58794deSPawel Jakub Dawidek 	} else {
1135c58794deSPawel Jakub Dawidek 		struct g_eli_softc *sc;
1136c58794deSPawel Jakub Dawidek 		const char *prov;
1137c58794deSPawel Jakub Dawidek 		char param[16];
1138c58794deSPawel Jakub Dawidek 		int i;
1139c58794deSPawel Jakub Dawidek 
1140c58794deSPawel Jakub Dawidek 		for (i = 0; i < *nargs; i++) {
11417d54b385SPawel Jakub Dawidek 			snprintf(param, sizeof(param), "arg%d", i);
1142c58794deSPawel Jakub Dawidek 			prov = gctl_get_asciiparam(req, param);
1143b5f30223SPawel Jakub Dawidek 			if (prov == NULL) {
1144b5f30223SPawel Jakub Dawidek 				G_ELI_DEBUG(0, "No 'arg%d' argument.", i);
1145b5f30223SPawel Jakub Dawidek 				continue;
1146b5f30223SPawel Jakub Dawidek 			}
1147c58794deSPawel Jakub Dawidek 
1148c58794deSPawel Jakub Dawidek 			sc = g_eli_find_device(mp, prov);
1149c58794deSPawel Jakub Dawidek 			if (sc == NULL) {
11507d54b385SPawel Jakub Dawidek 				G_ELI_DEBUG(0, "No such provider: %s.", prov);
1151c58794deSPawel Jakub Dawidek 				continue;
1152c58794deSPawel Jakub Dawidek 			}
1153c58794deSPawel Jakub Dawidek 			error = g_eli_kill_one(sc);
1154c58794deSPawel Jakub Dawidek 			if (error != 0)
1155c58794deSPawel Jakub Dawidek 				gctl_error(req, "Not fully done.");
1156c58794deSPawel Jakub Dawidek 		}
1157c58794deSPawel Jakub Dawidek 	}
1158c58794deSPawel Jakub Dawidek }
1159c58794deSPawel Jakub Dawidek 
1160c58794deSPawel Jakub Dawidek void
g_eli_config(struct gctl_req * req,struct g_class * mp,const char * verb)1161c58794deSPawel Jakub Dawidek g_eli_config(struct gctl_req *req, struct g_class *mp, const char *verb)
1162c58794deSPawel Jakub Dawidek {
1163c58794deSPawel Jakub Dawidek 	uint32_t *version;
1164c58794deSPawel Jakub Dawidek 
1165c58794deSPawel Jakub Dawidek 	g_topology_assert();
1166c58794deSPawel Jakub Dawidek 
1167c58794deSPawel Jakub Dawidek 	version = gctl_get_paraml(req, "version", sizeof(*version));
1168c58794deSPawel Jakub Dawidek 	if (version == NULL) {
1169c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "version");
1170c58794deSPawel Jakub Dawidek 		return;
1171c58794deSPawel Jakub Dawidek 	}
1172731adc86SPawel Jakub Dawidek 	while (*version != G_ELI_VERSION) {
1173731adc86SPawel Jakub Dawidek 		if (G_ELI_VERSION == G_ELI_VERSION_06 &&
1174731adc86SPawel Jakub Dawidek 		    *version == G_ELI_VERSION_05) {
1175731adc86SPawel Jakub Dawidek 			/* Compatible. */
1176731adc86SPawel Jakub Dawidek 			break;
1177731adc86SPawel Jakub Dawidek 		}
1178457bbc4fSPawel Jakub Dawidek 		if (G_ELI_VERSION == G_ELI_VERSION_07 &&
1179457bbc4fSPawel Jakub Dawidek 		    (*version == G_ELI_VERSION_05 ||
1180457bbc4fSPawel Jakub Dawidek 		     *version == G_ELI_VERSION_06)) {
1181457bbc4fSPawel Jakub Dawidek 			/* Compatible. */
1182457bbc4fSPawel Jakub Dawidek 			break;
1183457bbc4fSPawel Jakub Dawidek 		}
1184c58794deSPawel Jakub Dawidek 		gctl_error(req, "Userland and kernel parts are out of sync.");
1185c58794deSPawel Jakub Dawidek 		return;
1186c58794deSPawel Jakub Dawidek 	}
1187c58794deSPawel Jakub Dawidek 
1188c58794deSPawel Jakub Dawidek 	if (strcmp(verb, "attach") == 0)
1189c58794deSPawel Jakub Dawidek 		g_eli_ctl_attach(req, mp);
1190c58794deSPawel Jakub Dawidek 	else if (strcmp(verb, "detach") == 0 || strcmp(verb, "stop") == 0)
1191c58794deSPawel Jakub Dawidek 		g_eli_ctl_detach(req, mp);
1192c58794deSPawel Jakub Dawidek 	else if (strcmp(verb, "onetime") == 0)
1193c58794deSPawel Jakub Dawidek 		g_eli_ctl_onetime(req, mp);
11948abd1ad1SPawel Jakub Dawidek 	else if (strcmp(verb, "configure") == 0)
11958abd1ad1SPawel Jakub Dawidek 		g_eli_ctl_configure(req, mp);
1196c58794deSPawel Jakub Dawidek 	else if (strcmp(verb, "setkey") == 0)
1197c58794deSPawel Jakub Dawidek 		g_eli_ctl_setkey(req, mp);
1198c58794deSPawel Jakub Dawidek 	else if (strcmp(verb, "delkey") == 0)
1199c58794deSPawel Jakub Dawidek 		g_eli_ctl_delkey(req, mp);
12005ad4a7c7SPawel Jakub Dawidek 	else if (strcmp(verb, "suspend") == 0)
12015ad4a7c7SPawel Jakub Dawidek 		g_eli_ctl_suspend(req, mp);
12025ad4a7c7SPawel Jakub Dawidek 	else if (strcmp(verb, "resume") == 0)
12035ad4a7c7SPawel Jakub Dawidek 		g_eli_ctl_resume(req, mp);
1204c58794deSPawel Jakub Dawidek 	else if (strcmp(verb, "kill") == 0)
1205c58794deSPawel Jakub Dawidek 		g_eli_ctl_kill(req, mp);
1206c58794deSPawel Jakub Dawidek 	else
1207c58794deSPawel Jakub Dawidek 		gctl_error(req, "Unknown verb.");
1208c58794deSPawel Jakub Dawidek }
1209