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