xref: /freebsd/sys/geom/eli/g_eli_ctl.c (revision c58794debd2bfe8cfe8b69483080d0e7b3fcb3ed)
1c58794deSPawel Jakub Dawidek /*-
2c58794deSPawel Jakub Dawidek  * Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
3c58794deSPawel Jakub Dawidek  * All rights reserved.
4c58794deSPawel Jakub Dawidek  *
5c58794deSPawel Jakub Dawidek  * Redistribution and use in source and binary forms, with or without
6c58794deSPawel Jakub Dawidek  * modification, are permitted provided that the following conditions
7c58794deSPawel Jakub Dawidek  * are met:
8c58794deSPawel Jakub Dawidek  * 1. Redistributions of source code must retain the above copyright
9c58794deSPawel Jakub Dawidek  *    notice, this list of conditions and the following disclaimer.
10c58794deSPawel Jakub Dawidek  * 2. Redistributions in binary form must reproduce the above copyright
11c58794deSPawel Jakub Dawidek  *    notice, this list of conditions and the following disclaimer in the
12c58794deSPawel Jakub Dawidek  *    documentation and/or other materials provided with the distribution.
13c58794deSPawel Jakub Dawidek  *
14c58794deSPawel Jakub Dawidek  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
15c58794deSPawel Jakub Dawidek  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16c58794deSPawel Jakub Dawidek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17c58794deSPawel Jakub Dawidek  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
18c58794deSPawel Jakub Dawidek  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19c58794deSPawel Jakub Dawidek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20c58794deSPawel Jakub Dawidek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21c58794deSPawel Jakub Dawidek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22c58794deSPawel Jakub Dawidek  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23c58794deSPawel Jakub Dawidek  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24c58794deSPawel Jakub Dawidek  * SUCH DAMAGE.
25c58794deSPawel Jakub Dawidek  */
26c58794deSPawel Jakub Dawidek 
27c58794deSPawel Jakub Dawidek #include <sys/cdefs.h>
28c58794deSPawel Jakub Dawidek __FBSDID("$FreeBSD$");
29c58794deSPawel Jakub Dawidek 
30c58794deSPawel Jakub Dawidek #include <sys/param.h>
31c58794deSPawel Jakub Dawidek #include <sys/systm.h>
32c58794deSPawel Jakub Dawidek #include <sys/kernel.h>
33c58794deSPawel Jakub Dawidek #include <sys/module.h>
34c58794deSPawel Jakub Dawidek #include <sys/lock.h>
35c58794deSPawel Jakub Dawidek #include <sys/mutex.h>
36c58794deSPawel Jakub Dawidek #include <sys/bio.h>
37c58794deSPawel Jakub Dawidek #include <sys/sysctl.h>
38c58794deSPawel Jakub Dawidek #include <sys/malloc.h>
39c58794deSPawel Jakub Dawidek #include <sys/kthread.h>
40c58794deSPawel Jakub Dawidek #include <sys/proc.h>
41c58794deSPawel Jakub Dawidek #include <sys/sched.h>
42c58794deSPawel Jakub Dawidek #include <sys/uio.h>
43c58794deSPawel Jakub Dawidek 
44c58794deSPawel Jakub Dawidek #include <vm/uma.h>
45c58794deSPawel Jakub Dawidek 
46c58794deSPawel Jakub Dawidek #include <geom/geom.h>
47c58794deSPawel Jakub Dawidek #include <geom/eli/g_eli.h>
48c58794deSPawel Jakub Dawidek 
49c58794deSPawel Jakub Dawidek 
50c58794deSPawel Jakub Dawidek MALLOC_DECLARE(M_ELI);
51c58794deSPawel Jakub Dawidek 
52c58794deSPawel Jakub Dawidek 
53c58794deSPawel Jakub Dawidek static void
54c58794deSPawel Jakub Dawidek g_eli_ctl_attach(struct gctl_req *req, struct g_class *mp)
55c58794deSPawel Jakub Dawidek {
56c58794deSPawel Jakub Dawidek 	struct g_eli_metadata md;
57c58794deSPawel Jakub Dawidek 	struct g_provider *pp;
58c58794deSPawel Jakub Dawidek 	const char *name;
59c58794deSPawel Jakub Dawidek 	u_char *key, mkey[G_ELI_DATAIVKEYLEN];
60c58794deSPawel Jakub Dawidek 	int *nargs, *detach;
61c58794deSPawel Jakub Dawidek 	int keysize, error;
62c58794deSPawel Jakub Dawidek 	u_int nkey;
63c58794deSPawel Jakub Dawidek 
64c58794deSPawel Jakub Dawidek 	g_topology_assert();
65c58794deSPawel Jakub Dawidek 
66c58794deSPawel Jakub Dawidek 	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
67c58794deSPawel Jakub Dawidek 	if (nargs == NULL) {
68c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "nargs");
69c58794deSPawel Jakub Dawidek 		return;
70c58794deSPawel Jakub Dawidek 	}
71c58794deSPawel Jakub Dawidek 	if (*nargs != 1) {
72c58794deSPawel Jakub Dawidek 		gctl_error(req, "Invalid number of arguments.");
73c58794deSPawel Jakub Dawidek 		return;
74c58794deSPawel Jakub Dawidek 	}
75c58794deSPawel Jakub Dawidek 
76c58794deSPawel Jakub Dawidek 	detach = gctl_get_paraml(req, "detach", sizeof(*detach));
77c58794deSPawel Jakub Dawidek 	if (detach == NULL) {
78c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "detach");
79c58794deSPawel Jakub Dawidek 		return;
80c58794deSPawel Jakub Dawidek 	}
81c58794deSPawel Jakub Dawidek 
82c58794deSPawel Jakub Dawidek 	name = gctl_get_asciiparam(req, "arg0");
83c58794deSPawel Jakub Dawidek 	if (name == NULL) {
84c58794deSPawel Jakub Dawidek 		gctl_error(req, "No 'arg%u' argument.", 0);
85c58794deSPawel Jakub Dawidek 		return;
86c58794deSPawel Jakub Dawidek 	}
87c58794deSPawel Jakub Dawidek 	if (strncmp(name, "/dev/", strlen("/dev/")) == 0)
88c58794deSPawel Jakub Dawidek 		name += strlen("/dev/");
89c58794deSPawel Jakub Dawidek 	pp = g_provider_by_name(name);
90c58794deSPawel Jakub Dawidek 	if (pp == NULL) {
91c58794deSPawel Jakub Dawidek 		gctl_error(req, "Provider %s is invalid.", name);
92c58794deSPawel Jakub Dawidek 		return;
93c58794deSPawel Jakub Dawidek 	}
94c58794deSPawel Jakub Dawidek 	error = g_eli_read_metadata(mp, pp, &md);
95c58794deSPawel Jakub Dawidek 	if (error != 0) {
96c58794deSPawel Jakub Dawidek 		gctl_error(req, "Cannot read metadata from %s (error=%d).",
97c58794deSPawel Jakub Dawidek 		    name, error);
98c58794deSPawel Jakub Dawidek 		return;
99c58794deSPawel Jakub Dawidek 	}
100c58794deSPawel Jakub Dawidek 	if (md.md_keys == 0x00) {
101c58794deSPawel Jakub Dawidek 		bzero(&md, sizeof(md));
102c58794deSPawel Jakub Dawidek 		gctl_error(req, "No valid keys on %s.", pp->name);
103c58794deSPawel Jakub Dawidek 		return;
104c58794deSPawel Jakub Dawidek 	}
105c58794deSPawel Jakub Dawidek 
106c58794deSPawel Jakub Dawidek 	key = gctl_get_param(req, "key", &keysize);
107c58794deSPawel Jakub Dawidek 	if (key == NULL || keysize != G_ELI_USERKEYLEN) {
108c58794deSPawel Jakub Dawidek 		bzero(&md, sizeof(md));
109c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "key");
110c58794deSPawel Jakub Dawidek 		return;
111c58794deSPawel Jakub Dawidek 	}
112c58794deSPawel Jakub Dawidek 
113c58794deSPawel Jakub Dawidek 	error = g_eli_mkey_decrypt(&md, key, mkey, &nkey);
114c58794deSPawel Jakub Dawidek 	bzero(key, keysize);
115c58794deSPawel Jakub Dawidek 	if (error == -1) {
116c58794deSPawel Jakub Dawidek 		bzero(&md, sizeof(md));
117c58794deSPawel Jakub Dawidek 		gctl_error(req, "Wrong key for %s.", pp->name);
118c58794deSPawel Jakub Dawidek 		return;
119c58794deSPawel Jakub Dawidek 	} else if (error > 0) {
120c58794deSPawel Jakub Dawidek 		bzero(&md, sizeof(md));
121c58794deSPawel Jakub Dawidek 		gctl_error(req, "Cannot decrypt Master Key for %s (error=%d).",
122c58794deSPawel Jakub Dawidek 		    pp->name, error);
123c58794deSPawel Jakub Dawidek 		return;
124c58794deSPawel Jakub Dawidek 	}
125c58794deSPawel Jakub Dawidek 	G_ELI_DEBUG(1, "Using Master Key %u for %s.", nkey, pp->name);
126c58794deSPawel Jakub Dawidek 
127c58794deSPawel Jakub Dawidek 	if (*detach)
128c58794deSPawel Jakub Dawidek 		md.md_flags |= G_ELI_FLAG_WO_DETACH;
129c58794deSPawel Jakub Dawidek 	g_eli_create(req, mp, pp, &md, mkey, nkey);
130c58794deSPawel Jakub Dawidek 	bzero(mkey, sizeof(mkey));
131c58794deSPawel Jakub Dawidek 	bzero(&md, sizeof(md));
132c58794deSPawel Jakub Dawidek }
133c58794deSPawel Jakub Dawidek 
134c58794deSPawel Jakub Dawidek static struct g_eli_softc *
135c58794deSPawel Jakub Dawidek g_eli_find_device(struct g_class *mp, const char *prov)
136c58794deSPawel Jakub Dawidek {
137c58794deSPawel Jakub Dawidek 	struct g_eli_softc *sc;
138c58794deSPawel Jakub Dawidek 	struct g_geom *gp;
139c58794deSPawel Jakub Dawidek 	struct g_provider *pp;
140c58794deSPawel Jakub Dawidek 	struct g_consumer *cp;
141c58794deSPawel Jakub Dawidek 
142c58794deSPawel Jakub Dawidek 	if (strncmp(prov, "/dev/", strlen("/dev/")) == 0)
143c58794deSPawel Jakub Dawidek 		prov += strlen("/dev/");
144c58794deSPawel Jakub Dawidek 	LIST_FOREACH(gp, &mp->geom, geom) {
145c58794deSPawel Jakub Dawidek 		sc = gp->softc;
146c58794deSPawel Jakub Dawidek 		if (sc == NULL)
147c58794deSPawel Jakub Dawidek 			continue;
148c58794deSPawel Jakub Dawidek 		pp = LIST_FIRST(&gp->provider);
149c58794deSPawel Jakub Dawidek 		if (pp != NULL && strcmp(pp->name, prov) == 0)
150c58794deSPawel Jakub Dawidek 			return (sc);
151c58794deSPawel Jakub Dawidek 		cp = LIST_FIRST(&gp->consumer);
152c58794deSPawel Jakub Dawidek 		if (cp != NULL && cp->provider != NULL &&
153c58794deSPawel Jakub Dawidek 		    strcmp(cp->provider->name, prov) == 0) {
154c58794deSPawel Jakub Dawidek 			return (sc);
155c58794deSPawel Jakub Dawidek 		}
156c58794deSPawel Jakub Dawidek 	}
157c58794deSPawel Jakub Dawidek 	return (NULL);
158c58794deSPawel Jakub Dawidek }
159c58794deSPawel Jakub Dawidek 
160c58794deSPawel Jakub Dawidek static void
161c58794deSPawel Jakub Dawidek g_eli_ctl_detach(struct gctl_req *req, struct g_class *mp)
162c58794deSPawel Jakub Dawidek {
163c58794deSPawel Jakub Dawidek 	struct g_eli_softc *sc;
164c58794deSPawel Jakub Dawidek 	int *force, *last, *nargs, error;
165c58794deSPawel Jakub Dawidek 	const char *prov;
166c58794deSPawel Jakub Dawidek 	char param[16];
167c58794deSPawel Jakub Dawidek 	u_int i;
168c58794deSPawel Jakub Dawidek 
169c58794deSPawel Jakub Dawidek 	g_topology_assert();
170c58794deSPawel Jakub Dawidek 
171c58794deSPawel Jakub Dawidek 	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
172c58794deSPawel Jakub Dawidek 	if (nargs == NULL) {
173c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "nargs");
174c58794deSPawel Jakub Dawidek 		return;
175c58794deSPawel Jakub Dawidek 	}
176c58794deSPawel Jakub Dawidek 	if (*nargs <= 0) {
177c58794deSPawel Jakub Dawidek 		gctl_error(req, "Missing device(s).");
178c58794deSPawel Jakub Dawidek 		return;
179c58794deSPawel Jakub Dawidek 	}
180c58794deSPawel Jakub Dawidek 	force = gctl_get_paraml(req, "force", sizeof(*force));
181c58794deSPawel Jakub Dawidek 	if (force == NULL) {
182c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "force");
183c58794deSPawel Jakub Dawidek 		return;
184c58794deSPawel Jakub Dawidek 	}
185c58794deSPawel Jakub Dawidek 	last = gctl_get_paraml(req, "last", sizeof(*last));
186c58794deSPawel Jakub Dawidek 	if (last == NULL) {
187c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "last");
188c58794deSPawel Jakub Dawidek 		return;
189c58794deSPawel Jakub Dawidek 	}
190c58794deSPawel Jakub Dawidek 
191c58794deSPawel Jakub Dawidek 	for (i = 0; i < (u_int)*nargs; i++) {
192c58794deSPawel Jakub Dawidek 		snprintf(param, sizeof(param), "arg%u", i);
193c58794deSPawel Jakub Dawidek 		prov = gctl_get_asciiparam(req, param);
194c58794deSPawel Jakub Dawidek 		if (prov == NULL) {
195c58794deSPawel Jakub Dawidek 			gctl_error(req, "No 'arg%u' argument.", i);
196c58794deSPawel Jakub Dawidek 			return;
197c58794deSPawel Jakub Dawidek 		}
198c58794deSPawel Jakub Dawidek 		sc = g_eli_find_device(mp, prov);
199c58794deSPawel Jakub Dawidek 		if (sc == NULL) {
200c58794deSPawel Jakub Dawidek 			gctl_error(req, "No such device: %s.", prov);
201c58794deSPawel Jakub Dawidek 			return;
202c58794deSPawel Jakub Dawidek 		}
203c58794deSPawel Jakub Dawidek 		if (*last) {
204c58794deSPawel Jakub Dawidek 			sc->sc_flags |= G_ELI_FLAG_RW_DETACH;
205c58794deSPawel Jakub Dawidek 			sc->sc_geom->access = g_eli_access;
206c58794deSPawel Jakub Dawidek 		} else {
207c58794deSPawel Jakub Dawidek 			error = g_eli_destroy(sc, *force);
208c58794deSPawel Jakub Dawidek 			if (error != 0) {
209c58794deSPawel Jakub Dawidek 				gctl_error(req,
210c58794deSPawel Jakub Dawidek 				    "Cannot destroy device %s (error=%d).",
211c58794deSPawel Jakub Dawidek 				    sc->sc_name, error);
212c58794deSPawel Jakub Dawidek 				return;
213c58794deSPawel Jakub Dawidek 			}
214c58794deSPawel Jakub Dawidek 		}
215c58794deSPawel Jakub Dawidek 	}
216c58794deSPawel Jakub Dawidek }
217c58794deSPawel Jakub Dawidek 
218c58794deSPawel Jakub Dawidek static void
219c58794deSPawel Jakub Dawidek g_eli_ctl_onetime(struct gctl_req *req, struct g_class *mp)
220c58794deSPawel Jakub Dawidek {
221c58794deSPawel Jakub Dawidek 	struct g_eli_metadata md;
222c58794deSPawel Jakub Dawidek 	struct g_provider *pp;
223c58794deSPawel Jakub Dawidek 	const char *name;
224c58794deSPawel Jakub Dawidek 	intmax_t *keylen, *sectorsize;
225c58794deSPawel Jakub Dawidek 	u_char mkey[G_ELI_DATAIVKEYLEN];
226c58794deSPawel Jakub Dawidek 	int *nargs, *detach;
227c58794deSPawel Jakub Dawidek 
228c58794deSPawel Jakub Dawidek 	g_topology_assert();
229c58794deSPawel Jakub Dawidek 	bzero(&md, sizeof(md));
230c58794deSPawel Jakub Dawidek 
231c58794deSPawel Jakub Dawidek 	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
232c58794deSPawel Jakub Dawidek 	if (nargs == NULL) {
233c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "nargs");
234c58794deSPawel Jakub Dawidek 		return;
235c58794deSPawel Jakub Dawidek 	}
236c58794deSPawel Jakub Dawidek 	if (*nargs != 1) {
237c58794deSPawel Jakub Dawidek 		gctl_error(req, "Invalid number of arguments.");
238c58794deSPawel Jakub Dawidek 		return;
239c58794deSPawel Jakub Dawidek 	}
240c58794deSPawel Jakub Dawidek 
241c58794deSPawel Jakub Dawidek 	detach = gctl_get_paraml(req, "detach", sizeof(*detach));
242c58794deSPawel Jakub Dawidek 	if (detach == NULL) {
243c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "detach");
244c58794deSPawel Jakub Dawidek 		return;
245c58794deSPawel Jakub Dawidek 	}
246c58794deSPawel Jakub Dawidek 
247c58794deSPawel Jakub Dawidek 	strlcpy(md.md_magic, G_ELI_MAGIC, sizeof(md.md_magic));
248c58794deSPawel Jakub Dawidek 	md.md_version = G_ELI_VERSION;
249c58794deSPawel Jakub Dawidek 	md.md_flags |= G_ELI_FLAG_ONETIME;
250c58794deSPawel Jakub Dawidek 	if (*detach)
251c58794deSPawel Jakub Dawidek 		md.md_flags |= G_ELI_FLAG_WO_DETACH;
252c58794deSPawel Jakub Dawidek 
253c58794deSPawel Jakub Dawidek 	name = gctl_get_asciiparam(req, "algo");
254c58794deSPawel Jakub Dawidek 	if (name == NULL) {
255c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "algo");
256c58794deSPawel Jakub Dawidek 		return;
257c58794deSPawel Jakub Dawidek 	}
258c58794deSPawel Jakub Dawidek 	md.md_algo = g_eli_str2algo(name);
259c58794deSPawel Jakub Dawidek 	if (md.md_algo < CRYPTO_ALGORITHM_MIN ||
260c58794deSPawel Jakub Dawidek 	    md.md_algo > CRYPTO_ALGORITHM_MAX) {
261c58794deSPawel Jakub Dawidek 		gctl_error(req, "Invalid '%s' argument.", "algo");
262c58794deSPawel Jakub Dawidek 		return;
263c58794deSPawel Jakub Dawidek 	}
264c58794deSPawel Jakub Dawidek 
265c58794deSPawel Jakub Dawidek 	keylen = gctl_get_paraml(req, "keylen", sizeof(*keylen));
266c58794deSPawel Jakub Dawidek 	if (keylen == NULL) {
267c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "keylen");
268c58794deSPawel Jakub Dawidek 		return;
269c58794deSPawel Jakub Dawidek 	}
270c58794deSPawel Jakub Dawidek 	md.md_keylen = g_eli_keylen(md.md_algo, *keylen);
271c58794deSPawel Jakub Dawidek 	if (md.md_keylen == 0) {
272c58794deSPawel Jakub Dawidek 		gctl_error(req, "Invalid '%s' argument.", "keylen");
273c58794deSPawel Jakub Dawidek 		return;
274c58794deSPawel Jakub Dawidek 	}
275c58794deSPawel Jakub Dawidek 
276c58794deSPawel Jakub Dawidek 	/* Not important here. */
277c58794deSPawel Jakub Dawidek 	md.md_provsize = 0;
278c58794deSPawel Jakub Dawidek 	/* Not important here. */
279c58794deSPawel Jakub Dawidek 	bzero(md.md_salt, sizeof(md.md_salt));
280c58794deSPawel Jakub Dawidek 
281c58794deSPawel Jakub Dawidek 	md.md_keys = 0x01;
282c58794deSPawel Jakub Dawidek 	arc4rand(mkey, sizeof(mkey), 0);
283c58794deSPawel Jakub Dawidek 
284c58794deSPawel Jakub Dawidek 	/* Not important here. */
285c58794deSPawel Jakub Dawidek 	bzero(md.md_hash, sizeof(md.md_hash));
286c58794deSPawel Jakub Dawidek 
287c58794deSPawel Jakub Dawidek 	name = gctl_get_asciiparam(req, "arg0");
288c58794deSPawel Jakub Dawidek 	if (name == NULL) {
289c58794deSPawel Jakub Dawidek 		gctl_error(req, "No 'arg%u' argument.", 0);
290c58794deSPawel Jakub Dawidek 		return;
291c58794deSPawel Jakub Dawidek 	}
292c58794deSPawel Jakub Dawidek 	if (strncmp(name, "/dev/", strlen("/dev/")) == 0)
293c58794deSPawel Jakub Dawidek 		name += strlen("/dev/");
294c58794deSPawel Jakub Dawidek 	pp = g_provider_by_name(name);
295c58794deSPawel Jakub Dawidek 	if (pp == NULL) {
296c58794deSPawel Jakub Dawidek 		gctl_error(req, "Provider %s is invalid.", name);
297c58794deSPawel Jakub Dawidek 		return;
298c58794deSPawel Jakub Dawidek 	}
299c58794deSPawel Jakub Dawidek 
300c58794deSPawel Jakub Dawidek 	sectorsize = gctl_get_paraml(req, "sectorsize", sizeof(*sectorsize));
301c58794deSPawel Jakub Dawidek 	if (sectorsize == NULL) {
302c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "sectorsize");
303c58794deSPawel Jakub Dawidek 		return;
304c58794deSPawel Jakub Dawidek 	}
305c58794deSPawel Jakub Dawidek 	if (*sectorsize == 0)
306c58794deSPawel Jakub Dawidek 		md.md_sectorsize = pp->sectorsize;
307c58794deSPawel Jakub Dawidek 	else {
308c58794deSPawel Jakub Dawidek 		if (*sectorsize < 0 || (*sectorsize % pp->sectorsize) != 0) {
309c58794deSPawel Jakub Dawidek 			gctl_error(req, "Invalid sector size.");
310c58794deSPawel Jakub Dawidek 			return;
311c58794deSPawel Jakub Dawidek 		}
312c58794deSPawel Jakub Dawidek 		md.md_sectorsize = *sectorsize;
313c58794deSPawel Jakub Dawidek 	}
314c58794deSPawel Jakub Dawidek 
315c58794deSPawel Jakub Dawidek 	g_eli_create(req, mp, pp, &md, mkey, -1);
316c58794deSPawel Jakub Dawidek 	bzero(mkey, sizeof(mkey));
317c58794deSPawel Jakub Dawidek 	bzero(&md, sizeof(md));
318c58794deSPawel Jakub Dawidek }
319c58794deSPawel Jakub Dawidek 
320c58794deSPawel Jakub Dawidek static void
321c58794deSPawel Jakub Dawidek g_eli_ctl_setkey(struct gctl_req *req, struct g_class *mp)
322c58794deSPawel Jakub Dawidek {
323c58794deSPawel Jakub Dawidek 	struct g_eli_softc *sc;
324c58794deSPawel Jakub Dawidek 	struct g_eli_metadata md;
325c58794deSPawel Jakub Dawidek 	struct g_provider *pp;
326c58794deSPawel Jakub Dawidek 	struct g_consumer *cp;
327c58794deSPawel Jakub Dawidek 	const char *name;
328c58794deSPawel Jakub Dawidek 	u_char *key, *mkeydst, *sector;
329c58794deSPawel Jakub Dawidek 	intmax_t *valp;
330c58794deSPawel Jakub Dawidek 	int nkey;
331c58794deSPawel Jakub Dawidek 	int keysize, error;
332c58794deSPawel Jakub Dawidek 
333c58794deSPawel Jakub Dawidek 	g_topology_assert();
334c58794deSPawel Jakub Dawidek 
335c58794deSPawel Jakub Dawidek 	name = gctl_get_asciiparam(req, "arg0");
336c58794deSPawel Jakub Dawidek 	if (name == NULL) {
337c58794deSPawel Jakub Dawidek 		gctl_error(req, "No 'arg%u' argument.", 0);
338c58794deSPawel Jakub Dawidek 		return;
339c58794deSPawel Jakub Dawidek 	}
340c58794deSPawel Jakub Dawidek 	sc = g_eli_find_device(mp, name);
341c58794deSPawel Jakub Dawidek 	if (sc == NULL) {
342c58794deSPawel Jakub Dawidek 		gctl_error(req, "Provider %s is invalid.", name);
343c58794deSPawel Jakub Dawidek 		return;
344c58794deSPawel Jakub Dawidek 	}
345c58794deSPawel Jakub Dawidek 	cp = LIST_FIRST(&sc->sc_geom->consumer);
346c58794deSPawel Jakub Dawidek 	pp = cp->provider;
347c58794deSPawel Jakub Dawidek 
348c58794deSPawel Jakub Dawidek 	error = g_eli_read_metadata(mp, pp, &md);
349c58794deSPawel Jakub Dawidek 	if (error != 0) {
350c58794deSPawel Jakub Dawidek 		gctl_error(req, "Cannot read metadata from %s (error=%d).",
351c58794deSPawel Jakub Dawidek 		    name, error);
352c58794deSPawel Jakub Dawidek 		return;
353c58794deSPawel Jakub Dawidek 	}
354c58794deSPawel Jakub Dawidek 
355c58794deSPawel Jakub Dawidek 	valp = gctl_get_paraml(req, "keyno", sizeof(*valp));
356c58794deSPawel Jakub Dawidek 	if (valp == NULL) {
357c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "keyno");
358c58794deSPawel Jakub Dawidek 		return;
359c58794deSPawel Jakub Dawidek 	}
360c58794deSPawel Jakub Dawidek 	if (*valp != -1)
361c58794deSPawel Jakub Dawidek 		nkey = *valp;
362c58794deSPawel Jakub Dawidek 	else
363c58794deSPawel Jakub Dawidek 		nkey = sc->sc_nkey;
364c58794deSPawel Jakub Dawidek 	if (nkey < 0 || nkey >= G_ELI_MAXMKEYS) {
365c58794deSPawel Jakub Dawidek 		gctl_error(req, "Invalid '%s' argument.", "keyno");
366c58794deSPawel Jakub Dawidek 		return;
367c58794deSPawel Jakub Dawidek 	}
368c58794deSPawel Jakub Dawidek 
369c58794deSPawel Jakub Dawidek 	key = gctl_get_param(req, "key", &keysize);
370c58794deSPawel Jakub Dawidek 	if (key == NULL || keysize != G_ELI_USERKEYLEN) {
371c58794deSPawel Jakub Dawidek 		bzero(&md, sizeof(md));
372c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "key");
373c58794deSPawel Jakub Dawidek 		return;
374c58794deSPawel Jakub Dawidek 	}
375c58794deSPawel Jakub Dawidek 
376c58794deSPawel Jakub Dawidek 	mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN;
377c58794deSPawel Jakub Dawidek 	md.md_keys |= (1 << nkey);
378c58794deSPawel Jakub Dawidek 
379c58794deSPawel Jakub Dawidek 	bcopy(sc->sc_ivkey, mkeydst, sizeof(sc->sc_ivkey));
380c58794deSPawel Jakub Dawidek 	bcopy(sc->sc_datakey, mkeydst + sizeof(sc->sc_ivkey),
381c58794deSPawel Jakub Dawidek 	    sizeof(sc->sc_datakey));
382c58794deSPawel Jakub Dawidek 
383c58794deSPawel Jakub Dawidek 	/* Encrypt Master Key with the new key. */
384c58794deSPawel Jakub Dawidek 	error = g_eli_mkey_encrypt(md.md_algo, key, md.md_keylen, mkeydst);
385c58794deSPawel Jakub Dawidek 	bzero(key, sizeof(key));
386c58794deSPawel Jakub Dawidek 	if (error != 0) {
387c58794deSPawel Jakub Dawidek 		bzero(&md, sizeof(md));
388c58794deSPawel Jakub Dawidek 		gctl_error(req, "Cannot encrypt Master Key (error=%d).", error);
389c58794deSPawel Jakub Dawidek 		return;
390c58794deSPawel Jakub Dawidek 	}
391c58794deSPawel Jakub Dawidek 
392c58794deSPawel Jakub Dawidek 	sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO);
393c58794deSPawel Jakub Dawidek 	/* Store metadata with fresh key. */
394c58794deSPawel Jakub Dawidek 	eli_metadata_encode(&md, sector);
395c58794deSPawel Jakub Dawidek 	bzero(&md, sizeof(md));
396c58794deSPawel Jakub Dawidek 	error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
397c58794deSPawel Jakub Dawidek 	    pp->sectorsize);
398c58794deSPawel Jakub Dawidek 	bzero(sector, sizeof(sector));
399c58794deSPawel Jakub Dawidek 	free(sector, M_ELI);
400c58794deSPawel Jakub Dawidek 	if (error != 0) {
401c58794deSPawel Jakub Dawidek 		gctl_error(req, "Cannot store metadata on %s (error=%d).",
402c58794deSPawel Jakub Dawidek 		    pp->name, error);
403c58794deSPawel Jakub Dawidek 		return;
404c58794deSPawel Jakub Dawidek 	}
405c58794deSPawel Jakub Dawidek 	G_ELI_DEBUG(1, "Key %u changed on %s.", nkey, pp->name);
406c58794deSPawel Jakub Dawidek }
407c58794deSPawel Jakub Dawidek 
408c58794deSPawel Jakub Dawidek static void
409c58794deSPawel Jakub Dawidek g_eli_ctl_delkey(struct gctl_req *req, struct g_class *mp)
410c58794deSPawel Jakub Dawidek {
411c58794deSPawel Jakub Dawidek 	struct g_eli_softc *sc;
412c58794deSPawel Jakub Dawidek 	struct g_eli_metadata md;
413c58794deSPawel Jakub Dawidek 	struct g_provider *pp;
414c58794deSPawel Jakub Dawidek 	struct g_consumer *cp;
415c58794deSPawel Jakub Dawidek 	const char *name;
416c58794deSPawel Jakub Dawidek 	u_char *mkeydst, *sector;
417c58794deSPawel Jakub Dawidek 	intmax_t *valp;
418c58794deSPawel Jakub Dawidek 	size_t keysize;
419c58794deSPawel Jakub Dawidek 	int error, nkey, *all, *force;
420c58794deSPawel Jakub Dawidek 	u_int i;
421c58794deSPawel Jakub Dawidek 
422c58794deSPawel Jakub Dawidek 	g_topology_assert();
423c58794deSPawel Jakub Dawidek 
424c58794deSPawel Jakub Dawidek 	nkey = 0;	/* fixes causeless gcc warning */
425c58794deSPawel Jakub Dawidek 
426c58794deSPawel Jakub Dawidek 	name = gctl_get_asciiparam(req, "arg0");
427c58794deSPawel Jakub Dawidek 	if (name == NULL) {
428c58794deSPawel Jakub Dawidek 		gctl_error(req, "No 'arg%u' argument.", 0);
429c58794deSPawel Jakub Dawidek 		return;
430c58794deSPawel Jakub Dawidek 	}
431c58794deSPawel Jakub Dawidek 	sc = g_eli_find_device(mp, name);
432c58794deSPawel Jakub Dawidek 	if (sc == NULL) {
433c58794deSPawel Jakub Dawidek 		gctl_error(req, "Provider %s is invalid.", name);
434c58794deSPawel Jakub Dawidek 		return;
435c58794deSPawel Jakub Dawidek 	}
436c58794deSPawel Jakub Dawidek 	cp = LIST_FIRST(&sc->sc_geom->consumer);
437c58794deSPawel Jakub Dawidek 	pp = cp->provider;
438c58794deSPawel Jakub Dawidek 
439c58794deSPawel Jakub Dawidek 	error = g_eli_read_metadata(mp, pp, &md);
440c58794deSPawel Jakub Dawidek 	if (error != 0) {
441c58794deSPawel Jakub Dawidek 		gctl_error(req, "Cannot read metadata from %s (error=%d).",
442c58794deSPawel Jakub Dawidek 		    name, error);
443c58794deSPawel Jakub Dawidek 		return;
444c58794deSPawel Jakub Dawidek 	}
445c58794deSPawel Jakub Dawidek 
446c58794deSPawel Jakub Dawidek 	all = gctl_get_paraml(req, "all", sizeof(*all));
447c58794deSPawel Jakub Dawidek 	if (all == NULL) {
448c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "all");
449c58794deSPawel Jakub Dawidek 		return;
450c58794deSPawel Jakub Dawidek 	}
451c58794deSPawel Jakub Dawidek 
452c58794deSPawel Jakub Dawidek 	if (*all) {
453c58794deSPawel Jakub Dawidek 		mkeydst = md.md_mkeys;
454c58794deSPawel Jakub Dawidek 		keysize = sizeof(md.md_mkeys);
455c58794deSPawel Jakub Dawidek 	} else {
456c58794deSPawel Jakub Dawidek 		force = gctl_get_paraml(req, "force", sizeof(*force));
457c58794deSPawel Jakub Dawidek 		if (force == NULL) {
458c58794deSPawel Jakub Dawidek 			gctl_error(req, "No '%s' argument.", "force");
459c58794deSPawel Jakub Dawidek 			return;
460c58794deSPawel Jakub Dawidek 		}
461c58794deSPawel Jakub Dawidek 
462c58794deSPawel Jakub Dawidek 		valp = gctl_get_paraml(req, "keyno", sizeof(*valp));
463c58794deSPawel Jakub Dawidek 		if (valp == NULL) {
464c58794deSPawel Jakub Dawidek 			gctl_error(req, "No '%s' argument.", "keyno");
465c58794deSPawel Jakub Dawidek 			return;
466c58794deSPawel Jakub Dawidek 		}
467c58794deSPawel Jakub Dawidek 		if (*valp != -1)
468c58794deSPawel Jakub Dawidek 			nkey = *valp;
469c58794deSPawel Jakub Dawidek 		else
470c58794deSPawel Jakub Dawidek 			nkey = sc->sc_nkey;
471c58794deSPawel Jakub Dawidek 		if (nkey < 0 || nkey >= G_ELI_MAXMKEYS) {
472c58794deSPawel Jakub Dawidek 			gctl_error(req, "Invalid '%s' argument.", "keyno");
473c58794deSPawel Jakub Dawidek 			return;
474c58794deSPawel Jakub Dawidek 		}
475c58794deSPawel Jakub Dawidek 		if (!(md.md_keys & (1 << nkey)) && !*force) {
476c58794deSPawel Jakub Dawidek 			gctl_error(req, "Master Key %u is not set.", nkey);
477c58794deSPawel Jakub Dawidek 			return;
478c58794deSPawel Jakub Dawidek 		}
479c58794deSPawel Jakub Dawidek 		md.md_keys &= ~(1 << nkey);
480c58794deSPawel Jakub Dawidek 		if (md.md_keys == 0 && !*force) {
481c58794deSPawel Jakub Dawidek 			gctl_error(req, "This is the last Master Key. Use '-f' "
482c58794deSPawel Jakub Dawidek 			    "flag if you really want to remove it.");
483c58794deSPawel Jakub Dawidek 			return;
484c58794deSPawel Jakub Dawidek 		}
485c58794deSPawel Jakub Dawidek 		mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN;
486c58794deSPawel Jakub Dawidek 		keysize = G_ELI_MKEYLEN;
487c58794deSPawel Jakub Dawidek 	}
488c58794deSPawel Jakub Dawidek 
489c58794deSPawel Jakub Dawidek 	sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO);
490c58794deSPawel Jakub Dawidek 	for (i = 0; i <= g_eli_overwrites; i++) {
491c58794deSPawel Jakub Dawidek 		if (i == g_eli_overwrites)
492c58794deSPawel Jakub Dawidek 			bzero(mkeydst, keysize);
493c58794deSPawel Jakub Dawidek 		else
494c58794deSPawel Jakub Dawidek 			arc4rand(mkeydst, keysize, 0);
495c58794deSPawel Jakub Dawidek 		/* Store metadata with destroyed key. */
496c58794deSPawel Jakub Dawidek 		eli_metadata_encode(&md, sector);
497c58794deSPawel Jakub Dawidek 		error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
498c58794deSPawel Jakub Dawidek 		    pp->sectorsize);
499c58794deSPawel Jakub Dawidek 		if (error != 0) {
500c58794deSPawel Jakub Dawidek 			G_ELI_DEBUG(0, "Cannot store metadata on %s "
501c58794deSPawel Jakub Dawidek 			    "(error=%d).", pp->name, error);
502c58794deSPawel Jakub Dawidek 		}
503c58794deSPawel Jakub Dawidek 	}
504c58794deSPawel Jakub Dawidek 	bzero(&md, sizeof(md));
505c58794deSPawel Jakub Dawidek 	bzero(sector, sizeof(sector));
506c58794deSPawel Jakub Dawidek 	free(sector, M_ELI);
507c58794deSPawel Jakub Dawidek 	if (*all)
508c58794deSPawel Jakub Dawidek 		G_ELI_DEBUG(1, "All keys removed from %s.", pp->name);
509c58794deSPawel Jakub Dawidek 	else
510c58794deSPawel Jakub Dawidek 		G_ELI_DEBUG(1, "Key %d removed from %s.", nkey, pp->name);
511c58794deSPawel Jakub Dawidek }
512c58794deSPawel Jakub Dawidek 
513c58794deSPawel Jakub Dawidek static int
514c58794deSPawel Jakub Dawidek g_eli_kill_one(struct g_eli_softc *sc)
515c58794deSPawel Jakub Dawidek {
516c58794deSPawel Jakub Dawidek 	struct g_provider *pp;
517c58794deSPawel Jakub Dawidek 	struct g_consumer *cp;
518c58794deSPawel Jakub Dawidek 	u_char *sector;
519c58794deSPawel Jakub Dawidek 	int err, error = 0;
520c58794deSPawel Jakub Dawidek 	u_int i;
521c58794deSPawel Jakub Dawidek 
522c58794deSPawel Jakub Dawidek 	g_topology_assert();
523c58794deSPawel Jakub Dawidek 
524c58794deSPawel Jakub Dawidek 	if (sc == NULL)
525c58794deSPawel Jakub Dawidek 		return (ENOENT);
526c58794deSPawel Jakub Dawidek 
527c58794deSPawel Jakub Dawidek 	pp = LIST_FIRST(&sc->sc_geom->provider);
528c58794deSPawel Jakub Dawidek 	g_error_provider(pp, ENXIO);
529c58794deSPawel Jakub Dawidek 
530c58794deSPawel Jakub Dawidek 	cp = LIST_FIRST(&sc->sc_geom->consumer);
531c58794deSPawel Jakub Dawidek 	pp = cp->provider;
532c58794deSPawel Jakub Dawidek 
533c58794deSPawel Jakub Dawidek 	sector = malloc(pp->sectorsize, M_ELI, M_WAITOK);
534c58794deSPawel Jakub Dawidek 	for (i = 0; i <= g_eli_overwrites; i++) {
535c58794deSPawel Jakub Dawidek 		if (i == g_eli_overwrites)
536c58794deSPawel Jakub Dawidek 			bzero(sector, pp->sectorsize);
537c58794deSPawel Jakub Dawidek 		else
538c58794deSPawel Jakub Dawidek 			arc4rand(sector, pp->sectorsize, 0);
539c58794deSPawel Jakub Dawidek 		err = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
540c58794deSPawel Jakub Dawidek 		    pp->sectorsize);
541c58794deSPawel Jakub Dawidek 		if (err != 0) {
542c58794deSPawel Jakub Dawidek 			G_ELI_DEBUG(0, "Cannot erase metadata on %s "
543c58794deSPawel Jakub Dawidek 			    "(error=%d).", pp->name, err);
544c58794deSPawel Jakub Dawidek 			if (error == 0)
545c58794deSPawel Jakub Dawidek 				error = err;
546c58794deSPawel Jakub Dawidek 		}
547c58794deSPawel Jakub Dawidek 	}
548c58794deSPawel Jakub Dawidek 	free(sector, M_ELI);
549c58794deSPawel Jakub Dawidek 	if (error == 0)
550c58794deSPawel Jakub Dawidek 		G_ELI_DEBUG(0, "%s has been killed.", pp->name);
551c58794deSPawel Jakub Dawidek 	g_eli_destroy(sc, 1);
552c58794deSPawel Jakub Dawidek 	return (error);
553c58794deSPawel Jakub Dawidek }
554c58794deSPawel Jakub Dawidek 
555c58794deSPawel Jakub Dawidek static void
556c58794deSPawel Jakub Dawidek g_eli_ctl_kill(struct gctl_req *req, struct g_class *mp)
557c58794deSPawel Jakub Dawidek {
558c58794deSPawel Jakub Dawidek 	int *all, *nargs;
559c58794deSPawel Jakub Dawidek 	int error;
560c58794deSPawel Jakub Dawidek 
561c58794deSPawel Jakub Dawidek 	g_topology_assert();
562c58794deSPawel Jakub Dawidek 
563c58794deSPawel Jakub Dawidek 	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
564c58794deSPawel Jakub Dawidek 	if (nargs == NULL) {
565c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "nargs");
566c58794deSPawel Jakub Dawidek 		return;
567c58794deSPawel Jakub Dawidek 	}
568c58794deSPawel Jakub Dawidek 	all = gctl_get_paraml(req, "all", sizeof(*all));
569c58794deSPawel Jakub Dawidek 	if (all == NULL) {
570c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "all");
571c58794deSPawel Jakub Dawidek 		return;
572c58794deSPawel Jakub Dawidek 	}
573c58794deSPawel Jakub Dawidek 	if (!*all && *nargs == 0) {
574c58794deSPawel Jakub Dawidek 		gctl_error(req, "Too few arguments.");
575c58794deSPawel Jakub Dawidek 		return;
576c58794deSPawel Jakub Dawidek 	}
577c58794deSPawel Jakub Dawidek 
578c58794deSPawel Jakub Dawidek 	if (*all) {
579c58794deSPawel Jakub Dawidek 		struct g_geom *gp, *gp2;
580c58794deSPawel Jakub Dawidek 
581c58794deSPawel Jakub Dawidek 		LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) {
582c58794deSPawel Jakub Dawidek 			error = g_eli_kill_one(gp->softc);
583c58794deSPawel Jakub Dawidek 			if (error != 0)
584c58794deSPawel Jakub Dawidek 				gctl_error(req, "Not fully done.");
585c58794deSPawel Jakub Dawidek 		}
586c58794deSPawel Jakub Dawidek 	} else {
587c58794deSPawel Jakub Dawidek 		struct g_eli_softc *sc;
588c58794deSPawel Jakub Dawidek 		const char *prov;
589c58794deSPawel Jakub Dawidek 		char param[16];
590c58794deSPawel Jakub Dawidek 		int i;
591c58794deSPawel Jakub Dawidek 
592c58794deSPawel Jakub Dawidek 		for (i = 0; i < *nargs; i++) {
593c58794deSPawel Jakub Dawidek 			snprintf(param, sizeof(param), "arg%u", i);
594c58794deSPawel Jakub Dawidek 			prov = gctl_get_asciiparam(req, param);
595c58794deSPawel Jakub Dawidek 
596c58794deSPawel Jakub Dawidek 			sc = g_eli_find_device(mp, prov);
597c58794deSPawel Jakub Dawidek 			if (sc == NULL) {
598c58794deSPawel Jakub Dawidek 				G_ELI_DEBUG(1, "No such provider: %s.", prov);
599c58794deSPawel Jakub Dawidek 				continue;
600c58794deSPawel Jakub Dawidek 			}
601c58794deSPawel Jakub Dawidek 			error = g_eli_kill_one(sc);
602c58794deSPawel Jakub Dawidek 			if (error != 0)
603c58794deSPawel Jakub Dawidek 				gctl_error(req, "Not fully done.");
604c58794deSPawel Jakub Dawidek 		}
605c58794deSPawel Jakub Dawidek 	}
606c58794deSPawel Jakub Dawidek }
607c58794deSPawel Jakub Dawidek 
608c58794deSPawel Jakub Dawidek void
609c58794deSPawel Jakub Dawidek g_eli_config(struct gctl_req *req, struct g_class *mp, const char *verb)
610c58794deSPawel Jakub Dawidek {
611c58794deSPawel Jakub Dawidek 	uint32_t *version;
612c58794deSPawel Jakub Dawidek 
613c58794deSPawel Jakub Dawidek 	g_topology_assert();
614c58794deSPawel Jakub Dawidek 
615c58794deSPawel Jakub Dawidek 	version = gctl_get_paraml(req, "version", sizeof(*version));
616c58794deSPawel Jakub Dawidek 	if (version == NULL) {
617c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "version");
618c58794deSPawel Jakub Dawidek 		return;
619c58794deSPawel Jakub Dawidek 	}
620c58794deSPawel Jakub Dawidek 	if (*version != G_ELI_VERSION) {
621c58794deSPawel Jakub Dawidek 		gctl_error(req, "Userland and kernel parts are out of sync.");
622c58794deSPawel Jakub Dawidek 		return;
623c58794deSPawel Jakub Dawidek 	}
624c58794deSPawel Jakub Dawidek 
625c58794deSPawel Jakub Dawidek 	if (strcmp(verb, "attach") == 0)
626c58794deSPawel Jakub Dawidek 		g_eli_ctl_attach(req, mp);
627c58794deSPawel Jakub Dawidek 	else if (strcmp(verb, "detach") == 0 || strcmp(verb, "stop") == 0)
628c58794deSPawel Jakub Dawidek 		g_eli_ctl_detach(req, mp);
629c58794deSPawel Jakub Dawidek 	else if (strcmp(verb, "onetime") == 0)
630c58794deSPawel Jakub Dawidek 		g_eli_ctl_onetime(req, mp);
631c58794deSPawel Jakub Dawidek 	else if (strcmp(verb, "setkey") == 0)
632c58794deSPawel Jakub Dawidek 		g_eli_ctl_setkey(req, mp);
633c58794deSPawel Jakub Dawidek 	else if (strcmp(verb, "delkey") == 0)
634c58794deSPawel Jakub Dawidek 		g_eli_ctl_delkey(req, mp);
635c58794deSPawel Jakub Dawidek 	else if (strcmp(verb, "kill") == 0)
636c58794deSPawel Jakub Dawidek 		g_eli_ctl_kill(req, mp);
637c58794deSPawel Jakub Dawidek 	else
638c58794deSPawel Jakub Dawidek 		gctl_error(req, "Unknown verb.");
639c58794deSPawel Jakub Dawidek }
640