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