Commit message: Fix buffer overflow when processing crafted command packets

When the length of the REQ_SUBNETS_ACCESSED, REQ_CLIENT_ACCESSES
command requests and the RPY_SUBNETS_ACCESSED, RPY_CLIENT_ACCESSES,
RPY_CLIENT_ACCESSES_BY_INDEX, RPY_MANUAL_LIST command replies is
calculated, the number of items stored in the packet is not validated.

A crafted command request/reply can be used to crash the server/client.
Only clients allowed by cmdallow (by default only localhost) can crash
the server.

With chrony versions 1.25 and 1.26 this bug has a smaller security
impact as the server requires the clients to be authenticated in order
to process the subnet and client accesses commands. In 1.27 and 1.28,
however, the invalid calculated length is included also in the
authentication check which may cause another crash.
CVE: CVE-2012-4502
CWE: CWE-189
Vulnerability description: Multiple integer overflows in pktlength.c in Chrony before 1.29 allow remote attackers to cause a denial of service (crash) via a crafted (1) REQ_SUBNETS_ACCESSED or (2) REQ_CLIENT_ACCESSES command request to the PKL_CommandLength function or crafted (3) RPY_SUBNETS_ACCESSED, (4) RPY_CLIENT_ACCESSES, (5) RPY_CLIENT_ACCESSES_BY_INDEX, or (6) RPY_MANUAL_LIST command reply to the PKL_ReplyLength function, which triggers an out-of-bounds read or buffer overflow.  NOTE: versions 1.27 and 1.28 do not require authentication to exploit.

Project: chrony

ts_is_unique_and_not_stale(struct timeval *ts, struct timeval *now)
{
  int within_margin=0;
  int is_unique=0;
  long diff;

  diff = now->tv_sec - ts->tv_sec;
  if ((diff < TS_MARGIN) && (diff > -TS_MARGIN)) {
    within_margin = 1;
  } else {
    within_margin = 0;
  }
  is_unique = check_unique_ts(ts, now);
    
  return within_margin && is_unique;
}

Project: chrony

handle_modify_maxupdateskew(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  REF_ModifyMaxupdateskew(UTI_FloatNetworkToHost(rx_message->data.modify_maxupdateskew.new_max_update_skew));
  tx_message->status = htons(STT_SUCCESS);
}

Project: chrony

process_cmd_password(CMD_Request *msg, char *line)
{
  char *p;
  struct timeval now;
  int i, len;

  /* Blank and free the old password */
  if (password) {
    for (i = 0; i < password_length; i++)
      password[i] = 0;
    free(password);
    password = NULL;
  }

  p = line;

  if (!*p) {
    /* blank line, prompt for password */
    p = getpass("Password: ");
  }

  if (!*p)
    return 0;

  len = strlen(p);
  password_length = UTI_DecodePasswordFromText(p);

  if (password_length > 0) {
    password = malloc(password_length);
    memcpy(password, p, password_length);
  }

  /* Erase the password from the input or getpass buffer */
  for (i = 0; i < len; i++)
    p[i] = 0;

  if (password_length <= 0) {
      fprintf(stderr, "Could not decode password\n");
      return 0;
  }

  if (gettimeofday(&now, NULL) < 0) {
    printf("500 - Could not read time of day\n");
    return 0;
  } else {
    msg->command = htons(REQ_LOGON); /* Just force a round trip so that we get tokens etc */
    UTI_TimevalHostToNetwork(&now, &msg->data.logon.ts);
    return 1;
  }
}

Project: chrony

process_cmd_sourcestats(char *line)
{
  CMD_Request request;
  CMD_Reply reply;
  int n_sources, i;
  int verbose = 0;

  char hostname_buf[50];
  unsigned long n_samples, n_runs, span_seconds;
  double resid_freq_ppm, skew_ppm, sd, est_offset;
  uint32_t ref_id;
  IPAddr ip_addr;

  verbose = check_for_verbose_flag(line);

  request.command = htons(REQ_N_SOURCES);
  if (request_reply(&request, &reply, RPY_N_SOURCES, 0)) {
    n_sources = ntohl(reply.data.n_sources.n_sources);
    printf("210 Number of sources = %d\n", n_sources);
    if (verbose) {
      printf("                             .- Number of sample points in measurement set.\n");
      printf("                            /    .- Number of residual runs with same sign.\n");
      printf("                           |    /    .- Length of measurement set (time).\n");
      printf("                           |   |    /      .- Est. clock freq error (ppm).\n");
      printf("                           |   |   |      /           .- Est. error in freq.\n");
      printf("                           |   |   |     |           /         .- Est. offset.\n");
      printf("                           |   |   |     |          |          |   On the -.\n");
      printf("                           |   |   |     |          |          |   samples. \\\n");
      printf("                           |   |   |     |          |          |             |\n");
    }

    printf("Name/IP Address            NP  NR  Span  Frequency  Freq Skew  Offset  Std Dev\n");
    printf("==============================================================================\n");

    /*      NNNNNNNNNNNNNNNNNNNNNNNNN  NP  NR  SSSS FFFFFFFFFF SSSSSSSSSS  SSSSSSS  SSSSSS*/

    for (i=0; i<n_sources; i++) {
      request.command = htons(REQ_SOURCESTATS);
      request.data.source_data.index = htonl(i);
      if (request_reply(&request, &reply, RPY_SOURCESTATS, 0)) {
          ref_id = ntohl(reply.data.sourcestats.ref_id);
          UTI_IPNetworkToHost(&reply.data.sourcestats.ip_addr, &ip_addr);
          n_samples = ntohl(reply.data.sourcestats.n_samples);
          n_runs = ntohl(reply.data.sourcestats.n_runs);
          span_seconds = ntohl(reply.data.sourcestats.span_seconds);
          resid_freq_ppm = UTI_FloatNetworkToHost(reply.data.sourcestats.resid_freq_ppm);
          skew_ppm = UTI_FloatNetworkToHost(reply.data.sourcestats.skew_ppm);
          sd = UTI_FloatNetworkToHost(reply.data.sourcestats.sd);
          est_offset = UTI_FloatNetworkToHost(reply.data.sourcestats.est_offset);
          /* est_offset_err = UTI_FloatNetworkToHost(reply.data.sourcestats.est_offset_err); */

          if (ip_addr.family == IPADDR_UNSPEC)
            snprintf(hostname_buf, sizeof(hostname_buf), "%s", UTI_RefidToString(ref_id));
          else if (no_dns) {
            snprintf(hostname_buf, sizeof(hostname_buf), "%s", UTI_IPToString(&ip_addr));
          } else {
            DNS_IPAddress2Name(&ip_addr, hostname_buf, sizeof(hostname_buf));
            hostname_buf[25] = 0;
          }

          printf("%-25s %3lu %3lu  ", hostname_buf, n_samples, n_runs);
          print_seconds(span_seconds);
          printf(" ");
          print_freq_ppm(resid_freq_ppm);
          printf(" ");
          print_freq_ppm(skew_ppm);
          printf("  ");
          print_signed_nanoseconds(est_offset);
          printf("  ");
          print_nanoseconds(sd);
          printf("\n");
      } else {
        return 0;
      }
    }
  } else {
    return 0;
  }
  return 1;
}

Project: chrony

read_address_double(char *line, IPAddr *address, double *value)
{
  char *hostname;
  int ok = 0;

  hostname = line;
  line = CPS_SplitWord(line);

  if (sscanf(line, "%lf", value) != 1) {
    fprintf(stderr, "Invalid syntax for address value\n");
    ok = 0;
  } else {
    if (DNS_Name2IPAddress(hostname, address) != DNS_Success) {
      fprintf(stderr, "Could not get address for hostname\n");
      ok = 0;
    } else {
      ok = 1;
    }
  }

  return ok;

}

Project: chrony

print_freq_ppm(double f)
{
  if (fabs(f) < 99999.5) {
    printf("%10.3f", f);
  } else {
    printf("%10.0f", f);
  }
}

Project: chrony

handle_deny(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  IPAddr ip;
  int subnet_bits;
  UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
  subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
  if (NCR_AddAccessRestriction(&ip, subnet_bits, 0, 0)) {
    tx_message->status = htons(STT_SUCCESS);
  } else {
    tx_message->status = htons(STT_BADSUBNET);
  }              
}

Project: chrony

process_cmd_minstratum(CMD_Request *msg, char *line)
{
  IPAddr address;
  int min_stratum;
  int ok;
  
  if (read_address_integer(line, &address, &min_stratum)) {
    UTI_IPHostToNetwork(&address, &msg->data.modify_minstratum.address);
    msg->data.modify_minstratum.new_min_stratum = htonl(min_stratum);
    msg->command = htons(REQ_MODIFY_MINSTRATUM);
    ok = 1;
  } else {
    ok = 0;
  }

  return ok;

}

Project: chrony

handle_modify_polltarget(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  int status;
  IPAddr address;
  UTI_IPNetworkToHost(&rx_message->data.modify_polltarget.address, &address);
  status = NSR_ModifyPolltarget(&address,
                             ntohl(rx_message->data.modify_polltarget.new_poll_target));
  
  if (status) {
    tx_message->status = htons(STT_SUCCESS);
  } else {
    tx_message->status = htons(STT_NOSUCHSOURCE);
  }
}

Project: chrony

get_reply_slot(void)
{
  ResponseCell *result;
  if (!free_replies) {
    get_more_replies();
  }
  result = free_replies;
  free_replies = result->next;
  return result;
}

Project: chrony

handle_writertc(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  switch (RTC_WriteParameters()) {
    case RTC_ST_OK:
      tx_message->status = htons(STT_SUCCESS);
      break;
    case RTC_ST_NODRV:
      tx_message->status = htons(STT_NORTC);
      break;
    case RTC_ST_BADFILE:
      tx_message->status = htons(STT_BADRTCFILE);
      break;
  }
}

Project: chrony

process_cmd_minpoll(CMD_Request *msg, char *line)
{
  IPAddr address;
  int minpoll;
  int ok;
  
  if (read_address_integer(line, &address, &minpoll)) {
    UTI_IPHostToNetwork(&address, &msg->data.modify_minpoll.address);
    msg->data.modify_minpoll.new_minpoll = htonl(minpoll);
    msg->command = htons(REQ_MODIFY_MINPOLL);
    ok = 1;
  } else {
    ok = 0;
  }

  return ok;

}

Project: chrony

process_cmd_makestep(CMD_Request *msg, char *line)
{
  msg->command = htons(REQ_MAKESTEP);
}

Project: chrony

process_cmd_polltarget(CMD_Request *msg, char *line)
{
  IPAddr address;
  int poll_target;
  int ok;
  
  if (read_address_integer(line, &address, &poll_target)) {
    UTI_IPHostToNetwork(&address, &msg->data.modify_polltarget.address);
    msg->data.modify_polltarget.new_poll_target = htonl(poll_target);
    msg->command = htons(REQ_MODIFY_POLLTARGET);
    ok = 1;
  } else {
    ok = 0;
  }

  return ok;

}

Project: chrony

process_cmd_writertc(CMD_Request *msg, char *line)
{
  msg->command = htons(REQ_WRITERTC);
}

Project: chrony

process_cmd_cyclelogs(CMD_Request *msg, char *line)
{
  msg->command = htons(REQ_CYCLELOGS);
}

Project: chrony

process_cmd_online(CMD_Request *msg, char *line)
{
  IPAddr mask, address;
  int ok;

  if (read_mask_address(line, &mask, &address)) {
    UTI_IPHostToNetwork(&mask, &msg->data.online.mask);
    UTI_IPHostToNetwork(&address, &msg->data.online.address);
    msg->command = htons(REQ_ONLINE);
    ok = 1;
  } else {
    ok = 0;
  }

  return ok;

}

Project: chrony

process_cmd_deny(CMD_Request *msg, char *line)
{
  int status;
  msg->command = htons(REQ_DENY);
  status = parse_allow_deny(msg, line);
  return status;
}

Project: chrony

process_cmd_maxdelay(CMD_Request *msg, char *line)
{
  IPAddr address;
  double max_delay;
  int ok;
  
  if (read_address_double(line, &address, &max_delay)) {
    UTI_IPHostToNetwork(&address, &msg->data.modify_maxdelay.address);
    msg->data.modify_maxdelay.new_max_delay = UTI_FloatHostToNetwork(max_delay);
    msg->command = htons(REQ_MODIFY_MAXDELAY);
    ok = 1;
  } else {
    ok = 0;
  }

  return ok;

}

Project: chrony

token_acknowledged(unsigned long token, struct timeval *now)
{
  ResponseCell *last_valid, *cell, *next;

  last_valid = &kept_replies;
  cell = kept_replies.next;
  
  while(cell) {
    next = cell->next;

    /* Discard if it's the one or if the reply is stale */
    if ((cell->next_tok == token) ||
        ((now->tv_sec - cell->ts.tv_sec) > REPLY_MAXAGE)) {
      free_reply_slot(cell);
      last_valid->next = next;
    } else {
      last_valid->next = cell;
      last_valid = cell;
    }
    cell = next;
  }
}

Project: chrony

handle_cmdallowall(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  IPAddr ip;
  int subnet_bits;
  UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
  subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
  if (CAM_AddAccessRestriction(&ip, subnet_bits, 1, 1)) {
    tx_message->status = htons(STT_SUCCESS);
  } else {
    tx_message->status = htons(STT_BADSUBNET);
  }              
}

Project: chrony

print_command_packet(CMD_Request *pkt, int length)
{
  unsigned char *x;
  int i;
  x = (unsigned char *) pkt;
  for (i=0; i<length; i++) {
    fprintf(stderr, "%02x ", x[i]);
    if (i%16 == 15) {
      fprintf(stderr, "\n");
    }
  }
  fprintf(stderr, "\n");
}

Project: chrony

process_cmd_burst(CMD_Request *msg, char *line)
{
  int n_good_samples, n_total_samples;
  char *s1, *s2;
  IPAddr address, mask;

  s1 = line;
  s2 = CPS_SplitWord(s1);
  CPS_SplitWord(s2);

  if (sscanf(s1, "%d/%d", &n_good_samples, &n_total_samples) != 2) {
    fprintf(stderr, "Invalid syntax for burst command\n");
    return 0;
  }

  mask.family = address.family = IPADDR_UNSPEC;
  if (*s2 && !read_mask_address(s2, &mask, &address)) {
    return 0;
  }

  msg->command = htons(REQ_BURST);
  msg->data.burst.n_good_samples = ntohl(n_good_samples);
  msg->data.burst.n_total_samples = ntohl(n_total_samples);

  UTI_IPHostToNetwork(&mask, &msg->data.burst.mask);
  UTI_IPHostToNetwork(&address, &msg->data.burst.address);

  return 1;
}

Project: chrony

process_cmd_maxpoll(CMD_Request *msg, char *line)
{
  IPAddr address;
  int maxpoll;
  int ok;
  
  if (read_address_integer(line, &address, &maxpoll)) {
    UTI_IPHostToNetwork(&address, &msg->data.modify_maxpoll.address);
    msg->data.modify_maxpoll.new_maxpoll = htonl(maxpoll);
    msg->command = htons(REQ_MODIFY_MAXPOLL);
    ok = 1;
  } else {
    ok = 0;
  }

  return ok;

}

Project: chrony

process_cmd_authhash(const char *line)
{
  const char *hash_name;
  int new_hash_id;

  assert(auth_hash_id >= 0);
  hash_name = line;

  if (!*hash_name) {
    fprintf(stderr, "Could not parse hash name\n");
    return 0;
  }

  new_hash_id = HSH_GetHashId(hash_name);
  if (new_hash_id < 0) {
    fprintf(stderr, "Unknown hash name: %s\n", hash_name);
    return 0;
  }

  auth_hash_id = new_hash_id;

  return 1;
}

Project: chrony

process_cmd_allow(CMD_Request *msg, char *line)
{
  int status;
  msg->command = htons(REQ_ALLOW);
  status = parse_allow_deny(msg, line);
  return status;
}

Project: chrony

handle_accheck(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  IPAddr ip;
  UTI_IPNetworkToHost(&rx_message->data.ac_check.ip, &ip);
  if (NCR_CheckAccessRestriction(&ip)) {
    tx_message->status = htons(STT_ACCESSALLOWED);
  } else {
    tx_message->status = htons(STT_ACCESSDENIED);
  }
}

Project: chrony

process_cmd_reselect(CMD_Request *msg, char *line)
{
  msg->command = htons(REQ_RESELECT);
}

Project: chrony

process_cmd_manual(CMD_Request *msg, const char *line)
{
  const char *p;

  p = line;

  if (!*p) {
    return 0;
  } else if (!strcmp(p, "off")) {
    msg->data.manual.option = htonl(0);
  } else if (!strcmp(p, "on")) {
    msg->data.manual.option = htonl(1);
  } else if (!strcmp(p, "reset")) {
    msg->data.manual.option = htonl(2);
  } else {
    return 0;
  }
  msg->command = htons(REQ_MANUAL);

  return 1;
}

Project: chrony

