Blame client.c

Packit 96c956
/*
Packit 96c956
  chronyd/chronyc - Programs for keeping computer clocks accurate.
Packit 96c956
Packit 96c956
 **********************************************************************
Packit 96c956
 * Copyright (C) Richard P. Curnow  1997-2003
Packit 96c956
 * Copyright (C) Lonnie Abelbeck  2016, 2018
Packit 96c956
 * Copyright (C) Miroslav Lichvar  2009-2018
Packit 96c956
 * 
Packit 96c956
 * This program is free software; you can redistribute it and/or modify
Packit 96c956
 * it under the terms of version 2 of the GNU General Public License as
Packit 96c956
 * published by the Free Software Foundation.
Packit 96c956
 * 
Packit 96c956
 * This program is distributed in the hope that it will be useful, but
Packit 96c956
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 96c956
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 96c956
 * General Public License for more details.
Packit 96c956
 * 
Packit 96c956
 * You should have received a copy of the GNU General Public License along
Packit 96c956
 * with this program; if not, write to the Free Software Foundation, Inc.,
Packit 96c956
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
Packit 96c956
 * 
Packit 96c956
 **********************************************************************
Packit 96c956
Packit 96c956
  =======================================================================
Packit 96c956
Packit 96c956
  Command line client for configuring the daemon and obtaining status
Packit 96c956
  from it whilst running.
Packit 96c956
  */
Packit 96c956
Packit 96c956
#include "config.h"
Packit 96c956
Packit 96c956
#include "sysincl.h"
Packit 96c956
Packit 96c956
#include "array.h"
Packit 96c956
#include "candm.h"
Packit 96c956
#include "logging.h"
Packit 96c956
#include "memory.h"
Packit 96c956
#include "nameserv.h"
Packit 96c956
#include "getdate.h"
Packit 96c956
#include "cmdparse.h"
Packit 96c956
#include "pktlength.h"
Packit 96c956
#include "util.h"
Packit 96c956
Packit 96c956
#ifdef FEAT_READLINE
Packit 96c956
#ifdef USE_EDITLINE
Packit 96c956
#include <editline/readline.h>
Packit 96c956
#else
Packit 96c956
#include <readline/readline.h>
Packit 96c956
#include <readline/history.h>
Packit 96c956
#endif
Packit 96c956
#endif
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
union sockaddr_all {
Packit 96c956
  struct sockaddr_in in4;
Packit 96c956
#ifdef FEAT_IPV6
Packit 96c956
  struct sockaddr_in6 in6;
Packit 96c956
#endif
Packit 96c956
  struct sockaddr_un un;
Packit 96c956
  struct sockaddr sa;
Packit 96c956
};
Packit 96c956
Packit 96c956
static ARR_Instance sockaddrs;
Packit 96c956
Packit 96c956
static int sock_fd = -1;
Packit 96c956
Packit 96c956
static int quit = 0;
Packit 96c956
Packit 96c956
static int on_terminal = 0;
Packit 96c956
Packit 96c956
static int no_dns = 0;
Packit 96c956
Packit 96c956
static int csv_mode = 0;
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
/* Log a message. This is a minimalistic replacement of the logging.c
Packit 96c956
   implementation to avoid linking with it and other modules. */
Packit 96c956
Packit 96c956
int log_debug_enabled = 0;
Packit 96c956
Packit 96c956
void LOG_Message(LOG_Severity severity,
Packit 96c956
#if DEBUG > 0
Packit 96c956
                 int line_number, const char *filename, const char *function_name,
Packit 96c956
#endif
Packit 96c956
                 const char *format, ...)
