Blame cmdmon.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) Miroslav Lichvar  2009-2016, 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 and monitoring module in the main program
Packit 96c956
  */
Packit 96c956
Packit 96c956
#include "config.h"
Packit 96c956
Packit 96c956
#include "sysincl.h"
Packit 96c956
Packit 96c956
#include "cmdmon.h"
Packit 96c956
#include "candm.h"
Packit 96c956
#include "sched.h"
Packit 96c956
#include "util.h"
Packit 96c956
#include "logging.h"
Packit 96c956
#include "keys.h"
Packit 96c956
#include "ntp_sources.h"
Packit 96c956
#include "ntp_core.h"
Packit 96c956
#include "smooth.h"
Packit 96c956
#include "sources.h"
Packit 96c956
#include "sourcestats.h"
Packit 96c956
#include "reference.h"
Packit 96c956
#include "manual.h"
Packit 96c956
#include "memory.h"
Packit 96c956
#include "local.h"
Packit 96c956
#include "addrfilt.h"
Packit 96c956
#include "conf.h"
Packit 96c956
#include "rtc.h"
Packit 96c956
#include "pktlength.h"
Packit 96c956
#include "clientlog.h"
Packit 96c956
#include "refclock.h"
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
/* File descriptors for command and monitoring sockets */
Packit 96c956
static int sock_fdu;
Packit 96c956
static int sock_fd4;
Packit 96c956
#ifdef FEAT_IPV6
Packit 96c956
static int sock_fd6;
Packit 96c956
#endif
Packit 96c956
Packit 96c956
/* Flag indicating whether this module has been initialised or not */
Packit 96c956
static int initialised = 0;
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
/* Array of permission levels for command types */
Packit 96c956
Packit 96c956
static const char permissions[] = {
Packit 96c956
  PERMIT_OPEN, /* NULL */
Packit 96c956
  PERMIT_AUTH, /* ONLINE */
Packit 96c956
  PERMIT_AUTH, /* OFFLINE */
Packit 96c956
  PERMIT_AUTH, /* BURST */
Packit 96c956
  PERMIT_AUTH, /* MODIFY_MINPOLL */
Packit 96c956
  PERMIT_AUTH, /* MODIFY_MAXPOLL */
Packit 96c956
  PERMIT_AUTH, /* DUMP */
Packit 96c956
  PERMIT_AUTH, /* MODIFY_MAXDELAY */
Packit 96c956
  PERMIT_AUTH, /* MODIFY_MAXDELAYRATIO */
Packit 96c956
  PERMIT_AUTH, /* MODIFY_MAXUPDATESKEW */
Packit 96c956
  PERMIT_OPEN, /* LOGON */
Packit 96c956
  PERMIT_AUTH, /* SETTIME */
Packit 96c956
  PERMIT_AUTH, /* LOCAL */
Packit 96c956
  PERMIT_AUTH, /* MANUAL */
Packit 96c956
  PERMIT_OPEN, /* N_SOURCES */
Packit 96c956
  PERMIT_OPEN, /* SOURCE_DATA */
Packit 96c956
  PERMIT_AUTH, /* REKEY */
Packit 96c956
  PERMIT_AUTH, /* ALLOW */
Packit 96c956
  PERMIT_AUTH, /* ALLOWALL */
Packit 96c956
  PERMIT_AUTH, /* DENY */
Packit 96c956
  PERMIT_AUTH, /* DENYALL */
Packit 96c956
  PERMIT_AUTH, /* CMDALLOW */
Packit 96c956
  PERMIT_AUTH, /* CMDALLOWALL */
Packit 96c956
  PERMIT_AUTH, /* CMDDENY */
Packit 96c956
  PERMIT_AUTH, /* CMDDENYALL */
Packit 96c956
  PERMIT_AUTH, /* ACCHECK */
Packit 96c956
  PERMIT_AUTH, /* CMDACCHECK */
Packit 96c956
  PERMIT_AUTH, /* ADD_SERVER */
Packit 96c956
  PERMIT_AUTH, /* ADD_PEER */
Packit 96c956
  PERMIT_AUTH, /* DEL_SOURCE */
Packit 96c956
  PERMIT_AUTH, /* WRITERTC */
Packit 96c956
  PERMIT_AUTH, /* DFREQ */
Packit 96c956
  PERMIT_AUTH, /* DOFFSET */
Packit 96c956
  PERMIT_OPEN, /* TRACKING */
Packit 96c956
  PERMIT_OPEN, /* SOURCESTATS */
Packit 96c956
  PERMIT_OPEN, /* RTCREPORT */
Packit 96c956
  PERMIT_AUTH, /* TRIMRTC */
Packit 96c956
  PERMIT_AUTH, /* CYCLELOGS */
Packit 96c956
  PERMIT_AUTH, /* SUBNETS_ACCESSED */
Packit 96c956
  PERMIT_AUTH, /* CLIENT_ACCESSES (by subnet) */
Packit 96c956
  PERMIT_AUTH, /* CLIENT_ACCESSES_BY_INDEX */
Packit 96c956
  PERMIT_OPEN, /* MANUAL_LIST */
Packit 96c956
  PERMIT_AUTH, /* MANUAL_DELETE */
Packit 96c956
  PERMIT_AUTH, /* MAKESTEP */
Packit 96c956
  PERMIT_OPEN, /* ACTIVITY */
Packit 96c956
  PERMIT_AUTH, /* MODIFY_MINSTRATUM */
Packit 96c956
  PERMIT_AUTH, /* MODIFY_POLLTARGET */
Packit 96c956
  PERMIT_AUTH, /* MODIFY_MAXDELAYDEVRATIO */
Packit 96c956
  PERMIT_AUTH, /* RESELECT */
Packit 96c956
  PERMIT_AUTH, /* RESELECTDISTANCE */
Packit 96c956
  PERMIT_AUTH, /* MODIFY_MAKESTEP */
Packit 96c956
  PERMIT_OPEN, /* SMOOTHING */
Packit 96c956
  PERMIT_AUTH, /* SMOOTHTIME */
Packit 96c956
  PERMIT_AUTH, /* REFRESH */
Packit 96c956
  PERMIT_AUTH, /* SERVER_STATS */
Packit 96c956
  PERMIT_AUTH, /* CLIENT_ACCESSES_BY_INDEX2 */
Packit 96c956
  PERMIT_AUTH, /* LOCAL2 */
Packit 96c956
  PERMIT_AUTH, /* NTP_DATA */
Packit 96c956
  PERMIT_AUTH, /* ADD_SERVER2 */
Packit 96c956
  PERMIT_AUTH, /* ADD_PEER2 */
Packit 96c956
  PERMIT_AUTH, /* ADD_SERVER3 */
Packit 96c956
  PERMIT_AUTH, /* ADD_PEER3 */
Packit 96c956
  PERMIT_AUTH, /* SHUTDOWN */
Packit 96c956
  PERMIT_AUTH, /* ONOFFLINE */
Packit 96c956
};
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
/* This authorisation table is used for checking whether particular
Packit 96c956
   machines are allowed to make command and monitoring requests. */
Packit 96c956
static ADF_AuthTable access_auth_table;
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
/* Forward prototypes */
Packit 96c956
static void read_from_cmd_socket(int sock_fd, int event, void *anything);
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static int
Packit 96c956
prepare_socket(int family, int port_number)
Packit 96c956
{
Packit 96c956
  int sock_fd;
Packit 96c956
  socklen_t my_addr_len;
Packit 96c956
  union sockaddr_all my_addr;
Packit 96c956
  IPAddr bind_address;
Packit 96c956
  int on_off = 1;
Packit 96c956
Packit 96c956
  sock_fd = socket(family, SOCK_DGRAM, 0);
Packit 96c956
  if (sock_fd < 0) {
Packit 96c956
    LOG(LOGS_ERR, "Could not open %s command socket : %s",
Packit 96c956
        UTI_SockaddrFamilyToString(family), strerror(errno));
Packit 96c956
    return -1;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  /* Close on exec */
Packit 96c956
  UTI_FdSetCloexec(sock_fd);
Packit 96c956
Packit 96c956
  if (family != AF_UNIX) {
Packit 96c956
    /* Allow reuse of port number */
Packit 96c956
    if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on_off, sizeof(on_off)) < 0) {
Packit 96c956
      LOG(LOGS_ERR, "Could not set reuseaddr socket options");
Packit 96c956
      /* Don't quit - we might survive anyway */
Packit 96c956
    }
Packit 96c956
Packit 96c956
#ifdef IP_FREEBIND
Packit 96c956
    /* Allow binding to address that doesn't exist yet */
Packit 96c956
    if (setsockopt(sock_fd, IPPROTO_IP, IP_FREEBIND, (char *)&on_off, sizeof(on_off)) < 0) {
Packit 96c956
      LOG(LOGS_ERR, "Could not set free bind socket option");
Packit 96c956
    }
Packit 96c956
#endif
Packit 96c956
Packit 96c956
#ifdef FEAT_IPV6
Packit 96c956
    if (family == AF_INET6) {
Packit 96c956
#ifdef IPV6_V6ONLY
Packit 96c956
      /* Receive IPv6 packets only */
Packit 96c956
      if (setsockopt(sock_fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on_off, sizeof(on_off)) < 0) {
Packit 96c956
        LOG(LOGS_ERR, "Could not request IPV6_V6ONLY socket option");
Packit 96c956
      }
Packit 96c956
#endif
Packit 96c956
    }
Packit 96c956
#endif
Packit 96c956
  }
