hastctl.c revision 247867
1204076Spjd/*- 2204076Spjd * Copyright (c) 2009-2010 The FreeBSD Foundation 3204076Spjd * All rights reserved. 4204076Spjd * 5204076Spjd * This software was developed by Pawel Jakub Dawidek under sponsorship from 6204076Spjd * the FreeBSD Foundation. 7204076Spjd * 8204076Spjd * Redistribution and use in source and binary forms, with or without 9204076Spjd * modification, are permitted provided that the following conditions 10204076Spjd * are met: 11204076Spjd * 1. Redistributions of source code must retain the above copyright 12204076Spjd * notice, this list of conditions and the following disclaimer. 13204076Spjd * 2. Redistributions in binary form must reproduce the above copyright 14204076Spjd * notice, this list of conditions and the following disclaimer in the 15204076Spjd * documentation and/or other materials provided with the distribution. 16204076Spjd * 17204076Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 18204076Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19204076Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20204076Spjd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 21204076Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22204076Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23204076Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24204076Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25204076Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26204076Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27204076Spjd * SUCH DAMAGE. 28204076Spjd */ 29204076Spjd 30204076Spjd#include <sys/cdefs.h> 31204076Spjd__FBSDID("$FreeBSD: stable/9/sbin/hastctl/hastctl.c 247867 2013-03-06 06:58:11Z trociny $"); 32204076Spjd 33204076Spjd#include <sys/param.h> 34204076Spjd#include <sys/disk.h> 35204076Spjd#include <sys/ioctl.h> 36204076Spjd#include <sys/stat.h> 37204076Spjd#include <sys/sysctl.h> 38204076Spjd 39204076Spjd#include <err.h> 40204076Spjd#include <errno.h> 41204076Spjd#include <fcntl.h> 42219620Strociny#include <libutil.h> 43204076Spjd#include <limits.h> 44204076Spjd#include <signal.h> 45204076Spjd#include <stdio.h> 46204076Spjd#include <stdlib.h> 47204076Spjd#include <string.h> 48204076Spjd#include <sysexits.h> 49204076Spjd#include <unistd.h> 50204076Spjd 51204076Spjd#include <activemap.h> 52204076Spjd 53204076Spjd#include "hast.h" 54204076Spjd#include "hast_proto.h" 55204076Spjd#include "metadata.h" 56204076Spjd#include "nv.h" 57204076Spjd#include "pjdlog.h" 58204076Spjd#include "proto.h" 59204076Spjd#include "subr.h" 60204076Spjd 61204076Spjd/* Path to configuration file. */ 62204076Spjdstatic const char *cfgpath = HAST_CONFIG; 63204076Spjd/* Hastd configuration. */ 64204076Spjdstatic struct hastd_config *cfg; 65204076Spjd/* Control connection. */ 66204076Spjdstatic struct proto_conn *controlconn; 67204076Spjd 68204076Spjdenum { 69204076Spjd CMD_INVALID, 70204076Spjd CMD_CREATE, 71204076Spjd CMD_ROLE, 72204076Spjd CMD_STATUS, 73204076Spjd CMD_DUMP 74204076Spjd}; 75204076Spjd 76204076Spjdstatic __dead2 void 77204076Spjdusage(void) 78204076Spjd{ 79204076Spjd 80204076Spjd fprintf(stderr, 81204076Spjd "usage: %s create [-d] [-c config] [-e extentsize] [-k keepdirty]\n" 82204076Spjd "\t\t[-m mediasize] name ...\n", 83204076Spjd getprogname()); 84204076Spjd fprintf(stderr, 85204076Spjd " %s role [-d] [-c config] <init | primary | secondary> all | name ...\n", 86204076Spjd getprogname()); 87204076Spjd fprintf(stderr, 88204076Spjd " %s status [-d] [-c config] [all | name ...]\n", 89204076Spjd getprogname()); 90204076Spjd fprintf(stderr, 91204076Spjd " %s dump [-d] [-c config] [all | name ...]\n", 92204076Spjd getprogname()); 93204076Spjd exit(EX_USAGE); 94204076Spjd} 95204076Spjd 96204076Spjdstatic int 97204076Spjdcreate_one(struct hast_resource *res, intmax_t mediasize, intmax_t extentsize, 98204076Spjd intmax_t keepdirty) 99204076Spjd{ 100204076Spjd unsigned char *buf; 101204076Spjd size_t mapsize; 102204076Spjd int ec; 103204076Spjd 104204076Spjd ec = 0; 105204076Spjd pjdlog_prefix_set("[%s] ", res->hr_name); 106204076Spjd 107231017Strociny if (provinfo(res, true) == -1) { 108204076Spjd ec = EX_NOINPUT; 109204076Spjd goto end; 110204076Spjd } 111204076Spjd if (mediasize == 0) 112204076Spjd mediasize = res->hr_local_mediasize; 113204076Spjd else if (mediasize > res->hr_local_mediasize) { 114204076Spjd pjdlog_error("Provided mediasize is larger than provider %s size.", 115204076Spjd res->hr_localpath); 116204076Spjd ec = EX_DATAERR; 117204076Spjd goto end; 118204076Spjd } 119204076Spjd if (!powerof2(res->hr_local_sectorsize)) { 120204076Spjd pjdlog_error("Sector size of provider %s is not power of 2 (%u).", 121204076Spjd res->hr_localpath, res->hr_local_sectorsize); 122204076Spjd ec = EX_DATAERR; 123204076Spjd goto end; 124204076Spjd } 125204076Spjd if (extentsize == 0) 126204076Spjd extentsize = HAST_EXTENTSIZE; 127204076Spjd if (extentsize < res->hr_local_sectorsize) { 128204076Spjd pjdlog_error("Extent size (%jd) is less than sector size (%u).", 129204076Spjd (intmax_t)extentsize, res->hr_local_sectorsize); 130204076Spjd ec = EX_DATAERR; 131204076Spjd goto end; 132204076Spjd } 133204076Spjd if ((extentsize % res->hr_local_sectorsize) != 0) { 134204076Spjd pjdlog_error("Extent size (%jd) is not multiple of sector size (%u).", 135204076Spjd (intmax_t)extentsize, res->hr_local_sectorsize); 136204076Spjd ec = EX_DATAERR; 137204076Spjd goto end; 138204076Spjd } 139204076Spjd mapsize = activemap_calc_ondisk_size(mediasize - METADATA_SIZE, 140204076Spjd extentsize, res->hr_local_sectorsize); 141204076Spjd if (keepdirty == 0) 142204076Spjd keepdirty = HAST_KEEPDIRTY; 143204076Spjd res->hr_datasize = mediasize - METADATA_SIZE - mapsize; 144204076Spjd res->hr_extentsize = extentsize; 145204076Spjd res->hr_keepdirty = keepdirty; 146204076Spjd 147204076Spjd res->hr_localoff = METADATA_SIZE + mapsize; 148204076Spjd 149231017Strociny if (metadata_write(res) == -1) { 150204076Spjd ec = EX_IOERR; 151204076Spjd goto end; 152204076Spjd } 153204076Spjd buf = calloc(1, mapsize); 154204076Spjd if (buf == NULL) { 155204076Spjd pjdlog_error("Unable to allocate %zu bytes of memory for initial bitmap.", 156204076Spjd mapsize); 157204076Spjd ec = EX_TEMPFAIL; 158204076Spjd goto end; 159204076Spjd } 160204076Spjd if (pwrite(res->hr_localfd, buf, mapsize, METADATA_SIZE) != 161204076Spjd (ssize_t)mapsize) { 162204076Spjd pjdlog_errno(LOG_ERR, "Unable to store initial bitmap on %s", 163204076Spjd res->hr_localpath); 164204076Spjd free(buf); 165204076Spjd ec = EX_IOERR; 166204076Spjd goto end; 167204076Spjd } 168204076Spjd free(buf); 169204076Spjdend: 170204076Spjd if (res->hr_localfd >= 0) 171204076Spjd close(res->hr_localfd); 172204076Spjd pjdlog_prefix_set("%s", ""); 173204076Spjd return (ec); 174204076Spjd} 175204076Spjd 176204076Spjdstatic void 177204076Spjdcontrol_create(int argc, char *argv[], intmax_t mediasize, intmax_t extentsize, 178204076Spjd intmax_t keepdirty) 179204076Spjd{ 180204076Spjd struct hast_resource *res; 181204076Spjd int ec, ii, ret; 182204076Spjd 183204076Spjd /* Initialize the given resources. */ 184204076Spjd if (argc < 1) 185204076Spjd usage(); 186204076Spjd ec = 0; 187204076Spjd for (ii = 0; ii < argc; ii++) { 188204076Spjd TAILQ_FOREACH(res, &cfg->hc_resources, hr_next) { 189204076Spjd if (strcmp(argv[ii], res->hr_name) == 0) 190204076Spjd break; 191204076Spjd } 192204076Spjd if (res == NULL) { 193204076Spjd pjdlog_error("Unknown resource %s.", argv[ii]); 194204076Spjd if (ec == 0) 195204076Spjd ec = EX_DATAERR; 196204076Spjd continue; 197204076Spjd } 198204076Spjd ret = create_one(res, mediasize, extentsize, keepdirty); 199204076Spjd if (ret != 0 && ec == 0) 200204076Spjd ec = ret; 201204076Spjd } 202204076Spjd exit(ec); 203204076Spjd} 204204076Spjd 205204076Spjdstatic int 206204076Spjddump_one(struct hast_resource *res) 207204076Spjd{ 208204076Spjd int ret; 209204076Spjd 210204076Spjd ret = metadata_read(res, false); 211204076Spjd if (ret != 0) 212204076Spjd return (ret); 213204076Spjd 214204076Spjd printf("resource: %s\n", res->hr_name); 215219373Spjd printf(" datasize: %ju (%NB)\n", (uintmax_t)res->hr_datasize, 216219373Spjd (intmax_t)res->hr_datasize); 217219373Spjd printf(" extentsize: %d (%NB)\n", res->hr_extentsize, 218219373Spjd (intmax_t)res->hr_extentsize); 219204076Spjd printf(" keepdirty: %d\n", res->hr_keepdirty); 220204076Spjd printf(" localoff: %ju\n", (uintmax_t)res->hr_localoff); 221204076Spjd printf(" resuid: %ju\n", (uintmax_t)res->hr_resuid); 222204076Spjd printf(" localcnt: %ju\n", (uintmax_t)res->hr_primary_localcnt); 223204076Spjd printf(" remotecnt: %ju\n", (uintmax_t)res->hr_primary_remotecnt); 224204076Spjd printf(" prevrole: %s\n", role2str(res->hr_previous_role)); 225204076Spjd 226204076Spjd return (0); 227204076Spjd} 228204076Spjd 229204076Spjdstatic void 230204076Spjdcontrol_dump(int argc, char *argv[]) 231204076Spjd{ 232204076Spjd struct hast_resource *res; 233204076Spjd int ec, ret; 234204076Spjd 235204076Spjd /* Dump metadata of the given resource(s). */ 236204076Spjd 237204076Spjd ec = 0; 238204076Spjd if (argc == 0 || (argc == 1 && strcmp(argv[0], "all") == 0)) { 239204076Spjd TAILQ_FOREACH(res, &cfg->hc_resources, hr_next) { 240204076Spjd ret = dump_one(res); 241204076Spjd if (ret != 0 && ec == 0) 242204076Spjd ec = ret; 243204076Spjd } 244204076Spjd } else { 245204076Spjd int ii; 246204076Spjd 247204076Spjd for (ii = 0; ii < argc; ii++) { 248204076Spjd TAILQ_FOREACH(res, &cfg->hc_resources, hr_next) { 249204076Spjd if (strcmp(argv[ii], res->hr_name) == 0) 250204076Spjd break; 251204076Spjd } 252204076Spjd if (res == NULL) { 253204076Spjd pjdlog_error("Unknown resource %s.", argv[ii]); 254204076Spjd if (ec == 0) 255204076Spjd ec = EX_DATAERR; 256204076Spjd continue; 257204076Spjd } 258204076Spjd ret = dump_one(res); 259204076Spjd if (ret != 0 && ec == 0) 260204076Spjd ec = ret; 261204076Spjd } 262204076Spjd } 263204076Spjd exit(ec); 264204076Spjd} 265204076Spjd 266204076Spjdstatic int 267204076Spjdcontrol_set_role(struct nv *nv, const char *newrole) 268204076Spjd{ 269204076Spjd const char *res, *oldrole; 270204076Spjd unsigned int ii; 271204076Spjd int error, ret; 272204076Spjd 273204076Spjd ret = 0; 274204076Spjd 275204076Spjd for (ii = 0; ; ii++) { 276204076Spjd res = nv_get_string(nv, "resource%u", ii); 277204076Spjd if (res == NULL) 278204076Spjd break; 279204076Spjd pjdlog_prefix_set("[%s] ", res); 280204076Spjd error = nv_get_int16(nv, "error%u", ii); 281204076Spjd if (error != 0) { 282204076Spjd if (ret == 0) 283204076Spjd ret = error; 284204076Spjd pjdlog_warning("Received error %d from hastd.", error); 285204076Spjd continue; 286204076Spjd } 287204076Spjd oldrole = nv_get_string(nv, "role%u", ii); 288204076Spjd if (strcmp(oldrole, newrole) == 0) 289204076Spjd pjdlog_debug(2, "Role unchanged (%s).", oldrole); 290204076Spjd else { 291204076Spjd pjdlog_debug(1, "Role changed from %s to %s.", oldrole, 292204076Spjd newrole); 293204076Spjd } 294204076Spjd } 295204076Spjd pjdlog_prefix_set("%s", ""); 296204076Spjd return (ret); 297204076Spjd} 298204076Spjd 299204076Spjdstatic int 300204076Spjdcontrol_status(struct nv *nv) 301204076Spjd{ 302204076Spjd unsigned int ii; 303204076Spjd const char *str; 304204076Spjd int error, ret; 305204076Spjd 306204076Spjd ret = 0; 307204076Spjd 308204076Spjd for (ii = 0; ; ii++) { 309204076Spjd str = nv_get_string(nv, "resource%u", ii); 310204076Spjd if (str == NULL) 311204076Spjd break; 312204076Spjd printf("%s:\n", str); 313204076Spjd error = nv_get_int16(nv, "error%u", ii); 314204076Spjd if (error != 0) { 315204076Spjd if (ret == 0) 316204076Spjd ret = error; 317204076Spjd printf(" error: %d\n", error); 318204076Spjd continue; 319204076Spjd } 320204076Spjd printf(" role: %s\n", nv_get_string(nv, "role%u", ii)); 321204076Spjd printf(" provname: %s\n", 322204076Spjd nv_get_string(nv, "provname%u", ii)); 323204076Spjd printf(" localpath: %s\n", 324204076Spjd nv_get_string(nv, "localpath%u", ii)); 325219373Spjd printf(" extentsize: %u (%NB)\n", 326219373Spjd (unsigned int)nv_get_uint32(nv, "extentsize%u", ii), 327219373Spjd (intmax_t)nv_get_uint32(nv, "extentsize%u", ii)); 328204076Spjd printf(" keepdirty: %u\n", 329204076Spjd (unsigned int)nv_get_uint32(nv, "keepdirty%u", ii)); 330204076Spjd printf(" remoteaddr: %s\n", 331204076Spjd nv_get_string(nv, "remoteaddr%u", ii)); 332219821Spjd str = nv_get_string(nv, "sourceaddr%u", ii); 333219821Spjd if (str != NULL) 334219821Spjd printf(" sourceaddr: %s\n", str); 335204076Spjd printf(" replication: %s\n", 336204076Spjd nv_get_string(nv, "replication%u", ii)); 337204076Spjd str = nv_get_string(nv, "status%u", ii); 338204076Spjd if (str != NULL) 339204076Spjd printf(" status: %s\n", str); 340219373Spjd printf(" dirty: %ju (%NB)\n", 341219373Spjd (uintmax_t)nv_get_uint64(nv, "dirty%u", ii), 342219373Spjd (intmax_t)nv_get_uint64(nv, "dirty%u", ii)); 343222228Spjd printf(" statistics:\n"); 344222228Spjd printf(" reads: %ju\n", 345247867Strociny (uintmax_t)nv_get_uint64(nv, "stat_read%u", ii)); 346222228Spjd printf(" writes: %ju\n", 347247867Strociny (uintmax_t)nv_get_uint64(nv, "stat_write%u", ii)); 348222228Spjd printf(" deletes: %ju\n", 349247867Strociny (uintmax_t)nv_get_uint64(nv, "stat_delete%u", ii)); 350222228Spjd printf(" flushes: %ju\n", 351247867Strociny (uintmax_t)nv_get_uint64(nv, "stat_flush%u", ii)); 352222228Spjd printf(" activemap updates: %ju\n", 353247867Strociny (uintmax_t)nv_get_uint64(nv, "stat_activemap_update%u", ii)); 354247867Strociny printf(" local errors: " 355247867Strociny "read: %ju, write: %ju, delete: %ju, flush: %ju\n", 356247867Strociny (uintmax_t)nv_get_uint64(nv, "stat_read_error%u", ii), 357247867Strociny (uintmax_t)nv_get_uint64(nv, "stat_write_error%u", ii), 358247867Strociny (uintmax_t)nv_get_uint64(nv, "stat_delete_error%u", ii), 359247867Strociny (uintmax_t)nv_get_uint64(nv, "stat_flush_error%u", ii)); 360204076Spjd } 361204076Spjd return (ret); 362204076Spjd} 363204076Spjd 364204076Spjdint 365204076Spjdmain(int argc, char *argv[]) 366204076Spjd{ 367204076Spjd struct nv *nv; 368219620Strociny int64_t mediasize, extentsize, keepdirty; 369204076Spjd int cmd, debug, error, ii; 370204076Spjd const char *optstr; 371204076Spjd 372204076Spjd debug = 0; 373204076Spjd mediasize = extentsize = keepdirty = 0; 374204076Spjd 375204076Spjd if (argc == 1) 376204076Spjd usage(); 377204076Spjd 378204076Spjd if (strcmp(argv[1], "create") == 0) { 379204076Spjd cmd = CMD_CREATE; 380204076Spjd optstr = "c:de:k:m:h"; 381204076Spjd } else if (strcmp(argv[1], "role") == 0) { 382204076Spjd cmd = CMD_ROLE; 383204076Spjd optstr = "c:dh"; 384204076Spjd } else if (strcmp(argv[1], "status") == 0) { 385204076Spjd cmd = CMD_STATUS; 386204076Spjd optstr = "c:dh"; 387204076Spjd } else if (strcmp(argv[1], "dump") == 0) { 388204076Spjd cmd = CMD_DUMP; 389204076Spjd optstr = "c:dh"; 390204076Spjd } else 391204076Spjd usage(); 392204076Spjd 393204076Spjd argc--; 394204076Spjd argv++; 395204076Spjd 396204076Spjd for (;;) { 397204076Spjd int ch; 398204076Spjd 399204076Spjd ch = getopt(argc, argv, optstr); 400204076Spjd if (ch == -1) 401204076Spjd break; 402204076Spjd switch (ch) { 403204076Spjd case 'c': 404204076Spjd cfgpath = optarg; 405204076Spjd break; 406204076Spjd case 'd': 407204076Spjd debug++; 408204076Spjd break; 409204076Spjd case 'e': 410231017Strociny if (expand_number(optarg, &extentsize) == -1) 411223976Strociny errx(EX_USAGE, "Invalid extentsize"); 412204076Spjd break; 413204076Spjd case 'k': 414231017Strociny if (expand_number(optarg, &keepdirty) == -1) 415223976Strociny errx(EX_USAGE, "Invalid keepdirty"); 416204076Spjd break; 417204076Spjd case 'm': 418231017Strociny if (expand_number(optarg, &mediasize) == -1) 419223976Strociny errx(EX_USAGE, "Invalid mediasize"); 420204076Spjd break; 421204076Spjd case 'h': 422204076Spjd default: 423204076Spjd usage(); 424204076Spjd } 425204076Spjd } 426204076Spjd argc -= optind; 427204076Spjd argv += optind; 428204076Spjd 429204076Spjd switch (cmd) { 430204076Spjd case CMD_CREATE: 431204076Spjd case CMD_ROLE: 432204076Spjd if (argc == 0) 433204076Spjd usage(); 434204076Spjd break; 435204076Spjd } 436204076Spjd 437217965Spjd pjdlog_init(PJDLOG_MODE_STD); 438204076Spjd pjdlog_debug_set(debug); 439204076Spjd 440210909Sdougb cfg = yy_config_parse(cfgpath, true); 441229509Strociny PJDLOG_ASSERT(cfg != NULL); 442204076Spjd 443204076Spjd switch (cmd) { 444204076Spjd case CMD_CREATE: 445204076Spjd control_create(argc, argv, mediasize, extentsize, keepdirty); 446204076Spjd /* NOTREACHED */ 447229509Strociny PJDLOG_ABORT("What are we doing here?!"); 448204076Spjd break; 449204076Spjd case CMD_DUMP: 450204076Spjd /* Dump metadata from local component of the given resource. */ 451204076Spjd control_dump(argc, argv); 452204076Spjd /* NOTREACHED */ 453229509Strociny PJDLOG_ABORT("What are we doing here?!"); 454204076Spjd break; 455204076Spjd case CMD_ROLE: 456204076Spjd /* Change role for the given resources. */ 457204076Spjd if (argc < 2) 458204076Spjd usage(); 459204076Spjd nv = nv_alloc(); 460204076Spjd nv_add_uint8(nv, HASTCTL_CMD_SETROLE, "cmd"); 461204076Spjd if (strcmp(argv[0], "init") == 0) 462204076Spjd nv_add_uint8(nv, HAST_ROLE_INIT, "role"); 463204076Spjd else if (strcmp(argv[0], "primary") == 0) 464204076Spjd nv_add_uint8(nv, HAST_ROLE_PRIMARY, "role"); 465204076Spjd else if (strcmp(argv[0], "secondary") == 0) 466204076Spjd nv_add_uint8(nv, HAST_ROLE_SECONDARY, "role"); 467204076Spjd else 468204076Spjd usage(); 469204076Spjd for (ii = 0; ii < argc - 1; ii++) 470204076Spjd nv_add_string(nv, argv[ii + 1], "resource%d", ii); 471204076Spjd break; 472204076Spjd case CMD_STATUS: 473204076Spjd /* Obtain status of the given resources. */ 474204076Spjd nv = nv_alloc(); 475204076Spjd nv_add_uint8(nv, HASTCTL_CMD_STATUS, "cmd"); 476204076Spjd if (argc == 0) 477204076Spjd nv_add_string(nv, "all", "resource%d", 0); 478204076Spjd else { 479204076Spjd for (ii = 0; ii < argc; ii++) 480204076Spjd nv_add_string(nv, argv[ii], "resource%d", ii); 481204076Spjd } 482204076Spjd break; 483204076Spjd default: 484229509Strociny PJDLOG_ABORT("Impossible command!"); 485204076Spjd } 486204076Spjd 487204076Spjd /* Setup control connection... */ 488231017Strociny if (proto_client(NULL, cfg->hc_controladdr, &controlconn) == -1) { 489204076Spjd pjdlog_exit(EX_OSERR, 490204076Spjd "Unable to setup control connection to %s", 491204076Spjd cfg->hc_controladdr); 492204076Spjd } 493204076Spjd /* ...and connect to hastd. */ 494231017Strociny if (proto_connect(controlconn, HAST_TIMEOUT) == -1) { 495204076Spjd pjdlog_exit(EX_OSERR, "Unable to connect to hastd via %s", 496204076Spjd cfg->hc_controladdr); 497204076Spjd } 498218215Spjd 499221899Spjd if (drop_privs(NULL) != 0) 500218215Spjd exit(EX_CONFIG); 501218215Spjd 502204076Spjd /* Send the command to the server... */ 503231017Strociny if (hast_proto_send(NULL, controlconn, nv, NULL, 0) == -1) { 504204076Spjd pjdlog_exit(EX_UNAVAILABLE, 505204076Spjd "Unable to send command to hastd via %s", 506204076Spjd cfg->hc_controladdr); 507204076Spjd } 508204076Spjd nv_free(nv); 509204076Spjd /* ...and receive reply. */ 510231017Strociny if (hast_proto_recv_hdr(controlconn, &nv) == -1) { 511204076Spjd pjdlog_exit(EX_UNAVAILABLE, 512204076Spjd "cannot receive reply from hastd via %s", 513204076Spjd cfg->hc_controladdr); 514204076Spjd } 515204076Spjd 516204076Spjd error = nv_get_int16(nv, "error"); 517204076Spjd if (error != 0) { 518204076Spjd pjdlog_exitx(EX_SOFTWARE, "Error %d received from hastd.", 519204076Spjd error); 520204076Spjd } 521204076Spjd nv_set_error(nv, 0); 522204076Spjd 523204076Spjd switch (cmd) { 524204076Spjd case CMD_ROLE: 525204076Spjd error = control_set_role(nv, argv[0]); 526204076Spjd break; 527204076Spjd case CMD_STATUS: 528204076Spjd error = control_status(nv); 529204076Spjd break; 530204076Spjd default: 531229509Strociny PJDLOG_ABORT("Impossible command!"); 532204076Spjd } 533204076Spjd 534204076Spjd exit(error); 535204076Spjd} 536