process_line(char *line, int *quit)
{
  char *command;
  int do_normal_submit;
  int ret;
  CMD_Request tx_message;
  CMD_Reply rx_message;

  *quit = 0;
  ret = 0;

  do_normal_submit = 1;

  CPS_NormalizeLine(line);

  if (!*line) {
    fflush(stderr);
    fflush(stdout);
    return 1;
  };

  command = line;
  line = CPS_SplitWord(line);

  if (!strcmp(command, "accheck")) {
    do_normal_submit = process_cmd_accheck(&tx_message, line);
  } else if (!strcmp(command, "activity")) {
    do_normal_submit = 0;
    ret = process_cmd_activity(line);
  } else if (!strcmp(command, "add") && !strncmp(line, "peer", 4)) {
    do_normal_submit = process_cmd_add_peer(&tx_message, CPS_SplitWord(line));
  } else if (!strcmp(command, "add") && !strncmp(line, "server", 6)) {
    do_normal_submit = process_cmd_add_server(&tx_message, CPS_SplitWord(line));
  } else if (!strcmp(command, "allow")) {
    if (!strncmp(line, "all", 3)) {
      do_normal_submit = process_cmd_allowall(&tx_message, CPS_SplitWord(line));
    } else {
      do_normal_submit = process_cmd_allow(&tx_message, line);
    }
  } else if (!strcmp(command, "authhash")) {
    ret = process_cmd_authhash(line);
    do_normal_submit = 0;
  } else if (!strcmp(command, "burst")) {
    do_normal_submit = process_cmd_burst(&tx_message, line);
  } else if (!strcmp(command, "clients")) {
    ret = process_cmd_clients(line);
    do_normal_submit = 0;
  } else if (!strcmp(command, "cmdaccheck")) {
    do_normal_submit = process_cmd_cmdaccheck(&tx_message, line);
  } else if (!strcmp(command, "cmdallow")) {
    if (!strncmp(line, "all", 3)) {
      do_normal_submit = process_cmd_cmdallowall(&tx_message, CPS_SplitWord(line));
    } else {
      do_normal_submit = process_cmd_cmdallow(&tx_message, line);
    }
  } else if (!strcmp(command, "cmddeny")) {
    if (!strncmp(line, "all", 3)) {
      line = CPS_SplitWord(line);
      do_normal_submit = process_cmd_cmddenyall(&tx_message, line);
    } else {
      do_normal_submit = process_cmd_cmddeny(&tx_message, line);
    }
  } else if (!strcmp(command, "cyclelogs")) {
    process_cmd_cyclelogs(&tx_message, line);
  } else if (!strcmp(command, "delete")) {
    do_normal_submit = process_cmd_delete(&tx_message, line);
  } else if (!strcmp(command, "deny")) {
    if (!strncmp(line, "all", 3)) {
      do_normal_submit = process_cmd_denyall(&tx_message, CPS_SplitWord(line));
    } else {
      do_normal_submit = process_cmd_deny(&tx_message, line);
    }
  } else if (!strcmp(command, "dfreq")) {
    process_cmd_dfreq(&tx_message, line);
  } else if (!strcmp(command, "dns")) {
    ret = process_cmd_dns(line);
    do_normal_submit = 0;
  } else if (!strcmp(command, "doffset")) {
    process_cmd_doffset(&tx_message, line);
  } else if (!strcmp(command, "dump")) {
    process_cmd_dump(&tx_message, line);
  } else if (!strcmp(command, "exit")) {
    do_normal_submit = 0;
    *quit = 1;
    ret = 1;
  } else if (!strcmp(command, "help")) {
    do_normal_submit = 0;
    give_help();
    ret = 1;
  } else if (!strcmp(command, "local")) {
    do_normal_submit = process_cmd_local(&tx_message, line);
  } else if (!strcmp(command, "makestep")) {
    process_cmd_makestep(&tx_message, line);
  } else if (!strcmp(command, "manual")) {
    if (!strncmp(line, "list", 4)) {
      do_normal_submit = 0;
      ret = process_cmd_manual_list(CPS_SplitWord(line));
    } else if (!strncmp(line, "delete", 6)) {
      do_normal_submit = process_cmd_manual_delete(&tx_message, CPS_SplitWord(line));
    } else {
      do_normal_submit = process_cmd_manual(&tx_message, line);
    }
  } else if (!strcmp(command, "maxdelay")) {
    do_normal_submit = process_cmd_maxdelay(&tx_message, line);
  } else if (!strcmp(command, "maxdelaydevratio")) {
    do_normal_submit = process_cmd_maxdelaydevratio(&tx_message, line);
  } else if (!strcmp(command, "maxdelayratio")) {
    do_normal_submit = process_cmd_maxdelayratio(&tx_message, line);
  } else if (!strcmp(command, "maxpoll")) {
    do_normal_submit = process_cmd_maxpoll(&tx_message, line);
  } else if (!strcmp(command, "maxupdateskew")) {
    do_normal_submit = process_cmd_maxupdateskew(&tx_message, line);
  } else if (!strcmp(command, "minpoll")) {
    do_normal_submit = process_cmd_minpoll(&tx_message, line);
  } else if (!strcmp(command, "minstratum")) {
    do_normal_submit = process_cmd_minstratum(&tx_message, line);
  } else if (!strcmp(command, "offline")) {
    do_normal_submit = process_cmd_offline(&tx_message, line);
  } else if (!strcmp(command, "online")) {
    do_normal_submit = process_cmd_online(&tx_message, line);
  } else if (!strcmp(command, "password")) {
    do_normal_submit = process_cmd_password(&tx_message, line);
  } else if (!strcmp(command, "polltarget")) {
    do_normal_submit = process_cmd_polltarget(&tx_message, line);
  } else if (!strcmp(command, "quit")) {
    do_normal_submit = 0;
    *quit = 1;
    ret = 1;
  } else if (!strcmp(command, "rekey")) {
    process_cmd_rekey(&tx_message, line);
  } else if (!strcmp(command, "reselect")) {
    process_cmd_reselect(&tx_message, line);
  } else if (!strcmp(command, "reselectdist")) {
    do_normal_submit = process_cmd_reselectdist(&tx_message, line);
  } else if (!strcmp(command, "retries")) {
    ret = process_cmd_retries(line);
    do_normal_submit = 0;
  } else if (!strcmp(command, "rtcdata")) {
    do_normal_submit = 0;
    ret = process_cmd_rtcreport(line);
  } else if (!strcmp(command, "settime")) {
    do_normal_submit = 0;
    ret = process_cmd_settime(line);
  } else if (!strcmp(command, "sources")) {
    do_normal_submit = 0;
    ret = process_cmd_sources(line);
  } else if (!strcmp(command, "sourcestats")) {
    do_normal_submit = 0;
    ret = process_cmd_sourcestats(line);
  } else if (!strcmp(command, "timeout")) {
    ret = process_cmd_timeout(line);
    do_normal_submit = 0;
  } else if (!strcmp(command, "tracking")) {
    ret = process_cmd_tracking(line);
    do_normal_submit = 0;
  } else if (!strcmp(command, "trimrtc")) {
    process_cmd_trimrtc(&tx_message, line);
  } else if (!strcmp(command, "waitsync")) {
    ret = process_cmd_waitsync(line);
    do_normal_submit = 0;
  } else if (!strcmp(command, "writertc")) {
    process_cmd_writertc(&tx_message, line);
  } else {
    fprintf(stderr, "Unrecognized command\n");
    do_normal_submit = 0;
  }
    
  if (do_normal_submit) {
    ret = request_reply(&tx_message, &rx_message, RPY_NULL, 1);
  }
  fflush(stderr);
  fflush(stdout);
  return ret;
}

Project: chrony

print_nanoseconds(double s)
{
  s = fabs(s);

  if (s < 9999.5e-9) {
    printf("%4.0fns", s * 1e9);
  } else if (s < 9999.5e-6) {
    printf("%4.0fus", s * 1e6);
  } else if (s < 9999.5e-3) {
    printf("%4.0fms", s * 1e3);
  } else if (s < 999.5) {
    printf("%5.1fs", s);
  } else if (s < 99999.5) {
    printf("%5.0fs", s);
  } else if (s < 99999.5 * 60) {
    printf("%5.0fm", s / 60);
  } else if (s < 99999.5 * 3600) {
    printf("%5.0fh", s / 3600);
  } else if (s < 99999.5 * 3600 * 24) {
    printf("%5.0fd", s / (3600 * 24));
  } else {
    printf("%5.0fy", s / (3600 * 24 * 365));
  }
}

Project: chrony

bits_to_mask(int bits, int family, IPAddr *mask)
{
  int i;

  mask->family = family;
  switch (family) {
    case IPADDR_INET4:
      if (bits < 0)
        bits = 32;
      if (bits > 0) {
        mask->addr.in4 = -1;
        mask->addr.in4 <<= 32 - bits;
      } else {
        mask->addr.in4 = 0;
      }
      break;
    case IPADDR_INET6:
      if (bits > 128 || bits < 0)
        bits = 128;
      for (i = 0; i < bits / 8; i++)
        mask->addr.in6[i] = 0xff;
      if (i < 16)
        mask->addr.in6[i++] = (0xff << (8 - bits % 8)) & 0xff;
      for (; i < 16; i++)
        mask->addr.in6[i] = 0x0;
      break;
    default:
      assert(0);
  }
}

Project: chrony

cvt_to_sec_usec(double x, long *sec, long *usec) {
  long s, us;
  s = (long) x;
  us = (long)(0.5 + 1.0e6 * (x - (double) s));
  while (us >= 1000000) {
    us -= 1000000;
    s += 1;
  }
  while (us < 0) {
    us += 1000000;
    s -= 1;
  }
  
  *sec = s;
  *usec = us;
}

Project: chrony

print_reply_packet(CMD_Reply *pkt)
{
  unsigned char *x;
  int i;
  x = (unsigned char *) pkt;
  for (i=0; i<sizeof(CMD_Reply); i++) {
    fprintf(stderr, "%02x ", x[i]);
    if (i%16 == 15) {
      fprintf(stderr, "\n");
    }
  }
  fprintf(stderr, "\n");
}

Project: chrony

handle_denyall(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  IPAddr ip;
  int subnet_bits;
  UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
  subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
  if (NCR_AddAccessRestriction(&ip, subnet_bits, 0, 1)) {
    tx_message->status = htons(STT_SUCCESS);
  } else {
    tx_message->status = htons(STT_BADSUBNET);
  }              
}

Project: chrony

    if (request_reply(&request, &reply, RPY_CLIENT_ACCESSES, 0)) {
          n_replies = ntohl(reply.data.client_accesses.n_clients);
          for (j=0; j<n_replies; j++) {
            ip = ntohl(reply.data.client_accesses.clients[j].ip);
            if (ip != 0UL) {
              /* ip == 0 implies that the node could not be found in
                 the daemon's tables; we shouldn't ever generate this
                 case, but ignore it if we do.  (In future there might
                 be a protocol to reset the client logging; if another
                 administrator runs that while we're doing the clients
                 command, there will be a race condition that could
                 cause this). */
              
              client_hits = ntohl(reply.data.client_accesses.clients[j].client_hits);
              peer_hits = ntohl(reply.data.client_accesses.clients[j].peer_hits);
              cmd_hits_auth = ntohl(reply.data.client_accesses.clients[j].cmd_hits_auth);
              cmd_hits_normal = ntohl(reply.data.client_accesses.clients[j].cmd_hits_normal);
              cmd_hits_bad = ntohl(reply.data.client_accesses.clients[j].cmd_hits_bad);
              last_ntp_hit_ago = ntohl(reply.data.client_accesses.clients[j].last_ntp_hit_ago);
              last_cmd_hit_ago = ntohl(reply.data.client_accesses.clients[j].last_cmd_hit_ago);

              if (no_dns) {
                snprintf(hostname_buf, sizeof(hostname_buf), 
                         "%s", UTI_IPToDottedQuad(ip));
              } else {
                DNS_IPAddress2Name(ip, hostname_buf, sizeof(hostname_buf));
                hostname_buf[25] = 0;
              }
              printf("%-25s  %6d  %6d  %6d  %6d  %6d  ",
                     hostname_buf,
                     client_hits, peer_hits,
                     cmd_hits_auth, cmd_hits_normal, cmd_hits_bad);
              print_seconds(last_ntp_hit_ago);
              printf("  ");
              print_seconds(last_cmd_hit_ago);
              printf("\n");
            }
          }              

          /* Skip the todo pointer forwards by the number of nets looked
             up.  Can't do this earlier, because we might have to point
             at the next layer of subnets that have only just been
             concatenated to the linked list. */
          for (i=0; i<clients_looked_up; i++) {
            todo = todo->next;
          }

    }

Project: chrony

process_cmd_dns(const char *line)
{
  if (!strcmp(line, "-46")) {
    DNS_SetAddressFamily(IPADDR_UNSPEC);
  } else if (!strcmp(line, "-4")) {
    DNS_SetAddressFamily(IPADDR_INET4);
  } else if (!strcmp(line, "-6")) {
    DNS_SetAddressFamily(IPADDR_INET6);
  } else if (!strcmp(line, "-n")) {
    no_dns = 1;
  } else if (!strcmp(line, "+n")) {
    no_dns = 0;
  } else {
    fprintf(stderr, "Unrecognized dns command\n");
    return 0;
  }
  return 1;
}

Project: chrony

process_cmd_manual_delete(CMD_Request *msg, const char *line)
{
  int index;

  if (sscanf(line, "%d", &index) != 1) {
    fprintf(stderr, "Bad syntax for manual delete command\n");
    return 0;

  }

  msg->command = htons(REQ_MANUAL_DELETE);
  msg->data.manual_delete.index = htonl(index);
  return 1;
}

Project: chrony

handle_del_source(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  NTP_Remote_Address rem_addr;
  NSR_Status status;
  
  UTI_IPNetworkToHost(&rx_message->data.del_source.ip_addr, &rem_addr.ip_addr);
  rem_addr.local_ip_addr.family = IPADDR_UNSPEC;
  rem_addr.port = 0;
  
  status = NSR_RemoveSource(&rem_addr);
  switch (status) {
    case NSR_Success:
      tx_message->status = htons(STT_SUCCESS);
      break;
    case NSR_NoSuchSource:
      tx_message->status = htons(STT_NOSUCHSOURCE);
      break;
    case NSR_TooManySources:
    case NSR_AlreadyInUse:
    case NSR_InvalidAF:
      assert(0);
      break;
  }
}

Project: chrony

handle_make_step(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  LCL_MakeStep(0.0);
  tx_message->status = htons(STT_SUCCESS);
}

Project: chrony

process_cmd_accheck(CMD_Request *msg, char *line)
{
  IPAddr ip;
  msg->command = htons(REQ_ACCHECK);
  if (accheck_getaddr(line, &ip)) {
    UTI_IPHostToNetwork(&ip, &msg->data.ac_check.ip);
    return 1;
  } else {    
    fprintf(stderr, "Could not read address\n");
    return 0;
  }
}

Project: chrony

submit_request(CMD_Request *request, CMD_Reply *reply, int *reply_auth_ok)
{
  unsigned long tx_sequence;
  socklen_t where_from_len;
  union sockaddr_in46 where_from;
  int bad_length, bad_sender, bad_sequence, bad_header;
  int select_status;
  int recvfrom_status;
  int read_length;
  int expected_length;
  int command_length;
  int auth_length;
  struct timeval tv;
  int timeout;
  int n_attempts;
  fd_set rdfd, wrfd, exfd;

  request->version = PROTO_VERSION_NUMBER;
  request->pkt_type = PKT_TYPE_CMD_REQUEST;
  request->res1 = 0;
  request->res2 = 0;
  tx_sequence = sequence++;
  request->sequence = htonl(tx_sequence);
  request->attempt = 0;
  request->utoken = htonl(utoken);
  request->token = htonl(token);

  timeout = initial_timeout;

  n_attempts = 0;

  do {

    /* Decide whether to authenticate */
    if (password) {
      if (!utoken || (request->command == htons(REQ_LOGON))) {
        /* Otherwise, the daemon won't bother authenticating our
           packet and we won't get a token back */
        request->utoken = htonl(SPECIAL_UTOKEN);
      }
      auth_length = generate_auth(request);
    } else {
      auth_length = 0;
    }

    command_length = PKL_CommandLength(request);
    assert(command_length > 0);

    /* add empty MD5 auth so older servers will not drop the request
       due to bad length */
    if (!auth_length) {
      memset(((char *)request) + command_length, 0, 16);
      auth_length = 16;
    }

#if 0
    printf("Sent command length=%d bytes auth length=%d bytes\n", command_length, auth_length);
#endif

    if (sendto(sock_fd, (void *) request, command_length + auth_length, 0,
               &his_addr.u, his_addr_len) < 0) {


#if 0
      perror("Could not send packet");
#endif
      return 0;
    }

    /* Increment this for next time */
    ++ request->attempt;
      
    tv.tv_sec = timeout / 1000;
    tv.tv_usec = timeout % 1000 * 1000;
    timeout *= 2;

    FD_ZERO(&rdfd);
    FD_ZERO(&wrfd);
    FD_ZERO(&exfd);

    FD_SET(sock_fd, &rdfd);

    select_status = select(sock_fd + 1, &rdfd, &wrfd, &exfd, &tv);

    if (select_status < 0) {
#if 0
      perror("Select returned negative status");
#endif
    } else if (select_status == 0) {
      /* Timeout must have elapsed, try a resend? */
      n_attempts ++;
      if (n_attempts > max_retries) {
        return 0;
      }

      /* Back to top of loop to do resend */
      continue;
      
    } else {
      
      where_from_len = sizeof(where_from);
      recvfrom_status = recvfrom(sock_fd, (void *) reply, sizeof(CMD_Reply), 0,
                                 &where_from.u, &where_from_len);
      

#if 0
      printf("Received packet, status=%d\n", recvfrom_status);
#endif

      if (recvfrom_status < 0) {
        /* If we get connrefused here, it suggests the sendto is
           going to a dead port - but only if the daemon machine is
           running Linux (Solaris doesn't return anything) */
        n_attempts++;
        if (n_attempts > max_retries) {
          return 0;
        }
      } else {
        
        read_length = recvfrom_status;
        expected_length = PKL_ReplyLength(reply);

        bad_length = (read_length < expected_length ||
                      expected_length < offsetof(CMD_Reply, data));
        bad_sender = (where_from.u.sa_family != his_addr.u.sa_family ||
                      (where_from.u.sa_family == AF_INET &&
                       (where_from.in4.sin_addr.s_addr != his_addr.in4.sin_addr.s_addr ||
                        where_from.in4.sin_port != his_addr.in4.sin_port)) ||
#ifdef HAVE_IPV6
                      (where_from.u.sa_family == AF_INET6 &&
                       (memcmp(where_from.in6.sin6_addr.s6_addr, his_addr.in6.sin6_addr.s6_addr,
                               sizeof (where_from.in6.sin6_addr.s6_addr)) != 0 ||
                        where_from.in6.sin6_port != his_addr.in6.sin6_port)) ||
#endif
                      0);
        
        if (!bad_length) {
          bad_sequence = (ntohl(reply->sequence) != tx_sequence);
        } else {
          bad_sequence = 0;
        }
        
        if (bad_length || bad_sender || bad_sequence) {
          n_attempts++;
          if (n_attempts > max_retries) {
            return 0;
          }
          continue;
        }
        
        bad_header = ((reply->version != PROTO_VERSION_NUMBER &&
                       !(reply->version >= PROTO_VERSION_MISMATCH_COMPAT &&
                         ntohs(reply->status) == STT_BADPKTVERSION)) ||
                      (reply->pkt_type != PKT_TYPE_CMD_REPLY) ||
                      (reply->res1 != 0) ||
                      (reply->res2 != 0) ||
                      (reply->command != request->command));
        
        if (bad_header) {
          n_attempts++;
          if (n_attempts > max_retries) {
            return 0;
          }
          continue;
        }
        
        /* Good packet received, print out results */
#if 0
        printf("Reply cmd=%d reply=%d stat=%d num=%d tot=%d seq=%d utok=%08lx tok=%d\n",
               ntohs(reply->command), ntohs(reply->reply),
               ntohs(reply->status), ntohs(reply->number),
               ntohs(reply->total),
               ntohl(reply->sequence),
               ntohl(reply->utoken),
               ntohl(reply->token));
#endif

        if (password) {
          *reply_auth_ok = check_reply_auth(reply, read_length);
        } else {
          /* Assume in this case that the reply is always considered
             to be authentic */
          *reply_auth_ok = 1;
        }
            
        utoken = ntohl(reply->utoken);

        if (*reply_auth_ok) {
          /* If we're in authenticated mode, only acquire the utoken
             and new token values if the reply authenticated properly.
             This protects against forged packets with bogus tokens
             in.  We won't accept a repeat of an old message with a
             stale token in it, due to bad_sequence processing
             earlier. */
          utoken = ntohl(reply->utoken);
          token = ntohl(reply->token);
        }
        
        break;

      }
    }
  } while (1);

  return 1;
}

Project: chrony

read_mask_address(char *line, IPAddr *mask, IPAddr *address)
{
  unsigned int bits;
  char *p, *q;

  p = line;
  if (!*p) {
    mask->family = address->family = IPADDR_UNSPEC;
    return 1;
  } else {
    q = strchr(p, '/');
    if (q) {
      *q++ = 0;
      if (UTI_StringToIP(p, mask)) {
        p = q;
        if (UTI_StringToIP(p, address)) {
          if (address->family == mask->family)
            return 1;
        } else if (sscanf(p, "%u", &bits) == 1) {
          *address = *mask;
          bits_to_mask(bits, address->family, mask);
          return 1;
        }
      }
    } else {
      if (DNS_Name2IPAddress(p, address) == DNS_Success) {
        bits_to_mask(-1, address->family, mask);
        return 1;
      } else {
        fprintf(stderr, "Could not get address for hostname\n");
        return 0;
      }
    }
  }

  fprintf(stderr, "Invalid syntax for mask/address\n");
  return 0;
}

Project: chrony

process_cmd_cmdallowall(CMD_Request *msg, char *line)
{
  int status;
  msg->command = htons(REQ_CMDALLOWALL);
  status = parse_allow_deny(msg, line);
  return status;
}

Project: chrony

