xref: /dragonfly/usr.sbin/dntpd/main.c (revision 3d15852b)
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  *
34*3d15852bSMatthew Dillon  * $DragonFly: src/usr.sbin/dntpd/main.c,v 1.4 2005/04/25 17:42:49 dillon Exp $
35e0163549SMatthew Dillon  */
36e0163549SMatthew Dillon 
37e0163549SMatthew Dillon #include "defs.h"
38e0163549SMatthew Dillon 
39e0163549SMatthew Dillon static void usage(const char *av0);
40e0163549SMatthew Dillon static void dotest(const char *target);
41e0163549SMatthew Dillon static void add_server(const char *target);
42e0163549SMatthew Dillon 
43e0163549SMatthew Dillon static struct server_info **servers;
44e0163549SMatthew Dillon static int nservers;
45e0163549SMatthew Dillon static int maxservers;
46e0163549SMatthew Dillon 
47e0163549SMatthew Dillon int debug_opt;
48*3d15852bSMatthew Dillon int debug_level = -1;		/* (set to default later) */
49fdd4337fSMatthew Dillon int min_sleep_opt = 5;		/* 5 seconds minimum poll interval */
50fdd4337fSMatthew Dillon int nom_sleep_opt = 300;	/* 5 minutes nominal poll interval */
51fdd4337fSMatthew Dillon int max_sleep_opt = 1800;	/* 30 minutes maximum poll interval */
52e0163549SMatthew Dillon 
53e0163549SMatthew Dillon int
54e0163549SMatthew Dillon main(int ac, char **av)
55e0163549SMatthew Dillon {
569b724d8cSMatthew Dillon     int test_opt = 0;
579b724d8cSMatthew Dillon     int rc;
58e0163549SMatthew Dillon     int ch;
59e0163549SMatthew Dillon     int i;
60e0163549SMatthew Dillon 
61e0163549SMatthew Dillon     /*
62e0163549SMatthew Dillon      * Really randomize
63e0163549SMatthew Dillon      */
64e0163549SMatthew Dillon     srandomdev();
659b724d8cSMatthew Dillon     rc = 0;
66e0163549SMatthew Dillon 
67e0163549SMatthew Dillon     /*
68e0163549SMatthew Dillon      * Process Options
69e0163549SMatthew Dillon      */
70*3d15852bSMatthew Dillon     while ((ch = getopt(ac, av, "dl:qtT:L:")) != -1) {
71e0163549SMatthew Dillon 	switch(ch) {
729b724d8cSMatthew Dillon 	case 'T':
73fdd4337fSMatthew Dillon 	    nom_sleep_opt = strtol(optarg, NULL, 0);
74fdd4337fSMatthew Dillon 	    if (nom_sleep_opt < 1) {
75fdd4337fSMatthew Dillon 		fprintf(stderr, "Warning: nominal poll interval too small, "
76fdd4337fSMatthew Dillon 				"limiting to 1 second\n");
77fdd4337fSMatthew Dillon 		nom_sleep_opt = 1;
78fdd4337fSMatthew Dillon 	    }
79fdd4337fSMatthew Dillon 	    if (nom_sleep_opt > 24 * 60 * 60) {
80fdd4337fSMatthew Dillon 		fprintf(stderr, "Warning: nominal poll interval too large, "
81fdd4337fSMatthew Dillon 				"limiting to 24 hours\n");
82fdd4337fSMatthew Dillon 		nom_sleep_opt = 24 * 60 * 60;
83fdd4337fSMatthew Dillon 	    }
84fdd4337fSMatthew Dillon 	    if (min_sleep_opt > nom_sleep_opt)
85fdd4337fSMatthew Dillon 		min_sleep_opt = nom_sleep_opt;
86fdd4337fSMatthew Dillon 	    if (max_sleep_opt < nom_sleep_opt * 5)
87fdd4337fSMatthew Dillon 		max_sleep_opt = nom_sleep_opt * 5;
88fdd4337fSMatthew Dillon 	    break;
89fdd4337fSMatthew Dillon 	case 'L':
90fdd4337fSMatthew Dillon 	    max_sleep_opt = strtol(optarg, NULL, 0);
919b724d8cSMatthew Dillon 	    break;
92*3d15852bSMatthew Dillon 	case 'l':
93*3d15852bSMatthew Dillon 	    debug_level = strtol(optarg, NULL, 0);
94*3d15852bSMatthew Dillon 	    break;
95*3d15852bSMatthew Dillon 	case 'q':
96*3d15852bSMatthew Dillon 	    debug_level = 0;
97*3d15852bSMatthew Dillon 	    break;
98e0163549SMatthew Dillon 	case 'd':
99e0163549SMatthew Dillon 	    debug_opt = 1;
100*3d15852bSMatthew Dillon 	    if (debug_level < 0)
101*3d15852bSMatthew Dillon 		debug_level = 99;
102e0163549SMatthew Dillon 	    break;
103e0163549SMatthew Dillon 	case 't':
1049b724d8cSMatthew Dillon 	    test_opt = 1;
105*3d15852bSMatthew Dillon 	    debug_opt = 1;
106*3d15852bSMatthew Dillon 	    if (debug_level < 0)
107*3d15852bSMatthew Dillon 		debug_level = 99;
1089b724d8cSMatthew Dillon 	    break;
109e0163549SMatthew Dillon 	case 'h':
110e0163549SMatthew Dillon 	default:
111e0163549SMatthew Dillon 	    usage(av[0]);
112e0163549SMatthew Dillon 	    /* not reached */
113e0163549SMatthew Dillon 	}
114e0163549SMatthew Dillon     }
115e0163549SMatthew Dillon 
116*3d15852bSMatthew Dillon     if (debug_level < 0)
117*3d15852bSMatthew Dillon 	debug_level = 1;
118*3d15852bSMatthew Dillon 
119*3d15852bSMatthew Dillon     if (debug_opt == 0)
120*3d15852bSMatthew Dillon 	openlog("dntpd", LOG_CONS|LOG_PID, LOG_DAEMON);
121*3d15852bSMatthew Dillon 
1229b724d8cSMatthew Dillon     if (test_opt) {
1239b724d8cSMatthew Dillon 	if (optind != ac - 1)
1249b724d8cSMatthew Dillon 	    usage(av[0]);
1259b724d8cSMatthew Dillon 	dotest(av[optind]);
1269b724d8cSMatthew Dillon 	/* not reached */
1279b724d8cSMatthew Dillon     }
1289b724d8cSMatthew Dillon 
129e0163549SMatthew Dillon     /*
130e0163549SMatthew Dillon      * Add additional hosts.
131e0163549SMatthew Dillon      */
132e0163549SMatthew Dillon     for (i = optind; i < ac; ++i) {
133e0163549SMatthew Dillon 	add_server(av[i]);
134e0163549SMatthew Dillon     }
135e0163549SMatthew Dillon     if (nservers == 0) {
136e0163549SMatthew Dillon 	usage(av[0]);
137e0163549SMatthew Dillon 	/* not reached */
138e0163549SMatthew Dillon     }
139e0163549SMatthew Dillon 
140e0163549SMatthew Dillon     /*
141e0163549SMatthew Dillon      * And go.
142e0163549SMatthew Dillon      */
143e0163549SMatthew Dillon     client_init();
144e0163549SMatthew Dillon     rc = client_main(servers, nservers);
145e0163549SMatthew Dillon     return(rc);
146e0163549SMatthew Dillon }
147e0163549SMatthew Dillon 
148e0163549SMatthew Dillon static
149e0163549SMatthew Dillon void
150e0163549SMatthew Dillon usage(const char *av0)
151e0163549SMatthew Dillon {
152*3d15852bSMatthew Dillon     fprintf(stderr, "%s [-dqt] [-l log_level] [-T poll_interval] [-L poll_limit] [additional_targets]\n", av0);
1539b724d8cSMatthew Dillon     fprintf(stderr, "\t-d\tforeground operation, debugging turned on\n");
154*3d15852bSMatthew Dillon     fprintf(stderr, "\t-q\tquiet-mode, same as -L 0\n");
1559b724d8cSMatthew Dillon     fprintf(stderr, "\t-t\ttest mode (specify one target on command line)\n");
156*3d15852bSMatthew Dillon     fprintf(stderr, "\t-T\tnominal polling interval\n");
157*3d15852bSMatthew Dillon     fprintf(stderr, "\t-L\tmaximum polling interval\n");
158*3d15852bSMatthew Dillon     fprintf(stderr, "\t-l\tset log level (0-4), default 1\n");
159e0163549SMatthew Dillon     exit(1);
160e0163549SMatthew Dillon }
161e0163549SMatthew Dillon 
162e0163549SMatthew Dillon static
163e0163549SMatthew Dillon void
164e0163549SMatthew Dillon dotest(const char *target)
165e0163549SMatthew Dillon {
166e0163549SMatthew Dillon     struct server_info info;
167e0163549SMatthew Dillon 
168e0163549SMatthew Dillon     bzero(&info, sizeof(info));
169e0163549SMatthew Dillon     info.fd = udp_socket(target, 123);
170e0163549SMatthew Dillon     if (info.fd < 0) {
171e0163549SMatthew Dillon 	logerrstr("unable to create UDP socket for %s", target);
172e0163549SMatthew Dillon 	return;
173e0163549SMatthew Dillon     }
174e0163549SMatthew Dillon     info.target = strdup(target);
175e0163549SMatthew Dillon     client_init();
176e0163549SMatthew Dillon 
1779b724d8cSMatthew Dillon     fprintf(stderr,
178fdd4337fSMatthew Dillon 	    "Will run %d-second polls until interrupted.\n", nom_sleep_opt);
1799b724d8cSMatthew Dillon 
180e0163549SMatthew Dillon     for (;;) {
181fdd4337fSMatthew Dillon 	client_poll(&info, nom_sleep_opt);
182fdd4337fSMatthew Dillon 	sleep(nom_sleep_opt);
183e0163549SMatthew Dillon     }
1849b724d8cSMatthew Dillon     /* not reached */
185e0163549SMatthew Dillon }
186e0163549SMatthew Dillon 
187e0163549SMatthew Dillon static void
188e0163549SMatthew Dillon add_server(const char *target)
189e0163549SMatthew Dillon {
190e0163549SMatthew Dillon     server_info_t info;
191e0163549SMatthew Dillon 
192e0163549SMatthew Dillon     if (nservers == maxservers) {
193e0163549SMatthew Dillon 	maxservers += 16;
194e0163549SMatthew Dillon 	servers = realloc(servers, maxservers * sizeof(server_info_t));
195e0163549SMatthew Dillon 	assert(servers != NULL);
196e0163549SMatthew Dillon     }
197e0163549SMatthew Dillon     info = malloc(sizeof(struct server_info));
198e0163549SMatthew Dillon     servers[nservers] = info;
199e0163549SMatthew Dillon     bzero(info, sizeof(struct server_info));
200e0163549SMatthew Dillon     info->fd = udp_socket(target, 123);
201e0163549SMatthew Dillon     if (info->fd < 0) {
202e0163549SMatthew Dillon 	logerrstr("Unable to add server %s", target);
203e0163549SMatthew Dillon     } else {
204e0163549SMatthew Dillon 	info->target = strdup(target);
205e0163549SMatthew Dillon 	++nservers;
206e0163549SMatthew Dillon     }
207e0163549SMatthew Dillon }
208e0163549SMatthew Dillon 
209