Packit 96c956
Packit 96c956
  memset(&my_addr, 0, sizeof (my_addr));
Packit 96c956
Packit 96c956
  switch (family) {
Packit 96c956
    case AF_INET:
Packit 96c956
      my_addr_len = sizeof (my_addr.in4);
Packit 96c956
      my_addr.in4.sin_family = family;
Packit 96c956
      my_addr.in4.sin_port = htons((unsigned short)port_number);
Packit 96c956
Packit 96c956
      CNF_GetBindCommandAddress(IPADDR_INET4, &bind_address);
Packit 96c956
Packit 96c956
      if (bind_address.family == IPADDR_INET4)
Packit 96c956
        my_addr.in4.sin_addr.s_addr = htonl(bind_address.addr.in4);
Packit 96c956
      else
Packit 96c956
        my_addr.in4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
Packit 96c956
      break;
Packit 96c956
#ifdef FEAT_IPV6
Packit 96c956
    case AF_INET6:
Packit 96c956
      my_addr_len = sizeof (my_addr.in6);
Packit 96c956
      my_addr.in6.sin6_family = family;
Packit 96c956
      my_addr.in6.sin6_port = htons((unsigned short)port_number);
Packit 96c956
Packit 96c956
      CNF_GetBindCommandAddress(IPADDR_INET6, &bind_address);
Packit 96c956
Packit 96c956
      if (bind_address.family == IPADDR_INET6)
Packit 96c956
        memcpy(my_addr.in6.sin6_addr.s6_addr, bind_address.addr.in6,
Packit 96c956
            sizeof (my_addr.in6.sin6_addr.s6_addr));
Packit 96c956
      else
Packit 96c956
        my_addr.in6.sin6_addr = in6addr_loopback;
Packit 96c956
      break;
Packit 96c956
#endif
Packit 96c956
    case AF_UNIX:
Packit 96c956
      my_addr_len = sizeof (my_addr.un);
Packit 96c956
      my_addr.un.sun_family = family;
Packit 96c956
      if (snprintf(my_addr.un.sun_path, sizeof (my_addr.un.sun_path), "%s",
Packit 96c956
                   CNF_GetBindCommandPath()) >= sizeof (my_addr.un.sun_path))
Packit 96c956
        LOG_FATAL("Unix socket path too long");
Packit 96c956
      unlink(my_addr.un.sun_path);
Packit 96c956
      break;
Packit 96c956
    default:
Packit 96c956
      assert(0);
Packit 96c956
  }