check_for_verbose_flag(char *line)
{
  char *p = line;
  if (!strcmp(p, "-v")) {
    return 1;
  } else {
    return 0;
  }
}

Project: chrony

process_cmd_local(CMD_Request *msg, const char *line)
{
  const char *p;
  int stratum;

  p = line;
  
  if (!*p) {
    return 0;
  } else if (!strcmp(p, "off")) {
    msg->data.local.on_off = htonl(0);
    msg->data.local.stratum = htonl(0);
  } else if (sscanf(p, "stratum%d", &stratum) == 1) {
    msg->data.local.on_off = htonl(1);
    msg->data.local.stratum = htonl(stratum);
  } else {
    fprintf(stderr, "Invalid syntax for local command\n");
    return 0;
  }

  msg->command = htons(REQ_LOCAL);
  return 1;
}

Project: chrony

handle_cyclelogs(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  LOG_CycleLogFiles();
  
  tx_message->status = htons(STT_SUCCESS);
}

Project: chrony

handle_reselect(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  SRC_ReselectSource();
  tx_message->status = htons(STT_SUCCESS);
}

Project: chrony

process_cmd_maxupdateskew(CMD_Request *msg, char *line)
{
  int ok;
  double new_max_update_skew;
  
  if (sscanf(line, "%lf", &new_max_update_skew) == 1) {
    msg->data.modify_maxupdateskew.new_max_update_skew = UTI_FloatHostToNetwork(new_max_update_skew);
    msg->command = htons(REQ_MODIFY_MAXUPDATESKEW);
    ok = 1;
  } else {
    ok = 0;
  }

  return ok;

}

Project: chrony

read_line(void)
{
  static char line[2048];
  static const char *prompt = "chronyc> ";

  if (on_terminal) {
#ifdef FEAT_READLINE
    char *cmd;

    /* save line only if not empty */
    cmd = readline(prompt);
    if( cmd == NULL ) return( NULL );
    
    /* user pressed return */
    if( *cmd != '\0' ) {
      strncpy(line, cmd, sizeof(line) - 1);
      line[sizeof(line) - 1] = '\0';
      add_history(cmd);
      /* free the buffer allocated by readline */
      free(cmd);
    } else {
      /* simulate the user has entered an empty line */
      *line = '\0';
    }
    return( line );
#else
    printf("%s", prompt);
#endif
  }
  if (fgets(line, sizeof(line), stdin)) {
    return line;
  } else {
    return NULL;
  }
  
}

Project: chrony

check_unique_ts(struct timeval *ts, struct timeval *now)
{
  TimestampCell *last_valid, *cell, *next;
  int ok;

  ok = 1;
  last_valid = &(seen_ts_list);
  cell = last_valid->next;

  while (cell) {
    next = cell->next;
    /* Check if stale */
    if ((now->tv_sec - cell->ts.tv_sec) > TS_MARGIN) {
      release_ts_cell(cell);
      last_valid->next = next;
    } else {
      /* Timestamp in cell is still within window */
      last_valid->next = cell;
      last_valid = cell;
      if ((cell->ts.tv_sec == ts->tv_sec) && (cell->ts.tv_usec == ts->tv_usec)) {
        ok = 0;
      }
    }
    cell = next;
  }

  if (ok) {
    /* Need to add this timestamp to the list */
    cell = allocate_ts_cell();
    last_valid->next = cell;
    cell->next = NULL;
    cell->ts = *ts;
  }

  return ok;
}

Project: chrony

prepare_socket(int family)
{
  int port_number, sock_fd;
  socklen_t my_addr_len;
  union sockaddr_in46 my_addr;
  IPAddr bind_address;
  int on_off = 1;

  port_number = CNF_GetCommandPort();

  sock_fd = socket(family, SOCK_DGRAM, 0);
  if (sock_fd < 0) {
    LOG(LOGS_ERR, LOGF_CmdMon, "Could not open %s command socket : %s",
        family == AF_INET ? "IPv4" : "IPv6", strerror(errno));
    return -1;
  }

  /* Close on exec */
  UTI_FdSetCloexec(sock_fd);

  /* Allow reuse of port number */
  if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on_off, sizeof(on_off)) < 0) {
    LOG(LOGS_ERR, LOGF_CmdMon, "Could not set reuseaddr socket options");
    /* Don't quit - we might survive anyway */
  }
#ifdef HAVE_IPV6
  if (family == AF_INET6) {
#ifdef IPV6_V6ONLY
    /* Receive IPv6 packets only */
    if (setsockopt(sock_fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on_off, sizeof(on_off)) < 0) {
      LOG(LOGS_ERR, LOGF_CmdMon, "Could not request IPV6_V6ONLY socket option");
    }
#endif
  }
#endif

  memset(&my_addr, 0, sizeof (my_addr));

  switch (family) {
    case AF_INET:
      my_addr_len = sizeof (my_addr.in4);
      my_addr.in4.sin_family = family;
      my_addr.in4.sin_port = htons((unsigned short)port_number);

      CNF_GetBindCommandAddress(IPADDR_INET4, &bind_address);

      if (bind_address.family == IPADDR_INET4)
        my_addr.in4.sin_addr.s_addr = htonl(bind_address.addr.in4);
      else
        my_addr.in4.sin_addr.s_addr = htonl(INADDR_ANY);
      break;
#ifdef HAVE_IPV6
    case AF_INET6:
      my_addr_len = sizeof (my_addr.in6);
      my_addr.in6.sin6_family = family;
      my_addr.in6.sin6_port = htons((unsigned short)port_number);

      CNF_GetBindCommandAddress(IPADDR_INET6, &bind_address);

      if (bind_address.family == IPADDR_INET6)
        memcpy(my_addr.in6.sin6_addr.s6_addr, bind_address.addr.in6,
            sizeof (my_addr.in6.sin6_addr.s6_addr));
      else
        my_addr.in6.sin6_addr = in6addr_any;
      break;
#endif
    default:
      assert(0);
  }

  if (bind(sock_fd, &my_addr.u, my_addr_len) < 0) {
    LOG(LOGS_ERR, LOGF_CmdMon, "Could not bind %s command socket : %s",
        family == AF_INET ? "IPv4" : "IPv6", strerror(errno));
    close(sock_fd);
    return -1;
  }

  /* Register handler for read events on the socket */
  SCH_AddInputFileHandler(sock_fd, read_from_cmd_socket, (void *)(long)sock_fd);

  return sock_fd;
}

Project: chrony

PKL_ReplyLength(CMD_Reply *r)
{
  int type;
  type = ntohs(r->reply);
  /* Note that reply type codes start from 1, not 0 */
  if (type < 1 || type >= N_REPLY_TYPES) {
    return 0;
  } else {
    switch (type) {
      case RPY_NULL:
        return offsetof(CMD_Reply, data.null.EOR);
      case RPY_N_SOURCES:
        return offsetof(CMD_Reply, data.n_sources.EOR);
      case RPY_SOURCE_DATA:
        return offsetof(CMD_Reply, data.source_data.EOR);
      case RPY_MANUAL_TIMESTAMP:
        return offsetof(CMD_Reply, data.manual_timestamp.EOR);
      case RPY_TRACKING:
        return offsetof(CMD_Reply, data.tracking.EOR);
      case RPY_SOURCESTATS:
        return offsetof(CMD_Reply, data.sourcestats.EOR);
      case RPY_RTC:
        return offsetof(CMD_Reply, data.rtc.EOR);
      case RPY_SUBNETS_ACCESSED :
        {
          unsigned long ns = ntohl(r->data.subnets_accessed.n_subnets);
          if (r->status == htons(STT_SUCCESS)) {
            if (ns > MAX_SUBNETS_ACCESSED)
              return 0;
            return (offsetof(CMD_Reply, data.subnets_accessed.subnets) +
                    ns * sizeof(RPY_SubnetsAccessed_Subnet));
          } else {
            return offsetof(CMD_Reply, data);
          }
        }
      case RPY_CLIENT_ACCESSES:
        {
          unsigned long nc = ntohl(r->data.client_accesses.n_clients);
          if (r->status == htons(STT_SUCCESS)) {
            if (nc > MAX_CLIENT_ACCESSES)
              return 0;
            return (offsetof(CMD_Reply, data.client_accesses.clients) +
                    nc * sizeof(RPY_ClientAccesses_Client));
          } else {
            return offsetof(CMD_Reply, data);
          }
        }
      case RPY_CLIENT_ACCESSES_BY_INDEX:
        {
          unsigned long nc = ntohl(r->data.client_accesses_by_index.n_clients);
          if (r->status == htons(STT_SUCCESS)) {
            if (nc > MAX_CLIENT_ACCESSES)
              return 0;
            return (offsetof(CMD_Reply, data.client_accesses_by_index.clients) +
                    nc * sizeof(RPY_ClientAccesses_Client));
          } else {
            return offsetof(CMD_Reply, data);
          }
        }
      case RPY_MANUAL_LIST:
        {
          unsigned long ns = ntohl(r->data.manual_list.n_samples);
          if (ns > MAX_MANUAL_LIST_SAMPLES)
            return 0;
          if (r->status == htons(STT_SUCCESS)) {
            return (offsetof(CMD_Reply, data.manual_list.samples) +
                    ns * sizeof(RPY_ManualListSample));
          } else {
            return offsetof(CMD_Reply, data);
          }
        }
      case RPY_ACTIVITY:
        return offsetof(CMD_Reply, data.activity.EOR);
        
      default:
        assert(0);
    }
  }

  return 0;
}

Project: chrony

check_rx_packet_auth(CMD_Request *packet, int packet_len)
{
  int pkt_len, auth_len;

  pkt_len = PKL_CommandLength(packet);
  auth_len = packet_len - pkt_len;

  return KEY_CheckAuth(KEY_GetCommandKey(), (unsigned char *)packet,
      pkt_len, ((unsigned char *)packet) + pkt_len, auth_len);
}

Project: chrony

process_cmd_settime(char *line)
{
  struct timeval ts;
  time_t now, new_time;
  CMD_Request request;
  CMD_Reply reply;
  long offset_cs;
  double dfreq_ppm, new_afreq_ppm;
  double offset;

  now = time(NULL);
  new_time = get_date(line, &now);

  if (new_time == -1) {
    printf("510 - Could not parse date string\n");
  } else {
    ts.tv_sec = new_time;
    ts.tv_usec = 0;
    UTI_TimevalHostToNetwork(&ts, &request.data.settime.ts);
    request.command = htons(REQ_SETTIME);
    if (request_reply(&request, &reply, RPY_MANUAL_TIMESTAMP, 1)) {
          offset_cs = ntohl(reply.data.manual_timestamp.centiseconds);
          offset = 0.01 * (double)(int32_t)offset_cs;
          dfreq_ppm = UTI_FloatNetworkToHost(reply.data.manual_timestamp.dfreq_ppm);
          new_afreq_ppm = UTI_FloatNetworkToHost(reply.data.manual_timestamp.new_afreq_ppm);
          printf("Clock was %.2f seconds fast.  Frequency change = %.2fppm, new frequency = %.2fppm\n",
              offset, dfreq_ppm, new_afreq_ppm);
          return 1;
    }
  }
  return 0;
}

Project: chrony

process_cmd_cmdaccheck(CMD_Request *msg, char *line)
{
  IPAddr ip;
  msg->command = htons(REQ_CMDACCHECK);
  if (accheck_getaddr(line, &ip)) {
    UTI_IPHostToNetwork(&ip, &msg->data.ac_check.ip);
    return 1;
  } else {    
    fprintf(stderr, "Could not read address\n");
    return 0;
  }
}

Project: chrony

handle_cmddenyall(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  IPAddr ip;
  int subnet_bits;
  UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
  subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
  if (CAM_AddAccessRestriction(&ip, subnet_bits, 0, 1)) {
    tx_message->status = htons(STT_SUCCESS);
  } else {
    tx_message->status = htons(STT_BADSUBNET);
  }              
}

Project: chrony

    while ((i < MAX_CLIENT_ACCESSES) &&
           p) {

      request.data.client_accesses.client_ips[i] = htonl(p->ip);
      p = p->next;
      i++;
    }

Project: chrony

open_io(const char *hostname, int port)
{
  IPAddr ip;

  /* Note, this call could block for a while */
  if (DNS_Name2IPAddress(hostname, &ip) != DNS_Success) {
    fprintf(stderr, "Could not get IP address for %s\n", hostname);
    exit(1);
  }

  memset(&his_addr, 0, sizeof (his_addr));

  switch (ip.family) {
    case IPADDR_INET4:
      sock_fd = socket(AF_INET, SOCK_DGRAM, 0);

      his_addr.in4.sin_family = AF_INET;
      his_addr.in4.sin_addr.s_addr = htonl(ip.addr.in4);
      his_addr.in4.sin_port = htons(port);
      his_addr_len = sizeof (his_addr.in4);
      break;
#ifdef HAVE_IPV6
    case IPADDR_INET6:
      sock_fd = socket(AF_INET6, SOCK_DGRAM, 0);

      his_addr.in6.sin6_family = AF_INET6;
      memcpy(his_addr.in6.sin6_addr.s6_addr, ip.addr.in6,
          sizeof (his_addr.in6.sin6_addr.s6_addr));
      his_addr.in6.sin6_port = htons(port);
      his_addr_len = sizeof (his_addr.in6);
      break;
#endif
    default:
      assert(0);
  }

  if (sock_fd < 0) {
    perror("Can't create socket");
    exit(1);
  }
}

Project: chrony

handle_offline(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  int status;
  IPAddr address, mask;
  UTI_IPNetworkToHost(&rx_message->data.offline.mask, &mask);
  UTI_IPNetworkToHost(&rx_message->data.offline.address, &address);
  status = NSR_TakeSourcesOffline(&mask, &address);
  if (status) {
    tx_message->status = htons(STT_SUCCESS);
  } else {
    tx_message->status = htons(STT_NOSUCHSOURCE);
  }
}

Project: chrony

handle_allow(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  IPAddr ip;
  int subnet_bits;
  UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
  subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
  if (NCR_AddAccessRestriction(&ip, subnet_bits, 1, 0)) {
    tx_message->status = htons(STT_SUCCESS);
  } else {
    tx_message->status = htons(STT_BADSUBNET);
  }              
}

Project: chrony

get_more_replies(void)
{
  ResponseCell *new_replies;
  int i;

  if (!free_replies) {
    new_replies = MallocArray(ResponseCell, REPLY_EXTEND_QUANTUM);
    for (i=1; i<REPLY_EXTEND_QUANTUM; i++) {
      new_replies[i-1].next = new_replies + i;
    }
    free_replies = new_replies;
  }
}

Project: chrony

CAM_Finalise(void)
{
  if (sock_fd4 >= 0) {
    SCH_RemoveInputFileHandler(sock_fd4);
    close(sock_fd4);
  }
  sock_fd4 = -1;
#ifdef HAVE_IPV6
  if (sock_fd6 >= 0) {
    SCH_RemoveInputFileHandler(sock_fd6);
    close(sock_fd6);
  }
  sock_fd6 = -1;
#endif

  ADF_DestroyTable(access_auth_table);

  initialised = 0;
}

Project: chrony

process_cmd_clients(char *line)
{
  CMD_Request request;
  CMD_Reply reply;
  SubnetToDo *head, *todo, *tail, *p, *next_node, *new_node;
  int i, j, nets_looked_up, clients_looked_up;
  int word;
  unsigned long mask;
  unsigned long ip, bits;
  unsigned long client_hits;
  unsigned long peer_hits;
  unsigned long cmd_hits_auth;
  unsigned long cmd_hits_normal;
  unsigned long cmd_hits_bad;
  unsigned long last_ntp_hit_ago;
  unsigned long last_cmd_hit_ago;
  char hostname_buf[50];

  int n_replies;

  head = todo = MallocNew(SubnetToDo);
  todo->next = NULL;
  /* Set up initial query = root subnet */
  todo->ip = 0;
  todo->bits = 0;
  tail = todo;

  do {

    request.command = htons(REQ_SUBNETS_ACCESSED);
    /* Build list of subnets to examine */
    i=0;
    p=todo;
    while((i < MAX_SUBNETS_ACCESSED) &&
          p &&
          (p->bits < 32)) {
      
      request.data.subnets_accessed.subnets[i].ip = htonl(p->ip);
      request.data.subnets_accessed.subnets[i].bits_specd = htonl(p->bits);
      p = p->next;
      i++;
    }         

    nets_looked_up = i;

    if (nets_looked_up == 0) {
      /* No subnets need examining */
      break;
    }

    request.data.subnets_accessed.n_subnets = htonl(nets_looked_up);

    if (request_reply(&request, &reply, RPY_SUBNETS_ACCESSED, 0)) {
          n_replies = ntohl(reply.data.subnets_accessed.n_subnets);
          for (j=0; j<n_replies; j++) {
            ip = ntohl(reply.data.subnets_accessed.subnets[j].ip);
            bits = ntohl(reply.data.subnets_accessed.subnets[j].bits_specd);
            for (i=0; i<256; i++) {
              word = i/32;
              mask = 1UL << (i%32);
              if (ntohl(reply.data.subnets_accessed.subnets[j].bitmap[word]) & mask) {
                /* Add this subnet to the todo list */
                new_node = MallocNew(SubnetToDo);
                new_node->next = NULL;
                new_node->bits = bits + 8;
                new_node->ip = ip | (i << (24 - bits));
                tail->next = new_node;
                tail = new_node;
#if 0
                printf("%08lx %2d %3d %08lx\n", ip, bits, i, new_node->ip);
#endif
              }
            }
          }

          /* Skip the todo pointer forwards by the number of nets looked
             up.  Can't do this earlier, because we might have to point
             at the next layer of subnets that have only just been
             concatenated to the linked list. */
          for (i=0; i<nets_looked_up; i++) {
            todo = todo->next;
          }
          
      }
      
    } else {
      return;
    }
  } while (1); /* keep going until all subnets have been expanded,

Project: chrony

process_cmd_doffset(CMD_Request *msg, char *line)
{
  double doffset;
  long sec, usec;
  msg->command = htons(REQ_DOFFSET);
  if (sscanf(line, "%lf", &doffset) == 1) {
    cvt_to_sec_usec(doffset, &sec, &usec);
    msg->data.doffset.sec = htonl(sec);
    msg->data.doffset.usec = htonl(usec);
  } else {
    msg->data.doffset.sec = htonl(0);
    msg->data.doffset.usec = htonl(0);
  }
}

Project: chrony

CAM_CheckAccessRestriction(IPAddr *ip_addr)
{
  return ADF_IsAllowed(access_auth_table, ip_addr);
}

Project: chrony

free_reply_slot(ResponseCell *cell)
{
  cell->next = free_replies;
  free_replies = cell;
}

Project: chrony

process_cmd_rekey(CMD_Request *msg, char *line)
{
  msg->command = htons(REQ_REKEY);
}

Project: chrony

process_cmd_sources(char *line)
{
  CMD_Request request;
  CMD_Reply reply;
  int n_sources, i;
  int verbose = 0;

  double orig_latest_meas, latest_meas, latest_meas_err;
  IPAddr ip_addr;
  uint32_t latest_meas_ago;
  uint16_t poll, stratum;
  uint16_t state, mode, flags, reachability;
  char hostname_buf[50];

  /* Check whether to output verbose headers */
  verbose = check_for_verbose_flag(line);
  
  request.command = htons(REQ_N_SOURCES);
  if (request_reply(&request, &reply, RPY_N_SOURCES, 0)) {
    n_sources = ntohl(reply.data.n_sources.n_sources);
    printf("210 Number of sources = %d\n", n_sources);
    if (verbose) {
      printf("\n");
      printf("  .-- Source mode  '^' = server, '=' = peer, '#' = local clock.\n");
      printf(" / .- Source state '*' = current synced, '+' = combined , '-' = not combined,\n");
      printf("| /   '?' = unreachable, 'x' = time may be in error, '~' = time too variable.\n");
      printf("||                                                 .- xxxx [ yyyy ] +/- zzzz\n");
      printf("||                                                /   xxxx = adjusted offset,\n");
      printf("||         Log2(Polling interval) -.             |    yyyy = measured offset,\n");
      printf("||                                  \\            |    zzzz = estimated error.\n");
      printf("||                                   |           |                         \n");
    }

    printf("MS Name/IP address         Stratum Poll Reach LastRx Last sample\n");
    printf("===============================================================================\n");

    /*     "MS NNNNNNNNNNNNNNNNNNNNNNNNNNN  SS  PP   RRR  RRRR  SSSSSSS[SSSSSSS] +/- SSSSSS" */

    for (i=0; i<n_sources; i++) {
      request.command = htons(REQ_SOURCE_DATA);
      request.data.source_data.index = htonl(i);
      if (request_reply(&request, &reply, RPY_SOURCE_DATA, 0)) {
          UTI_IPNetworkToHost(&reply.data.source_data.ip_addr, &ip_addr);
          poll = ntohs(reply.data.source_data.poll);
          stratum = ntohs(reply.data.source_data.stratum);
          state = ntohs(reply.data.source_data.state);
          mode = ntohs(reply.data.source_data.mode);
          flags = ntohs(reply.data.source_data.flags);
          reachability = ntohs(reply.data.source_data.reachability);
          latest_meas_ago = ntohl(reply.data.source_data.since_sample);
          orig_latest_meas = UTI_FloatNetworkToHost(reply.data.source_data.orig_latest_meas);
          latest_meas = UTI_FloatNetworkToHost(reply.data.source_data.latest_meas);
          latest_meas_err = UTI_FloatNetworkToHost(reply.data.source_data.latest_meas_err);

          if (mode == RPY_SD_MD_REF) {
            snprintf(hostname_buf, sizeof(hostname_buf), "%s", UTI_RefidToString(ip_addr.addr.in4));
          } else if (no_dns) {
            snprintf(hostname_buf, sizeof(hostname_buf), "%s", UTI_IPToString(&ip_addr));
          } else {
            DNS_IPAddress2Name(&ip_addr, hostname_buf, sizeof(hostname_buf));
            hostname_buf[25] = 0;
          }

          switch (mode) {
            case RPY_SD_MD_CLIENT:
              printf("^"); break;
            case RPY_SD_MD_PEER:
              printf("="); break;
            case RPY_SD_MD_REF:
              printf("#"); break;
            default:
              printf(" ");
          }
          switch (state) {
            case RPY_SD_ST_SYNC:
              printf("*"); break;
            case RPY_SD_ST_UNREACH:
              printf("?"); break;
            case RPY_SD_ST_FALSETICKER:
              printf("x"); break;
            case RPY_SD_ST_JITTERY:
              printf("~"); break;
            case RPY_SD_ST_CANDIDATE:
              printf("+"); break;
            case RPY_SD_ST_OUTLIER:
              printf("-"); break;
            default:
              printf(" ");
          }
          switch (flags) {
            default:
              break;
          }

          printf(" %-27s  %2d  %2d   %3o  ", hostname_buf, stratum, poll, reachability);
          print_seconds(latest_meas_ago);
          printf("  ");
          print_signed_nanoseconds(latest_meas);
          printf("[");
          print_signed_nanoseconds(orig_latest_meas);
          printf("]");
          printf(" +/- ");
          print_nanoseconds(latest_meas_err);
          printf("\n");
      } else {
        return 0;
      }
    }
  } else {
    return 0;
  }
  return 1;
}

