xref: /freebsd/sys/geom/eli/g_eli_ctl.c (revision eaa3b91996d80ab0c2d5574e70773119f0f13dfc)
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];
1677d54b385SPawel Jakub Dawidek 	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 
1917d54b385SPawel Jakub Dawidek 	for (i = 0; i < *nargs; i++) {
1927d54b385SPawel Jakub Dawidek 		snprintf(param, sizeof(param), "arg%d", i);
193c58794deSPawel Jakub Dawidek 		prov = gctl_get_asciiparam(req, param);
194c58794deSPawel Jakub Dawidek 		if (prov == NULL) {
1957d54b385SPawel Jakub Dawidek 			gctl_error(req, "No 'arg%d' 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 
253eaa3b919SPawel Jakub Dawidek 	name = gctl_get_asciiparam(req, "aalgo");
254c58794deSPawel Jakub Dawidek 	if (name == NULL) {
255eaa3b919SPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "aalgo");
256c58794deSPawel Jakub Dawidek 		return;
257c58794deSPawel Jakub Dawidek 	}
258eaa3b919SPawel Jakub Dawidek 	if (strcmp(name, "none") != 0) {
259eaa3b919SPawel Jakub Dawidek 		md.md_aalgo = g_eli_str2aalgo(name);
260eaa3b919SPawel Jakub Dawidek 		if (md.md_aalgo < CRYPTO_ALGORITHM_MIN ||
261eaa3b919SPawel Jakub Dawidek 		    md.md_aalgo > CRYPTO_ALGORITHM_MAX) {
262eaa3b919SPawel Jakub Dawidek 			gctl_error(req, "Invalid authentication algorithm.");
263eaa3b919SPawel Jakub Dawidek 			return;
264eaa3b919SPawel Jakub Dawidek 		}
265eaa3b919SPawel Jakub Dawidek 		md.md_flags |= G_ELI_FLAG_AUTH;
266eaa3b919SPawel Jakub Dawidek 	}
267eaa3b919SPawel Jakub Dawidek 
268eaa3b919SPawel Jakub Dawidek 	name = gctl_get_asciiparam(req, "ealgo");
269eaa3b919SPawel Jakub Dawidek 	if (name == NULL) {
270eaa3b919SPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "ealgo");
271eaa3b919SPawel Jakub Dawidek 		return;
272eaa3b919SPawel Jakub Dawidek 	}
273eaa3b919SPawel Jakub Dawidek 	md.md_ealgo = g_eli_str2ealgo(name);
274eaa3b919SPawel Jakub Dawidek 	if (md.md_ealgo < CRYPTO_ALGORITHM_MIN ||
275eaa3b919SPawel Jakub Dawidek 	    md.md_ealgo > CRYPTO_ALGORITHM_MAX) {
276eaa3b919SPawel Jakub Dawidek 		gctl_error(req, "Invalid encryption algorithm.");
277c58794deSPawel Jakub Dawidek 		return;
278c58794deSPawel Jakub Dawidek 	}
279c58794deSPawel Jakub Dawidek 
280c58794deSPawel Jakub Dawidek 	keylen = gctl_get_paraml(req, "keylen", sizeof(*keylen));
281c58794deSPawel Jakub Dawidek 	if (keylen == NULL) {
282c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "keylen");
283c58794deSPawel Jakub Dawidek 		return;
284c58794deSPawel Jakub Dawidek 	}
285eaa3b919SPawel Jakub Dawidek 	md.md_keylen = g_eli_keylen(md.md_ealgo, *keylen);
286c58794deSPawel Jakub Dawidek 	if (md.md_keylen == 0) {
287c58794deSPawel Jakub Dawidek 		gctl_error(req, "Invalid '%s' argument.", "keylen");
288c58794deSPawel Jakub Dawidek 		return;
289c58794deSPawel Jakub Dawidek 	}
290c58794deSPawel Jakub Dawidek 
291c58794deSPawel Jakub Dawidek 	/* Not important here. */
292c58794deSPawel Jakub Dawidek 	md.md_provsize = 0;
293c58794deSPawel Jakub Dawidek 	/* Not important here. */
294c58794deSPawel Jakub Dawidek 	bzero(md.md_salt, sizeof(md.md_salt));
295c58794deSPawel Jakub Dawidek 
296c58794deSPawel Jakub Dawidek 	md.md_keys = 0x01;
297c58794deSPawel Jakub Dawidek 	arc4rand(mkey, sizeof(mkey), 0);
298c58794deSPawel Jakub Dawidek 
299c58794deSPawel Jakub Dawidek 	/* Not important here. */
300c58794deSPawel Jakub Dawidek 	bzero(md.md_hash, sizeof(md.md_hash));
301c58794deSPawel Jakub Dawidek 
302c58794deSPawel Jakub Dawidek 	name = gctl_get_asciiparam(req, "arg0");
303c58794deSPawel Jakub Dawidek 	if (name == NULL) {
304c58794deSPawel Jakub Dawidek 		gctl_error(req, "No 'arg%u' argument.", 0);
305c58794deSPawel Jakub Dawidek 		return;
306c58794deSPawel Jakub Dawidek 	}
307c58794deSPawel Jakub Dawidek 	if (strncmp(name, "/dev/", strlen("/dev/")) == 0)
308c58794deSPawel Jakub Dawidek 		name += strlen("/dev/");
309c58794deSPawel Jakub Dawidek 	pp = g_provider_by_name(name);
310c58794deSPawel Jakub Dawidek 	if (pp == NULL) {
311c58794deSPawel Jakub Dawidek 		gctl_error(req, "Provider %s is invalid.", name);
312c58794deSPawel Jakub Dawidek 		return;
313c58794deSPawel Jakub Dawidek 	}
314c58794deSPawel Jakub Dawidek 
315c58794deSPawel Jakub Dawidek 	sectorsize = gctl_get_paraml(req, "sectorsize", sizeof(*sectorsize));
316c58794deSPawel Jakub Dawidek 	if (sectorsize == NULL) {
317c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "sectorsize");
318c58794deSPawel Jakub Dawidek 		return;
319c58794deSPawel Jakub Dawidek 	}
320c58794deSPawel Jakub Dawidek 	if (*sectorsize == 0)
321c58794deSPawel Jakub Dawidek 		md.md_sectorsize = pp->sectorsize;
322c58794deSPawel Jakub Dawidek 	else {
323c58794deSPawel Jakub Dawidek 		if (*sectorsize < 0 || (*sectorsize % pp->sectorsize) != 0) {
324c58794deSPawel Jakub Dawidek 			gctl_error(req, "Invalid sector size.");
325c58794deSPawel Jakub Dawidek 			return;
326c58794deSPawel Jakub Dawidek 		}
327c58794deSPawel Jakub Dawidek 		md.md_sectorsize = *sectorsize;
328c58794deSPawel Jakub Dawidek 	}
329c58794deSPawel Jakub Dawidek 
330c58794deSPawel Jakub Dawidek 	g_eli_create(req, mp, pp, &md, mkey, -1);
331c58794deSPawel Jakub Dawidek 	bzero(mkey, sizeof(mkey));
332c58794deSPawel Jakub Dawidek 	bzero(&md, sizeof(md));
333c58794deSPawel Jakub Dawidek }
334c58794deSPawel Jakub Dawidek 
335c58794deSPawel Jakub Dawidek static void
336c58794deSPawel Jakub Dawidek g_eli_ctl_setkey(struct gctl_req *req, struct g_class *mp)
337c58794deSPawel Jakub Dawidek {
338c58794deSPawel Jakub Dawidek 	struct g_eli_softc *sc;
339c58794deSPawel Jakub Dawidek 	struct g_eli_metadata md;
340c58794deSPawel Jakub Dawidek 	struct g_provider *pp;
341c58794deSPawel Jakub Dawidek 	struct g_consumer *cp;
342c58794deSPawel Jakub Dawidek 	const char *name;
343c58794deSPawel Jakub Dawidek 	u_char *key, *mkeydst, *sector;
344c58794deSPawel Jakub Dawidek 	intmax_t *valp;
3457a5c26fcSPawel Jakub Dawidek 	int keysize, nkey, error;
346c58794deSPawel Jakub Dawidek 
347c58794deSPawel Jakub Dawidek 	g_topology_assert();
348c58794deSPawel Jakub Dawidek 
349c58794deSPawel Jakub Dawidek 	name = gctl_get_asciiparam(req, "arg0");
350c58794deSPawel Jakub Dawidek 	if (name == NULL) {
351c58794deSPawel Jakub Dawidek 		gctl_error(req, "No 'arg%u' argument.", 0);
352c58794deSPawel Jakub Dawidek 		return;
353c58794deSPawel Jakub Dawidek 	}
354c58794deSPawel Jakub Dawidek 	sc = g_eli_find_device(mp, name);
355c58794deSPawel Jakub Dawidek 	if (sc == NULL) {
356c58794deSPawel Jakub Dawidek 		gctl_error(req, "Provider %s is invalid.", name);
357c58794deSPawel Jakub Dawidek 		return;
358c58794deSPawel Jakub Dawidek 	}
359c58794deSPawel Jakub Dawidek 	cp = LIST_FIRST(&sc->sc_geom->consumer);
360c58794deSPawel Jakub Dawidek 	pp = cp->provider;
361c58794deSPawel Jakub Dawidek 
362c58794deSPawel Jakub Dawidek 	error = g_eli_read_metadata(mp, pp, &md);
363c58794deSPawel Jakub Dawidek 	if (error != 0) {
364c58794deSPawel Jakub Dawidek 		gctl_error(req, "Cannot read metadata from %s (error=%d).",
365c58794deSPawel Jakub Dawidek 		    name, error);
366c58794deSPawel Jakub Dawidek 		return;
367c58794deSPawel Jakub Dawidek 	}
368c58794deSPawel Jakub Dawidek 
369c58794deSPawel Jakub Dawidek 	valp = gctl_get_paraml(req, "keyno", sizeof(*valp));
370c58794deSPawel Jakub Dawidek 	if (valp == NULL) {
371c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "keyno");
372c58794deSPawel Jakub Dawidek 		return;
373c58794deSPawel Jakub Dawidek 	}
374c58794deSPawel Jakub Dawidek 	if (*valp != -1)
375c58794deSPawel Jakub Dawidek 		nkey = *valp;
376c58794deSPawel Jakub Dawidek 	else
377c58794deSPawel Jakub Dawidek 		nkey = sc->sc_nkey;
378c58794deSPawel Jakub Dawidek 	if (nkey < 0 || nkey >= G_ELI_MAXMKEYS) {
379c58794deSPawel Jakub Dawidek 		gctl_error(req, "Invalid '%s' argument.", "keyno");
380c58794deSPawel Jakub Dawidek 		return;
381c58794deSPawel Jakub Dawidek 	}
382c58794deSPawel Jakub Dawidek 
3837a5c26fcSPawel Jakub Dawidek 	valp = gctl_get_paraml(req, "iterations", sizeof(*valp));
3847a5c26fcSPawel Jakub Dawidek 	if (valp == NULL) {
3857a5c26fcSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "iterations");
3867a5c26fcSPawel Jakub Dawidek 		return;
3877a5c26fcSPawel Jakub Dawidek 	}
3887a5c26fcSPawel Jakub Dawidek 	/* Check if iterations number should and can be changed. */
3897a5c26fcSPawel Jakub Dawidek 	if (*valp != -1) {
3907a5c26fcSPawel Jakub Dawidek 		if (bitcount32(md.md_keys) != 1) {
3917a5c26fcSPawel Jakub Dawidek 			gctl_error(req, "To be able to use '-i' option, only "
3927a5c26fcSPawel Jakub Dawidek 			    "one key can be defined.");
3937a5c26fcSPawel Jakub Dawidek 			return;
3947a5c26fcSPawel Jakub Dawidek 		}
3957a5c26fcSPawel Jakub Dawidek 		if (md.md_keys != (1 << nkey)) {
3967a5c26fcSPawel Jakub Dawidek 			gctl_error(req, "Only already defined key can be "
3977a5c26fcSPawel Jakub Dawidek 			    "changed when '-i' option is used.");
3987a5c26fcSPawel Jakub Dawidek 			return;
3997a5c26fcSPawel Jakub Dawidek 		}
4007a5c26fcSPawel Jakub Dawidek 		md.md_iterations = *valp;
4017a5c26fcSPawel Jakub Dawidek 	}
4027a5c26fcSPawel Jakub Dawidek 
403c58794deSPawel Jakub Dawidek 	key = gctl_get_param(req, "key", &keysize);
404c58794deSPawel Jakub Dawidek 	if (key == NULL || keysize != G_ELI_USERKEYLEN) {
405c58794deSPawel Jakub Dawidek 		bzero(&md, sizeof(md));
406c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "key");
407c58794deSPawel Jakub Dawidek 		return;
408c58794deSPawel Jakub Dawidek 	}
409c58794deSPawel Jakub Dawidek 
410c58794deSPawel Jakub Dawidek 	mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN;
411c58794deSPawel Jakub Dawidek 	md.md_keys |= (1 << nkey);
412c58794deSPawel Jakub Dawidek 
413eaa3b919SPawel Jakub Dawidek 	bcopy(sc->sc_mkey, mkeydst, sizeof(sc->sc_mkey));
414c58794deSPawel Jakub Dawidek 
415c58794deSPawel Jakub Dawidek 	/* Encrypt Master Key with the new key. */
416eaa3b919SPawel Jakub Dawidek 	error = g_eli_mkey_encrypt(md.md_ealgo, key, md.md_keylen, mkeydst);
417c58794deSPawel Jakub Dawidek 	bzero(key, sizeof(key));
418c58794deSPawel Jakub Dawidek 	if (error != 0) {
419c58794deSPawel Jakub Dawidek 		bzero(&md, sizeof(md));
420c58794deSPawel Jakub Dawidek 		gctl_error(req, "Cannot encrypt Master Key (error=%d).", error);
421c58794deSPawel Jakub Dawidek 		return;
422c58794deSPawel Jakub Dawidek 	}
423c58794deSPawel Jakub Dawidek 
424c58794deSPawel Jakub Dawidek 	sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO);
425c58794deSPawel Jakub Dawidek 	/* Store metadata with fresh key. */
426c58794deSPawel Jakub Dawidek 	eli_metadata_encode(&md, sector);
427c58794deSPawel Jakub Dawidek 	bzero(&md, sizeof(md));
428c58794deSPawel Jakub Dawidek 	error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
429c58794deSPawel Jakub Dawidek 	    pp->sectorsize);
430c58794deSPawel Jakub Dawidek 	bzero(sector, sizeof(sector));
431c58794deSPawel Jakub Dawidek 	free(sector, M_ELI);
432c58794deSPawel Jakub Dawidek 	if (error != 0) {
433c58794deSPawel Jakub Dawidek 		gctl_error(req, "Cannot store metadata on %s (error=%d).",
434c58794deSPawel Jakub Dawidek 		    pp->name, error);
435c58794deSPawel Jakub Dawidek 		return;
436c58794deSPawel Jakub Dawidek 	}
437c58794deSPawel Jakub Dawidek 	G_ELI_DEBUG(1, "Key %u changed on %s.", nkey, pp->name);
438c58794deSPawel Jakub Dawidek }
439c58794deSPawel Jakub Dawidek 
440c58794deSPawel Jakub Dawidek static void
441c58794deSPawel Jakub Dawidek g_eli_ctl_delkey(struct gctl_req *req, struct g_class *mp)
442c58794deSPawel Jakub Dawidek {
443c58794deSPawel Jakub Dawidek 	struct g_eli_softc *sc;
444c58794deSPawel Jakub Dawidek 	struct g_eli_metadata md;
445c58794deSPawel Jakub Dawidek 	struct g_provider *pp;
446c58794deSPawel Jakub Dawidek 	struct g_consumer *cp;
447c58794deSPawel Jakub Dawidek 	const char *name;
448c58794deSPawel Jakub Dawidek 	u_char *mkeydst, *sector;
449c58794deSPawel Jakub Dawidek 	intmax_t *valp;
450c58794deSPawel Jakub Dawidek 	size_t keysize;
451c58794deSPawel Jakub Dawidek 	int error, nkey, *all, *force;
452c58794deSPawel Jakub Dawidek 	u_int i;
453c58794deSPawel Jakub Dawidek 
454c58794deSPawel Jakub Dawidek 	g_topology_assert();
455c58794deSPawel Jakub Dawidek 
456c58794deSPawel Jakub Dawidek 	nkey = 0;	/* fixes causeless gcc warning */
457c58794deSPawel Jakub Dawidek 
458c58794deSPawel Jakub Dawidek 	name = gctl_get_asciiparam(req, "arg0");
459c58794deSPawel Jakub Dawidek 	if (name == NULL) {
460c58794deSPawel Jakub Dawidek 		gctl_error(req, "No 'arg%u' argument.", 0);
461c58794deSPawel Jakub Dawidek 		return;
462c58794deSPawel Jakub Dawidek 	}
463c58794deSPawel Jakub Dawidek 	sc = g_eli_find_device(mp, name);
464c58794deSPawel Jakub Dawidek 	if (sc == NULL) {
465c58794deSPawel Jakub Dawidek 		gctl_error(req, "Provider %s is invalid.", name);
466c58794deSPawel Jakub Dawidek 		return;
467c58794deSPawel Jakub Dawidek 	}
468c58794deSPawel Jakub Dawidek 	cp = LIST_FIRST(&sc->sc_geom->consumer);
469c58794deSPawel Jakub Dawidek 	pp = cp->provider;
470c58794deSPawel Jakub Dawidek 
471c58794deSPawel Jakub Dawidek 	error = g_eli_read_metadata(mp, pp, &md);
472c58794deSPawel Jakub Dawidek 	if (error != 0) {
473c58794deSPawel Jakub Dawidek 		gctl_error(req, "Cannot read metadata from %s (error=%d).",
474c58794deSPawel Jakub Dawidek 		    name, error);
475c58794deSPawel Jakub Dawidek 		return;
476c58794deSPawel Jakub Dawidek 	}
477c58794deSPawel Jakub Dawidek 
478c58794deSPawel Jakub Dawidek 	all = gctl_get_paraml(req, "all", sizeof(*all));
479c58794deSPawel Jakub Dawidek 	if (all == NULL) {
480c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "all");
481c58794deSPawel Jakub Dawidek 		return;
482c58794deSPawel Jakub Dawidek 	}
483c58794deSPawel Jakub Dawidek 
484c58794deSPawel Jakub Dawidek 	if (*all) {
485c58794deSPawel Jakub Dawidek 		mkeydst = md.md_mkeys;
486c58794deSPawel Jakub Dawidek 		keysize = sizeof(md.md_mkeys);
487c58794deSPawel Jakub Dawidek 	} else {
488c58794deSPawel Jakub Dawidek 		force = gctl_get_paraml(req, "force", sizeof(*force));
489c58794deSPawel Jakub Dawidek 		if (force == NULL) {
490c58794deSPawel Jakub Dawidek 			gctl_error(req, "No '%s' argument.", "force");
491c58794deSPawel Jakub Dawidek 			return;
492c58794deSPawel Jakub Dawidek 		}
493c58794deSPawel Jakub Dawidek 
494c58794deSPawel Jakub Dawidek 		valp = gctl_get_paraml(req, "keyno", sizeof(*valp));
495c58794deSPawel Jakub Dawidek 		if (valp == NULL) {
496c58794deSPawel Jakub Dawidek 			gctl_error(req, "No '%s' argument.", "keyno");
497c58794deSPawel Jakub Dawidek 			return;
498c58794deSPawel Jakub Dawidek 		}
499c58794deSPawel Jakub Dawidek 		if (*valp != -1)
500c58794deSPawel Jakub Dawidek 			nkey = *valp;
501c58794deSPawel Jakub Dawidek 		else
502c58794deSPawel Jakub Dawidek 			nkey = sc->sc_nkey;
503c58794deSPawel Jakub Dawidek 		if (nkey < 0 || nkey >= G_ELI_MAXMKEYS) {
504c58794deSPawel Jakub Dawidek 			gctl_error(req, "Invalid '%s' argument.", "keyno");
505c58794deSPawel Jakub Dawidek 			return;
506c58794deSPawel Jakub Dawidek 		}
507c58794deSPawel Jakub Dawidek 		if (!(md.md_keys & (1 << nkey)) && !*force) {
508c58794deSPawel Jakub Dawidek 			gctl_error(req, "Master Key %u is not set.", nkey);
509c58794deSPawel Jakub Dawidek 			return;
510c58794deSPawel Jakub Dawidek 		}
511c58794deSPawel Jakub Dawidek 		md.md_keys &= ~(1 << nkey);
512c58794deSPawel Jakub Dawidek 		if (md.md_keys == 0 && !*force) {
513c58794deSPawel Jakub Dawidek 			gctl_error(req, "This is the last Master Key. Use '-f' "
514c58794deSPawel Jakub Dawidek 			    "flag if you really want to remove it.");
515c58794deSPawel Jakub Dawidek 			return;
516c58794deSPawel Jakub Dawidek 		}
517c58794deSPawel Jakub Dawidek 		mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN;
518c58794deSPawel Jakub Dawidek 		keysize = G_ELI_MKEYLEN;
519c58794deSPawel Jakub Dawidek 	}
520c58794deSPawel Jakub Dawidek 
521c58794deSPawel Jakub Dawidek 	sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO);
522c58794deSPawel Jakub Dawidek 	for (i = 0; i <= g_eli_overwrites; i++) {
523c58794deSPawel Jakub Dawidek 		if (i == g_eli_overwrites)
524c58794deSPawel Jakub Dawidek 			bzero(mkeydst, keysize);
525c58794deSPawel Jakub Dawidek 		else
526c58794deSPawel Jakub Dawidek 			arc4rand(mkeydst, keysize, 0);
527c58794deSPawel Jakub Dawidek 		/* Store metadata with destroyed key. */
528c58794deSPawel Jakub Dawidek 		eli_metadata_encode(&md, sector);
529c58794deSPawel Jakub Dawidek 		error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
530c58794deSPawel Jakub Dawidek 		    pp->sectorsize);
531c58794deSPawel Jakub Dawidek 		if (error != 0) {
532c58794deSPawel Jakub Dawidek 			G_ELI_DEBUG(0, "Cannot store metadata on %s "
533c58794deSPawel Jakub Dawidek 			    "(error=%d).", pp->name, error);
534c58794deSPawel Jakub Dawidek 		}
535c58794deSPawel Jakub Dawidek 	}
536c58794deSPawel Jakub Dawidek 	bzero(&md, sizeof(md));
537c58794deSPawel Jakub Dawidek 	bzero(sector, sizeof(sector));
538c58794deSPawel Jakub Dawidek 	free(sector, M_ELI);
539c58794deSPawel Jakub Dawidek 	if (*all)
540c58794deSPawel Jakub Dawidek 		G_ELI_DEBUG(1, "All keys removed from %s.", pp->name);
541c58794deSPawel Jakub Dawidek 	else
542c58794deSPawel Jakub Dawidek 		G_ELI_DEBUG(1, "Key %d removed from %s.", nkey, pp->name);
543c58794deSPawel Jakub Dawidek }
544c58794deSPawel Jakub Dawidek 
545c58794deSPawel Jakub Dawidek static int
546c58794deSPawel Jakub Dawidek g_eli_kill_one(struct g_eli_softc *sc)
547c58794deSPawel Jakub Dawidek {
548c58794deSPawel Jakub Dawidek 	struct g_provider *pp;
549c58794deSPawel Jakub Dawidek 	struct g_consumer *cp;
550c58794deSPawel Jakub Dawidek 	u_char *sector;
551c58794deSPawel Jakub Dawidek 	int err, error = 0;
552c58794deSPawel Jakub Dawidek 	u_int i;
553c58794deSPawel Jakub Dawidek 
554c58794deSPawel Jakub Dawidek 	g_topology_assert();
555c58794deSPawel Jakub Dawidek 
556c58794deSPawel Jakub Dawidek 	if (sc == NULL)
557c58794deSPawel Jakub Dawidek 		return (ENOENT);
558c58794deSPawel Jakub Dawidek 
559c58794deSPawel Jakub Dawidek 	pp = LIST_FIRST(&sc->sc_geom->provider);
560c58794deSPawel Jakub Dawidek 	g_error_provider(pp, ENXIO);
561c58794deSPawel Jakub Dawidek 
562c58794deSPawel Jakub Dawidek 	cp = LIST_FIRST(&sc->sc_geom->consumer);
563c58794deSPawel Jakub Dawidek 	pp = cp->provider;
564c58794deSPawel Jakub Dawidek 
565c58794deSPawel Jakub Dawidek 	sector = malloc(pp->sectorsize, M_ELI, M_WAITOK);
566c58794deSPawel Jakub Dawidek 	for (i = 0; i <= g_eli_overwrites; i++) {
567c58794deSPawel Jakub Dawidek 		if (i == g_eli_overwrites)
568c58794deSPawel Jakub Dawidek 			bzero(sector, pp->sectorsize);
569c58794deSPawel Jakub Dawidek 		else
570c58794deSPawel Jakub Dawidek 			arc4rand(sector, pp->sectorsize, 0);
571c58794deSPawel Jakub Dawidek 		err = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
572c58794deSPawel Jakub Dawidek 		    pp->sectorsize);
573c58794deSPawel Jakub Dawidek 		if (err != 0) {
574c58794deSPawel Jakub Dawidek 			G_ELI_DEBUG(0, "Cannot erase metadata on %s "
575c58794deSPawel Jakub Dawidek 			    "(error=%d).", pp->name, err);
576c58794deSPawel Jakub Dawidek 			if (error == 0)
577c58794deSPawel Jakub Dawidek 				error = err;
578c58794deSPawel Jakub Dawidek 		}
579c58794deSPawel Jakub Dawidek 	}
580c58794deSPawel Jakub Dawidek 	free(sector, M_ELI);
581c58794deSPawel Jakub Dawidek 	if (error == 0)
582c58794deSPawel Jakub Dawidek 		G_ELI_DEBUG(0, "%s has been killed.", pp->name);
583c58794deSPawel Jakub Dawidek 	g_eli_destroy(sc, 1);
584c58794deSPawel Jakub Dawidek 	return (error);
585c58794deSPawel Jakub Dawidek }
586c58794deSPawel Jakub Dawidek 
587c58794deSPawel Jakub Dawidek static void
588c58794deSPawel Jakub Dawidek g_eli_ctl_kill(struct gctl_req *req, struct g_class *mp)
589c58794deSPawel Jakub Dawidek {
590c58794deSPawel Jakub Dawidek 	int *all, *nargs;
591c58794deSPawel Jakub Dawidek 	int error;
592c58794deSPawel Jakub Dawidek 
593c58794deSPawel Jakub Dawidek 	g_topology_assert();
594c58794deSPawel Jakub Dawidek 
595c58794deSPawel Jakub Dawidek 	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
596c58794deSPawel Jakub Dawidek 	if (nargs == NULL) {
597c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "nargs");
598c58794deSPawel Jakub Dawidek 		return;
599c58794deSPawel Jakub Dawidek 	}
600c58794deSPawel Jakub Dawidek 	all = gctl_get_paraml(req, "all", sizeof(*all));
601c58794deSPawel Jakub Dawidek 	if (all == NULL) {
602c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "all");
603c58794deSPawel Jakub Dawidek 		return;
604c58794deSPawel Jakub Dawidek 	}
605c58794deSPawel Jakub Dawidek 	if (!*all && *nargs == 0) {
606c58794deSPawel Jakub Dawidek 		gctl_error(req, "Too few arguments.");
607c58794deSPawel Jakub Dawidek 		return;
608c58794deSPawel Jakub Dawidek 	}
609c58794deSPawel Jakub Dawidek 
610c58794deSPawel Jakub Dawidek 	if (*all) {
611c58794deSPawel Jakub Dawidek 		struct g_geom *gp, *gp2;
612c58794deSPawel Jakub Dawidek 
613c58794deSPawel Jakub Dawidek 		LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) {
614c58794deSPawel Jakub Dawidek 			error = g_eli_kill_one(gp->softc);
615c58794deSPawel Jakub Dawidek 			if (error != 0)
616c58794deSPawel Jakub Dawidek 				gctl_error(req, "Not fully done.");
617c58794deSPawel Jakub Dawidek 		}
618c58794deSPawel Jakub Dawidek 	} else {
619c58794deSPawel Jakub Dawidek 		struct g_eli_softc *sc;
620c58794deSPawel Jakub Dawidek 		const char *prov;
621c58794deSPawel Jakub Dawidek 		char param[16];
622c58794deSPawel Jakub Dawidek 		int i;
623c58794deSPawel Jakub Dawidek 
624c58794deSPawel Jakub Dawidek 		for (i = 0; i < *nargs; i++) {
6257d54b385SPawel Jakub Dawidek 			snprintf(param, sizeof(param), "arg%d", i);
626c58794deSPawel Jakub Dawidek 			prov = gctl_get_asciiparam(req, param);
627b5f30223SPawel Jakub Dawidek 			if (prov == NULL) {
628b5f30223SPawel Jakub Dawidek 				G_ELI_DEBUG(0, "No 'arg%d' argument.", i);
629b5f30223SPawel Jakub Dawidek 				continue;
630b5f30223SPawel Jakub Dawidek 			}
631c58794deSPawel Jakub Dawidek 
632c58794deSPawel Jakub Dawidek 			sc = g_eli_find_device(mp, prov);
633c58794deSPawel Jakub Dawidek 			if (sc == NULL) {
6347d54b385SPawel Jakub Dawidek 				G_ELI_DEBUG(0, "No such provider: %s.", prov);
635c58794deSPawel Jakub Dawidek 				continue;
636c58794deSPawel Jakub Dawidek 			}
637c58794deSPawel Jakub Dawidek 			error = g_eli_kill_one(sc);
638c58794deSPawel Jakub Dawidek 			if (error != 0)
639c58794deSPawel Jakub Dawidek 				gctl_error(req, "Not fully done.");
640c58794deSPawel Jakub Dawidek 		}
641c58794deSPawel Jakub Dawidek 	}
642c58794deSPawel Jakub Dawidek }
643c58794deSPawel Jakub Dawidek 
644c58794deSPawel Jakub Dawidek void
645c58794deSPawel Jakub Dawidek g_eli_config(struct gctl_req *req, struct g_class *mp, const char *verb)
646c58794deSPawel Jakub Dawidek {
647c58794deSPawel Jakub Dawidek 	uint32_t *version;
648c58794deSPawel Jakub Dawidek 
649c58794deSPawel Jakub Dawidek 	g_topology_assert();
650c58794deSPawel Jakub Dawidek 
651c58794deSPawel Jakub Dawidek 	version = gctl_get_paraml(req, "version", sizeof(*version));
652c58794deSPawel Jakub Dawidek 	if (version == NULL) {
653c58794deSPawel Jakub Dawidek 		gctl_error(req, "No '%s' argument.", "version");
654c58794deSPawel Jakub Dawidek 		return;
655c58794deSPawel Jakub Dawidek 	}
656c58794deSPawel Jakub Dawidek 	if (*version != G_ELI_VERSION) {
657c58794deSPawel Jakub Dawidek 		gctl_error(req, "Userland and kernel parts are out of sync.");
658c58794deSPawel Jakub Dawidek 		return;
659c58794deSPawel Jakub Dawidek 	}
660c58794deSPawel Jakub Dawidek 
661c58794deSPawel Jakub Dawidek 	if (strcmp(verb, "attach") == 0)
662c58794deSPawel Jakub Dawidek 		g_eli_ctl_attach(req, mp);
663c58794deSPawel Jakub Dawidek 	else if (strcmp(verb, "detach") == 0 || strcmp(verb, "stop") == 0)
664c58794deSPawel Jakub Dawidek 		g_eli_ctl_detach(req, mp);
665c58794deSPawel Jakub Dawidek 	else if (strcmp(verb, "onetime") == 0)
666c58794deSPawel Jakub Dawidek 		g_eli_ctl_onetime(req, mp);
667c58794deSPawel Jakub Dawidek 	else if (strcmp(verb, "setkey") == 0)
668c58794deSPawel Jakub Dawidek 		g_eli_ctl_setkey(req, mp);
669c58794deSPawel Jakub Dawidek 	else if (strcmp(verb, "delkey") == 0)
670c58794deSPawel Jakub Dawidek 		g_eli_ctl_delkey(req, mp);
671c58794deSPawel Jakub Dawidek 	else if (strcmp(verb, "kill") == 0)
672c58794deSPawel Jakub Dawidek 		g_eli_ctl_kill(req, mp);
673c58794deSPawel Jakub Dawidek 	else
674c58794deSPawel Jakub Dawidek 		gctl_error(req, "Unknown verb.");
675c58794deSPawel Jakub Dawidek }
676