Packit 96c956
Packit 96c956
  if (bind(sock_fd, &my_addr.sa, my_addr_len) < 0) {
Packit 96c956
    LOG(LOGS_ERR, "Could not bind %s command socket : %s",
Packit 96c956
        UTI_SockaddrFamilyToString(family), strerror(errno));
Packit 96c956
    close(sock_fd);
Packit 96c956
    return -1;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  /* Register handler for read events on the socket */
Packit 96c956
  SCH_AddFileHandler(sock_fd, SCH_FILE_INPUT, read_from_cmd_socket, NULL);
Packit 96c956
Packit 96c956
  return sock_fd;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
do_size_checks(void)
Packit 96c956
{
Packit 96c956
  int i, request_length, padding_length, reply_length;
Packit 96c956
  CMD_Request request;
Packit 96c956
  CMD_Reply reply;
Packit 96c956
Packit 96c956
  assert(offsetof(CMD_Request, data) == 20);
Packit 96c956
  assert(offsetof(CMD_Reply, data) == 28);
Packit 96c956
Packit 96c956
  for (i = 0; i < N_REQUEST_TYPES; i++) {
Packit 96c956
    request.version = PROTO_VERSION_NUMBER;
Packit 96c956
    request.command = htons(i);
Packit 96c956
    request_length = PKL_CommandLength(&request);
Packit 96c956
    padding_length = PKL_CommandPaddingLength(&request);
Packit 96c956
    if (padding_length > MAX_PADDING_LENGTH || padding_length > request_length ||
Packit 96c956
        request_length > sizeof (CMD_Request) ||
Packit 96c956
        (request_length && request_length < offsetof(CMD_Request, data)))
Packit 96c956
      assert(0);
Packit 96c956
  }
Packit 96c956
Packit 96c956
  for (i = 1; i < N_REPLY_TYPES; i++) {
Packit 96c956
    reply.reply = htons(i);
Packit 96c956
    reply.status = STT_SUCCESS;
Packit 96c956
    reply_length = PKL_ReplyLength(&reply);
Packit 96c956
    if ((reply_length && reply_length < offsetof(CMD_Reply, data)) ||
Packit 96c956
        reply_length > sizeof (CMD_Reply))
Packit 96c956
      assert(0);
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
void
Packit 96c956
CAM_Initialise(int family)
Packit 96c956
{
Packit 96c956
  int port_number;
Packit 96c956
Packit 96c956
  assert(!initialised);
Packit 96c956
  assert(sizeof (permissions) / sizeof (permissions[0]) == N_REQUEST_TYPES);
Packit 96c956
  do_size_checks();
Packit 96c956
Packit 96c956
  initialised = 1;
Packit 96c956
  sock_fdu = -1;
Packit 96c956
  port_number = CNF_GetCommandPort();
Packit 96c956
Packit 96c956
  if (port_number && (family == IPADDR_UNSPEC || family == IPADDR_INET4))
Packit 96c956
    sock_fd4 = prepare_socket(AF_INET, port_number);
Packit 96c956
  else
Packit 96c956
    sock_fd4 = -1;
Packit 96c956
#ifdef FEAT_IPV6
Packit 96c956
  if (port_number && (family == IPADDR_UNSPEC || family == IPADDR_INET6))
Packit 96c956
    sock_fd6 = prepare_socket(AF_INET6, port_number);
Packit 96c956
  else
Packit 96c956
    sock_fd6 = -1;
Packit 96c956
#endif
Packit 96c956
Packit 96c956
  if (port_number && sock_fd4 < 0
Packit 96c956
#ifdef FEAT_IPV6
Packit 96c956
      && sock_fd6 < 0
Packit 96c956
#endif
Packit 96c956
      ) {
Packit 96c956
    LOG_FATAL("Could not open any command socket");
Packit 96c956
  }
Packit 96c956
Packit 96c956
  access_auth_table = ADF_CreateTable();
Packit 96c956
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
void
Packit 96c956
CAM_Finalise(void)
Packit 96c956
{
Packit 96c956
  if (sock_fdu >= 0) {
Packit 96c956
    SCH_RemoveFileHandler(sock_fdu);
Packit 96c956
    close(sock_fdu);
Packit 96c956
    unlink(CNF_GetBindCommandPath());
Packit 96c956
  }
Packit 96c956
  sock_fdu = -1;
Packit 96c956
  if (sock_fd4 >= 0) {
Packit 96c956
    SCH_RemoveFileHandler(sock_fd4);
Packit 96c956
    close(sock_fd4);
Packit 96c956
  }
Packit 96c956
  sock_fd4 = -1;
Packit 96c956
#ifdef FEAT_IPV6
Packit 96c956
  if (sock_fd6 >= 0) {
Packit 96c956
    SCH_RemoveFileHandler(sock_fd6);
Packit 96c956
    close(sock_fd6);
Packit 96c956
  }
Packit 96c956
  sock_fd6 = -1;
Packit 96c956
#endif
Packit 96c956
Packit 96c956
  ADF_DestroyTable(access_auth_table);
Packit 96c956
Packit 96c956
  initialised = 0;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
void
Packit 96c956
CAM_OpenUnixSocket(void)
Packit 96c956
{
Packit 96c956
  /* This is separated from CAM_Initialise() as it needs to be called when
Packit 96c956
     the process has already dropped the root privileges */
Packit 96c956
  if (CNF_GetBindCommandPath()[0])
Packit 96c956
    sock_fdu = prepare_socket(AF_UNIX, 0);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
transmit_reply(CMD_Reply *msg, union sockaddr_all *where_to)
Packit 96c956
{
Packit 96c956
  int status;
Packit 96c956
  int tx_message_length;
Packit 96c956
  int sock_fd;
Packit 96c956
  socklen_t addrlen;
Packit 96c956
Packit 96c956
  switch (where_to->sa.sa_family) {
Packit 96c956
    case AF_INET:
Packit 96c956
      sock_fd = sock_fd4;
Packit 96c956
      addrlen = sizeof (where_to->in4);
Packit 96c956
      break;
Packit 96c956
#ifdef FEAT_IPV6
Packit 96c956
    case AF_INET6:
Packit 96c956
      sock_fd = sock_fd6;
Packit 96c956
      addrlen = sizeof (where_to->in6);
Packit 96c956
      break;
Packit 96c956
#endif
Packit 96c956
    case AF_UNIX:
Packit 96c956
      sock_fd = sock_fdu;
Packit 96c956
      addrlen = sizeof (where_to->un);
Packit 96c956
      break;
Packit 96c956
    default:
Packit 96c956
      assert(0);
Packit 96c956
  }
Packit 96c956
Packit 96c956
  tx_message_length = PKL_ReplyLength(msg);
Packit 96c956
  status = sendto(sock_fd, (void *) msg, tx_message_length, 0,
Packit 96c956
                  &where_to->sa, addrlen);
Packit 96c956
Packit 96c956
  if (status < 0) {
Packit 96c956
    DEBUG_LOG("Could not send to %s fd %d : %s",
Packit 96c956
              UTI_SockaddrToString(&where_to->sa), sock_fd, strerror(errno));
Packit 96c956
    return;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  DEBUG_LOG("Sent %d bytes to %s fd %d", status,
Packit 96c956
            UTI_SockaddrToString(&where_to->sa), sock_fd);
Packit 96c956
}
Packit 96c956
  
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_dump(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  SRC_DumpSources();
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_online(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  IPAddr address, mask;
Packit 96c956
Packit 96c956
  UTI_IPNetworkToHost(&rx_message->data.online.mask, &mask);
Packit 96c956
  UTI_IPNetworkToHost(&rx_message->data.online.address, &address);
Packit 96c956
  if (!NSR_SetConnectivity(&mask, &address, SRC_ONLINE))
Packit 96c956
    tx_message->status = htons(STT_NOSUCHSOURCE);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_offline(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  IPAddr address, mask;
Packit 96c956
Packit 96c956
  UTI_IPNetworkToHost(&rx_message->data.offline.mask, &mask);
Packit 96c956
  UTI_IPNetworkToHost(&rx_message->data.offline.address, &address);
Packit 96c956
  if (!NSR_SetConnectivity(&mask, &address, SRC_OFFLINE))
Packit 96c956
    tx_message->status = htons(STT_NOSUCHSOURCE);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_onoffline(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  IPAddr address, mask;
Packit 96c956
Packit 96c956
  address.family = mask.family = IPADDR_UNSPEC;
Packit 96c956
  if (!NSR_SetConnectivity(&mask, &address, SRC_MAYBE_ONLINE))
Packit 96c956
    ;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_burst(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  IPAddr address, mask;
Packit 96c956
Packit 96c956
  UTI_IPNetworkToHost(&rx_message->data.burst.mask, &mask);
Packit 96c956
  UTI_IPNetworkToHost(&rx_message->data.burst.address, &address);
Packit 96c956
  if (!NSR_InitiateSampleBurst(ntohl(rx_message->data.burst.n_good_samples),
Packit 96c956
                               ntohl(rx_message->data.burst.n_total_samples),
Packit 96c956
                               &mask, &address))
Packit 96c956
    tx_message->status = htons(STT_NOSUCHSOURCE);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_modify_minpoll(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  IPAddr address;
Packit 96c956
Packit 96c956
  UTI_IPNetworkToHost(&rx_message->data.modify_minpoll.address, &address);
Packit 96c956
  if (!NSR_ModifyMinpoll(&address,
Packit 96c956
                         ntohl(rx_message->data.modify_minpoll.new_minpoll)))
Packit 96c956
    tx_message->status = htons(STT_NOSUCHSOURCE);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_modify_maxpoll(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  IPAddr address;
Packit 96c956
Packit 96c956
  UTI_IPNetworkToHost(&rx_message->data.modify_minpoll.address, &address);
Packit 96c956
  if (!NSR_ModifyMaxpoll(&address,
Packit 96c956
                         ntohl(rx_message->data.modify_minpoll.new_minpoll)))
Packit 96c956
    tx_message->status = htons(STT_NOSUCHSOURCE);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_modify_maxdelay(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  IPAddr address;
Packit 96c956
Packit 96c956
  UTI_IPNetworkToHost(&rx_message->data.modify_maxdelay.address, &address);
Packit 96c956
  if (!NSR_ModifyMaxdelay(&address,
Packit 96c956
        UTI_FloatNetworkToHost(rx_message->data.modify_maxdelay.new_max_delay)))
Packit 96c956
    tx_message->status = htons(STT_NOSUCHSOURCE);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_modify_maxdelayratio(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  IPAddr address;
Packit 96c956
Packit 96c956
  UTI_IPNetworkToHost(&rx_message->data.modify_maxdelayratio.address, &address);
Packit 96c956
  if (!NSR_ModifyMaxdelayratio(&address,
Packit 96c956
        UTI_FloatNetworkToHost(rx_message->data.modify_maxdelayratio.new_max_delay_ratio)))
Packit 96c956
    tx_message->status = htons(STT_NOSUCHSOURCE);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_modify_maxdelaydevratio(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  IPAddr address;
Packit 96c956
Packit 96c956
  UTI_IPNetworkToHost(&rx_message->data.modify_maxdelaydevratio.address, &address);
Packit 96c956
  if (!NSR_ModifyMaxdelaydevratio(&address,
Packit 96c956
        UTI_FloatNetworkToHost(rx_message->data.modify_maxdelaydevratio.new_max_delay_dev_ratio)))
Packit 96c956
    tx_message->status = htons(STT_NOSUCHSOURCE);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_modify_minstratum(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  IPAddr address;
Packit 96c956
Packit 96c956
  UTI_IPNetworkToHost(&rx_message->data.modify_minpoll.address, &address);
Packit 96c956
  if (!NSR_ModifyMinstratum(&address,
Packit 96c956
                            ntohl(rx_message->data.modify_minstratum.new_min_stratum)))
Packit 96c956
    tx_message->status = htons(STT_NOSUCHSOURCE);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_modify_polltarget(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  IPAddr address;
Packit 96c956
Packit 96c956
  UTI_IPNetworkToHost(&rx_message->data.modify_polltarget.address, &address);
Packit 96c956
  if (!NSR_ModifyPolltarget(&address,
Packit 96c956
                            ntohl(rx_message->data.modify_polltarget.new_poll_target)))
Packit 96c956
    tx_message->status = htons(STT_NOSUCHSOURCE);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_modify_maxupdateskew(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  REF_ModifyMaxupdateskew(UTI_FloatNetworkToHost(rx_message->data.modify_maxupdateskew.new_max_update_skew));
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_modify_makestep(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  REF_ModifyMakestep(ntohl(rx_message->data.modify_makestep.limit),
Packit 96c956
                     UTI_FloatNetworkToHost(rx_message->data.modify_makestep.threshold));
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_settime(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  struct timespec ts;
Packit 96c956
  double offset, dfreq_ppm, new_afreq_ppm;
Packit 96c956
  UTI_TimespecNetworkToHost(&rx_message->data.settime.ts, &ts);
Packit 96c956
  if (!MNL_IsEnabled()) {
Packit 96c956
    tx_message->status = htons(STT_NOTENABLED);
Packit 96c956
  } else if (MNL_AcceptTimestamp(&ts, &offset, &dfreq_ppm, &new_afreq_ppm)) {
Packit 96c956
    tx_message->reply = htons(RPY_MANUAL_TIMESTAMP2);
Packit 96c956
    tx_message->data.manual_timestamp.offset = UTI_FloatHostToNetwork(offset);
Packit 96c956
    tx_message->data.manual_timestamp.dfreq_ppm = UTI_FloatHostToNetwork(dfreq_ppm);
Packit 96c956
    tx_message->data.manual_timestamp.new_afreq_ppm = UTI_FloatHostToNetwork(new_afreq_ppm);
Packit 96c956
  } else {
Packit 96c956
    tx_message->status = htons(STT_FAILED);
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_local(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  if (ntohl(rx_message->data.local.on_off)) {
Packit 96c956
    REF_EnableLocal(ntohl(rx_message->data.local.stratum),
Packit 96c956
                    UTI_FloatNetworkToHost(rx_message->data.local.distance),
Packit 96c956
                    ntohl(rx_message->data.local.orphan));
Packit 96c956
  } else {
Packit 96c956
    REF_DisableLocal();
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_manual(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  int option;
Packit 96c956
  option = ntohl(rx_message->data.manual.option);
Packit 96c956
  switch (option) {
Packit 96c956
    case 0:
Packit 96c956
      MNL_Disable();
Packit 96c956
      break;
Packit 96c956
    case 1:
Packit 96c956
      MNL_Enable();
Packit 96c956
      break;
Packit 96c956
    case 2:
Packit 96c956
      MNL_Reset();
Packit 96c956
      break;
Packit 96c956
    default:
Packit 96c956
      tx_message->status = htons(STT_INVALID);
Packit 96c956
      break;
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_n_sources(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  int n_sources;
Packit 96c956
  n_sources = SRC_ReadNumberOfSources();
Packit 96c956
  tx_message->reply = htons(RPY_N_SOURCES);
Packit 96c956
  tx_message->data.n_sources.n_sources = htonl(n_sources);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_source_data(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  RPT_SourceReport report;
Packit 96c956
  struct timespec now_corr;
Packit 96c956
Packit 96c956
  /* Get data */
Packit 96c956
  SCH_GetLastEventTime(&now_corr, NULL, NULL);
Packit 96c956
  if (SRC_ReportSource(ntohl(rx_message->data.source_data.index), &report, &now_corr)) {
Packit 96c956
    switch (SRC_GetType(ntohl(rx_message->data.source_data.index))) {
Packit 96c956
      case SRC_NTP:
Packit 96c956
        NSR_ReportSource(&report, &now_corr);
Packit 96c956
        break;
Packit 96c956
      case SRC_REFCLOCK:
Packit 96c956
        RCL_ReportSource(&report, &now_corr);
Packit 96c956
        break;
Packit 96c956
    }
Packit 96c956
    
Packit 96c956
    tx_message->reply  = htons(RPY_SOURCE_DATA);
Packit 96c956
    
Packit 96c956
    UTI_IPHostToNetwork(&report.ip_addr, &tx_message->data.source_data.ip_addr);
Packit 96c956
    tx_message->data.source_data.stratum = htons(report.stratum);
Packit 96c956
    tx_message->data.source_data.poll    = htons(report.poll);
Packit 96c956
    switch (report.state) {
Packit 96c956
      case RPT_SYNC:
Packit 96c956
        tx_message->data.source_data.state   = htons(RPY_SD_ST_SYNC);
Packit 96c956
        break;
Packit 96c956
      case RPT_UNREACH:
Packit 96c956
        tx_message->data.source_data.state   = htons(RPY_SD_ST_UNREACH);
Packit 96c956
        break;
Packit 96c956
      case RPT_FALSETICKER:
Packit 96c956
        tx_message->data.source_data.state   = htons(RPY_SD_ST_FALSETICKER);
Packit 96c956
        break;
Packit 96c956
      case RPT_JITTERY:
Packit 96c956
        tx_message->data.source_data.state   = htons(RPY_SD_ST_JITTERY);
Packit 96c956
        break;
Packit 96c956
      case RPT_CANDIDATE:
Packit 96c956
        tx_message->data.source_data.state   = htons(RPY_SD_ST_CANDIDATE);
Packit 96c956
        break;
Packit 96c956
      case RPT_OUTLIER:
Packit 96c956
        tx_message->data.source_data.state   = htons(RPY_SD_ST_OUTLIER);
Packit 96c956
        break;
Packit 96c956
    }
Packit 96c956
    switch (report.mode) {
Packit 96c956
      case RPT_NTP_CLIENT:
Packit 96c956
        tx_message->data.source_data.mode    = htons(RPY_SD_MD_CLIENT);
Packit 96c956
        break;
Packit 96c956
      case RPT_NTP_PEER:
Packit 96c956
        tx_message->data.source_data.mode    = htons(RPY_SD_MD_PEER);
Packit 96c956
        break;
Packit 96c956
      case RPT_LOCAL_REFERENCE:
Packit 96c956
        tx_message->data.source_data.mode    = htons(RPY_SD_MD_REF);
Packit 96c956
        break;
Packit 96c956
    }
Packit 96c956
    tx_message->data.source_data.flags =
Packit 96c956
                  htons((report.sel_options & SRC_SELECT_PREFER ? RPY_SD_FLAG_PREFER : 0) |
Packit 96c956
                        (report.sel_options & SRC_SELECT_NOSELECT ? RPY_SD_FLAG_NOSELECT : 0) |
Packit 96c956
                        (report.sel_options & SRC_SELECT_TRUST ? RPY_SD_FLAG_TRUST : 0) |
Packit 96c956
                        (report.sel_options & SRC_SELECT_REQUIRE ? RPY_SD_FLAG_REQUIRE : 0));
Packit 96c956
    tx_message->data.source_data.reachability = htons(report.reachability);
Packit 96c956
    tx_message->data.source_data.since_sample = htonl(report.latest_meas_ago);
Packit 96c956
    tx_message->data.source_data.orig_latest_meas = UTI_FloatHostToNetwork(report.orig_latest_meas);
Packit 96c956
    tx_message->data.source_data.latest_meas = UTI_FloatHostToNetwork(report.latest_meas);
Packit 96c956
    tx_message->data.source_data.latest_meas_err = UTI_FloatHostToNetwork(report.latest_meas_err);
Packit 96c956
  } else {
Packit 96c956
    tx_message->status = htons(STT_NOSUCHSOURCE);
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_rekey(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  KEY_Reload();
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_allowdeny(CMD_Request *rx_message, CMD_Reply *tx_message, int allow, int all)
Packit 96c956
{
Packit 96c956
  IPAddr ip;
Packit 96c956
  int subnet_bits;
Packit 96c956
Packit 96c956
  UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
Packit 96c956
  subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
Packit 96c956
  if (!NCR_AddAccessRestriction(&ip, subnet_bits, allow, all))
Packit 96c956
    tx_message->status = htons(STT_BADSUBNET);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_cmdallowdeny(CMD_Request *rx_message, CMD_Reply *tx_message, int allow, int all)
Packit 96c956
{
Packit 96c956
  IPAddr ip;
Packit 96c956
  int subnet_bits;
Packit 96c956
Packit 96c956
  UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
Packit 96c956
  subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
Packit 96c956
  if (!CAM_AddAccessRestriction(&ip, subnet_bits, allow, all))
Packit 96c956
    tx_message->status = htons(STT_BADSUBNET);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_accheck(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  IPAddr ip;
Packit 96c956
  UTI_IPNetworkToHost(&rx_message->data.ac_check.ip, &ip);
Packit 96c956
  if (NCR_CheckAccessRestriction(&ip)) {
Packit 96c956
    tx_message->status = htons(STT_ACCESSALLOWED);
Packit 96c956
  } else {
Packit 96c956
    tx_message->status = htons(STT_ACCESSDENIED);
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_cmdaccheck(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  IPAddr ip;
Packit 96c956
  UTI_IPNetworkToHost(&rx_message->data.ac_check.ip, &ip);
Packit 96c956
  if (CAM_CheckAccessRestriction(&ip)) {
Packit 96c956
    tx_message->status = htons(STT_ACCESSALLOWED);
Packit 96c956
  } else {
Packit 96c956
    tx_message->status = htons(STT_ACCESSDENIED);
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_add_source(NTP_Source_Type type, CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  NTP_Remote_Address rem_addr;
Packit 96c956
  SourceParameters params;
Packit 96c956
  NSR_Status status;
Packit 96c956
  
Packit 96c956
  UTI_IPNetworkToHost(&rx_message->data.ntp_source.ip_addr, &rem_addr.ip_addr);
Packit 96c956
  rem_addr.port = (unsigned short)(ntohl(rx_message->data.ntp_source.port));
Packit 96c956
  params.minpoll = ntohl(rx_message->data.ntp_source.minpoll);
Packit 96c956
  params.maxpoll = ntohl(rx_message->data.ntp_source.maxpoll);
Packit 96c956
  params.presend_minpoll = ntohl(rx_message->data.ntp_source.presend_minpoll);
Packit 96c956
  params.min_stratum = ntohl(rx_message->data.ntp_source.min_stratum);
Packit 96c956
  params.poll_target = ntohl(rx_message->data.ntp_source.poll_target);
Packit 96c956
  params.version = ntohl(rx_message->data.ntp_source.version);
Packit 96c956
  params.max_sources = ntohl(rx_message->data.ntp_source.max_sources);
Packit 96c956
  params.min_samples = ntohl(rx_message->data.ntp_source.min_samples);
Packit 96c956
  params.max_samples = ntohl(rx_message->data.ntp_source.max_samples);
Packit 96c956
  params.filter_length = ntohl(rx_message->data.ntp_source.filter_length);
Packit 96c956
  params.authkey = ntohl(rx_message->data.ntp_source.authkey);
Packit 96c956
  params.max_delay = UTI_FloatNetworkToHost(rx_message->data.ntp_source.max_delay);
Packit 96c956
  params.max_delay_ratio =
Packit 96c956
    UTI_FloatNetworkToHost(rx_message->data.ntp_source.max_delay_ratio);
Packit 96c956
  params.max_delay_dev_ratio =
Packit 96c956
    UTI_FloatNetworkToHost(rx_message->data.ntp_source.max_delay_dev_ratio);
Packit 96c956
  params.min_delay = UTI_FloatNetworkToHost(rx_message->data.ntp_source.min_delay);
Packit 96c956
  params.asymmetry = UTI_FloatNetworkToHost(rx_message->data.ntp_source.asymmetry);
Packit 96c956
  params.offset = UTI_FloatNetworkToHost(rx_message->data.ntp_source.offset);
Packit 96c956
Packit 96c956
  params.connectivity = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_ONLINE ?
Packit 96c956
                        SRC_ONLINE : SRC_OFFLINE;
Packit 96c956
  params.auto_offline = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_AUTOOFFLINE ? 1 : 0;
Packit 96c956
  params.iburst = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_IBURST ? 1 : 0;
Packit 96c956
  params.interleaved = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_INTERLEAVED ? 1 : 0;
Packit 96c956
  params.burst = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_BURST ? 1 : 0;
Packit 96c956
  params.sel_options =
Packit 96c956
    (ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_PREFER ? SRC_SELECT_PREFER : 0) |
Packit 96c956
    (ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_NOSELECT ? SRC_SELECT_NOSELECT : 0) |
Packit 96c956
    (ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_TRUST ? SRC_SELECT_TRUST : 0) |
Packit 96c956
    (ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_REQUIRE ? SRC_SELECT_REQUIRE : 0);
Packit 96c956
Packit 96c956
  status = NSR_AddSource(&rem_addr, type, &params);
Packit 96c956
  switch (status) {
Packit 96c956
    case NSR_Success:
Packit 96c956
      break;
Packit 96c956
    case NSR_AlreadyInUse:
Packit 96c956
      tx_message->status = htons(STT_SOURCEALREADYKNOWN);
Packit 96c956
      break;
Packit 96c956
    case NSR_TooManySources:
Packit 96c956
      tx_message->status = htons(STT_TOOMANYSOURCES);
Packit 96c956
      break;
Packit 96c956
    case NSR_InvalidAF:
Packit 96c956
      tx_message->status = htons(STT_INVALIDAF);
Packit 96c956
      break;
Packit 96c956
    case NSR_NoSuchSource:
Packit 96c956
      assert(0);
Packit 96c956
      break;
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_del_source(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  NTP_Remote_Address rem_addr;
Packit 96c956
  NSR_Status status;
Packit 96c956
  
Packit 96c956
  UTI_IPNetworkToHost(&rx_message->data.del_source.ip_addr, &rem_addr.ip_addr);
Packit 96c956
  rem_addr.port = 0;
Packit 96c956
  
Packit 96c956
  status = NSR_RemoveSource(&rem_addr);
Packit 96c956
  switch (status) {
Packit 96c956
    case NSR_Success:
Packit 96c956
      break;
Packit 96c956
    case NSR_NoSuchSource:
Packit 96c956
      tx_message->status = htons(STT_NOSUCHSOURCE);
Packit 96c956
      break;
Packit 96c956
    case NSR_TooManySources:
Packit 96c956
    case NSR_AlreadyInUse:
Packit 96c956
    case NSR_InvalidAF:
Packit 96c956
      assert(0);
Packit 96c956
      break;
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_writertc(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  switch (RTC_WriteParameters()) {
Packit 96c956
    case RTC_ST_OK:
Packit 96c956
      break;
Packit 96c956
    case RTC_ST_NODRV:
Packit 96c956
      tx_message->status = htons(STT_NORTC);
Packit 96c956
      break;
Packit 96c956
    case RTC_ST_BADFILE:
Packit 96c956
      tx_message->status = htons(STT_BADRTCFILE);
Packit 96c956
      break;
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_dfreq(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  double dfreq;
Packit 96c956
  dfreq = UTI_FloatNetworkToHost(rx_message->data.dfreq.dfreq);
Packit 96c956
  LCL_AccumulateDeltaFrequency(dfreq * 1.0e-6);
Packit 96c956
  LOG(LOGS_INFO, "Accumulated delta freq of %.3fppm", dfreq);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_doffset(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  long sec, usec;
Packit 96c956
  double doffset;
Packit 96c956
  sec = (int32_t)ntohl(rx_message->data.doffset.sec);
Packit 96c956
  usec = (int32_t)ntohl(rx_message->data.doffset.usec);
Packit 96c956
  doffset = (double) sec + 1.0e-6 * (double) usec;
Packit 96c956
  LOG(LOGS_INFO, "Accumulated delta offset of %.6f seconds", doffset);
Packit 96c956
  LCL_AccumulateOffset(doffset, 0.0);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_tracking(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  RPT_TrackingReport rpt;
Packit 96c956
Packit 96c956
  REF_GetTrackingReport(&rpt;;
Packit 96c956
  tx_message->reply  = htons(RPY_TRACKING);
Packit 96c956
  tx_message->data.tracking.ref_id = htonl(rpt.ref_id);
Packit 96c956
  UTI_IPHostToNetwork(&rpt.ip_addr, &tx_message->data.tracking.ip_addr);
Packit 96c956
  tx_message->data.tracking.stratum = htons(rpt.stratum);
Packit 96c956
  tx_message->data.tracking.leap_status = htons(rpt.leap_status);
Packit 96c956
  UTI_TimespecHostToNetwork(&rpt.ref_time, &tx_message->data.tracking.ref_time);
Packit 96c956
  tx_message->data.tracking.current_correction = UTI_FloatHostToNetwork(rpt.current_correction);
Packit 96c956
  tx_message->data.tracking.last_offset = UTI_FloatHostToNetwork(rpt.last_offset);
Packit 96c956
  tx_message->data.tracking.rms_offset = UTI_FloatHostToNetwork(rpt.rms_offset);
Packit 96c956
  tx_message->data.tracking.freq_ppm = UTI_FloatHostToNetwork(rpt.freq_ppm);
Packit 96c956
  tx_message->data.tracking.resid_freq_ppm = UTI_FloatHostToNetwork(rpt.resid_freq_ppm);
Packit 96c956
  tx_message->data.tracking.skew_ppm = UTI_FloatHostToNetwork(rpt.skew_ppm);
Packit 96c956
  tx_message->data.tracking.root_delay = UTI_FloatHostToNetwork(rpt.root_delay);
Packit 96c956
  tx_message->data.tracking.root_dispersion = UTI_FloatHostToNetwork(rpt.root_dispersion);
Packit 96c956
  tx_message->data.tracking.last_update_interval = UTI_FloatHostToNetwork(rpt.last_update_interval);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_smoothing(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  RPT_SmoothingReport report;
Packit 96c956
  struct timespec now;
Packit 96c956
Packit 96c956
  SCH_GetLastEventTime(&now, NULL, NULL);
Packit 96c956
Packit 96c956
  if (!SMT_GetSmoothingReport(&report, &now)) {
Packit 96c956
    tx_message->status = htons(STT_NOTENABLED);
Packit 96c956
    return;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  tx_message->reply  = htons(RPY_SMOOTHING);
Packit 96c956
  tx_message->data.smoothing.flags = htonl((report.active ? RPY_SMT_FLAG_ACTIVE : 0) |
Packit 96c956
                                           (report.leap_only ? RPY_SMT_FLAG_LEAPONLY : 0));
Packit 96c956
  tx_message->data.smoothing.offset = UTI_FloatHostToNetwork(report.offset);
Packit 96c956
  tx_message->data.smoothing.freq_ppm = UTI_FloatHostToNetwork(report.freq_ppm);
Packit 96c956
  tx_message->data.smoothing.wander_ppm = UTI_FloatHostToNetwork(report.wander_ppm);
Packit 96c956
  tx_message->data.smoothing.last_update_ago = UTI_FloatHostToNetwork(report.last_update_ago);
Packit 96c956
  tx_message->data.smoothing.remaining_time = UTI_FloatHostToNetwork(report.remaining_time);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_smoothtime(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  struct timespec now;
Packit 96c956
  int option;
Packit 96c956
Packit 96c956
  if (!SMT_IsEnabled()) {
Packit 96c956
    tx_message->status = htons(STT_NOTENABLED);
Packit 96c956
    return;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  option = ntohl(rx_message->data.smoothtime.option);
Packit 96c956
  SCH_GetLastEventTime(&now, NULL, NULL);
Packit 96c956
Packit 96c956
  switch (option) {
Packit 96c956
    case REQ_SMOOTHTIME_RESET:
Packit 96c956
      SMT_Reset(&now;;
Packit 96c956
      break;
Packit 96c956
    case REQ_SMOOTHTIME_ACTIVATE:
Packit 96c956
      SMT_Activate(&now;;
Packit 96c956
      break;
Packit 96c956
    default:
Packit 96c956
      tx_message->status = htons(STT_INVALID);
Packit 96c956
      break;
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_sourcestats(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  int status;
Packit 96c956
  RPT_SourcestatsReport report;
Packit 96c956
  struct timespec now_corr;
Packit 96c956
Packit 96c956
  SCH_GetLastEventTime(&now_corr, NULL, NULL);
Packit 96c956
  status = SRC_ReportSourcestats(ntohl(rx_message->data.sourcestats.index),
Packit 96c956
                                 &report, &now_corr);
Packit 96c956
Packit 96c956
  if (status) {
Packit 96c956
    tx_message->reply = htons(RPY_SOURCESTATS);
Packit 96c956
    tx_message->data.sourcestats.ref_id = htonl(report.ref_id);
Packit 96c956
    UTI_IPHostToNetwork(&report.ip_addr, &tx_message->data.sourcestats.ip_addr);
Packit 96c956
    tx_message->data.sourcestats.n_samples = htonl(report.n_samples);
Packit 96c956
    tx_message->data.sourcestats.n_runs = htonl(report.n_runs);
Packit 96c956
    tx_message->data.sourcestats.span_seconds = htonl(report.span_seconds);
Packit 96c956
    tx_message->data.sourcestats.resid_freq_ppm = UTI_FloatHostToNetwork(report.resid_freq_ppm);
Packit 96c956
    tx_message->data.sourcestats.skew_ppm = UTI_FloatHostToNetwork(report.skew_ppm);
Packit 96c956
    tx_message->data.sourcestats.sd = UTI_FloatHostToNetwork(report.sd);
Packit 96c956
    tx_message->data.sourcestats.est_offset = UTI_FloatHostToNetwork(report.est_offset);
Packit 96c956
    tx_message->data.sourcestats.est_offset_err = UTI_FloatHostToNetwork(report.est_offset_err);
Packit 96c956
  } else {
Packit 96c956
    tx_message->status = htons(STT_NOSUCHSOURCE);
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_rtcreport(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  int status;
Packit 96c956
  RPT_RTC_Report report;
Packit 96c956
  status = RTC_GetReport(&report);
Packit 96c956
  if (status) {
Packit 96c956
    tx_message->reply  = htons(RPY_RTC);
Packit 96c956
    UTI_TimespecHostToNetwork(&report.ref_time, &tx_message->data.rtc.ref_time);
Packit 96c956
    tx_message->data.rtc.n_samples = htons(report.n_samples);
Packit 96c956
    tx_message->data.rtc.n_runs = htons(report.n_runs);
Packit 96c956
    tx_message->data.rtc.span_seconds = htonl(report.span_seconds);
Packit 96c956
    tx_message->data.rtc.rtc_seconds_fast = UTI_FloatHostToNetwork(report.rtc_seconds_fast);
Packit 96c956
    tx_message->data.rtc.rtc_gain_rate_ppm = UTI_FloatHostToNetwork(report.rtc_gain_rate_ppm);
Packit 96c956
  } else {
Packit 96c956
    tx_message->status = htons(STT_NORTC);
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_trimrtc(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  if (!RTC_Trim())
Packit 96c956
    tx_message->status = htons(STT_NORTC);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_cyclelogs(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  LOG_CycleLogFiles();
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_client_accesses_by_index(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  RPT_ClientAccessByIndex_Report report;
Packit 96c956
  RPY_ClientAccesses_Client *client;
Packit 96c956
  int n_indices;
Packit 96c956
  uint32_t i, j, req_first_index, req_n_clients;
Packit 96c956
  struct timespec now;
Packit 96c956
Packit 96c956
  SCH_GetLastEventTime(&now, NULL, NULL);
Packit 96c956
Packit 96c956
  req_first_index = ntohl(rx_message->data.client_accesses_by_index.first_index);
Packit 96c956
  req_n_clients = ntohl(rx_message->data.client_accesses_by_index.n_clients);
Packit 96c956
  if (req_n_clients > MAX_CLIENT_ACCESSES)
Packit 96c956
    req_n_clients = MAX_CLIENT_ACCESSES;
Packit 96c956
Packit 96c956
  n_indices = CLG_GetNumberOfIndices();
Packit 96c956
  if (n_indices < 0) {
Packit 96c956
    tx_message->status = htons(STT_INACTIVE);
Packit 96c956
    return;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  tx_message->reply = htons(RPY_CLIENT_ACCESSES_BY_INDEX2);
Packit 96c956
  tx_message->data.client_accesses_by_index.n_indices = htonl(n_indices);
Packit 96c956
Packit 96c956
  for (i = req_first_index, j = 0; i < (uint32_t)n_indices && j < req_n_clients; i++) {
Packit 96c956
    if (!CLG_GetClientAccessReportByIndex(i, &report, &now))
Packit 96c956
      continue;
Packit 96c956
Packit 96c956
    client = &tx_message->data.client_accesses_by_index.clients[j++];
Packit 96c956
Packit 96c956
    UTI_IPHostToNetwork(&report.ip_addr, &client->ip);
Packit 96c956
    client->ntp_hits = htonl(report.ntp_hits);
Packit 96c956
    client->cmd_hits = htonl(report.cmd_hits);
Packit 96c956
    client->ntp_drops = htonl(report.ntp_drops);
Packit 96c956
    client->cmd_drops = htonl(report.cmd_drops);
Packit 96c956
    client->ntp_interval = report.ntp_interval;
Packit 96c956
    client->cmd_interval = report.cmd_interval;
Packit 96c956
    client->ntp_timeout_interval = report.ntp_timeout_interval;
Packit 96c956
    client->last_ntp_hit_ago = htonl(report.last_ntp_hit_ago);
Packit 96c956
    client->last_cmd_hit_ago = htonl(report.last_cmd_hit_ago);
Packit 96c956
  }
Packit 96c956
Packit 96c956
  tx_message->data.client_accesses_by_index.next_index = htonl(i);
Packit 96c956
  tx_message->data.client_accesses_by_index.n_clients = htonl(j);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_manual_list(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  int n_samples;
Packit 96c956
  int i;
Packit 96c956
  RPY_ManualListSample *sample;
Packit 96c956
  RPT_ManualSamplesReport report[MAX_MANUAL_LIST_SAMPLES];
Packit 96c956
Packit 96c956
  tx_message->reply = htons(RPY_MANUAL_LIST2);
Packit 96c956
  
Packit 96c956
  MNL_ReportSamples(report, MAX_MANUAL_LIST_SAMPLES, &n_samples);
Packit 96c956
  tx_message->data.manual_list.n_samples = htonl(n_samples);
Packit 96c956
Packit 96c956
  for (i=0; i
Packit 96c956
    sample = &tx_message->data.manual_list.samples[i];
Packit 96c956
    UTI_TimespecHostToNetwork(&report[i].when, &sample->when);
Packit 96c956
    sample->slewed_offset = UTI_FloatHostToNetwork(report[i].slewed_offset);
Packit 96c956
    sample->orig_offset = UTI_FloatHostToNetwork(report[i].orig_offset);
Packit 96c956
    sample->residual = UTI_FloatHostToNetwork(report[i].residual);
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_manual_delete(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  int index;
Packit 96c956
Packit 96c956
  index = ntohl(rx_message->data.manual_delete.index);
Packit 96c956
  if (!MNL_DeleteSample(index))
Packit 96c956
    tx_message->status = htons(STT_BADSAMPLE);
Packit 96c956
}  
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_make_step(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  if (!LCL_MakeStep())
Packit 96c956
    tx_message->status = htons(STT_FAILED);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_activity(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  RPT_ActivityReport report;
Packit 96c956
  NSR_GetActivityReport(&report);
Packit 96c956
  tx_message->data.activity.online = htonl(report.online);
Packit 96c956
  tx_message->data.activity.offline = htonl(report.offline);
Packit 96c956
  tx_message->data.activity.burst_online = htonl(report.burst_online);
Packit 96c956
  tx_message->data.activity.burst_offline = htonl(report.burst_offline);
Packit 96c956
  tx_message->data.activity.unresolved = htonl(report.unresolved);
Packit 96c956
  tx_message->reply = htons(RPY_ACTIVITY);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_reselect_distance(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  double dist;
Packit 96c956
  dist = UTI_FloatNetworkToHost(rx_message->data.reselect_distance.distance);
Packit 96c956
  SRC_SetReselectDistance(dist);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_reselect(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  SRC_ReselectSource();
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_refresh(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  NSR_RefreshAddresses();
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_server_stats(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  RPT_ServerStatsReport report;
Packit 96c956
Packit 96c956
  CLG_GetServerStatsReport(&report);
Packit 96c956
  tx_message->reply = htons(RPY_SERVER_STATS);
Packit 96c956
  tx_message->data.server_stats.ntp_hits = htonl(report.ntp_hits);
Packit 96c956
  tx_message->data.server_stats.cmd_hits = htonl(report.cmd_hits);
Packit 96c956
  tx_message->data.server_stats.ntp_drops = htonl(report.ntp_drops);
Packit 96c956
  tx_message->data.server_stats.cmd_drops = htonl(report.cmd_drops);
Packit 96c956
  tx_message->data.server_stats.log_drops = htonl(report.log_drops);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_ntp_data(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  RPT_NTPReport report;
Packit 96c956
Packit 96c956
  UTI_IPNetworkToHost(&rx_message->data.ntp_data.ip_addr, &report.remote_addr);
Packit 96c956
Packit 96c956
  if (!NSR_GetNTPReport(&report)) {
Packit 96c956
    tx_message->status = htons(STT_NOSUCHSOURCE);
Packit 96c956
    return;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  tx_message->reply = htons(RPY_NTP_DATA);
Packit 96c956
  UTI_IPHostToNetwork(&report.remote_addr, &tx_message->data.ntp_data.remote_addr);
Packit 96c956
  UTI_IPHostToNetwork(&report.local_addr, &tx_message->data.ntp_data.local_addr);
Packit 96c956
  tx_message->data.ntp_data.remote_port = htons(report.remote_port);
Packit 96c956
  tx_message->data.ntp_data.leap = report.leap;
Packit 96c956
  tx_message->data.ntp_data.version = report.version;
Packit 96c956
  tx_message->data.ntp_data.mode = report.mode;
Packit 96c956
  tx_message->data.ntp_data.stratum = report.stratum;
Packit 96c956
  tx_message->data.ntp_data.poll = report.poll;
Packit 96c956
  tx_message->data.ntp_data.precision = report.precision;
Packit 96c956
  tx_message->data.ntp_data.root_delay = UTI_FloatHostToNetwork(report.root_delay);
Packit 96c956
  tx_message->data.ntp_data.root_dispersion = UTI_FloatHostToNetwork(report.root_dispersion);
Packit 96c956
  tx_message->data.ntp_data.ref_id = htonl(report.ref_id);
Packit 96c956
  UTI_TimespecHostToNetwork(&report.ref_time, &tx_message->data.ntp_data.ref_time);
Packit 96c956
  tx_message->data.ntp_data.offset = UTI_FloatHostToNetwork(report.offset);
Packit 96c956
  tx_message->data.ntp_data.peer_delay = UTI_FloatHostToNetwork(report.peer_delay);
Packit 96c956
  tx_message->data.ntp_data.peer_dispersion = UTI_FloatHostToNetwork(report.peer_dispersion);
Packit 96c956
  tx_message->data.ntp_data.response_time = UTI_FloatHostToNetwork(report.response_time);
Packit 96c956
  tx_message->data.ntp_data.jitter_asymmetry = UTI_FloatHostToNetwork(report.jitter_asymmetry);
Packit 96c956
  tx_message->data.ntp_data.flags = htons((report.tests & RPY_NTP_FLAGS_TESTS) |
Packit 96c956
                                          (report.interleaved ? RPY_NTP_FLAG_INTERLEAVED : 0) |
Packit 96c956
                                          (report.authenticated ? RPY_NTP_FLAG_AUTHENTICATED : 0));
Packit 96c956
  tx_message->data.ntp_data.tx_tss_char = report.tx_tss_char;
Packit 96c956
  tx_message->data.ntp_data.rx_tss_char = report.rx_tss_char;
Packit 96c956
  tx_message->data.ntp_data.total_tx_count = htonl(report.total_tx_count);
Packit 96c956
  tx_message->data.ntp_data.total_rx_count = htonl(report.total_rx_count);
Packit 96c956
  tx_message->data.ntp_data.total_valid_count = htonl(report.total_valid_count);
Packit 96c956
  memset(tx_message->data.ntp_data.reserved, 0xff, sizeof (tx_message->data.ntp_data.reserved));
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void
Packit 96c956
handle_shutdown(CMD_Request *rx_message, CMD_Reply *tx_message)
Packit 96c956
{
Packit 96c956
  LOG(LOGS_INFO, "Received shutdown command");
Packit 96c956
  SCH_QuitProgram();
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
/* Read a packet and process it */
Packit 96c956
Packit 96c956
static void
Packit 96c956
read_from_cmd_socket(int sock_fd, int event, void *anything)
Packit 96c956
{
Packit 96c956
  CMD_Request rx_message;
Packit 96c956
  CMD_Reply tx_message;
Packit 96c956
  int status, read_length, expected_length, rx_message_length;
Packit 96c956
  int localhost, allowed, log_index;
Packit 96c956
  union sockaddr_all where_from;
Packit 96c956
  socklen_t from_length;
Packit 96c956
  IPAddr remote_ip;
Packit 96c956
  unsigned short remote_port, rx_command;
Packit 96c956
  struct timespec now, cooked_now;
Packit 96c956
Packit 96c956
  rx_message_length = sizeof(rx_message);
Packit 96c956
  from_length = sizeof(where_from);
Packit 96c956
Packit 96c956
  status = recvfrom(sock_fd, (char *)&rx_message, rx_message_length, 0,
Packit 96c956
                    &where_from.sa, &from_length);
Packit 96c956
Packit 96c956
  if (status < 0) {
Packit 96c956
    LOG(LOGS_WARN, "Error [%s] reading from control socket %d",
Packit 96c956
        strerror(errno), sock_fd);
Packit 96c956
    return;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  if (from_length > sizeof (where_from) ||
Packit 96c956
      from_length <= sizeof (where_from.sa.sa_family)) {
Packit 96c956
    DEBUG_LOG("Read command packet without source address");
Packit 96c956
    return;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  read_length = status;
Packit 96c956
Packit 96c956
  /* Get current time cheaply */
Packit 96c956
  SCH_GetLastEventTime(&cooked_now, NULL, &now;;
Packit 96c956
Packit 96c956
  UTI_SockaddrToIPAndPort(&where_from.sa, &remote_ip, &remote_port);
Packit 96c956
Packit 96c956
  /* Check if it's from localhost (127.0.0.1, ::1, or Unix domain) */
Packit 96c956
  switch (remote_ip.family) {
Packit 96c956
    case IPADDR_INET4:
Packit 96c956
      assert(sock_fd == sock_fd4);
Packit 96c956
      localhost = remote_ip.addr.in4 == INADDR_LOOPBACK;
Packit 96c956
      break;
Packit 96c956
#ifdef FEAT_IPV6
Packit 96c956
    case IPADDR_INET6:
Packit 96c956
      assert(sock_fd == sock_fd6);
Packit 96c956
      localhost = !memcmp(remote_ip.addr.in6, &in6addr_loopback,
Packit 96c956
                          sizeof (in6addr_loopback));
Packit 96c956
      break;
Packit 96c956
#endif
Packit 96c956
    case IPADDR_UNSPEC:
Packit 96c956
      /* This should be the Unix domain socket */
Packit 96c956
      if (where_from.sa.sa_family != AF_UNIX)
Packit 96c956
        return;
Packit 96c956
      assert(sock_fd == sock_fdu);
Packit 96c956
      localhost = 1;
Packit 96c956
      break;
Packit 96c956
    default:
Packit 96c956
      assert(0);
Packit 96c956
  }
Packit 96c956
Packit 96c956
  DEBUG_LOG("Received %d bytes from %s fd %d",
Packit 96c956
            status, UTI_SockaddrToString(&where_from.sa), sock_fd);
Packit 96c956
Packit 96c956
  if (!(localhost || ADF_IsAllowed(access_auth_table, &remote_ip))) {
Packit 96c956
    /* The client is not allowed access, so don't waste any more time
Packit 96c956
       on him.  Note that localhost is always allowed access
Packit 96c956
       regardless of the defined access rules - otherwise, we could
Packit 96c956
       shut ourselves out completely! */
Packit 96c956
    return;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  if (read_length < offsetof(CMD_Request, data) ||
Packit 96c956
      read_length < offsetof(CMD_Reply, data) ||
Packit 96c956
      rx_message.pkt_type != PKT_TYPE_CMD_REQUEST ||
Packit 96c956
      rx_message.res1 != 0 ||
Packit 96c956
      rx_message.res2 != 0) {
Packit 96c956
Packit 96c956
    /* We don't know how to process anything like this or an error reply
Packit 96c956
       would be larger than the request */
Packit 96c956
    DEBUG_LOG("Command packet dropped");
Packit 96c956
    return;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  expected_length = PKL_CommandLength(&rx_message);
Packit 96c956
  rx_command = ntohs(rx_message.command);
Packit 96c956
Packit 96c956
  memset(&tx_message, 0, sizeof (tx_message));
Packit 96c956
Packit 96c956
  tx_message.version = PROTO_VERSION_NUMBER;
Packit 96c956
  tx_message.pkt_type = PKT_TYPE_CMD_REPLY;
Packit 96c956
  tx_message.command = rx_message.command;
Packit 96c956
  tx_message.reply = htons(RPY_NULL);
Packit 96c956
  tx_message.status = htons(STT_SUCCESS);
Packit 96c956
  tx_message.sequence = rx_message.sequence;
Packit 96c956
Packit 96c956
  if (rx_message.version != PROTO_VERSION_NUMBER) {
Packit 96c956
    DEBUG_LOG("Command packet has invalid version (%d != %d)",
Packit 96c956
              rx_message.version, PROTO_VERSION_NUMBER);
Packit 96c956
Packit 96c956
    if (rx_message.version >= PROTO_VERSION_MISMATCH_COMPAT_SERVER) {
Packit 96c956
      tx_message.status = htons(STT_BADPKTVERSION);
Packit 96c956
      transmit_reply(&tx_message, &where_from);
Packit 96c956
    }
Packit 96c956
    return;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  if (rx_command >= N_REQUEST_TYPES ||
Packit 96c956
      expected_length < (int)offsetof(CMD_Request, data)) {
Packit 96c956
    DEBUG_LOG("Command packet has invalid command %d", rx_command);
Packit 96c956
Packit 96c956
    tx_message.status = htons(STT_INVALID);
Packit 96c956
    transmit_reply(&tx_message, &where_from);
Packit 96c956
    return;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  if (read_length < expected_length) {
Packit 96c956
    DEBUG_LOG("Command packet is too short (%d < %d)", read_length,
Packit 96c956
              expected_length);
Packit 96c956
Packit 96c956
    tx_message.status = htons(STT_BADPKTLENGTH);
Packit 96c956
    transmit_reply(&tx_message, &where_from);
Packit 96c956
    return;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  /* OK, we have a valid message.  Now dispatch on message type and process it. */
Packit 96c956
Packit 96c956
  log_index = CLG_LogCommandAccess(&remote_ip, &cooked_now);
Packit 96c956
Packit 96c956
  /* Don't reply to all requests from hosts other than localhost if the rate
Packit 96c956
     is excessive */
Packit 96c956
  if (!localhost && log_index >= 0 && CLG_LimitCommandResponseRate(log_index)) {
Packit 96c956
      DEBUG_LOG("Command packet discarded to limit response rate");
Packit 96c956
      return;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  if (rx_command >= N_REQUEST_TYPES) {
Packit 96c956
    /* This should be already handled */
Packit 96c956
    assert(0);
Packit 96c956
  } else {
Packit 96c956
    /* Check level of authority required to issue the command.  All commands
Packit 96c956
       from the Unix domain socket (which is accessible only by the root and
Packit 96c956
       chrony user/group) are allowed. */
Packit 96c956
    if (where_from.sa.sa_family == AF_UNIX) {
Packit 96c956
      assert(sock_fd == sock_fdu);
Packit 96c956
      allowed = 1;
Packit 96c956
    } else {
Packit 96c956
      switch (permissions[rx_command]) {
Packit 96c956
        case PERMIT_AUTH:
Packit 96c956
          allowed = 0;
Packit 96c956
          break;
Packit 96c956
        case PERMIT_LOCAL:
Packit 96c956
          allowed = localhost;
Packit 96c956
          break;
Packit 96c956
        case PERMIT_OPEN:
Packit 96c956
          allowed = 1;
Packit 96c956
          break;
Packit 96c956
        default:
Packit 96c956
          assert(0);
Packit 96c956
          allowed = 0;
Packit 96c956
      }
Packit 96c956
    }
Packit 96c956
Packit 96c956
    if (allowed) {
Packit 96c956
      switch(rx_command) {
Packit 96c956
        case REQ_NULL:
Packit 96c956
          /* Do nothing */
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_DUMP:
Packit 96c956
          handle_dump(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_ONLINE:
Packit 96c956
          handle_online(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_OFFLINE:
Packit 96c956
          handle_offline(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_BURST:
Packit 96c956
          handle_burst(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_MODIFY_MINPOLL:
Packit 96c956
          handle_modify_minpoll(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_MODIFY_MAXPOLL:
Packit 96c956
          handle_modify_maxpoll(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_MODIFY_MAXDELAY:
Packit 96c956
          handle_modify_maxdelay(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_MODIFY_MAXDELAYRATIO:
Packit 96c956
          handle_modify_maxdelayratio(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_MODIFY_MAXDELAYDEVRATIO:
Packit 96c956
          handle_modify_maxdelaydevratio(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_MODIFY_MAXUPDATESKEW:
Packit 96c956
          handle_modify_maxupdateskew(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_MODIFY_MAKESTEP:
Packit 96c956
          handle_modify_makestep(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_LOGON:
Packit 96c956
          /* Authentication is no longer supported, log-on always fails */
Packit 96c956
          tx_message.status = htons(STT_FAILED);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_SETTIME:
Packit 96c956
          handle_settime(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
        
Packit 96c956
        case REQ_LOCAL2:
Packit 96c956
          handle_local(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_MANUAL:
Packit 96c956
          handle_manual(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_N_SOURCES:
Packit 96c956
          handle_n_sources(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_SOURCE_DATA:
Packit 96c956
          handle_source_data(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_REKEY:
Packit 96c956
          handle_rekey(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_ALLOW:
Packit 96c956
          handle_allowdeny(&rx_message, &tx_message, 1, 0);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_ALLOWALL:
Packit 96c956
          handle_allowdeny(&rx_message, &tx_message, 1, 1);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_DENY:
Packit 96c956
          handle_allowdeny(&rx_message, &tx_message, 0, 0);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_DENYALL:
Packit 96c956
          handle_allowdeny(&rx_message, &tx_message, 0, 1);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_CMDALLOW:
Packit 96c956
          handle_cmdallowdeny(&rx_message, &tx_message, 1, 0);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_CMDALLOWALL:
Packit 96c956
          handle_cmdallowdeny(&rx_message, &tx_message, 1, 1);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_CMDDENY:
Packit 96c956
          handle_cmdallowdeny(&rx_message, &tx_message, 0, 0);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_CMDDENYALL:
Packit 96c956
          handle_cmdallowdeny(&rx_message, &tx_message, 0, 1);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_ACCHECK:
Packit 96c956
          handle_accheck(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_CMDACCHECK:
Packit 96c956
          handle_cmdaccheck(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_ADD_SERVER3:
Packit 96c956
          handle_add_source(NTP_SERVER, &rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_ADD_PEER3:
Packit 96c956
          handle_add_source(NTP_PEER, &rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_DEL_SOURCE:
Packit 96c956
          handle_del_source(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_WRITERTC:
Packit 96c956
          handle_writertc(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
          
Packit 96c956
        case REQ_DFREQ:
Packit 96c956
          handle_dfreq(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_DOFFSET:
Packit 96c956
          handle_doffset(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_TRACKING:
Packit 96c956
          handle_tracking(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_SMOOTHING:
Packit 96c956
          handle_smoothing(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_SMOOTHTIME:
Packit 96c956
          handle_smoothtime(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_SOURCESTATS:
Packit 96c956
          handle_sourcestats(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_RTCREPORT:
Packit 96c956
          handle_rtcreport(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
          
Packit 96c956
        case REQ_TRIMRTC:
Packit 96c956
          handle_trimrtc(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_CYCLELOGS:
Packit 96c956
          handle_cyclelogs(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_CLIENT_ACCESSES_BY_INDEX2:
Packit 96c956
          handle_client_accesses_by_index(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_MANUAL_LIST:
Packit 96c956
          handle_manual_list(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_MANUAL_DELETE:
Packit 96c956
          handle_manual_delete(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_MAKESTEP:
Packit 96c956
          handle_make_step(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_ACTIVITY:
Packit 96c956
          handle_activity(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_RESELECTDISTANCE:
Packit 96c956
          handle_reselect_distance(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_RESELECT:
Packit 96c956
          handle_reselect(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_MODIFY_MINSTRATUM:
Packit 96c956
          handle_modify_minstratum(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_MODIFY_POLLTARGET:
Packit 96c956
          handle_modify_polltarget(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_REFRESH:
Packit 96c956
          handle_refresh(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_SERVER_STATS:
Packit 96c956
          handle_server_stats(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_NTP_DATA:
Packit 96c956
          handle_ntp_data(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_SHUTDOWN:
Packit 96c956
          handle_shutdown(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        case REQ_ONOFFLINE:
Packit 96c956
          handle_onoffline(&rx_message, &tx_message);
Packit 96c956
          break;
Packit 96c956
Packit 96c956
        default:
Packit 96c956
          DEBUG_LOG("Unhandled command %d", rx_command);
Packit 96c956
          tx_message.status = htons(STT_FAILED);
Packit 96c956
          break;
Packit 96c956
      }
Packit 96c956
    } else {
Packit 96c956
      tx_message.status = htons(STT_UNAUTH);
Packit 96c956
    }
Packit 96c956
  }
Packit 96c956
Packit 96c956
  /* Transmit the response */
Packit 96c956
  {
Packit 96c956
    /* Include a simple way to lose one message in three to test resend */
Packit 96c956
Packit 96c956
    static int do_it=1;
Packit 96c956
Packit 96c956
    if (do_it) {
Packit 96c956
      transmit_reply(&tx_message, &where_from);
Packit 96c956
    }
Packit 96c956
Packit 96c956
#if 0
Packit 96c956
    do_it = ((do_it + 1) % 3);
Packit 96c956
#endif
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
int
Packit 96c956
CAM_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all)
Packit 96c956
 {
Packit 96c956
  ADF_Status status;
Packit 96c956
Packit 96c956
  if (allow) {
Packit 96c956
    if (all) {
Packit 96c956
      status = ADF_AllowAll(access_auth_table, ip_addr, subnet_bits);
Packit 96c956
    } else {
Packit 96c956
      status = ADF_Allow(access_auth_table, ip_addr, subnet_bits);
Packit 96c956
    }
Packit 96c956
  } else {
Packit 96c956
    if (all) {
Packit 96c956
      status = ADF_DenyAll(access_auth_table, ip_addr, subnet_bits);
Packit 96c956
    } else {
Packit 96c956
      status = ADF_Deny(access_auth_table, ip_addr, subnet_bits);
Packit 96c956
    }
Packit 96c956
  }
Packit 96c956
Packit 96c956
  if (status == ADF_BADSUBNET) {
Packit 96c956
    return 0;
Packit 96c956
  } else if (status == ADF_SUCCESS) {
Packit 96c956
    return 1;
Packit 96c956
  } else {
Packit 96c956
    return 0;
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
int
Packit 96c956
CAM_CheckAccessRestriction(IPAddr *ip_addr)
Packit 96c956
{
Packit 96c956
  return ADF_IsAllowed(access_auth_table, ip_addr);
Packit 96c956
}
Packit 96c956
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
/* ================================================== */