Project: chrony

process_cmd_tracking(char *line)
{
  CMD_Request request;
  CMD_Reply reply;
  IPAddr ip_addr;
  uint32_t ref_id;
  char host[50];
  char *ref_ip;
  struct timeval ref_time;
  struct tm ref_time_tm;
  unsigned long a, b, c, d;
  double correction;
  double last_offset;
  double rms_offset;
  double freq_ppm;
  double resid_freq_ppm;
  double skew_ppm;
  double root_delay;
  double root_dispersion;
  double last_update_interval;
  const char *leap_status;
  
  request.command = htons(REQ_TRACKING);
  if (request_reply(&request, &reply, RPY_TRACKING, 0)) {
    ref_id = ntohl(reply.data.tracking.ref_id);
    a = (ref_id >> 24);
    b = (ref_id >> 16) & 0xff;
    c = (ref_id >> 8) & 0xff;
    d = (ref_id) & 0xff;
    
    UTI_IPNetworkToHost(&reply.data.tracking.ip_addr, &ip_addr);
    if (ip_addr.family == IPADDR_UNSPEC) {
      ref_ip = UTI_RefidToString(ref_id);
    } else if (no_dns) {
      ref_ip = UTI_IPToString(&ip_addr);
    } else {
      DNS_IPAddress2Name(&ip_addr, host, sizeof (host));
      ref_ip = host;
    }
    
    switch (ntohs(reply.data.tracking.leap_status)) {
      case LEAP_Normal:
        leap_status = "Normal";
        break;
      case LEAP_InsertSecond:
        leap_status = "Insert second";
        break;
      case LEAP_DeleteSecond:
        leap_status = "Delete second";
        break;
      case LEAP_Unsynchronised:
        leap_status = "Not synchronised";
        break;
      default:
        leap_status = "Unknown";
        break;
    }

    printf("Reference ID    : %lu.%lu.%lu.%lu (%s)\n", a, b, c, d, ref_ip);
    printf("Stratum         : %lu\n", (unsigned long) ntohs(reply.data.tracking.stratum));
    UTI_TimevalNetworkToHost(&reply.data.tracking.ref_time, &ref_time);
    ref_time_tm = *gmtime((time_t *)&ref_time.tv_sec);
    printf("Ref time (UTC)  : %s", asctime(&ref_time_tm));
    correction = UTI_FloatNetworkToHost(reply.data.tracking.current_correction);
    last_offset = UTI_FloatNetworkToHost(reply.data.tracking.last_offset);
    rms_offset = UTI_FloatNetworkToHost(reply.data.tracking.rms_offset);
    printf("System time     : %.9f seconds %s of NTP time\n", fabs(correction),
           (correction > 0.0) ? "slow" : "fast");
    printf("Last offset     : %.9f seconds\n", last_offset);
    printf("RMS offset      : %.9f seconds\n", rms_offset);
    freq_ppm = UTI_FloatNetworkToHost(reply.data.tracking.freq_ppm);
    resid_freq_ppm = UTI_FloatNetworkToHost(reply.data.tracking.resid_freq_ppm);
    skew_ppm = UTI_FloatNetworkToHost(reply.data.tracking.skew_ppm);
    root_delay = UTI_FloatNetworkToHost(reply.data.tracking.root_delay);
    root_dispersion = UTI_FloatNetworkToHost(reply.data.tracking.root_dispersion);
    last_update_interval = UTI_FloatNetworkToHost(reply.data.tracking.last_update_interval);
    printf("Frequency       : %.3f ppm %s\n", fabs(freq_ppm), (freq_ppm < 0.0) ? "slow" : "fast"); 
    printf("Residual freq   : %.3f ppm\n", resid_freq_ppm);
    printf("Skew            : %.3f ppm\n", skew_ppm);
    printf("Root delay      : %.6f seconds\n", root_delay);
    printf("Root dispersion : %.6f seconds\n", root_dispersion);
    printf("Update interval : %.1f seconds\n", last_update_interval);
    printf("Leap status     : %s\n", leap_status);
    return 1;
  }
  return 0;
}

Project: chrony

process_cmd_offline(CMD_Request *msg, char *line)
{
  IPAddr mask, address;
  int ok;

  if (read_mask_address(line, &mask, &address)) {
    UTI_IPHostToNetwork(&mask, &msg->data.offline.mask);
    UTI_IPHostToNetwork(&address, &msg->data.offline.address);
    msg->command = htons(REQ_OFFLINE);
    ok = 1;
  } else {
    ok = 0;
  }

  return ok;

}

Project: chrony

handle_add_source(NTP_Source_Type type, CMD_Request *rx_message, CMD_Reply *tx_message)
{
  NTP_Remote_Address rem_addr;
  SourceParameters params;
  NSR_Status status;
  
  UTI_IPNetworkToHost(&rx_message->data.ntp_source.ip_addr, &rem_addr.ip_addr);
  rem_addr.local_ip_addr.family = IPADDR_UNSPEC;
  rem_addr.port = (unsigned short)(ntohl(rx_message->data.ntp_source.port));
  params.minpoll = ntohl(rx_message->data.ntp_source.minpoll);
  params.maxpoll = ntohl(rx_message->data.ntp_source.maxpoll);
  params.presend_minpoll = ntohl(rx_message->data.ntp_source.presend_minpoll);
  params.authkey = ntohl(rx_message->data.ntp_source.authkey);
  params.online  = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_ONLINE ? 1 : 0;
  params.auto_offline = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_AUTOOFFLINE ? 1 : 0;
  params.iburst = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_IBURST ? 1 : 0;
  params.sel_option = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_PREFER ? SRC_SelectPrefer :
                      ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_NOSELECT ? SRC_SelectNoselect : SRC_SelectNormal;
  params.max_delay = UTI_FloatNetworkToHost(rx_message->data.ntp_source.max_delay);
  params.max_delay_ratio = UTI_FloatNetworkToHost(rx_message->data.ntp_source.max_delay_ratio);

 /* not transmitted in cmdmon protocol yet */
  params.min_stratum = SRC_DEFAULT_MINSTRATUM;       
  params.poll_target = SRC_DEFAULT_POLLTARGET;
  params.max_delay_dev_ratio = SRC_DEFAULT_MAXDELAYDEVRATIO;

  status = NSR_AddSource(&rem_addr, type, &params);
  switch (status) {
    case NSR_Success:
      tx_message->status = htons(STT_SUCCESS);
      break;
    case NSR_AlreadyInUse:
      tx_message->status = htons(STT_SOURCEALREADYKNOWN);
      break;
    case NSR_TooManySources:
      tx_message->status = htons(STT_TOOMANYSOURCES);
      break;
    case NSR_InvalidAF:
      tx_message->status = htons(STT_INVALIDAF);
      break;
    case NSR_NoSuchSource:
      assert(0);
      break;
  }
}

Project: chrony

shift_tokens(void)
{
  do {
    issued_tokens >>= 1;
    returned_tokens >>= 1;
    token_base++;
    issue_pointer--;
  } while ((issued_tokens & 1) && (returned_tokens & 1));
}

Project: chrony

process_cmd_add_server_or_peer(CMD_Request *msg, char *line)
{
  CPS_NTP_Source data;
  CPS_Status status;
  IPAddr ip_addr;
  int result = 0;
  
  status = CPS_ParseNTPSourceAdd(line, &data);
  switch (status) {
    case CPS_Success:
      if (DNS_Name2IPAddress(data.name, &ip_addr) != DNS_Success) {
        Free(data.name);
        fprintf(stderr, "Invalid host/IP address\n");
        break;
      }
      Free(data.name);

      if (data.params.min_stratum != SRC_DEFAULT_MINSTRATUM) {
        fprintf(stderr, "Option minstratum not supported\n");
        break;
      }

      if (data.params.poll_target != SRC_DEFAULT_POLLTARGET) {
        fprintf(stderr, "Option polltarget not supported\n");
        break;
      }

      if (data.params.max_delay_dev_ratio != SRC_DEFAULT_MAXDELAYDEVRATIO) {
        fprintf(stderr, "Option maxdelaydevratio not supported\n");
        break;
      }

      msg->data.ntp_source.port = htonl((unsigned long) data.port);
      UTI_IPHostToNetwork(&ip_addr, &msg->data.ntp_source.ip_addr);
      msg->data.ntp_source.minpoll = htonl(data.params.minpoll);
      msg->data.ntp_source.maxpoll = htonl(data.params.maxpoll);
      msg->data.ntp_source.presend_minpoll = htonl(data.params.presend_minpoll);
      msg->data.ntp_source.authkey = htonl(data.params.authkey);
      msg->data.ntp_source.max_delay = UTI_FloatHostToNetwork(data.params.max_delay);
      msg->data.ntp_source.max_delay_ratio = UTI_FloatHostToNetwork(data.params.max_delay_ratio);
      msg->data.ntp_source.flags = htonl(
          (data.params.online ? REQ_ADDSRC_ONLINE : 0) |
          (data.params.auto_offline ? REQ_ADDSRC_AUTOOFFLINE : 0) |
          (data.params.iburst ? REQ_ADDSRC_IBURST : 0) |
          (data.params.sel_option == SRC_SelectPrefer ? REQ_ADDSRC_PREFER : 0) |
          (data.params.sel_option == SRC_SelectNoselect ? REQ_ADDSRC_NOSELECT : 0));
      result = 1;

      break;
    case CPS_BadOption:
      fprintf(stderr, "Unrecognized subcommand\n");
      break;
    case CPS_BadHost:
      fprintf(stderr, "Invalid host/IP address\n");
      break;
    case CPS_BadPort:
      fprintf(stderr, "Unreadable port number\n");
      break;
    case CPS_BadMinpoll:
      fprintf(stderr, "Unreadable minpoll value\n");
      break;
    case CPS_BadMaxpoll:
      fprintf(stderr, "Unreadable maxpoll value\n");
      break;
    case CPS_BadPresend:
      fprintf(stderr, "Unreadable presend value\n");
      break;
    case CPS_BadMaxdelaydevratio:
      fprintf(stderr, "Unreadable max delay dev ratio value\n");
      break;
    case CPS_BadMaxdelayratio:
      fprintf(stderr, "Unreadable max delay ratio value\n");
      break;
    case CPS_BadMaxdelay:
      fprintf(stderr, "Unreadable max delay value\n");
      break;
    case CPS_BadKey:
      fprintf(stderr, "Unreadable key value\n");
      break;
    case CPS_BadMinstratum:
      fprintf(stderr, "Unreadable minstratum value\n");
      break;
    case CPS_BadPolltarget:
      fprintf(stderr, "Unreadable polltarget value\n");
      break;
  }

  return result;
}

Project: chrony

handle_null(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  tx_message->status = htons(STT_SUCCESS);
}

Project: chrony

process_cmd_add_server(CMD_Request *msg, char *line)
{
  msg->command = htons(REQ_ADD_SERVER);
  return process_cmd_add_server_or_peer(msg, line);
}

Project: chrony

CAM_Initialise(int family)
{
  assert(!initialised);
  initialised = 1;

  assert(sizeof (permissions) / sizeof (permissions[0]) == N_REQUEST_TYPES);

  utoken = (unsigned long) time(NULL);

  issued_tokens = returned_tokens = issue_pointer = 0;
  token_base = 1; /* zero is the value used when the previous command was
                     unauthenticated */

  free_replies = NULL;
  kept_replies.next = NULL;

  if (family == IPADDR_UNSPEC || family == IPADDR_INET4)
    sock_fd4 = prepare_socket(AF_INET);
  else
    sock_fd4 = -1;
#ifdef HAVE_IPV6
  if (family == IPADDR_UNSPEC || family == IPADDR_INET6)
    sock_fd6 = prepare_socket(AF_INET6);
  else
    sock_fd6 = -1;
#endif

  if (sock_fd4 < 0
#ifdef HAVE_IPV6
      && sock_fd6 < 0
#endif
      ) {
    LOG_FATAL(LOGF_CmdMon, "Could not open any command socket");
  }

  access_auth_table = ADF_CreateTable();

}

Project: chrony

handle_burst(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  int status;
  IPAddr address, mask;
  UTI_IPNetworkToHost(&rx_message->data.burst.mask, &mask);
  UTI_IPNetworkToHost(&rx_message->data.burst.address, &address);
  status = NSR_InitiateSampleBurst(ntohl(rx_message->data.burst.n_good_samples),
                                   ntohl(rx_message->data.burst.n_total_samples),
                                   &mask, &address);
  
  if (status) {
    tx_message->status = htons(STT_SUCCESS);
  } else {
    tx_message->status = htons(STT_NOSUCHSOURCE);
  }
}

Project: chrony

generate_auth(CMD_Request *msg)
{
  int data_len;

  data_len = PKL_CommandLength(msg);

  assert(auth_hash_id >= 0);

  return UTI_GenerateNTPAuth(auth_hash_id, (unsigned char *)password, password_length,
      (unsigned char *)msg, data_len, ((unsigned char *)msg) + data_len, sizeof (msg->auth));
}

Project: chrony

process_cmd_retries(const char *line)
{
  int retries;

  retries = atoi(line);
  if (retries < 0) {
    fprintf(stderr, "Invalid maximum number of retries\n");
    return 0;
  }
  max_retries = retries;
  return 1;
}

Project: chrony

process_cmd_add_peer(CMD_Request *msg, char *line)
{
  msg->command = htons(REQ_ADD_PEER);
  return process_cmd_add_server_or_peer(msg, line);
}

Project: chrony

handle_settime(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  struct timeval ts;
  long offset_cs;
  double dfreq_ppm, new_afreq_ppm;
  UTI_TimevalNetworkToHost(&rx_message->data.settime.ts, &ts);
  if (MNL_AcceptTimestamp(&ts, &offset_cs, &dfreq_ppm, &new_afreq_ppm)) {
    tx_message->status = htons(STT_SUCCESS);
    tx_message->reply = htons(RPY_MANUAL_TIMESTAMP);
    tx_message->data.manual_timestamp.centiseconds = htonl((int32_t)offset_cs);
    tx_message->data.manual_timestamp.dfreq_ppm = UTI_FloatHostToNetwork(dfreq_ppm);
    tx_message->data.manual_timestamp.new_afreq_ppm = UTI_FloatHostToNetwork(new_afreq_ppm);
  } else {
    tx_message->status = htons(STT_NOTENABLED);
  }
}

Project: chrony

accheck_getaddr(char *line, IPAddr *addr)
{
  unsigned long a, b, c, d;
  IPAddr ip;
  char *p;
  p = line;
  if (!*p) {
    return 0;
  } else {
    if (sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d) == 4) {
      addr->family = IPADDR_INET4;
      addr->addr.in4 = (a<<24) | (b<<16) | (c<<8) | d;
      return 1;
    } else {
      if (DNS_Name2IPAddress(p, &ip) != DNS_Success) {
        return 0;
      } else {
        *addr = ip;
        return 1;
      }
    }
  }
}

Project: chrony

handle_trimrtc(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  int status;
  status = RTC_Trim();
  if (status) {
    tx_message->status = htons(STT_SUCCESS);
  } else {
    tx_message->status = htons(STT_NORTC);
  }
}

Project: chrony

handle_(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  int status;
}

Project: chrony

handle_cmdallow(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  IPAddr ip;
  int subnet_bits;
  UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
  subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
  if (CAM_AddAccessRestriction(&ip, subnet_bits, 1, 0)) {
    tx_message->status = htons(STT_SUCCESS);
  } else {
    tx_message->status = htons(STT_BADSUBNET);
  }              
}

Project: chrony

handle_modify_maxpoll(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  int status;
  IPAddr address;
  UTI_IPNetworkToHost(&rx_message->data.modify_minpoll.address, &address);
  status = NSR_ModifyMaxpoll(&address,
                             ntohl(rx_message->data.modify_minpoll.new_minpoll));
  
  if (status) {
    tx_message->status = htons(STT_SUCCESS);
  } else {
    tx_message->status = htons(STT_NOSUCHSOURCE);
  }
}

Project: chrony