Packit 96c956
{
Packit 96c956
  va_list ap;
Packit 96c956
Packit 96c956
  va_start(ap, format);
Packit 96c956
  vfprintf(stderr, format, ap);
Packit 96c956
  putc('\n', stderr);
Packit 96c956
  va_end(ap);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
/* Read a single line of commands from standard input */
Packit 96c956
Packit 96c956
#ifdef FEAT_READLINE
Packit 96c956
static char **command_name_completion(const char *text, int start, int end);
Packit 96c956
#endif
Packit 96c956
Packit 96c956
static char *
Packit 96c956
read_line(void)
Packit 96c956
{
Packit 96c956
  static char line[2048];
Packit 96c956
  static const char *prompt = "chronyc> ";
Packit 96c956
Packit 96c956
  if (on_terminal) {
Packit 96c956
#ifdef FEAT_READLINE
Packit 96c956
    char *cmd;
Packit 96c956
Packit 96c956
    rl_attempted_completion_function = command_name_completion;
Packit 96c956
    rl_basic_word_break_characters = " \t\n\r";
Packit 96c956
Packit 96c956
    /* save line only if not empty */
Packit 96c956
    cmd = readline(prompt);
Packit 96c956
    if( cmd == NULL ) return( NULL );
Packit 96c956
    
Packit 96c956
    /* user pressed return */
Packit 96c956
    if( *cmd != '\0' ) {
Packit 96c956
      strncpy(line, cmd, sizeof(line) - 1);
Packit 96c956
      line[sizeof(line) - 1] = '\0';
Packit 96c956
      add_history(cmd);
Packit 96c956
      /* free the buffer allocated by readline */
Packit 96c956
      Free(cmd);
Packit 96c956
    } else {
Packit 96c956
      /* simulate the user has entered an empty line */
Packit 96c956
      *line = '\0';
Packit 96c956
    }
Packit 96c956
    return( line );
Packit 96c956
#else
Packit 96c956
    printf("%s", prompt);
Packit 96c956
    fflush(stdout);
Packit 96c956
#endif
Packit 96c956
  }
Packit 96c956
  if (fgets(line, sizeof(line), stdin)) {
Packit 96c956
    return line;
Packit 96c956
  } else {
Packit 96c956
    return NULL;
Packit 96c956
  }
Packit 96c956
  
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static ARR_Instance
Packit 96c956
get_sockaddrs(const char *hostnames, int port)
Packit 96c956
{
Packit 96c956
  ARR_Instance addrs;
Packit 96c956
  char *hostname, *s1, *s2;
Packit 96c956
  IPAddr ip_addrs[DNS_MAX_ADDRESSES];
Packit 96c956
  union sockaddr_all *addr;
Packit 96c956
  int i;
Packit 96c956
Packit 96c956
  addrs = ARR_CreateInstance(sizeof (union sockaddr_all));
Packit 96c956
  s1 = Strdup(hostnames);
Packit 96c956
Packit 96c956
  /* Parse the comma-separated list of hostnames */
Packit 96c956
  for (hostname = s1; hostname && *hostname; hostname = s2) {
Packit 96c956
    s2 = strchr(hostname, ',');
Packit 96c956
    if (s2)
Packit 96c956
      *s2++ = '\0';
Packit 96c956
Packit 96c956
    /* hostname starting with / is considered a path of Unix domain socket */
Packit 96c956
    if (hostname[0] == '/') {
Packit 96c956
      addr = (union sockaddr_all *)ARR_GetNewElement(addrs);
Packit 96c956
      if (snprintf(addr->un.sun_path, sizeof (addr->un.sun_path), "%s", hostname) >=
Packit 96c956
          sizeof (addr->un.sun_path))
Packit 96c956
        LOG_FATAL("Unix socket path too long");
Packit 96c956
      addr->un.sun_family = AF_UNIX;
Packit 96c956
    } else {
Packit 96c956
      if (DNS_Name2IPAddress(hostname, ip_addrs, DNS_MAX_ADDRESSES) != DNS_Success) {
Packit 96c956
        DEBUG_LOG("Could not get IP address for %s", hostname);
Packit 96c956
        continue;
Packit 96c956
      }
Packit 96c956
Packit 96c956
      for (i = 0; i < DNS_MAX_ADDRESSES && ip_addrs[i].family != IPADDR_UNSPEC; i++) {
Packit 96c956
        addr = (union sockaddr_all *)ARR_GetNewElement(addrs);
Packit 96c956
        UTI_IPAndPortToSockaddr(&ip_addrs[i], port, (struct sockaddr *)addr);
Packit 96c956
        DEBUG_LOG("Resolved %s to %s", hostname, UTI_IPToString(&ip_addrs[i]));
Packit 96c956
      }
Packit 96c956
    }
Packit 96c956
  }
Packit 96c956
Packit 96c956
  Free(s1);
Packit 96c956
  return addrs;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
/* Initialise the socket used to talk to the daemon */
Packit 96c956
Packit 96c956
static int
Packit 96c956
prepare_socket(union sockaddr_all *addr)
Packit 96c956
{
Packit 96c956
  socklen_t addr_len;
Packit 96c956
  char *dir;
Packit 96c956
Packit 96c956
  switch (addr->sa.sa_family) {
Packit 96c956
    case AF_UNIX:
Packit 96c956
      addr_len = sizeof (addr->un);
Packit 96c956
      break;
Packit 96c956
    case AF_INET:
Packit 96c956
      addr_len = sizeof (addr->in4);
Packit 96c956
      break;
Packit 96c956
#ifdef FEAT_IPV6
Packit 96c956
    case AF_INET6:
Packit 96c956
      addr_len = sizeof (addr->in6);
Packit 96c956
      break;
Packit 96c956
#endif
Packit 96c956
    default:
Packit 96c956
      assert(0);
Packit 96c956
  }
Packit 96c956
Packit 96c956
  sock_fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0);
Packit 96c956
Packit 96c956
  if (sock_fd < 0) {
Packit 96c956
    DEBUG_LOG("Could not create socket : %s", strerror(errno));
Packit 96c956
    return 0;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  if (addr->sa.sa_family == AF_UNIX) {
Packit 96c956
    struct sockaddr_un sa_un;
Packit 96c956
Packit 96c956
    /* Construct path of our socket.  Use the same directory as the server
Packit 96c956
       socket and include our process ID to allow multiple chronyc instances
Packit 96c956
       running at the same time. */
Packit 96c956
    dir = UTI_PathToDir(addr->un.sun_path);
Packit 96c956
    if (snprintf(sa_un.sun_path, sizeof (sa_un.sun_path),
Packit 96c956
                 "%s/chronyc.%d.sock", dir, (int)getpid()) >= sizeof (sa_un.sun_path))
Packit 96c956
      LOG_FATAL("Unix socket path too long");
Packit 96c956
    Free(dir);
Packit 96c956
Packit 96c956
    sa_un.sun_family = AF_UNIX;
Packit 96c956
    unlink(sa_un.sun_path);
Packit 96c956
Packit 96c956
    /* Bind the socket to the path */
Packit 96c956
    if (bind(sock_fd, (struct sockaddr *)&sa_un, sizeof (sa_un)) < 0) {
Packit 96c956
      DEBUG_LOG("Could not bind socket : %s", strerror(errno));
Packit 96c956
      return 0;
Packit 96c956
    }
Packit 96c956
Packit 96c956
    /* Allow server without root privileges to send replies to our socket */
Packit 96c956
    if (chmod(sa_un.sun_path, 0666) < 0) {
Packit 96c956
      DEBUG_LOG("Could not change socket permissions : %s", strerror(errno));
Packit 96c956
      return 0;
Packit 96c956
    }
Packit 96c956
  }
Packit 96c956
Packit 96c956
  if (connect(sock_fd, &addr->sa, addr_len) < 0) {
Packit 96c956
    DEBUG_LOG("Could not connect socket : %s", strerror(errno));
Packit 96c956
    return 0;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  return 1;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
close_io(void)
Packit 96c956
{
Packit 96c956
  union sockaddr_all addr;
Packit 96c956
  socklen_t addr_len = sizeof (addr);
Packit 96c956
Packit 96c956
  if (sock_fd < 0)
Packit 96c956
    return;
Packit 96c956
Packit 96c956
  /* Remove our Unix domain socket */
Packit 96c956
  if (getsockname(sock_fd, &addr.sa, &addr_len) < 0)
Packit 96c956
    LOG_FATAL("getsockname() failed : %s", strerror(errno));
Packit 96c956
  if (addr_len <= sizeof (addr) && addr_len > sizeof (addr.sa.sa_family) &&
Packit 96c956
      addr.sa.sa_family == AF_UNIX)
Packit 96c956
    unlink(addr.un.sun_path);
Packit 96c956
Packit 96c956
  close(sock_fd);
Packit 96c956
  sock_fd = -1;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
open_io(void)
Packit 96c956
{
Packit 96c956
  static unsigned int address_index = 0;
Packit 96c956
  union sockaddr_all *addr;
Packit 96c956
Packit 96c956
  /* If a socket is already opened, close it and try the next address */
Packit 96c956
  if (sock_fd >= 0) {
Packit 96c956
    close_io();
Packit 96c956
    address_index++;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  /* Find an address for which a socket can be opened and connected */
Packit 96c956
  for (; address_index < ARR_GetSize(sockaddrs); address_index++) {
Packit 96c956
    addr = (union sockaddr_all *)ARR_GetElement(sockaddrs, address_index);
Packit 96c956
    DEBUG_LOG("Opening connection to %s", UTI_SockaddrToString(&addr->sa));
Packit 96c956
Packit 96c956
    if (prepare_socket(addr))
Packit 96c956
      return 1;
Packit 96c956
Packit 96c956
    close_io();
Packit 96c956
  }
Packit 96c956
Packit 96c956
  return 0;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
bits_to_mask(int bits, int family, IPAddr *mask)
Packit 96c956
{
Packit 96c956
  int i;
Packit 96c956
Packit 96c956
  mask->family = family;
Packit 96c956
  switch (family) {
Packit 96c956
    case IPADDR_INET4:
Packit 96c956
      if (bits > 32 || bits < 0)
Packit 96c956
        bits = 32;
Packit 96c956
      if (bits > 0) {
Packit 96c956
        mask->addr.in4 = -1;
Packit 96c956
        mask->addr.in4 <<= 32 - bits;
Packit 96c956
      } else {
Packit 96c956
        mask->addr.in4 = 0;
Packit 96c956
      }
Packit 96c956
      break;
Packit 96c956
    case IPADDR_INET6:
Packit 96c956
      if (bits > 128 || bits < 0)
Packit 96c956
        bits = 128;
Packit 96c956
      for (i = 0; i < bits / 8; i++)
Packit 96c956
        mask->addr.in6[i] = 0xff;
Packit 96c956
      if (i < 16)
Packit 96c956
        mask->addr.in6[i++] = (0xff << (8 - bits % 8)) & 0xff;
Packit 96c956
      for (; i < 16; i++)
Packit 96c956
        mask->addr.in6[i] = 0x0;
Packit 96c956
      break;
Packit 96c956
    default:
Packit 96c956
      assert(0);
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
read_mask_address(char *line, IPAddr *mask, IPAddr *address)
Packit 96c956
{
Packit 96c956
  unsigned int bits;
Packit 96c956
  char *p, *q;
Packit 96c956
Packit 96c956
  p = line;
Packit 96c956
  if (!*p) {
Packit 96c956
    mask->family = address->family = IPADDR_UNSPEC;
Packit 96c956
    return 1;
Packit 96c956
  } else {
Packit 96c956
    q = strchr(p, '/');
Packit 96c956
    if (q) {
Packit 96c956
      *q++ = 0;
Packit 96c956
      if (UTI_StringToIP(p, mask)) {
Packit 96c956
        p = q;
Packit 96c956
        if (UTI_StringToIP(p, address)) {
Packit 96c956
          if (address->family == mask->family)
Packit 96c956
            return 1;
Packit 96c956
        } else if (sscanf(p, "%u", &bits) == 1) {
Packit 96c956
          *address = *mask;
Packit 96c956
          bits_to_mask(bits, address->family, mask);
Packit 96c956
          return 1;
Packit 96c956
        }
Packit 96c956
      }
Packit 96c956
    } else {
Packit 96c956
      if (DNS_Name2IPAddress(p, address, 1) == DNS_Success) {
Packit 96c956
        bits_to_mask(-1, address->family, mask);
Packit 96c956
        return 1;
Packit 96c956
      } else {
Packit 96c956
        LOG(LOGS_ERR, "Could not get address for hostname");
Packit 96c956
        return 0;
Packit 96c956
      }
Packit 96c956
    }
Packit 96c956
  }
Packit 96c956
Packit 96c956
  LOG(LOGS_ERR, "Invalid syntax for mask/address");
Packit 96c956
  return 0;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_offline(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  IPAddr mask, address;
Packit 96c956
  int ok;
Packit 96c956
Packit 96c956
  if (read_mask_address(line, &mask, &address)) {
Packit 96c956
    UTI_IPHostToNetwork(&mask, &msg->data.offline.mask);
Packit 96c956
    UTI_IPHostToNetwork(&address, &msg->data.offline.address);
Packit 96c956
    msg->command = htons(REQ_OFFLINE);
Packit 96c956
    ok = 1;
Packit 96c956
  } else {
Packit 96c956
    ok = 0;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  return ok;
Packit 96c956
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_online(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  IPAddr mask, address;
Packit 96c956
  int ok;
Packit 96c956
Packit 96c956
  if (read_mask_address(line, &mask, &address)) {
Packit 96c956
    UTI_IPHostToNetwork(&mask, &msg->data.online.mask);
Packit 96c956
    UTI_IPHostToNetwork(&address, &msg->data.online.address);
Packit 96c956
    msg->command = htons(REQ_ONLINE);
Packit 96c956
    ok = 1;
Packit 96c956
  } else {
Packit 96c956
    ok = 0;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  return ok;
Packit 96c956
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
process_cmd_onoffline(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  msg->command = htons(REQ_ONOFFLINE);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
read_address_integer(char *line, IPAddr *address, int *value)
Packit 96c956
{
Packit 96c956
  char *hostname;
Packit 96c956
  int ok = 0;
Packit 96c956
Packit 96c956
  hostname = line;
Packit 96c956
  line = CPS_SplitWord(line);
Packit 96c956
Packit 96c956
  if (sscanf(line, "%d", value) != 1) {
Packit 96c956
    LOG(LOGS_ERR, "Invalid syntax for address value");
Packit 96c956
    ok = 0;
Packit 96c956
  } else {
Packit 96c956
    if (DNS_Name2IPAddress(hostname, address, 1) != DNS_Success) {
Packit 96c956
      LOG(LOGS_ERR, "Could not get address for hostname");
Packit 96c956
      ok = 0;
Packit 96c956
    } else {
Packit 96c956
      ok = 1;
Packit 96c956
    }
Packit 96c956
  }
Packit 96c956
Packit 96c956
  return ok;
Packit 96c956
Packit 96c956
}
Packit 96c956
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
read_address_double(char *line, IPAddr *address, double *value)
Packit 96c956
{
Packit 96c956
  char *hostname;
Packit 96c956
  int ok = 0;
Packit 96c956
Packit 96c956
  hostname = line;
Packit 96c956
  line = CPS_SplitWord(line);
Packit 96c956
Packit 96c956
  if (sscanf(line, "%lf", value) != 1) {
Packit 96c956
    LOG(LOGS_ERR, "Invalid syntax for address value");
Packit 96c956
    ok = 0;
Packit 96c956
  } else {
Packit 96c956
    if (DNS_Name2IPAddress(hostname, address, 1) != DNS_Success) {
Packit 96c956
      LOG(LOGS_ERR, "Could not get address for hostname");
Packit 96c956
      ok = 0;
Packit 96c956
    } else {
Packit 96c956
      ok = 1;
Packit 96c956
    }
Packit 96c956
  }
Packit 96c956
Packit 96c956
  return ok;
Packit 96c956
Packit 96c956
}
Packit 96c956
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_minpoll(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  IPAddr address;
Packit 96c956
  int minpoll;
Packit 96c956
  int ok;
Packit 96c956
  
Packit 96c956
  if (read_address_integer(line, &address, &minpoll)) {
Packit 96c956
    UTI_IPHostToNetwork(&address, &msg->data.modify_minpoll.address);
Packit 96c956
    msg->data.modify_minpoll.new_minpoll = htonl(minpoll);
Packit 96c956
    msg->command = htons(REQ_MODIFY_MINPOLL);
Packit 96c956
    ok = 1;
Packit 96c956
  } else {
Packit 96c956
    ok = 0;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  return ok;
Packit 96c956
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_maxpoll(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  IPAddr address;
Packit 96c956
  int maxpoll;
Packit 96c956
  int ok;
Packit 96c956
  
Packit 96c956
  if (read_address_integer(line, &address, &maxpoll)) {
Packit 96c956
    UTI_IPHostToNetwork(&address, &msg->data.modify_maxpoll.address);
Packit 96c956
    msg->data.modify_maxpoll.new_maxpoll = htonl(maxpoll);
Packit 96c956
    msg->command = htons(REQ_MODIFY_MAXPOLL);
Packit 96c956
    ok = 1;
Packit 96c956
  } else {
Packit 96c956
    ok = 0;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  return ok;
Packit 96c956
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_maxdelay(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  IPAddr address;
Packit 96c956
  double max_delay;
Packit 96c956
  int ok;
Packit 96c956
  
Packit 96c956
  if (read_address_double(line, &address, &max_delay)) {
Packit 96c956
    UTI_IPHostToNetwork(&address, &msg->data.modify_maxdelay.address);
Packit 96c956
    msg->data.modify_maxdelay.new_max_delay = UTI_FloatHostToNetwork(max_delay);
Packit 96c956
    msg->command = htons(REQ_MODIFY_MAXDELAY);
Packit 96c956
    ok = 1;
Packit 96c956
  } else {
Packit 96c956
    ok = 0;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  return ok;
Packit 96c956
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_maxdelaydevratio(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  IPAddr address;
Packit 96c956
  double max_delay_dev_ratio;
Packit 96c956
  int ok;
Packit 96c956
  
Packit 96c956
  if (read_address_double(line, &address, &max_delay_dev_ratio)) {
Packit 96c956
    UTI_IPHostToNetwork(&address, &msg->data.modify_maxdelaydevratio.address);
Packit 96c956
    msg->data.modify_maxdelayratio.new_max_delay_ratio = UTI_FloatHostToNetwork(max_delay_dev_ratio);
Packit 96c956
    msg->command = htons(REQ_MODIFY_MAXDELAYDEVRATIO);
Packit 96c956
    ok = 1;
Packit 96c956
  } else {
Packit 96c956
    ok = 0;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  return ok;
Packit 96c956
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_maxdelayratio(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  IPAddr address;
Packit 96c956
  double max_delay_ratio;
Packit 96c956
  int ok;
Packit 96c956
  
Packit 96c956
  if (read_address_double(line, &address, &max_delay_ratio)) {
Packit 96c956
    UTI_IPHostToNetwork(&address, &msg->data.modify_maxdelayratio.address);
Packit 96c956
    msg->data.modify_maxdelayratio.new_max_delay_ratio = UTI_FloatHostToNetwork(max_delay_ratio);
Packit 96c956
    msg->command = htons(REQ_MODIFY_MAXDELAYRATIO);
Packit 96c956
    ok = 1;
Packit 96c956
  } else {
Packit 96c956
    ok = 0;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  return ok;
Packit 96c956
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_minstratum(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  IPAddr address;
Packit 96c956
  int min_stratum;
Packit 96c956
  int ok;
Packit 96c956
  
Packit 96c956
  if (read_address_integer(line, &address, &min_stratum)) {
Packit 96c956
    UTI_IPHostToNetwork(&address, &msg->data.modify_minstratum.address);
Packit 96c956
    msg->data.modify_minstratum.new_min_stratum = htonl(min_stratum);
Packit 96c956
    msg->command = htons(REQ_MODIFY_MINSTRATUM);
Packit 96c956
    ok = 1;
Packit 96c956
  } else {
Packit 96c956
    ok = 0;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  return ok;
Packit 96c956
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_polltarget(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  IPAddr address;
Packit 96c956
  int poll_target;
Packit 96c956
  int ok;
Packit 96c956
  
Packit 96c956
  if (read_address_integer(line, &address, &poll_target)) {
Packit 96c956
    UTI_IPHostToNetwork(&address, &msg->data.modify_polltarget.address);
Packit 96c956
    msg->data.modify_polltarget.new_poll_target = htonl(poll_target);
Packit 96c956
    msg->command = htons(REQ_MODIFY_POLLTARGET);
Packit 96c956
    ok = 1;
Packit 96c956
  } else {
Packit 96c956
    ok = 0;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  return ok;
Packit 96c956
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_maxupdateskew(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  int ok;
Packit 96c956
  double new_max_update_skew;
Packit 96c956
  
Packit 96c956
  if (sscanf(line, "%lf", &new_max_update_skew) == 1) {
Packit 96c956
    msg->data.modify_maxupdateskew.new_max_update_skew = UTI_FloatHostToNetwork(new_max_update_skew);
Packit 96c956
    msg->command = htons(REQ_MODIFY_MAXUPDATESKEW);
Packit 96c956
    ok = 1;
Packit 96c956
  } else {
Packit 96c956
    ok = 0;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  return ok;
Packit 96c956
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
process_cmd_dump(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  msg->command = htons(REQ_DUMP);
Packit 96c956
  msg->data.dump.pad = htonl(0);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
process_cmd_writertc(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  msg->command = htons(REQ_WRITERTC);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
process_cmd_trimrtc(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  msg->command = htons(REQ_TRIMRTC);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
process_cmd_cyclelogs(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  msg->command = htons(REQ_CYCLELOGS);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_burst(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  int n_good_samples, n_total_samples;
Packit 96c956
  char *s1, *s2;
Packit 96c956
  IPAddr address, mask;
Packit 96c956
Packit 96c956
  s1 = line;
Packit 96c956
  s2 = CPS_SplitWord(s1);
Packit 96c956
  CPS_SplitWord(s2);
Packit 96c956
Packit 96c956
  if (sscanf(s1, "%d/%d", &n_good_samples, &n_total_samples) != 2) {
Packit 96c956
    LOG(LOGS_ERR, "Invalid syntax for burst command");
Packit 96c956
    return 0;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  mask.family = address.family = IPADDR_UNSPEC;
Packit 96c956
  if (*s2 && !read_mask_address(s2, &mask, &address)) {
Packit 96c956
    return 0;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  msg->command = htons(REQ_BURST);
Packit 96c956
  msg->data.burst.n_good_samples = ntohl(n_good_samples);
Packit 96c956
  msg->data.burst.n_total_samples = ntohl(n_total_samples);
Packit 96c956
Packit 96c956
  UTI_IPHostToNetwork(&mask, &msg->data.burst.mask);
Packit 96c956
  UTI_IPHostToNetwork(&address, &msg->data.burst.address);
Packit 96c956
Packit 96c956
  return 1;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_local(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  int on_off, stratum = 0, orphan = 0;
Packit 96c956
  double distance = 0.0;
Packit 96c956
Packit 96c956
  if (!strcmp(line, "off")) {
Packit 96c956
    on_off = 0;
Packit 96c956
  } else if (CPS_ParseLocal(line, &stratum, &orphan, &distance)) {
Packit 96c956
    on_off = 1;
Packit 96c956
  } else {
Packit 96c956
    LOG(LOGS_ERR, "Invalid syntax for local command");
Packit 96c956
    return 0;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  msg->command = htons(REQ_LOCAL2);
Packit 96c956
  msg->data.local.on_off = htonl(on_off);
Packit 96c956
  msg->data.local.stratum = htonl(stratum);
Packit 96c956
  msg->data.local.distance = UTI_FloatHostToNetwork(distance);
Packit 96c956
  msg->data.local.orphan = htonl(orphan);
Packit 96c956
Packit 96c956
  return 1;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_manual(CMD_Request *msg, const char *line)
Packit 96c956
{
Packit 96c956
  const char *p;
Packit 96c956
Packit 96c956
  p = line;
Packit 96c956
Packit 96c956
  if (!strcmp(p, "off")) {
Packit 96c956
    msg->data.manual.option = htonl(0);
Packit 96c956
  } else if (!strcmp(p, "on")) {
Packit 96c956
    msg->data.manual.option = htonl(1);
Packit 96c956
  } else if (!strcmp(p, "reset")) {
Packit 96c956
    msg->data.manual.option = htonl(2);
Packit 96c956
  } else {
Packit 96c956
    LOG(LOGS_ERR, "Invalid syntax for manual command");
Packit 96c956
    return 0;
Packit 96c956
  }
Packit 96c956
  msg->command = htons(REQ_MANUAL);
Packit 96c956
Packit 96c956
  return 1;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
parse_allow_deny(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  unsigned long a, b, c, d;
Packit 96c956
  int n, specified_subnet_bits;
Packit 96c956
  IPAddr ip;
Packit 96c956
  char *p;
Packit 96c956
  
Packit 96c956
  p = line;
Packit 96c956
  if (!*p) {
Packit 96c956
    /* blank line - applies to all addresses */
Packit 96c956
    ip.family = IPADDR_UNSPEC;
Packit 96c956
    UTI_IPHostToNetwork(&ip, &msg->data.allow_deny.ip);
Packit 96c956
    msg->data.allow_deny.subnet_bits = htonl(0);
Packit 96c956
  } else {
Packit 96c956
    char *slashpos;
Packit 96c956
    slashpos = strchr(p, '/');
Packit 96c956
    if (slashpos) *slashpos = 0;
Packit 96c956
    
Packit 96c956
    n = 0;
Packit 96c956
    if (!UTI_StringToIP(p, &ip) &&
Packit 96c956
        (n = sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d)) <= 0) {
Packit 96c956
Packit 96c956
      /* Try to parse as the name of a machine */
Packit 96c956
      if (slashpos || DNS_Name2IPAddress(p, &ip, 1) != DNS_Success) {
Packit 96c956
        LOG(LOGS_ERR, "Could not read address");
Packit 96c956
        return 0;
Packit 96c956
      } else {
Packit 96c956
        UTI_IPHostToNetwork(&ip, &msg->data.allow_deny.ip);
Packit 96c956
        if (ip.family == IPADDR_INET6)
Packit 96c956
          msg->data.allow_deny.subnet_bits = htonl(128);
Packit 96c956
        else
Packit 96c956
          msg->data.allow_deny.subnet_bits = htonl(32);
Packit 96c956
      }        
Packit 96c956
    } else {
Packit 96c956
      
Packit 96c956
      if (n == 0) {
Packit 96c956
        if (ip.family == IPADDR_INET6)
Packit 96c956
          msg->data.allow_deny.subnet_bits = htonl(128);
Packit 96c956
        else
Packit 96c956
          msg->data.allow_deny.subnet_bits = htonl(32);
Packit 96c956
      } else {
Packit 96c956
        ip.family = IPADDR_INET4;
Packit 96c956
Packit 96c956
        a &= 0xff;
Packit 96c956
        b &= 0xff;
Packit 96c956
        c &= 0xff;
Packit 96c956
        d &= 0xff;
Packit 96c956
        
Packit 96c956
        switch (n) {
Packit 96c956
          case 1:
Packit 96c956
            ip.addr.in4 = htonl((a<<24));
Packit 96c956
            msg->data.allow_deny.subnet_bits = htonl(8);
Packit 96c956
            break;
Packit 96c956
          case 2:
Packit 96c956
            ip.addr.in4 = htonl((a<<24) | (b<<16));
Packit 96c956
            msg->data.allow_deny.subnet_bits = htonl(16);
Packit 96c956
            break;
Packit 96c956
          case 3:
Packit 96c956
            ip.addr.in4 = htonl((a<<24) | (b<<16) | (c<<8));
Packit 96c956
            msg->data.allow_deny.subnet_bits = htonl(24);
Packit 96c956
            break;
Packit 96c956
          case 4:
Packit 96c956
            ip.addr.in4 = htonl((a<<24) | (b<<16) | (c<<8) | d);
Packit 96c956
            msg->data.allow_deny.subnet_bits = htonl(32);
Packit 96c956
            break;
Packit 96c956
          default:
Packit 96c956
            assert(0);
Packit 96c956
        }
Packit 96c956
      }
Packit 96c956
Packit 96c956
      UTI_IPHostToNetwork(&ip, &msg->data.allow_deny.ip);
Packit 96c956
Packit 96c956
      if (slashpos) {
Packit 96c956
        n = sscanf(slashpos+1, "%d", &specified_subnet_bits);
Packit 96c956
        if (n == 1) {
Packit 96c956
          msg->data.allow_deny.subnet_bits = htonl(specified_subnet_bits);
Packit 96c956
        } else {
Packit 96c956
          LOG(LOGS_WARN, "Warning: badly formatted subnet size, using %d",
Packit 96c956
              (int)ntohl(msg->data.allow_deny.subnet_bits));
Packit 96c956
        }
Packit 96c956
      } 
Packit 96c956
    }
Packit 96c956
  }
Packit 96c956
  return 1;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_allow(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  int status;
Packit 96c956
  msg->command = htons(REQ_ALLOW);
Packit 96c956
  status = parse_allow_deny(msg, line);
Packit 96c956
  return status;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_allowall(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  int status;
Packit 96c956
  msg->command = htons(REQ_ALLOWALL);
Packit 96c956
  status = parse_allow_deny(msg, line);
Packit 96c956
  return status;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_deny(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  int status;
Packit 96c956
  msg->command = htons(REQ_DENY);
Packit 96c956
  status = parse_allow_deny(msg, line);
Packit 96c956
  return status;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_denyall(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  int status;
Packit 96c956
  msg->command = htons(REQ_DENYALL);
Packit 96c956
  status = parse_allow_deny(msg, line);
Packit 96c956
  return status;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_cmdallow(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  int status;
Packit 96c956
  msg->command = htons(REQ_CMDALLOW);
Packit 96c956
  status = parse_allow_deny(msg, line);
Packit 96c956
  return status;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_cmdallowall(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  int status;
Packit 96c956
  msg->command = htons(REQ_CMDALLOWALL);
Packit 96c956
  status = parse_allow_deny(msg, line);
Packit 96c956
  return status;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_cmddeny(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  int status;
Packit 96c956
  msg->command = htons(REQ_CMDDENY);
Packit 96c956
  status = parse_allow_deny(msg, line);
Packit 96c956
  return status;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_cmddenyall(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  int status;
Packit 96c956
  msg->command = htons(REQ_CMDDENYALL);
Packit 96c956
  status = parse_allow_deny(msg, line);
Packit 96c956
  return status;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
accheck_getaddr(char *line, IPAddr *addr)
Packit 96c956
{
Packit 96c956
  unsigned long a, b, c, d;
Packit 96c956
  IPAddr ip;
Packit 96c956
  char *p;
Packit 96c956
  p = line;
Packit 96c956
  if (!*p) {
Packit 96c956
    return 0;
Packit 96c956
  } else {
Packit 96c956
    if (sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d) == 4) {
Packit 96c956
      addr->family = IPADDR_INET4;
Packit 96c956
      addr->addr.in4 = (a<<24) | (b<<16) | (c<<8) | d;
Packit 96c956
      return 1;
Packit 96c956
    } else {
Packit 96c956
      if (DNS_Name2IPAddress(p, &ip, 1) != DNS_Success) {
Packit 96c956
        return 0;
Packit 96c956
      } else {
Packit 96c956
        *addr = ip;
Packit 96c956
        return 1;
Packit 96c956
      }
Packit 96c956
    }
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_accheck(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  IPAddr ip;
Packit 96c956
  msg->command = htons(REQ_ACCHECK);
Packit 96c956
  if (accheck_getaddr(line, &ip)) {
Packit 96c956
    UTI_IPHostToNetwork(&ip, &msg->data.ac_check.ip);
Packit 96c956
    return 1;
Packit 96c956
  } else {    
Packit 96c956
    LOG(LOGS_ERR, "Could not read address");
Packit 96c956
    return 0;
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_cmdaccheck(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  IPAddr ip;
Packit 96c956
  msg->command = htons(REQ_CMDACCHECK);
Packit 96c956
  if (accheck_getaddr(line, &ip)) {
Packit 96c956
    UTI_IPHostToNetwork(&ip, &msg->data.ac_check.ip);
Packit 96c956
    return 1;
Packit 96c956
  } else {    
Packit 96c956
    LOG(LOGS_ERR, "Could not read address");
Packit 96c956
    return 0;
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
process_cmd_dfreq(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  double dfreq;
Packit 96c956
  msg->command = htons(REQ_DFREQ);
Packit 96c956
  if (sscanf(line, "%lf", &dfreq) == 1) {
Packit 96c956
    msg->data.dfreq.dfreq = UTI_FloatHostToNetwork(dfreq);
Packit 96c956
  } else {
Packit 96c956
    msg->data.dfreq.dfreq = UTI_FloatHostToNetwork(0.0);
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
cvt_to_sec_usec(double x, long *sec, long *usec) {
Packit 96c956
  long s, us;
Packit 96c956
  s = (long) x;
Packit 96c956
  us = (long)(0.5 + 1.0e6 * (x - (double) s));
Packit 96c956
  while (us >= 1000000) {
Packit 96c956
    us -= 1000000;
Packit 96c956
    s += 1;
Packit 96c956
  }
Packit 96c956
  while (us < 0) {
Packit 96c956
    us += 1000000;
Packit 96c956
    s -= 1;
Packit 96c956
  }
Packit 96c956
  
Packit 96c956
  *sec = s;
Packit 96c956
  *usec = us;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
process_cmd_doffset(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  double doffset;
Packit 96c956
  long sec, usec;
Packit 96c956
  msg->command = htons(REQ_DOFFSET);
Packit 96c956
  if (sscanf(line, "%lf", &doffset) == 1) {
Packit 96c956
    cvt_to_sec_usec(doffset, &sec, &usec);
Packit 96c956
    msg->data.doffset.sec = htonl(sec);
Packit 96c956
    msg->data.doffset.usec = htonl(usec);
Packit 96c956
  } else {
Packit 96c956
    msg->data.doffset.sec = htonl(0);
Packit 96c956
    msg->data.doffset.usec = htonl(0);
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_add_server_or_peer(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  CPS_NTP_Source data;
Packit 96c956
  IPAddr ip_addr;
Packit 96c956
  int result = 0, status;
Packit 96c956
  const char *opt_name;
Packit 96c956
  
Packit 96c956
  status = CPS_ParseNTPSourceAdd(line, &data);
Packit 96c956
  switch (status) {
Packit 96c956
    case 0:
Packit 96c956
      LOG(LOGS_ERR, "Invalid syntax for add command");
Packit 96c956
      break;
Packit 96c956
    default:
Packit 96c956
      if (DNS_Name2IPAddress(data.name, &ip_addr, 1) != DNS_Success) {
Packit 96c956
        LOG(LOGS_ERR, "Invalid host/IP address");
Packit 96c956
        break;
Packit 96c956
      }
Packit 96c956
Packit 96c956
      opt_name = NULL;
Packit 96c956
      if (opt_name) {
Packit 96c956
        LOG(LOGS_ERR, "%s can't be set in chronyc", opt_name);
Packit 96c956
        break;
Packit 96c956
      }
Packit 96c956
Packit 96c956
      msg->data.ntp_source.port = htonl((unsigned long) data.port);
Packit 96c956
      UTI_IPHostToNetwork(&ip_addr, &msg->data.ntp_source.ip_addr);
Packit 96c956
      msg->data.ntp_source.minpoll = htonl(data.params.minpoll);
Packit 96c956
      msg->data.ntp_source.maxpoll = htonl(data.params.maxpoll);
Packit 96c956
      msg->data.ntp_source.presend_minpoll = htonl(data.params.presend_minpoll);
Packit 96c956
      msg->data.ntp_source.min_stratum = htonl(data.params.min_stratum);
Packit 96c956
      msg->data.ntp_source.poll_target = htonl(data.params.poll_target);
Packit 96c956
      msg->data.ntp_source.version = htonl(data.params.version);
Packit 96c956
      msg->data.ntp_source.max_sources = htonl(data.params.max_sources);
Packit 96c956
      msg->data.ntp_source.min_samples = htonl(data.params.min_samples);
Packit 96c956
      msg->data.ntp_source.max_samples = htonl(data.params.max_samples);
Packit 96c956
      msg->data.ntp_source.authkey = htonl(data.params.authkey);
Packit 96c956
      msg->data.ntp_source.max_delay = UTI_FloatHostToNetwork(data.params.max_delay);
Packit 96c956
      msg->data.ntp_source.max_delay_ratio = UTI_FloatHostToNetwork(data.params.max_delay_ratio);
Packit 96c956
      msg->data.ntp_source.max_delay_dev_ratio =
Packit 96c956
        UTI_FloatHostToNetwork(data.params.max_delay_dev_ratio);
Packit 96c956
      msg->data.ntp_source.min_delay = UTI_FloatHostToNetwork(data.params.min_delay);
Packit 96c956
      msg->data.ntp_source.asymmetry = UTI_FloatHostToNetwork(data.params.asymmetry);
Packit 96c956
      msg->data.ntp_source.offset = UTI_FloatHostToNetwork(data.params.offset);
Packit 96c956
      msg->data.ntp_source.flags = htonl(
Packit 96c956
          (data.params.connectivity == SRC_ONLINE ? REQ_ADDSRC_ONLINE : 0) |
Packit 96c956
          (data.params.auto_offline ? REQ_ADDSRC_AUTOOFFLINE : 0) |
Packit 96c956
          (data.params.iburst ? REQ_ADDSRC_IBURST : 0) |
Packit 96c956
          (data.params.interleaved ? REQ_ADDSRC_INTERLEAVED : 0) |
Packit 96c956
          (data.params.burst ? REQ_ADDSRC_BURST : 0) |
Packit 96c956
          (data.params.sel_options & SRC_SELECT_PREFER ? REQ_ADDSRC_PREFER : 0) |
Packit 96c956
          (data.params.sel_options & SRC_SELECT_NOSELECT ? REQ_ADDSRC_NOSELECT : 0) |
Packit 96c956
          (data.params.sel_options & SRC_SELECT_TRUST ? REQ_ADDSRC_TRUST : 0) |
Packit 96c956
          (data.params.sel_options & SRC_SELECT_REQUIRE ? REQ_ADDSRC_REQUIRE : 0));
Packit 96c956
      msg->data.ntp_source.filter_length = htonl(data.params.filter_length);
Packit 96c956
      memset(msg->data.ntp_source.reserved, 0, sizeof (msg->data.ntp_source.reserved));
Packit 96c956
Packit 96c956
      result = 1;
Packit 96c956
Packit 96c956
      break;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  return result;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_add_server(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  msg->command = htons(REQ_ADD_SERVER3);
Packit 96c956
  return process_cmd_add_server_or_peer(msg, line);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_add_peer(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  msg->command = htons(REQ_ADD_PEER3);
Packit 96c956
  return process_cmd_add_server_or_peer(msg, line);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_delete(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  char *hostname;
Packit 96c956
  int ok = 0;
Packit 96c956
  IPAddr address;
Packit 96c956
Packit 96c956
  msg->command = htons(REQ_DEL_SOURCE);
Packit 96c956
  hostname = line;
Packit 96c956
  CPS_SplitWord(line);
Packit 96c956
Packit 96c956
  if (!*hostname) {
Packit 96c956
    LOG(LOGS_ERR, "Invalid syntax for address");
Packit 96c956
    ok = 0;
Packit 96c956
  } else {
Packit 96c956
    if (DNS_Name2IPAddress(hostname, &address, 1) != DNS_Success) {
Packit 96c956
      LOG(LOGS_ERR, "Could not get address for hostname");
Packit 96c956
      ok = 0;
Packit 96c956
    } else {
Packit 96c956
      UTI_IPHostToNetwork(&address, &msg->data.del_source.ip_addr);
Packit 96c956
      ok = 1;
Packit 96c956
    }
Packit 96c956
  }
Packit 96c956
Packit 96c956
  return ok;
Packit 96c956
  
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
give_help(void)
Packit 96c956
{
Packit 96c956
  int line, len;
Packit 96c956
  const char *s, cols[] =
Packit 96c956
    "System clock:\0\0"
Packit 96c956
    "tracking\0Display system time information\0"
Packit 96c956
    "makestep\0Correct clock by stepping immediately\0"
Packit 96c956
    "makestep <threshold> <updates>\0Configure automatic clock stepping\0"
Packit 96c956
    "maxupdateskew <skew>\0Modify maximum valid skew to update frequency\0"
Packit 96c956
    "waitsync [<max-tries> [<max-correction> [<max-skew> [<interval>]]]]\0"
Packit 96c956
                          "Wait until synchronised in specified limits\0"
Packit 96c956
    "\0\0"
Packit 96c956
    "Time sources:\0\0"
Packit 96c956
    "sources [-v]\0Display information about current sources\0"
Packit 96c956
    "sourcestats [-v]\0Display statistics about collected measurements\0"
Packit 96c956
    "reselect\0Force reselecting synchronisation source\0"
Packit 96c956
    "reselectdist <dist>\0Modify reselection distance\0"
Packit 96c956
    "\0\0"
Packit 96c956
    "NTP sources:\0\0"
Packit 96c956
    "activity\0Check how many NTP sources are online/offline\0"
Packit 96c956
    "ntpdata [<address>]\0Display information about last valid measurement\0"
Packit 96c956
    "add server <address> [options]\0Add new NTP server\0"
Packit 96c956
    "add peer <address> [options]\0Add new NTP peer\0"
Packit 96c956
    "delete <address>\0Remove server or peer\0"
Packit 96c956
    "burst <n-good>/<n-max> [<mask>/<address>]\0Start rapid set of measurements\0"
Packit 96c956
    "maxdelay <address> <delay>\0Modify maximum valid sample delay\0"
Packit 96c956
    "maxdelayratio <address> <ratio>\0Modify maximum valid delay/minimum ratio\0"
Packit 96c956
    "maxdelaydevratio <address> <ratio>\0Modify maximum valid delay/deviation ratio\0"
Packit 96c956
    "minpoll <address> <poll>\0Modify minimum polling interval\0"
Packit 96c956
    "maxpoll <address> <poll>\0Modify maximum polling interval\0"
Packit 96c956
    "minstratum <address> <stratum>\0Modify minimum stratum\0"
Packit 96c956
    "offline [<mask>/<address>]\0Set sources in subnet to offline status\0"
Packit 96c956
    "online [<mask>/<address>]\0Set sources in subnet to online status\0"
Packit 96c956
    "onoffline\0Set all sources to online or offline status\0"
Packit 96c956
    "\0according to network configuration\0"
Packit 96c956
    "polltarget <address> <target>\0Modify poll target\0"
Packit 96c956
    "refresh\0Refresh IP addresses\0"
Packit 96c956
    "\0\0"
Packit 96c956
    "Manual time input:\0\0"
Packit 96c956
    "manual off|on|reset\0Disable/enable/reset settime command\0"
Packit 96c956
    "manual list\0Show previous settime entries\0"
Packit 96c956
    "manual delete <index>\0Delete previous settime entry\0"
Packit 96c956
    "settime <time>\0Set daemon time\0"
Packit 96c956
    "\0(e.g. Sep 25, 2015 16:30:05 or 16:30:05)\0"
Packit 96c956
    "\0\0NTP access:\0\0"
Packit 96c956
    "accheck <address>\0Check whether address is allowed\0"
Packit 96c956
    "clients\0Report on clients that have accessed the server\0"
Packit 96c956
    "serverstats\0Display statistics of the server\0"
Packit 96c956
    "allow [<subnet>]\0Allow access to subnet as a default\0"
Packit 96c956
    "allow all [<subnet>]\0Allow access to subnet and all children\0"
Packit 96c956
    "deny [<subnet>]\0Deny access to subnet as a default\0"
Packit 96c956
    "deny all [<subnet>]\0Deny access to subnet and all children\0"
Packit 96c956
    "local [options]\0Serve time even when not synchronised\0"
Packit 96c956
    "local off\0Don't serve time when not synchronised\0"
Packit 96c956
    "smoothtime reset|activate\0Reset/activate time smoothing\0"
Packit 96c956
    "smoothing\0Display current time smoothing state\0"
Packit 96c956
    "\0\0"
Packit 96c956
    "Monitoring access:\0\0"
Packit 96c956
    "cmdaccheck <address>\0Check whether address is allowed\0"
Packit 96c956
    "cmdallow [<subnet>]\0Allow access to subnet as a default\0"
Packit 96c956
    "cmdallow all [<subnet>]\0Allow access to subnet and all children\0"
Packit 96c956
    "cmddeny [<subnet>]\0Deny access to subnet as a default\0"
Packit 96c956
    "cmddeny all [<subnet>]\0Deny access to subnet and all children\0"
Packit 96c956
    "\0\0"
Packit 96c956
    "Real-time clock:\0\0"
Packit 96c956
    "rtcdata\0Print current RTC performance parameters\0"
Packit 96c956
    "trimrtc\0Correct RTC relative to system clock\0"
Packit 96c956
    "writertc\0Save RTC performance parameters to file\0"
Packit 96c956
    "\0\0"
Packit 96c956
    "Other daemon commands:\0\0"
Packit 96c956
    "cyclelogs\0Close and re-open log files\0"
Packit 96c956
    "dump\0Dump all measurements to save files\0"
Packit 96c956
    "rekey\0Re-read keys from key file\0"
Packit 96c956
    "shutdown\0Stop daemon\0"
Packit 96c956
    "\0\0"
Packit 96c956
    "Client commands:\0\0"
Packit 96c956
    "dns -n|+n\0Disable/enable resolving IP addresses to hostnames\0"
Packit 96c956
    "dns -4|-6|-46\0Resolve hostnames only to IPv4/IPv6/both addresses\0"
Packit 96c956
    "timeout <milliseconds>\0Set initial response timeout\0"
Packit 96c956
    "retries <retries>\0Set maximum number of retries\0"
Packit 96c956
    "keygen [<id> [<type> [<bits>]]]\0Generate key for key file\0"
Packit 96c956
    "exit|quit\0Leave the program\0"
Packit 96c956
    "help\0Generate this help\0"
Packit 96c956
    "\0";
Packit 96c956
Packit 96c956
  /* Indent the second column */
Packit 96c956
  for (s = cols, line = 0; s < cols + sizeof (cols); s += len + 1, line++) {
Packit 96c956
    len = strlen(s);
Packit 96c956
    printf(line % 2 == 0 ? (len >= 28 ? "%s\n%28s" : "%-28s%s") : "%s%s\n",
Packit 96c956
           s, "");
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
/* Tab-completion when editline/readline is available */
Packit 96c956
Packit 96c956
#ifdef FEAT_READLINE
Packit 96c956
Packit 96c956
enum {
Packit 96c956
  TAB_COMPLETE_BASE_CMDS,
Packit 96c956
  TAB_COMPLETE_ADD_OPTS,
Packit 96c956
  TAB_COMPLETE_MANUAL_OPTS,
Packit 96c956
  TAB_COMPLETE_SOURCES_OPTS,
Packit 96c956
  TAB_COMPLETE_SOURCESTATS_OPTS,
Packit 96c956
  TAB_COMPLETE_MAX_INDEX
Packit 96c956
};
Packit 96c956
Packit 96c956
static int tab_complete_index;
Packit 96c956
Packit 96c956
static char *
Packit 96c956
command_name_generator(const char *text, int state)
Packit 96c956
{
Packit 96c956
  const char *name, **names[TAB_COMPLETE_MAX_INDEX];
Packit 96c956
  const char *base_commands[] = {
Packit 96c956
    "accheck", "activity", "add", "allow", "burst",
Packit 96c956
    "clients", "cmdaccheck", "cmdallow", "cmddeny", "cyclelogs", "delete",
Packit 96c956
    "deny", "dns", "dump", "exit", "help", "keygen", "local", "makestep",
Packit 96c956
    "manual", "maxdelay", "maxdelaydevratio", "maxdelayratio", "maxpoll",
Packit 96c956
    "maxupdateskew", "minpoll", "minstratum", "ntpdata", "offline", "online", "onoffline",
Packit 96c956
    "polltarget", "quit", "refresh", "rekey", "reselect", "reselectdist",
Packit 96c956
    "retries", "rtcdata", "serverstats", "settime", "shutdown", "smoothing",
Packit 96c956
    "smoothtime", "sources", "sourcestats",
Packit 96c956
    "timeout", "tracking", "trimrtc", "waitsync", "writertc",
Packit 96c956
    NULL
Packit 96c956
  };
Packit 96c956
  const char *add_options[] = { "peer", "server", NULL };
Packit 96c956
  const char *manual_options[] = { "on", "off", "delete", "list", "reset", NULL };
Packit 96c956
  const char *sources_options[] = { "-v", NULL };
Packit 96c956
  const char *sourcestats_options[] = { "-v", NULL };
Packit 96c956
  static int list_index, len;
Packit 96c956
Packit 96c956
  names[TAB_COMPLETE_BASE_CMDS] = base_commands;
Packit 96c956
  names[TAB_COMPLETE_ADD_OPTS] = add_options;
Packit 96c956
  names[TAB_COMPLETE_MANUAL_OPTS] = manual_options;
Packit 96c956
  names[TAB_COMPLETE_SOURCES_OPTS] = sources_options;
Packit 96c956
  names[TAB_COMPLETE_SOURCESTATS_OPTS] = sourcestats_options;
Packit 96c956
Packit 96c956
  if (!state) {
Packit 96c956
    list_index = 0;
Packit 96c956
    len = strlen(text);
Packit 96c956
  }
Packit 96c956
Packit 96c956
  while ((name = names[tab_complete_index][list_index++])) {
Packit 96c956
    if (strncmp(name, text, len) == 0) {
Packit 96c956
      return strdup(name);
Packit 96c956
    }
Packit 96c956
  }
Packit 96c956
Packit 96c956
  return NULL;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static char **
Packit 96c956
command_name_completion(const char *text, int start, int end)
Packit 96c956
{
Packit 96c956
  char first[32];
Packit 96c956
Packit 96c956
  snprintf(first, MIN(sizeof (first), start + 1), "%s", rl_line_buffer);
Packit 96c956
  rl_attempted_completion_over = 1;
Packit 96c956
Packit 96c956
  if (!strcmp(first, "add ")) {
Packit 96c956
    tab_complete_index = TAB_COMPLETE_ADD_OPTS;
Packit 96c956
  } else if (!strcmp(first, "manual ")) {
Packit 96c956
    tab_complete_index = TAB_COMPLETE_MANUAL_OPTS;
Packit 96c956
  } else if (!strcmp(first, "sources ")) {
Packit 96c956
    tab_complete_index = TAB_COMPLETE_SOURCES_OPTS;
Packit 96c956
  } else if (!strcmp(first, "sourcestats ")) {
Packit 96c956
    tab_complete_index = TAB_COMPLETE_SOURCESTATS_OPTS;
Packit 96c956
  } else if (first[0] == '\0') {
Packit 96c956
    tab_complete_index = TAB_COMPLETE_BASE_CMDS;
Packit 96c956
  } else {
Packit 96c956
    return NULL;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  return rl_completion_matches(text, command_name_generator);
Packit 96c956
}
Packit 96c956
#endif
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int max_retries = 2;
Packit 96c956
static int initial_timeout = 1000;
Packit 96c956
static int proto_version = PROTO_VERSION_NUMBER;
Packit 96c956
Packit 96c956
/* This is the core protocol module.  Complete particular fields in
Packit 96c956
   the outgoing packet, send it, wait for a response, handle retries,
Packit 96c956
   etc.  Returns a Boolean indicating whether the protocol was
Packit 96c956
   successful or not.*/
Packit 96c956
Packit 96c956
static int
Packit 96c956
submit_request(CMD_Request *request, CMD_Reply *reply)
Packit 96c956
{
Packit 96c956
  int select_status;
Packit 96c956
  int recv_status;
Packit 96c956
  int read_length;
Packit 96c956
  int command_length;
Packit 96c956
  int padding_length;
Packit 96c956
  struct timespec ts_now, ts_start;
Packit 96c956
  struct timeval tv;
Packit 96c956
  int n_attempts, new_attempt;
Packit 96c956
  double timeout;
Packit 96c956
  fd_set rdfd;
Packit 96c956
Packit 96c956
  request->pkt_type = PKT_TYPE_CMD_REQUEST;
Packit 96c956
  request->res1 = 0;
Packit 96c956
  request->res2 = 0;
Packit 96c956
  request->pad1 = 0;
Packit 96c956
  request->pad2 = 0;
Packit 96c956
Packit 96c956
  n_attempts = 0;
Packit 96c956
  new_attempt = 1;
Packit 96c956
Packit 96c956
  do {
Packit 96c956
    if (gettimeofday(&tv, NULL))
Packit 96c956
      return 0;
Packit 96c956
Packit 96c956
    if (new_attempt) {
Packit 96c956
      new_attempt = 0;
Packit 96c956
Packit 96c956
      if (n_attempts > max_retries)
Packit 96c956
        return 0;
Packit 96c956
Packit 96c956
      UTI_TimevalToTimespec(&tv, &ts_start);
Packit 96c956
Packit 96c956
      UTI_GetRandomBytes(&request->sequence, sizeof (request->sequence));
Packit 96c956
      request->attempt = htons(n_attempts);
Packit 96c956
      request->version = proto_version;
Packit 96c956
      command_length = PKL_CommandLength(request);
Packit 96c956
      padding_length = PKL_CommandPaddingLength(request);
Packit 96c956
      assert(command_length > 0 && command_length > padding_length);
Packit 96c956
Packit 96c956
      n_attempts++;
Packit 96c956
Packit 96c956
      /* Zero the padding to not send any uninitialized data */
Packit 96c956
      memset(((char *)request) + command_length - padding_length, 0, padding_length);
Packit 96c956
Packit 96c956
      if (sock_fd < 0) {
Packit 96c956
        DEBUG_LOG("No socket to send request");
Packit 96c956
        return 0;
Packit 96c956
      }
Packit 96c956
Packit 96c956
      if (send(sock_fd, (void *)request, command_length, 0) < 0) {
Packit 96c956
        DEBUG_LOG("Could not send %d bytes : %s", command_length, strerror(errno));
Packit 96c956
        return 0;
Packit 96c956
      }
Packit 96c956
Packit 96c956
      DEBUG_LOG("Sent %d bytes", command_length);
Packit 96c956
    }
Packit 96c956
Packit 96c956
    UTI_TimevalToTimespec(&tv, &ts_now);
Packit 96c956
Packit 96c956
    /* Check if the clock wasn't stepped back */
Packit 96c956
    if (UTI_CompareTimespecs(&ts_now, &ts_start) < 0)
Packit 96c956
      ts_start = ts_now;
Packit 96c956
Packit 96c956
    timeout = initial_timeout / 1000.0 * (1U << (n_attempts - 1)) -
Packit 96c956
              UTI_DiffTimespecsToDouble(&ts_now, &ts_start);
Packit 96c956
    DEBUG_LOG("Timeout %f seconds", timeout);
Packit 96c956
Packit 96c956
    /* Avoid calling select() with an invalid timeout */
Packit 96c956
    if (timeout <= 0.0) {
Packit 96c956
      new_attempt = 1;
Packit 96c956
      continue;
Packit 96c956
    }
Packit 96c956
Packit 96c956
    UTI_DoubleToTimeval(timeout, &tv;;
Packit 96c956
Packit 96c956
    FD_ZERO(&rdfd);
Packit 96c956
    FD_SET(sock_fd, &rdfd);
Packit 96c956
Packit 96c956
    if (quit)
Packit 96c956
      return 0;
Packit 96c956
Packit 96c956
    select_status = select(sock_fd + 1, &rdfd, NULL, NULL, &tv;;
Packit 96c956
Packit 96c956
    if (select_status < 0) {
Packit 96c956
      DEBUG_LOG("select failed : %s", strerror(errno));
Packit 96c956
      return 0;
Packit 96c956
    } else if (select_status == 0) {
Packit 96c956
      /* Timeout must have elapsed, try a resend? */
Packit 96c956
      new_attempt = 1;
Packit 96c956
    } else {
Packit 96c956
      recv_status = recv(sock_fd, (void *)reply, sizeof(CMD_Reply), 0);
Packit 96c956
      
Packit 96c956
      if (recv_status < 0) {
Packit 96c956
        /* If we get connrefused here, it suggests the sendto is
Packit 96c956
           going to a dead port */
Packit 96c956
        DEBUG_LOG("Could not receive : %s", strerror(errno));
Packit 96c956
        new_attempt = 1;
Packit 96c956
      } else {
Packit 96c956
        DEBUG_LOG("Received %d bytes", recv_status);
Packit 96c956
        
Packit 96c956
        read_length = recv_status;
Packit 96c956
        
Packit 96c956
        /* Check if the header is valid */
Packit 96c956
        if (read_length < offsetof(CMD_Reply, data) ||
Packit 96c956
            (reply->version != proto_version &&
Packit 96c956
             !(reply->version >= PROTO_VERSION_MISMATCH_COMPAT_CLIENT &&
Packit 96c956
               ntohs(reply->status) == STT_BADPKTVERSION)) ||
Packit 96c956
            reply->pkt_type != PKT_TYPE_CMD_REPLY ||
Packit 96c956
            reply->res1 != 0 ||
Packit 96c956
            reply->res2 != 0 ||
Packit 96c956
            reply->command != request->command ||
Packit 96c956
            reply->sequence != request->sequence) {
Packit 96c956
          DEBUG_LOG("Invalid reply");
Packit 96c956
          continue;
Packit 96c956
        }
Packit 96c956
        
Packit 96c956
#if PROTO_VERSION_NUMBER == 6
Packit 96c956
        /* Protocol version 5 is similar to 6 except there is no padding.
Packit 96c956
           If a version 5 reply with STT_BADPKTVERSION is received,
Packit 96c956
           switch our version and try again. */
Packit 96c956
        if (proto_version == PROTO_VERSION_NUMBER &&
Packit 96c956
            reply->version == PROTO_VERSION_NUMBER - 1) {
Packit 96c956
          proto_version = PROTO_VERSION_NUMBER - 1;
Packit 96c956
          n_attempts--;
Packit 96c956
          new_attempt = 1;
Packit 96c956
          continue;
Packit 96c956
        }
Packit 96c956
#else
Packit 96c956
#error unknown compatibility with PROTO_VERSION - 1
Packit 96c956
#endif
Packit 96c956
Packit 96c956
        /* Check that the packet contains all data it is supposed to have.
Packit 96c956
           Unknown responses will always pass this test as their expected
Packit 96c956
           length is zero. */
Packit 96c956
        if (read_length < PKL_ReplyLength(reply)) {
Packit 96c956
          DEBUG_LOG("Reply too short");
Packit 96c956
          new_attempt = 1;
Packit 96c956
          continue;
Packit 96c956
        }
Packit 96c956
Packit 96c956
        /* Good packet received, print out results */
Packit 96c956
        DEBUG_LOG("Reply cmd=%d reply=%d stat=%d",
Packit 96c956
                  ntohs(reply->command), ntohs(reply->reply), ntohs(reply->status));
Packit 96c956
        break;
Packit 96c956
      }
Packit 96c956
    }
Packit 96c956
  } while (1);
Packit 96c956
Packit 96c956
  return 1;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
request_reply(CMD_Request *request, CMD_Reply *reply, int requested_reply, int verbose)
Packit 96c956
{
Packit 96c956
  int status;
Packit 96c956
Packit 96c956
  while (!submit_request(request, reply)) {
Packit 96c956
    /* Try connecting to other addresses before giving up */
Packit 96c956
    if (open_io())
Packit 96c956
      continue;
Packit 96c956
    printf("506 Cannot talk to daemon\n");
Packit 96c956
    return 0;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  status = ntohs(reply->status);
Packit 96c956
        
Packit 96c956
  if (verbose || status != STT_SUCCESS) {
Packit 96c956
    switch (status) {
Packit 96c956
      case STT_SUCCESS:
Packit 96c956
        printf("200 OK");
Packit 96c956
        break;
Packit 96c956
      case STT_ACCESSALLOWED:
Packit 96c956
        printf("208 Access allowed");
Packit 96c956
        break;
Packit 96c956
      case STT_ACCESSDENIED:
Packit 96c956
        printf("209 Access denied");
Packit 96c956
        break;
Packit 96c956
      case STT_FAILED:
Packit 96c956
        printf("500 Failure");
Packit 96c956
        break;
Packit 96c956
      case STT_UNAUTH:
Packit 96c956
        printf("501 Not authorised");
Packit 96c956
        break;
Packit 96c956
      case STT_INVALID:
Packit 96c956
        printf("502 Invalid command");
Packit 96c956
        break;
Packit 96c956
      case STT_NOSUCHSOURCE:
Packit 96c956
        printf("503 No such source");
Packit 96c956
        break;
Packit 96c956
      case STT_INVALIDTS:
Packit 96c956
        printf("504 Duplicate or stale logon detected");
Packit 96c956
        break;
Packit 96c956
      case STT_NOTENABLED:
Packit 96c956
        printf("505 Facility not enabled in daemon");
Packit 96c956
        break;
Packit 96c956
      case STT_BADSUBNET:
Packit 96c956
        printf("507 Bad subnet");
Packit 96c956
        break;
Packit 96c956
      case STT_NOHOSTACCESS:
Packit 96c956
        printf("510 No command access from this host");
Packit 96c956
        break;
Packit 96c956
      case STT_SOURCEALREADYKNOWN:
Packit 96c956
        printf("511 Source already present");
Packit 96c956
        break;
Packit 96c956
      case STT_TOOMANYSOURCES:
Packit 96c956
        printf("512 Too many sources present");
Packit 96c956
        break;
Packit 96c956
      case STT_NORTC:
Packit 96c956
        printf("513 RTC driver not running");
Packit 96c956
        break;
Packit 96c956
      case STT_BADRTCFILE:
Packit 96c956
        printf("514 Can't write RTC parameters");
Packit 96c956
        break;
Packit 96c956
      case STT_INVALIDAF:
Packit 96c956
        printf("515 Invalid address family");
Packit 96c956
        break;
Packit 96c956
      case STT_BADSAMPLE:
Packit 96c956
        printf("516 Sample index out of range");
Packit 96c956
        break;
Packit 96c956
      case STT_BADPKTVERSION:
Packit 96c956
        printf("517 Protocol version mismatch");
Packit 96c956
        break;
Packit 96c956
      case STT_BADPKTLENGTH:
Packit 96c956
        printf("518 Packet length mismatch");
Packit 96c956
        break;
Packit 96c956
      case STT_INACTIVE:
Packit 96c956
        printf("519 Client logging is not active in the daemon");
Packit 96c956
        break;
Packit 96c956
      default:
Packit 96c956
        printf("520 Got unexpected error from daemon");
Packit 96c956
    }
Packit 96c956
    printf("\n");
Packit 96c956
  }
Packit 96c956
  
Packit 96c956
  if (status != STT_SUCCESS &&
Packit 96c956
      status != STT_ACCESSALLOWED && status != STT_ACCESSDENIED) {
Packit 96c956
    return 0;
Packit 96c956
  } 
Packit 96c956
Packit 96c956
  if (ntohs(reply->reply) != requested_reply) {
Packit 96c956
    printf("508 Bad reply from daemon\n");
Packit 96c956
    return 0;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  /* Make sure an unknown response was not requested */
Packit 96c956
  assert(PKL_ReplyLength(reply));
Packit 96c956
Packit 96c956
  return 1;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
print_seconds(unsigned long s)
Packit 96c956
{
Packit 96c956
  unsigned long d;
Packit 96c956
Packit 96c956
  if (s == (uint32_t)-1) {
Packit 96c956
    printf("   -");
Packit 96c956
  } else if (s < 1200) {
Packit 96c956
    printf("%4lu", s);
Packit 96c956
  } else if (s < 36000) {
Packit 96c956
    printf("%3lum", s / 60);
Packit 96c956
  } else if (s < 345600) {
Packit 96c956
    printf("%3luh", s / 3600);
Packit 96c956
  } else {
Packit 96c956
    d = s / 86400;
Packit 96c956
    if (d > 999) {
Packit 96c956
      printf("%3luy", d / 365);
Packit 96c956
    } else {
Packit 96c956
      printf("%3lud", d);
Packit 96c956
    }
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
print_nanoseconds(double s)
Packit 96c956
{
Packit 96c956
  s = fabs(s);
Packit 96c956
Packit 96c956
  if (s < 9999.5e-9) {
Packit 96c956
    printf("%4.0fns", s * 1e9);
Packit 96c956
  } else if (s < 9999.5e-6) {
Packit 96c956
    printf("%4.0fus", s * 1e6);
Packit 96c956
  } else if (s < 9999.5e-3) {
Packit 96c956
    printf("%4.0fms", s * 1e3);
Packit 96c956
  } else if (s < 999.5) {
Packit 96c956
    printf("%5.1fs", s);
Packit 96c956
  } else if (s < 99999.5) {
Packit 96c956
    printf("%5.0fs", s);
Packit 96c956
  } else if (s < 99999.5 * 60) {
Packit 96c956
    printf("%5.0fm", s / 60);
Packit 96c956
  } else if (s < 99999.5 * 3600) {
Packit 96c956
    printf("%5.0fh", s / 3600);
Packit 96c956
  } else if (s < 99999.5 * 3600 * 24) {
Packit 96c956
    printf("%5.0fd", s / (3600 * 24));
Packit 96c956
  } else {
Packit 96c956
    printf("%5.0fy", s / (3600 * 24 * 365));
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
print_signed_nanoseconds(double s)
Packit 96c956
{
Packit 96c956
  double x;
Packit 96c956
Packit 96c956
  x = fabs(s);
Packit 96c956
Packit 96c956
  if (x < 9999.5e-9) {
Packit 96c956
    printf("%+5.0fns", s * 1e9);
Packit 96c956
  } else if (x < 9999.5e-6) {
Packit 96c956
    printf("%+5.0fus", s * 1e6);
Packit 96c956
  } else if (x < 9999.5e-3) {
Packit 96c956
    printf("%+5.0fms", s * 1e3);
Packit 96c956
  } else if (x < 999.5) {
Packit 96c956
    printf("%+6.1fs", s);
Packit 96c956
  } else if (x < 99999.5) {
Packit 96c956
    printf("%+6.0fs", s);
Packit 96c956
  } else if (x < 99999.5 * 60) {
Packit 96c956
    printf("%+6.0fm", s / 60);
Packit 96c956
  } else if (x < 99999.5 * 3600) {
Packit 96c956
    printf("%+6.0fh", s / 3600);
Packit 96c956
  } else if (x < 99999.5 * 3600 * 24) {
Packit 96c956
    printf("%+6.0fd", s / (3600 * 24));
Packit 96c956
  } else {
Packit 96c956
    printf("%+6.0fy", s / (3600 * 24 * 365));
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
print_freq_ppm(double f)
Packit 96c956
{
Packit 96c956
  if (fabs(f) < 99999.5) {
Packit 96c956
    printf("%10.3f", f);
Packit 96c956
  } else {
Packit 96c956
    printf("%10.0f", f);
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
print_signed_freq_ppm(double f)
Packit 96c956
{
Packit 96c956
  if (fabs(f) < 99999.5) {
Packit 96c956
    printf("%+10.3f", f);
Packit 96c956
  } else {
Packit 96c956
    printf("%+10.0f", f);
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
print_clientlog_interval(int rate)
Packit 96c956
{
Packit 96c956
  if (rate >= 127) {
Packit 96c956
    printf(" -");
Packit 96c956
  } else {
Packit 96c956
    printf("%2d", rate);
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
print_header(const char *header)
Packit 96c956
{
Packit 96c956
  int len;
Packit 96c956
Packit 96c956
  if (csv_mode)
Packit 96c956
    return;
Packit 96c956
Packit 96c956
  printf("%s\n", header);
Packit 96c956
Packit 96c956
  len = strlen(header);
Packit 96c956
  while (len--)
Packit 96c956
    printf("=");
Packit 96c956
  printf("\n");
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
#define REPORT_END 0x1234
Packit 96c956
Packit 96c956
/* Print a report. The syntax of the format is similar to printf(), but not all
Packit 96c956
   specifiers are supported and some are different! */
Packit 96c956
Packit 96c956
static void
Packit 96c956
print_report(const char *format, ...)
Packit 96c956
{
Packit 96c956
  char buf[256];
Packit 96c956
  va_list ap;
Packit 96c956
  int i, field, sign, width, prec, spec;
Packit 96c956
  const char *string;
Packit 96c956
  unsigned long long_uinteger;
Packit 96c956
  unsigned int uinteger;
Packit 96c956
  int integer;
Packit 96c956
  struct timespec *ts;
Packit 96c956
  struct tm *tm;
Packit 96c956
  double dbl;
Packit 96c956
Packit 96c956
  va_start(ap, format);
Packit 96c956
Packit 96c956
  for (field = 0; ; field++) {
Packit 96c956
    /* Search for text between format specifiers and print it
Packit 96c956
       if not in the CSV mode */
Packit 96c956
    for (i = 0; i < sizeof (buf) && format[i] != '%' && format[i] != '\0'; i++)
Packit 96c956
      buf[i] = format[i];
Packit 96c956
Packit 96c956
    if (i >= sizeof (buf))
Packit 96c956
      break;
Packit 96c956
Packit 96c956
    buf[i] = '\0';
Packit 96c956
Packit 96c956
    if (!csv_mode)
Packit 96c956
      printf("%s", buf);
Packit 96c956
Packit 96c956
    if (format[i] == '\0' || format[i + 1] == '\0')
Packit 96c956
      break;
Packit 96c956
Packit 96c956
    format += i + 1;
Packit 96c956
Packit 96c956
    sign = 0;
Packit 96c956
    width = 0;
Packit 96c956
    prec = 5;
Packit 96c956
Packit 96c956
    if (*format == '+' || *format == '-') {
Packit 96c956
      sign = 1;
Packit 96c956
      format++;
Packit 96c956
    }
Packit 96c956
Packit 96c956
    if (isdigit((unsigned char)*format)) {
Packit 96c956
      width = atoi(format);
Packit 96c956
      while (isdigit((unsigned char)*format))
Packit 96c956
        format++;
Packit 96c956
    }
Packit 96c956
Packit 96c956
    if (*format == '.') {
Packit 96c956
      format++;
Packit 96c956
      prec = atoi(format);
Packit 96c956
      while (isdigit((unsigned char)*format))
Packit 96c956
        format++;
Packit 96c956
    }
Packit 96c956
Packit 96c956
    spec = *format;
Packit 96c956
    format++;
Packit 96c956
Packit 96c956
    /* Disable human-readable formatting in the CSV mode */
Packit 96c956
    if (csv_mode) {
Packit 96c956
      sign = width = 0;
Packit 96c956
Packit 96c956
      if (field > 0)
Packit 96c956
        printf(",");
Packit 96c956
Packit 96c956
      switch (spec) {
Packit 96c956
        case 'C':
Packit 96c956
          spec = 'd';
Packit 96c956
          break;
Packit 96c956
        case 'F':
Packit 96c956
        case 'P':
Packit 96c956
          prec = 3;
Packit 96c956
          spec = 'f';
Packit 96c956
          break;
Packit 96c956
        case 'O':
Packit 96c956
        case 'S':
Packit 96c956
          prec = 9;
Packit 96c956
          spec = 'f';
Packit 96c956
          break;
Packit 96c956
        case 'I':
Packit 96c956
          spec = 'U';
Packit 96c956
          break;
Packit 96c956
        case 'T':
Packit 96c956
          spec = 'V';
Packit 96c956
          break;
Packit 96c956
      }
Packit 96c956
    }
Packit 96c956
Packit 96c956
    switch (spec) {
Packit 96c956
      case 'B': /* boolean */
Packit 96c956
        integer = va_arg(ap, int);
Packit 96c956
        printf("%s", integer ? "Yes" : "No");
Packit 96c956
        break;
Packit 96c956
      case 'C': /* clientlog interval */
Packit 96c956
        integer = va_arg(ap, int);
Packit 96c956
        print_clientlog_interval(integer);
Packit 96c956
        break;
Packit 96c956
      case 'F': /* absolute frequency in ppm with fast/slow keyword */
Packit 96c956
      case 'O': /* absolute offset in seconds with fast/slow keyword */
Packit 96c956
        dbl = va_arg(ap, double);
Packit 96c956
        printf("%*.*f %s %s", width, prec, fabs(dbl),
Packit 96c956
               spec == 'O' ? "seconds" : "ppm",
Packit 96c956
               (dbl > 0.0) ^ (spec != 'O') ? "slow" : "fast");
Packit 96c956
        break;
Packit 96c956
      case 'I': /* interval with unit */
Packit 96c956
        long_uinteger = va_arg(ap, unsigned long);
Packit 96c956
        print_seconds(long_uinteger);
Packit 96c956
        break;
Packit 96c956
      case 'L': /* leap status */
Packit 96c956
        integer = va_arg(ap, int);
Packit 96c956
        switch (integer) {
Packit 96c956
          case LEAP_Normal:
Packit 96c956
            string = "Normal";
Packit 96c956
            break;
Packit 96c956
          case LEAP_InsertSecond:
Packit 96c956
            string = "Insert second";
Packit 96c956
            break;
Packit 96c956
          case LEAP_DeleteSecond:
Packit 96c956
            string = "Delete second";
Packit 96c956
            break;
Packit 96c956
          case LEAP_Unsynchronised:
Packit 96c956
            string = "Not synchronised";
Packit 96c956
            break;
Packit 96c956
          default:
Packit 96c956
            string = "Invalid";
Packit 96c956
            break;
Packit 96c956
        }
Packit 96c956
        printf("%s", string);
Packit 96c956
        break;
Packit 96c956
      case 'M': /* NTP mode */
Packit 96c956
        integer = va_arg(ap, int);
Packit 96c956
        switch (integer) {
Packit 96c956
          case MODE_ACTIVE:
Packit 96c956
            string = "Symmetric active";
Packit 96c956
            break;
Packit 96c956
          case MODE_PASSIVE:
Packit 96c956
            string = "Symmetric passive";
Packit 96c956
            break;
Packit 96c956
          case MODE_SERVER:
Packit 96c956
            string = "Server";
Packit 96c956
            break;
Packit 96c956
          default:
Packit 96c956
            string = "Invalid";
Packit 96c956
            break;
Packit 96c956
        }
Packit 96c956
        printf("%s", string);
Packit 96c956
        break;
Packit 96c956
      case 'N': /* Timestamp source */
Packit 96c956
        integer = va_arg(ap, int);
Packit 96c956
        switch (integer) {
Packit 96c956
          case 'D':
Packit 96c956
            string = "Daemon";
Packit 96c956
            break;
Packit 96c956
          case 'K':
Packit 96c956
            string = "Kernel";
Packit 96c956
            break;
Packit 96c956
          case 'H':
Packit 96c956
            string = "Hardware";
Packit 96c956
            break;
Packit 96c956
          default:
Packit 96c956
            string = "Invalid";
Packit 96c956
            break;
Packit 96c956
        }
Packit 96c956
        printf("%s", string);
Packit 96c956
        break;
Packit 96c956
      case 'P': /* frequency in ppm */
Packit 96c956
        dbl = va_arg(ap, double);
Packit 96c956
        if (sign)
Packit 96c956
          print_signed_freq_ppm(dbl);
Packit 96c956
        else
Packit 96c956
          print_freq_ppm(dbl);
Packit 96c956
        break;
Packit 96c956
      case 'R': /* reference ID in hexdecimal */
Packit 96c956
        long_uinteger = va_arg(ap, unsigned long);
Packit 96c956
        printf("%08lX", long_uinteger);
Packit 96c956
        break;
Packit 96c956
      case 'S': /* offset with unit */
Packit 96c956
        dbl = va_arg(ap, double);
Packit 96c956
        if (sign)
Packit 96c956
          print_signed_nanoseconds(dbl);
Packit 96c956
        else
Packit 96c956
          print_nanoseconds(dbl);
Packit 96c956
        break;
Packit 96c956
      case 'T': /* timespec as date and time in UTC */
Packit 96c956
        ts = va_arg(ap, struct timespec *);
Packit 96c956
        tm = gmtime(&ts->tv_sec);
Packit 96c956
        if (!tm)
Packit 96c956
          break;
Packit 96c956
        strftime(buf, sizeof (buf), "%a %b %d %T %Y", tm);
Packit 96c956
        printf("%s", buf);
Packit 96c956
        break;
Packit 96c956
      case 'U': /* unsigned long in decimal */
Packit 96c956
        long_uinteger = va_arg(ap, unsigned long);
Packit 96c956
        printf("%*lu", width, long_uinteger);
Packit 96c956
        break;
Packit 96c956
      case 'V': /* timespec as seconds since epoch */
Packit 96c956
        ts = va_arg(ap, struct timespec *);
Packit 96c956
        printf("%s", UTI_TimespecToString(ts));
Packit 96c956
        break;
Packit 96c956
      case 'b': /* unsigned int in binary */
Packit 96c956
        uinteger = va_arg(ap, unsigned int);
Packit 96c956
        for (i = prec - 1; i >= 0; i--)
Packit 96c956
          printf("%c", uinteger & 1U << i ? '1' : '0');
Packit 96c956
        break;
Packit 96c956
Packit 96c956
      /* Classic printf specifiers */
Packit 96c956
      case 'c': /* character */
Packit 96c956
        integer = va_arg(ap, int);
Packit 96c956
        printf("%c", integer);
Packit 96c956
        break;
Packit 96c956
      case 'd': /* signed int in decimal */
Packit 96c956
        integer = va_arg(ap, int);
Packit 96c956
        printf("%*d", width, integer);
Packit 96c956
        break;
Packit 96c956
      case 'f': /* double */
Packit 96c956
        dbl = va_arg(ap, double);
Packit 96c956
        printf(sign ? "%+*.*f" : "%*.*f", width, prec, dbl);
Packit 96c956
        break;
Packit 96c956
      case 'o': /* unsigned int in octal */
Packit 96c956
        uinteger = va_arg(ap, unsigned int);
Packit 96c956
        printf("%*o", width, uinteger);
Packit 96c956
        break;
Packit 96c956
      case 's': /* string */
Packit 96c956
        string = va_arg(ap, const char *);
Packit 96c956
        if (sign)
Packit 96c956
          printf("%-*s", width, string);
Packit 96c956
        else
Packit 96c956
          printf("%*s", width, string);
Packit 96c956
        break;
Packit 96c956
      case 'u': /* unsigned int in decimal */
Packit 96c956
        uinteger = va_arg(ap, unsigned int);
Packit 96c956
        printf("%*u", width, uinteger);
Packit 96c956
        break;
Packit 96c956
    }
Packit 96c956
  }
Packit 96c956
Packit 96c956
  /* Require terminating argument to catch bad type conversions */
Packit 96c956
  if (va_arg(ap, int) != REPORT_END)
Packit 96c956
    assert(0);
Packit 96c956
Packit 96c956
  va_end(ap);
Packit 96c956
Packit 96c956
  if (csv_mode)
Packit 96c956
    printf("\n");
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
print_info_field(const char *format, ...)
Packit 96c956
{
Packit 96c956
  va_list ap;
Packit 96c956
Packit 96c956
  if (csv_mode)
Packit 96c956
    return;
Packit 96c956
Packit 96c956
  va_start(ap, format);
Packit 96c956
  vprintf(format, ap);
Packit 96c956
  va_end(ap);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
format_name(char *buf, int size, int trunc_dns, int ref, uint32_t ref_id,
Packit 96c956
            IPAddr *ip_addr)
Packit 96c956
{
Packit 96c956
  if (ref) {
Packit 96c956
    snprintf(buf, size, "%s", UTI_RefidToString(ref_id));
Packit 96c956
  } else if (no_dns || csv_mode) {
Packit 96c956
    snprintf(buf, size, "%s", UTI_IPToString(ip_addr));
Packit 96c956
  } else {
Packit 96c956
    DNS_IPAddress2Name(ip_addr, buf, size);
Packit 96c956
    if (trunc_dns > 0 && strlen(buf) > trunc_dns) {
Packit 96c956
      buf[trunc_dns - 1] = '>';
Packit 96c956
      buf[trunc_dns] = '\0';
Packit 96c956
    }
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
check_for_verbose_flag(char *line)
Packit 96c956
{
Packit 96c956
  if (!csv_mode && !strcmp(line, "-v"))
Packit 96c956
    return 1;
Packit 96c956
  return 0;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_sources(char *line)
Packit 96c956
{
Packit 96c956
  CMD_Request request;
Packit 96c956
  CMD_Reply reply;
Packit 96c956
  IPAddr ip_addr;
Packit 96c956
  uint32_t i, mode, n_sources;
Packit 96c956
  char name[50], mode_ch, state_ch;
Packit 96c956
  int verbose;
Packit 96c956
Packit 96c956
  /* Check whether to output verbose headers */
Packit 96c956
  verbose = check_for_verbose_flag(line);
Packit 96c956
  
Packit 96c956
  request.command = htons(REQ_N_SOURCES);
Packit 96c956
  if (!request_reply(&request, &reply, RPY_N_SOURCES, 0))
Packit 96c956
    return 0;
Packit 96c956
Packit 96c956
  n_sources = ntohl(reply.data.n_sources.n_sources);
Packit 96c956
  print_info_field("210 Number of sources = %lu\n", (unsigned long)n_sources);
Packit 96c956
Packit 96c956
  if (verbose) {
Packit 96c956
    printf("\n");
Packit 96c956
    printf("  .-- Source mode  '^' = server, '=' = peer, '#' = local clock.\n");
Packit 96c956
    printf(" / .- Source state '*' = current synced, '+' = combined , '-' = not combined,\n");
Packit 96c956
    printf("| /   '?' = unreachable, 'x' = time may be in error, '~' = time too variable.\n");
Packit 96c956
    printf("||                                                 .- xxxx [ yyyy ] +/- zzzz\n");
Packit 96c956
    printf("||      Reachability register (octal) -.           |  xxxx = adjusted offset,\n");
Packit 96c956
    printf("||      Log2(Polling interval) --.      |          |  yyyy = measured offset,\n");
Packit 96c956
    printf("||                                \\     |          |  zzzz = estimated error.\n");
Packit 96c956
    printf("||                                 |    |           \\\n");
Packit 96c956
  }
Packit 96c956
Packit 96c956
  print_header("MS Name/IP address         Stratum Poll Reach LastRx Last sample               ");
Packit 96c956
Packit 96c956
  /*           "MS NNNNNNNNNNNNNNNNNNNNNNNNNNN  SS  PP   RRR  RRRR  SSSSSSS[SSSSSSS] +/- SSSSSS" */
Packit 96c956
Packit 96c956
  for (i = 0; i < n_sources; i++) {
Packit 96c956
    request.command = htons(REQ_SOURCE_DATA);
Packit 96c956
    request.data.source_data.index = htonl(i);
Packit 96c956
    if (!request_reply(&request, &reply, RPY_SOURCE_DATA, 0))
Packit 96c956
      return 0;
Packit 96c956
Packit 96c956
    mode = ntohs(reply.data.source_data.mode);
Packit 96c956
    UTI_IPNetworkToHost(&reply.data.source_data.ip_addr, &ip_addr);
Packit 96c956
    format_name(name, sizeof (name), 25,
Packit 96c956
                mode == RPY_SD_MD_REF && ip_addr.family == IPADDR_INET4,
Packit 96c956
                ip_addr.addr.in4, &ip_addr);
Packit 96c956
Packit 96c956
    switch (mode) {
Packit 96c956
      case RPY_SD_MD_CLIENT:
Packit 96c956
        mode_ch = '^';
Packit 96c956
        break;
Packit 96c956
      case RPY_SD_MD_PEER:
Packit 96c956
        mode_ch = '=';
Packit 96c956
        break;
Packit 96c956
      case RPY_SD_MD_REF:
Packit 96c956
        mode_ch = '#';
Packit 96c956
        break;
Packit 96c956
      default:
Packit 96c956
        mode_ch = ' ';
Packit 96c956
    }
Packit 96c956
Packit 96c956
    switch (ntohs(reply.data.source_data.state)) {
Packit 96c956
      case RPY_SD_ST_SYNC:
Packit 96c956
        state_ch = '*';
Packit 96c956
        break;
Packit 96c956
      case RPY_SD_ST_UNREACH:
Packit 96c956
        state_ch = '?';
Packit 96c956
        break;
Packit 96c956
      case RPY_SD_ST_FALSETICKER:
Packit 96c956
        state_ch = 'x';
Packit 96c956
        break;
Packit 96c956
      case RPY_SD_ST_JITTERY:
Packit 96c956
        state_ch = '~';
Packit 96c956
        break;
Packit 96c956
      case RPY_SD_ST_CANDIDATE:
Packit 96c956
        state_ch = '+';
Packit 96c956
        break;
Packit 96c956
      case RPY_SD_ST_OUTLIER:
Packit 96c956
        state_ch = '-';
Packit 96c956
        break;
Packit 96c956
      default:
Packit 96c956
        state_ch = ' ';
Packit 96c956
    }
Packit 96c956
Packit 96c956
    switch (ntohs(reply.data.source_data.flags)) {
Packit 96c956
      default:
Packit 96c956
        break;
Packit 96c956
    }
Packit 96c956
Packit 96c956
    print_report("%c%c %-27s  %2d  %2d   %3o  %I  %+S[%+S] +/- %S\n",
Packit 96c956
                 mode_ch, state_ch, name,
Packit 96c956
                 ntohs(reply.data.source_data.stratum),
Packit 96c956
                 (int16_t)ntohs(reply.data.source_data.poll),
Packit 96c956
                 ntohs(reply.data.source_data.reachability),
Packit 96c956
                 (unsigned long)ntohl(reply.data.source_data.since_sample),
Packit 96c956
                 UTI_FloatNetworkToHost(reply.data.source_data.latest_meas),
Packit 96c956
                 UTI_FloatNetworkToHost(reply.data.source_data.orig_latest_meas),
Packit 96c956
                 UTI_FloatNetworkToHost(reply.data.source_data.latest_meas_err),
Packit 96c956
                 REPORT_END);
Packit 96c956
  }
Packit 96c956
Packit 96c956
  return 1;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_sourcestats(char *line)
Packit 96c956
{
Packit 96c956
  CMD_Request request;
Packit 96c956
  CMD_Reply reply;
Packit 96c956
  uint32_t i, n_sources;
Packit 96c956
  int verbose = 0;
Packit 96c956
  char name[50];
Packit 96c956
  IPAddr ip_addr;
Packit 96c956
Packit 96c956
  verbose = check_for_verbose_flag(line);
Packit 96c956
Packit 96c956
  request.command = htons(REQ_N_SOURCES);
Packit 96c956
  if (!request_reply(&request, &reply, RPY_N_SOURCES, 0))
Packit 96c956
    return 0;
Packit 96c956
Packit 96c956
  n_sources = ntohl(reply.data.n_sources.n_sources);
Packit 96c956
  print_info_field("210 Number of sources = %lu\n", (unsigned long)n_sources);
Packit 96c956
Packit 96c956
  if (verbose) {
Packit 96c956
    printf("                             .- Number of sample points in measurement set.\n");
Packit 96c956
    printf("                            /    .- Number of residual runs with same sign.\n");
Packit 96c956
    printf("                           |    /    .- Length of measurement set (time).\n");
Packit 96c956
    printf("                           |   |    /      .- Est. clock freq error (ppm).\n");
Packit 96c956
    printf("                           |   |   |      /           .- Est. error in freq.\n");
Packit 96c956
    printf("                           |   |   |     |           /         .- Est. offset.\n");
Packit 96c956
    printf("                           |   |   |     |          |          |   On the -.\n");
Packit 96c956
    printf("                           |   |   |     |          |          |   samples. \\\n");
Packit 96c956
    printf("                           |   |   |     |          |          |             |\n");
Packit 96c956
  }
Packit 96c956
Packit 96c956
  print_header("Name/IP Address            NP  NR  Span  Frequency  Freq Skew  Offset  Std Dev");
Packit 96c956
Packit 96c956
  /*           "NNNNNNNNNNNNNNNNNNNNNNNNN  NP  NR  SSSS FFFFFFFFFF SSSSSSSSSS  SSSSSSS  SSSSSS" */
Packit 96c956
Packit 96c956
  for (i = 0; i < n_sources; i++) {
Packit 96c956
    request.command = htons(REQ_SOURCESTATS);
Packit 96c956
    request.data.source_data.index = htonl(i);
Packit 96c956
    if (!request_reply(&request, &reply, RPY_SOURCESTATS, 0))
Packit 96c956
      return 0;
Packit 96c956
Packit 96c956
    UTI_IPNetworkToHost(&reply.data.sourcestats.ip_addr, &ip_addr);
Packit 96c956
    format_name(name, sizeof (name), 25, ip_addr.family == IPADDR_UNSPEC,
Packit 96c956
                ntohl(reply.data.sourcestats.ref_id), &ip_addr);
Packit 96c956
Packit 96c956
    print_report("%-25s %3U %3U  %I %+P %P  %+S  %S\n",
Packit 96c956
                 name,
Packit 96c956
                 (unsigned long)ntohl(reply.data.sourcestats.n_samples),
Packit 96c956
                 (unsigned long)ntohl(reply.data.sourcestats.n_runs),
Packit 96c956
                 (unsigned long)ntohl(reply.data.sourcestats.span_seconds),
Packit 96c956
                 UTI_FloatNetworkToHost(reply.data.sourcestats.resid_freq_ppm),
Packit 96c956
                 UTI_FloatNetworkToHost(reply.data.sourcestats.skew_ppm),
Packit 96c956
                 UTI_FloatNetworkToHost(reply.data.sourcestats.est_offset),
Packit 96c956
                 UTI_FloatNetworkToHost(reply.data.sourcestats.sd),
Packit 96c956
                 REPORT_END);
Packit 96c956
  }
Packit 96c956
Packit 96c956
  return 1;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_tracking(char *line)
Packit 96c956
{
Packit 96c956
  CMD_Request request;
Packit 96c956
  CMD_Reply reply;
Packit 96c956
  IPAddr ip_addr;
Packit 96c956
  uint32_t ref_id;
Packit 96c956
  char name[50];
Packit 96c956
  struct timespec ref_time;
Packit 96c956
  
Packit 96c956
  request.command = htons(REQ_TRACKING);
Packit 96c956
  if (!request_reply(&request, &reply, RPY_TRACKING, 0))
Packit 96c956
    return 0;
Packit 96c956
Packit 96c956
  ref_id = ntohl(reply.data.tracking.ref_id);
Packit 96c956
Packit 96c956
  UTI_IPNetworkToHost(&reply.data.tracking.ip_addr, &ip_addr);
Packit 96c956
  format_name(name, sizeof (name), sizeof (name),
Packit 96c956
              ip_addr.family == IPADDR_UNSPEC, ref_id, &ip_addr);
Packit 96c956
Packit 96c956
  UTI_TimespecNetworkToHost(&reply.data.tracking.ref_time, &ref_time);
Packit 96c956
Packit 96c956
  print_report("Reference ID    : %R (%s)\n"
Packit 96c956
               "Stratum         : %u\n"
Packit 96c956
               "Ref time (UTC)  : %T\n"
Packit 96c956
               "System time     : %.9O of NTP time\n"
Packit 96c956
               "Last offset     : %+.9f seconds\n"
Packit 96c956
               "RMS offset      : %.9f seconds\n"
Packit 96c956
               "Frequency       : %.3F\n"
Packit 96c956
               "Residual freq   : %+.3f ppm\n"
Packit 96c956
               "Skew            : %.3f ppm\n"
Packit 96c956
               "Root delay      : %.9f seconds\n"
Packit 96c956
               "Root dispersion : %.9f seconds\n"
Packit 96c956
               "Update interval : %.1f seconds\n"
Packit 96c956
               "Leap status     : %L\n",
Packit 96c956
               (unsigned long)ref_id, name,
Packit 96c956
               ntohs(reply.data.tracking.stratum),
Packit 96c956
               &ref_time,
Packit 96c956
               UTI_FloatNetworkToHost(reply.data.tracking.current_correction),
Packit 96c956
               UTI_FloatNetworkToHost(reply.data.tracking.last_offset),
Packit 96c956
               UTI_FloatNetworkToHost(reply.data.tracking.rms_offset),
Packit 96c956
               UTI_FloatNetworkToHost(reply.data.tracking.freq_ppm),
Packit 96c956
               UTI_FloatNetworkToHost(reply.data.tracking.resid_freq_ppm),
Packit 96c956
               UTI_FloatNetworkToHost(reply.data.tracking.skew_ppm),
Packit 96c956
               UTI_FloatNetworkToHost(reply.data.tracking.root_delay),
Packit 96c956
               UTI_FloatNetworkToHost(reply.data.tracking.root_dispersion),
Packit 96c956
               UTI_FloatNetworkToHost(reply.data.tracking.last_update_interval),
Packit 96c956
               ntohs(reply.data.tracking.leap_status), REPORT_END);
Packit 96c956
Packit 96c956
  return 1;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_ntpdata(char *line)
Packit 96c956
{
Packit 96c956
  CMD_Request request;
Packit 96c956
  CMD_Reply reply;
Packit 96c956
  IPAddr remote_addr, local_addr;
Packit 96c956
  struct timespec ref_time;
Packit 96c956
  uint32_t i, n_sources;
Packit 96c956
  uint16_t mode;
Packit 96c956
  int specified_addr;
Packit 96c956
Packit 96c956
  if (*line) {
Packit 96c956
    specified_addr = 1;
Packit 96c956
    n_sources = 1;
Packit 96c956
  } else {
Packit 96c956
    specified_addr = 0;
Packit 96c956
    request.command = htons(REQ_N_SOURCES);
Packit 96c956
    if (!request_reply(&request, &reply, RPY_N_SOURCES, 0))
Packit 96c956
      return 0;
Packit 96c956
    n_sources = ntohl(reply.data.n_sources.n_sources);
Packit 96c956
  }
Packit 96c956
Packit 96c956
  for (i = 0; i < n_sources; i++) {
Packit 96c956
    if (specified_addr) {
Packit 96c956
      if (DNS_Name2IPAddress(line, &remote_addr, 1) != DNS_Success) {
Packit 96c956
        LOG(LOGS_ERR, "Could not get address for hostname");
Packit 96c956
        return 0;
Packit 96c956
      }
Packit 96c956
    } else {
Packit 96c956
      request.command = htons(REQ_SOURCE_DATA);
Packit 96c956
      request.data.source_data.index = htonl(i);
Packit 96c956
      if (!request_reply(&request, &reply, RPY_SOURCE_DATA, 0))
Packit 96c956
        return 0;
Packit 96c956
Packit 96c956
      mode = ntohs(reply.data.source_data.mode);
Packit 96c956
      if (mode != RPY_SD_MD_CLIENT && mode != RPY_SD_MD_PEER)
Packit 96c956
        continue;
Packit 96c956
Packit 96c956
      UTI_IPNetworkToHost(&reply.data.source_data.ip_addr, &remote_addr);
Packit 96c956
    }
Packit 96c956
Packit 96c956
    request.command = htons(REQ_NTP_DATA);
Packit 96c956
    UTI_IPHostToNetwork(&remote_addr, &request.data.ntp_data.ip_addr);
Packit 96c956
    if (!request_reply(&request, &reply, RPY_NTP_DATA, 0))
Packit 96c956
      return 0;
Packit 96c956
Packit 96c956
    UTI_IPNetworkToHost(&reply.data.ntp_data.remote_addr, &remote_addr);
Packit 96c956
    UTI_IPNetworkToHost(&reply.data.ntp_data.local_addr, &local_addr);
Packit 96c956
    UTI_TimespecNetworkToHost(&reply.data.ntp_data.ref_time, &ref_time);
Packit 96c956
Packit 96c956
    if (!specified_addr && !csv_mode)
Packit 96c956
      printf("\n");
Packit 96c956
Packit 96c956
    print_report("Remote address  : %s (%R)\n"
Packit 96c956
                 "Remote port     : %u\n"
Packit 96c956
                 "Local address   : %s (%R)\n"
Packit 96c956
                 "Leap status     : %L\n"
Packit 96c956
                 "Version         : %u\n"
Packit 96c956
                 "Mode            : %M\n"
Packit 96c956
                 "Stratum         : %u\n"
Packit 96c956
                 "Poll interval   : %d (%.0f seconds)\n"
Packit 96c956
                 "Precision       : %d (%.9f seconds)\n"
Packit 96c956
                 "Root delay      : %.6f seconds\n"
Packit 96c956
                 "Root dispersion : %.6f seconds\n"
Packit 96c956
                 "Reference ID    : %R (%s)\n"
Packit 96c956
                 "Reference time  : %T\n"
Packit 96c956
                 "Offset          : %+.9f seconds\n"
Packit 96c956
                 "Peer delay      : %.9f seconds\n"
Packit 96c956
                 "Peer dispersion : %.9f seconds\n"
Packit 96c956
                 "Response time   : %.9f seconds\n"
Packit 96c956
                 "Jitter asymmetry: %+.2f\n"
Packit 96c956
                 "NTP tests       : %.3b %.3b %.4b\n"
Packit 96c956
                 "Interleaved     : %B\n"
Packit 96c956
                 "Authenticated   : %B\n"
Packit 96c956
                 "TX timestamping : %N\n"
Packit 96c956
                 "RX timestamping : %N\n"
Packit 96c956
                 "Total TX        : %U\n"
Packit 96c956
                 "Total RX        : %U\n"
Packit 96c956
                 "Total valid RX  : %U\n",
Packit 96c956
                 UTI_IPToString(&remote_addr), (unsigned long)UTI_IPToRefid(&remote_addr),
Packit 96c956
                 ntohs(reply.data.ntp_data.remote_port),
Packit 96c956
                 UTI_IPToString(&local_addr), (unsigned long)UTI_IPToRefid(&local_addr),
Packit 96c956
                 reply.data.ntp_data.leap, reply.data.ntp_data.version,
Packit 96c956
                 reply.data.ntp_data.mode, reply.data.ntp_data.stratum,
Packit 96c956
                 reply.data.ntp_data.poll, UTI_Log2ToDouble(reply.data.ntp_data.poll),
Packit 96c956
                 reply.data.ntp_data.precision, UTI_Log2ToDouble(reply.data.ntp_data.precision),
Packit 96c956
                 UTI_FloatNetworkToHost(reply.data.ntp_data.root_delay),
Packit 96c956
                 UTI_FloatNetworkToHost(reply.data.ntp_data.root_dispersion),
Packit 96c956
                 (unsigned long)ntohl(reply.data.ntp_data.ref_id),
Packit 96c956
                 reply.data.ntp_data.stratum <= 1 ?
Packit 96c956
                   UTI_RefidToString(ntohl(reply.data.ntp_data.ref_id)) : "",
Packit 96c956
                 &ref_time,
Packit 96c956
                 UTI_FloatNetworkToHost(reply.data.ntp_data.offset),
Packit 96c956
                 UTI_FloatNetworkToHost(reply.data.ntp_data.peer_delay),
Packit 96c956
                 UTI_FloatNetworkToHost(reply.data.ntp_data.peer_dispersion),
Packit 96c956
                 UTI_FloatNetworkToHost(reply.data.ntp_data.response_time),
Packit 96c956
                 UTI_FloatNetworkToHost(reply.data.ntp_data.jitter_asymmetry),
Packit 96c956
                 ntohs(reply.data.ntp_data.flags) >> 7,
Packit 96c956
                 ntohs(reply.data.ntp_data.flags) >> 4,
Packit 96c956
                 ntohs(reply.data.ntp_data.flags),
Packit 96c956
                 ntohs(reply.data.ntp_data.flags) & RPY_NTP_FLAG_INTERLEAVED,
Packit 96c956
                 ntohs(reply.data.ntp_data.flags) & RPY_NTP_FLAG_AUTHENTICATED,
Packit 96c956
                 reply.data.ntp_data.tx_tss_char, reply.data.ntp_data.rx_tss_char,
Packit 96c956
                 (unsigned long)ntohl(reply.data.ntp_data.total_tx_count),
Packit 96c956
                 (unsigned long)ntohl(reply.data.ntp_data.total_rx_count),
Packit 96c956
                 (unsigned long)ntohl(reply.data.ntp_data.total_valid_count),
Packit 96c956
                 REPORT_END);
Packit 96c956
  }
Packit 96c956
Packit 96c956
  return 1;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_serverstats(char *line)
Packit 96c956
{
Packit 96c956
  CMD_Request request;
Packit 96c956
  CMD_Reply reply;
Packit 96c956
Packit 96c956
  request.command = htons(REQ_SERVER_STATS);
Packit 96c956
  if (!request_reply(&request, &reply, RPY_SERVER_STATS, 0))
Packit 96c956
    return 0;
Packit 96c956
Packit 96c956
  print_report("NTP packets received       : %U\n"
Packit 96c956
               "NTP packets dropped        : %U\n"
Packit 96c956
               "Command packets received   : %U\n"
Packit 96c956
               "Command packets dropped    : %U\n"
Packit 96c956
               "Client log records dropped : %U\n",
Packit 96c956
               (unsigned long)ntohl(reply.data.server_stats.ntp_hits),
Packit 96c956
               (unsigned long)ntohl(reply.data.server_stats.ntp_drops),
Packit 96c956
               (unsigned long)ntohl(reply.data.server_stats.cmd_hits),
Packit 96c956
               (unsigned long)ntohl(reply.data.server_stats.cmd_drops),
Packit 96c956
               (unsigned long)ntohl(reply.data.server_stats.log_drops),
Packit 96c956
               REPORT_END);
Packit 96c956
Packit 96c956
  return 1;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_smoothing(char *line)
Packit 96c956
{
Packit 96c956
  CMD_Request request;
Packit 96c956
  CMD_Reply reply;
Packit 96c956
  uint32_t flags;
Packit 96c956
Packit 96c956
  request.command = htons(REQ_SMOOTHING);
Packit 96c956
  if (!request_reply(&request, &reply, RPY_SMOOTHING, 0))
Packit 96c956
    return 0;
Packit 96c956
Packit 96c956
  flags = ntohl(reply.data.smoothing.flags);
Packit 96c956
Packit 96c956
  print_report("Active         : %B %s\n"
Packit 96c956
               "Offset         : %+.9f seconds\n"
Packit 96c956
               "Frequency      : %+.6f ppm\n"
Packit 96c956
               "Wander         : %+.6f ppm per second\n"
Packit 96c956
               "Last update    : %.1f seconds ago\n"
Packit 96c956
               "Remaining time : %.1f seconds\n",
Packit 96c956
               !!(flags & RPY_SMT_FLAG_ACTIVE),
Packit 96c956
               flags & RPY_SMT_FLAG_LEAPONLY ? "(leap second only)" : "",
Packit 96c956
               UTI_FloatNetworkToHost(reply.data.smoothing.offset),
Packit 96c956
               UTI_FloatNetworkToHost(reply.data.smoothing.freq_ppm),
Packit 96c956
               UTI_FloatNetworkToHost(reply.data.smoothing.wander_ppm),
Packit 96c956
               UTI_FloatNetworkToHost(reply.data.smoothing.last_update_ago),
Packit 96c956
               UTI_FloatNetworkToHost(reply.data.smoothing.remaining_time),
Packit 96c956
               REPORT_END);
Packit 96c956
Packit 96c956
  return 1;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_smoothtime(CMD_Request *msg, const char *line)
Packit 96c956
{
Packit 96c956
  if (!strcmp(line, "reset")) {
Packit 96c956
    msg->data.smoothtime.option = htonl(REQ_SMOOTHTIME_RESET);
Packit 96c956
  } else if (!strcmp(line, "activate")) {
Packit 96c956
    msg->data.smoothtime.option = htonl(REQ_SMOOTHTIME_ACTIVATE);
Packit 96c956
  } else {
Packit 96c956
    LOG(LOGS_ERR, "Invalid syntax for smoothtime command");
Packit 96c956
    return 0;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  msg->command = htons(REQ_SMOOTHTIME);
Packit 96c956
Packit 96c956
  return 1;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_rtcreport(char *line)
Packit 96c956
{
Packit 96c956
  CMD_Request request;
Packit 96c956
  CMD_Reply reply;
Packit 96c956
  struct timespec ref_time;
Packit 96c956
  
Packit 96c956
  request.command = htons(REQ_RTCREPORT);
Packit 96c956
  if (!request_reply(&request, &reply, RPY_RTC, 0))
Packit 96c956
    return 0;
Packit 96c956
Packit 96c956
  UTI_TimespecNetworkToHost(&reply.data.rtc.ref_time, &ref_time);
Packit 96c956
Packit 96c956
  print_report("RTC ref time (UTC) : %T\n"
Packit 96c956
               "Number of samples  : %u\n"
Packit 96c956
               "Number of runs     : %u\n"
Packit 96c956
               "Sample span period : %I\n"
Packit 96c956
               "RTC is fast by     : %12.6f seconds\n"
Packit 96c956
               "RTC gains time at  : %9.3f ppm\n",
Packit 96c956
               &ref_time,
Packit 96c956
               ntohs(reply.data.rtc.n_samples),
Packit 96c956
               ntohs(reply.data.rtc.n_runs),
Packit 96c956
               (unsigned long)ntohl(reply.data.rtc.span_seconds),
Packit 96c956
               UTI_FloatNetworkToHost(reply.data.rtc.rtc_seconds_fast),
Packit 96c956
               UTI_FloatNetworkToHost(reply.data.rtc.rtc_gain_rate_ppm),
Packit 96c956
               REPORT_END);
Packit 96c956
Packit 96c956
  return 1;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_clients(char *line)
Packit 96c956
{
Packit 96c956
  CMD_Request request;
Packit 96c956
  CMD_Reply reply;
Packit 96c956
  IPAddr ip;
Packit 96c956
  uint32_t i, n_clients, next_index, n_indices;
Packit 96c956
  RPY_ClientAccesses_Client *client;
Packit 96c956
  char name[50];
Packit 96c956
Packit 96c956
  next_index = 0;
Packit 96c956
Packit 96c956
  print_header("Hostname                      NTP   Drop Int IntL Last     Cmd   Drop Int  Last");
Packit 96c956
Packit 96c956
  while (1) {
Packit 96c956
    request.command = htons(REQ_CLIENT_ACCESSES_BY_INDEX2);
Packit 96c956
    request.data.client_accesses_by_index.first_index = htonl(next_index);
Packit 96c956
    request.data.client_accesses_by_index.n_clients = htonl(MAX_CLIENT_ACCESSES);
Packit 96c956
Packit 96c956
    if (!request_reply(&request, &reply, RPY_CLIENT_ACCESSES_BY_INDEX2, 0))
Packit 96c956
      return 0;
Packit 96c956
Packit 96c956
    n_clients = ntohl(reply.data.client_accesses_by_index.n_clients);
Packit 96c956
    n_indices = ntohl(reply.data.client_accesses_by_index.n_indices);
Packit 96c956
Packit 96c956
    for (i = 0; i < n_clients && i < MAX_CLIENT_ACCESSES; i++) {
Packit 96c956
      client = &reply.data.client_accesses_by_index.clients[i];
Packit 96c956
Packit 96c956
      UTI_IPNetworkToHost(&client->ip, &ip);
Packit 96c956
Packit 96c956
      /* UNSPEC means the record could not be found in the daemon's tables.
Packit 96c956
         We shouldn't ever generate this case, but ignore it if we do. */
Packit 96c956
      if (ip.family == IPADDR_UNSPEC)
Packit 96c956
        continue;
Packit 96c956
Packit 96c956
      format_name(name, sizeof (name), 25, 0, 0, &ip);
Packit 96c956
Packit 96c956
      print_report("%-25s  %6U  %5U  %C  %C  %I  %6U  %5U  %C  %I\n",
Packit 96c956
                   name,
Packit 96c956
                   (unsigned long)ntohl(client->ntp_hits),
Packit 96c956
                   (unsigned long)ntohl(client->ntp_drops),
Packit 96c956
                   client->ntp_interval,
Packit 96c956
                   client->ntp_timeout_interval,
Packit 96c956
                   (unsigned long)ntohl(client->last_ntp_hit_ago),
Packit 96c956
                   (unsigned long)ntohl(client->cmd_hits),
Packit 96c956
                   (unsigned long)ntohl(client->cmd_drops),
Packit 96c956
                   client->cmd_interval,
Packit 96c956
                   (unsigned long)ntohl(client->last_cmd_hit_ago),
Packit 96c956
                   REPORT_END);
Packit 96c956
    }
Packit 96c956
Packit 96c956
    /* Set the next index to probe based on what the server tells us */
Packit 96c956
    next_index = ntohl(reply.data.client_accesses_by_index.next_index);
Packit 96c956
Packit 96c956
    if (next_index >= n_indices || n_clients < MAX_CLIENT_ACCESSES)
Packit 96c956
      break;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  return 1;
Packit 96c956
}
Packit 96c956
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
/* Process the manual list command */
Packit 96c956
static int
Packit 96c956
process_cmd_manual_list(const char *line)
Packit 96c956
{
Packit 96c956
  CMD_Request request;
Packit 96c956
  CMD_Reply reply;
Packit 96c956
  uint32_t i, n_samples;
Packit 96c956
  RPY_ManualListSample *sample;
Packit 96c956
  struct timespec when;
Packit 96c956
Packit 96c956
  request.command = htons(REQ_MANUAL_LIST);
Packit 96c956
  if (!request_reply(&request, &reply, RPY_MANUAL_LIST2, 0))
Packit 96c956
    return 0;
Packit 96c956
Packit 96c956
  n_samples = ntohl(reply.data.manual_list.n_samples);
Packit 96c956
  print_info_field("210 n_samples = %lu\n", (unsigned long)n_samples);
Packit 96c956
Packit 96c956
  print_header("#    Date     Time(UTC)    Slewed   Original   Residual");
Packit 96c956
Packit 96c956
  for (i = 0; i < n_samples && i < MAX_MANUAL_LIST_SAMPLES; i++) {
Packit 96c956
    sample = &reply.data.manual_list.samples[i];
Packit 96c956
    UTI_TimespecNetworkToHost(&sample->when, &when);
Packit 96c956
Packit 96c956
    print_report("%2d %s %10.2f %10.2f %10.2f\n",
Packit 96c956
                 i, UTI_TimeToLogForm(when.tv_sec),
Packit 96c956
                 UTI_FloatNetworkToHost(sample->slewed_offset),
Packit 96c956
                 UTI_FloatNetworkToHost(sample->orig_offset),
Packit 96c956
                 UTI_FloatNetworkToHost(sample->residual),
Packit 96c956
                 REPORT_END);
Packit 96c956
  }
Packit 96c956
Packit 96c956
  return 1;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_manual_delete(CMD_Request *msg, const char *line)
Packit 96c956
{
Packit 96c956
  int index;
Packit 96c956
Packit 96c956
  if (sscanf(line, "%d", &index) != 1) {
Packit 96c956
    LOG(LOGS_ERR, "Bad syntax for manual delete command");
Packit 96c956
    return 0;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  msg->command = htons(REQ_MANUAL_DELETE);
Packit 96c956
  msg->data.manual_delete.index = htonl(index);
Packit 96c956
  return 1;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_settime(char *line)
Packit 96c956
{
Packit 96c956
  struct timespec ts;
Packit 96c956
  time_t now, new_time;
Packit 96c956
  CMD_Request request;
Packit 96c956
  CMD_Reply reply;
Packit 96c956
  double dfreq_ppm, new_afreq_ppm;
Packit 96c956
  double offset;
Packit 96c956
Packit 96c956
  now = time(NULL);
Packit 96c956
  new_time = get_date(line, &now;;
Packit 96c956
Packit 96c956
  if (new_time == -1) {
Packit 96c956
    printf("510 - Could not parse date string\n");
Packit 96c956
  } else {
Packit 96c956
    ts.tv_sec = new_time;
Packit 96c956
    ts.tv_nsec = 0;
Packit 96c956
    UTI_TimespecHostToNetwork(&ts, &request.data.settime.ts);
Packit 96c956
    request.command = htons(REQ_SETTIME);
Packit 96c956
    if (request_reply(&request, &reply, RPY_MANUAL_TIMESTAMP2, 1)) {
Packit 96c956
          offset = UTI_FloatNetworkToHost(reply.data.manual_timestamp.offset);
Packit 96c956
          dfreq_ppm = UTI_FloatNetworkToHost(reply.data.manual_timestamp.dfreq_ppm);
Packit 96c956
          new_afreq_ppm = UTI_FloatNetworkToHost(reply.data.manual_timestamp.new_afreq_ppm);
Packit 96c956
          printf("Clock was %.2f seconds fast.  Frequency change = %.2fppm, new frequency = %.2fppm\n",
Packit 96c956
              offset, dfreq_ppm, new_afreq_ppm);
Packit 96c956
          return 1;
Packit 96c956
    }
Packit 96c956
  }
Packit 96c956
  return 0;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
process_cmd_rekey(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  msg->command = htons(REQ_REKEY);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_makestep(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  int limit;
Packit 96c956
  double threshold;
Packit 96c956
Packit 96c956
  if (*line) {
Packit 96c956
    if (sscanf(line, "%lf %d", &threshold, &limit) != 2) {
Packit 96c956
      LOG(LOGS_ERR, "Bad syntax for makestep command");
Packit 96c956
      return 0;
Packit 96c956
    }
Packit 96c956
    msg->command = htons(REQ_MODIFY_MAKESTEP);
Packit 96c956
    msg->data.modify_makestep.limit = htonl(limit);
Packit 96c956
    msg->data.modify_makestep.threshold = UTI_FloatHostToNetwork(threshold);
Packit 96c956
  } else {
Packit 96c956
    msg->command = htons(REQ_MAKESTEP);
Packit 96c956
  }
Packit 96c956
Packit 96c956
  return 1;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_activity(const char *line)
Packit 96c956
{
Packit 96c956
  CMD_Request request;
Packit 96c956
  CMD_Reply reply;
Packit 96c956
Packit 96c956
  request.command = htons(REQ_ACTIVITY);
Packit 96c956
  if (!request_reply(&request, &reply, RPY_ACTIVITY, 0))
Packit 96c956
    return 0;
Packit 96c956
Packit 96c956
  print_info_field("200 OK\n");
Packit 96c956
Packit 96c956
  print_report("%U sources online\n"
Packit 96c956
               "%U sources offline\n"
Packit 96c956
               "%U sources doing burst (return to online)\n"
Packit 96c956
               "%U sources doing burst (return to offline)\n"
Packit 96c956
               "%U sources with unknown address\n",
Packit 96c956
               (unsigned long)ntohl(reply.data.activity.online),
Packit 96c956
               (unsigned long)ntohl(reply.data.activity.offline),
Packit 96c956
               (unsigned long)ntohl(reply.data.activity.burst_online),
Packit 96c956
               (unsigned long)ntohl(reply.data.activity.burst_offline),
Packit 96c956
               (unsigned long)ntohl(reply.data.activity.unresolved),
Packit 96c956
               REPORT_END);
Packit 96c956
Packit 96c956
  return 1;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_reselectdist(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  double dist;
Packit 96c956
  int ok;
Packit 96c956
  msg->command = htons(REQ_RESELECTDISTANCE);
Packit 96c956
  if (sscanf(line, "%lf", &dist) == 1) {
Packit 96c956
    msg->data.reselect_distance.distance = UTI_FloatHostToNetwork(dist);
Packit 96c956
    ok = 1;
Packit 96c956
  } else {
Packit 96c956
    ok = 0;
Packit 96c956
  }
Packit 96c956
  return ok;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
process_cmd_reselect(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  msg->command = htons(REQ_RESELECT);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
process_cmd_refresh(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  msg->command = htons(REQ_REFRESH);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
process_cmd_shutdown(CMD_Request *msg, char *line)
Packit 96c956
{
Packit 96c956
  msg->command = htons(REQ_SHUTDOWN);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_waitsync(char *line)
Packit 96c956
{
Packit 96c956
  CMD_Request request;
Packit 96c956
  CMD_Reply reply;
Packit 96c956
  IPAddr ip_addr;
Packit 96c956
  uint32_t ref_id;
Packit 96c956
  double correction, skew_ppm, max_correction, max_skew_ppm, interval;
Packit 96c956
  int ret = 0, max_tries, i;
Packit 96c956
  struct timeval timeout;
Packit 96c956
Packit 96c956
  max_tries = 0;
Packit 96c956
  max_correction = 0.0;
Packit 96c956
  max_skew_ppm = 0.0;
Packit 96c956
  interval = 10.0;
Packit 96c956
Packit 96c956
  if (sscanf(line, "%d %lf %lf %lf", &max_tries, &max_correction, &max_skew_ppm, &interval))
Packit 96c956
    ;
Packit 96c956
Packit 96c956
  /* Don't allow shorter interval than 0.1 seconds */
Packit 96c956
  if (interval < 0.1)
Packit 96c956
    interval = 0.1;
Packit 96c956
Packit 96c956
  request.command = htons(REQ_TRACKING);
Packit 96c956
Packit 96c956
  for (i = 1; ; i++) {
Packit 96c956
    if (request_reply(&request, &reply, RPY_TRACKING, 0)) {
Packit 96c956
      ref_id = ntohl(reply.data.tracking.ref_id);
Packit 96c956
      UTI_IPNetworkToHost(&reply.data.tracking.ip_addr, &ip_addr);
Packit 96c956
Packit 96c956
      correction = UTI_FloatNetworkToHost(reply.data.tracking.current_correction);
Packit 96c956
      correction = fabs(correction);
Packit 96c956
      skew_ppm = UTI_FloatNetworkToHost(reply.data.tracking.skew_ppm);
Packit 96c956
Packit 96c956
      print_report("try: %d, refid: %R, correction: %.9f, skew: %.3f\n",
Packit 96c956
                   i, (unsigned long)ref_id, correction, skew_ppm, REPORT_END);
Packit 96c956
Packit 96c956
      if ((ip_addr.family != IPADDR_UNSPEC ||
Packit 96c956
           (ref_id != 0 && ref_id != 0x7f7f0101L /* LOCAL refid */)) &&
Packit 96c956
          (max_correction == 0.0 || correction <= max_correction) &&
Packit 96c956
          (max_skew_ppm == 0.0 || skew_ppm <= max_skew_ppm)) {
Packit 96c956
        ret = 1;
Packit 96c956
      }
Packit 96c956
    }
Packit 96c956
Packit 96c956
    if (!ret && (!max_tries || i < max_tries) && !quit) {
Packit 96c956
      UTI_DoubleToTimeval(interval, &timeout);
Packit 96c956
      if (select(0, NULL, NULL, NULL, &timeout))
Packit 96c956
        break;
Packit 96c956
    } else {
Packit 96c956
      break;
Packit 96c956
    }
Packit 96c956
  }
Packit 96c956
  return ret;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_dns(const char *line)
Packit 96c956
{
Packit 96c956
  if (!strcmp(line, "-46")) {
Packit 96c956
    DNS_SetAddressFamily(IPADDR_UNSPEC);
Packit 96c956
  } else if (!strcmp(line, "-4")) {
Packit 96c956
    DNS_SetAddressFamily(IPADDR_INET4);
Packit 96c956
  } else if (!strcmp(line, "-6")) {
Packit 96c956
    DNS_SetAddressFamily(IPADDR_INET6);
Packit 96c956
  } else if (!strcmp(line, "-n")) {
Packit 96c956
    no_dns = 1;
Packit 96c956
  } else if (!strcmp(line, "+n")) {
Packit 96c956
    no_dns = 0;
Packit 96c956
  } else {
Packit 96c956
    LOG(LOGS_ERR, "Unrecognized dns command");
Packit 96c956
    return 0;
Packit 96c956
  }
Packit 96c956
  return 1;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_timeout(const char *line)
Packit 96c956
{
Packit 96c956
  int timeout;
Packit 96c956
Packit 96c956
  timeout = atoi(line);
Packit 96c956
  if (timeout < 100) {
Packit 96c956
    LOG(LOGS_ERR, "Timeout %d is too short", timeout);
Packit 96c956
    return 0;
Packit 96c956
  }
Packit 96c956
  initial_timeout = timeout;
Packit 96c956
  return 1;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_retries(const char *line)
Packit 96c956
{
Packit 96c956
  int retries;
Packit 96c956
Packit 96c956
  retries = atoi(line);
Packit 96c956
  if (retries < 0 || retries > 30) {
Packit 96c956
    LOG(LOGS_ERR, "Invalid maximum number of retries");
Packit 96c956
    return 0;
Packit 96c956
  }
Packit 96c956
  max_retries = retries;
Packit 96c956
  return 1;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_cmd_keygen(char *line)
Packit 96c956
{
Packit 96c956
  char hash_name[17];
Packit 96c956
  unsigned char key[512];
Packit 96c956
  unsigned int i, length, id = 1, bits = 160;
Packit 96c956
Packit 96c956
#ifdef FEAT_SECHASH
Packit 96c956
  snprintf(hash_name, sizeof (hash_name), "SHA1");
Packit 96c956
#else
Packit 96c956
  snprintf(hash_name, sizeof (hash_name), "MD5");
Packit 96c956
#endif
Packit 96c956
Packit 96c956
  if (sscanf(line, "%u %16s %u", &id, hash_name, &bits))
Packit 96c956
    ;
Packit 96c956
Packit 96c956
  length = CLAMP(10, (bits + 7) / 8, sizeof (key));
Packit 96c956
  if (HSH_GetHashId(hash_name) < 0) {
Packit 96c956
    LOG(LOGS_ERR, "Unknown hash function %s", hash_name);
Packit 96c956
    return 0;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  UTI_GetRandomBytesUrandom(key, length);
Packit 96c956
Packit 96c956
  printf("%u %s HEX:", id, hash_name);
Packit 96c956
  for (i = 0; i < length; i++)
Packit 96c956
    printf("%02hhX", key[i]);
Packit 96c956
  printf("\n");
Packit 96c956
Packit 96c956
  return 1;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_line(char *line)
Packit 96c956
{
Packit 96c956
  char *command;
Packit 96c956
  int do_normal_submit;
Packit 96c956
  int ret;
Packit 96c956
  CMD_Request tx_message;
Packit 96c956
  CMD_Reply rx_message;
Packit 96c956
Packit 96c956
  ret = 0;
Packit 96c956
Packit 96c956
  do_normal_submit = 1;
Packit 96c956
Packit 96c956
  CPS_NormalizeLine(line);
Packit 96c956
Packit 96c956
  if (!*line) {
Packit 96c956
    fflush(stderr);
Packit 96c956
    fflush(stdout);
Packit 96c956
    return 1;
Packit 96c956
  };
Packit 96c956
Packit 96c956
  command = line;
Packit 96c956
  line = CPS_SplitWord(line);
Packit 96c956
Packit 96c956
  if (!strcmp(command, "accheck")) {
Packit 96c956
    do_normal_submit = process_cmd_accheck(&tx_message, line);
Packit 96c956
  } else if (!strcmp(command, "activity")) {
Packit 96c956
    do_normal_submit = 0;
Packit 96c956
    ret = process_cmd_activity(line);
Packit 96c956
  } else if (!strcmp(command, "add") && !strncmp(line, "peer", 4)) {
Packit 96c956
    do_normal_submit = process_cmd_add_peer(&tx_message, CPS_SplitWord(line));
Packit 96c956
  } else if (!strcmp(command, "add") && !strncmp(line, "server", 6)) {
Packit 96c956
    do_normal_submit = process_cmd_add_server(&tx_message, CPS_SplitWord(line));
Packit 96c956
  } else if (!strcmp(command, "allow")) {
Packit 96c956
    if (!strncmp(line, "all", 3)) {
Packit 96c956
      do_normal_submit = process_cmd_allowall(&tx_message, CPS_SplitWord(line));
Packit 96c956
    } else {
Packit 96c956
      do_normal_submit = process_cmd_allow(&tx_message, line);
Packit 96c956
    }
Packit 96c956
  } else if (!strcmp(command, "burst")) {
Packit 96c956
    do_normal_submit = process_cmd_burst(&tx_message, line);
Packit 96c956
  } else if (!strcmp(command, "clients")) {
Packit 96c956
    ret = process_cmd_clients(line);
Packit 96c956
    do_normal_submit = 0;
Packit 96c956
  } else if (!strcmp(command, "cmdaccheck")) {
Packit 96c956
    do_normal_submit = process_cmd_cmdaccheck(&tx_message, line);
Packit 96c956
  } else if (!strcmp(command, "cmdallow")) {
Packit 96c956
    if (!strncmp(line, "all", 3)) {
Packit 96c956
      do_normal_submit = process_cmd_cmdallowall(&tx_message, CPS_SplitWord(line));
Packit 96c956
    } else {
Packit 96c956
      do_normal_submit = process_cmd_cmdallow(&tx_message, line);
Packit 96c956
    }
Packit 96c956
  } else if (!strcmp(command, "cmddeny")) {
Packit 96c956
    if (!strncmp(line, "all", 3)) {
Packit 96c956
      line = CPS_SplitWord(line);
Packit 96c956
      do_normal_submit = process_cmd_cmddenyall(&tx_message, line);
Packit 96c956
    } else {
Packit 96c956
      do_normal_submit = process_cmd_cmddeny(&tx_message, line);
Packit 96c956
    }
Packit 96c956
  } else if (!strcmp(command, "cyclelogs")) {
Packit 96c956
    process_cmd_cyclelogs(&tx_message, line);
Packit 96c956
  } else if (!strcmp(command, "delete")) {
Packit 96c956
    do_normal_submit = process_cmd_delete(&tx_message, line);
Packit 96c956
  } else if (!strcmp(command, "deny")) {
Packit 96c956
    if (!strncmp(line, "all", 3)) {
Packit 96c956
      do_normal_submit = process_cmd_denyall(&tx_message, CPS_SplitWord(line));
Packit 96c956
    } else {
Packit 96c956
      do_normal_submit = process_cmd_deny(&tx_message, line);
Packit 96c956
    }
Packit 96c956
  } else if (!strcmp(command, "dfreq")) {
Packit 96c956
    process_cmd_dfreq(&tx_message, line);
Packit 96c956
  } else if (!strcmp(command, "dns")) {
Packit 96c956
    ret = process_cmd_dns(line);
Packit 96c956
    do_normal_submit = 0;
Packit 96c956
  } else if (!strcmp(command, "doffset")) {
Packit 96c956
    process_cmd_doffset(&tx_message, line);
Packit 96c956
  } else if (!strcmp(command, "dump")) {
Packit 96c956
    process_cmd_dump(&tx_message, line);
Packit 96c956
  } else if (!strcmp(command, "exit")) {
Packit 96c956
    do_normal_submit = 0;
Packit 96c956
    quit = 1;
Packit 96c956
    ret = 1;
Packit 96c956
  } else if (!strcmp(command, "help")) {
Packit 96c956
    do_normal_submit = 0;
Packit 96c956
    give_help();
Packit 96c956
    ret = 1;
Packit 96c956
  } else if (!strcmp(command, "keygen")) {
Packit 96c956
    ret = process_cmd_keygen(line);
Packit 96c956
    do_normal_submit = 0;
Packit 96c956
  } else if (!strcmp(command, "local")) {
Packit 96c956
    do_normal_submit = process_cmd_local(&tx_message, line);
Packit 96c956
  } else if (!strcmp(command, "makestep")) {
Packit 96c956
    do_normal_submit = process_cmd_makestep(&tx_message, line);
Packit 96c956
  } else if (!strcmp(command, "manual")) {
Packit 96c956
    if (!strncmp(line, "list", 4)) {
Packit 96c956
      do_normal_submit = 0;
Packit 96c956
      ret = process_cmd_manual_list(CPS_SplitWord(line));
Packit 96c956
    } else if (!strncmp(line, "delete", 6)) {
Packit 96c956
      do_normal_submit = process_cmd_manual_delete(&tx_message, CPS_SplitWord(line));
Packit 96c956
    } else {
Packit 96c956
      do_normal_submit = process_cmd_manual(&tx_message, line);
Packit 96c956
    }
Packit 96c956
  } else if (!strcmp(command, "maxdelay")) {
Packit 96c956
    do_normal_submit = process_cmd_maxdelay(&tx_message, line);
Packit 96c956
  } else if (!strcmp(command, "maxdelaydevratio")) {
Packit 96c956
    do_normal_submit = process_cmd_maxdelaydevratio(&tx_message, line);
Packit 96c956
  } else if (!strcmp(command, "maxdelayratio")) {
Packit 96c956
    do_normal_submit = process_cmd_maxdelayratio(&tx_message, line);
Packit 96c956
  } else if (!strcmp(command, "maxpoll")) {
Packit 96c956
    do_normal_submit = process_cmd_maxpoll(&tx_message, line);
Packit 96c956
  } else if (!strcmp(command, "maxupdateskew")) {
Packit 96c956
    do_normal_submit = process_cmd_maxupdateskew(&tx_message, line);
Packit 96c956
  } else if (!strcmp(command, "minpoll")) {
Packit 96c956
    do_normal_submit = process_cmd_minpoll(&tx_message, line);
Packit 96c956
  } else if (!strcmp(command, "minstratum")) {
Packit 96c956
    do_normal_submit = process_cmd_minstratum(&tx_message, line);
Packit 96c956
  } else if (!strcmp(command, "ntpdata")) {
Packit 96c956
    do_normal_submit = 0;
Packit 96c956
    ret = process_cmd_ntpdata(line);
Packit 96c956
  } else if (!strcmp(command, "offline")) {
Packit 96c956
    do_normal_submit = process_cmd_offline(&tx_message, line);
Packit 96c956
  } else if (!strcmp(command, "online")) {
Packit 96c956
    do_normal_submit = process_cmd_online(&tx_message, line);
Packit 96c956
  } else if (!strcmp(command, "onoffline")) {
Packit 96c956
    process_cmd_onoffline(&tx_message, line);
Packit 96c956
  } else if (!strcmp(command, "polltarget")) {
Packit 96c956
    do_normal_submit = process_cmd_polltarget(&tx_message, line);
Packit 96c956
  } else if (!strcmp(command, "quit")) {
Packit 96c956
    do_normal_submit = 0;
Packit 96c956
    quit = 1;
Packit 96c956
    ret = 1;
Packit 96c956
  } else if (!strcmp(command, "refresh")) {
Packit 96c956
    process_cmd_refresh(&tx_message, line);
Packit 96c956
  } else if (!strcmp(command, "rekey")) {
Packit 96c956
    process_cmd_rekey(&tx_message, line);
Packit 96c956
  } else if (!strcmp(command, "reselect")) {
Packit 96c956
    process_cmd_reselect(&tx_message, line);
Packit 96c956
  } else if (!strcmp(command, "reselectdist")) {
Packit 96c956
    do_normal_submit = process_cmd_reselectdist(&tx_message, line);
Packit 96c956
  } else if (!strcmp(command, "retries")) {
Packit 96c956
    ret = process_cmd_retries(line);
Packit 96c956
    do_normal_submit = 0;
Packit 96c956
  } else if (!strcmp(command, "rtcdata")) {
Packit 96c956
    do_normal_submit = 0;
Packit 96c956
    ret = process_cmd_rtcreport(line);
Packit 96c956
  } else if (!strcmp(command, "serverstats")) {
Packit 96c956
    do_normal_submit = 0;
Packit 96c956
    ret = process_cmd_serverstats(line);
Packit 96c956
  } else if (!strcmp(command, "settime")) {
Packit 96c956
    do_normal_submit = 0;
Packit 96c956
    ret = process_cmd_settime(line);
Packit 96c956
  } else if (!strcmp(command, "shutdown")) {
Packit 96c956
    process_cmd_shutdown(&tx_message, line);
Packit 96c956
  } else if (!strcmp(command, "smoothing")) {
Packit 96c956
    do_normal_submit = 0;
Packit 96c956
    ret = process_cmd_smoothing(line);
Packit 96c956
  } else if (!strcmp(command, "smoothtime")) {
Packit 96c956
    do_normal_submit = process_cmd_smoothtime(&tx_message, line);
Packit 96c956
  } else if (!strcmp(command, "sources")) {
Packit 96c956
    do_normal_submit = 0;
Packit 96c956
    ret = process_cmd_sources(line);
Packit 96c956
  } else if (!strcmp(command, "sourcestats")) {
Packit 96c956
    do_normal_submit = 0;
Packit 96c956
    ret = process_cmd_sourcestats(line);
Packit 96c956
  } else if (!strcmp(command, "timeout")) {
Packit 96c956
    ret = process_cmd_timeout(line);
Packit 96c956
    do_normal_submit = 0;
Packit 96c956
  } else if (!strcmp(command, "tracking")) {
Packit 96c956
    ret = process_cmd_tracking(line);
Packit 96c956
    do_normal_submit = 0;
Packit 96c956
  } else if (!strcmp(command, "trimrtc")) {
Packit 96c956
    process_cmd_trimrtc(&tx_message, line);
Packit 96c956
  } else if (!strcmp(command, "waitsync")) {
Packit 96c956
    ret = process_cmd_waitsync(line);
Packit 96c956
    do_normal_submit = 0;
Packit 96c956
  } else if (!strcmp(command, "writertc")) {
Packit 96c956
    process_cmd_writertc(&tx_message, line);
Packit 96c956
  } else if (!strcmp(command, "authhash") ||
Packit 96c956
             !strcmp(command, "password")) {
Packit 96c956
    /* Warn, but don't return error to not break scripts */
Packit 96c956
    LOG(LOGS_WARN, "Authentication is no longer supported");
Packit 96c956
    do_normal_submit = 0;
Packit 96c956
    ret = 1;
Packit 96c956
  } else {
Packit 96c956
    LOG(LOGS_ERR, "Unrecognized command");
Packit 96c956
    do_normal_submit = 0;
Packit 96c956
  }
Packit 96c956
    
Packit 96c956
  if (do_normal_submit) {
Packit 96c956
    ret = request_reply(&tx_message, &rx_message, RPY_NULL, 1);
Packit 96c956
  }
Packit 96c956
  fflush(stderr);
Packit 96c956
  fflush(stdout);
Packit 96c956
  return ret;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
process_args(int argc, char **argv, int multi)
Packit 96c956
{
Packit 96c956
  int total_length, i, ret = 0;
Packit 96c956
  char *line;
Packit 96c956
Packit 96c956
  total_length = 0;
Packit 96c956
  for(i=0; i
Packit 96c956
    total_length += strlen(argv[i]) + 1;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  line = (char *) Malloc((2 + total_length) * sizeof(char));
Packit 96c956
Packit 96c956
  for (i = 0; i < argc; i++) {
Packit 96c956
    line[0] = '\0';
Packit 96c956
    if (multi) {
Packit 96c956
      strcat(line, argv[i]);
Packit 96c956
    } else {
Packit 96c956
      for (; i < argc; i++) {
Packit 96c956
        strcat(line, argv[i]);
Packit 96c956
        if (i + 1 < argc)
Packit 96c956
          strcat(line, " ");
Packit 96c956
      }
Packit 96c956
    }
Packit 96c956
Packit 96c956
    ret = process_line(line);
Packit 96c956
    if (!ret || quit)
Packit 96c956
      break;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  Free(line);
Packit 96c956
Packit 96c956
  return ret;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
signal_handler(int signum)
Packit 96c956
{
Packit 96c956
  quit = 1;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
display_gpl(void)
Packit 96c956
{
Packit 96c956
    printf("chrony version %s\n"
Packit 96c956
           "Copyright (C) 1997-2003, 2007, 2009-2019 Richard P. Curnow and others\n"
Packit 96c956
           "chrony comes with ABSOLUTELY NO WARRANTY.  This is free software, and\n"
Packit 96c956
           "you are welcome to redistribute it under certain conditions.  See the\n"
Packit 96c956
           "GNU General Public License version 2 for details.\n\n",
Packit 96c956
           CHRONY_VERSION);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
print_help(const char *progname)
Packit 96c956
{
Packit 96c956
      printf("Usage: %s [-h HOST] [-p PORT] [-n] [-c] [-d] [-4|-6] [-m] [COMMAND]\n",
Packit 96c956
             progname);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
print_version(void)
Packit 96c956
{
Packit 96c956
      printf("chronyc (chrony) version %s (%s)\n", CHRONY_VERSION, CHRONYC_FEATURES);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
int
Packit 96c956
main(int argc, char **argv)
Packit 96c956
{
Packit 96c956
  char *line;
Packit 96c956
  const char *progname = argv[0];
Packit 96c956
  const char *hostnames = NULL;
Packit 96c956
  int opt, ret = 1, multi = 0, family = IPADDR_UNSPEC;
Packit 96c956
  int port = DEFAULT_CANDM_PORT;
Packit 96c956
Packit 96c956
  /* Parse (undocumented) long command-line options */
Packit 96c956
  for (optind = 1; optind < argc; optind++) {
Packit 96c956
    if (!strcmp("--help", argv[optind])) {
Packit 96c956
      print_help(progname);
Packit 96c956
      return 0;
Packit 96c956
    } else if (!strcmp("--version", argv[optind])) {
Packit 96c956
      print_version();
Packit 96c956
      return 0;
Packit 96c956
    }
Packit 96c956
  }
Packit 96c956
Packit 96c956
  optind = 1;
Packit 96c956
Packit 96c956
  /* Parse short command-line options */
Packit 96c956
  while ((opt = getopt(argc, argv, "+46acdf:h:mnp:v")) != -1) {
Packit 96c956
    switch (opt) {
Packit 96c956
      case '4':
Packit 96c956
      case '6':
Packit 96c956
        family = opt == '4' ? IPADDR_INET4 : IPADDR_INET6;
Packit 96c956
        break;
Packit 96c956
      case 'a':
Packit 96c956
      case 'f':
Packit 96c956
        /* For compatibility only */
Packit 96c956
        break;
Packit 96c956
      case 'c':
Packit 96c956
        csv_mode = 1;
Packit 96c956
        break;
Packit 96c956
      case 'd':
Packit 96c956
        log_debug_enabled = 1;
Packit 96c956
        break;
Packit 96c956
      case 'h':
Packit 96c956
        hostnames = optarg;
Packit 96c956
        break;
Packit 96c956
      case 'm':
Packit 96c956
        multi = 1;
Packit 96c956
        break;
Packit 96c956
      case 'n':
Packit 96c956
        no_dns = 1;
Packit 96c956
        break;
Packit 96c956
      case 'p':
Packit 96c956
        port = atoi(optarg);
Packit 96c956
        break;
Packit 96c956
      case 'v':
Packit 96c956
        print_version();
Packit 96c956
        return 0;
Packit 96c956
      default:
Packit 96c956
        print_help(progname);
Packit 96c956
        return 1;
Packit 96c956
    }
Packit 96c956
  }
Packit 96c956
Packit 96c956
  if (isatty(0) && isatty(1) && isatty(2)) {
Packit 96c956
    on_terminal = 1;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  if (on_terminal && optind == argc) {
Packit 96c956
    display_gpl();
Packit 96c956
  }
Packit 96c956
  
Packit 96c956
  DNS_SetAddressFamily(family);
Packit 96c956
Packit 96c956
  if (!hostnames) {
Packit 96c956
    hostnames = DEFAULT_COMMAND_SOCKET",127.0.0.1,::1";
Packit 96c956
  }
Packit 96c956
Packit 96c956
  UTI_SetQuitSignalsHandler(signal_handler, 0);
Packit 96c956
Packit 96c956
  sockaddrs = get_sockaddrs(hostnames, port);
Packit 96c956
Packit 96c956
  if (!open_io())
Packit 96c956
    LOG_FATAL("Could not open connection to daemon");
Packit 96c956
Packit 96c956
  if (optind < argc) {
Packit 96c956
    ret = process_args(argc - optind, argv + optind, multi);
Packit 96c956
  } else {
Packit 96c956
    do {
Packit 96c956
      line = read_line();
Packit 96c956
      if (line && !quit) {
Packit 96c956
        ret = process_line(line);
Packit 96c956
      }else {
Packit 96c956
	/* supply the final '\n' when user exits via ^D */
Packit 96c956
        if( on_terminal ) printf("\n");
Packit 96c956
      }
Packit 96c956
    } while (line && !quit);
Packit 96c956
  }
Packit 96c956
Packit 96c956
  close_io();
Packit 96c956
Packit 96c956
  ARR_DestroyInstance(sockaddrs);
Packit 96c956
Packit 96c956
  return !ret;
Packit 96c956
}
Packit 96c956
Packit 96c956