1e0163549SMatthew Dillon /*
2e0163549SMatthew Dillon * Copyright (c) 2005 The DragonFly Project. All rights reserved.
3e0163549SMatthew Dillon *
4e0163549SMatthew Dillon * This code is derived from software contributed to The DragonFly Project
5e0163549SMatthew Dillon * by Matthew Dillon <dillon@backplane.com>
6e0163549SMatthew Dillon *
7e0163549SMatthew Dillon * Redistribution and use in source and binary forms, with or without
8e0163549SMatthew Dillon * modification, are permitted provided that the following conditions
9e0163549SMatthew Dillon * are met:
10e0163549SMatthew Dillon *
11e0163549SMatthew Dillon * 1. Redistributions of source code must retain the above copyright
12e0163549SMatthew Dillon * notice, this list of conditions and the following disclaimer.
13e0163549SMatthew Dillon * 2. Redistributions in binary form must reproduce the above copyright
14e0163549SMatthew Dillon * notice, this list of conditions and the following disclaimer in
15e0163549SMatthew Dillon * the documentation and/or other materials provided with the
16e0163549SMatthew Dillon * distribution.
17e0163549SMatthew Dillon * 3. Neither the name of The DragonFly Project nor the names of its
18e0163549SMatthew Dillon * contributors may be used to endorse or promote products derived
19e0163549SMatthew Dillon * from this software without specific, prior written permission.
20e0163549SMatthew Dillon *
21e0163549SMatthew Dillon * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22e0163549SMatthew Dillon * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23e0163549SMatthew Dillon * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24e0163549SMatthew Dillon * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25e0163549SMatthew Dillon * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26e0163549SMatthew Dillon * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27e0163549SMatthew Dillon * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28e0163549SMatthew Dillon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29e0163549SMatthew Dillon * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30e0163549SMatthew Dillon * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31e0163549SMatthew Dillon * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32e0163549SMatthew Dillon * SUCH DAMAGE.
33e0163549SMatthew Dillon */
34e0163549SMatthew Dillon
35e0163549SMatthew Dillon #include "defs.h"
36e0163549SMatthew Dillon
37e0163549SMatthew Dillon static void usage(const char *av0);
38e0163549SMatthew Dillon static void dotest(const char *target);
39e0163549SMatthew Dillon static void add_server(const char *target);
4097c30a15SMatthew Dillon static void process_config_file(const char *path);
4197c30a15SMatthew Dillon static pid_t check_pid(void);
4297c30a15SMatthew Dillon static void set_pid(const char *av0);
43c32f1362SMatthew Dillon static void sigint_handler(int signo __unused);
44e0163549SMatthew Dillon
45e0163549SMatthew Dillon static struct server_info **servers;
46e0163549SMatthew Dillon static int nservers;
47e0163549SMatthew Dillon static int maxservers;
48e0163549SMatthew Dillon
4997c30a15SMatthew Dillon int daemon_opt = 1;
50c44548fcSMatthew Dillon int debug_opt = 0;
513d15852bSMatthew Dillon int debug_level = -1; /* (set to default later) */
5275349a56SMatthew Dillon int quickset_opt = 0; /* immediately set time of day on startup */
53c44548fcSMatthew Dillon int no_update_opt = 0; /* do not make any actual updates */
54fdd4337fSMatthew Dillon int min_sleep_opt = 5; /* 5 seconds minimum poll interval */
55fdd4337fSMatthew Dillon int nom_sleep_opt = 300; /* 5 minutes nominal poll interval */
56fdd4337fSMatthew Dillon int max_sleep_opt = 1800; /* 30 minutes maximum poll interval */
574d1d74baSMatthias Schmidt int family = PF_UNSPEC; /* Address family */
585e13edd7SMatthew Dillon double insane_deviation = 0.5; /* 0.5 seconds of deviation == insane */
5997c30a15SMatthew Dillon const char *config_opt; /* config file */
6097c30a15SMatthew Dillon const char *pid_opt = "/var/run/dntpd.pid";
61e0163549SMatthew Dillon
62e0163549SMatthew Dillon int
main(int ac,char ** av)63e0163549SMatthew Dillon main(int ac, char **av)
64e0163549SMatthew Dillon {
659b724d8cSMatthew Dillon int test_opt = 0;
6697c30a15SMatthew Dillon pid_t pid;
67e0163549SMatthew Dillon int ch;
68e0163549SMatthew Dillon int i;
69e0163549SMatthew Dillon
70e0163549SMatthew Dillon /*
71e0163549SMatthew Dillon * Really randomize
72e0163549SMatthew Dillon */
73e0163549SMatthew Dillon srandomdev();
74e0163549SMatthew Dillon
75e0163549SMatthew Dillon /*
76e0163549SMatthew Dillon * Process Options
77e0163549SMatthew Dillon */
784d1d74baSMatthias Schmidt while ((ch = getopt(ac, av, "46df:i:l:np:qstFL:QST:")) != -1) {
79e0163549SMatthew Dillon switch(ch) {
804d1d74baSMatthias Schmidt case '4':
814d1d74baSMatthias Schmidt family = PF_INET;
824d1d74baSMatthias Schmidt break;
834d1d74baSMatthias Schmidt case '6':
844d1d74baSMatthias Schmidt family = PF_INET6;
854d1d74baSMatthias Schmidt break;
8697c30a15SMatthew Dillon case 'd':
8797c30a15SMatthew Dillon debug_opt = 1;
8897c30a15SMatthew Dillon daemon_opt = 0;
8997c30a15SMatthew Dillon if (debug_level < 0)
9097c30a15SMatthew Dillon debug_level = 99;
9197c30a15SMatthew Dillon if (config_opt == NULL)
9297c30a15SMatthew Dillon config_opt = "/dev/null";
9397c30a15SMatthew Dillon break;
9497c30a15SMatthew Dillon case 'p':
9597c30a15SMatthew Dillon pid_opt = optarg;
9697c30a15SMatthew Dillon break;
9797c30a15SMatthew Dillon case 'f':
9897c30a15SMatthew Dillon config_opt = optarg;
9997c30a15SMatthew Dillon break;
1005e13edd7SMatthew Dillon case 'i':
1015e13edd7SMatthew Dillon insane_deviation = strtod(optarg, NULL);
1025e13edd7SMatthew Dillon break;
10397c30a15SMatthew Dillon case 'l':
10497c30a15SMatthew Dillon debug_level = strtol(optarg, NULL, 0);
10597c30a15SMatthew Dillon break;
106c44548fcSMatthew Dillon case 'n':
107c44548fcSMatthew Dillon no_update_opt = 1;
108c44548fcSMatthew Dillon break;
10997c30a15SMatthew Dillon case 'q':
11097c30a15SMatthew Dillon debug_level = 0;
11197c30a15SMatthew Dillon break;
11297c30a15SMatthew Dillon case 's':
11397c30a15SMatthew Dillon quickset_opt = 1;
11497c30a15SMatthew Dillon break;
11597c30a15SMatthew Dillon case 'S':
11697c30a15SMatthew Dillon quickset_opt = 0;
11797c30a15SMatthew Dillon break;
11897c30a15SMatthew Dillon case 't':
11997c30a15SMatthew Dillon test_opt = 1;
12097c30a15SMatthew Dillon debug_opt = 1;
12197c30a15SMatthew Dillon daemon_opt = 0;
12297c30a15SMatthew Dillon if (debug_level < 0)
12397c30a15SMatthew Dillon debug_level = 99;
12497c30a15SMatthew Dillon if (config_opt == NULL)
12597c30a15SMatthew Dillon config_opt = "/dev/null";
12697c30a15SMatthew Dillon break;
12797c30a15SMatthew Dillon case 'F':
12897c30a15SMatthew Dillon daemon_opt = 0;
12997c30a15SMatthew Dillon break;
13097c30a15SMatthew Dillon case 'L':
13197c30a15SMatthew Dillon max_sleep_opt = strtol(optarg, NULL, 0);
13297c30a15SMatthew Dillon break;
1339b724d8cSMatthew Dillon case 'T':
134fdd4337fSMatthew Dillon nom_sleep_opt = strtol(optarg, NULL, 0);
135fdd4337fSMatthew Dillon if (nom_sleep_opt < 1) {
136fdd4337fSMatthew Dillon fprintf(stderr, "Warning: nominal poll interval too small, "
137fdd4337fSMatthew Dillon "limiting to 1 second\n");
138fdd4337fSMatthew Dillon nom_sleep_opt = 1;
139fdd4337fSMatthew Dillon }
140fdd4337fSMatthew Dillon if (nom_sleep_opt > 24 * 60 * 60) {
141fdd4337fSMatthew Dillon fprintf(stderr, "Warning: nominal poll interval too large, "
142fdd4337fSMatthew Dillon "limiting to 24 hours\n");
143fdd4337fSMatthew Dillon nom_sleep_opt = 24 * 60 * 60;
144fdd4337fSMatthew Dillon }
145fdd4337fSMatthew Dillon if (min_sleep_opt > nom_sleep_opt)
146fdd4337fSMatthew Dillon min_sleep_opt = nom_sleep_opt;
147fdd4337fSMatthew Dillon if (max_sleep_opt < nom_sleep_opt * 5)
148fdd4337fSMatthew Dillon max_sleep_opt = nom_sleep_opt * 5;
149fdd4337fSMatthew Dillon break;
15097c30a15SMatthew Dillon case 'Q':
15197c30a15SMatthew Dillon if ((pid = check_pid()) != 0) {
15297c30a15SMatthew Dillon fprintf(stderr, "%s: killing old daemon\n", av[0]);
15397c30a15SMatthew Dillon kill(pid, SIGINT);
15497c30a15SMatthew Dillon usleep(100000);
15597c30a15SMatthew Dillon if (check_pid())
15697c30a15SMatthew Dillon sleep(1);
15797c30a15SMatthew Dillon if (check_pid())
15897c30a15SMatthew Dillon sleep(9);
15997c30a15SMatthew Dillon if (check_pid()) {
160c44548fcSMatthew Dillon fprintf(stderr, "%s: Unable to kill running daemon.\n", av[0]);
16197c30a15SMatthew Dillon } else {
162c44548fcSMatthew Dillon fprintf(stderr, "%s: Running daemon has been terminated.\n", av[0]);
16397c30a15SMatthew Dillon }
16497c30a15SMatthew Dillon } else {
165c44548fcSMatthew Dillon fprintf(stderr, "%s: There is no daemon running to kill.\n", av[0]);
16697c30a15SMatthew Dillon }
16797c30a15SMatthew Dillon exit(0);
1689b724d8cSMatthew Dillon break;
169e0163549SMatthew Dillon case 'h':
170e0163549SMatthew Dillon default:
171e0163549SMatthew Dillon usage(av[0]);
172e0163549SMatthew Dillon /* not reached */
173e0163549SMatthew Dillon }
174e0163549SMatthew Dillon }
1752408d859SMatthew Dillon
1762408d859SMatthew Dillon /*
1772408d859SMatthew Dillon * Make sure min and nom intervals are less then or equal to the maximum
1782408d859SMatthew Dillon * interval.
1792408d859SMatthew Dillon */
1802408d859SMatthew Dillon if (min_sleep_opt > max_sleep_opt)
1812408d859SMatthew Dillon min_sleep_opt = max_sleep_opt;
1822408d859SMatthew Dillon if (nom_sleep_opt > max_sleep_opt)
1832408d859SMatthew Dillon nom_sleep_opt = max_sleep_opt;
1842408d859SMatthew Dillon
1852408d859SMatthew Dillon /*
1862408d859SMatthew Dillon * Set default config file
1872408d859SMatthew Dillon */
18897c30a15SMatthew Dillon if (config_opt == NULL) {
18997c30a15SMatthew Dillon if (optind != ac)
19097c30a15SMatthew Dillon config_opt = "/dev/null";
19197c30a15SMatthew Dillon else
19297c30a15SMatthew Dillon config_opt = "/etc/dntpd.conf";
19397c30a15SMatthew Dillon }
194e0163549SMatthew Dillon
1953d15852bSMatthew Dillon if (debug_level < 0)
1963d15852bSMatthew Dillon debug_level = 1;
1973d15852bSMatthew Dillon
19897c30a15SMatthew Dillon process_config_file(config_opt);
19997c30a15SMatthew Dillon
2003d15852bSMatthew Dillon if (debug_opt == 0)
2013d15852bSMatthew Dillon openlog("dntpd", LOG_CONS|LOG_PID, LOG_DAEMON);
2023d15852bSMatthew Dillon
2039b724d8cSMatthew Dillon if (test_opt) {
2049b724d8cSMatthew Dillon if (optind != ac - 1)
2059b724d8cSMatthew Dillon usage(av[0]);
2069b724d8cSMatthew Dillon dotest(av[optind]);
2079b724d8cSMatthew Dillon /* not reached */
2089b724d8cSMatthew Dillon }
2099b724d8cSMatthew Dillon
210e0163549SMatthew Dillon /*
211e0163549SMatthew Dillon * Add additional hosts.
212e0163549SMatthew Dillon */
213e0163549SMatthew Dillon for (i = optind; i < ac; ++i) {
214e0163549SMatthew Dillon add_server(av[i]);
215e0163549SMatthew Dillon }
216e0163549SMatthew Dillon if (nservers == 0) {
217e0163549SMatthew Dillon usage(av[0]);
218e0163549SMatthew Dillon /* not reached */
219e0163549SMatthew Dillon }
220e0163549SMatthew Dillon
221e0163549SMatthew Dillon /*
22297c30a15SMatthew Dillon * Do an initial course time setting if requested using the first
22397c30a15SMatthew Dillon * host successfully polled.
22497c30a15SMatthew Dillon */
22597c30a15SMatthew Dillon /* XXX */
22697c30a15SMatthew Dillon
22797c30a15SMatthew Dillon /*
22897c30a15SMatthew Dillon * Daemonize, stop logging to stderr.
22997c30a15SMatthew Dillon */
23097c30a15SMatthew Dillon if (daemon_opt) {
23197c30a15SMatthew Dillon if ((pid = check_pid()) != 0) {
23297c30a15SMatthew Dillon logerrstr("%s: NOTE: killing old daemon and starting a new one",
23397c30a15SMatthew Dillon av[0]);
23497c30a15SMatthew Dillon kill(pid, SIGINT);
23597c30a15SMatthew Dillon usleep(100000);
23697c30a15SMatthew Dillon if (check_pid())
23797c30a15SMatthew Dillon sleep(1);
23897c30a15SMatthew Dillon if (check_pid())
23997c30a15SMatthew Dillon sleep(9);
24097c30a15SMatthew Dillon if (check_pid()) {
24197c30a15SMatthew Dillon logerrstr("%s: Unable to kill running daemon, exiting", av[0]);
24297c30a15SMatthew Dillon exit(1);
24397c30a15SMatthew Dillon }
24497c30a15SMatthew Dillon }
24597c30a15SMatthew Dillon daemon(0, 0);
24697c30a15SMatthew Dillon } else if (check_pid() != 0) {
24797c30a15SMatthew Dillon logerrstr("%s: A background dntpd is running, you must kill it first",
24897c30a15SMatthew Dillon av[0]);
24997c30a15SMatthew Dillon exit(1);
25097c30a15SMatthew Dillon }
25197c30a15SMatthew Dillon if (debug_opt == 0) {
25297c30a15SMatthew Dillon log_stderr = 0;
25397c30a15SMatthew Dillon set_pid(av[0]);
25497c30a15SMatthew Dillon signal(SIGINT, sigint_handler);
25597c30a15SMatthew Dillon logdebug(0, "dntpd version %s started\n", DNTPD_VERSION);
25697c30a15SMatthew Dillon }
25797c30a15SMatthew Dillon
25897c30a15SMatthew Dillon /*
259e0163549SMatthew Dillon * And go.
260e0163549SMatthew Dillon */
261c44548fcSMatthew Dillon sysntp_clear_alternative_corrections();
262e0163549SMatthew Dillon client_init();
2632408d859SMatthew Dillon client_check_duplicate_ips(servers, nservers);
264*1d9b37b0SSascha Wildner client_main(servers, nservers);
265*1d9b37b0SSascha Wildner return(0);
266e0163549SMatthew Dillon }
267e0163549SMatthew Dillon
268e0163549SMatthew Dillon static
269e0163549SMatthew Dillon void
usage(const char * av0)270e0163549SMatthew Dillon usage(const char *av0)
271e0163549SMatthew Dillon {
272d399b893SMatthew Dillon fprintf(stderr, "%s [-dnqstFSQ] [-f config_file] [-l log_level] [-T poll_interval] [-L poll_limit] [additional_targets]\n", av0);
27397c30a15SMatthew Dillon fprintf(stderr,
27497c30a15SMatthew Dillon "\t-d\tDebugging mode, implies -F, -l 99, and logs to stderr\n"
27597c30a15SMatthew Dillon "\t-f file\tSpecify the config file (/etc/dntpd.conf)\n"
27697c30a15SMatthew Dillon "\t-l int\tSet log level (0-4), default 1\n"
277c44548fcSMatthew Dillon "\t-n\tNo-update mode. No offset or frequency corrections are made\n"
27897c30a15SMatthew Dillon "\t-q\tQuiet-mode, same as -L 0\n"
27997c30a15SMatthew Dillon "\t-s\tSet the time immediately on startup\n"
280c44548fcSMatthew Dillon "\t-t\tTest mode, implies -F, -l 99, -n, logs to stderr\n"
281c44548fcSMatthew Dillon "\t-F\tRun in foreground (log still goes to syslog)\n"
28297c30a15SMatthew Dillon "\t-L int\tMaximum polling interval\n"
28397c30a15SMatthew Dillon "\t-S\tDo not set the time immediately on startup\n"
28497c30a15SMatthew Dillon "\t-T int\tNominal polling interval\n"
28597c30a15SMatthew Dillon "\t-Q\tTerminate any running background daemon\n"
286c44548fcSMatthew Dillon "\n"
287c44548fcSMatthew Dillon "\t\tNOTE: in debug and test modes -f must be specified if\n"
288c44548fcSMatthew Dillon "\t\tyou want to use a config file.\n"
28997c30a15SMatthew Dillon );
290e0163549SMatthew Dillon exit(1);
291e0163549SMatthew Dillon }
292e0163549SMatthew Dillon
293e0163549SMatthew Dillon static
294e0163549SMatthew Dillon void
dotest(const char * target)295e0163549SMatthew Dillon dotest(const char *target)
296e0163549SMatthew Dillon {
297e0163549SMatthew Dillon struct server_info info;
298e0163549SMatthew Dillon
299e0163549SMatthew Dillon bzero(&info, sizeof(info));
3004d1d74baSMatthias Schmidt info.sam = (struct sockaddr *)&info.sam_st;
30185ecde19SNicolas Thery info.fd = udp_socket(target, 123, info.sam, LOG_DNS_ERROR);
302e0163549SMatthew Dillon if (info.fd < 0) {
303e0163549SMatthew Dillon logerrstr("unable to create UDP socket for %s", target);
304e0163549SMatthew Dillon return;
305e0163549SMatthew Dillon }
306e0163549SMatthew Dillon info.target = strdup(target);
307e0163549SMatthew Dillon client_init();
308e0163549SMatthew Dillon
3099b724d8cSMatthew Dillon fprintf(stderr,
310fdd4337fSMatthew Dillon "Will run %d-second polls until interrupted.\n", nom_sleep_opt);
3119b724d8cSMatthew Dillon
312e0163549SMatthew Dillon for (;;) {
313c32f1362SMatthew Dillon client_poll(&info, nom_sleep_opt, 1);
314fdd4337fSMatthew Dillon sleep(nom_sleep_opt);
315e0163549SMatthew Dillon }
3169b724d8cSMatthew Dillon /* not reached */
317e0163549SMatthew Dillon }
318e0163549SMatthew Dillon
3194d1d74baSMatthias Schmidt static char *
myaddr2ascii(struct sockaddr * sa)3204d1d74baSMatthias Schmidt myaddr2ascii(struct sockaddr *sa)
3214d1d74baSMatthias Schmidt {
3224d1d74baSMatthias Schmidt static char str[INET6_ADDRSTRLEN];
3234d1d74baSMatthias Schmidt struct sockaddr_in *soin;
3244d1d74baSMatthias Schmidt struct sockaddr_in6 *sin6;
3254d1d74baSMatthias Schmidt
3264d1d74baSMatthias Schmidt switch (sa->sa_family) {
3274d1d74baSMatthias Schmidt case AF_INET:
3284d1d74baSMatthias Schmidt soin = (struct sockaddr_in *) sa;
3294d1d74baSMatthias Schmidt inet_ntop(AF_INET, &soin->sin_addr, str, sizeof(str));
3304d1d74baSMatthias Schmidt break;
3314d1d74baSMatthias Schmidt case AF_INET6:
3324d1d74baSMatthias Schmidt sin6 = (struct sockaddr_in6 *) sa;
3334d1d74baSMatthias Schmidt inet_ntop(AF_INET6, &sin6->sin6_addr, str, sizeof(str));
3344d1d74baSMatthias Schmidt break;
3354d1d74baSMatthias Schmidt }
3364d1d74baSMatthias Schmidt return (str);
3374d1d74baSMatthias Schmidt }
3384d1d74baSMatthias Schmidt
339e0163549SMatthew Dillon static void
add_server(const char * target)340e0163549SMatthew Dillon add_server(const char *target)
341e0163549SMatthew Dillon {
342e0163549SMatthew Dillon server_info_t info;
343e0163549SMatthew Dillon
344e0163549SMatthew Dillon if (nservers == maxservers) {
345e0163549SMatthew Dillon maxservers += 16;
346e0163549SMatthew Dillon servers = realloc(servers, maxservers * sizeof(server_info_t));
347e0163549SMatthew Dillon assert(servers != NULL);
348e0163549SMatthew Dillon }
349e0163549SMatthew Dillon info = malloc(sizeof(struct server_info));
350e0163549SMatthew Dillon servers[nservers] = info;
351e0163549SMatthew Dillon bzero(info, sizeof(struct server_info));
3524d1d74baSMatthias Schmidt info->sam = (struct sockaddr *)&info->sam_st;
353e0163549SMatthew Dillon info->target = strdup(target);
35485ecde19SNicolas Thery /*
35585ecde19SNicolas Thery * Postpone socket opening and server name resolution until we are in main
35685ecde19SNicolas Thery * loop to avoid hang during init if network down.
35785ecde19SNicolas Thery */
35885ecde19SNicolas Thery info->fd = -1;
35985ecde19SNicolas Thery info->server_state = -1;
360e0163549SMatthew Dillon ++nservers;
361e0163549SMatthew Dillon }
3622408d859SMatthew Dillon
3632408d859SMatthew Dillon void
disconnect_server(server_info_t info)3642408d859SMatthew Dillon disconnect_server(server_info_t info)
3652408d859SMatthew Dillon {
3662408d859SMatthew Dillon if (info->fd >= 0)
3672408d859SMatthew Dillon close(info->fd);
3682408d859SMatthew Dillon info->fd = -1;
3692408d859SMatthew Dillon if (info->ipstr) {
3702408d859SMatthew Dillon free(info->ipstr);
3712408d859SMatthew Dillon info->ipstr = NULL;
3722408d859SMatthew Dillon }
3732408d859SMatthew Dillon }
3742408d859SMatthew Dillon
3752408d859SMatthew Dillon void
reconnect_server(server_info_t info)3762408d859SMatthew Dillon reconnect_server(server_info_t info)
3772408d859SMatthew Dillon {
3782408d859SMatthew Dillon const char *ipstr;
37985ecde19SNicolas Thery dns_error_policy_t policy;
3802408d859SMatthew Dillon
38185ecde19SNicolas Thery /*
38285ecde19SNicolas Thery * Ignore DNS errors if never connected before to handle the case where
38385ecde19SNicolas Thery * we're started before network up.
38485ecde19SNicolas Thery */
38585ecde19SNicolas Thery policy = IGNORE_DNS_ERROR;
38685ecde19SNicolas Thery if (info->fd >= 0) {
3872408d859SMatthew Dillon close(info->fd);
38885ecde19SNicolas Thery policy = LOG_DNS_ERROR;
38985ecde19SNicolas Thery }
3902408d859SMatthew Dillon if (info->ipstr) {
3912408d859SMatthew Dillon free(info->ipstr);
3922408d859SMatthew Dillon info->ipstr = NULL;
3932408d859SMatthew Dillon }
3944d1d74baSMatthias Schmidt info->sam = (struct sockaddr *)&info->sam_st;
39585ecde19SNicolas Thery info->fd = udp_socket(info->target, 123, info->sam, policy);
3962408d859SMatthew Dillon if (info->fd >= 0) {
3974d1d74baSMatthias Schmidt ipstr = myaddr2ascii(info->sam);
3982408d859SMatthew Dillon info->ipstr = strdup(ipstr);
3992408d859SMatthew Dillon }
400e0163549SMatthew Dillon }
401e0163549SMatthew Dillon
40297c30a15SMatthew Dillon static void
process_config_file(const char * path)40397c30a15SMatthew Dillon process_config_file(const char *path)
40497c30a15SMatthew Dillon {
40597c30a15SMatthew Dillon const char *ws = " \t\r\n";
40697c30a15SMatthew Dillon char buf[1024];
40797c30a15SMatthew Dillon char *keyword;
40897c30a15SMatthew Dillon char *data;
40997c30a15SMatthew Dillon int line;
41097c30a15SMatthew Dillon FILE *fi;
41197c30a15SMatthew Dillon
41297c30a15SMatthew Dillon if ((fi = fopen(path, "r")) != NULL) {
41397c30a15SMatthew Dillon line = 1;
41497c30a15SMatthew Dillon while (fgets(buf, sizeof(buf), fi) != NULL) {
41597c30a15SMatthew Dillon if (strchr(buf, '#'))
41697c30a15SMatthew Dillon *strchr(buf, '#') = 0;
41797c30a15SMatthew Dillon if ((keyword = strtok(buf, ws)) != NULL) {
41897c30a15SMatthew Dillon data = strtok(NULL, ws);
41997c30a15SMatthew Dillon if (strcmp(keyword, "server") == 0) {
42097c30a15SMatthew Dillon if (data == NULL) {
42197c30a15SMatthew Dillon logerr("%s:%d server missing host specification",
42297c30a15SMatthew Dillon path, line);
42397c30a15SMatthew Dillon } else {
42497c30a15SMatthew Dillon add_server(data);
42597c30a15SMatthew Dillon }
42697c30a15SMatthew Dillon } else {
42797c30a15SMatthew Dillon logerr("%s:%d unknown keyword %s", path, line, keyword);
42897c30a15SMatthew Dillon }
42997c30a15SMatthew Dillon }
43097c30a15SMatthew Dillon ++line;
43197c30a15SMatthew Dillon }
43297c30a15SMatthew Dillon fclose(fi);
43397c30a15SMatthew Dillon } else {
43497c30a15SMatthew Dillon logerr("Unable to open %s", path);
43597c30a15SMatthew Dillon exit(1);
43697c30a15SMatthew Dillon }
43797c30a15SMatthew Dillon }
43897c30a15SMatthew Dillon
43997c30a15SMatthew Dillon static
44097c30a15SMatthew Dillon pid_t
check_pid(void)44197c30a15SMatthew Dillon check_pid(void)
44297c30a15SMatthew Dillon {
44397c30a15SMatthew Dillon char buf[32];
44497c30a15SMatthew Dillon pid_t pid;
44597c30a15SMatthew Dillon FILE *fi;
44697c30a15SMatthew Dillon
44797c30a15SMatthew Dillon pid = 0;
44897c30a15SMatthew Dillon if ((fi = fopen(pid_opt, "r")) != NULL) {
44997c30a15SMatthew Dillon if (fgets(buf, sizeof(buf), fi) != NULL) {
45097c30a15SMatthew Dillon pid = strtol(buf, NULL, 0);
45197c30a15SMatthew Dillon if (kill(pid, 0) != 0)
45297c30a15SMatthew Dillon pid = 0;
45397c30a15SMatthew Dillon }
45497c30a15SMatthew Dillon fclose(fi);
45597c30a15SMatthew Dillon }
45697c30a15SMatthew Dillon return(pid);
45797c30a15SMatthew Dillon }
45897c30a15SMatthew Dillon
45997c30a15SMatthew Dillon static
46097c30a15SMatthew Dillon void
set_pid(const char * av0)46197c30a15SMatthew Dillon set_pid(const char *av0)
46297c30a15SMatthew Dillon {
46397c30a15SMatthew Dillon pid_t pid;
46497c30a15SMatthew Dillon FILE *fo;
46597c30a15SMatthew Dillon
46697c30a15SMatthew Dillon pid = getpid();
46797c30a15SMatthew Dillon if ((fo = fopen(pid_opt, "w")) != NULL) {
46897c30a15SMatthew Dillon fprintf(fo, "%d\n", (int)pid);
46997c30a15SMatthew Dillon fclose(fo);
47097c30a15SMatthew Dillon } else {
47197c30a15SMatthew Dillon logerr("%s: Unable to create %s, continuing anyway.", av0, pid_opt);
47297c30a15SMatthew Dillon }
47397c30a15SMatthew Dillon }
47497c30a15SMatthew Dillon
47597c30a15SMatthew Dillon static
47697c30a15SMatthew Dillon void
sigint_handler(int signo __unused)477c32f1362SMatthew Dillon sigint_handler(int signo __unused)
47897c30a15SMatthew Dillon {
47997c30a15SMatthew Dillon remove(pid_opt);
48097c30a15SMatthew Dillon /* dangerous, but we are exiting anyway so pray... */
48197c30a15SMatthew Dillon logdebug(0, "dntpd version %s stopped\n", DNTPD_VERSION);
48297c30a15SMatthew Dillon exit(0);
48397c30a15SMatthew Dillon }
48497c30a15SMatthew Dillon
485