read_address_integer(char *line, IPAddr *address, int *value)
{
  char *hostname;
  int ok = 0;

  hostname = line;
  line = CPS_SplitWord(line);

  if (sscanf(line, "%d", value) != 1) {
    fprintf(stderr, "Invalid syntax for address value\n");
    ok = 0;
  } else {
    if (DNS_Name2IPAddress(hostname, address) != DNS_Success) {
      fprintf(stderr, "Could not get address for hostname\n");
      ok = 0;
    } else {
      ok = 1;
    }
  }

  return ok;

}

Project: chrony

transmit_reply(CMD_Reply *msg, union sockaddr_in46 *where_to, int auth_len)
{
  int status;
  int tx_message_length;
  int sock_fd;
  socklen_t addrlen;
  
  switch (where_to->u.sa_family) {
    case AF_INET:
      sock_fd = sock_fd4;
      addrlen = sizeof (where_to->in4);
      break;
#ifdef HAVE_IPV6
    case AF_INET6:
      sock_fd = sock_fd6;
      addrlen = sizeof (where_to->in6);
      break;
#endif
    default:
      assert(0);
  }

  tx_message_length = PKL_ReplyLength(msg) + auth_len;
  status = sendto(sock_fd, (void *) msg, tx_message_length, 0,
                  &where_to->u, addrlen);

  if (status < 0 && !LOG_RateLimited()) {
    unsigned short port;
    IPAddr ip;

    switch (where_to->u.sa_family) {
      case AF_INET:
        ip.family = IPADDR_INET4;
        ip.addr.in4 = ntohl(where_to->in4.sin_addr.s_addr);
        port = ntohs(where_to->in4.sin_port);
        break;
#ifdef HAVE_IPV6
      case AF_INET6:
        ip.family = IPADDR_INET6;
        memcpy(ip.addr.in6, (where_to->in6.sin6_addr.s6_addr), sizeof(ip.addr.in6));
        port = ntohs(where_to->in6.sin6_port);
        break;
#endif
      default:
        assert(0);
    }

    LOG(LOGS_WARN, LOGF_CmdMon, "Could not send response to %s:%hu", UTI_IPToString(&ip), port);
  }
}

Project: chrony

handle_cmddeny(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  IPAddr ip;
  int subnet_bits;
  UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
  subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
  if (CAM_AddAccessRestriction(&ip, subnet_bits, 0, 0)) {
    tx_message->status = htons(STT_SUCCESS);
  } else {
    tx_message->status = htons(STT_BADSUBNET);
  }              
}

Project: chrony

handle_modify_minpoll(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  int status;
  IPAddr address;
  UTI_IPNetworkToHost(&rx_message->data.modify_minpoll.address, &address);
  status = NSR_ModifyMinpoll(&address,
                             ntohl(rx_message->data.modify_minpoll.new_minpoll));
  
  if (status) {
    tx_message->status = htons(STT_SUCCESS);
  } else {
    tx_message->status = htons(STT_NOSUCHSOURCE);
  }
}

Project: chrony

handle_doffset(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  long sec, usec;
  double doffset;
  sec = (long)(ntohl(rx_message->data.doffset.sec));
  usec = (long)(ntohl(rx_message->data.doffset.usec));
  doffset = (double) sec + 1.0e-6 * (double) usec;
  LOG(LOGS_INFO, LOGF_CmdMon, "Accumulated delta offset of %.6f seconds", doffset);
  LCL_AccumulateOffset(doffset, 0.0);
  tx_message->status = htons(STT_SUCCESS);
}

Project: chrony

CAM_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all)
 {
  ADF_Status status;

  if (allow) {
    if (all) {
      status = ADF_AllowAll(access_auth_table, ip_addr, subnet_bits);
    } else {
      status = ADF_Allow(access_auth_table, ip_addr, subnet_bits);
    }
  } else {
    if (all) {
      status = ADF_DenyAll(access_auth_table, ip_addr, subnet_bits);
    } else {
      status = ADF_Deny(access_auth_table, ip_addr, subnet_bits);
    }
  }

  if (status == ADF_BADSUBNET) {
    return 0;
  } else if (status == ADF_SUCCESS) {
    return 1;
  } else {
    return 0;
  }
}

Project: chrony

allocate_ts_cell(void)
{
  TimestampCell *result;
  int i;
  if (free_ts_list == NULL) {
    free_ts_list = MallocArray(TimestampCell, EXTEND_QUANTUM);
    for (i=0; i<EXTEND_QUANTUM-1; i++) {
      free_ts_list[i].next = free_ts_list + i + 1;
    }
    free_ts_list[EXTEND_QUANTUM - 1].next = NULL;
  }

  result = free_ts_list;
  free_ts_list = free_ts_list->next;
  return result;
}

Project: chrony

process_cmd_rtcreport(char *line)
{
  CMD_Request request;
  CMD_Reply reply;
  struct timeval ref_time;
  struct tm ref_time_tm;
  unsigned short n_samples;
  unsigned short n_runs;
  unsigned long span_seconds;
  double coef_seconds_fast;
  double coef_gain_rate_ppm;
  
  request.command = htons(REQ_RTCREPORT);
  if (request_reply(&request, &reply, RPY_RTC, 0)) {
    UTI_TimevalNetworkToHost(&reply.data.rtc.ref_time, &ref_time);
    ref_time_tm = *gmtime(&ref_time.tv_sec);
    n_samples = ntohs(reply.data.rtc.n_samples);
    n_runs = ntohs(reply.data.rtc.n_runs);
    span_seconds = ntohl(reply.data.rtc.span_seconds);
    coef_seconds_fast = UTI_FloatNetworkToHost(reply.data.rtc.rtc_seconds_fast);
    coef_gain_rate_ppm = UTI_FloatNetworkToHost(reply.data.rtc.rtc_gain_rate_ppm);
    printf("RTC ref time (UTC) : %s", asctime(&ref_time_tm));
    printf("Number of samples  : %d\n", n_samples);
    printf("Number of runs     : %d\n", n_runs);
    printf("Sample span period : ");
    print_seconds(span_seconds);
    printf("\n");
    printf("RTC is fast by     : %12.6f seconds\n", coef_seconds_fast);
    printf("RTC gains time at  : %9.3f ppm\n", coef_gain_rate_ppm);
    return 1;
  }
  return 0;
}

Project: chrony

handle_manual(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  int option;
  option = ntohl(rx_message->data.manual.option);
  switch (option) {
    case 0:
      MNL_Disable();
      break;
    case 1:
      MNL_Enable();
      break;
    case 2:
      MNL_Reset();
      break;
  }
  tx_message->status = htons(STT_SUCCESS);
}

Project: chrony

process_args(int argc, char **argv, int multi)
{
  int total_length, i, ret, quit;
  char *line;

  total_length = 0;
  for(i=0; i<argc; i++) {
    total_length += strlen(argv[i]) + 1;
  }

  line = (char *) malloc((2 + total_length) * sizeof(char));

  for (i = 0; i < argc; i++) {
    line[0] = '\0';
    if (multi) {
      strcat(line, argv[i]);
    } else {
      for (; i < argc; i++) {
        strcat(line, argv[i]);
        if (i + 1 < argc)
          strcat(line, " ");
      }
    }

    ret = process_line(line, &quit);
    if (!ret || quit)
      break;
  }

  free(line);

  return ret;
}

Project: chrony

handle_client_accesses_by_index(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  CLG_Status result;
  RPT_ClientAccessByIndex_Report report;
  unsigned long first_index, n_indices, last_index, n_indices_in_table;
  int i, j;
  struct timeval now;

  LCL_ReadCookedTime(&now, NULL);

  first_index = ntohl(rx_message->data.client_accesses_by_index.first_index);
  n_indices = ntohl(rx_message->data.client_accesses_by_index.n_indices);
  last_index = first_index + n_indices - 1;

  tx_message->status = htons(STT_SUCCESS);
  tx_message->reply = htons(RPY_CLIENT_ACCESSES_BY_INDEX);

  for (i = first_index, j = 0;
       (i <= last_index) && (j < MAX_CLIENT_ACCESSES);
       i++) {

    result = CLG_GetClientAccessReportByIndex(i, &report, now.tv_sec, &n_indices_in_table);
    tx_message->data.client_accesses_by_index.n_indices = htonl(n_indices_in_table);

    switch (result) {
      case CLG_SUCCESS:
        UTI_IPHostToNetwork(&report.ip_addr, &tx_message->data.client_accesses_by_index.clients[j].ip);
        tx_message->data.client_accesses_by_index.clients[j].client_hits = htonl(report.client_hits);
        tx_message->data.client_accesses_by_index.clients[j].peer_hits = htonl(report.peer_hits);
        tx_message->data.client_accesses_by_index.clients[j].cmd_hits_auth = htonl(report.cmd_hits_auth);
        tx_message->data.client_accesses_by_index.clients[j].cmd_hits_normal = htonl(report.cmd_hits_normal);
        tx_message->data.client_accesses_by_index.clients[j].cmd_hits_bad = htonl(report.cmd_hits_bad);
        tx_message->data.client_accesses_by_index.clients[j].last_ntp_hit_ago = htonl(report.last_ntp_hit_ago);
        tx_message->data.client_accesses_by_index.clients[j].last_cmd_hit_ago = htonl(report.last_cmd_hit_ago);
        j++;
        break;
      case CLG_INDEXTOOLARGE:
        break; /* ignore this index */
      case CLG_INACTIVE:
        tx_message->status = htons(STT_INACTIVE);
        return;
      default:
        assert(0);
        break;
    }
  }

  tx_message->data.client_accesses_by_index.next_index = htonl(i);
  tx_message->data.client_accesses_by_index.n_clients = htonl(j);
}

Project: chrony

process_cmd_manual_list(const char *line)
{
  CMD_Request request;
  CMD_Reply reply;
  int n_samples;
  RPY_ManualListSample *sample;
  int i;
  struct timeval when;
  double slewed_offset, orig_offset, residual;

  request.command = htons(REQ_MANUAL_LIST);
  if (request_reply(&request, &reply, RPY_MANUAL_LIST, 0)) {
          n_samples = ntohl(reply.data.manual_list.n_samples);
          printf("210 n_samples = %d\n", n_samples);
          printf("#    Date  Time(UTC)    Slewed   Original   Residual\n"
                 "====================================================\n");
          for (i=0; i<n_samples; i++) {
            sample = &reply.data.manual_list.samples[i];
            UTI_TimevalNetworkToHost(&sample->when, &when);
            slewed_offset = UTI_FloatNetworkToHost(sample->slewed_offset);
            orig_offset = UTI_FloatNetworkToHost(sample->orig_offset);
            residual = UTI_FloatNetworkToHost(sample->residual);
            printf("%2d %s %10.2f %10.2f %10.2f\n", i, time_to_log_form(when.tv_sec), slewed_offset, orig_offset, residual);
          }
          return 1;
  }
  return 0;
}

Project: chrony

main(int argc, char **argv)
{
  char *line;
  const char *progname = argv[0];
  const char *hostname = "localhost";
  const char *conf_file = DEFAULT_CONF_FILE;
  int quit = 0, ret = 1, multi = 0, auto_auth = 0;
  int port = DEFAULT_CANDM_PORT;

  /* Parse command line options */
  while (++argv, --argc) {
    if (!strcmp(*argv, "-h")) {
      ++argv, --argc;
      if (*argv) {
        hostname = *argv;
      }
    } else if (!strcmp(*argv, "-p")) {
      ++argv, --argc;
      if (*argv) {
        port = atoi(*argv);
      }
    } else if (!strcmp(*argv, "-f")) {
      ++argv, --argc;
      if (*argv) {
        conf_file = *argv;
      }
    } else if (!strcmp(*argv, "-a")) {
      auto_auth = 1;
    } else if (!strcmp(*argv, "-m")) {
      multi = 1;
    } else if (!strcmp(*argv, "-n")) {
      no_dns = 1;
    } else if (!strcmp(*argv, "-4")) {
      DNS_SetAddressFamily(IPADDR_INET4);
      hostname = "127.0.0.1";
    } else if (!strcmp(*argv, "-6")) {
      DNS_SetAddressFamily(IPADDR_INET6);
      hostname = "::1";
    } else if (!strcmp("-v", *argv) || !strcmp("--version",*argv)) {
      printf("chronyc (chrony) version %s\n", CHRONY_VERSION);
      exit(0);
    } else if (!strncmp(*argv, "-", 1)) {
      fprintf(stderr, "Usage : %s [-h <hostname>] [-p <port-number>] [-n] [-4|-6] [-m] [-a] [-f <file>]] [command]\n", progname);
      exit(1);
    } else {
      break; /* And process remainder of line as a command */
    }
  }

  if (isatty(0) && isatty(1) && isatty(2)) {
    on_terminal = 1;
  }

  if (on_terminal && (argc == 0)) {
    display_gpl();
  }

  /* MD5 is the default authentication hash */
  auth_hash_id = HSH_GetHashId("MD5");
  if (auth_hash_id < 0) {
    fprintf(stderr, "Could not initialize MD5\n");
    return 1;
  }
  
  open_io(hostname, port);

  if (auto_auth) {
    ret = authenticate_from_config(conf_file);
  }

  if (!ret) {
    ;
  } else if (argc > 0) {
    ret = process_args(argc, argv, multi);
  } else {
    do {
      line = read_line();
      if (line) {
        ret = process_line(line, &quit);
      }else {
	/* supply the final '\n' when user exits via ^D */
        if( on_terminal ) printf("\n");
      }
    } while (line && !quit);
  }

  close_io();

  free(password);

  return !ret;
}

Project: chrony

handle_manual_delete(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  int status;
  int index;

  index = ntohl(rx_message->data.manual_delete.index);
  status = MNL_DeleteSample(index);
  if (!status) {
    tx_message->status = htons(STT_BADSAMPLE);
  } else {
    tx_message->status = htons(STT_SUCCESS);
  }
}

Project: chrony

handle_rekey(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  tx_message->status = htons(STT_SUCCESS);
  KEY_Reload();
}

Project: chrony

process_cmd_dfreq(CMD_Request *msg, char *line)
{
  double dfreq;
  msg->command = htons(REQ_DFREQ);
  if (sscanf(line, "%lf", &dfreq) == 1) {
    msg->data.dfreq.dfreq = UTI_FloatHostToNetwork(dfreq);
  } else {
    msg->data.dfreq.dfreq = UTI_FloatHostToNetwork(0.0);
  }
}

Project: chrony

handle_modify_maxdelayratio(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  int status;
  IPAddr address;
  UTI_IPNetworkToHost(&rx_message->data.modify_maxdelayratio.address, &address);
  status = NSR_ModifyMaxdelayratio(&address,
                                   UTI_FloatNetworkToHost(rx_message->data.modify_maxdelayratio.new_max_delay_ratio));
  if (status) {
    tx_message->status = htons(STT_SUCCESS);
  } else {
    tx_message->status = htons(STT_NOSUCHSOURCE);
  }
}

Project: chrony

authenticate_from_config(const char *filename)
{
  CMD_Request tx_message;
  CMD_Reply rx_message;
  char line[2048], keyfile[2048], *command, *arg, *password;
  const char *hashname;
  unsigned long key_id = 0, key_id2 = -1;
  int ret;
  FILE *in;

  in = fopen(filename, "r");
  if (!in) {
    fprintf(stderr, "Could not open file %s\n", filename);
    return 0;
  }

  *keyfile = '\0';
  while (fgets(line, sizeof (line), in)) {
    CPS_NormalizeLine(line);
    command = line;
    arg = CPS_SplitWord(line);
    if (!strcasecmp(command, "keyfile")) {
      snprintf(keyfile, sizeof (keyfile), "%s", arg);
    } else if (!strcasecmp(command, "commandkey")) {
      if (sscanf(arg, "%lu", &key_id) != 1)
        key_id = -1;
    }
  }
  fclose(in);

  if (!*keyfile || key_id == -1) {
    fprintf(stderr, "Could not read keyfile or commandkey in file %s\n", filename);
    return 0;
  }

  in = fopen(keyfile, "r");
  if (!in) {
    fprintf(stderr, "Could not open keyfile %s\n", filename);
    return 0;
  }

  while (fgets(line, sizeof (line), in)) {
    CPS_NormalizeLine(line);
    if (!*line || !CPS_ParseKey(line, &key_id2, &hashname, &password))
      continue;
    if (key_id == key_id2)
      break;
  }
  fclose(in);

  if (key_id == key_id2) {
    if (process_cmd_authhash(hashname) &&
        process_cmd_password(&tx_message, password)) {
      ret = request_reply(&tx_message, &rx_message, RPY_NULL, 1);
    } else {
      ret = 0;
    }
  } else {
    fprintf(stderr, "Could not find key %lu in keyfile %s\n", key_id, keyfile);
    ret = 0;
  }

  /* Erase password from stack */
  memset(line, 0, sizeof (line));

  return ret;
}

Project: chrony

handle_local(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  int on_off, stratum;
  on_off = ntohl(rx_message->data.local.on_off);
  if (on_off) {
    stratum = ntohl(rx_message->data.local.stratum);
    REF_EnableLocal(stratum);
  } else {
    REF_DisableLocal();
  }
  tx_message->status = htons(STT_SUCCESS);
}

Project: chrony

process_cmd_cmddeny(CMD_Request *msg, char *line)
{
  int status;
  msg->command = htons(REQ_CMDDENY);
  status = parse_allow_deny(msg, line);
  return status;
}

Project: chrony

handle_tracking(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  RPT_TrackingReport rpt;

  REF_GetTrackingReport(&rpt);
  tx_message->status = htons(STT_SUCCESS);
  tx_message->reply  = htons(RPY_TRACKING);
  tx_message->data.tracking.ref_id = htonl(rpt.ref_id);
  UTI_IPHostToNetwork(&rpt.ip_addr, &tx_message->data.tracking.ip_addr);
  tx_message->data.tracking.stratum = htons(rpt.stratum);
  tx_message->data.tracking.leap_status = htons(rpt.leap_status);
  UTI_TimevalHostToNetwork(&rpt.ref_time, &tx_message->data.tracking.ref_time);
  tx_message->data.tracking.current_correction = UTI_FloatHostToNetwork(rpt.current_correction);
  tx_message->data.tracking.last_offset = UTI_FloatHostToNetwork(rpt.last_offset);
  tx_message->data.tracking.rms_offset = UTI_FloatHostToNetwork(rpt.rms_offset);
  tx_message->data.tracking.freq_ppm = UTI_FloatHostToNetwork(rpt.freq_ppm);
  tx_message->data.tracking.resid_freq_ppm = UTI_FloatHostToNetwork(rpt.resid_freq_ppm);
  tx_message->data.tracking.skew_ppm = UTI_FloatHostToNetwork(rpt.skew_ppm);
  tx_message->data.tracking.root_delay = UTI_FloatHostToNetwork(rpt.root_delay);
  tx_message->data.tracking.root_dispersion = UTI_FloatHostToNetwork(rpt.root_dispersion);
  tx_message->data.tracking.last_update_interval = UTI_FloatHostToNetwork(rpt.last_update_interval);
}

Project: chrony

generate_tx_packet_auth(CMD_Reply *packet)
{
  int pkt_len;

  pkt_len = PKL_ReplyLength(packet);

  return KEY_GenerateAuth(KEY_GetCommandKey(), (unsigned char *)packet,
      pkt_len, ((unsigned char *)packet) + pkt_len, sizeof (packet->auth));
}

Project: chrony

