1 %{ 2 /*- 3 * Copyright (c) 2012 The FreeBSD Foundation 4 * All rights reserved. 5 * 6 * This software was developed by Pawel Jakub Dawidek under sponsorship from 7 * the FreeBSD Foundation. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #include <config/config.h> 32 33 #include <sys/types.h> 34 #include <sys/queue.h> 35 #include <sys/sysctl.h> 36 37 #include <arpa/inet.h> 38 39 #include <err.h> 40 #include <errno.h> 41 #include <stdio.h> 42 #include <string.h> 43 #include <sysexits.h> 44 #include <unistd.h> 45 #ifndef HAVE_STRLCPY 46 #include <compat/strlcpy.h> 47 #endif 48 49 #include "auditdistd.h" 50 #include "pjdlog.h" 51 52 extern int depth; 53 extern int lineno; 54 55 extern FILE *yyin; 56 extern char *yytext; 57 58 static struct adist_config *lconfig; 59 static struct adist_host *curhost; 60 #define SECTION_GLOBAL 0 61 #define SECTION_SENDER 1 62 #define SECTION_RECEIVER 2 63 static int cursection; 64 65 /* Sender section. */ 66 static char depth1_source[ADIST_ADDRSIZE]; 67 static int depth1_checksum; 68 static int depth1_compression; 69 /* Sender and receiver sections. */ 70 static char depth1_directory[PATH_MAX]; 71 72 static bool adjust_directory(char *path); 73 static bool family_supported(int family); 74 75 extern void yyrestart(FILE *); 76 %} 77 78 %token CB 79 %token CERTFILE 80 %token DIRECTORY 81 %token FINGERPRINT 82 %token HOST 83 %token KEYFILE 84 %token LISTEN 85 %token NAME 86 %token OB 87 %token PASSWORD 88 %token PIDFILE 89 %token RECEIVER REMOTE 90 %token SENDER SOURCE 91 %token TIMEOUT 92 93 /* 94 %type <num> checksum_type 95 %type <num> compression_type 96 */ 97 98 %union 99 { 100 int num; 101 char *str; 102 } 103 104 %token <num> NUM 105 %token <str> STR 106 107 %% 108 109 statements: 110 | 111 statements statement 112 ; 113 114 statement: 115 name_statement 116 | 117 pidfile_statement 118 | 119 timeout_statement 120 | 121 sender_statement 122 | 123 receiver_statement 124 ; 125 126 name_statement: NAME STR 127 { 128 PJDLOG_RASSERT(depth == 0, 129 "The name variable can only be specificed in the global section."); 130 131 if (lconfig->adc_name[0] != '\0') { 132 pjdlog_error("The name variable is specified twice."); 133 free($2); 134 return (1); 135 } 136 if (strlcpy(lconfig->adc_name, $2, 137 sizeof(lconfig->adc_name)) >= 138 sizeof(lconfig->adc_name)) { 139 pjdlog_error("The name value is too long."); 140 free($2); 141 return (1); 142 } 143 free($2); 144 } 145 ; 146 147 pidfile_statement: PIDFILE STR 148 { 149 PJDLOG_RASSERT(depth == 0, 150 "The pidfile variable can only be specificed in the global section."); 151 152 if (lconfig->adc_pidfile[0] != '\0') { 153 pjdlog_error("The pidfile variable is specified twice."); 154 free($2); 155 return (1); 156 } 157 if (strcmp($2, "none") != 0 && $2[0] != '/') { 158 pjdlog_error("The pidfile variable must be set to absolute pathname or \"none\"."); 159 free($2); 160 return (1); 161 } 162 if (strlcpy(lconfig->adc_pidfile, $2, 163 sizeof(lconfig->adc_pidfile)) >= 164 sizeof(lconfig->adc_pidfile)) { 165 pjdlog_error("The pidfile value is too long."); 166 free($2); 167 return (1); 168 } 169 free($2); 170 } 171 ; 172 173 timeout_statement: TIMEOUT NUM 174 { 175 PJDLOG_ASSERT(depth == 0); 176 177 lconfig->adc_timeout = $2; 178 } 179 ; 180 181 sender_statement: SENDER sender_start sender_entries CB 182 { 183 PJDLOG_ASSERT(depth == 0); 184 PJDLOG_ASSERT(cursection == SECTION_SENDER); 185 186 /* Configure defaults. */ 187 if (depth1_checksum == -1) 188 depth1_checksum = ADIST_CHECKSUM_NONE; 189 if (depth1_compression == -1) 190 depth1_compression = ADIST_COMPRESSION_NONE; 191 if (depth1_directory[0] == '\0') { 192 (void)strlcpy(depth1_directory, ADIST_DIRECTORY_SENDER, 193 sizeof(depth1_directory)); 194 } 195 /* Empty depth1_source is ok. */ 196 TAILQ_FOREACH(curhost, &lconfig->adc_hosts, adh_next) { 197 if (curhost->adh_role != ADIST_ROLE_SENDER) 198 continue; 199 if (curhost->adh_checksum == -1) 200 curhost->adh_checksum = depth1_checksum; 201 if (curhost->adh_compression == -1) 202 curhost->adh_compression = depth1_compression; 203 if (curhost->adh_directory[0] == '\0') { 204 (void)strlcpy(curhost->adh_directory, 205 depth1_directory, 206 sizeof(curhost->adh_directory)); 207 } 208 if (curhost->adh_localaddr[0] == '\0') { 209 (void)strlcpy(curhost->adh_localaddr, 210 depth1_source, 211 sizeof(curhost->adh_localaddr)); 212 } 213 } 214 cursection = SECTION_GLOBAL; 215 } 216 ; 217 218 sender_start: OB 219 { 220 PJDLOG_ASSERT(depth == 1); 221 PJDLOG_ASSERT(cursection == SECTION_GLOBAL); 222 223 cursection = SECTION_SENDER; 224 depth1_checksum = -1; 225 depth1_compression = -1; 226 depth1_source[0] = '\0'; 227 depth1_directory[0] = '\0'; 228 229 #ifndef HAVE_AUDIT_SYSCALLS 230 pjdlog_error("Sender functionality is not available."); 231 return (1); 232 #endif 233 } 234 ; 235 236 sender_entries: 237 | 238 sender_entries sender_entry 239 ; 240 241 sender_entry: 242 source_statement 243 | 244 directory_statement 245 /* 246 | 247 checksum_statement 248 | 249 compression_statement 250 */ 251 | 252 sender_host_statement 253 ; 254 255 receiver_statement: RECEIVER receiver_start receiver_entries CB 256 { 257 PJDLOG_ASSERT(depth == 0); 258 PJDLOG_ASSERT(cursection == SECTION_RECEIVER); 259 260 /* 261 * If not listen addresses were specified, 262 * configure default ones. 263 */ 264 if (TAILQ_EMPTY(&lconfig->adc_listen)) { 265 struct adist_listen *lst; 266 267 if (family_supported(AF_INET)) { 268 lst = calloc(1, sizeof(*lst)); 269 if (lst == NULL) { 270 pjdlog_error("Unable to allocate memory for listen address."); 271 return (1); 272 } 273 (void)strlcpy(lst->adl_addr, 274 ADIST_LISTEN_TLS_TCP4, 275 sizeof(lst->adl_addr)); 276 TAILQ_INSERT_TAIL(&lconfig->adc_listen, lst, adl_next); 277 } else { 278 pjdlog_debug(1, 279 "No IPv4 support in the kernel, not listening on IPv4 address."); 280 } 281 if (family_supported(AF_INET6)) { 282 lst = calloc(1, sizeof(*lst)); 283 if (lst == NULL) { 284 pjdlog_error("Unable to allocate memory for listen address."); 285 return (1); 286 } 287 (void)strlcpy(lst->adl_addr, 288 ADIST_LISTEN_TLS_TCP6, 289 sizeof(lst->adl_addr)); 290 TAILQ_INSERT_TAIL(&lconfig->adc_listen, lst, adl_next); 291 } else { 292 pjdlog_debug(1, 293 "No IPv6 support in the kernel, not listening on IPv6 address."); 294 } 295 if (TAILQ_EMPTY(&lconfig->adc_listen)) { 296 pjdlog_error("No address to listen on."); 297 return (1); 298 } 299 } 300 /* Configure defaults. */ 301 if (depth1_directory[0] == '\0') { 302 (void)strlcpy(depth1_directory, 303 ADIST_DIRECTORY_RECEIVER, 304 sizeof(depth1_directory)); 305 } 306 TAILQ_FOREACH(curhost, &lconfig->adc_hosts, adh_next) { 307 if (curhost->adh_role != ADIST_ROLE_RECEIVER) 308 continue; 309 if (curhost->adh_directory[0] == '\0') { 310 if (snprintf(curhost->adh_directory, 311 sizeof(curhost->adh_directory), "%s/%s", 312 depth1_directory, curhost->adh_name) >= 313 (ssize_t)sizeof(curhost->adh_directory)) { 314 pjdlog_error("Directory value is too long."); 315 return (1); 316 } 317 } 318 } 319 cursection = SECTION_GLOBAL; 320 } 321 ; 322 323 receiver_start: OB 324 { 325 PJDLOG_ASSERT(depth == 1); 326 PJDLOG_ASSERT(cursection == SECTION_GLOBAL); 327 328 cursection = SECTION_RECEIVER; 329 depth1_directory[0] = '\0'; 330 } 331 ; 332 333 receiver_entries: 334 | 335 receiver_entries receiver_entry 336 ; 337 338 receiver_entry: 339 listen_statement 340 | 341 directory_statement 342 | 343 certfile_statement 344 | 345 keyfile_statement 346 | 347 receiver_host_statement 348 ; 349 350 /* 351 checksum_statement: CHECKSUM checksum_type 352 { 353 PJDLOG_ASSERT(cursection == SECTION_SENDER); 354 355 switch (depth) { 356 case 1: 357 depth1_checksum = $2; 358 break; 359 case 2: 360 PJDLOG_ASSERT(curhost != NULL); 361 curhost->adh_checksum = $2; 362 break; 363 default: 364 PJDLOG_ABORT("checksum at wrong depth level"); 365 } 366 } 367 ; 368 369 checksum_type: 370 NONE { $$ = ADIST_CHECKSUM_NONE; } 371 | 372 CRC32 { $$ = ADIST_CHECKSUM_CRC32; } 373 | 374 SHA256 { $$ = ADIST_CHECKSUM_SHA256; } 375 ; 376 377 compression_statement: COMPRESSION compression_type 378 { 379 PJDLOG_ASSERT(cursection == SECTION_SENDER); 380 381 switch (depth) { 382 case 1: 383 depth1_compression = $2; 384 break; 385 case 2: 386 PJDLOG_ASSERT(curhost != NULL); 387 curhost->adh_compression = $2; 388 break; 389 default: 390 PJDLOG_ABORT("compression at wrong depth level"); 391 } 392 } 393 ; 394 395 compression_type: 396 NONE { $$ = ADIST_COMPRESSION_NONE; } 397 | 398 LZF { $$ = ADIST_COMPRESSION_LZF; } 399 ; 400 */ 401 402 directory_statement: DIRECTORY STR 403 { 404 PJDLOG_ASSERT(cursection == SECTION_SENDER || 405 cursection == SECTION_RECEIVER); 406 407 switch (depth) { 408 case 1: 409 if (strlcpy(depth1_directory, $2, 410 sizeof(depth1_directory)) >= 411 sizeof(depth1_directory)) { 412 pjdlog_error("Directory value is too long."); 413 free($2); 414 return (1); 415 } 416 if (!adjust_directory(depth1_directory)) 417 return (1); 418 break; 419 case 2: 420 if (cursection == SECTION_SENDER || $2[0] == '/') { 421 if (strlcpy(curhost->adh_directory, $2, 422 sizeof(curhost->adh_directory)) >= 423 sizeof(curhost->adh_directory)) { 424 pjdlog_error("Directory value is too long."); 425 free($2); 426 return (1); 427 } 428 } else /* if (cursection == SECTION_RECEIVER) */ { 429 if (depth1_directory[0] == '\0') { 430 pjdlog_error("Directory path must be absolute."); 431 free($2); 432 return (1); 433 } 434 if (snprintf(curhost->adh_directory, 435 sizeof(curhost->adh_directory), "%s/%s", 436 depth1_directory, $2) >= 437 (ssize_t)sizeof(curhost->adh_directory)) { 438 pjdlog_error("Directory value is too long."); 439 free($2); 440 return (1); 441 } 442 } 443 break; 444 default: 445 PJDLOG_ABORT("directory at wrong depth level"); 446 } 447 free($2); 448 } 449 ; 450 451 source_statement: SOURCE STR 452 { 453 PJDLOG_RASSERT(cursection == SECTION_SENDER, 454 "The source variable must be in sender section."); 455 456 switch (depth) { 457 case 1: 458 if (strlcpy(depth1_source, $2, 459 sizeof(depth1_source)) >= 460 sizeof(depth1_source)) { 461 pjdlog_error("Source value is too long."); 462 free($2); 463 return (1); 464 } 465 break; 466 case 2: 467 if (strlcpy(curhost->adh_localaddr, $2, 468 sizeof(curhost->adh_localaddr)) >= 469 sizeof(curhost->adh_localaddr)) { 470 pjdlog_error("Source value is too long."); 471 free($2); 472 return (1); 473 } 474 break; 475 } 476 free($2); 477 } 478 ; 479 480 fingerprint_statement: FINGERPRINT STR 481 { 482 PJDLOG_ASSERT(cursection == SECTION_SENDER); 483 PJDLOG_ASSERT(depth == 2); 484 485 if (strncasecmp($2, "SHA256=", 7) != 0) { 486 pjdlog_error("Invalid fingerprint value."); 487 free($2); 488 return (1); 489 } 490 if (strlcpy(curhost->adh_fingerprint, $2, 491 sizeof(curhost->adh_fingerprint)) >= 492 sizeof(curhost->adh_fingerprint)) { 493 pjdlog_error("Fingerprint value is too long."); 494 free($2); 495 return (1); 496 } 497 free($2); 498 } 499 ; 500 501 password_statement: PASSWORD STR 502 { 503 PJDLOG_ASSERT(cursection == SECTION_SENDER || 504 cursection == SECTION_RECEIVER); 505 PJDLOG_ASSERT(depth == 2); 506 507 if (strlcpy(curhost->adh_password, $2, 508 sizeof(curhost->adh_password)) >= 509 sizeof(curhost->adh_password)) { 510 pjdlog_error("Password value is too long."); 511 bzero($2, strlen($2)); 512 free($2); 513 return (1); 514 } 515 bzero($2, strlen($2)); 516 free($2); 517 } 518 ; 519 520 certfile_statement: CERTFILE STR 521 { 522 PJDLOG_ASSERT(cursection == SECTION_RECEIVER); 523 PJDLOG_ASSERT(depth == 1); 524 525 if (strlcpy(lconfig->adc_certfile, $2, 526 sizeof(lconfig->adc_certfile)) >= 527 sizeof(lconfig->adc_certfile)) { 528 pjdlog_error("Certfile value is too long."); 529 free($2); 530 return (1); 531 } 532 free($2); 533 } 534 ; 535 536 keyfile_statement: KEYFILE STR 537 { 538 PJDLOG_ASSERT(cursection == SECTION_RECEIVER); 539 PJDLOG_ASSERT(depth == 1); 540 541 if (strlcpy(lconfig->adc_keyfile, $2, 542 sizeof(lconfig->adc_keyfile)) >= 543 sizeof(lconfig->adc_keyfile)) { 544 pjdlog_error("Keyfile value is too long."); 545 free($2); 546 return (1); 547 } 548 free($2); 549 } 550 ; 551 552 listen_statement: LISTEN STR 553 { 554 struct adist_listen *lst; 555 556 PJDLOG_ASSERT(depth == 1); 557 PJDLOG_ASSERT(cursection == SECTION_RECEIVER); 558 559 lst = calloc(1, sizeof(*lst)); 560 if (lst == NULL) { 561 pjdlog_error("Unable to allocate memory for listen address."); 562 free($2); 563 return (1); 564 } 565 if (strlcpy(lst->adl_addr, $2, sizeof(lst->adl_addr)) >= 566 sizeof(lst->adl_addr)) { 567 pjdlog_error("listen argument is too long."); 568 free($2); 569 free(lst); 570 return (1); 571 } 572 TAILQ_INSERT_TAIL(&lconfig->adc_listen, lst, adl_next); 573 free($2); 574 } 575 ; 576 577 sender_host_statement: HOST host_start OB sender_host_entries CB 578 { 579 /* Put it onto host list. */ 580 TAILQ_INSERT_TAIL(&lconfig->adc_hosts, curhost, adh_next); 581 curhost = NULL; 582 } 583 ; 584 585 receiver_host_statement: HOST host_start OB receiver_host_entries CB 586 { 587 /* Put it onto host list. */ 588 TAILQ_INSERT_TAIL(&lconfig->adc_hosts, curhost, adh_next); 589 curhost = NULL; 590 } 591 ; 592 593 host_start: STR 594 { 595 /* Check if there is no duplicate entry. */ 596 TAILQ_FOREACH(curhost, &lconfig->adc_hosts, adh_next) { 597 if (strcmp(curhost->adh_name, $1) != 0) 598 continue; 599 if (curhost->adh_role == ADIST_ROLE_SENDER && 600 cursection == SECTION_RECEIVER) { 601 continue; 602 } 603 if (curhost->adh_role == ADIST_ROLE_RECEIVER && 604 cursection == SECTION_SENDER) { 605 continue; 606 } 607 pjdlog_error("%s host %s is configured more than once.", 608 curhost->adh_role == ADIST_ROLE_SENDER ? 609 "Sender" : "Receiver", curhost->adh_name); 610 free($1); 611 return (1); 612 } 613 614 curhost = calloc(1, sizeof(*curhost)); 615 if (curhost == NULL) { 616 pjdlog_error("Unable to allocate memory for host configuration."); 617 free($1); 618 return (1); 619 } 620 if (strlcpy(curhost->adh_name, $1, sizeof(curhost->adh_name)) >= 621 sizeof(curhost->adh_name)) { 622 pjdlog_error("Host name is too long."); 623 free($1); 624 return (1); 625 } 626 free($1); 627 curhost->adh_role = cursection == SECTION_SENDER ? 628 ADIST_ROLE_SENDER : ADIST_ROLE_RECEIVER; 629 curhost->adh_version = ADIST_VERSION; 630 curhost->adh_localaddr[0] = '\0'; 631 curhost->adh_remoteaddr[0] = '\0'; 632 curhost->adh_remote = NULL; 633 curhost->adh_directory[0] = '\0'; 634 curhost->adh_password[0] = '\0'; 635 curhost->adh_fingerprint[0] = '\0'; 636 curhost->adh_worker_pid = 0; 637 curhost->adh_conn = NULL; 638 } 639 ; 640 641 sender_host_entries: 642 | 643 sender_host_entries sender_host_entry 644 ; 645 646 sender_host_entry: 647 source_statement 648 | 649 remote_statement 650 | 651 directory_statement 652 | 653 fingerprint_statement 654 | 655 password_statement 656 /* 657 | 658 checksum_statement 659 | 660 compression_statement 661 */ 662 ; 663 664 receiver_host_entries: 665 | 666 receiver_host_entries receiver_host_entry 667 ; 668 669 receiver_host_entry: 670 remote_statement 671 | 672 directory_statement 673 | 674 password_statement 675 ; 676 677 remote_statement: REMOTE STR 678 { 679 PJDLOG_ASSERT(depth == 2); 680 PJDLOG_ASSERT(cursection == SECTION_SENDER || 681 cursection == SECTION_RECEIVER); 682 683 if (strlcpy(curhost->adh_remoteaddr, $2, 684 sizeof(curhost->adh_remoteaddr)) >= 685 sizeof(curhost->adh_remoteaddr)) { 686 pjdlog_error("Remote value is too long."); 687 free($2); 688 return (1); 689 } 690 free($2); 691 } 692 ; 693 694 %% 695 696 static bool 697 family_supported(int family) 698 { 699 int sock; 700 701 sock = socket(family, SOCK_STREAM, 0); 702 if (sock == -1 && errno == EPROTONOSUPPORT) 703 return (false); 704 if (sock >= 0) 705 (void)close(sock); 706 return (true); 707 } 708 709 static bool 710 adjust_directory(char *path) 711 { 712 size_t len; 713 714 len = strlen(path); 715 for (;;) { 716 if (len == 0) { 717 pjdlog_error("Directory path is empty."); 718 return (false); 719 } 720 if (path[len - 1] != '/') 721 break; 722 len--; 723 path[len] = '\0'; 724 } 725 if (path[0] != '/') { 726 pjdlog_error("Directory path must be absolute."); 727 return (false); 728 } 729 return (true); 730 } 731 732 static int 733 my_name(char *name, size_t size) 734 { 735 char buf[MAXHOSTNAMELEN]; 736 char *pos; 737 738 if (gethostname(buf, sizeof(buf)) < 0) { 739 pjdlog_errno(LOG_ERR, "gethostname() failed"); 740 return (-1); 741 } 742 743 /* First component of the host name. */ 744 pos = strchr(buf, '.'); 745 if (pos == NULL) 746 (void)strlcpy(name, buf, size); 747 else 748 (void)strlcpy(name, buf, MIN((size_t)(pos - buf + 1), size)); 749 750 if (name[0] == '\0') { 751 pjdlog_error("Empty host name."); 752 return (-1); 753 } 754 755 return (0); 756 } 757 758 void 759 yyerror(const char *str) 760 { 761 762 pjdlog_error("Unable to parse configuration file at line %d near '%s': %s", 763 lineno, yytext, str); 764 } 765 766 struct adist_config * 767 yy_config_parse(const char *config, bool exitonerror) 768 { 769 int ret; 770 771 curhost = NULL; 772 cursection = SECTION_GLOBAL; 773 depth = 0; 774 lineno = 0; 775 776 lconfig = calloc(1, sizeof(*lconfig)); 777 if (lconfig == NULL) { 778 pjdlog_error("Unable to allocate memory for configuration."); 779 if (exitonerror) 780 exit(EX_TEMPFAIL); 781 return (NULL); 782 } 783 TAILQ_INIT(&lconfig->adc_hosts); 784 TAILQ_INIT(&lconfig->adc_listen); 785 lconfig->adc_name[0] = '\0'; 786 lconfig->adc_timeout = -1; 787 lconfig->adc_pidfile[0] = '\0'; 788 lconfig->adc_certfile[0] = '\0'; 789 lconfig->adc_keyfile[0] = '\0'; 790 791 yyin = fopen(config, "r"); 792 if (yyin == NULL) { 793 pjdlog_errno(LOG_ERR, "Unable to open configuration file %s", 794 config); 795 yy_config_free(lconfig); 796 if (exitonerror) 797 exit(EX_OSFILE); 798 return (NULL); 799 } 800 yyrestart(yyin); 801 ret = yyparse(); 802 fclose(yyin); 803 if (ret != 0) { 804 yy_config_free(lconfig); 805 if (exitonerror) 806 exit(EX_CONFIG); 807 return (NULL); 808 } 809 810 /* 811 * Let's see if everything is set up. 812 */ 813 if (lconfig->adc_name[0] == '\0' && my_name(lconfig->adc_name, 814 sizeof(lconfig->adc_name)) == -1) { 815 yy_config_free(lconfig); 816 if (exitonerror) 817 exit(EX_CONFIG); 818 return (NULL); 819 } 820 if (lconfig->adc_timeout == -1) 821 lconfig->adc_timeout = ADIST_TIMEOUT; 822 if (lconfig->adc_pidfile[0] == '\0') { 823 (void)strlcpy(lconfig->adc_pidfile, ADIST_PIDFILE, 824 sizeof(lconfig->adc_pidfile)); 825 } 826 if (lconfig->adc_certfile[0] == '\0') { 827 (void)strlcpy(lconfig->adc_certfile, ADIST_CERTFILE, 828 sizeof(lconfig->adc_certfile)); 829 } 830 if (lconfig->adc_keyfile[0] == '\0') { 831 (void)strlcpy(lconfig->adc_keyfile, ADIST_KEYFILE, 832 sizeof(lconfig->adc_keyfile)); 833 } 834 835 return (lconfig); 836 } 837 838 void 839 yy_config_free(struct adist_config *config) 840 { 841 struct adist_host *adhost; 842 struct adist_listen *lst; 843 844 while ((lst = TAILQ_FIRST(&config->adc_listen)) != NULL) { 845 TAILQ_REMOVE(&config->adc_listen, lst, adl_next); 846 free(lst); 847 } 848 while ((adhost = TAILQ_FIRST(&config->adc_hosts)) != NULL) { 849 TAILQ_REMOVE(&config->adc_hosts, adhost, adh_next); 850 bzero(adhost, sizeof(*adhost)); 851 free(adhost); 852 } 853 free(config); 854 } 855