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