process_cmd_maxdelayratio(CMD_Request *msg, char *line)
{
  IPAddr address;
  double max_delay_ratio;
  int ok;
  
  if (read_address_double(line, &address, &max_delay_ratio)) {
    UTI_IPHostToNetwork(&address, &msg->data.modify_maxdelayratio.address);
    msg->data.modify_maxdelayratio.new_max_delay_ratio = UTI_FloatHostToNetwork(max_delay_ratio);
    msg->command = htons(REQ_MODIFY_MAXDELAYRATIO);
    ok = 1;
  } else {
    ok = 0;
  }

  return ok;

}

Project: chrony

request_reply(CMD_Request *request, CMD_Reply *reply, int requested_reply, int verbose)
{
  int reply_auth_ok;
  int status;

  if (!submit_request(request, reply, &reply_auth_ok)) {
    printf("506 Cannot talk to daemon\n");
    return 0;
  }

  status = ntohs(reply->status);
        
  if (verbose || status != STT_SUCCESS) {
    switch (status) {
      case STT_SUCCESS:
        printf("200 OK");
        break;
      case STT_ACCESSALLOWED:
        printf("208 Access allowed");
        break;
      case STT_ACCESSDENIED:
        printf("209 Access denied");
        break;
      case STT_FAILED:
        printf("500 Failure");
        break;
      case STT_UNAUTH:
        printf("501 Not authorised");
        break;
      case STT_INVALID:
        printf("502 Invalid command");
        break;
      case STT_NOSUCHSOURCE:
        printf("503 No such source");
        break;
      case STT_INVALIDTS:
        printf("504 Duplicate or stale logon detected");
        break;
      case STT_NOTENABLED:
        printf("505 Facility not enabled in daemon");
        break;
      case STT_BADSUBNET:
        printf("507 Bad subnet");
        break;
      case STT_NOHOSTACCESS:
        printf("510 No command access from this host");
        break;
      case STT_SOURCEALREADYKNOWN:
        printf("511 Source already present");
        break;
      case STT_TOOMANYSOURCES:
        printf("512 Too many sources present");
        break;
      case STT_NORTC:
        printf("513 RTC driver not running");
        break;
      case STT_BADRTCFILE:
        printf("514 Can't write RTC parameters");
        break;
      case STT_INVALIDAF:
        printf("515 Invalid address family");
        break;
      case STT_BADSAMPLE:
        printf("516 Sample index out of range");
        break;
      case STT_BADPKTVERSION:
        printf("517 Protocol version mismatch");
        break;
      case STT_BADPKTLENGTH:
        printf("518 Packet length mismatch");
        break;
      case STT_INACTIVE:
        printf("519 Client logging is not active in the daemon");
        break;
      default:
        printf("520 Got unexpected error from daemon");
    }
    if (reply_auth_ok) {
      printf("\n");
    } else {
      printf(" --- Reply not authenticated\n");
    }
  }
  
  if (status != STT_SUCCESS &&
      status != STT_ACCESSALLOWED && status != STT_ACCESSDENIED) {
    return 0;
  } 

  if (ntohs(reply->reply) != requested_reply) {
    printf("508 Bad reply from daemon\n");
    return 0;
  }

  return 1;
}

Project: chrony

check_reply_auth(CMD_Reply *msg, int len)
{
  int data_len;

  data_len = PKL_ReplyLength(msg);

  assert(auth_hash_id >= 0);

  return UTI_CheckNTPAuth(auth_hash_id, (unsigned char *)password, password_length,
      (unsigned char *)msg, data_len,
      ((unsigned char *)msg) + data_len, len - data_len);
}

Project: chrony

handle_sourcestats(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  int status;
  RPT_SourcestatsReport report;
  struct timeval now_corr;

  LCL_ReadCookedTime(&now_corr, NULL);
  status = SRC_ReportSourcestats(ntohl(rx_message->data.sourcestats.index),
                                 &report, &now_corr);

  if (status) {
    tx_message->status = htons(STT_SUCCESS);
    tx_message->reply = htons(RPY_SOURCESTATS);
    tx_message->data.sourcestats.ref_id = htonl(report.ref_id);
    UTI_IPHostToNetwork(&report.ip_addr, &tx_message->data.sourcestats.ip_addr);
    tx_message->data.sourcestats.n_samples = htonl(report.n_samples);
    tx_message->data.sourcestats.n_runs = htonl(report.n_runs);
    tx_message->data.sourcestats.span_seconds = htonl(report.span_seconds);
    tx_message->data.sourcestats.resid_freq_ppm = UTI_FloatHostToNetwork(report.resid_freq_ppm);
    tx_message->data.sourcestats.skew_ppm = UTI_FloatHostToNetwork(report.skew_ppm);
    tx_message->data.sourcestats.sd = UTI_FloatHostToNetwork(report.sd);
    tx_message->data.sourcestats.est_offset = UTI_FloatHostToNetwork(report.est_offset);
    tx_message->data.sourcestats.est_offset_err = UTI_FloatHostToNetwork(report.est_offset_err);
  } else {
    tx_message->status = htons(STT_NOSUCHSOURCE);
  }
}

Project: chrony

process_cmd_timeout(const char *line)
{
  int timeout;

  timeout = atoi(line);
  if (timeout < 100) {
    fprintf(stderr, "Timeout %d is too short\n", timeout);
    return 0;
  }
  initial_timeout = timeout;
  return 1;
}

Project: chrony

handle_online(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  int status;
  IPAddr address, mask;
  UTI_IPNetworkToHost(&rx_message->data.online.mask, &mask);
  UTI_IPNetworkToHost(&rx_message->data.online.address, &address);
  status = NSR_TakeSourcesOnline(&mask, &address);
  if (status) {
    tx_message->status = htons(STT_SUCCESS);
  } else {
    tx_message->status = htons(STT_NOSUCHSOURCE);
  }
}

Project: chrony

display_gpl(void)
{
    printf("chrony version %s\n"
           "Copyright (C) 1997-2003, 2007, 2009-2013 Richard P. Curnow and others\n"
           "chrony comes with ABSOLUTELY NO WARRANTY.  This is free software, and\n"
           "you are welcome to redistribute it under certain conditions.  See the\n"
           "GNU General Public License version 2 for details.\n\n",
           CHRONY_VERSION);
}

Project: chrony

process_cmd_trimrtc(CMD_Request *msg, char *line)
{
  msg->command = htons(REQ_TRIMRTC);
}

Project: chrony

handle_reselect_distance(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  double dist;
  dist = UTI_FloatNetworkToHost(rx_message->data.reselect_distance.distance);
  SRC_SetReselectDistance(dist);
  tx_message->status = htons(STT_SUCCESS);
}

Project: chrony

process_cmd_denyall(CMD_Request *msg, char *line)
{
  int status;
  msg->command = htons(REQ_DENYALL);
  status = parse_allow_deny(msg, line);
  return status;
}

Project: chrony

save_reply(CMD_Reply *msg,
           unsigned long tok_reply_to,
           unsigned long new_tok_issued,
           unsigned long client_msg_seq,
           unsigned short attempt,
           struct timeval *now)
{
  ResponseCell *cell;

  cell = get_reply_slot();

  cell->ts = *now;
  memcpy(&cell->rpy, msg, sizeof(CMD_Reply));
  cell->tok = tok_reply_to;
  cell->next_tok = new_tok_issued;
  cell->msg_seq = client_msg_seq;
  cell->attempt = (unsigned long) attempt;

  cell->next = kept_replies.next;
  kept_replies.next = cell;

}

Project: chrony

get_token(void)
{
  unsigned long result;

  if (issue_pointer == 32) {
    /* The lowest number open token has not been returned - bad luck
       to that command client */
    shift_tokens();
  }

  result = token_base + issue_pointer;
  issued_tokens |= (1UL << issue_pointer);
  issue_pointer++;

  return result;
}

Project: chrony

lookup_reply(unsigned long prev_msg_token, unsigned long client_msg_seq, unsigned short attempt)
{
  ResponseCell *ptr;

  ptr = kept_replies.next;
  while (ptr) {
    if ((ptr->tok == prev_msg_token) &&
        (ptr->msg_seq == client_msg_seq) &&
        ((unsigned long) attempt > ptr->attempt)) {

      /* Set the attempt field to remember the highest number we have
         had so far */
      ptr->attempt = (unsigned long) attempt;
      return &ptr->rpy;
    }
    ptr = ptr->next;
  }

  return NULL;
}

Project: chrony

handle_allowall(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  IPAddr ip;
  int subnet_bits;
  UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
  subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
  if (NCR_AddAccessRestriction(&ip, subnet_bits, 1, 1)) {
    tx_message->status = htons(STT_SUCCESS);
  } else {
    tx_message->status = htons(STT_BADSUBNET);
  }              
}

Project: chrony

read_from_cmd_socket(void *anything)
{
  int status;
  int read_length; /* Length of packet read */
  int expected_length; /* Expected length of packet without auth data */
  unsigned long flags;
  CMD_Request rx_message;
  CMD_Reply tx_message, *prev_tx_message;
  int rx_message_length, tx_message_length;
  int sock_fd;
  union sockaddr_in46 where_from;
  socklen_t from_length;
  IPAddr remote_ip;
  unsigned short remote_port;
  int auth_length;
  int auth_ok;
  int utoken_ok, token_ok;
  int issue_token;
  int valid_ts;
  int authenticated;
  int localhost;
  int allowed;
  unsigned short rx_command;
  unsigned long rx_message_token;
  unsigned long tx_message_token;
  unsigned long rx_message_seq;
  unsigned long rx_attempt;
  struct timeval now;
  struct timeval cooked_now;

  flags = 0;
  rx_message_length = sizeof(rx_message);
  from_length = sizeof(where_from);

  sock_fd = (long)anything;
  status = recvfrom(sock_fd, (char *)&rx_message, rx_message_length, flags,
                    &where_from.u, &from_length);

  if (status < 0) {
    LOG(LOGS_WARN, LOGF_CmdMon, "Error [%s] reading from control socket %d",
        strerror(errno), sock_fd);
    return;
  }

  read_length = status;

  LCL_ReadRawTime(&now);
  LCL_CookTime(&now, &cooked_now, NULL);

  switch (where_from.u.sa_family) {
    case AF_INET:
      remote_ip.family = IPADDR_INET4;
      remote_ip.addr.in4 = ntohl(where_from.in4.sin_addr.s_addr);
      remote_port = ntohs(where_from.in4.sin_port);
      localhost = (remote_ip.addr.in4 == 0x7f000001UL);
      break;
#ifdef HAVE_IPV6
    case AF_INET6:
      remote_ip.family = IPADDR_INET6;
      memcpy(&remote_ip.addr.in6, where_from.in6.sin6_addr.s6_addr,
          sizeof (remote_ip.addr.in6));
      remote_port = ntohs(where_from.in6.sin6_port);
      /* Check for ::1 */
      for (localhost = 0; localhost < 16; localhost++)
        if (remote_ip.addr.in6[localhost] != 0)
          break;
      localhost = (localhost == 15 && remote_ip.addr.in6[localhost] == 1);
      break;
#endif
    default:
      assert(0);
  }

  allowed = ADF_IsAllowed(access_auth_table, &remote_ip) || localhost;

  /* Message size sanity check */
  if (read_length >= offsetof(CMD_Request, data)) {
    expected_length = PKL_CommandLength(&rx_message);
  } else {
    expected_length = 0;
  }

  if (expected_length < offsetof(CMD_Request, data) ||
      rx_message.pkt_type != PKT_TYPE_CMD_REQUEST ||
      rx_message.res1 != 0 ||
      rx_message.res2 != 0) {

    /* We don't know how to process anything like this */
    if (allowed)
      CLG_LogCommandAccess(&remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec);
    
    return;
  }

  rx_command = ntohs(rx_message.command);

  tx_message.version = PROTO_VERSION_NUMBER;
  tx_message.pkt_type = PKT_TYPE_CMD_REPLY;
  tx_message.res1 = 0;
  tx_message.res2 = 0;
  tx_message.command = rx_message.command;
  tx_message.sequence = rx_message.sequence;
  tx_message.reply = htons(RPY_NULL);
  tx_message.number = htons(1);
  tx_message.total = htons(1);
  tx_message.pad1 = 0;
  tx_message.utoken = htonl(utoken);
  /* Set this to a default (invalid) value.  This protects against the
     token field being set to an arbitrary value if we reject the
     message, e.g. due to the host failing the access check. */
  tx_message.token = htonl(0xffffffffUL);
  memset(&tx_message.auth, 0, sizeof(tx_message.auth));

  if (rx_message.version != PROTO_VERSION_NUMBER) {
    tx_message.status = htons(STT_NOHOSTACCESS);
    if (!LOG_RateLimited()) {
      LOG(LOGS_WARN, LOGF_CmdMon, "Read command packet with protocol version %d (expected %d) from %s:%hu", rx_message.version, PROTO_VERSION_NUMBER, UTI_IPToString(&remote_ip), remote_port);
    }
    if (allowed)
      CLG_LogCommandAccess(&remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec);

    if (rx_message.version >= PROTO_VERSION_MISMATCH_COMPAT) {
      tx_message.status = htons(STT_BADPKTVERSION);
      /* add empty MD5 auth so older clients will not drop
         the reply due to bad length */
      memset(((char *)&tx_message) + PKL_ReplyLength(&tx_message), 0, 16);
      transmit_reply(&tx_message, &where_from, 16);
    }
    return;
  }

  if (rx_command >= N_REQUEST_TYPES) {
    if (!LOG_RateLimited()) {
      LOG(LOGS_WARN, LOGF_CmdMon, "Read command packet with invalid command %d from %s:%hu", rx_command, UTI_IPToString(&remote_ip), remote_port);
    }
    if (allowed)
      CLG_LogCommandAccess(&remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec);

    tx_message.status = htons(STT_INVALID);
    transmit_reply(&tx_message, &where_from, 0);
    return;
  }

  if (read_length < expected_length) {
    if (!LOG_RateLimited()) {
      LOG(LOGS_WARN, LOGF_CmdMon, "Read incorrectly sized command packet from %s:%hu", UTI_IPToString(&remote_ip), remote_port);
    }
    if (allowed)
      CLG_LogCommandAccess(&remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec);

    tx_message.status = htons(STT_BADPKTLENGTH);
    transmit_reply(&tx_message, &where_from, 0);
    return;
  }

  if (!allowed) {
    /* The client is not allowed access, so don't waste any more time
       on him.  Note that localhost is always allowed access
       regardless of the defined access rules - otherwise, we could
       shut ourselves out completely! */

    if (!LOG_RateLimited()) {
      LOG(LOGS_WARN, LOGF_CmdMon, "Command packet received from unauthorised host %s port %d",
          UTI_IPToString(&remote_ip),
          remote_port);
    }

    tx_message.status = htons(STT_NOHOSTACCESS);
    transmit_reply(&tx_message, &where_from, 0);

    return;
  }

  /* OK, we have a valid message.  Now dispatch on message type and process it. */

  /* Do authentication stuff and command tokens here.  Well-behaved
     clients will set their utokens to 0 to save us wasting our time
     if the packet is unauthenticatable. */
  if (rx_message.utoken != 0) {
    auth_ok = check_rx_packet_auth(&rx_message, read_length);
  } else {
    auth_ok = 0;
  }

  /* All this malarky is to protect the system against various forms
     of attack.

     Simple packet forgeries are blocked by requiring the packet to
     authenticate properly with MD5 or other crypto hash.  (The
     assumption is that the command key is in a read-only keys file
     read by the daemon, and is known only to administrators.)

     Replay attacks are prevented by 2 fields in the packet.  The
     'token' field is where the client plays back to us a token that
     he was issued in an earlier reply.  Each time we reply to a
     suitable packet, we issue a new token.  The 'utoken' field is set
     to a new (hopefully increasing) value each time the daemon is
     run.  This prevents packets from a previous incarnation being
     played back at us when the same point in the 'token' sequence
     comes up.  (The token mechanism also prevents a non-idempotent
     command from being executed twice from the same client, if the
     client fails to receive our reply the first time and tries a
     resend.)

     The problem is how a client should get its first token.  Our
     token handling only remembers a finite number of issued tokens
     (actually 32) - if a client replies with a (legitimate) token
     older than that, it will be treated as though a duplicate token
     has been supplied.  If a simple token-request protocol were used,
     the whole thing would be vulnerable to a denial of service
     attack, where an attacker just replays valid token-request
     packets at us, causing us to keep issuing new tokens,
     invalidating all the ones we have given out to true clients
     already.

     To protect against this, the token-request (REQ_LOGON) packet
     includes a timestamp field.  To issue a token, we require that
     this field is different from any we have processed before.  To
     bound our storage, we require that the timestamp is within a
     certain period of our current time.  For clients running on the
     same host this will be easily satisfied.

     */

  utoken_ok = (ntohl(rx_message.utoken) == utoken);

  /* Avoid binning a valid user's token if we merely get a forged
     packet */
  rx_message_token = ntohl(rx_message.token);
  rx_message_seq = ntohl(rx_message.sequence);
  rx_attempt = ntohs(rx_message.attempt);

  if (auth_ok && utoken_ok) {
    token_ok = check_token(rx_message_token);
  } else {
    token_ok = 0;
  }

  if (auth_ok && utoken_ok && !token_ok) {
    /* This might be a resent message, due to the client not getting
       our reply to the first attempt.  See if we can find the message. */
    prev_tx_message = lookup_reply(rx_message_token, rx_message_seq, rx_attempt);
    if (prev_tx_message) {
      /* Just send this message again */
      tx_message_length = PKL_ReplyLength(prev_tx_message);
      status = sendto(sock_fd, (void *) prev_tx_message, tx_message_length, 0,
                      &where_from.u, from_length);
      if (status < 0 && !LOG_RateLimited()) {
        LOG(LOGS_WARN, LOGF_CmdMon, "Could not send response to %s:%hu", UTI_IPToString(&remote_ip), remote_port);
      }
      return;
    }
    /* Otherwise, just fall through into normal processing */

  }

  if (auth_ok && utoken_ok && token_ok) {
    /* See whether we can discard the previous reply from storage */
    token_acknowledged(rx_message_token, &now);
  }

  valid_ts = 0;

  if (auth_ok) {
    struct timeval ts;

    UTI_TimevalNetworkToHost(&rx_message.data.logon.ts, &ts);
    if ((utoken_ok && token_ok) ||
        ((ntohl(rx_message.utoken) == SPECIAL_UTOKEN) &&
         (rx_command == REQ_LOGON) &&
         (valid_ts = ts_is_unique_and_not_stale(&ts, &now))))
      issue_token = 1;
    else 
      issue_token = 0;
  } else {
    issue_token = 0;
  }

  authenticated = auth_ok & utoken_ok & token_ok;

  if (authenticated) {
    CLG_LogCommandAccess(&remote_ip, CLG_CMD_AUTH, cooked_now.tv_sec);
  } else {
    CLG_LogCommandAccess(&remote_ip, CLG_CMD_NORMAL, cooked_now.tv_sec);
  }

  if (issue_token) {
    /* Only command clients where the user has apparently 'logged on'
       get a token to allow them to emit an authenticated command next
       time */
    tx_message_token = get_token();
  } else {
    tx_message_token = 0xffffffffUL;
  }

  tx_message.token = htonl(tx_message_token);


  if (rx_command >= N_REQUEST_TYPES) {
    /* This should be already handled */
    assert(0);
  } else {
    allowed = 0;

    /* Check level of authority required to issue the command */
    switch(permissions[rx_command]) {
      case PERMIT_AUTH:
        if (authenticated) {
          allowed = 1;
        } else {
          allowed = 0;
        }
        break;
      case PERMIT_LOCAL:
        if (authenticated || localhost) {
          allowed = 1;
        } else {
          allowed = 0;
        }
        break;
      case PERMIT_OPEN:
        allowed = 1;
        break;
      default:
        assert(0);
    }

    if (allowed) {
      switch(rx_command) {
        case REQ_NULL:
          handle_null(&rx_message, &tx_message);
          break;

        case REQ_ONLINE:
          handle_online(&rx_message, &tx_message);
          break;

        case REQ_OFFLINE:
          handle_offline(&rx_message, &tx_message);
          break;

        case REQ_BURST:
          handle_burst(&rx_message, &tx_message);
          break;

        case REQ_MODIFY_MINPOLL:
          handle_modify_minpoll(&rx_message, &tx_message);
          break;

        case REQ_MODIFY_MAXPOLL:
          handle_modify_maxpoll(&rx_message, &tx_message);
          break;

        case REQ_DUMP:
          SRC_DumpSources();
          tx_message.status = htons(STT_SUCCESS);
          break;

        case REQ_MODIFY_MAXDELAY:
          handle_modify_maxdelay(&rx_message, &tx_message);
          break;

        case REQ_MODIFY_MAXDELAYRATIO:
          handle_modify_maxdelayratio(&rx_message, &tx_message);
          break;

        case REQ_MODIFY_MAXDELAYDEVRATIO:
          handle_modify_maxdelaydevratio(&rx_message, &tx_message);
          break;

        case REQ_MODIFY_MAXUPDATESKEW:
          handle_modify_maxupdateskew(&rx_message, &tx_message);
          break;

        case REQ_LOGON:
          /* If the log-on fails, record the reason why */
          if (!issue_token && !LOG_RateLimited()) {
            LOG(LOGS_WARN, LOGF_CmdMon,
                "Bad command logon from %s port %d (auth_ok=%d valid_ts=%d)",
                UTI_IPToString(&remote_ip),
                remote_port,
                auth_ok, valid_ts);
          }

          if (issue_token == 1) {
            tx_message.status = htons(STT_SUCCESS);
          } else if (!auth_ok) {
            tx_message.status = htons(STT_UNAUTH);
          } else if (!valid_ts) {
            tx_message.status = htons(STT_INVALIDTS);
          } else {
            tx_message.status = htons(STT_FAILED);
          }
            
          break;

        case REQ_SETTIME:
          handle_settime(&rx_message, &tx_message);
          break;
        
        case REQ_LOCAL:
          handle_local(&rx_message, &tx_message);
          break;

        case REQ_MANUAL:
          handle_manual(&rx_message, &tx_message);
          break;

        case REQ_N_SOURCES:
          handle_n_sources(&rx_message, &tx_message);
          break;

        case REQ_SOURCE_DATA:
          handle_source_data(&rx_message, &tx_message);
          break;

        case REQ_REKEY:
          handle_rekey(&rx_message, &tx_message);
          break;

        case REQ_ALLOW:
          handle_allow(&rx_message, &tx_message);
          break;

        case REQ_ALLOWALL:
          handle_allowall(&rx_message, &tx_message);
          break;

        case REQ_DENY:
          handle_deny(&rx_message, &tx_message);
          break;

        case REQ_DENYALL:
          handle_denyall(&rx_message, &tx_message);
          break;

        case REQ_CMDALLOW:
          handle_cmdallow(&rx_message, &tx_message);
          break;

        case REQ_CMDALLOWALL:
          handle_cmdallowall(&rx_message, &tx_message);
          break;

        case REQ_CMDDENY:
          handle_cmddeny(&rx_message, &tx_message);
          break;

        case REQ_CMDDENYALL:
          handle_cmddenyall(&rx_message, &tx_message);
          break;

        case REQ_ACCHECK:
          handle_accheck(&rx_message, &tx_message);
          break;

        case REQ_CMDACCHECK:
          handle_cmdaccheck(&rx_message, &tx_message);
          break;

        case REQ_ADD_SERVER:
          handle_add_source(NTP_SERVER, &rx_message, &tx_message);
          break;

        case REQ_ADD_PEER:
          handle_add_source(NTP_PEER, &rx_message, &tx_message);
          break;

        case REQ_DEL_SOURCE:
          handle_del_source(&rx_message, &tx_message);
          break;

        case REQ_WRITERTC:
          handle_writertc(&rx_message, &tx_message);
          break;
          
        case REQ_DFREQ:
          handle_dfreq(&rx_message, &tx_message);
          break;

        case REQ_DOFFSET:
          handle_doffset(&rx_message, &tx_message);
          break;

        case REQ_TRACKING:
          handle_tracking(&rx_message, &tx_message);
          break;

        case REQ_SOURCESTATS:
          handle_sourcestats(&rx_message, &tx_message);
          break;

        case REQ_RTCREPORT:
          handle_rtcreport(&rx_message, &tx_message);
          break;
          
        case REQ_TRIMRTC:
          handle_trimrtc(&rx_message, &tx_message);
          break;

        case REQ_CYCLELOGS:
          handle_cyclelogs(&rx_message, &tx_message);
          break;

        case REQ_SUBNETS_ACCESSED:
          handle_subnets_accessed(&rx_message, &tx_message);
          break;

        case REQ_CLIENT_ACCESSES:
          handle_client_accesses(&rx_message, &tx_message);
          break;

        case REQ_CLIENT_ACCESSES_BY_INDEX:
          handle_client_accesses_by_index(&rx_message, &tx_message);
          break;

        case REQ_MANUAL_LIST:
          handle_manual_list(&rx_message, &tx_message);
          break;

        case REQ_MANUAL_DELETE:
          handle_manual_delete(&rx_message, &tx_message);
          break;

        case REQ_MAKESTEP:
          handle_make_step(&rx_message, &tx_message);
          break;

        case REQ_ACTIVITY:
          handle_activity(&rx_message, &tx_message);
          break;

        case REQ_RESELECTDISTANCE:
          handle_reselect_distance(&rx_message, &tx_message);
          break;

        case REQ_RESELECT:
          handle_reselect(&rx_message, &tx_message);
          break;

        case REQ_MODIFY_MINSTRATUM:
          handle_modify_minstratum(&rx_message, &tx_message);
          break;

        case REQ_MODIFY_POLLTARGET:
          handle_modify_polltarget(&rx_message, &tx_message);
          break;

        default:
          assert(0);
          break;
      }
    } else {
      tx_message.status = htons(STT_UNAUTH);
    }
  }

  if (auth_ok) {
    auth_length = generate_tx_packet_auth(&tx_message);
  } else {
    auth_length = 0;
  }

  if (token_ok) {
    save_reply(&tx_message,
               rx_message_token,
               tx_message_token,
               rx_message_seq,
               rx_attempt,
               &now);
  }

  /* Transmit the response */
  {
    /* Include a simple way to lose one message in three to test resend */

    static int do_it=1;

    if (do_it) {
      transmit_reply(&tx_message, &where_from, auth_length);
    }

#if 0
    do_it = ((do_it + 1) % 3);
#endif
  }
}

