1204076Spjd%{ 2204076Spjd/*- 3204076Spjd * Copyright (c) 2009-2010 The FreeBSD Foundation 4219351Spjd * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net> 5204076Spjd * All rights reserved. 6204076Spjd * 7204076Spjd * This software was developed by Pawel Jakub Dawidek under sponsorship from 8204076Spjd * the FreeBSD Foundation. 9204076Spjd * 10204076Spjd * Redistribution and use in source and binary forms, with or without 11204076Spjd * modification, are permitted provided that the following conditions 12204076Spjd * are met: 13204076Spjd * 1. Redistributions of source code must retain the above copyright 14204076Spjd * notice, this list of conditions and the following disclaimer. 15204076Spjd * 2. Redistributions in binary form must reproduce the above copyright 16204076Spjd * notice, this list of conditions and the following disclaimer in the 17204076Spjd * documentation and/or other materials provided with the distribution. 18204076Spjd * 19204076Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 20204076Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21204076Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22204076Spjd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 23204076Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24204076Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25204076Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26204076Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27204076Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28204076Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29204076Spjd * SUCH DAMAGE. 30204076Spjd * 31204076Spjd * $FreeBSD$ 32204076Spjd */ 33204076Spjd 34204076Spjd#include <sys/param.h> /* MAXHOSTNAMELEN */ 35204076Spjd#include <sys/queue.h> 36222108Spjd#include <sys/socket.h> 37204076Spjd#include <sys/sysctl.h> 38204076Spjd 39204076Spjd#include <arpa/inet.h> 40204076Spjd 41204076Spjd#include <err.h> 42222108Spjd#include <errno.h> 43204076Spjd#include <stdio.h> 44204076Spjd#include <string.h> 45204076Spjd#include <sysexits.h> 46204076Spjd#include <unistd.h> 47204076Spjd 48210883Spjd#include <pjdlog.h> 49210883Spjd 50204076Spjd#include "hast.h" 51204076Spjd 52204076Spjdextern int depth; 53204076Spjdextern int lineno; 54204076Spjd 55204076Spjdextern FILE *yyin; 56204076Spjdextern char *yytext; 57204076Spjd 58210883Spjdstatic struct hastd_config *lconfig; 59204076Spjdstatic struct hast_resource *curres; 60216721Spjdstatic bool mynode, hadmynode; 61204076Spjd 62204076Spjdstatic char depth0_control[HAST_ADDRSIZE]; 63229509Strocinystatic char depth0_pidfile[PATH_MAX]; 64222119Spjdstatic char depth0_listen_tcp4[HAST_ADDRSIZE]; 65222119Spjdstatic char depth0_listen_tcp6[HAST_ADDRSIZE]; 66222108Spjdstatic TAILQ_HEAD(, hastd_listen) depth0_listen; 67204076Spjdstatic int depth0_replication; 68219351Spjdstatic int depth0_checksum; 69219354Spjdstatic int depth0_compression; 70207371Spjdstatic int depth0_timeout; 71211886Spjdstatic char depth0_exec[PATH_MAX]; 72229509Strocinystatic int depth0_metaflush; 73204076Spjd 74204076Spjdstatic char depth1_provname[PATH_MAX]; 75204076Spjdstatic char depth1_localpath[PATH_MAX]; 76229509Strocinystatic int depth1_metaflush; 77204076Spjd 78252181Smariusextern void yyerror(const char *); 79252181Smariusextern int yylex(void); 80210883Spjdextern void yyrestart(FILE *); 81210883Spjd 82210883Spjdstatic int 83204076Spjdisitme(const char *name) 84204076Spjd{ 85204076Spjd char buf[MAXHOSTNAMELEN]; 86249236Strociny unsigned long hostid; 87204076Spjd char *pos; 88204076Spjd size_t bufsize; 89204076Spjd 90204076Spjd /* 91231017Strociny * First check if the given name matches our full hostname. 92204076Spjd */ 93210883Spjd if (gethostname(buf, sizeof(buf)) < 0) { 94210883Spjd pjdlog_errno(LOG_ERR, "gethostname() failed"); 95210883Spjd return (-1); 96210883Spjd } 97204076Spjd if (strcmp(buf, name) == 0) 98210883Spjd return (1); 99204076Spjd 100204076Spjd /* 101249236Strociny * Check if it matches first part of the host name. 102204076Spjd */ 103204076Spjd pos = strchr(buf, '.'); 104221632Strociny if (pos != NULL && (size_t)(pos - buf) == strlen(name) && 105221632Strociny strncmp(buf, name, pos - buf) == 0) { 106210883Spjd return (1); 107221632Strociny } 108204076Spjd 109204076Spjd /* 110249236Strociny * Check if it matches host UUID. 111204076Spjd */ 112204076Spjd bufsize = sizeof(buf); 113210883Spjd if (sysctlbyname("kern.hostuuid", buf, &bufsize, NULL, 0) < 0) { 114210883Spjd pjdlog_errno(LOG_ERR, "sysctlbyname(kern.hostuuid) failed"); 115210883Spjd return (-1); 116210883Spjd } 117204076Spjd if (strcasecmp(buf, name) == 0) 118210883Spjd return (1); 119204076Spjd 120249236Strociny /* 121249236Strociny * Check if it matches hostid. 122249236Strociny */ 123249236Strociny bufsize = sizeof(hostid); 124249236Strociny if (sysctlbyname("kern.hostid", &hostid, &bufsize, NULL, 0) < 0) { 125249236Strociny pjdlog_errno(LOG_ERR, "sysctlbyname(kern.hostid) failed"); 126249236Strociny return (-1); 127249236Strociny } 128249236Strociny (void)snprintf(buf, sizeof(buf), "hostid%lu", hostid); 129249236Strociny if (strcmp(buf, name) == 0) 130249236Strociny return (1); 131249236Strociny 132204076Spjd /* 133204076Spjd * Looks like this isn't about us. 134204076Spjd */ 135210883Spjd return (0); 136204076Spjd} 137204076Spjd 138222108Spjdstatic bool 139222108Spjdfamily_supported(int family) 140222108Spjd{ 141222108Spjd int sock; 142222108Spjd 143222108Spjd sock = socket(family, SOCK_STREAM, 0); 144222108Spjd if (sock == -1 && errno == EPROTONOSUPPORT) 145222108Spjd return (false); 146222108Spjd if (sock >= 0) 147222108Spjd (void)close(sock); 148222108Spjd return (true); 149222108Spjd} 150222108Spjd 151216721Spjdstatic int 152216721Spjdnode_names(char **namesp) 153216721Spjd{ 154216721Spjd static char names[MAXHOSTNAMELEN * 3]; 155216721Spjd char buf[MAXHOSTNAMELEN]; 156249236Strociny unsigned long hostid; 157216721Spjd char *pos; 158216721Spjd size_t bufsize; 159216721Spjd 160216721Spjd if (gethostname(buf, sizeof(buf)) < 0) { 161216721Spjd pjdlog_errno(LOG_ERR, "gethostname() failed"); 162216721Spjd return (-1); 163216721Spjd } 164216721Spjd 165216721Spjd /* First component of the host name. */ 166216721Spjd pos = strchr(buf, '.'); 167216721Spjd if (pos != NULL && pos != buf) { 168216721Spjd (void)strlcpy(names, buf, MIN((size_t)(pos - buf + 1), 169216721Spjd sizeof(names))); 170216721Spjd (void)strlcat(names, ", ", sizeof(names)); 171216721Spjd } 172216721Spjd 173216721Spjd /* Full host name. */ 174216721Spjd (void)strlcat(names, buf, sizeof(names)); 175216721Spjd (void)strlcat(names, ", ", sizeof(names)); 176216721Spjd 177216721Spjd /* Host UUID. */ 178216721Spjd bufsize = sizeof(buf); 179216721Spjd if (sysctlbyname("kern.hostuuid", buf, &bufsize, NULL, 0) < 0) { 180216721Spjd pjdlog_errno(LOG_ERR, "sysctlbyname(kern.hostuuid) failed"); 181216721Spjd return (-1); 182216721Spjd } 183216721Spjd (void)strlcat(names, buf, sizeof(names)); 184249236Strociny (void)strlcat(names, ", ", sizeof(names)); 185216721Spjd 186249236Strociny /* Host ID. */ 187249236Strociny bufsize = sizeof(hostid); 188249236Strociny if (sysctlbyname("kern.hostid", &hostid, &bufsize, NULL, 0) < 0) { 189249236Strociny pjdlog_errno(LOG_ERR, "sysctlbyname(kern.hostid) failed"); 190249236Strociny return (-1); 191249236Strociny } 192249236Strociny (void)snprintf(buf, sizeof(buf), "hostid%lu", hostid); 193249236Strociny (void)strlcat(names, buf, sizeof(names)); 194249236Strociny 195216721Spjd *namesp = names; 196216721Spjd 197216721Spjd return (0); 198216721Spjd} 199216721Spjd 200204076Spjdvoid 201204076Spjdyyerror(const char *str) 202204076Spjd{ 203204076Spjd 204210883Spjd pjdlog_error("Unable to parse configuration file at line %d near '%s': %s", 205204076Spjd lineno, yytext, str); 206204076Spjd} 207204076Spjd 208204076Spjdstruct hastd_config * 209210883Spjdyy_config_parse(const char *config, bool exitonerror) 210204076Spjd{ 211204076Spjd int ret; 212204076Spjd 213204076Spjd curres = NULL; 214204076Spjd mynode = false; 215210883Spjd depth = 0; 216210883Spjd lineno = 0; 217204076Spjd 218207371Spjd depth0_timeout = HAST_TIMEOUT; 219249236Strociny depth0_replication = HAST_REPLICATION_MEMSYNC; 220219351Spjd depth0_checksum = HAST_CHECKSUM_NONE; 221219354Spjd depth0_compression = HAST_COMPRESSION_HOLE; 222204076Spjd strlcpy(depth0_control, HAST_CONTROL, sizeof(depth0_control)); 223229509Strociny strlcpy(depth0_pidfile, HASTD_PIDFILE, sizeof(depth0_pidfile)); 224222108Spjd TAILQ_INIT(&depth0_listen); 225222119Spjd strlcpy(depth0_listen_tcp4, HASTD_LISTEN_TCP4, 226222119Spjd sizeof(depth0_listen_tcp4)); 227222119Spjd strlcpy(depth0_listen_tcp6, HASTD_LISTEN_TCP6, 228222119Spjd sizeof(depth0_listen_tcp6)); 229211886Spjd depth0_exec[0] = '\0'; 230229509Strociny depth0_metaflush = 1; 231204076Spjd 232210883Spjd lconfig = calloc(1, sizeof(*lconfig)); 233210883Spjd if (lconfig == NULL) { 234210883Spjd pjdlog_error("Unable to allocate memory for configuration."); 235210883Spjd if (exitonerror) 236210883Spjd exit(EX_TEMPFAIL); 237210883Spjd return (NULL); 238210883Spjd } 239204076Spjd 240222108Spjd TAILQ_INIT(&lconfig->hc_listen); 241210883Spjd TAILQ_INIT(&lconfig->hc_resources); 242210883Spjd 243204076Spjd yyin = fopen(config, "r"); 244210883Spjd if (yyin == NULL) { 245210883Spjd pjdlog_errno(LOG_ERR, "Unable to open configuration file %s", 246210883Spjd config); 247210883Spjd yy_config_free(lconfig); 248210883Spjd if (exitonerror) 249210883Spjd exit(EX_OSFILE); 250210883Spjd return (NULL); 251210883Spjd } 252210883Spjd yyrestart(yyin); 253204076Spjd ret = yyparse(); 254204076Spjd fclose(yyin); 255204076Spjd if (ret != 0) { 256210883Spjd yy_config_free(lconfig); 257210883Spjd if (exitonerror) 258210883Spjd exit(EX_CONFIG); 259210883Spjd return (NULL); 260204076Spjd } 261204076Spjd 262204076Spjd /* 263204076Spjd * Let's see if everything is set up. 264204076Spjd */ 265210883Spjd if (lconfig->hc_controladdr[0] == '\0') { 266210883Spjd strlcpy(lconfig->hc_controladdr, depth0_control, 267210883Spjd sizeof(lconfig->hc_controladdr)); 268204076Spjd } 269229509Strociny if (lconfig->hc_pidfile[0] == '\0') { 270229509Strociny strlcpy(lconfig->hc_pidfile, depth0_pidfile, 271229509Strociny sizeof(lconfig->hc_pidfile)); 272229509Strociny } 273222108Spjd if (!TAILQ_EMPTY(&depth0_listen)) 274222108Spjd TAILQ_CONCAT(&lconfig->hc_listen, &depth0_listen, hl_next); 275222108Spjd if (TAILQ_EMPTY(&lconfig->hc_listen)) { 276222108Spjd struct hastd_listen *lst; 277222108Spjd 278222108Spjd if (family_supported(AF_INET)) { 279222108Spjd lst = calloc(1, sizeof(*lst)); 280222108Spjd if (lst == NULL) { 281222108Spjd pjdlog_error("Unable to allocate memory for listen address."); 282222108Spjd yy_config_free(lconfig); 283222108Spjd if (exitonerror) 284222108Spjd exit(EX_TEMPFAIL); 285222108Spjd return (NULL); 286222108Spjd } 287222119Spjd (void)strlcpy(lst->hl_addr, depth0_listen_tcp4, 288222108Spjd sizeof(lst->hl_addr)); 289222108Spjd TAILQ_INSERT_TAIL(&lconfig->hc_listen, lst, hl_next); 290222108Spjd } else { 291222108Spjd pjdlog_debug(1, 292222108Spjd "No IPv4 support in the kernel, not listening on IPv4 address."); 293222108Spjd } 294222108Spjd if (family_supported(AF_INET6)) { 295222108Spjd lst = calloc(1, sizeof(*lst)); 296222108Spjd if (lst == NULL) { 297222108Spjd pjdlog_error("Unable to allocate memory for listen address."); 298222108Spjd yy_config_free(lconfig); 299222108Spjd if (exitonerror) 300222108Spjd exit(EX_TEMPFAIL); 301222108Spjd return (NULL); 302222108Spjd } 303222119Spjd (void)strlcpy(lst->hl_addr, depth0_listen_tcp6, 304222108Spjd sizeof(lst->hl_addr)); 305222108Spjd TAILQ_INSERT_TAIL(&lconfig->hc_listen, lst, hl_next); 306222108Spjd } else { 307222108Spjd pjdlog_debug(1, 308222108Spjd "No IPv6 support in the kernel, not listening on IPv6 address."); 309222108Spjd } 310222108Spjd if (TAILQ_EMPTY(&lconfig->hc_listen)) { 311222108Spjd pjdlog_error("No address to listen on."); 312222108Spjd yy_config_free(lconfig); 313222108Spjd if (exitonerror) 314222108Spjd exit(EX_TEMPFAIL); 315222108Spjd return (NULL); 316222108Spjd } 317204076Spjd } 318210883Spjd TAILQ_FOREACH(curres, &lconfig->hc_resources, hr_next) { 319229509Strociny PJDLOG_ASSERT(curres->hr_provname[0] != '\0'); 320229509Strociny PJDLOG_ASSERT(curres->hr_localpath[0] != '\0'); 321229509Strociny PJDLOG_ASSERT(curres->hr_remoteaddr[0] != '\0'); 322204076Spjd 323204076Spjd if (curres->hr_replication == -1) { 324204076Spjd /* 325204076Spjd * Replication is not set at resource-level. 326204076Spjd * Use global or default setting. 327204076Spjd */ 328204076Spjd curres->hr_replication = depth0_replication; 329249236Strociny curres->hr_original_replication = depth0_replication; 330204076Spjd } 331219351Spjd if (curres->hr_checksum == -1) { 332219351Spjd /* 333219351Spjd * Checksum is not set at resource-level. 334219351Spjd * Use global or default setting. 335219351Spjd */ 336219351Spjd curres->hr_checksum = depth0_checksum; 337219351Spjd } 338219354Spjd if (curres->hr_compression == -1) { 339219354Spjd /* 340219354Spjd * Compression is not set at resource-level. 341219354Spjd * Use global or default setting. 342219354Spjd */ 343219354Spjd curres->hr_compression = depth0_compression; 344219354Spjd } 345207371Spjd if (curres->hr_timeout == -1) { 346207371Spjd /* 347207371Spjd * Timeout is not set at resource-level. 348207371Spjd * Use global or default setting. 349207371Spjd */ 350207371Spjd curres->hr_timeout = depth0_timeout; 351207371Spjd } 352211886Spjd if (curres->hr_exec[0] == '\0') { 353211886Spjd /* 354211886Spjd * Exec is not set at resource-level. 355211886Spjd * Use global or default setting. 356211886Spjd */ 357211886Spjd strlcpy(curres->hr_exec, depth0_exec, 358211886Spjd sizeof(curres->hr_exec)); 359211886Spjd } 360229509Strociny if (curres->hr_metaflush == -1) { 361229509Strociny /* 362229509Strociny * Metaflush is not set at resource-level. 363229509Strociny * Use global or default setting. 364229509Strociny */ 365229509Strociny curres->hr_metaflush = depth0_metaflush; 366229509Strociny } 367204076Spjd } 368204076Spjd 369210883Spjd return (lconfig); 370204076Spjd} 371204076Spjd 372204076Spjdvoid 373204076Spjdyy_config_free(struct hastd_config *config) 374204076Spjd{ 375222108Spjd struct hastd_listen *lst; 376204076Spjd struct hast_resource *res; 377204076Spjd 378222108Spjd while ((lst = TAILQ_FIRST(&depth0_listen)) != NULL) { 379222108Spjd TAILQ_REMOVE(&depth0_listen, lst, hl_next); 380222108Spjd free(lst); 381222108Spjd } 382222108Spjd while ((lst = TAILQ_FIRST(&config->hc_listen)) != NULL) { 383222108Spjd TAILQ_REMOVE(&config->hc_listen, lst, hl_next); 384222108Spjd free(lst); 385222108Spjd } 386204076Spjd while ((res = TAILQ_FIRST(&config->hc_resources)) != NULL) { 387204076Spjd TAILQ_REMOVE(&config->hc_resources, res, hr_next); 388204076Spjd free(res); 389204076Spjd } 390210883Spjd free(config); 391204076Spjd} 392204076Spjd%} 393204076Spjd 394231017Strociny%token CONTROL PIDFILE LISTEN REPLICATION CHECKSUM COMPRESSION METAFLUSH 395231017Strociny%token TIMEOUT EXEC RESOURCE NAME LOCAL REMOTE SOURCE ON OFF 396219354Spjd%token FULLSYNC MEMSYNC ASYNC NONE CRC32 SHA256 HOLE LZF 397204076Spjd%token NUM STR OB CB 398204076Spjd 399221643Spjd%type <str> remote_str 400204076Spjd%type <num> replication_type 401219351Spjd%type <num> checksum_type 402219354Spjd%type <num> compression_type 403229509Strociny%type <num> boolean 404204076Spjd 405204076Spjd%union 406204076Spjd{ 407204076Spjd int num; 408204076Spjd char *str; 409204076Spjd} 410204076Spjd 411204076Spjd%token <num> NUM 412204076Spjd%token <str> STR 413204076Spjd 414204076Spjd%% 415204076Spjd 416204076Spjdstatements: 417204076Spjd | 418204076Spjd statements statement 419204076Spjd ; 420204076Spjd 421204076Spjdstatement: 422204076Spjd control_statement 423204076Spjd | 424229509Strociny pidfile_statement 425229509Strociny | 426204076Spjd listen_statement 427204076Spjd | 428204076Spjd replication_statement 429204076Spjd | 430219351Spjd checksum_statement 431219351Spjd | 432219354Spjd compression_statement 433219354Spjd | 434207371Spjd timeout_statement 435207371Spjd | 436211886Spjd exec_statement 437211886Spjd | 438229509Strociny metaflush_statement 439229509Strociny | 440204076Spjd node_statement 441204076Spjd | 442204076Spjd resource_statement 443204076Spjd ; 444204076Spjd 445204076Spjdcontrol_statement: CONTROL STR 446204076Spjd { 447204076Spjd switch (depth) { 448204076Spjd case 0: 449204076Spjd if (strlcpy(depth0_control, $2, 450204076Spjd sizeof(depth0_control)) >= 451204076Spjd sizeof(depth0_control)) { 452210883Spjd pjdlog_error("control argument is too long."); 453214274Spjd free($2); 454210883Spjd return (1); 455204076Spjd } 456204076Spjd break; 457204076Spjd case 1: 458211883Spjd if (!mynode) 459211883Spjd break; 460211883Spjd if (strlcpy(lconfig->hc_controladdr, $2, 461211883Spjd sizeof(lconfig->hc_controladdr)) >= 462211883Spjd sizeof(lconfig->hc_controladdr)) { 463211883Spjd pjdlog_error("control argument is too long."); 464214274Spjd free($2); 465211883Spjd return (1); 466204076Spjd } 467204076Spjd break; 468204076Spjd default: 469229509Strociny PJDLOG_ABORT("control at wrong depth level"); 470204076Spjd } 471214274Spjd free($2); 472204076Spjd } 473204076Spjd ; 474204076Spjd 475229509Strocinypidfile_statement: PIDFILE STR 476229509Strociny { 477229509Strociny switch (depth) { 478229509Strociny case 0: 479229509Strociny if (strlcpy(depth0_pidfile, $2, 480229509Strociny sizeof(depth0_pidfile)) >= 481229509Strociny sizeof(depth0_pidfile)) { 482229509Strociny pjdlog_error("pidfile argument is too long."); 483229509Strociny free($2); 484229509Strociny return (1); 485229509Strociny } 486229509Strociny break; 487229509Strociny case 1: 488229509Strociny if (!mynode) 489229509Strociny break; 490229509Strociny if (strlcpy(lconfig->hc_pidfile, $2, 491229509Strociny sizeof(lconfig->hc_pidfile)) >= 492229509Strociny sizeof(lconfig->hc_pidfile)) { 493229509Strociny pjdlog_error("pidfile argument is too long."); 494229509Strociny free($2); 495229509Strociny return (1); 496229509Strociny } 497229509Strociny break; 498229509Strociny default: 499229509Strociny PJDLOG_ABORT("pidfile at wrong depth level"); 500229509Strociny } 501229509Strociny free($2); 502229509Strociny } 503229509Strociny ; 504229509Strociny 505204076Spjdlisten_statement: LISTEN STR 506204076Spjd { 507222108Spjd struct hastd_listen *lst; 508222108Spjd 509222108Spjd lst = calloc(1, sizeof(*lst)); 510222108Spjd if (lst == NULL) { 511222108Spjd pjdlog_error("Unable to allocate memory for listen address."); 512222108Spjd free($2); 513222108Spjd return (1); 514222108Spjd } 515222108Spjd if (strlcpy(lst->hl_addr, $2, sizeof(lst->hl_addr)) >= 516222108Spjd sizeof(lst->hl_addr)) { 517222108Spjd pjdlog_error("listen argument is too long."); 518222108Spjd free($2); 519222108Spjd free(lst); 520222108Spjd return (1); 521222108Spjd } 522204076Spjd switch (depth) { 523204076Spjd case 0: 524222108Spjd TAILQ_INSERT_TAIL(&depth0_listen, lst, hl_next); 525204076Spjd break; 526204076Spjd case 1: 527222108Spjd if (mynode) 528222108Spjd TAILQ_INSERT_TAIL(&depth0_listen, lst, hl_next); 529222108Spjd else 530222108Spjd free(lst); 531204076Spjd break; 532204076Spjd default: 533229509Strociny PJDLOG_ABORT("listen at wrong depth level"); 534204076Spjd } 535214274Spjd free($2); 536204076Spjd } 537204076Spjd ; 538204076Spjd 539204076Spjdreplication_statement: REPLICATION replication_type 540204076Spjd { 541204076Spjd switch (depth) { 542204076Spjd case 0: 543204076Spjd depth0_replication = $2; 544204076Spjd break; 545204076Spjd case 1: 546229509Strociny PJDLOG_ASSERT(curres != NULL); 547229509Strociny curres->hr_replication = $2; 548249236Strociny curres->hr_original_replication = $2; 549204076Spjd break; 550204076Spjd default: 551229509Strociny PJDLOG_ABORT("replication at wrong depth level"); 552204076Spjd } 553204076Spjd } 554204076Spjd ; 555204076Spjd 556204076Spjdreplication_type: 557204076Spjd FULLSYNC { $$ = HAST_REPLICATION_FULLSYNC; } 558204076Spjd | 559204076Spjd MEMSYNC { $$ = HAST_REPLICATION_MEMSYNC; } 560204076Spjd | 561204076Spjd ASYNC { $$ = HAST_REPLICATION_ASYNC; } 562204076Spjd ; 563204076Spjd 564219351Spjdchecksum_statement: CHECKSUM checksum_type 565219351Spjd { 566219351Spjd switch (depth) { 567219351Spjd case 0: 568219351Spjd depth0_checksum = $2; 569219351Spjd break; 570219351Spjd case 1: 571229509Strociny PJDLOG_ASSERT(curres != NULL); 572229509Strociny curres->hr_checksum = $2; 573219351Spjd break; 574219351Spjd default: 575229509Strociny PJDLOG_ABORT("checksum at wrong depth level"); 576219351Spjd } 577219351Spjd } 578219351Spjd ; 579219351Spjd 580219351Spjdchecksum_type: 581219351Spjd NONE { $$ = HAST_CHECKSUM_NONE; } 582219351Spjd | 583219351Spjd CRC32 { $$ = HAST_CHECKSUM_CRC32; } 584219351Spjd | 585219351Spjd SHA256 { $$ = HAST_CHECKSUM_SHA256; } 586219351Spjd ; 587219351Spjd 588219354Spjdcompression_statement: COMPRESSION compression_type 589219354Spjd { 590219354Spjd switch (depth) { 591219354Spjd case 0: 592219354Spjd depth0_compression = $2; 593219354Spjd break; 594219354Spjd case 1: 595229509Strociny PJDLOG_ASSERT(curres != NULL); 596229509Strociny curres->hr_compression = $2; 597219354Spjd break; 598219354Spjd default: 599229509Strociny PJDLOG_ABORT("compression at wrong depth level"); 600219354Spjd } 601219354Spjd } 602219354Spjd ; 603219354Spjd 604219354Spjdcompression_type: 605219354Spjd NONE { $$ = HAST_COMPRESSION_NONE; } 606219354Spjd | 607219354Spjd HOLE { $$ = HAST_COMPRESSION_HOLE; } 608219354Spjd | 609219354Spjd LZF { $$ = HAST_COMPRESSION_LZF; } 610219354Spjd ; 611219354Spjd 612207371Spjdtimeout_statement: TIMEOUT NUM 613207371Spjd { 614220889Spjd if ($2 <= 0) { 615220889Spjd pjdlog_error("Negative or zero timeout."); 616220889Spjd return (1); 617220889Spjd } 618207371Spjd switch (depth) { 619207371Spjd case 0: 620207371Spjd depth0_timeout = $2; 621207371Spjd break; 622207371Spjd case 1: 623229509Strociny PJDLOG_ASSERT(curres != NULL); 624229509Strociny curres->hr_timeout = $2; 625207371Spjd break; 626207371Spjd default: 627229509Strociny PJDLOG_ABORT("timeout at wrong depth level"); 628207371Spjd } 629207371Spjd } 630207371Spjd ; 631207371Spjd 632211886Spjdexec_statement: EXEC STR 633211886Spjd { 634211886Spjd switch (depth) { 635211886Spjd case 0: 636211886Spjd if (strlcpy(depth0_exec, $2, sizeof(depth0_exec)) >= 637211886Spjd sizeof(depth0_exec)) { 638211886Spjd pjdlog_error("Exec path is too long."); 639214274Spjd free($2); 640211886Spjd return (1); 641211886Spjd } 642211886Spjd break; 643211886Spjd case 1: 644229509Strociny PJDLOG_ASSERT(curres != NULL); 645211886Spjd if (strlcpy(curres->hr_exec, $2, 646211886Spjd sizeof(curres->hr_exec)) >= 647211886Spjd sizeof(curres->hr_exec)) { 648211886Spjd pjdlog_error("Exec path is too long."); 649214274Spjd free($2); 650211886Spjd return (1); 651211886Spjd } 652211886Spjd break; 653211886Spjd default: 654229509Strociny PJDLOG_ABORT("exec at wrong depth level"); 655211886Spjd } 656214274Spjd free($2); 657211886Spjd } 658211886Spjd ; 659211886Spjd 660229509Strocinymetaflush_statement: METAFLUSH boolean 661229509Strociny { 662229509Strociny switch (depth) { 663229509Strociny case 0: 664229509Strociny depth0_metaflush = $2; 665229509Strociny break; 666229509Strociny case 1: 667229509Strociny PJDLOG_ASSERT(curres != NULL); 668229509Strociny depth1_metaflush = $2; 669229509Strociny break; 670229509Strociny case 2: 671229509Strociny if (!mynode) 672229509Strociny break; 673229509Strociny PJDLOG_ASSERT(curres != NULL); 674229509Strociny curres->hr_metaflush = $2; 675229509Strociny break; 676229509Strociny default: 677229509Strociny PJDLOG_ABORT("metaflush at wrong depth level"); 678229509Strociny } 679229509Strociny } 680229509Strociny ; 681229509Strociny 682229509Strocinyboolean: 683229509Strociny ON { $$ = 1; } 684229509Strociny | 685229509Strociny OFF { $$ = 0; } 686229509Strociny ; 687229509Strociny 688204076Spjdnode_statement: ON node_start OB node_entries CB 689204076Spjd { 690204076Spjd mynode = false; 691204076Spjd } 692204076Spjd ; 693204076Spjd 694204076Spjdnode_start: STR 695204076Spjd { 696210883Spjd switch (isitme($1)) { 697210883Spjd case -1: 698214274Spjd free($1); 699210883Spjd return (1); 700210883Spjd case 0: 701210883Spjd break; 702210883Spjd case 1: 703204076Spjd mynode = true; 704210883Spjd break; 705210883Spjd default: 706229509Strociny PJDLOG_ABORT("invalid isitme() return value"); 707210883Spjd } 708214274Spjd free($1); 709204076Spjd } 710204076Spjd ; 711204076Spjd 712204076Spjdnode_entries: 713204076Spjd | 714204076Spjd node_entries node_entry 715204076Spjd ; 716204076Spjd 717204076Spjdnode_entry: 718204076Spjd control_statement 719204076Spjd | 720229509Strociny pidfile_statement 721229509Strociny | 722204076Spjd listen_statement 723204076Spjd ; 724204076Spjd 725204076Spjdresource_statement: RESOURCE resource_start OB resource_entries CB 726204076Spjd { 727204076Spjd if (curres != NULL) { 728204076Spjd /* 729216721Spjd * There must be section for this node, at least with 730216721Spjd * remote address configuration. 731216721Spjd */ 732216721Spjd if (!hadmynode) { 733216721Spjd char *names; 734216721Spjd 735216721Spjd if (node_names(&names) != 0) 736216721Spjd return (1); 737216721Spjd pjdlog_error("No resource %s configuration for this node (acceptable node names: %s).", 738216721Spjd curres->hr_name, names); 739216721Spjd return (1); 740216721Spjd } 741216721Spjd 742216721Spjd /* 743229509Strociny * Let's see if there are some resource-level settings 744204076Spjd * that we can use for node-level settings. 745204076Spjd */ 746204076Spjd if (curres->hr_provname[0] == '\0' && 747204076Spjd depth1_provname[0] != '\0') { 748204076Spjd /* 749204076Spjd * Provider name is not set at node-level, 750204076Spjd * but is set at resource-level, use it. 751204076Spjd */ 752204076Spjd strlcpy(curres->hr_provname, depth1_provname, 753204076Spjd sizeof(curres->hr_provname)); 754204076Spjd } 755204076Spjd if (curres->hr_localpath[0] == '\0' && 756204076Spjd depth1_localpath[0] != '\0') { 757204076Spjd /* 758204076Spjd * Path to local provider is not set at 759204076Spjd * node-level, but is set at resource-level, 760204076Spjd * use it. 761204076Spjd */ 762204076Spjd strlcpy(curres->hr_localpath, depth1_localpath, 763204076Spjd sizeof(curres->hr_localpath)); 764204076Spjd } 765229509Strociny if (curres->hr_metaflush == -1 && depth1_metaflush != -1) { 766229509Strociny /* 767229509Strociny * Metaflush is not set at node-level, 768229509Strociny * but is set at resource-level, use it. 769229509Strociny */ 770229509Strociny curres->hr_metaflush = depth1_metaflush; 771229509Strociny } 772204076Spjd 773204076Spjd /* 774204076Spjd * If provider name is not given, use resource name 775204076Spjd * as provider name. 776204076Spjd */ 777204076Spjd if (curres->hr_provname[0] == '\0') { 778204076Spjd strlcpy(curres->hr_provname, curres->hr_name, 779204076Spjd sizeof(curres->hr_provname)); 780204076Spjd } 781204076Spjd 782204076Spjd /* 783204076Spjd * Remote address has to be configured at this point. 784204076Spjd */ 785204076Spjd if (curres->hr_remoteaddr[0] == '\0') { 786210883Spjd pjdlog_error("Remote address not configured for resource %s.", 787204076Spjd curres->hr_name); 788210883Spjd return (1); 789204076Spjd } 790204076Spjd /* 791204076Spjd * Path to local provider has to be configured at this 792204076Spjd * point. 793204076Spjd */ 794204076Spjd if (curres->hr_localpath[0] == '\0') { 795210883Spjd pjdlog_error("Path to local component not configured for resource %s.", 796204076Spjd curres->hr_name); 797210883Spjd return (1); 798204076Spjd } 799204076Spjd 800204076Spjd /* Put it onto resource list. */ 801210883Spjd TAILQ_INSERT_TAIL(&lconfig->hc_resources, curres, hr_next); 802204076Spjd curres = NULL; 803204076Spjd } 804204076Spjd } 805204076Spjd ; 806204076Spjd 807204076Spjdresource_start: STR 808204076Spjd { 809216722Spjd /* Check if there is no duplicate entry. */ 810216722Spjd TAILQ_FOREACH(curres, &lconfig->hc_resources, hr_next) { 811216722Spjd if (strcmp(curres->hr_name, $1) == 0) { 812216722Spjd pjdlog_error("Resource %s configured more than once.", 813216722Spjd curres->hr_name); 814216722Spjd free($1); 815216722Spjd return (1); 816216722Spjd } 817216722Spjd } 818216722Spjd 819204076Spjd /* 820204076Spjd * Clear those, so we can tell if they were set at 821204076Spjd * resource-level or not. 822204076Spjd */ 823204076Spjd depth1_provname[0] = '\0'; 824204076Spjd depth1_localpath[0] = '\0'; 825229509Strociny depth1_metaflush = -1; 826216721Spjd hadmynode = false; 827204076Spjd 828204076Spjd curres = calloc(1, sizeof(*curres)); 829204076Spjd if (curres == NULL) { 830210883Spjd pjdlog_error("Unable to allocate memory for resource."); 831214274Spjd free($1); 832210883Spjd return (1); 833204076Spjd } 834204076Spjd if (strlcpy(curres->hr_name, $1, 835204076Spjd sizeof(curres->hr_name)) >= 836204076Spjd sizeof(curres->hr_name)) { 837210883Spjd pjdlog_error("Resource name is too long."); 838231017Strociny free(curres); 839214274Spjd free($1); 840210883Spjd return (1); 841204076Spjd } 842214274Spjd free($1); 843204076Spjd curres->hr_role = HAST_ROLE_INIT; 844204076Spjd curres->hr_previous_role = HAST_ROLE_INIT; 845204076Spjd curres->hr_replication = -1; 846249236Strociny curres->hr_original_replication = -1; 847219351Spjd curres->hr_checksum = -1; 848219354Spjd curres->hr_compression = -1; 849249236Strociny curres->hr_version = 1; 850207371Spjd curres->hr_timeout = -1; 851211886Spjd curres->hr_exec[0] = '\0'; 852204076Spjd curres->hr_provname[0] = '\0'; 853204076Spjd curres->hr_localpath[0] = '\0'; 854204076Spjd curres->hr_localfd = -1; 855229509Strociny curres->hr_localflush = true; 856229509Strociny curres->hr_metaflush = -1; 857204076Spjd curres->hr_remoteaddr[0] = '\0'; 858219818Spjd curres->hr_sourceaddr[0] = '\0'; 859204076Spjd curres->hr_ggateunit = -1; 860204076Spjd } 861204076Spjd ; 862204076Spjd 863204076Spjdresource_entries: 864204076Spjd | 865204076Spjd resource_entries resource_entry 866204076Spjd ; 867204076Spjd 868204076Spjdresource_entry: 869204076Spjd replication_statement 870204076Spjd | 871219351Spjd checksum_statement 872219351Spjd | 873219354Spjd compression_statement 874219354Spjd | 875207371Spjd timeout_statement 876207371Spjd | 877211886Spjd exec_statement 878211886Spjd | 879229509Strociny metaflush_statement 880229509Strociny | 881204076Spjd name_statement 882204076Spjd | 883204076Spjd local_statement 884204076Spjd | 885204076Spjd resource_node_statement 886204076Spjd ; 887204076Spjd 888204076Spjdname_statement: NAME STR 889204076Spjd { 890204076Spjd switch (depth) { 891204076Spjd case 1: 892204076Spjd if (strlcpy(depth1_provname, $2, 893204076Spjd sizeof(depth1_provname)) >= 894204076Spjd sizeof(depth1_provname)) { 895210883Spjd pjdlog_error("name argument is too long."); 896214274Spjd free($2); 897210883Spjd return (1); 898204076Spjd } 899204076Spjd break; 900204076Spjd case 2: 901211883Spjd if (!mynode) 902211883Spjd break; 903229509Strociny PJDLOG_ASSERT(curres != NULL); 904211883Spjd if (strlcpy(curres->hr_provname, $2, 905211883Spjd sizeof(curres->hr_provname)) >= 906211883Spjd sizeof(curres->hr_provname)) { 907211883Spjd pjdlog_error("name argument is too long."); 908214274Spjd free($2); 909211883Spjd return (1); 910204076Spjd } 911204076Spjd break; 912204076Spjd default: 913229509Strociny PJDLOG_ABORT("name at wrong depth level"); 914204076Spjd } 915214274Spjd free($2); 916204076Spjd } 917204076Spjd ; 918204076Spjd 919204076Spjdlocal_statement: LOCAL STR 920204076Spjd { 921204076Spjd switch (depth) { 922204076Spjd case 1: 923204076Spjd if (strlcpy(depth1_localpath, $2, 924204076Spjd sizeof(depth1_localpath)) >= 925204076Spjd sizeof(depth1_localpath)) { 926210883Spjd pjdlog_error("local argument is too long."); 927214274Spjd free($2); 928210883Spjd return (1); 929204076Spjd } 930204076Spjd break; 931204076Spjd case 2: 932211883Spjd if (!mynode) 933211883Spjd break; 934229509Strociny PJDLOG_ASSERT(curres != NULL); 935211883Spjd if (strlcpy(curres->hr_localpath, $2, 936211883Spjd sizeof(curres->hr_localpath)) >= 937211883Spjd sizeof(curres->hr_localpath)) { 938211883Spjd pjdlog_error("local argument is too long."); 939214274Spjd free($2); 940211883Spjd return (1); 941204076Spjd } 942204076Spjd break; 943204076Spjd default: 944229509Strociny PJDLOG_ABORT("local at wrong depth level"); 945204076Spjd } 946214274Spjd free($2); 947204076Spjd } 948204076Spjd ; 949204076Spjd 950204076Spjdresource_node_statement:ON resource_node_start OB resource_node_entries CB 951204076Spjd { 952204076Spjd mynode = false; 953204076Spjd } 954204076Spjd ; 955204076Spjd 956204076Spjdresource_node_start: STR 957204076Spjd { 958210883Spjd if (curres != NULL) { 959210883Spjd switch (isitme($1)) { 960210883Spjd case -1: 961214274Spjd free($1); 962210883Spjd return (1); 963210883Spjd case 0: 964210883Spjd break; 965210883Spjd case 1: 966216721Spjd mynode = hadmynode = true; 967210883Spjd break; 968210883Spjd default: 969229509Strociny PJDLOG_ABORT("invalid isitme() return value"); 970210883Spjd } 971210883Spjd } 972214274Spjd free($1); 973204076Spjd } 974204076Spjd ; 975204076Spjd 976204076Spjdresource_node_entries: 977204076Spjd | 978204076Spjd resource_node_entries resource_node_entry 979204076Spjd ; 980204076Spjd 981204076Spjdresource_node_entry: 982204076Spjd name_statement 983204076Spjd | 984204076Spjd local_statement 985204076Spjd | 986204076Spjd remote_statement 987219818Spjd | 988219818Spjd source_statement 989229509Strociny | 990229509Strociny metaflush_statement 991204076Spjd ; 992204076Spjd 993221643Spjdremote_statement: REMOTE remote_str 994204076Spjd { 995229509Strociny PJDLOG_ASSERT(depth == 2); 996204076Spjd if (mynode) { 997229509Strociny PJDLOG_ASSERT(curres != NULL); 998204076Spjd if (strlcpy(curres->hr_remoteaddr, $2, 999204076Spjd sizeof(curres->hr_remoteaddr)) >= 1000204076Spjd sizeof(curres->hr_remoteaddr)) { 1001210883Spjd pjdlog_error("remote argument is too long."); 1002214274Spjd free($2); 1003210883Spjd return (1); 1004204076Spjd } 1005204076Spjd } 1006214274Spjd free($2); 1007204076Spjd } 1008204076Spjd ; 1009219818Spjd 1010221643Spjdremote_str: 1011221643Spjd NONE { $$ = strdup("none"); } 1012221643Spjd | 1013221643Spjd STR { } 1014221643Spjd ; 1015221643Spjd 1016219818Spjdsource_statement: SOURCE STR 1017219818Spjd { 1018229509Strociny PJDLOG_ASSERT(depth == 2); 1019219818Spjd if (mynode) { 1020229509Strociny PJDLOG_ASSERT(curres != NULL); 1021219818Spjd if (strlcpy(curres->hr_sourceaddr, $2, 1022219818Spjd sizeof(curres->hr_sourceaddr)) >= 1023219818Spjd sizeof(curres->hr_sourceaddr)) { 1024219818Spjd pjdlog_error("source argument is too long."); 1025219818Spjd free($2); 1026219818Spjd return (1); 1027219818Spjd } 1028219818Spjd } 1029219818Spjd free($2); 1030219818Spjd } 1031219818Spjd ; 1032