diff options
author | pjd <pjd@FreeBSD.org> | 2006-09-16 10:43:17 +0000 |
---|---|---|
committer | pjd <pjd@FreeBSD.org> | 2006-09-16 10:43:17 +0000 |
commit | 2e387b9b852a5ae8c2980ff133e33d076004f6bf (patch) | |
tree | d6a32a6317a6d83082fb42a45340d13d9d9c56f0 /sys | |
parent | f5e129df20c2b3984d81e96cfffd8fe2979a18be (diff) | |
download | FreeBSD-src-2e387b9b852a5ae8c2980ff133e33d076004f6bf.zip FreeBSD-src-2e387b9b852a5ae8c2980ff133e33d076004f6bf.tar.gz |
Add 'configure' subcommand which for now only allows setting and removing
of the BOOT flag. It can be performed on both attached and detached
providers.
Requested by: Matthias Lederhofer <matled@gmx.net>
MFC after: 1 week
Diffstat (limited to 'sys')
-rw-r--r-- | sys/geom/eli/g_eli.h | 8 | ||||
-rw-r--r-- | sys/geom/eli/g_eli_ctl.c | 111 |
2 files changed, 116 insertions, 3 deletions
diff --git a/sys/geom/eli/g_eli.h b/sys/geom/eli/g_eli.h index e24f314..5460eea 100644 --- a/sys/geom/eli/g_eli.h +++ b/sys/geom/eli/g_eli.h @@ -59,8 +59,9 @@ * 2 - Added G_ELI_FLAG_READONLY. * - IV is generated from offset converted to little-endian * (flag G_ELI_FLAG_NATIVE_BYTE_ORDER will be set for older versions). + * 3 - Added 'configure' subcommand. */ -#define G_ELI_VERSION 2 +#define G_ELI_VERSION 3 /* ON DISK FLAGS. */ /* Use random, onetime keys. */ @@ -228,7 +229,7 @@ eli_metadata_decode_v0(const u_char *data, struct g_eli_metadata *md) return (0); } static __inline int -eli_metadata_decode_v1v2(const u_char *data, struct g_eli_metadata *md) +eli_metadata_decode_v1v2v3(const u_char *data, struct g_eli_metadata *md) { MD5_CTX ctx; const u_char *p; @@ -264,7 +265,8 @@ eli_metadata_decode(const u_char *data, struct g_eli_metadata *md) break; case 1: case 2: - error = eli_metadata_decode_v1v2(data, md); + case 3: + error = eli_metadata_decode_v1v2v3(data, md); break; default: error = EINVAL; diff --git a/sys/geom/eli/g_eli_ctl.c b/sys/geom/eli/g_eli_ctl.c index e420af3..a788ba2 100644 --- a/sys/geom/eli/g_eli_ctl.c +++ b/sys/geom/eli/g_eli_ctl.c @@ -364,6 +364,115 @@ g_eli_ctl_onetime(struct gctl_req *req, struct g_class *mp) } static void +g_eli_ctl_configure(struct gctl_req *req, struct g_class *mp) +{ + struct g_eli_softc *sc; + struct g_eli_metadata md; + struct g_provider *pp; + struct g_consumer *cp; + char param[16]; + const char *prov; + u_char *sector; + int *nargs, *boot, *noboot; + int error; + u_int i; + + g_topology_assert(); + + nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); + if (nargs == NULL) { + gctl_error(req, "No '%s' argument.", "nargs"); + return; + } + if (*nargs <= 0) { + gctl_error(req, "Missing device(s)."); + return; + } + + boot = gctl_get_paraml(req, "boot", sizeof(*boot)); + if (boot == NULL) { + gctl_error(req, "No '%s' argument.", "boot"); + return; + } + noboot = gctl_get_paraml(req, "noboot", sizeof(*noboot)); + if (noboot == NULL) { + gctl_error(req, "No '%s' argument.", "noboot"); + return; + } + if (*boot && *noboot) { + gctl_error(req, "Options -b and -B are mutually exclusive."); + return; + } + if (!*boot && !*noboot) { + gctl_error(req, "No option given."); + return; + } + + for (i = 0; i < *nargs; i++) { + snprintf(param, sizeof(param), "arg%d", i); + prov = gctl_get_asciiparam(req, param); + if (prov == NULL) { + gctl_error(req, "No 'arg%d' argument.", i); + return; + } + sc = g_eli_find_device(mp, prov); + if (sc == NULL) { + /* + * We ignore not attached providers, userland part will + * take care of them. + */ + G_ELI_DEBUG(1, "Skipping configuration of not attached " + "provider %s.", prov); + continue; + } + if (*boot && (sc->sc_flags & G_ELI_FLAG_BOOT)) { + G_ELI_DEBUG(1, "BOOT flag already configured for %s.", + prov); + continue; + } else if (!*boot && !(sc->sc_flags & G_ELI_FLAG_BOOT)) { + G_ELI_DEBUG(1, "BOOT flag not configured for %s.", + prov); + continue; + } + if (sc->sc_flags & G_ELI_FLAG_RO) { + gctl_error(req, "Cannot change configuration of " + "read-only provider %s.", prov); + continue; + } + cp = LIST_FIRST(&sc->sc_geom->consumer); + pp = cp->provider; + error = g_eli_read_metadata(mp, pp, &md); + if (error != 0) { + gctl_error(req, + "Cannot read metadata from %s (error=%d).", + prov, error); + continue; + } + + if (*boot) { + md.md_flags |= G_ELI_FLAG_BOOT; + sc->sc_flags |= G_ELI_FLAG_BOOT; + } else { + md.md_flags &= ~G_ELI_FLAG_BOOT; + sc->sc_flags &= ~G_ELI_FLAG_BOOT; + } + + sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO); + eli_metadata_encode(&md, sector); + error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector, + pp->sectorsize); + if (error != 0) { + gctl_error(req, + "Cannot store metadata on %s (error=%d).", + prov, error); + } + bzero(&md, sizeof(md)); + bzero(sector, sizeof(sector)); + free(sector, M_ELI); + } +} + +static void g_eli_ctl_setkey(struct gctl_req *req, struct g_class *mp) { struct g_eli_softc *sc; @@ -710,6 +819,8 @@ g_eli_config(struct gctl_req *req, struct g_class *mp, const char *verb) g_eli_ctl_detach(req, mp); else if (strcmp(verb, "onetime") == 0) g_eli_ctl_onetime(req, mp); + else if (strcmp(verb, "configure") == 0) + g_eli_ctl_configure(req, mp); else if (strcmp(verb, "setkey") == 0) g_eli_ctl_setkey(req, mp); else if (strcmp(verb, "delkey") == 0) |