Project: chrony

handle_manual_list(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  int n_samples;
  int i;
  RPY_ManualListSample *sample;
  RPT_ManualSamplesReport report[MAX_MANUAL_LIST_SAMPLES];

  tx_message->status = htons(STT_SUCCESS);
  tx_message->reply = htons(RPY_MANUAL_LIST);
  
  MNL_ReportSamples(report, MAX_MANUAL_LIST_SAMPLES, &n_samples);
  tx_message->data.manual_list.n_samples = htonl(n_samples);
  for (i=0; i<n_samples; i++) {
    sample = &tx_message->data.manual_list.samples[i];
    UTI_TimevalHostToNetwork(&report[i].when, &sample->when);
    sample->slewed_offset = UTI_FloatHostToNetwork(report[i].slewed_offset);
    sample->orig_offset = UTI_FloatHostToNetwork(report[i].orig_offset);
    sample->residual = UTI_FloatHostToNetwork(report[i].residual);
  }
}

Project: chrony

handle_modify_maxdelaydevratio(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  int status;
  IPAddr address;
  UTI_IPNetworkToHost(&rx_message->data.modify_maxdelaydevratio.address, &address);
  status = NSR_ModifyMaxdelaydevratio(&address,
                                   UTI_FloatNetworkToHost(rx_message->data.modify_maxdelaydevratio.new_max_delay_dev_ratio));
  if (status) {
    tx_message->status = htons(STT_SUCCESS);
  } else {
    tx_message->status = htons(STT_NOSUCHSOURCE);
  }
}

Project: chrony

process_cmd_dump(CMD_Request *msg, char *line)
{
  msg->command = htons(REQ_DUMP);
  msg->data.dump.pad = htonl(0);
}

Project: chrony

check_token(unsigned long token)
{
  int result;
  unsigned long pos;

  if (token < token_base) {
    /* Token too old */
    result = 0;
  } else {
    pos = token - token_base;
    if (pos >= issue_pointer) {
      /* Token hasn't been issued yet */
      result = 0;
    } else {
      if (returned_tokens & (1UL << pos)) {
        /* Token has already been returned */
        result = 0;
      } else {
        /* Token is OK */
        result = 1;
        returned_tokens |= (1UL << pos);
        if (pos == 0) {
          shift_tokens();
        }
      }
    }
  }

  return result;

}

Project: chrony

give_help(void)
{
  printf("Commands:\n");
  printf("accheck <address> : Check whether NTP access is allowed to <address>\n");
  printf("activity : Check how many NTP sources are online/offline\n");
  printf("add peer <address> ... : Add a new NTP peer\n");
  printf("add server <address> ... : Add a new NTP server\n");
  printf("allow [<subnet-addr>] : Allow NTP access to that subnet as a default\n");
  printf("allow all [<subnet-addr>] : Allow NTP access to that subnet and all children\n");
  printf("burst <n-good>/<n-max> [<mask>/<masked-address>] : Start a rapid set of measurements\n");
  printf("clients : Report on clients that have accessed the server\n");
  printf("cmdaccheck <address> : Check whether command access is allowed to <address>\n");
  printf("cmdallow [<subnet-addr>] : Allow command access to that subnet as a default\n");
  printf("cmdallow all [<subnet-addr>] : Allow command access to that subnet and all children\n");
  printf("cmddeny [<subnet-addr>] : Deny command access to that subnet as a default\n");
  printf("cmddeny all [<subnet-addr>] : Deny command access to that subnet and all children\n");
  printf("cyclelogs : Close and re-open logs files\n");
  printf("delete <address> : Remove an NTP server or peer\n");
  printf("deny [<subnet-addr>] : Deny NTP access to that subnet as a default\n");
  printf("deny all [<subnet-addr>] : Deny NTP access to that subnet and all children\n");
  printf("dump : Dump all measurements to save files\n");
  printf("local off : Disable server capability for unsynchronised clock\n");
  printf("local stratum <stratum> : Enable server capability for unsynchronised clock\n");
  printf("makestep : Jump the time to remove any correction being slewed\n");
  printf("manual off|on|reset : Disable/enable/reset settime command and statistics\n");
  printf("manual list : Show previous settime entries\n");
  printf("maxdelay <address> <new-max-delay> : Modify maximum round-trip valid sample delay for source\n");
  printf("maxdelayratio <address> <new-max-ratio> : Modify max round-trip delay ratio for source\n");
  printf("maxdelaydevratio <address> <new-max-ratio> : Modify max round-trip delay dev ratio for source\n");
  printf("maxpoll <address> <new-maxpoll> : Modify maximum polling interval of source\n");
  printf("maxupdateskew <new-max-skew> : Modify maximum skew for a clock frequency update to be made\n");
  printf("minpoll <address> <new-minpoll> : Modify minimum polling interval of source\n");
  printf("minstratum <address> <new-min-stratum> : Modify minimum stratum of source\n");
  printf("offline [<mask>/<masked-address>] : Set sources in subnet to offline status\n");
  printf("online [<mask>/<masked-address>] : Set sources in subnet to online status\n");
  printf("password [<new-password>] : Set command authentication password\n");
  printf("polltarget <address> <new-poll-target> : Modify poll target of source\n");
  printf("reselect : Reselect synchronisation source\n");
  printf("rtcdata : Print current RTC performance parameters\n");
  printf("settime <date/time (e.g. Nov 21, 1997 16:30:05 or 16:30:05)> : Manually set the daemon time\n");
  printf("sources [-v] : Display information about current sources\n");
  printf("sourcestats [-v] : Display estimation information about current sources\n");
  printf("tracking : Display system time information\n");
  printf("trimrtc : Correct RTC relative to system clock\n");
  printf("waitsync [max-tries [max-correction [max-skew]]] : Wait until synchronised\n");
  printf("writertc : Save RTC parameters to file\n");
  printf("\n");
  printf("authhash <name>: Set command authentication hash function\n");
  printf("dns -n|+n : Disable/enable resolving IP addresses to hostnames\n");
  printf("dns -4|-6|-46 : Resolve hostnames only to IPv4/IPv6/both addresses\n");
  printf("timeout <milliseconds> : Set initial response timeout\n");
  printf("retries <n> : Set maximum number of retries\n");
  printf("exit|quit : Leave the program\n");
  printf("help : Generate this help\n");
  printf("\n");
}

Project: chrony

parse_allow_deny(CMD_Request *msg, char *line)
{
  unsigned long a, b, c, d, n;
  IPAddr ip;
  char *p;
  
  p = line;
  if (!*p) {
    /* blank line - applies to all addresses */
    ip.family = IPADDR_UNSPEC;
    UTI_IPHostToNetwork(&ip, &msg->data.allow_deny.ip);
    msg->data.allow_deny.subnet_bits = htonl(0);
  } else {
    char *slashpos;
    slashpos = strchr(p, '/');
    if (slashpos) *slashpos = 0;
    
    n = 0;
    if (!UTI_StringToIP(p, &ip) &&
        (n = sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d)) == 0) {

      /* Try to parse as the name of a machine */
      if (DNS_Name2IPAddress(p, &ip) != DNS_Success) {
        fprintf(stderr, "Could not read address\n");
        return 0;
      } else {
        UTI_IPHostToNetwork(&ip, &msg->data.allow_deny.ip);
        if (ip.family == IPADDR_INET6)
          msg->data.allow_deny.subnet_bits = htonl(128);
        else
          msg->data.allow_deny.subnet_bits = htonl(32);
      }        
    } else {
      
      if (n == 0) {
        if (ip.family == IPADDR_INET6)
          msg->data.allow_deny.subnet_bits = htonl(128);
        else
          msg->data.allow_deny.subnet_bits = htonl(32);
      } else {
        ip.family = IPADDR_INET4;

        a &= 0xff;
        b &= 0xff;
        c &= 0xff;
        d &= 0xff;
        
        switch (n) {
          case 1:
            ip.addr.in4 = htonl((a<<24));
            msg->data.allow_deny.subnet_bits = htonl(8);
            break;
          case 2:
            ip.addr.in4 = htonl((a<<24) | (b<<16));
            msg->data.allow_deny.subnet_bits = htonl(16);
            break;
          case 3:
            ip.addr.in4 = htonl((a<<24) | (b<<16) | (c<<8));
            msg->data.allow_deny.subnet_bits = htonl(24);
            break;
          case 4:
            ip.addr.in4 = htonl((a<<24) | (b<<16) | (c<<8) | d);
            msg->data.allow_deny.subnet_bits = htonl(32);
            break;
          default:
            assert(0);
        }
      }

      UTI_IPHostToNetwork(&ip, &msg->data.allow_deny.ip);

      if (slashpos) {
        int specified_subnet_bits, n;
        n = sscanf(slashpos+1, "%d", &specified_subnet_bits);
        if (n == 1) {
          msg->data.allow_deny.subnet_bits = htonl(specified_subnet_bits);
        } else {
          fprintf(stderr, "Warning: badly formatted subnet size, using %ld\n", (long) ntohl(msg->data.allow_deny.subnet_bits));
        }
      } 
    }
  }
  return 1;
}

Project: chrony

process_cmd_maxdelaydevratio(CMD_Request *msg, char *line)
{
  IPAddr address;
  double max_delay_dev_ratio;
  int ok;
  
  if (read_address_double(line, &address, &max_delay_dev_ratio)) {
    UTI_IPHostToNetwork(&address, &msg->data.modify_maxdelaydevratio.address);
    msg->data.modify_maxdelayratio.new_max_delay_ratio = UTI_FloatHostToNetwork(max_delay_dev_ratio);
    msg->command = htons(REQ_MODIFY_MAXDELAYDEVRATIO);
    ok = 1;
  } else {
    ok = 0;
  }

  return ok;

}

Project: chrony

process_cmd_cmddenyall(CMD_Request *msg, char *line)
{
  int status;
  msg->command = htons(REQ_CMDDENYALL);
  status = parse_allow_deny(msg, line);
  return status;
}

Project: chrony

handle_dfreq(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  double dfreq;
  dfreq = UTI_FloatNetworkToHost(rx_message->data.dfreq.dfreq);
  LCL_AccumulateDeltaFrequency(dfreq * 1.0e-6);
  LOG(LOGS_INFO, LOGF_CmdMon, "Accumulated delta freq of %.3fppm", dfreq);
  tx_message->status = htons(STT_SUCCESS);
}

Project: chrony

handle_rtcreport(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  int status;
  RPT_RTC_Report report;
  status = RTC_GetReport(&report);
  if (status) {
    tx_message->status = htons(STT_SUCCESS);
    tx_message->reply  = htons(RPY_RTC);
    UTI_TimevalHostToNetwork(&report.ref_time, &tx_message->data.rtc.ref_time);
    tx_message->data.rtc.n_samples = htons(report.n_samples);
    tx_message->data.rtc.n_runs = htons(report.n_runs);
    tx_message->data.rtc.span_seconds = htonl(report.span_seconds);
    tx_message->data.rtc.rtc_seconds_fast = UTI_FloatHostToNetwork(report.rtc_seconds_fast);
    tx_message->data.rtc.rtc_gain_rate_ppm = UTI_FloatHostToNetwork(report.rtc_gain_rate_ppm);
  } else {
    tx_message->status = htons(STT_NORTC);
  }
}

Project: chrony

    if (clients_looked_up == 0) {
      /* No more clients to do */
      break;
    }

Project: chrony

