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
adjust_directory(char * path)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
my_name(char * name,size_t size)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
yyerror(const char * str)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 *
yy_config_parse(const char * config,bool exitonerror)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
yy_config_free(struct adist_config * config)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