parse.y revision 222108
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: head/sbin/hastd/parse.y 222108 2011-05-19 23:18:42Z pjd $ 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 <assert.h> 42204076Spjd#include <err.h> 43222108Spjd#include <errno.h> 44204076Spjd#include <stdio.h> 45204076Spjd#include <string.h> 46204076Spjd#include <sysexits.h> 47204076Spjd#include <unistd.h> 48204076Spjd 49210883Spjd#include <pjdlog.h> 50210883Spjd 51204076Spjd#include "hast.h" 52204076Spjd 53204076Spjdextern int depth; 54204076Spjdextern int lineno; 55204076Spjd 56204076Spjdextern FILE *yyin; 57204076Spjdextern char *yytext; 58204076Spjd 59210883Spjdstatic struct hastd_config *lconfig; 60204076Spjdstatic struct hast_resource *curres; 61216721Spjdstatic bool mynode, hadmynode; 62204076Spjd 63204076Spjdstatic char depth0_control[HAST_ADDRSIZE]; 64222108Spjdstatic char depth0_listen_ipv4[HAST_ADDRSIZE]; 65222108Spjdstatic char depth0_listen_ipv6[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]; 72204076Spjd 73204076Spjdstatic char depth1_provname[PATH_MAX]; 74204076Spjdstatic char depth1_localpath[PATH_MAX]; 75204076Spjd 76210883Spjdextern void yyrestart(FILE *); 77210883Spjd 78210883Spjdstatic int 79204076Spjdisitme(const char *name) 80204076Spjd{ 81204076Spjd char buf[MAXHOSTNAMELEN]; 82204076Spjd char *pos; 83204076Spjd size_t bufsize; 84204076Spjd 85204076Spjd /* 86204076Spjd * First check if the give name matches our full hostname. 87204076Spjd */ 88210883Spjd if (gethostname(buf, sizeof(buf)) < 0) { 89210883Spjd pjdlog_errno(LOG_ERR, "gethostname() failed"); 90210883Spjd return (-1); 91210883Spjd } 92204076Spjd if (strcmp(buf, name) == 0) 93210883Spjd return (1); 94204076Spjd 95204076Spjd /* 96204076Spjd * Now check if it matches first part of the host name. 97204076Spjd */ 98204076Spjd pos = strchr(buf, '.'); 99221632Strociny if (pos != NULL && (size_t)(pos - buf) == strlen(name) && 100221632Strociny strncmp(buf, name, pos - buf) == 0) { 101210883Spjd return (1); 102221632Strociny } 103204076Spjd 104204076Spjd /* 105204076Spjd * At the end check if name is equal to our host's UUID. 106204076Spjd */ 107204076Spjd bufsize = sizeof(buf); 108210883Spjd if (sysctlbyname("kern.hostuuid", buf, &bufsize, NULL, 0) < 0) { 109210883Spjd pjdlog_errno(LOG_ERR, "sysctlbyname(kern.hostuuid) failed"); 110210883Spjd return (-1); 111210883Spjd } 112204076Spjd if (strcasecmp(buf, name) == 0) 113210883Spjd return (1); 114204076Spjd 115204076Spjd /* 116204076Spjd * Looks like this isn't about us. 117204076Spjd */ 118210883Spjd return (0); 119204076Spjd} 120204076Spjd 121222108Spjdstatic bool 122222108Spjdfamily_supported(int family) 123222108Spjd{ 124222108Spjd int sock; 125222108Spjd 126222108Spjd sock = socket(family, SOCK_STREAM, 0); 127222108Spjd if (sock == -1 && errno == EPROTONOSUPPORT) 128222108Spjd return (false); 129222108Spjd if (sock >= 0) 130222108Spjd (void)close(sock); 131222108Spjd return (true); 132222108Spjd} 133222108Spjd 134216721Spjdstatic int 135216721Spjdnode_names(char **namesp) 136216721Spjd{ 137216721Spjd static char names[MAXHOSTNAMELEN * 3]; 138216721Spjd char buf[MAXHOSTNAMELEN]; 139216721Spjd char *pos; 140216721Spjd size_t bufsize; 141216721Spjd 142216721Spjd if (gethostname(buf, sizeof(buf)) < 0) { 143216721Spjd pjdlog_errno(LOG_ERR, "gethostname() failed"); 144216721Spjd return (-1); 145216721Spjd } 146216721Spjd 147216721Spjd /* First component of the host name. */ 148216721Spjd pos = strchr(buf, '.'); 149216721Spjd if (pos != NULL && pos != buf) { 150216721Spjd (void)strlcpy(names, buf, MIN((size_t)(pos - buf + 1), 151216721Spjd sizeof(names))); 152216721Spjd (void)strlcat(names, ", ", sizeof(names)); 153216721Spjd } 154216721Spjd 155216721Spjd /* Full host name. */ 156216721Spjd (void)strlcat(names, buf, sizeof(names)); 157216721Spjd (void)strlcat(names, ", ", sizeof(names)); 158216721Spjd 159216721Spjd /* Host UUID. */ 160216721Spjd bufsize = sizeof(buf); 161216721Spjd if (sysctlbyname("kern.hostuuid", buf, &bufsize, NULL, 0) < 0) { 162216721Spjd pjdlog_errno(LOG_ERR, "sysctlbyname(kern.hostuuid) failed"); 163216721Spjd return (-1); 164216721Spjd } 165216721Spjd (void)strlcat(names, buf, sizeof(names)); 166216721Spjd 167216721Spjd *namesp = names; 168216721Spjd 169216721Spjd return (0); 170216721Spjd} 171216721Spjd 172204076Spjdvoid 173204076Spjdyyerror(const char *str) 174204076Spjd{ 175204076Spjd 176210883Spjd pjdlog_error("Unable to parse configuration file at line %d near '%s': %s", 177204076Spjd lineno, yytext, str); 178204076Spjd} 179204076Spjd 180204076Spjdstruct hastd_config * 181210883Spjdyy_config_parse(const char *config, bool exitonerror) 182204076Spjd{ 183204076Spjd int ret; 184204076Spjd 185204076Spjd curres = NULL; 186204076Spjd mynode = false; 187210883Spjd depth = 0; 188210883Spjd lineno = 0; 189204076Spjd 190207371Spjd depth0_timeout = HAST_TIMEOUT; 191220573Spjd depth0_replication = HAST_REPLICATION_FULLSYNC; 192219351Spjd depth0_checksum = HAST_CHECKSUM_NONE; 193219354Spjd depth0_compression = HAST_COMPRESSION_HOLE; 194204076Spjd strlcpy(depth0_control, HAST_CONTROL, sizeof(depth0_control)); 195222108Spjd TAILQ_INIT(&depth0_listen); 196222108Spjd strlcpy(depth0_listen_ipv4, HASTD_LISTEN_IPV4, 197222108Spjd sizeof(depth0_listen_ipv4)); 198222108Spjd strlcpy(depth0_listen_ipv6, HASTD_LISTEN_IPV6, 199222108Spjd sizeof(depth0_listen_ipv6)); 200211886Spjd depth0_exec[0] = '\0'; 201204076Spjd 202210883Spjd lconfig = calloc(1, sizeof(*lconfig)); 203210883Spjd if (lconfig == NULL) { 204210883Spjd pjdlog_error("Unable to allocate memory for configuration."); 205210883Spjd if (exitonerror) 206210883Spjd exit(EX_TEMPFAIL); 207210883Spjd return (NULL); 208210883Spjd } 209204076Spjd 210222108Spjd TAILQ_INIT(&lconfig->hc_listen); 211210883Spjd TAILQ_INIT(&lconfig->hc_resources); 212210883Spjd 213204076Spjd yyin = fopen(config, "r"); 214210883Spjd if (yyin == NULL) { 215210883Spjd pjdlog_errno(LOG_ERR, "Unable to open configuration file %s", 216210883Spjd config); 217210883Spjd yy_config_free(lconfig); 218210883Spjd if (exitonerror) 219210883Spjd exit(EX_OSFILE); 220210883Spjd return (NULL); 221210883Spjd } 222210883Spjd yyrestart(yyin); 223204076Spjd ret = yyparse(); 224204076Spjd fclose(yyin); 225204076Spjd if (ret != 0) { 226210883Spjd yy_config_free(lconfig); 227210883Spjd if (exitonerror) 228210883Spjd exit(EX_CONFIG); 229210883Spjd return (NULL); 230204076Spjd } 231204076Spjd 232204076Spjd /* 233204076Spjd * Let's see if everything is set up. 234204076Spjd */ 235210883Spjd if (lconfig->hc_controladdr[0] == '\0') { 236210883Spjd strlcpy(lconfig->hc_controladdr, depth0_control, 237210883Spjd sizeof(lconfig->hc_controladdr)); 238204076Spjd } 239222108Spjd if (!TAILQ_EMPTY(&depth0_listen)) 240222108Spjd TAILQ_CONCAT(&lconfig->hc_listen, &depth0_listen, hl_next); 241222108Spjd if (TAILQ_EMPTY(&lconfig->hc_listen)) { 242222108Spjd struct hastd_listen *lst; 243222108Spjd 244222108Spjd if (family_supported(AF_INET)) { 245222108Spjd lst = calloc(1, sizeof(*lst)); 246222108Spjd if (lst == NULL) { 247222108Spjd pjdlog_error("Unable to allocate memory for listen address."); 248222108Spjd yy_config_free(lconfig); 249222108Spjd if (exitonerror) 250222108Spjd exit(EX_TEMPFAIL); 251222108Spjd return (NULL); 252222108Spjd } 253222108Spjd (void)strlcpy(lst->hl_addr, depth0_listen_ipv4, 254222108Spjd sizeof(lst->hl_addr)); 255222108Spjd TAILQ_INSERT_TAIL(&lconfig->hc_listen, lst, hl_next); 256222108Spjd } else { 257222108Spjd pjdlog_debug(1, 258222108Spjd "No IPv4 support in the kernel, not listening on IPv4 address."); 259222108Spjd } 260222108Spjd#ifdef notyet 261222108Spjd if (family_supported(AF_INET6)) { 262222108Spjd lst = calloc(1, sizeof(*lst)); 263222108Spjd if (lst == NULL) { 264222108Spjd pjdlog_error("Unable to allocate memory for listen address."); 265222108Spjd yy_config_free(lconfig); 266222108Spjd if (exitonerror) 267222108Spjd exit(EX_TEMPFAIL); 268222108Spjd return (NULL); 269222108Spjd } 270222108Spjd (void)strlcpy(lst->hl_addr, depth0_listen_ipv6, 271222108Spjd sizeof(lst->hl_addr)); 272222108Spjd TAILQ_INSERT_TAIL(&lconfig->hc_listen, lst, hl_next); 273222108Spjd } else { 274222108Spjd pjdlog_debug(1, 275222108Spjd "No IPv6 support in the kernel, not listening on IPv6 address."); 276222108Spjd } 277222108Spjd#endif 278222108Spjd if (TAILQ_EMPTY(&lconfig->hc_listen)) { 279222108Spjd pjdlog_error("No address to listen on."); 280222108Spjd yy_config_free(lconfig); 281222108Spjd if (exitonerror) 282222108Spjd exit(EX_TEMPFAIL); 283222108Spjd return (NULL); 284222108Spjd } 285204076Spjd } 286210883Spjd TAILQ_FOREACH(curres, &lconfig->hc_resources, hr_next) { 287204076Spjd assert(curres->hr_provname[0] != '\0'); 288204076Spjd assert(curres->hr_localpath[0] != '\0'); 289204076Spjd assert(curres->hr_remoteaddr[0] != '\0'); 290204076Spjd 291204076Spjd if (curres->hr_replication == -1) { 292204076Spjd /* 293204076Spjd * Replication is not set at resource-level. 294204076Spjd * Use global or default setting. 295204076Spjd */ 296204076Spjd curres->hr_replication = depth0_replication; 297204076Spjd } 298220573Spjd if (curres->hr_replication == HAST_REPLICATION_MEMSYNC || 299220573Spjd curres->hr_replication == HAST_REPLICATION_ASYNC) { 300220573Spjd pjdlog_warning("Replication mode \"%s\" is not implemented, falling back to \"%s\".", 301220573Spjd curres->hr_replication == HAST_REPLICATION_MEMSYNC ? 302220573Spjd "memsync" : "async", "fullsync"); 303220573Spjd curres->hr_replication = HAST_REPLICATION_FULLSYNC; 304220573Spjd } 305219351Spjd if (curres->hr_checksum == -1) { 306219351Spjd /* 307219351Spjd * Checksum is not set at resource-level. 308219351Spjd * Use global or default setting. 309219351Spjd */ 310219351Spjd curres->hr_checksum = depth0_checksum; 311219351Spjd } 312219354Spjd if (curres->hr_compression == -1) { 313219354Spjd /* 314219354Spjd * Compression is not set at resource-level. 315219354Spjd * Use global or default setting. 316219354Spjd */ 317219354Spjd curres->hr_compression = depth0_compression; 318219354Spjd } 319207371Spjd if (curres->hr_timeout == -1) { 320207371Spjd /* 321207371Spjd * Timeout is not set at resource-level. 322207371Spjd * Use global or default setting. 323207371Spjd */ 324207371Spjd curres->hr_timeout = depth0_timeout; 325207371Spjd } 326211886Spjd if (curres->hr_exec[0] == '\0') { 327211886Spjd /* 328211886Spjd * Exec is not set at resource-level. 329211886Spjd * Use global or default setting. 330211886Spjd */ 331211886Spjd strlcpy(curres->hr_exec, depth0_exec, 332211886Spjd sizeof(curres->hr_exec)); 333211886Spjd } 334204076Spjd } 335204076Spjd 336210883Spjd return (lconfig); 337204076Spjd} 338204076Spjd 339204076Spjdvoid 340204076Spjdyy_config_free(struct hastd_config *config) 341204076Spjd{ 342222108Spjd struct hastd_listen *lst; 343204076Spjd struct hast_resource *res; 344204076Spjd 345222108Spjd while ((lst = TAILQ_FIRST(&depth0_listen)) != NULL) { 346222108Spjd TAILQ_REMOVE(&depth0_listen, lst, hl_next); 347222108Spjd free(lst); 348222108Spjd } 349222108Spjd while ((lst = TAILQ_FIRST(&config->hc_listen)) != NULL) { 350222108Spjd TAILQ_REMOVE(&config->hc_listen, lst, hl_next); 351222108Spjd free(lst); 352222108Spjd } 353204076Spjd while ((res = TAILQ_FIRST(&config->hc_resources)) != NULL) { 354204076Spjd TAILQ_REMOVE(&config->hc_resources, res, hr_next); 355204076Spjd free(res); 356204076Spjd } 357210883Spjd free(config); 358204076Spjd} 359204076Spjd%} 360204076Spjd 361219354Spjd%token CONTROL LISTEN PORT REPLICATION CHECKSUM COMPRESSION 362219818Spjd%token TIMEOUT EXEC EXTENTSIZE RESOURCE NAME LOCAL REMOTE SOURCE ON 363219354Spjd%token FULLSYNC MEMSYNC ASYNC NONE CRC32 SHA256 HOLE LZF 364204076Spjd%token NUM STR OB CB 365204076Spjd 366221643Spjd%type <str> remote_str 367204076Spjd%type <num> replication_type 368219351Spjd%type <num> checksum_type 369219354Spjd%type <num> compression_type 370204076Spjd 371204076Spjd%union 372204076Spjd{ 373204076Spjd int num; 374204076Spjd char *str; 375204076Spjd} 376204076Spjd 377204076Spjd%token <num> NUM 378204076Spjd%token <str> STR 379204076Spjd 380204076Spjd%% 381204076Spjd 382204076Spjdstatements: 383204076Spjd | 384204076Spjd statements statement 385204076Spjd ; 386204076Spjd 387204076Spjdstatement: 388204076Spjd control_statement 389204076Spjd | 390204076Spjd listen_statement 391204076Spjd | 392204076Spjd replication_statement 393204076Spjd | 394219351Spjd checksum_statement 395219351Spjd | 396219354Spjd compression_statement 397219354Spjd | 398207371Spjd timeout_statement 399207371Spjd | 400211886Spjd exec_statement 401211886Spjd | 402204076Spjd node_statement 403204076Spjd | 404204076Spjd resource_statement 405204076Spjd ; 406204076Spjd 407204076Spjdcontrol_statement: CONTROL STR 408204076Spjd { 409204076Spjd switch (depth) { 410204076Spjd case 0: 411204076Spjd if (strlcpy(depth0_control, $2, 412204076Spjd sizeof(depth0_control)) >= 413204076Spjd sizeof(depth0_control)) { 414210883Spjd pjdlog_error("control argument is too long."); 415214274Spjd free($2); 416210883Spjd return (1); 417204076Spjd } 418204076Spjd break; 419204076Spjd case 1: 420211883Spjd if (!mynode) 421211883Spjd break; 422211883Spjd if (strlcpy(lconfig->hc_controladdr, $2, 423211883Spjd sizeof(lconfig->hc_controladdr)) >= 424211883Spjd sizeof(lconfig->hc_controladdr)) { 425211883Spjd pjdlog_error("control argument is too long."); 426214274Spjd free($2); 427211883Spjd return (1); 428204076Spjd } 429204076Spjd break; 430204076Spjd default: 431204076Spjd assert(!"control at wrong depth level"); 432204076Spjd } 433214274Spjd free($2); 434204076Spjd } 435204076Spjd ; 436204076Spjd 437204076Spjdlisten_statement: LISTEN STR 438204076Spjd { 439222108Spjd struct hastd_listen *lst; 440222108Spjd 441222108Spjd lst = calloc(1, sizeof(*lst)); 442222108Spjd if (lst == NULL) { 443222108Spjd pjdlog_error("Unable to allocate memory for listen address."); 444222108Spjd free($2); 445222108Spjd return (1); 446222108Spjd } 447222108Spjd if (strlcpy(lst->hl_addr, $2, sizeof(lst->hl_addr)) >= 448222108Spjd sizeof(lst->hl_addr)) { 449222108Spjd pjdlog_error("listen argument is too long."); 450222108Spjd free($2); 451222108Spjd free(lst); 452222108Spjd return (1); 453222108Spjd } 454204076Spjd switch (depth) { 455204076Spjd case 0: 456222108Spjd TAILQ_INSERT_TAIL(&depth0_listen, lst, hl_next); 457204076Spjd break; 458204076Spjd case 1: 459222108Spjd if (mynode) 460222108Spjd TAILQ_INSERT_TAIL(&depth0_listen, lst, hl_next); 461222108Spjd else 462222108Spjd free(lst); 463204076Spjd break; 464204076Spjd default: 465204076Spjd assert(!"listen at wrong depth level"); 466204076Spjd } 467214274Spjd free($2); 468204076Spjd } 469204076Spjd ; 470204076Spjd 471204076Spjdreplication_statement: REPLICATION replication_type 472204076Spjd { 473204076Spjd switch (depth) { 474204076Spjd case 0: 475204076Spjd depth0_replication = $2; 476204076Spjd break; 477204076Spjd case 1: 478204076Spjd if (curres != NULL) 479204076Spjd curres->hr_replication = $2; 480204076Spjd break; 481204076Spjd default: 482204076Spjd assert(!"replication at wrong depth level"); 483204076Spjd } 484204076Spjd } 485204076Spjd ; 486204076Spjd 487204076Spjdreplication_type: 488204076Spjd FULLSYNC { $$ = HAST_REPLICATION_FULLSYNC; } 489204076Spjd | 490204076Spjd MEMSYNC { $$ = HAST_REPLICATION_MEMSYNC; } 491204076Spjd | 492204076Spjd ASYNC { $$ = HAST_REPLICATION_ASYNC; } 493204076Spjd ; 494204076Spjd 495219351Spjdchecksum_statement: CHECKSUM checksum_type 496219351Spjd { 497219351Spjd switch (depth) { 498219351Spjd case 0: 499219351Spjd depth0_checksum = $2; 500219351Spjd break; 501219351Spjd case 1: 502219351Spjd if (curres != NULL) 503219351Spjd curres->hr_checksum = $2; 504219351Spjd break; 505219351Spjd default: 506219351Spjd assert(!"checksum at wrong depth level"); 507219351Spjd } 508219351Spjd } 509219351Spjd ; 510219351Spjd 511219351Spjdchecksum_type: 512219351Spjd NONE { $$ = HAST_CHECKSUM_NONE; } 513219351Spjd | 514219351Spjd CRC32 { $$ = HAST_CHECKSUM_CRC32; } 515219351Spjd | 516219351Spjd SHA256 { $$ = HAST_CHECKSUM_SHA256; } 517219351Spjd ; 518219351Spjd 519219354Spjdcompression_statement: COMPRESSION compression_type 520219354Spjd { 521219354Spjd switch (depth) { 522219354Spjd case 0: 523219354Spjd depth0_compression = $2; 524219354Spjd break; 525219354Spjd case 1: 526219354Spjd if (curres != NULL) 527219354Spjd curres->hr_compression = $2; 528219354Spjd break; 529219354Spjd default: 530219354Spjd assert(!"compression at wrong depth level"); 531219354Spjd } 532219354Spjd } 533219354Spjd ; 534219354Spjd 535219354Spjdcompression_type: 536219354Spjd NONE { $$ = HAST_COMPRESSION_NONE; } 537219354Spjd | 538219354Spjd HOLE { $$ = HAST_COMPRESSION_HOLE; } 539219354Spjd | 540219354Spjd LZF { $$ = HAST_COMPRESSION_LZF; } 541219354Spjd ; 542219354Spjd 543207371Spjdtimeout_statement: TIMEOUT NUM 544207371Spjd { 545220889Spjd if ($2 <= 0) { 546220889Spjd pjdlog_error("Negative or zero timeout."); 547220889Spjd return (1); 548220889Spjd } 549207371Spjd switch (depth) { 550207371Spjd case 0: 551207371Spjd depth0_timeout = $2; 552207371Spjd break; 553207371Spjd case 1: 554207371Spjd if (curres != NULL) 555207371Spjd curres->hr_timeout = $2; 556207371Spjd break; 557207371Spjd default: 558207371Spjd assert(!"timeout at wrong depth level"); 559207371Spjd } 560207371Spjd } 561207371Spjd ; 562207371Spjd 563211886Spjdexec_statement: EXEC STR 564211886Spjd { 565211886Spjd switch (depth) { 566211886Spjd case 0: 567211886Spjd if (strlcpy(depth0_exec, $2, sizeof(depth0_exec)) >= 568211886Spjd sizeof(depth0_exec)) { 569211886Spjd pjdlog_error("Exec path is too long."); 570214274Spjd free($2); 571211886Spjd return (1); 572211886Spjd } 573211886Spjd break; 574211886Spjd case 1: 575211886Spjd if (curres == NULL) 576211886Spjd break; 577211886Spjd if (strlcpy(curres->hr_exec, $2, 578211886Spjd sizeof(curres->hr_exec)) >= 579211886Spjd sizeof(curres->hr_exec)) { 580211886Spjd pjdlog_error("Exec path is too long."); 581214274Spjd free($2); 582211886Spjd return (1); 583211886Spjd } 584211886Spjd break; 585211886Spjd default: 586211886Spjd assert(!"exec at wrong depth level"); 587211886Spjd } 588214274Spjd free($2); 589211886Spjd } 590211886Spjd ; 591211886Spjd 592204076Spjdnode_statement: ON node_start OB node_entries CB 593204076Spjd { 594204076Spjd mynode = false; 595204076Spjd } 596204076Spjd ; 597204076Spjd 598204076Spjdnode_start: STR 599204076Spjd { 600210883Spjd switch (isitme($1)) { 601210883Spjd case -1: 602214274Spjd free($1); 603210883Spjd return (1); 604210883Spjd case 0: 605210883Spjd break; 606210883Spjd case 1: 607204076Spjd mynode = true; 608210883Spjd break; 609210883Spjd default: 610210883Spjd assert(!"invalid isitme() return value"); 611210883Spjd } 612214274Spjd free($1); 613204076Spjd } 614204076Spjd ; 615204076Spjd 616204076Spjdnode_entries: 617204076Spjd | 618204076Spjd node_entries node_entry 619204076Spjd ; 620204076Spjd 621204076Spjdnode_entry: 622204076Spjd control_statement 623204076Spjd | 624204076Spjd listen_statement 625204076Spjd ; 626204076Spjd 627204076Spjdresource_statement: RESOURCE resource_start OB resource_entries CB 628204076Spjd { 629204076Spjd if (curres != NULL) { 630204076Spjd /* 631216721Spjd * There must be section for this node, at least with 632216721Spjd * remote address configuration. 633216721Spjd */ 634216721Spjd if (!hadmynode) { 635216721Spjd char *names; 636216721Spjd 637216721Spjd if (node_names(&names) != 0) 638216721Spjd return (1); 639216721Spjd pjdlog_error("No resource %s configuration for this node (acceptable node names: %s).", 640216721Spjd curres->hr_name, names); 641216721Spjd return (1); 642216721Spjd } 643216721Spjd 644216721Spjd /* 645204076Spjd * Let's see there are some resource-level settings 646204076Spjd * that we can use for node-level settings. 647204076Spjd */ 648204076Spjd if (curres->hr_provname[0] == '\0' && 649204076Spjd depth1_provname[0] != '\0') { 650204076Spjd /* 651204076Spjd * Provider name is not set at node-level, 652204076Spjd * but is set at resource-level, use it. 653204076Spjd */ 654204076Spjd strlcpy(curres->hr_provname, depth1_provname, 655204076Spjd sizeof(curres->hr_provname)); 656204076Spjd } 657204076Spjd if (curres->hr_localpath[0] == '\0' && 658204076Spjd depth1_localpath[0] != '\0') { 659204076Spjd /* 660204076Spjd * Path to local provider is not set at 661204076Spjd * node-level, but is set at resource-level, 662204076Spjd * use it. 663204076Spjd */ 664204076Spjd strlcpy(curres->hr_localpath, depth1_localpath, 665204076Spjd sizeof(curres->hr_localpath)); 666204076Spjd } 667204076Spjd 668204076Spjd /* 669204076Spjd * If provider name is not given, use resource name 670204076Spjd * as provider name. 671204076Spjd */ 672204076Spjd if (curres->hr_provname[0] == '\0') { 673204076Spjd strlcpy(curres->hr_provname, curres->hr_name, 674204076Spjd sizeof(curres->hr_provname)); 675204076Spjd } 676204076Spjd 677204076Spjd /* 678204076Spjd * Remote address has to be configured at this point. 679204076Spjd */ 680204076Spjd if (curres->hr_remoteaddr[0] == '\0') { 681210883Spjd pjdlog_error("Remote address not configured for resource %s.", 682204076Spjd curres->hr_name); 683210883Spjd return (1); 684204076Spjd } 685204076Spjd /* 686204076Spjd * Path to local provider has to be configured at this 687204076Spjd * point. 688204076Spjd */ 689204076Spjd if (curres->hr_localpath[0] == '\0') { 690210883Spjd pjdlog_error("Path to local component not configured for resource %s.", 691204076Spjd curres->hr_name); 692210883Spjd return (1); 693204076Spjd } 694204076Spjd 695204076Spjd /* Put it onto resource list. */ 696210883Spjd TAILQ_INSERT_TAIL(&lconfig->hc_resources, curres, hr_next); 697204076Spjd curres = NULL; 698204076Spjd } 699204076Spjd } 700204076Spjd ; 701204076Spjd 702204076Spjdresource_start: STR 703204076Spjd { 704216722Spjd /* Check if there is no duplicate entry. */ 705216722Spjd TAILQ_FOREACH(curres, &lconfig->hc_resources, hr_next) { 706216722Spjd if (strcmp(curres->hr_name, $1) == 0) { 707216722Spjd pjdlog_error("Resource %s configured more than once.", 708216722Spjd curres->hr_name); 709216722Spjd free($1); 710216722Spjd return (1); 711216722Spjd } 712216722Spjd } 713216722Spjd 714204076Spjd /* 715204076Spjd * Clear those, so we can tell if they were set at 716204076Spjd * resource-level or not. 717204076Spjd */ 718204076Spjd depth1_provname[0] = '\0'; 719204076Spjd depth1_localpath[0] = '\0'; 720216721Spjd hadmynode = false; 721204076Spjd 722204076Spjd curres = calloc(1, sizeof(*curres)); 723204076Spjd if (curres == NULL) { 724210883Spjd pjdlog_error("Unable to allocate memory for resource."); 725214274Spjd free($1); 726210883Spjd return (1); 727204076Spjd } 728204076Spjd if (strlcpy(curres->hr_name, $1, 729204076Spjd sizeof(curres->hr_name)) >= 730204076Spjd sizeof(curres->hr_name)) { 731210883Spjd pjdlog_error("Resource name is too long."); 732214274Spjd free($1); 733210883Spjd return (1); 734204076Spjd } 735214274Spjd free($1); 736204076Spjd curres->hr_role = HAST_ROLE_INIT; 737204076Spjd curres->hr_previous_role = HAST_ROLE_INIT; 738204076Spjd curres->hr_replication = -1; 739219351Spjd curres->hr_checksum = -1; 740219354Spjd curres->hr_compression = -1; 741207371Spjd curres->hr_timeout = -1; 742211886Spjd curres->hr_exec[0] = '\0'; 743204076Spjd curres->hr_provname[0] = '\0'; 744204076Spjd curres->hr_localpath[0] = '\0'; 745204076Spjd curres->hr_localfd = -1; 746204076Spjd curres->hr_remoteaddr[0] = '\0'; 747219818Spjd curres->hr_sourceaddr[0] = '\0'; 748204076Spjd curres->hr_ggateunit = -1; 749204076Spjd } 750204076Spjd ; 751204076Spjd 752204076Spjdresource_entries: 753204076Spjd | 754204076Spjd resource_entries resource_entry 755204076Spjd ; 756204076Spjd 757204076Spjdresource_entry: 758204076Spjd replication_statement 759204076Spjd | 760219351Spjd checksum_statement 761219351Spjd | 762219354Spjd compression_statement 763219354Spjd | 764207371Spjd timeout_statement 765207371Spjd | 766211886Spjd exec_statement 767211886Spjd | 768204076Spjd name_statement 769204076Spjd | 770204076Spjd local_statement 771204076Spjd | 772204076Spjd resource_node_statement 773204076Spjd ; 774204076Spjd 775204076Spjdname_statement: NAME STR 776204076Spjd { 777204076Spjd switch (depth) { 778204076Spjd case 1: 779204076Spjd if (strlcpy(depth1_provname, $2, 780204076Spjd sizeof(depth1_provname)) >= 781204076Spjd sizeof(depth1_provname)) { 782210883Spjd pjdlog_error("name argument is too long."); 783214274Spjd free($2); 784210883Spjd return (1); 785204076Spjd } 786204076Spjd break; 787204076Spjd case 2: 788211883Spjd if (!mynode) 789211883Spjd break; 790211883Spjd assert(curres != NULL); 791211883Spjd if (strlcpy(curres->hr_provname, $2, 792211883Spjd sizeof(curres->hr_provname)) >= 793211883Spjd sizeof(curres->hr_provname)) { 794211883Spjd pjdlog_error("name argument is too long."); 795214274Spjd free($2); 796211883Spjd return (1); 797204076Spjd } 798204076Spjd break; 799204076Spjd default: 800204076Spjd assert(!"name at wrong depth level"); 801204076Spjd } 802214274Spjd free($2); 803204076Spjd } 804204076Spjd ; 805204076Spjd 806204076Spjdlocal_statement: LOCAL STR 807204076Spjd { 808204076Spjd switch (depth) { 809204076Spjd case 1: 810204076Spjd if (strlcpy(depth1_localpath, $2, 811204076Spjd sizeof(depth1_localpath)) >= 812204076Spjd sizeof(depth1_localpath)) { 813210883Spjd pjdlog_error("local argument is too long."); 814214274Spjd free($2); 815210883Spjd return (1); 816204076Spjd } 817204076Spjd break; 818204076Spjd case 2: 819211883Spjd if (!mynode) 820211883Spjd break; 821211883Spjd assert(curres != NULL); 822211883Spjd if (strlcpy(curres->hr_localpath, $2, 823211883Spjd sizeof(curres->hr_localpath)) >= 824211883Spjd sizeof(curres->hr_localpath)) { 825211883Spjd pjdlog_error("local argument is too long."); 826214274Spjd free($2); 827211883Spjd return (1); 828204076Spjd } 829204076Spjd break; 830204076Spjd default: 831204076Spjd assert(!"local at wrong depth level"); 832204076Spjd } 833214274Spjd free($2); 834204076Spjd } 835204076Spjd ; 836204076Spjd 837204076Spjdresource_node_statement:ON resource_node_start OB resource_node_entries CB 838204076Spjd { 839204076Spjd mynode = false; 840204076Spjd } 841204076Spjd ; 842204076Spjd 843204076Spjdresource_node_start: STR 844204076Spjd { 845210883Spjd if (curres != NULL) { 846210883Spjd switch (isitme($1)) { 847210883Spjd case -1: 848214274Spjd free($1); 849210883Spjd return (1); 850210883Spjd case 0: 851210883Spjd break; 852210883Spjd case 1: 853216721Spjd mynode = hadmynode = true; 854210883Spjd break; 855210883Spjd default: 856210883Spjd assert(!"invalid isitme() return value"); 857210883Spjd } 858210883Spjd } 859214274Spjd free($1); 860204076Spjd } 861204076Spjd ; 862204076Spjd 863204076Spjdresource_node_entries: 864204076Spjd | 865204076Spjd resource_node_entries resource_node_entry 866204076Spjd ; 867204076Spjd 868204076Spjdresource_node_entry: 869204076Spjd name_statement 870204076Spjd | 871204076Spjd local_statement 872204076Spjd | 873204076Spjd remote_statement 874219818Spjd | 875219818Spjd source_statement 876204076Spjd ; 877204076Spjd 878221643Spjdremote_statement: REMOTE remote_str 879204076Spjd { 880204076Spjd assert(depth == 2); 881204076Spjd if (mynode) { 882204076Spjd assert(curres != NULL); 883204076Spjd if (strlcpy(curres->hr_remoteaddr, $2, 884204076Spjd sizeof(curres->hr_remoteaddr)) >= 885204076Spjd sizeof(curres->hr_remoteaddr)) { 886210883Spjd pjdlog_error("remote argument is too long."); 887214274Spjd free($2); 888210883Spjd return (1); 889204076Spjd } 890204076Spjd } 891214274Spjd free($2); 892204076Spjd } 893204076Spjd ; 894219818Spjd 895221643Spjdremote_str: 896221643Spjd NONE { $$ = strdup("none"); } 897221643Spjd | 898221643Spjd STR { } 899221643Spjd ; 900221643Spjd 901219818Spjdsource_statement: SOURCE STR 902219818Spjd { 903219818Spjd assert(depth == 2); 904219818Spjd if (mynode) { 905219818Spjd assert(curres != NULL); 906219818Spjd if (strlcpy(curres->hr_sourceaddr, $2, 907219818Spjd sizeof(curres->hr_sourceaddr)) >= 908219818Spjd sizeof(curres->hr_sourceaddr)) { 909219818Spjd pjdlog_error("source argument is too long."); 910219818Spjd free($2); 911219818Spjd return (1); 912219818Spjd } 913219818Spjd } 914219818Spjd free($2); 915219818Spjd } 916219818Spjd ; 917