process_cmd_clients(char *line)
{
  CMD_Request request;
  CMD_Reply reply;
  unsigned long next_index;
  int j;
  IPAddr ip;
  unsigned long client_hits;
  unsigned long peer_hits;
  unsigned long cmd_hits_auth;
  unsigned long cmd_hits_normal;
  unsigned long cmd_hits_bad;
  unsigned long last_ntp_hit_ago;
  unsigned long last_cmd_hit_ago;
  char hostname_buf[50];

  int n_replies;
  int n_indices_in_table;

  next_index = 0;

  printf("Hostname                   Client    Peer CmdAuth CmdNorm  CmdBad  LstN  LstC\n"
         "=========================  ======  ======  ======  ======  ======  ====  ====\n");

  do {

    request.command = htons(REQ_CLIENT_ACCESSES_BY_INDEX);
    request.data.client_accesses_by_index.first_index = htonl(next_index);
    request.data.client_accesses_by_index.n_indices = htonl(MAX_CLIENT_ACCESSES);

    if (request_reply(&request, &reply, RPY_CLIENT_ACCESSES_BY_INDEX, 0)) {
          n_replies = ntohl(reply.data.client_accesses_by_index.n_clients);
          n_indices_in_table = ntohl(reply.data.client_accesses_by_index.n_indices);
          if (n_replies == 0) {
            goto finished;
          }
          for (j=0; j<n_replies; j++) {
            UTI_IPNetworkToHost(&reply.data.client_accesses_by_index.clients[j].ip, &ip);
            if (ip.family != IPADDR_UNSPEC) {
              /* UNSPEC implies that the node could not be found in
                 the daemon's tables; we shouldn't ever generate this
                 case, but ignore it if we do.  (In future there might
                 be a protocol to reset the client logging; if another
                 administrator runs that while we're doing the clients
                 command, there will be a race condition that could
                 cause this). */
              
              client_hits = ntohl(reply.data.client_accesses_by_index.clients[j].client_hits);
              peer_hits = ntohl(reply.data.client_accesses_by_index.clients[j].peer_hits);
              cmd_hits_auth = ntohl(reply.data.client_accesses_by_index.clients[j].cmd_hits_auth);
              cmd_hits_normal = ntohl(reply.data.client_accesses_by_index.clients[j].cmd_hits_normal);
              cmd_hits_bad = ntohl(reply.data.client_accesses_by_index.clients[j].cmd_hits_bad);
              last_ntp_hit_ago = ntohl(reply.data.client_accesses_by_index.clients[j].last_ntp_hit_ago);
              last_cmd_hit_ago = ntohl(reply.data.client_accesses_by_index.clients[j].last_cmd_hit_ago);

              if (no_dns) {
                snprintf(hostname_buf, sizeof(hostname_buf),
                         "%s", UTI_IPToString(&ip));
              } else {
                DNS_IPAddress2Name(&ip, hostname_buf, sizeof(hostname_buf));
                hostname_buf[25] = 0;
              }
              printf("%-25s  %6ld  %6ld  %6ld  %6ld  %6ld  ",
                     hostname_buf,
                     client_hits, peer_hits,
                     cmd_hits_auth, cmd_hits_normal, cmd_hits_bad);
              print_seconds(last_ntp_hit_ago);
              printf("  ");
              print_seconds(last_cmd_hit_ago);
              printf("\n");
            }
          }              

          /* Set the next index to probe based on what the server tells us */
          next_index = ntohl(reply.data.client_accesses_by_index.next_index);
          if (next_index >= n_indices_in_table) {
            goto finished;
          }
    } else {
      return 0;
    }
  } while (1); /* keep going until all subnets have been expanded,
                  down to single nodes */

finished:
  return 1;
}

Project: chrony

process_cmd_reselectdist(CMD_Request *msg, char *line)
{
  double dist;
  int ok;
  msg->command = htons(REQ_RESELECTDISTANCE);
  if (sscanf(line, "%lf", &dist) == 1) {
    msg->data.reselect_distance.distance = UTI_FloatHostToNetwork(dist);
    ok = 1;
  } else {
    ok = 0;
  }
  return ok;
}

Project: chrony

print_signed_nanoseconds(double s)
{
  double x;

  x = fabs(s);

  if (x < 9999.5e-9) {
    printf("%+5.0fns", s * 1e9);
  } else if (x < 9999.5e-6) {
    printf("%+5.0fus", s * 1e6);
  } else if (x < 9999.5e-3) {
    printf("%+5.0fms", s * 1e3);
  } else if (x < 999.5) {
    printf("%+6.1fs", s);
  } else if (x < 99999.5) {
    printf("%+6.0fs", s);
  } else if (x < 99999.5 * 60) {
    printf("%+6.0fm", s / 60);
  } else if (x < 99999.5 * 3600) {
    printf("%+6.0fh", s / 3600);
  } else if (x < 99999.5 * 3600 * 24) {
    printf("%+6.0fd", s / (3600 * 24));
  } else {
    printf("%+6.0fy", s / (3600 * 24 * 365));
  }
}

Project: chrony

process_cmd_allowall(CMD_Request *msg, char *line)
{
  int status;
  msg->command = htons(REQ_ALLOWALL);
  status = parse_allow_deny(msg, line);
  return status;
}

Project: chrony

process_cmd_waitsync(char *line)
{
  CMD_Request request;
  CMD_Reply reply;
  uint32_t ref_id, a, b, c, d;
  double correction, skew_ppm, max_correction, max_skew_ppm;
  int ret = 0, max_tries, i;

  max_tries = 0;
  max_correction = 0.0;
  max_skew_ppm = 0.0;

  sscanf(line, "%d %lf %lf", &max_tries, &max_correction, &max_skew_ppm);

  request.command = htons(REQ_TRACKING);

  for (i = 1; ; i++) {
    if (request_reply(&request, &reply, RPY_TRACKING, 0)) {
      ref_id = ntohl(reply.data.tracking.ref_id);
      a = (ref_id >> 24);
      b = (ref_id >> 16) & 0xff;
      c = (ref_id >> 8) & 0xff;
      d = (ref_id) & 0xff;

      correction = UTI_FloatNetworkToHost(reply.data.tracking.current_correction);
      correction = fabs(correction);
      skew_ppm = UTI_FloatNetworkToHost(reply.data.tracking.skew_ppm);

      printf("try: %d, refid: %d.%d.%d.%d, correction: %.9f, skew: %.3f\n",
          i, a, b, c, d, correction, skew_ppm);

      if (ref_id != 0 && ref_id != 0x7f7f0101L /* LOCAL refid */ &&
          (max_correction == 0.0 || correction <= max_correction) &&
          (max_skew_ppm == 0.0 || skew_ppm <= max_skew_ppm)) {
        ret = 1;
      }
    }

    if (!ret && (!max_tries || i < max_tries)) {
      sleep(10);
    } else {
      break;
    }
  }
  return ret;
}

Project: chrony

process_cmd_activity(const char *line)
{
  CMD_Request request;
  CMD_Reply reply;
  request.command = htons(REQ_ACTIVITY);
  if (request_reply(&request, &reply, RPY_ACTIVITY, 1)) {
        printf(
               "%ld sources online\n"
               "%ld sources offline\n"
               "%ld sources doing burst (return to online)\n"
               "%ld sources doing burst (return to offline)\n"
               "%ld sources with unknown address\n",
                (long) ntohl(reply.data.activity.online),
                (long) ntohl(reply.data.activity.offline),
                (long) ntohl(reply.data.activity.burst_online),
                (long) ntohl(reply.data.activity.burst_offline),
                (long) ntohl(reply.data.activity.unresolved));
        return 1;
  }
  return 0;
}

Project: chrony

handle_source_data(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  RPT_SourceReport report;
  struct timeval now_corr;

  /* Get data */
  LCL_ReadCookedTime(&now_corr, NULL);
  if (SRC_ReportSource(ntohl(rx_message->data.source_data.index), &report, &now_corr)) {
    switch (SRC_GetType(ntohl(rx_message->data.source_data.index))) {
      case SRC_NTP:
        NSR_ReportSource(&report, &now_corr);
        break;
      case SRC_REFCLOCK:
        RCL_ReportSource(&report, &now_corr);
        break;
    }
    
    tx_message->status = htons(STT_SUCCESS);
    tx_message->reply  = htons(RPY_SOURCE_DATA);
    
    UTI_IPHostToNetwork(&report.ip_addr, &tx_message->data.source_data.ip_addr);
    tx_message->data.source_data.stratum = htons(report.stratum);
    tx_message->data.source_data.poll    = htons(report.poll);
    switch (report.state) {
      case RPT_SYNC:
        tx_message->data.source_data.state   = htons(RPY_SD_ST_SYNC);
        break;
      case RPT_UNREACH:
        tx_message->data.source_data.state   = htons(RPY_SD_ST_UNREACH);
        break;
      case RPT_FALSETICKER:
        tx_message->data.source_data.state   = htons(RPY_SD_ST_FALSETICKER);
        break;
      case RPT_JITTERY:
        tx_message->data.source_data.state   = htons(RPY_SD_ST_JITTERY);
        break;
      case RPT_CANDIDATE:
        tx_message->data.source_data.state   = htons(RPY_SD_ST_CANDIDATE);
        break;
      case RPT_OUTLIER:
        tx_message->data.source_data.state   = htons(RPY_SD_ST_OUTLIER);
        break;
    }
    switch (report.mode) {
      case RPT_NTP_CLIENT:
        tx_message->data.source_data.mode    = htons(RPY_SD_MD_CLIENT);
        break;
      case RPT_NTP_PEER:
        tx_message->data.source_data.mode    = htons(RPY_SD_MD_PEER);
        break;
      case RPT_LOCAL_REFERENCE:
        tx_message->data.source_data.mode    = htons(RPY_SD_MD_REF);
        break;
    }
    switch (report.sel_option) {
      case RPT_NORMAL:
        tx_message->data.source_data.flags = htons(0);
        break;
      case RPT_PREFER:
        tx_message->data.source_data.flags = htons(RPY_SD_FLAG_PREFER);
        break;
      case RPT_NOSELECT:
        tx_message->data.source_data.flags = htons(RPY_SD_FLAG_PREFER);
        break;
    }
    tx_message->data.source_data.reachability = htons(report.reachability);
    tx_message->data.source_data.since_sample = htonl(report.latest_meas_ago);
    tx_message->data.source_data.orig_latest_meas = UTI_FloatHostToNetwork(report.orig_latest_meas);
    tx_message->data.source_data.latest_meas = UTI_FloatHostToNetwork(report.latest_meas);
    tx_message->data.source_data.latest_meas_err = UTI_FloatHostToNetwork(report.latest_meas_err);
  } else {
    tx_message->status = htons(STT_NOSUCHSOURCE);
  }
}

Project: chrony

handle_modify_maxdelay(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  int status;
  IPAddr address;
  UTI_IPNetworkToHost(&rx_message->data.modify_maxdelay.address, &address);
  status = NSR_ModifyMaxdelay(&address,
                              UTI_FloatNetworkToHost(rx_message->data.modify_maxdelay.new_max_delay));
  if (status) {
    tx_message->status = htons(STT_SUCCESS);
  } else {
    tx_message->status = htons(STT_NOSUCHSOURCE);
  }
}

Project: chrony

close_io(void)
{

  close(sock_fd);

}

Project: chrony

PKL_CommandLength(CMD_Request *r)
{
  int type;
  type = ntohs(r->command);
  if (type < 0 || type >= N_REQUEST_TYPES) {
    return 0;
  } else {
    switch (type) {
      
      case REQ_NULL:
        return offsetof(CMD_Request, data);
      case REQ_ONLINE:
        return offsetof(CMD_Request, data.online.EOR);
      case REQ_OFFLINE:
        return offsetof(CMD_Request, data.offline.EOR);
      case REQ_BURST:
        return offsetof(CMD_Request, data.burst.EOR);
      case REQ_MODIFY_MINPOLL:
        return offsetof(CMD_Request, data.modify_minpoll.EOR);
      case REQ_MODIFY_MAXPOLL:
        return offsetof(CMD_Request, data.modify_maxpoll.EOR);
      case REQ_DUMP:
        return offsetof(CMD_Request, data.dump.EOR);
      case REQ_MODIFY_MAXDELAY:
        return offsetof(CMD_Request, data.modify_maxdelay.EOR);
      case REQ_MODIFY_MAXDELAYRATIO:
        return offsetof(CMD_Request, data.modify_maxdelayratio.EOR);
      case REQ_MODIFY_MAXDELAYDEVRATIO:
        return offsetof(CMD_Request, data.modify_maxdelaydevratio.EOR);
      case REQ_MODIFY_MAXUPDATESKEW:
        return offsetof(CMD_Request, data.modify_maxupdateskew.EOR);
      case REQ_LOGON :
        return offsetof(CMD_Request, data.logon.EOR);
      case REQ_SETTIME :
        return offsetof(CMD_Request, data.settime.EOR);
      case REQ_LOCAL :
        return offsetof(CMD_Request, data.local.EOR);
      case REQ_MANUAL :
        return offsetof(CMD_Request, data.manual.EOR);
      case REQ_N_SOURCES :
        return offsetof(CMD_Request, data.n_sources.EOR);
      case REQ_SOURCE_DATA :
        return offsetof(CMD_Request, data.source_data.EOR);
      case REQ_REKEY :
        return offsetof(CMD_Request, data.rekey.EOR);
      case REQ_ALLOW :
        return offsetof(CMD_Request, data.allow_deny.EOR);
      case REQ_ALLOWALL :
        return offsetof(CMD_Request, data.allow_deny.EOR);
      case REQ_DENY :
        return offsetof(CMD_Request, data.allow_deny.EOR);
      case REQ_DENYALL :
        return offsetof(CMD_Request, data.allow_deny.EOR);
      case REQ_CMDALLOW :
        return offsetof(CMD_Request, data.allow_deny.EOR);
      case REQ_CMDALLOWALL :
        return offsetof(CMD_Request, data.allow_deny.EOR);
      case REQ_CMDDENY :
        return offsetof(CMD_Request, data.allow_deny.EOR);
      case REQ_CMDDENYALL :
        return offsetof(CMD_Request, data.allow_deny.EOR);
      case REQ_ACCHECK :
        return offsetof(CMD_Request, data.ac_check.EOR);
      case REQ_CMDACCHECK :
        return offsetof(CMD_Request, data.ac_check.EOR);
      case REQ_ADD_SERVER :
        return offsetof(CMD_Request, data.ntp_source.EOR);
      case REQ_ADD_PEER :
        return offsetof(CMD_Request, data.ntp_source.EOR);
      case REQ_DEL_SOURCE :
        return offsetof(CMD_Request, data.del_source.EOR);
      case REQ_WRITERTC :
        return offsetof(CMD_Request, data.writertc.EOR);
      case REQ_DFREQ :
        return offsetof(CMD_Request, data.dfreq.EOR);
      case REQ_DOFFSET :
        return offsetof(CMD_Request, data.doffset.EOR);
      case REQ_TRACKING :
        return offsetof(CMD_Request, data.tracking.EOR);
      case REQ_SOURCESTATS :
        return offsetof(CMD_Request, data.sourcestats.EOR);
      case REQ_RTCREPORT :
        return offsetof(CMD_Request, data.rtcreport.EOR);
      case REQ_TRIMRTC :
        return offsetof(CMD_Request, data.trimrtc.EOR);
      case REQ_CYCLELOGS :
        return offsetof(CMD_Request, data.cyclelogs.EOR);
      case REQ_SUBNETS_ACCESSED :
        {
          unsigned long ns;
          ns = ntohl(r->data.subnets_accessed.n_subnets);
          if (ns > MAX_SUBNETS_ACCESSED)
            return 0;
          return (offsetof(CMD_Request, data.subnets_accessed.subnets) +
                  ns * sizeof(REQ_SubnetsAccessed_Subnet));
        }
      case REQ_CLIENT_ACCESSES:
        {
          unsigned long nc;
          nc = ntohl(r->data.client_accesses.n_clients);
          if (nc > MAX_CLIENT_ACCESSES)
            return 0;
          return (offsetof(CMD_Request, data.client_accesses.client_ips) +
                  nc * sizeof(unsigned long));
        }
      case REQ_CLIENT_ACCESSES_BY_INDEX:
        return offsetof(CMD_Request, data.client_accesses_by_index.EOR);
      case REQ_MANUAL_LIST:
        return offsetof(CMD_Request, data.manual_list.EOR);
      case REQ_MANUAL_DELETE:
        return offsetof(CMD_Request, data.manual_delete.EOR);
      case REQ_MAKESTEP:
        return offsetof(CMD_Request, data.make_step.EOR);
      case REQ_ACTIVITY:
        return offsetof(CMD_Request, data.activity.EOR);
      case REQ_RESELECT:
        return offsetof(CMD_Request, data.reselect.EOR);
      case REQ_RESELECTDISTANCE:
        return offsetof(CMD_Request, data.reselect_distance.EOR);
      case REQ_MODIFY_MINSTRATUM:
        return offsetof(CMD_Request, data.modify_minstratum.EOR);
      case REQ_MODIFY_POLLTARGET:
        return offsetof(CMD_Request, data.modify_polltarget.EOR);
      default:
        /* If we fall through the switch, it most likely means we've forgotten to implement a new case */
        assert(0);
    }
  }

  /* Catch-all case */
  return 0;

}

Project: chrony

handle_n_sources(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  int n_sources;
  n_sources = SRC_ReadNumberOfSources();
  tx_message->status = htons(STT_SUCCESS);
  tx_message->reply = htons(RPY_N_SOURCES);
  tx_message->data.n_sources.n_sources = htonl(n_sources);
}

Project: chrony

handle_modify_minstratum(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  int status;
  IPAddr address;
  UTI_IPNetworkToHost(&rx_message->data.modify_minpoll.address, &address);
  status = NSR_ModifyMinstratum(&address,
                             ntohl(rx_message->data.modify_minstratum.new_min_stratum));
  
  if (status) {
    tx_message->status = htons(STT_SUCCESS);
  } else {
    tx_message->status = htons(STT_NOSUCHSOURCE);
  }
}

Project: chrony

release_ts_cell(TimestampCell *node)
{
  node->next = free_ts_list;
  free_ts_list = node;
}

Project: chrony

process_cmd_delete(CMD_Request *msg, char *line)
{
  char *hostname;
  int ok = 0;
  IPAddr address;

  msg->command = htons(REQ_DEL_SOURCE);
  hostname = line;
  CPS_SplitWord(line);

  if (!*hostname) {
    fprintf(stderr, "Invalid syntax for address\n");
    ok = 0;
  } else {
    if (DNS_Name2IPAddress(hostname, &address) != DNS_Success) {
      fprintf(stderr, "Could not get address for hostname\n");
      ok = 0;
    } else {
      UTI_IPHostToNetwork(&address, &msg->data.del_source.ip_addr);
      ok = 1;
    }
  }

  return ok;
  
}

Project: chrony

handle_activity(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  RPT_ActivityReport report;
  NSR_GetActivityReport(&report);
  tx_message->data.activity.online = htonl(report.online);
  tx_message->data.activity.offline = htonl(report.offline);
  tx_message->data.activity.burst_online = htonl(report.burst_online);
  tx_message->data.activity.burst_offline = htonl(report.burst_offline);
  tx_message->data.activity.unresolved = htonl(report.unresolved);
  tx_message->status = htons(STT_SUCCESS);
  tx_message->reply = htons(RPY_ACTIVITY);
}

Project: chrony

process_cmd_cmdallow(CMD_Request *msg, char *line)
{
  int status;
  msg->command = htons(REQ_CMDALLOW);
  status = parse_allow_deny(msg, line);
  return status;
}

Project: chrony

print_seconds(unsigned long s)
{
  unsigned long d;
  if (s <= 1024) {
    printf("%4ld", s);
  } else if (s < 36000) {
    printf("%3ldm", s / 60);
  } else if (s < 345600) {
    printf("%3ldh", s / 3600);
  } else {
    d = s / 86400;
    if (d > 999) {
      printf("%3ldy", d / 365);
    } else {
      printf("%3ldd", d);
    }
  }
}

Project: chrony

time_to_log_form(time_t t)
{
  struct tm stm;
  static char buffer[64];
  static const char *months[] = {"Jan", "Feb", "Mar", "Apr",
                                 "May", "Jun", "Jul", "Aug",
                                 "Sep", "Oct", "Nov", "Dec"};


  stm = *gmtime(&t);
  snprintf(buffer, sizeof(buffer),
          "%2d%s%02d %02d:%02d:%02d",
          stm.tm_mday, months[stm.tm_mon], stm.tm_year % 100,
          stm.tm_hour, stm.tm_min, stm.tm_sec);

  return buffer;
}

Project: chrony

  for (p = head; p; ) {
    next_node = p->next;
    Free(p);
    p = next_node;
  }

Project: chrony

handle_cmdaccheck(CMD_Request *rx_message, CMD_Reply *tx_message)
{
  IPAddr ip;
  UTI_IPNetworkToHost(&rx_message->data.ac_check.ip, &ip);
  if (CAM_CheckAccessRestriction(&ip)) {
    tx_message->status = htons(STT_ACCESSALLOWED);
  } else {
    tx_message->status = htons(STT_ACCESSDENIED);
  }
}