]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
Add IPv6 support
authorMiroslav Lichvar <mlichvar@redhat.com>
Fri, 9 Oct 2009 13:00:59 +0000 (15:00 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Tue, 13 Oct 2009 12:44:33 +0000 (14:44 +0200)
32 files changed:
acquire.c
acquire.h
addressing.h
addrfilt.c
addrfilt.h
broadcast.c
broadcast.h
candm.h
client.c
clientlog.c
clientlog.h
cmdmon.c
cmdmon.h
cmdparse.c
cmdparse.h
conf.c
conf.h
configure
nameserv.c
nameserv.h
ntp_core.c
ntp_core.h
ntp_io.c
ntp_sources.c
ntp_sources.h
refclock.c
reports.h
sources.c
sources.h
sysincl.h
util.c
util.h

index 94b4e61acf4e0fe5007e52fcf02806013d91d818..2a6fb468a89d30c8422842fa507ce1fcc8e8c2e2 100644 (file)
--- a/acquire.c
+++ b/acquire.c
@@ -65,7 +65,8 @@
 
 #define RETRANSMISSION_TIMEOUT (1.0)
 
-typedef struct {  unsigned long ip_addr;
+typedef struct {
+  IPAddr ip_addr;               /* Address of the server */
   int sanity;                   /* Flag indicating whether source
                                    looks sane or not */
   int n_dead_probes;            /* Number of probes sent to the server
@@ -93,7 +94,18 @@ static int n_completed_sources;
 
 static int init_slew_threshold = -1;
 
-static int sock_fd = -1;
+union sockaddr_in46 {
+  struct sockaddr_in in4;
+#ifdef HAVE_IPV6
+  struct sockaddr_in6 in6;
+#endif
+  struct sockaddr u;
+};
+
+static int sock_fd4 = -1;
+#ifdef HAVE_IPV6
+static int sock_fd6 = -1;
+#endif
 
 /* ================================================== */
 
@@ -143,12 +155,13 @@ ACQ_Finalise(void)
 
 /* ================================================== */
 
-static void
-initialise_io(void)
+static int
+prepare_socket(int family)
 {
   unsigned short port_number = CNF_GetAcquisitionPort();
+  int sock_fd;
 
-  sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
+  sock_fd = socket(family, SOCK_DGRAM, 0);
 
   if (sock_fd < 0) {
     LOG_FATAL(LOGF_Acquire, "Could not open socket : %s", strerror(errno));
@@ -158,18 +171,48 @@ initialise_io(void)
     /* Don't bother binding this socket - we're not fussed what port
        number it gets */
   } else {
-    struct sockaddr_in my_addr;
-    my_addr.sin_family = AF_INET;
-    my_addr.sin_port = htons(port_number);
-    my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
-    if (bind(sock_fd, (struct sockaddr *) &my_addr, sizeof(my_addr)) < 0) {
+    union sockaddr_in46 my_addr;
+
+    memset(&my_addr, 0, sizeof (my_addr));
+
+    switch (family) {
+      case AF_INET:
+        my_addr.in4.sin_family = family;
+        my_addr.in4.sin_port = htons(port_number);
+        my_addr.in4.sin_addr.s_addr = htonl(INADDR_ANY);
+        break;
+#ifdef HAVE_IPV6
+      case AF_INET6:
+        my_addr.in6.sin6_family = family;
+        my_addr.in6.sin6_port = htons(port_number);
+        my_addr.in6.sin6_addr = in6addr_any;
+        break;
+#endif
+      default:
+        assert(0);
+    }
+
+    if (bind(sock_fd, &my_addr.u, sizeof(my_addr)) < 0) {
       LOG(LOGS_ERR, LOGF_Acquire, "Could not bind socket : %s\n", strerror(errno));
       /* but keep running */
     }
   }
 
-  SCH_AddInputFileHandler(sock_fd, read_from_socket, NULL);
+  SCH_AddInputFileHandler(sock_fd, read_from_socket, (void *)(long)sock_fd);
 
+  return sock_fd;
+}
+/* ================================================== */
+
+static void
+initialise_io(int family)
+{
+  if (family == IPADDR_INET4 || family == IPADDR_UNSPEC)
+    sock_fd4 = prepare_socket(AF_INET);
+#ifdef HAVE_IPV6
+  if (family == IPADDR_INET6 || family == IPADDR_UNSPEC)
+    sock_fd6 = prepare_socket(AF_INET6);
+#endif
 }
 
 /* ================================================== */
@@ -177,10 +220,18 @@ initialise_io(void)
 static void
 finalise_io(void)
 {
-  if (sock_fd >= 0) {
-    SCH_RemoveInputFileHandler(sock_fd);
-    close(sock_fd);
+  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
 
   return;
 }
@@ -195,10 +246,11 @@ probe_source(SourceRecord *src)
   NTP_Mode my_mode = MODE_CLIENT;
   struct timeval cooked;
   double local_time_err;
-  struct sockaddr_in his_addr;
+  union sockaddr_in46 his_addr;
+  int sock_fd;
 
 #if 0
-  printf("Sending probe to %08lx sent=%d samples=%d\n", src->ip_addr, src->n_probes_sent, src->n_samples);
+  printf("Sending probe to %s sent=%d samples=%d\n", UTI_IPToString(&src->ip_addr), src->n_probes_sent, src->n_samples);
 #endif
 
   pkt.lvm = (((LEAP_Unsynchronised << 6) & 0xc0) |
@@ -219,18 +271,37 @@ probe_source(SourceRecord *src)
   pkt.receive_ts.lo = 0;   /* Set to 0 */
 
   /* And do transmission */
-  his_addr.sin_addr.s_addr = htonl(src->ip_addr);
-  his_addr.sin_port = htons(123); /* Fixed for now */
-  his_addr.sin_family = AF_INET;
+
+  memset(&his_addr, 0, sizeof (his_addr));
+  switch (src->ip_addr.family) {
+    case IPADDR_INET4:
+      his_addr.in4.sin_addr.s_addr = htonl(src->ip_addr.addr.in4);
+      his_addr.in4.sin_port = htons(123); /* Fixed for now */
+      his_addr.in4.sin_family = AF_INET;
+      sock_fd = sock_fd4;
+      break;
+#ifdef HAVE_IPV6
+    case IPADDR_INET6:
+      memcpy(&his_addr.in6.sin6_addr.s6_addr, &src->ip_addr.addr.in6,
+          sizeof (his_addr.in6.sin6_addr.s6_addr));
+      his_addr.in6.sin6_port = htons(123); /* Fixed for now */
+      his_addr.in6.sin6_family = AF_INET6;
+      sock_fd = sock_fd6;
+      break;
+#endif
+    default:
+      assert(0);
+  }
+
 
   LCL_ReadCookedTime(&cooked, &local_time_err);
   UTI_TimevalToInt64(&cooked, &pkt.transmit_ts);
 
   if (sendto(sock_fd, (void *) &pkt, NTP_NORMAL_PACKET_SIZE,
              0,
-             (struct sockaddr *) &his_addr, sizeof(his_addr)) < 0) {
+             &his_addr.u, sizeof(his_addr)) < 0) {
     LOG(LOGS_WARN, LOGF_Acquire, "Could not send to %s : %s",
-        UTI_IPToDottedQuad(src->ip_addr),
+        UTI_IPToString(&src->ip_addr),
         strerror(errno));
   }
 
@@ -253,7 +324,7 @@ transmit_timeout(void *x)
   src->timer_running = 0;
 
 #if 0
-  printf("Timeout expired for server %08lx\n", src->ip_addr);
+  printf("Timeout expired for server %s\n", UTI_IPToString(&src->ip_addr));
 #endif
 
   if (src->n_dead_probes < MAX_DEAD_PROBES) {
@@ -357,11 +428,12 @@ read_from_socket(void *anything)
 {
   int status;
   ReceiveBuffer msg;
-  struct sockaddr_in his_addr;
+  union sockaddr_in46 his_addr;
+  int sock_fd;
   socklen_t his_addr_len;
   int flags;
   int message_length;
-  unsigned long remote_ip;
+  IPAddr remote_ip;
   int i, ok;
   struct timeval now;
   double local_time_err;
@@ -374,24 +446,39 @@ read_from_socket(void *anything)
   /* Get timestamp */
   LCL_ReadCookedTime(&now, &local_time_err);
 
+  sock_fd = (long)anything;
   status = recvfrom (sock_fd, (char *)&msg, message_length, flags,
-                     (struct sockaddr *) &his_addr, &his_addr_len);
+                     &his_addr.u, &his_addr_len);
 
   if (status < 0) {
     LOG(LOGS_WARN, LOGF_Acquire, "Error reading from socket, %s", strerror(errno));
     return;
   }
   
-  remote_ip = ntohl(his_addr.sin_addr.s_addr);
+  switch (his_addr.u.sa_family) {
+    case AF_INET:
+      remote_ip.family = IPADDR_INET4;
+      remote_ip.addr.in4 = ntohl(his_addr.in4.sin_addr.s_addr);
+      break;
+#ifdef HAVE_IPV6
+    case AF_INET6:
+      remote_ip.family = IPADDR_INET6;
+      memcpy(&remote_ip.addr.in6, his_addr.in6.sin6_addr.s6_addr,
+          sizeof (remote_ip.addr.in6));
+      break;
+#endif
+    default:
+      assert(0);
+  }
 
 #if 0
-  printf("Got message from %08lx\n", remote_ip);
+  printf("Got message from %s\n", UTI_IPToString(&remote_ip));
 #endif
   
   /* Find matching host */
   ok = 0;
   for (i=0; i<n_sources; i++) {
-    if (remote_ip == sources[i].ip_addr) {
+    if (UTI_CompareIPs(&remote_ip, &sources[i].ip_addr, NULL) == 0) {
       ok = 1;
       break;
     }
@@ -418,7 +505,7 @@ read_from_socket(void *anything)
         (src->n_total_samples >= MAX_SAMPLES)) {
       ++n_completed_sources;
 #if 0
-      printf("Source %08lx completed\n", src->ip_addr);
+      printf("Source %s completed\n", UTI_IPToString(&src->ip_addr));
 #endif
       if (n_completed_sources == n_sources) {
         wind_up_acquisition();
@@ -440,7 +527,7 @@ start_next_source(void)
 {
   probe_source(sources + n_started_sources);
 #if 0
-  printf("Trying to start source %08lx\n", sources[n_started_sources].ip_addr);
+  printf("Trying to start source %s\n", UTI_IPToString(&sources[n_started_sources].ip_addr));
 #endif
   n_started_sources++;
   
@@ -552,10 +639,10 @@ process_measurements(void)
   for (i=0; i<2*n_sane_sources; i++) {
 
 #if 0
-    fprintf(stderr, "Endpoint type %s source index %d [ip=%08lx] offset=%.6f\n",
+    fprintf(stderr, "Endpoint type %s source index %d [ip=%s] offset=%.6f\n",
             (eps[i].type == LO) ? "LO" : "HIGH",
             eps[i].index,
-            sources[eps[i].index].ip_addr,
+            UTI_IPToString(&sources[eps[i].index].ip_addr),
             eps[i].offset);
 #endif
 
@@ -655,10 +742,10 @@ start_source_timeout_handler(void *not_used)
 /* ================================================== */
 
 void
-ACQ_StartAcquisition(int n, unsigned long *ip_addrs, int threshold, void (*after_hook)(void *), void *anything)
+ACQ_StartAcquisition(int n, IPAddr *ip_addrs, int threshold, void (*after_hook)(void *), void *anything)
 {
 
-  int i;
+  int i, ip4, ip6;
 
   saved_after_hook = after_hook;
   saved_after_hook_anything = anything;
@@ -670,14 +757,18 @@ ACQ_StartAcquisition(int n, unsigned long *ip_addrs, int threshold, void (*after
   n_sources = n;
   sources = MallocArray(SourceRecord, n);
 
-  for (i=0; i<n; i++) {
+  for (i = ip4 = ip6 = 0; i < n; i++) {
     sources[i].ip_addr = ip_addrs[i];
     sources[i].n_samples = 0;
     sources[i].n_total_samples = 0;
     sources[i].n_dead_probes = 0;
+    if (ip_addrs[i].family == IPADDR_INET4)
+      ip4++;
+    else if (ip_addrs[i].family == IPADDR_INET6)
+      ip6++;
   }
 
-  initialise_io();
+  initialise_io((ip4 && ip6) ? IPADDR_UNSPEC : (ip4 ? IPADDR_INET4 : IPADDR_INET6));
 
   /* Start sampling first source */
   start_next_source();
index e1e00aee9379816586809ca54ec3e37b2bebfb7a..840e1479cca3d54a3ee1821d3bcda1c530afa922 100644 (file)
--- a/acquire.h
+++ b/acquire.h
 #ifndef GOT_ACQUIRE_H
 #define GOT_ACQUIRE_H
 
+#include "addressing.h"
+
 typedef struct ACQ_SourceRecord *ACQ_Source;
 
 extern void ACQ_Initialise(void);
 
 extern void ACQ_Finalise(void);
 
-extern void ACQ_StartAcquisition(int n, unsigned long *ip_addrs, int init_slew_threshold,
+extern void ACQ_StartAcquisition(int n, IPAddr *ip_addrs, int init_slew_threshold,
                                  void (*after_hook)(void *), void *anything);
 
 extern void ACQ_AccumulateSample(ACQ_Source acq_source, double offset, double root_distance);
index 89e82d43ef4434f877ec163f2ef2f15e6c4ff0c9..9ff48058b2ba263c12e004d990c45d95cdeeb034 100644 (file)
 #ifndef GOT_ADDRESSING_H
 #define GOT_ADDRESSING_H
 
-/* This type is used to represent an IPv4 address and port
-   number.  Both parts are in HOST order, NOT network order. */
+#include "sysincl.h"
+
+/* This type is used to represent an IPv4 address or IPv6 address.
+   All parts are in HOST order, NOT network order. */
+
+#define IPADDR_UNSPEC 0
+#define IPADDR_INET4 1
+#define IPADDR_INET6 2
+
 typedef struct {
-  unsigned long ip_addr;
-  unsigned long local_ip_addr;
+  union { 
+    uint32_t in4;
+    uint8_t in6[16];
+  } addr;
+  uint16_t family;
+} IPAddr;
+
+typedef struct {
+  IPAddr ip_addr;
+  IPAddr local_ip_addr;
   unsigned short port;
 } NTP_Remote_Address;
 
-#if 0
-unsigned long NTP_IP_Address;
-#endif
-
 #endif /* GOT_ADDRESSING_H */
 
index 133563813a8ff8339fb0f2d5b93743b4c729aa68..754854102db969e67ac41c3cbb560699ddb6ce7a 100644 (file)
@@ -51,23 +51,35 @@ typedef struct _TableNode {
 } TableNode;
 
 struct ADF_AuthTableInst {
-  TableNode base;
+  TableNode base4;      /* IPv4 node */
+  TableNode base6;      /* IPv6 node */
 };
 
 /* ================================================== */
 
-inline static unsigned long
-get_subnet(unsigned long addr)
+static void
+split_ip6(IPAddr *ip, uint32_t *dst)
 {
-  return (addr >> (32-NBITS)) & ((1UL<<NBITS) - 1);
+  int i;
+
+  for (i = 0; i < 4; i++)
+    dst[i] = ip->addr.in6[i * 4 + 0] << 24 |
+             ip->addr.in6[i * 4 + 1] << 16 |
+             ip->addr.in6[i * 4 + 2] << 8 |
+             ip->addr.in6[i * 4 + 3];
 }
 
 /* ================================================== */
 
-inline static unsigned long
-get_residual(unsigned long addr)
+inline static uint32_t
+get_subnet(uint32_t *addr, unsigned int where)
 {
-  return (addr << NBITS);
+  int off;
+
+  off = where / 32;
+  where %= 32;
+
+  return (addr[off] >> (32 - NBITS - where)) & ((1UL << NBITS) - 1);
 }
 
 /* ================================================== */
@@ -79,8 +91,10 @@ ADF_CreateTable(void)
   result = MallocNew(struct ADF_AuthTableInst);
 
   /* Default is that nothing is allowed */
-  result->base.state = DENY;
-  result->base.extended = NULL;
+  result->base4.state = DENY;
+  result->base4.extended = NULL;
+  result->base6.state = DENY;
+  result->base6.extended = NULL;
 
   return result;
 }
@@ -135,22 +149,22 @@ open_node(TableNode *node)
 
 static ADF_Status
 set_subnet(TableNode *start_node,
-           unsigned long ip,
+           uint32_t *ip,
+           int ip_len,
            int subnet_bits,
            State new_state,
            int delete_children)
 {
-  int bits_to_go;
-  unsigned long residual;
-  unsigned long subnet;
+  int bits_to_go, bits_consumed;
+  uint32_t subnet;
   TableNode *node;
 
+  bits_consumed = 0;
   bits_to_go = subnet_bits;
-  residual = ip;
   node = start_node;
 
   if ((subnet_bits < 0) ||
-      (subnet_bits > 32)) {
+      (subnet_bits > 32 * ip_len)) {
 
     return ADF_BADSUBNET;
 
@@ -159,13 +173,13 @@ set_subnet(TableNode *start_node,
     if ((bits_to_go & (NBITS-1)) == 0) {
     
       while (bits_to_go > 0) {
-        subnet = get_subnet(residual);
-        residual = get_residual(residual);
+        subnet = get_subnet(ip, bits_consumed);
         if (!(node->extended)) {
           open_node(node);
         }
         node = &(node->extended[subnet]);
         bits_to_go -= NBITS;
+        bits_consumed += NBITS;
       }
 
       if (delete_children) {
@@ -178,18 +192,18 @@ set_subnet(TableNode *start_node,
       TableNode *this_node;
 
       while (bits_to_go >= NBITS) {
-        subnet = get_subnet(residual);
-        residual = get_residual(residual);
+        subnet = get_subnet(ip, bits_consumed);
         if (!(node->extended)) {
           open_node(node);
         }
         node = &(node->extended[subnet]);
         bits_to_go -= NBITS;
+        bits_consumed += NBITS;
       }
 
       /* How many subnet entries to set : 1->8, 2->4, 3->2 */
       N = 1 << (NBITS-bits_to_go);
-      subnet = get_subnet(residual);
+      subnet = get_subnet(ip, bits_consumed);
       if (!(node->extended)) {
         open_node(node);
       }
@@ -210,12 +224,41 @@ set_subnet(TableNode *start_node,
 
 /* ================================================== */
 
+static ADF_Status
+set_subnet_(ADF_AuthTable table,
+           IPAddr *ip_addr,
+           int subnet_bits,
+           State new_state,
+           int delete_children)
+{
+  uint32_t ip6[4];
+
+  switch (ip_addr->family) {
+    case IPADDR_INET4:
+      return set_subnet(&table->base4, &ip_addr->addr.in4, 1, subnet_bits, new_state, delete_children);
+    case IPADDR_INET6:
+      split_ip6(ip_addr, ip6);
+      return set_subnet(&table->base6, ip6, 4, subnet_bits, new_state, delete_children);
+    case IPADDR_UNSPEC:
+      /* Apply to both, subnet_bits has to be 0 */
+      if (subnet_bits != 0)
+        return ADF_BADSUBNET;
+      memset(ip6, 0, sizeof (ip6));
+      if (set_subnet(&table->base4, ip6, 1, 0, new_state, delete_children) == ADF_SUCCESS &&
+          set_subnet(&table->base6, ip6, 4, 0, new_state, delete_children) == ADF_SUCCESS)
+        return ADF_SUCCESS;
+      break;
+  }
+
+  return ADF_BADSUBNET;
+}
+
 ADF_Status
 ADF_Allow(ADF_AuthTable table,
-          unsigned long ip,
+          IPAddr *ip,
           int subnet_bits)
 {
-  return set_subnet(&(table->base), ip, subnet_bits, ALLOW, 0);
+  return set_subnet_(table, ip, subnet_bits, ALLOW, 0);
 }
 
 /* ================================================== */
@@ -223,30 +266,30 @@ ADF_Allow(ADF_AuthTable table,
 
 ADF_Status
 ADF_AllowAll(ADF_AuthTable table,
-             unsigned long ip,
+             IPAddr *ip,
              int subnet_bits)
 {
-  return set_subnet(&(table->base), ip, subnet_bits, ALLOW, 1);
+  return set_subnet_(table, ip, subnet_bits, ALLOW, 1);
 }
 
 /* ================================================== */
 
 ADF_Status
 ADF_Deny(ADF_AuthTable table,
-         unsigned long ip,
+         IPAddr *ip,
          int subnet_bits)
 {
-  return set_subnet(&(table->base), ip, subnet_bits, DENY, 0);
+  return set_subnet_(table, ip, subnet_bits, DENY, 0);
 }
 
 /* ================================================== */
 
 ADF_Status
 ADF_DenyAll(ADF_AuthTable table,
-            unsigned long ip,
+            IPAddr *ip,
             int subnet_bits)
 {
-  return set_subnet(&(table->base), ip, subnet_bits, DENY, 1);
+  return set_subnet_(table, ip, subnet_bits, DENY, 1);
 }
 
 /* ================================================== */
@@ -254,32 +297,33 @@ ADF_DenyAll(ADF_AuthTable table,
 void
 ADF_DestroyTable(ADF_AuthTable table)
 {
-  close_node(&(table->base));
+  close_node(&table->base4);
+  close_node(&table->base6);
   Free(table);
 }
 
 /* ================================================== */
 
 static int
-check_ip_in_node(TableNode *start_node, unsigned long ip)
+check_ip_in_node(TableNode *start_node, uint32_t *ip)
 {
-  unsigned long residual, subnet;
+  uint32_t subnet;
+  int bits_consumed = 0;
   int result = 0;
   int finished = 0;
   TableNode *node;
   State state=DENY;
 
   node = start_node;
-  residual = ip;
 
   do {
     if (node->state != AS_PARENT) {
       state = node->state;
     }
     if (node->extended) {
-      subnet = get_subnet(residual);
-      residual = get_residual(residual);
+      subnet = get_subnet(ip, bits_consumed);
       node = &(node->extended[subnet]);
+      bits_consumed += NBITS;
     } else {
       /* Make decision on this node */
       finished = 1;
@@ -306,38 +350,63 @@ check_ip_in_node(TableNode *start_node, unsigned long ip)
 
 int
 ADF_IsAllowed(ADF_AuthTable table,
-              unsigned long ip)
+              IPAddr *ip_addr)
 {
+  uint32_t ip6[4];
+
+  switch (ip_addr->family) {
+    case IPADDR_INET4:
+      return check_ip_in_node(&table->base4, &ip_addr->addr.in4);
+    case IPADDR_INET6:
+      split_ip6(ip_addr, ip6);
+      return check_ip_in_node(&table->base6, ip6);
+  }
 
-  return check_ip_in_node(&(table->base), ip);
-
+  return 0;
 }
 
 /* ================================================== */
 
 #if defined TEST
 
-static void print_node(TableNode *node, unsigned long addr, int shift, int subnet_bits)
+static void print_node(TableNode *node, uint32_t *addr, int ip_len, int shift, int subnet_bits)
 {
-  unsigned long new_addr;
+  uint32_t new_addr[4];
   int i;
   TableNode *sub_node;
 
   for (i=0; i<subnet_bits; i++) putchar(' ');
 
-  printf("%d.%d.%d.%d/%d : %s\n",
-         ((addr >> 24) & 255),
-         ((addr >> 16) & 255),
-         ((addr >>  8) & 255),
-         ((addr      ) & 255),
+  if (ip_len == 1)
+      printf("%d.%d.%d.%d",
+          ((addr[0] >> 24) & 255),
+          ((addr[0] >> 16) & 255),
+          ((addr[0] >>  8) & 255),
+          ((addr[0]      ) & 255));
+  else {
+    for (i=0; i<4; i++) {
+      if (addr[i])
+        printf("%d.%d.%d.%d",
+            ((addr[i] >> 24) & 255),
+            ((addr[i] >> 16) & 255),
+            ((addr[i] >>  8) & 255),
+            ((addr[i]      ) & 255));
+      putchar(i < 3 ? ':' : '\0');
+    }
+  }
+  printf("/%d : %s\n",
          subnet_bits,
          (node->state == ALLOW) ? "allow" :
          (node->state == DENY)  ? "deny" : "as parent");
   if (node->extended) {
     for (i=0; i<16; i++) {
-      sub_node = &((*(node->extended))[i]);
-      new_addr = addr | ((unsigned long) i << shift);
-      print_node(sub_node, new_addr, shift - 4, subnet_bits + 4);
+      sub_node = &(node->extended[i]);
+      new_addr[0] = addr[0];
+      new_addr[1] = addr[1];
+      new_addr[2] = addr[2];
+      new_addr[3] = addr[3];
+      new_addr[ip_len - 1 - shift / 32] |= ((uint32_t)i << (shift % 32));
+      print_node(sub_node, new_addr, ip_len, shift - 4, subnet_bits + 4);
     }
   }
   return;
@@ -346,11 +415,15 @@ static void print_node(TableNode *node, unsigned long addr, int shift, int subne
 
 static void print_table(ADF_AuthTable table)
 {
-  unsigned long addr = 0;
-  int shift = 28;
-  int subnet_bits = 0;
+  uint32_t addr[4];
+
+  memset(addr, 0, sizeof (addr));
+  printf("IPv4 table:\n");
+  print_node(&table->base4, addr, 1, 28, 0);
 
-  print_node(&table->base, addr, shift, subnet_bits);
+  memset(addr, 0, sizeof (addr));
+  printf("IPv6 table:\n");
+  print_node(&table->base6, addr, 4, 124, 0);
   return;
 }
 
@@ -358,13 +431,41 @@ static void print_table(ADF_AuthTable table)
 
 int main (int argc, char **argv)
 {
+  IPAddr ip;
   ADF_AuthTable table;
   table = ADF_CreateTable();
 
-  ADF_Allow(table, 0x7e800000, 9);
-  ADF_Deny(table, 0x7ecc0000, 14);
-  /* ADF_Deny(table, 0x7f000001, 32); */
-  /* ADF_Allow(table, 0x7f000000, 8); */
+  ip.family = IPADDR_INET4;
+
+  ip.addr.in4 = 0x7e800000;
+  ADF_Allow(table, &ip, 9);
+  ip.addr.in4 = 0x7ecc0000;
+  ADF_Deny(table, &ip, 14);
+#if 0
+  ip.addr.in4 = 0x7f000001;
+  ADF_Deny(table, &ip, 32);
+  ip.addr.in4 = 0x7f000000;
+  ADF_Allow(table, &ip, 8);
+#endif
+
+  printf("allowed: %d\n", ADF_IsAllowed(table, &ip));
+  ip.addr.in4 ^= 1;
+  printf("allowed: %d\n", ADF_IsAllowed(table, &ip));
+
+  ip.family = IPADDR_INET6;
+
+  memcpy(ip.addr.in6, "abcdefghijklmnop", 16);
+  ADF_Deny(table, &ip, 66);
+  ADF_Allow(table, &ip, 59);
+
+  memcpy(ip.addr.in6, "xbcdefghijklmnop", 16);
+  ADF_Deny(table, &ip, 128);
+  ip.addr.in6[15] ^= 3;
+  ADF_Allow(table, &ip, 127);
+
+  printf("allowed: %d\n", ADF_IsAllowed(table, &ip));
+  ip.addr.in4 ^= 1;
+  printf("allowed: %d\n", ADF_IsAllowed(table, &ip));
 
   print_table(table);
 
index f96f0fb0c809cbcd40ecbfcb8a11fcbb05bcd0df..42e8350c6a58f1e6d3423570653cae65ab4ba7f1 100644 (file)
@@ -31,6 +31,8 @@
 #ifndef GOT_ADDRFILT_H
 #define GOT_ADDRFILT_H
 
+#include "addressing.h"
+
 typedef struct ADF_AuthTableInst *ADF_AuthTable;
 
 typedef enum {
@@ -45,25 +47,25 @@ extern ADF_AuthTable ADF_CreateTable(void);
 /* Allow anything in the supplied subnet, EXCEPT for any more specific
    subnets that are already defined */
 extern ADF_Status ADF_Allow(ADF_AuthTable table,
-                            unsigned long ip,
+                            IPAddr *ip,
                             int subnet_bits);
 
 /* Allow anything in the supplied subnet, overwriting existing
    definitions for any more specific subnets */
 extern ADF_Status ADF_AllowAll(ADF_AuthTable table,
-                               unsigned long ip,
+                               IPAddr *ip,
                                int subnet_bits);
 
 /* Deny anything in the supplied subnet, EXCEPT for any more specific
    subnets that are already defined */
 extern ADF_Status ADF_Deny(ADF_AuthTable table,
-                           unsigned long ip,
+                           IPAddr *ip,
                            int subnet_bits);
 
 /* Deny anything in the supplied subnet, overwriting existing
    definitions for any more specific subnets */
 extern ADF_Status ADF_DenyAll(ADF_AuthTable table,
-                              unsigned long ip,
+                              IPAddr *ip,
                               int subnet_bits);
 
 /* Clear up the table */
@@ -72,6 +74,6 @@ extern void ADF_DestroyTable(ADF_AuthTable table);
 /* Check whether a given IP address is allowed by the rules in 
    the table */
 extern int ADF_IsAllowed(ADF_AuthTable table,
-                         unsigned long ip);
+                         IPAddr *ip);
 
 #endif /* GOT_ADDRFILT_H */
index 35df56fd2dd991c386b8472b08e3bd1276b3c9d3..f177e322b23777611359152adfaa5a55d7933cf0 100644 (file)
@@ -132,7 +132,7 @@ timeout_handler(void *arbitrary)
 /* ================================================== */
 
 void 
-BRD_AddDestination(unsigned long addr, unsigned short port, int interval)
+BRD_AddDestination(IPAddr *addr, unsigned short port, int interval)
 {
   if (max_destinations == n_destinations) {
     /* Expand array */
@@ -144,8 +144,8 @@ BRD_AddDestination(unsigned long addr, unsigned short port, int interval)
     }
   }
 
-  destinations[n_destinations].addr.ip_addr = addr;
-  destinations[n_destinations].addr.local_ip_addr = 0;
+  destinations[n_destinations].addr.ip_addr = *addr;
+  destinations[n_destinations].addr.local_ip_addr.family = IPADDR_UNSPEC;
   destinations[n_destinations].addr.port = port;
   destinations[n_destinations].interval = interval;
 
index 01013bc2f907d9575b55a4963b54ee52163c036b..21650c8945aeb947129100be7ece8a2e36fd9095 100644 (file)
 #ifndef GOT_BROADCAST_H
 #define GOT_BROADCAST_H
 
+#include "addressing.h"
+
 extern void BRD_Initialise(void);
 extern void BRD_Finalise(void);
-extern void BRD_AddDestination(unsigned long addr, unsigned short port, int interval);
+extern void BRD_AddDestination(IPAddr *addr, unsigned short port, int interval);
 
 #endif /* GOT_BROADCAST_H */
 
diff --git a/candm.h b/candm.h
index c0d05cbac0e359c25a6b360a7442e289b96b33bb..52f58d3bda4d756e9ce1faa96f24883d3fc61c5e 100644 (file)
--- a/candm.h
+++ b/candm.h
@@ -34,6 +34,7 @@
 #define GOT_CANDM_H
 
 #include "sysincl.h"
+#include "addressing.h"
 
 /* This is the default port to use for CANDM, if no alternative is
    defined */
    transmitted for each packet type. */
 
 typedef struct {
-  uint32_t mask;
-  uint32_t address;
+  IPAddr mask;
+  IPAddr address;
   int32_t EOR;
 } REQ_Online;
 
 typedef struct {
-  uint32_t mask;
-  uint32_t address;
+  IPAddr mask;
+  IPAddr address;
   int32_t EOR;
 } REQ_Offline;
 
 typedef struct {
-  uint32_t mask;
-  uint32_t address;
+  IPAddr mask;
+  IPAddr address;
   int32_t n_good_samples;
   int32_t n_total_samples;
   int32_t EOR;
 } REQ_Burst;
 
 typedef struct {
-  uint32_t address;
+  IPAddr address;
   int32_t new_minpoll;
   int32_t EOR;
 } REQ_Modify_Minpoll;
 
 typedef struct {
-  uint32_t address;
+  IPAddr address;
   int32_t new_maxpoll;
   int32_t EOR;
 } REQ_Modify_Maxpoll;
@@ -133,13 +134,13 @@ typedef struct {
 } REQ_Dump;
 
 typedef struct {
-  uint32_t address;
+  IPAddr address;
   int32_t new_max_delay;
   int32_t EOR;
 } REQ_Modify_Maxdelay;
 
 typedef struct {
-  uint32_t address;
+  IPAddr address;
   int32_t new_max_delay_ratio;
   int32_t EOR;
 } REQ_Modify_Maxdelayratio;
@@ -184,18 +185,18 @@ typedef struct {
 } REQ_Rekey;
 
 typedef struct {
-  uint32_t ip;
+  IPAddr ip;
   int32_t subnet_bits;
   int32_t EOR;
 } REQ_Allow_Deny;
 
 typedef struct {
-  uint32_t ip;
+  IPAddr ip;
   int32_t EOR;
 } REQ_Ac_Check;
 
 typedef struct {
-  uint32_t ip_addr;
+  IPAddr ip_addr;
   uint32_t port;
   int32_t minpoll;
   int32_t maxpoll;
@@ -209,7 +210,7 @@ typedef struct {
 } REQ_NTP_Source;
 
 typedef struct {
-  uint32_t ip_addr;
+  IPAddr ip_addr;
   int32_t EOR;
 } REQ_Del_Source;
 
@@ -250,7 +251,7 @@ typedef struct {
 } REQ_CycleLogs;
 
 typedef struct {
-  uint32_t ip;
+  IPAddr ip;
   uint32_t bits_specd;
 } REQ_SubnetsAccessed_Subnet;
 
@@ -263,11 +264,11 @@ typedef struct {
 
 /* This is based on the response size rather than the
    request size */
-#define MAX_CLIENT_ACCESSES 16
+#define MAX_CLIENT_ACCESSES 8
 
 typedef struct {
   uint32_t n_clients;
-  uint32_t client_ips[MAX_CLIENT_ACCESSES];
+  IPAddr client_ips[MAX_CLIENT_ACCESSES];
 } REQ_ClientAccesses;  
 
 typedef struct {
@@ -310,9 +311,11 @@ typedef struct {
 
    Version 3 : NTP_Source message lengthened (auto_offline)
 
+   Version 4 : IPv6 addressing added
+
  */
 
-#define PROTO_VERSION_NUMBER 3
+#define PROTO_VERSION_NUMBER 4
 
 /* ================================================== */
 
@@ -419,6 +422,7 @@ typedef struct {
 #define STT_BADRTCFILE 14
 #define STT_INACTIVE 15
 #define STT_BADSAMPLE 16
+#define STT_INVALIDAF 17
 
 typedef struct {
   int32_t EOR;
@@ -440,7 +444,7 @@ typedef struct {
 #define RPY_SD_ST_OTHER 4
 
 typedef struct {
-  uint32_t ip_addr;
+  IPAddr ip_addr;
   uint16_t poll;
   uint16_t stratum;
   uint16_t state;
@@ -472,7 +476,7 @@ typedef struct {
 } RPY_Tracking;
 
 typedef struct {
-  uint32_t ip_addr;
+  IPAddr ip_addr;
   uint32_t n_samples;
   uint32_t n_runs;
   uint32_t span_seconds;
@@ -500,7 +504,7 @@ typedef struct {
 } RPY_ManualTimestamp;
 
 typedef struct {
-  uint32_t ip;
+  IPAddr ip;
   uint32_t bits_specd;
   uint32_t bitmap[8];
 } RPY_SubnetsAccessed_Subnet;
@@ -511,7 +515,7 @@ typedef struct {
 } RPY_SubnetsAccessed;
 
 typedef struct {
-  uint32_t ip;
+  IPAddr ip;
   uint32_t client_hits;
   uint32_t peer_hits;
   uint32_t cmd_hits_auth;
index bd250fe319c246e303fbe44e9fc265f664debf3e..de074e11e5fca4b505d3c116fc3073d721eb13ed 100644 (file)
--- a/client.c
+++ b/client.c
 
 /* ================================================== */
 
+union sockaddr_in46 {
+  struct sockaddr_in in4;
+#ifdef HAVE_IPV6
+  struct sockaddr_in6 in6;
+#endif
+  struct sockaddr u;
+};
+
 static int sock_fd;
-struct sockaddr_in his_addr;
+union sockaddr_in46 his_addr;
 
 static int on_terminal = 0;
 
@@ -138,61 +146,63 @@ read_line(void)
 }
 
 /* ================================================== */
+/* Initialise the socket used to talk to the daemon */
 
-static unsigned long
-get_address(const char *hostname)
+static void
+open_io(const char *hostname, int port)
 {
-  char *address0;
-  struct hostent *host;
-  unsigned long result;
+  union sockaddr_in46 my_addr;
+  IPAddr ip;
 
   /* Note, this call could block for a while */
-  host = gethostbyname(hostname);
-  if (host == NULL) {
+  if (!DNS_Name2IPAddress(hostname, &ip, 0)) {
     fprintf(stderr, "Could not get IP address for %s\n", hostname);
     exit(1);
-  } else {
-    address0 = host->h_addr_list[0];
-    result = ((((unsigned long) address0[0] & 0xff) << 24) |
-              (((unsigned long) address0[1] & 0xff) << 16) |
-              (((unsigned long) address0[2] & 0xff) <<  8) |
-              (((unsigned long) address0[3] & 0xff)));
   }
 
-  return result;
+  memset(&my_addr, 0, sizeof (my_addr));
+  memset(&his_addr, 0, sizeof (his_addr));
 
-}
+  switch (ip.family) {
+    case IPADDR_INET4:
+      sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
 
-/* ================================================== */
-/* Initialise the socket used to talk to the daemon */
+      my_addr.in4.sin_family = AF_INET;
+      my_addr.in4.sin_port = htons(INADDR_ANY);
+      my_addr.in4.sin_addr.s_addr = htonl(INADDR_ANY);
 
-static void
-open_io(const char *hostname, int port)
-{
-  struct sockaddr_in my_addr;
+      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);
+      break;
+#ifdef HAVE_IPV6
+    case IPADDR_INET6:
+      sock_fd = socket(AF_INET6, SOCK_DGRAM, 0);
+
+      my_addr.in6.sin6_family = AF_INET6;
+      my_addr.in6.sin6_port = htons(INADDR_ANY);
+      my_addr.in6.sin6_addr = in6addr_any;
+
+      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);
+      break;
+#endif
+    default:
+      assert(0);
+  }
 
-  sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
   if (sock_fd < 0) {
     perror("Can't create socket");
     exit(1);
   }
 
-  my_addr.sin_family = AF_INET;
-  my_addr.sin_port = htons(INADDR_ANY);
-  my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
-
-  if(bind(sock_fd, (struct sockaddr *) &my_addr, sizeof(my_addr)) < 0) {
+  if(bind(sock_fd, &my_addr.u, sizeof(my_addr)) < 0) {
     perror("Can't bind socket");
     exit(1);
   }
 
-  /* Build the socket address structure for sending packets */
-  his_addr.sin_family = AF_INET;
-  his_addr.sin_addr.s_addr = htonl(get_address(hostname));
-
-  /* Eventually the port number needs to be a command line param */
-  his_addr.sin_port = htons(port);
-
   return;
 }
 
@@ -208,34 +218,78 @@ close_io(void)
 
 /* ================================================== */
 
+static void
+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);
+  }
+}
+
+/* ================================================== */
+
 static int
-read_mask_address(char *line, unsigned long *mask, unsigned long *address)
+read_mask_address(char *line, IPAddr *mask, IPAddr *address)
 {
-  unsigned int ma, mb, mc, md, aa, ab, ac, ad;
-  int ok = 0;
-  char *p;
+  unsigned int bits;
+  char *p, *q;
 
   p = line;
   while (*p && isspace((unsigned char)*p)) p++;
   if (!*p) {
-    *mask = *address = 0;
-    ok = 1;
+    mask->family = address->family = IPADDR_UNSPEC;
+    return 1;
   } else {
-
-    if (sscanf(line, "%u.%u.%u.%u/%u.%u.%u.%u",
-               &ma, &mb, &mc, &md,
-               &aa, &ab, &ac, &ad) != 8) {
-      fprintf(stderr, "Invalid syntax for mask/address\n");
-      ok = 0;
+    q = strchr(p, '/');
+    if (q) {
+      *q++ = 0;
+      if (UTI_StringToIP(p, mask)) {
+        p = q;
+        while (*q && !isspace((unsigned char)*q)) q++;
+        *q = 0;
+        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 {
-      *mask =    (ma << 24) | (mb << 16) | (mc << 8) | md;
-      *address = (aa << 24) | (ab << 16) | (ac << 8) | ad;
-      ok = 1;
+      if (UTI_StringToIP(p, address)) {
+        bits_to_mask(-1, address->family, mask);
+        return 1;
+      }
     }
   }
 
-  return ok;
-
+  fprintf(stderr, "Invalid syntax for mask/address\n");
+  return 0;
 }
 
 /* ================================================== */
@@ -243,12 +297,12 @@ read_mask_address(char *line, unsigned long *mask, unsigned long *address)
 static int
 process_cmd_offline(CMD_Request *msg, char *line)
 {
-  unsigned long mask, address;
+  IPAddr mask, address;
   int ok;
 
   if (read_mask_address(line, &mask, &address)) {
-    msg->data.offline.mask = htonl(mask);
-    msg->data.offline.address = htonl(address);
+    UTI_IPHostToNetwork(&mask, &msg->data.offline.mask);
+    UTI_IPHostToNetwork(&address, &msg->data.offline.address);
     msg->command = htons(REQ_OFFLINE);
     ok = 1;
   } else {
@@ -265,12 +319,12 @@ process_cmd_offline(CMD_Request *msg, char *line)
 static int
 process_cmd_online(CMD_Request *msg, char *line)
 {
-  unsigned long mask, address;
+  IPAddr mask, address;
   int ok;
 
   if (read_mask_address(line, &mask, &address)) {
-    msg->data.online.mask = htonl(mask);
-    msg->data.online.address = htonl(address);
+    UTI_IPHostToNetwork(&mask, &msg->data.online.mask);
+    UTI_IPHostToNetwork(&address, &msg->data.online.address);
     msg->command = htons(REQ_ONLINE);
     ok = 1;
   } else {
@@ -284,7 +338,7 @@ process_cmd_online(CMD_Request *msg, char *line)
 /* ================================================== */
 
 static int
-read_address_integer(char *line, unsigned long *address, int *value)
+read_address_integer(char *line, IPAddr *address, int *value)
 {
   char hostname[2048];
   int ok = 0;
@@ -293,8 +347,7 @@ read_address_integer(char *line, unsigned long *address, int *value)
     fprintf(stderr, "Invalid syntax for address value\n");
     ok = 0;
   } else {
-    *address = DNS_Name2IPAddress(hostname);
-    if (*address == DNS_Failed_Address) {
+    if (!DNS_Name2IPAddress(hostname, address, 0)) {
       fprintf(stderr, "Could not get address for hostname\n");
       ok = 0;
     } else {
@@ -310,7 +363,7 @@ read_address_integer(char *line, unsigned long *address, int *value)
 /* ================================================== */
 
 static int
-read_address_double(char *line, unsigned long *address, double *value)
+read_address_double(char *line, IPAddr *address, double *value)
 {
   char hostname[2048];
   int ok = 0;
@@ -319,8 +372,7 @@ read_address_double(char *line, unsigned long *address, double *value)
     fprintf(stderr, "Invalid syntax for address value\n");
     ok = 0;
   } else {
-    *address = DNS_Name2IPAddress(hostname);
-    if (*address == DNS_Failed_Address) {
+    if (!DNS_Name2IPAddress(hostname, address, 0)) {
       fprintf(stderr, "Could not get address for hostname\n");
       ok = 0;
     } else {
@@ -338,12 +390,12 @@ read_address_double(char *line, unsigned long *address, double *value)
 static int
 process_cmd_minpoll(CMD_Request *msg, char *line)
 {
-  unsigned long address;
+  IPAddr address;
   int minpoll;
   int ok;
   
   if (read_address_integer(line, &address, &minpoll)) {
-    msg->data.modify_minpoll.address = htonl(address);
+    UTI_IPHostToNetwork(&address, &msg->data.modify_minpoll.address);
     msg->data.modify_minpoll.new_minpoll = htonl(minpoll);
     msg->command = htons(REQ_MODIFY_MINPOLL);
     ok = 1;
@@ -360,12 +412,12 @@ process_cmd_minpoll(CMD_Request *msg, char *line)
 static int
 process_cmd_maxpoll(CMD_Request *msg, char *line)
 {
-  unsigned long address;
+  IPAddr address;
   int maxpoll;
   int ok;
   
   if (read_address_integer(line, &address, &maxpoll)) {
-    msg->data.modify_maxpoll.address = htonl(address);
+    UTI_IPHostToNetwork(&address, &msg->data.modify_maxpoll.address);
     msg->data.modify_maxpoll.new_maxpoll = htonl(maxpoll);
     msg->command = htons(REQ_MODIFY_MAXPOLL);
     ok = 1;
@@ -382,12 +434,12 @@ process_cmd_maxpoll(CMD_Request *msg, char *line)
 static int
 process_cmd_maxdelay(CMD_Request *msg, char *line)
 {
-  unsigned long address;
+  IPAddr address;
   double max_delay;
   int ok;
   
   if (read_address_double(line, &address, &max_delay)) {
-    msg->data.modify_maxdelay.address = htonl(address);
+    UTI_IPHostToNetwork(&address, &msg->data.modify_maxdelay.address);
     msg->data.modify_maxdelay.new_max_delay = REAL2WIRE(max_delay);
     msg->command = htons(REQ_MODIFY_MAXDELAY);
     ok = 1;
@@ -404,12 +456,12 @@ process_cmd_maxdelay(CMD_Request *msg, char *line)
 static int
 process_cmd_maxdelayratio(CMD_Request *msg, char *line)
 {
-  unsigned long address;
+  IPAddr address;
   double max_delay_ratio;
   int ok;
   
   if (read_address_double(line, &address, &max_delay_ratio)) {
-    msg->data.modify_maxdelayratio.address = htonl(address);
+    UTI_IPHostToNetwork(&address, &msg->data.modify_maxdelayratio.address);
     msg->data.modify_maxdelayratio.new_max_delay_ratio = REAL2WIRE(max_delay_ratio);
     msg->command = htons(REQ_MODIFY_MAXDELAYRATIO);
     ok = 1;
@@ -478,36 +530,28 @@ process_cmd_cyclelogs(CMD_Request *msg, char *line)
 static int
 process_cmd_burst(CMD_Request *msg, char *line)
 {
-  int ok;
   int n_good_samples, n_total_samples;
-  unsigned int ma, mb, mc, md, aa, ab, ac, ad;
   int n_parsed;
+  char s[101];
+  IPAddr address, mask;
 
-  n_parsed = sscanf(line, "%d/%d %u.%u.%u.%u/%u.%u.%u.%u",
-                    &n_good_samples,
-                    &n_total_samples,
-                    &ma, &mb, &mc, &md,
-                    &aa, &ab, &ac, &ad);
+  n_parsed = sscanf(line, "%d/%d %100s", &n_good_samples, &n_total_samples, s);
 
   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);
 
-  if (n_parsed == 10) {
-    msg->data.burst.mask = htonl((ma << 24) | (mb << 16) | (mc << 8) | md);
-    msg->data.burst.address = htonl((aa << 24) | (ab << 16) | (ac << 8) | ad);
-    ok = 1;
-  } else if (n_parsed == 2) {
-    msg->data.burst.mask = 0;
-    msg->data.burst.address = 0;
-    ok = 1;
-  } else {
-    ok = 0;
+  mask.family = address.family = IPADDR_UNSPEC;
+
+  if (n_parsed < 2 || (n_parsed == 3 && !read_mask_address(s, &mask, &address))) {
     fprintf(stderr, "Invalid syntax for burst command\n");
+    return 0;
   }
 
-  return ok;
+  UTI_IPHostToNetwork(&mask, &msg->data.burst.mask);
+  UTI_IPHostToNetwork(&address, &msg->data.burst.address);
 
+  return 1;
 }
 
 /* ================================================== */
@@ -574,66 +618,81 @@ process_cmd_manual(CMD_Request *msg, const char *line)
 static int
 parse_allow_deny(CMD_Request *msg, char *line)
 {
-  unsigned long a, b, c, d, n, ip;
+  unsigned long a, b, c, d, n;
+  IPAddr ip;
   char *p, *q;
   
   p = line;
   while (*p && isspace((unsigned char)*p)) p++;
   if (!*p) {
     /* blank line - applies to all addresses */
-    msg->data.allow_deny.ip = htonl(0);
+    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 = sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d);
+    n = 0;
+    if (!UTI_StringToIP(p, &ip) &&
+        (n = sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d)) == 0) {
 
-    if (n == 0) {
       /* Try to parse as the name of a machine */
       q = p;
       while (*q) {
         if (*q == '\n') *q = 0;
         q++;
       }
-      ip = DNS_Name2IPAddress(p);
-      if (ip == DNS_Failed_Address) {
+      if (!DNS_Name2IPAddress(p, &ip, 0)) {
         fprintf(stderr, "Could not read address\n");
         return 0;
       } else {
-        msg->data.allow_deny.ip = htonl(ip);
-        msg->data.allow_deny.subnet_bits = htonl(32);
+        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 {
       
-      a &= 0xff;
-      b &= 0xff;
-      c &= 0xff;
-      d &= 0xff;
-      
-      switch (n) {
-        case 1:
-          msg->data.allow_deny.ip = htonl((a<<24));
-          msg->data.allow_deny.subnet_bits = htonl(8);
-          break;
-        case 2:
-          msg->data.allow_deny.ip = htonl((a<<24) | (b<<16));
-          msg->data.allow_deny.subnet_bits = htonl(16);
-          break;
-        case 3:
-          msg->data.allow_deny.ip = htonl((a<<24) | (b<<16) | (c<<8));
-          msg->data.allow_deny.subnet_bits = htonl(24);
-          break;
-        case 4:
-          msg->data.allow_deny.ip = htonl((a<<24) | (b<<16) | (c<<8) | d);
+      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);
-          break;
-        default:
-          assert(0);
-          
+      } 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);
@@ -739,9 +798,10 @@ process_cmd_cmddenyall(CMD_Request *msg, char *line)
 /* ================================================== */
 
 static int
-accheck_getaddr(char *line, unsigned long *addr)
+accheck_getaddr(char *line, IPAddr *addr)
 {
-  unsigned long a, b, c, d, ip;
+  unsigned long a, b, c, d;
+  IPAddr ip;
   char *p, *q;
   p = line;
   while (*p && isspace(*p)) p++;
@@ -749,7 +809,8 @@ accheck_getaddr(char *line, unsigned long *addr)
     return 0;
   } else {
     if (sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d) == 4) {
-      *addr = (a<<24) | (b<<16) | (c<<8) | d;
+      addr->family = IPADDR_INET4;
+      addr->addr.in4 = (a<<24) | (b<<16) | (c<<8) | d;
       return 1;
     } else {
       q = p;
@@ -757,8 +818,7 @@ accheck_getaddr(char *line, unsigned long *addr)
         if (*q == '\n') *q = 0;
         q++;
       }
-      ip = DNS_Name2IPAddress(p);
-      if (ip == DNS_Failed_Address) {
+      if (!DNS_Name2IPAddress(p, &ip, 0)) {
         return 0;
       } else {
         *addr = ip;
@@ -773,10 +833,10 @@ accheck_getaddr(char *line, unsigned long *addr)
 static int
 process_cmd_accheck(CMD_Request *msg, char *line)
 {
-  unsigned long ip;
+  IPAddr ip;
   msg->command = htons(REQ_ACCHECK);
   if (accheck_getaddr(line, &ip)) {
-    msg->data.ac_check.ip = htonl(ip);
+    UTI_IPHostToNetwork(&ip, &msg->data.ac_check.ip);
     return 1;
   } else {    
     fprintf(stderr, "Could not read address\n");
@@ -789,10 +849,10 @@ process_cmd_accheck(CMD_Request *msg, char *line)
 static int
 process_cmd_cmdaccheck(CMD_Request *msg, char *line)
 {
-  unsigned long ip;
+  IPAddr ip;
   msg->command = htons(REQ_CMDACCHECK);
   if (accheck_getaddr(line, &ip)) {
-    msg->data.ac_check.ip = htonl(ip);
+    UTI_IPHostToNetwork(&ip, &msg->data.ac_check.ip);
     return 1;
   } else {    
     fprintf(stderr, "Could not read address\n");
@@ -866,7 +926,7 @@ process_cmd_add_server_or_peer(CMD_Request *msg, char *line)
   switch (status) {
     case CPS_Success:
       msg->data.ntp_source.port = htonl((unsigned long) data.port);
-      msg->data.ntp_source.ip_addr = htonl(data.ip_addr);
+      UTI_IPHostToNetwork(&data.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);
@@ -935,7 +995,7 @@ process_cmd_delete(CMD_Request *msg, char *line)
 {
   char hostname[2048];
   int ok = 0;
-  unsigned long address = 0UL;
+  IPAddr address;
 
   msg->command = htons(REQ_DEL_SOURCE);
 
@@ -943,8 +1003,7 @@ process_cmd_delete(CMD_Request *msg, char *line)
     fprintf(stderr, "Invalid syntax for address\n");
     ok = 0;
   } else {
-    address = DNS_Name2IPAddress(hostname);
-    if (address == DNS_Failed_Address) {
+    if (!DNS_Name2IPAddress(hostname, &address, 0)) {
       fprintf(stderr, "Could not get address for hostname\n");
       ok = 0;
     } else {
@@ -952,7 +1011,7 @@ process_cmd_delete(CMD_Request *msg, char *line)
     }
   }
 
-  msg->data.del_source.ip_addr = htonl(address);
+  UTI_IPHostToNetwork(&address, &msg->data.del_source.ip_addr);
 
   return ok;
   
@@ -1121,7 +1180,7 @@ submit_request(CMD_Request *request, CMD_Reply *reply, int *reply_auth_ok)
 {
   unsigned long tx_sequence;
   socklen_t where_from_len;
-  struct sockaddr_in where_from;
+  union sockaddr_in46 where_from;
   int bad_length, bad_sender, bad_sequence, bad_header;
   int select_status;
   int recvfrom_status;
@@ -1168,7 +1227,7 @@ submit_request(CMD_Request *request, CMD_Reply *reply, int *reply_auth_ok)
 #endif
 
     if (sendto(sock_fd, (void *) request, command_length, 0,
-               (struct sockaddr *) &his_addr, sizeof(his_addr)) < 0) {
+               &his_addr.u, sizeof(his_addr)) < 0) {
 
 
 #if 0
@@ -1210,7 +1269,7 @@ submit_request(CMD_Request *request, CMD_Reply *reply, int *reply_auth_ok)
       
       where_from_len = sizeof(where_from);
       recvfrom_status = recvfrom(sock_fd, (void *) reply, sizeof(CMD_Reply), 0,
-                                 (struct sockaddr *) &where_from, &where_from_len);
+                                 &where_from.u, &where_from_len);
       
 
 #if 0
@@ -1231,8 +1290,17 @@ submit_request(CMD_Request *request, CMD_Reply *reply, int *reply_auth_ok)
         expected_length = PKL_ReplyLength(reply);
 
         bad_length = (read_length != expected_length);
-        bad_sender = ((where_from.sin_addr.s_addr != his_addr.sin_addr.s_addr) ||
-                      (where_from.sin_port != his_addr.sin_port));
+        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);
@@ -1382,13 +1450,12 @@ process_cmd_sources(char *line)
   int verbose = 0;
 
   int32_t orig_latest_meas, latest_meas, est_offset;
-  uint32_t ip_addr;
+  IPAddr ip_addr;
   uint32_t latest_meas_err, est_offset_err;
   uint32_t latest_meas_ago;
   uint16_t poll, stratum;
   uint16_t state, mode;
   double resid_freq, resid_skew;
-  const char *dns_lookup;
   char hostname_buf[32];
   uint16_t status;
 
@@ -1439,7 +1506,7 @@ process_cmd_sources(char *line)
 
       if (submit_ok) {
         if (ntohs(reply.status) == STT_SUCCESS) {
-          ip_addr = ntohl(reply.data.source_data.ip_addr);
+          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);
@@ -1453,14 +1520,13 @@ process_cmd_sources(char *line)
           resid_freq = (double) ((long) ntohl(reply.data.source_data.resid_freq)) * 1.0e-3;
           resid_skew = (double) (ntohl(reply.data.source_data.resid_skew)) * 1.0e-3;
 
-          hostname_buf[25] = 0;
           if (mode == RPY_SD_MD_REF) {
-            snprintf(hostname_buf, sizeof(hostname_buf), "%s", UTI_RefidToString(ip_addr));
+            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_IPToDottedQuad(ip_addr));
+            snprintf(hostname_buf, sizeof(hostname_buf), "%s", UTI_IPToString(&ip_addr));
           } else {
-            dns_lookup = DNS_IPAddress2Name(ip_addr);
-            strncpy(hostname_buf, dns_lookup, 25);
+            DNS_IPAddress2Name(&ip_addr, hostname_buf, sizeof(hostname_buf));
+            hostname_buf[25] = 0;
           }
 
           switch (mode) {
@@ -1515,12 +1581,11 @@ process_cmd_sourcestats(char *line)
   int n_sources, i;
   int verbose = 0;
 
-  const char *dns_lookup;
   char hostname_buf[32];
   unsigned long n_samples, n_runs, span_seconds;
   double resid_freq_ppm, skew_ppm;
   unsigned long sd_us;
-  unsigned long ip_addr;
+  IPAddr ip_addr;
   unsigned short status;
 
   verbose = check_for_verbose_flag(line);
@@ -1569,7 +1634,7 @@ process_cmd_sourcestats(char *line)
       if (submit_ok) {
         if (ntohs(reply.status) == STT_SUCCESS) {
           
-          ip_addr = ntohl(reply.data.sourcestats.ip_addr);
+          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);
@@ -1577,12 +1642,11 @@ process_cmd_sourcestats(char *line)
           skew_ppm = WIRE2REAL(reply.data.sourcestats.skew_ppm);
           sd_us = ntohl(reply.data.sourcestats.sd_us);
 
-          hostname_buf[25] = 0;
           if (no_dns) {
-            snprintf(hostname_buf, sizeof(hostname_buf), "%s", UTI_IPToDottedQuad(ip_addr));
+            snprintf(hostname_buf, sizeof(hostname_buf), "%s", UTI_IPToString(&ip_addr));
           } else {
-            dns_lookup = DNS_IPAddress2Name(ip_addr);
-            strncpy(hostname_buf, dns_lookup, 25);
+            DNS_IPAddress2Name(&ip_addr, hostname_buf, sizeof(hostname_buf));
+            hostname_buf[25] = 0;
           }
 
           printf("%-25s  %2lu  %2lu  ", hostname_buf, n_samples, n_runs);
@@ -1644,9 +1708,10 @@ process_cmd_tracking(char *line)
     b = (ref_id >> 16) & 0xff;
     c = (ref_id >> 8) & 0xff;
     d = (ref_id) & 0xff;
+    
     printf("Reference ID    : %lu.%lu.%lu.%lu (%s)\n",
-           a, b, c, d,
-           (no_dns) ? UTI_IPToDottedQuad(ref_id) : DNS_IPAddress2Name(ref_id));
+           a, b, c, d, "");
+           //* TODO (no_dns) ? UTI_IPToDottedQuad(ref_id) : DNS_IPAddress2Name(ref_id)); */
     printf("Stratum         : %lu\n", (unsigned long) ntohl(reply.data.tracking.stratum));
     ref_time.tv_sec = ntohl(reply.data.tracking.ref_time_s);
     ref_time.tv_usec = ntohl(reply.data.tracking.ref_time_us);
@@ -1766,7 +1831,6 @@ process_cmd_clients(char *line)
   unsigned long last_ntp_hit_ago;
   unsigned long last_cmd_hit_ago;
   char hostname_buf[32];
-  const char *dns_lookup;
 
   int n_replies;
 
@@ -1922,9 +1986,8 @@ process_cmd_clients(char *line)
                 snprintf(hostname_buf, sizeof(hostname_buf), 
                          "%s", UTI_IPToDottedQuad(ip));
               } else {
-                dns_lookup = DNS_IPAddress2Name(ip);
+                DNS_IPAddress2Name(ip, hostname_buf, sizeof(hostname_buf));
                 hostname_buf[25] = 0;
-                strncpy(hostname_buf, dns_lookup, 25);
               }
               printf("%-25s  %6d  %6d  %6d  %6d  %6d  ",
                      hostname_buf,
@@ -1988,7 +2051,7 @@ process_cmd_clients(char *line)
   int status;
   unsigned long next_index;
   int j;
-  unsigned long ip;
+  IPAddr ip;
   unsigned long client_hits;
   unsigned long peer_hits;
   unsigned long cmd_hits_auth;
@@ -1997,7 +2060,6 @@ process_cmd_clients(char *line)
   unsigned long last_ntp_hit_ago;
   unsigned long last_cmd_hit_ago;
   char hostname_buf[32];
-  const char *dns_lookup;
 
   int n_replies;
   int n_indices_in_table;
@@ -2025,9 +2087,9 @@ process_cmd_clients(char *line)
             goto finished;
           }
           for (j=0; j<n_replies; j++) {
-            ip = ntohl(reply.data.client_accesses_by_index.clients[j].ip);
-            if (ip != 0UL) {
-              /* ip == 0 implies that the node could not be found in
+            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
@@ -2045,11 +2107,10 @@ process_cmd_clients(char *line)
 
               if (no_dns) {
                 snprintf(hostname_buf, sizeof(hostname_buf),
-                         "%s", UTI_IPToDottedQuad(ip));
+                         "%s", UTI_IPToString(&ip));
               } else {
-                dns_lookup = DNS_IPAddress2Name(ip);
+                DNS_IPAddress2Name(&ip, hostname_buf, sizeof(hostname_buf));
                 hostname_buf[25] = 0;
-                strncpy(hostname_buf, dns_lookup, 25);
               }
               printf("%-25s  %6ld  %6ld  %6ld  %6ld  %6ld  ",
                      hostname_buf,
@@ -2475,6 +2536,9 @@ process_line(char *line)
         case STT_BADRTCFILE:
           printf("514 Can't write RTC parameters");
           break;
+        case STT_INVALIDAF:
+          printf("515 Invalid address family");
+          break;
       }
       
       if (reply_auth_ok) {
index f3ca03391973ad8d061af33df5ec2b343262527b..d7b8fc1e5f4ff724d185fc4f9b9967c5f77f3d22 100644 (file)
@@ -53,7 +53,7 @@
 #define TABLE_SIZE (1UL<<NBITS)
 
 typedef struct _Node {
-  unsigned long ip_addr;
+  IPAddr ip_addr;
   unsigned long client_hits;
   unsigned long peer_hits;
   unsigned long cmd_hits_bad;
@@ -69,8 +69,10 @@ typedef struct _Subnet {
 
 /* ================================================== */
 
-/* Table for the class A subnet */
-static Subnet top_subnet;
+/* Table for the IPv4 class A subnet */
+static Subnet top_subnet4;
+/* Table for IPv6 */
+static Subnet top_subnet6;
 
 /* Table containing pointers directly to all nodes that have been
    allocated. */
@@ -89,6 +91,34 @@ static int active = 0;
 
 /* ================================================== */
 
+static void
+split_ip6(IPAddr *ip, uint32_t *dst)
+{
+  int i;
+
+  for (i = 0; i < 4; i++)
+    dst[i] = ip->addr.in6[i * 4 + 0] << 24 |
+             ip->addr.in6[i * 4 + 1] << 16 |
+             ip->addr.in6[i * 4 + 2] << 8 |
+             ip->addr.in6[i * 4 + 3];
+}
+
+/* ================================================== */
+
+inline static uint32_t
+get_subnet(uint32_t *addr, unsigned int where)
+{
+  int off;
+
+  off = where / 32;
+  where %= 32;
+
+  return (addr[off] >> (32 - NBITS - where)) & ((1UL << NBITS) - 1);
+}
+
+/* ================================================== */
+
+
 static void
 clear_subnet(Subnet *subnet)
 {
@@ -118,7 +148,8 @@ clear_node(Node *node)
 void
 CLG_Initialise(void)
 {
-  clear_subnet(&top_subnet);
+  clear_subnet(&top_subnet4);
+  clear_subnet(&top_subnet6);
   if (CNF_GetNoClientLog()) {
     active = 0;
   } else {
@@ -178,27 +209,18 @@ create_node(Subnet *parent_subnet, int the_entry)
    expanding subnet tables and node entries as we go if necessary. */
 
 static void *
-find_subnet(Subnet *subnet, CLG_IP_Addr addr, int bits_left)
+find_subnet(Subnet *subnet, uint32_t *addr, int addr_len, int bits_consumed)
 {
-  unsigned long this_subnet, new_subnet, mask, shift;
-  unsigned long new_bits_left;
-  
-  shift = 32 - NBITS;
-  mask = (1UL<<shift) - 1;
-  this_subnet = addr >> shift;
-  new_subnet = (addr & mask) << NBITS;
-  new_bits_left = bits_left - NBITS;
-
-#if 0
-  fprintf(stderr, "fs addr=%08lx bl=%d ma=%08lx this=%08lx newsn=%08lx nbl=%d\n",
-          addr, bits_left, mask, this_subnet, new_subnet, new_bits_left);
-#endif
-
-  if (new_bits_left > 0) {
+  uint32_t this_subnet;
+
+  this_subnet = get_subnet(addr, bits_consumed);
+  bits_consumed += NBITS;
+
+  if (bits_consumed < 32 * addr_len) {
     if (!subnet->entry[this_subnet]) {
       create_subnet(subnet, this_subnet);
     }
-    return find_subnet((Subnet *) subnet->entry[this_subnet], new_subnet, new_bits_left);
+    return find_subnet((Subnet *) subnet->entry[this_subnet], addr, addr_len, bits_consumed);
   } else {
     if (!subnet->entry[this_subnet]) {
       create_node(subnet, this_subnet);
@@ -213,30 +235,21 @@ find_subnet(Subnet *subnet, CLG_IP_Addr addr, int bits_left)
    one of the parents does not exist - never open a node out */
 
 static void *
-find_subnet_dont_open(Subnet *subnet, CLG_IP_Addr addr, int bits_left)
+find_subnet_dont_open(Subnet *subnet, uint32_t *addr, int addr_len, int bits_consumed)
 {
-  unsigned long this_subnet, new_subnet, mask, shift;
-  unsigned long new_bits_left;
+  uint32_t this_subnet;
 
-  if (bits_left == 0) {
+  if (bits_consumed >= 32 * addr_len) {
     return subnet;
   } else {
     
-    shift = 32 - NBITS;
-    mask = (1UL<<shift) - 1;
-    this_subnet = addr >> shift;
-    new_subnet = (addr & mask) << NBITS;
-    new_bits_left = bits_left - NBITS;
-
-#if 0
-    fprintf(stderr, "fsdo addr=%08lx bl=%d this=%08lx newsn=%08lx nbl=%d\n",
-            addr, bits_left, this_subnet, new_subnet, new_bits_left);
-#endif
-    
+    this_subnet = get_subnet(addr, bits_consumed);
+    bits_consumed += NBITS;
+
     if (!subnet->entry[this_subnet]) {
       return NULL;
     } else {
-      return find_subnet_dont_open((Subnet *) subnet->entry[this_subnet], new_subnet, new_bits_left);
+      return find_subnet_dont_open((Subnet *) subnet->entry[this_subnet], addr, addr_len, bits_consumed);
     }
   }
 }
@@ -244,12 +257,25 @@ find_subnet_dont_open(Subnet *subnet, CLG_IP_Addr addr, int bits_left)
 /* ================================================== */
 
 void
-CLG_LogNTPClientAccess (CLG_IP_Addr client, time_t now)
+CLG_LogNTPClientAccess (IPAddr *client, time_t now)
 {
+  uint32_t ip6[4];
   Node *node;
+
   if (active) {
-    node = (Node *) find_subnet(&top_subnet, client, 32);
-    node->ip_addr = client;
+    switch (client->family) {
+      case IPADDR_INET4:
+        node = (Node *) find_subnet(&top_subnet4, &client->addr.in4, 1, 0);
+        break;
+      case IPADDR_INET6:
+        split_ip6(client, ip6);
+        node = (Node *) find_subnet(&top_subnet6, ip6, 4, 0);
+        break;
+      default:
+        assert(0);
+    }
+
+    node->ip_addr = *client;
     ++node->client_hits;
     node->last_ntp_hit = now;
   }
@@ -258,12 +284,25 @@ CLG_LogNTPClientAccess (CLG_IP_Addr client, time_t now)
 /* ================================================== */
 
 void
-CLG_LogNTPPeerAccess(CLG_IP_Addr client, time_t now)
+CLG_LogNTPPeerAccess(IPAddr *client, time_t now)
 {
+  uint32_t ip6[4];
   Node *node;
+
   if (active) {
-    node = (Node *) find_subnet(&top_subnet, client, 32);
-    node->ip_addr = client;
+    switch (client->family) {
+      case IPADDR_INET4:
+        node = (Node *) find_subnet(&top_subnet4, &client->addr.in4, 1, 0);
+        break;
+      case IPADDR_INET6:
+        split_ip6(client, ip6);
+        node = (Node *) find_subnet(&top_subnet6, ip6, 4, 0);
+        break;
+      default:
+        assert(0);
+    }
+
+    node->ip_addr = *client;
     ++node->peer_hits;
     node->last_ntp_hit = now;
   }
@@ -272,12 +311,25 @@ CLG_LogNTPPeerAccess(CLG_IP_Addr client, time_t now)
 /* ================================================== */
 
 void
-CLG_LogCommandAccess(CLG_IP_Addr client, CLG_Command_Type type, time_t now)
+CLG_LogCommandAccess(IPAddr *client, CLG_Command_Type type, time_t now)
 {
+  uint32_t ip6[4];
   Node *node;
+
   if (active) {
-    node = (Node *) find_subnet(&top_subnet, client, 32);
-    node->ip_addr = client;
+    switch (client->family) {
+      case IPADDR_INET4:
+        node = (Node *) find_subnet(&top_subnet4, &client->addr.in4, 1, 0);
+        break;
+      case IPADDR_INET6:
+        split_ip6(client, ip6);
+        node = (Node *) find_subnet(&top_subnet6, ip6, 4, 0);
+        break;
+      default:
+        assert(0);
+    }
+
+    node->ip_addr = *client;
     node->last_cmd_hit = now;
     switch (type) {
       case CLG_CMD_AUTH:
@@ -299,16 +351,32 @@ CLG_LogCommandAccess(CLG_IP_Addr client, CLG_Command_Type type, time_t now)
 /* ================================================== */
 
 CLG_Status
-CLG_GetSubnetBitmap(CLG_IP_Addr subnet, int bits, CLG_Bitmap result)
+CLG_GetSubnetBitmap(IPAddr *subnet, int bits, CLG_Bitmap result)
 {
   Subnet *s;
+  uint32_t ip6[4];
   unsigned long i;
   unsigned long word, bit, mask;
 
-  if ((bits == 0) || (bits == 8) || (bits == 16) || (bits == 24)) {
+  if (bits >= 0 && bits % 8 == 0) {
     memset (result, 0, TABLE_SIZE/8);
     if (active) {
-      s = find_subnet_dont_open(&top_subnet, subnet, bits);
+      switch (subnet->family) {
+        case IPADDR_INET4:
+          if (bits >= 32)
+            return CLG_BADSUBNET;
+          s = find_subnet_dont_open(&top_subnet4, &subnet->addr.in4, 1, 32 - bits);
+          break;
+        case IPADDR_INET6:
+          if (bits >= 128)
+            return CLG_BADSUBNET;
+          split_ip6(subnet, ip6);
+          s = find_subnet_dont_open(&top_subnet6, ip6, 4, 128 - bits);
+          break;
+        default:
+          return CLG_BADSUBNET;
+      }
+
       if (s) {
         for (i=0; i<256; i++) {
           if (s->entry[i]) {
@@ -333,15 +401,26 @@ CLG_GetSubnetBitmap(CLG_IP_Addr subnet, int bits, CLG_Bitmap result)
 /* ================================================== */
 
 CLG_Status
-CLG_GetClientAccessReportByIP(unsigned long ip, RPT_ClientAccess_Report *report, time_t now)
+CLG_GetClientAccessReportByIP(IPAddr *ip, RPT_ClientAccess_Report *report, time_t now)
 {
+  uint32_t ip6[4];
   Node *node;
 
   if (!active) {
     return CLG_INACTIVE;
   } else {
-    node = (Node *) find_subnet_dont_open(&top_subnet, ip, 32);
-  
+    switch (ip->family) {
+      case IPADDR_INET4:
+        node = (Node *) find_subnet_dont_open(&top_subnet4, &ip->addr.in4, 1, 0);
+        break;
+      case IPADDR_INET6:
+        split_ip6(ip, ip6);
+        node = (Node *) find_subnet_dont_open(&top_subnet6, ip6, 4, 0);
+        break;
+      default:
+        return CLG_EMPTYSUBNET;
+    }
+
     if (!node) {
       return CLG_EMPTYSUBNET;
     } else {
index ab7c470dad7c9c2360e0bd8b366451cb9f68d947..0df9de8deb97a3abc8839912360f6bb740ee66d6 100644 (file)
 #include "sysincl.h"
 #include "reports.h"
 
-typedef unsigned long CLG_IP_Addr;
-
 /* Enough to hold flags for 256 hosts in a class C */
 typedef uint32_t CLG_Bitmap[8];
 
 extern void CLG_Initialise(void);
 extern void CLG_Finalise(void);
-extern void CLG_LogNTPClientAccess(CLG_IP_Addr client, time_t now);
-extern void CLG_LogNTPPeerAccess(CLG_IP_Addr client, time_t now);
+extern void CLG_LogNTPClientAccess(IPAddr *client, time_t now);
+extern void CLG_LogNTPPeerAccess(IPAddr *client, time_t now);
 
 /* When logging command packets, there are several subtypes */
 
@@ -53,7 +51,7 @@ typedef enum {
   CLG_CMD_BAD_PKT               /* bad version or packet length */
 } CLG_Command_Type;
 
-extern void CLG_LogCommandAccess(CLG_IP_Addr client, CLG_Command_Type type, time_t now);
+extern void CLG_LogCommandAccess(IPAddr *client, CLG_Command_Type type, time_t now);
 
 /* And some reporting functions, for use by chronyc. */
 /* TBD */
@@ -70,10 +68,10 @@ typedef enum {
    known.  For bits=24, flag which hosts in that subnet are known.
    Other values, return 0 (failed) */
 
-extern CLG_Status CLG_GetSubnetBitmap(CLG_IP_Addr subnet, int bits, CLG_Bitmap result);
+extern CLG_Status CLG_GetSubnetBitmap(IPAddr *subnet, int bits, CLG_Bitmap result);
 
 extern CLG_Status
-CLG_GetClientAccessReportByIP(unsigned long ip, RPT_ClientAccess_Report *report, time_t now);
+CLG_GetClientAccessReportByIP(IPAddr *ip, RPT_ClientAccess_Report *report, time_t now);
 
 CLG_Status
 CLG_GetClientAccessReportByIndex(int index, RPT_ClientAccessByIndex_Report *report,
@@ -83,7 +81,7 @@ CLG_GetClientAccessReportByIndex(int index, RPT_ClientAccessByIndex_Report *repo
    that has accessed us since 'since'. */
 
 extern void CLG_IterateNTPClients
-(void (*fn)(CLG_IP_Addr client, void *arb),
+(void (*fn)(IPAddr *client, void *arb),
  void *arb,
  time_t since);
 
index f5e3c8b9c259d0d47d25565e46c276abca3d0954..04087551bf7bda2f7be502fd855505258b74f621 100644 (file)
--- a/cmdmon.c
+++ b/cmdmon.c
 
 /* ================================================== */
 
-/* File descriptor for command and monitoring socket */
-static int sock_fd;
+union sockaddr_in46 {
+  struct sockaddr_in in4;
+#ifdef HAVE_IPV6
+  struct sockaddr_in6 in6;
+#endif
+  struct sockaddr u;
+};
+
+/* File descriptors for command and monitoring sockets */
+static int sock_fd4;
+#ifdef HAVE_IPV6
+static int sock_fd6;
+#endif
 
 /* Flag indicating whether this module has been initialised or not */
 static int initialised = 0;
@@ -157,45 +168,28 @@ static ADF_AuthTable access_auth_table;
 
 /* ================================================== */
 /* Forward prototypes */
+static int prepare_socket(int family);
 static void read_from_cmd_socket(void *anything);
 
 /* ================================================== */
 
-void
-CAM_Initialise(void)
+static int
+prepare_socket(int family)
 {
-  int port_number;
-  struct sockaddr_in my_addr;
-  unsigned long bind_address;
+  int port_number, sock_fd;
+  union sockaddr_in46 my_addr;
+  IPAddr bind_address;
   int on_off = 1;
 
-  if (initialised) {
-    CROAK("Shouldn't be initialised");
-  }
-
-  initialised = 1;
-
-  if ((sizeof(permissions)/sizeof(permissions[0])) != N_REQUEST_TYPES) {
-    CROAK("Permissions table size wrong");
-  }
-
-  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;
-
   port_number = CNF_GetCommandPort();
   if (port_number < 0) {
     port_number = DEFAULT_CANDM_PORT;
   }
 
-  sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
+  sock_fd = socket(family, SOCK_DGRAM, 0);
   if (sock_fd < 0) {
-    LOG_FATAL(LOGF_CmdMon, "Could not open socket : %s", strerror(errno));
+    LOG(LOGS_ERR, LOGF_CmdMon, "Could not open socket : %s", strerror(errno));
+    return -1;
   }
 
   /* Allow reuse of port number */
@@ -203,24 +197,96 @@ CAM_Initialise(void)
     LOG(LOGS_ERR, LOGF_CmdMon, "Could not set 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_NtpIO, "Could not request IPV6_V6ONLY socket option");
+    }
+#endif
+  }
+#endif
 
-  my_addr.sin_family = AF_INET;
-  my_addr.sin_port = htons((unsigned short) port_number);
+  memset(&my_addr, 0, sizeof (my_addr));
 
-  CNF_GetBindCommandAddress(&bind_address);
+  switch (family) {
+    case AF_INET:
+      my_addr.in4.sin_family = family;
+      my_addr.in4.sin_port = htons((unsigned short)port_number);
 
-  if (bind_address != 0UL) {
-    my_addr.sin_addr.s_addr = htonl(bind_address);
-  } else {
-    my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+      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.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, (struct sockaddr *) &my_addr, sizeof(my_addr)) < 0) {
+  if (bind(sock_fd, &my_addr.u, sizeof(my_addr)) < 0) {
     LOG_FATAL(LOGF_CmdMon, "Could not bind socket : %s", strerror(errno));
   }
 
   /* Register handler for read events on the socket */
-  SCH_AddInputFileHandler(sock_fd, read_from_cmd_socket, NULL);
+  SCH_AddInputFileHandler(sock_fd, read_from_cmd_socket, (void *)(long)sock_fd);
+
+  return sock_fd;
+}
+
+/* ================================================== */
+
+void
+CAM_Initialise(void)
+{
+
+  if (initialised) {
+    CROAK("Shouldn't be initialised");
+  }
+
+  initialised = 1;
+
+  if ((sizeof(permissions)/sizeof(permissions[0])) != N_REQUEST_TYPES) {
+    CROAK("Permissions table size wrong");
+  }
+
+  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;
+
+  sock_fd4 = prepare_socket(AF_INET);
+#ifdef HAVE_IPV6
+  sock_fd6 = prepare_socket(AF_INET6);
+#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();
 
@@ -231,9 +297,18 @@ CAM_Initialise(void)
 void
 CAM_Finalise(void)
 {
-  SCH_RemoveInputFileHandler(sock_fd);
-  close(sock_fd);
-  sock_fd = -1;
+  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);
 
@@ -644,21 +719,51 @@ print_reply_packet(CMD_Reply *pkt)
 /* ================================================== */
 
 static void
-transmit_reply(CMD_Reply *msg, struct sockaddr_in *where_to)
+transmit_reply(CMD_Reply *msg, union sockaddr_in46 *where_to)
 {
   int status;
   int tx_message_length;
-  unsigned long remote_ip;
-  unsigned short remote_port;
+  int sock_fd;
+  
+  switch (where_to->u.sa_family) {
+    case AF_INET:
+      sock_fd = sock_fd4;
+      break;
+#ifdef HAVE_IPV6
+    case AF_INET6:
+      sock_fd = sock_fd6;
+      break;
+#endif
+    default:
+      assert(0);
+  }
 
   tx_message_length = PKL_ReplyLength(msg);
   status = sendto(sock_fd, (void *) msg, tx_message_length, 0,
-                  (struct sockaddr *) where_to, sizeof(struct sockaddr_in));
+                  &where_to->u, sizeof(union sockaddr_in46));
 
   if (status < 0) {
-    remote_ip = ntohl(where_to->sin_addr.s_addr);
-    remote_port = ntohs(where_to->sin_port);
-    LOG(LOGS_WARN, LOGF_CmdMon, "Could not send response to %s:%hu", UTI_IPToDottedQuad(remote_ip), remote_port);
+    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);
   }
 
   return;
@@ -679,7 +784,10 @@ static void
 handle_online(CMD_Request *rx_message, CMD_Reply *tx_message)
 {
   int status;
-  status = NSR_TakeSourcesOnline(ntohl(rx_message->data.online.mask), ntohl(rx_message->data.online.address));
+  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 {
@@ -693,7 +801,10 @@ static void
 handle_offline(CMD_Request *rx_message, CMD_Reply *tx_message)
 {
   int status;
-  status = NSR_TakeSourcesOffline(ntohl(rx_message->data.offline.mask), ntohl(rx_message->data.offline.address));
+  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 {
@@ -707,10 +818,12 @@ static void
 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),
-                                   ntohl(rx_message->data.burst.mask),
-                                   ntohl(rx_message->data.burst.address));
+                                   &mask, &address);
   
   if (status) {
     tx_message->status = htons(STT_SUCCESS);
@@ -725,7 +838,9 @@ static void
 handle_modify_minpoll(CMD_Request *rx_message, CMD_Reply *tx_message)
 {
   int status;
-  status = NSR_ModifyMinpoll(ntohl(rx_message->data.modify_minpoll.address),
+  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) {
@@ -741,7 +856,9 @@ static void
 handle_modify_maxpoll(CMD_Request *rx_message, CMD_Reply *tx_message)
 {
   int status;
-  status = NSR_ModifyMaxpoll(ntohl(rx_message->data.modify_minpoll.address),
+  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) {
@@ -757,7 +874,9 @@ static void
 handle_modify_maxdelay(CMD_Request *rx_message, CMD_Reply *tx_message)
 {
   int status;
-  status = NSR_ModifyMaxdelay(ntohl(rx_message->data.modify_maxdelay.address),
+  IPAddr address;
+  UTI_IPNetworkToHost(&rx_message->data.modify_maxdelay.address, &address);
+  status = NSR_ModifyMaxdelay(&address,
                               WIRE2REAL(rx_message->data.modify_maxdelay.new_max_delay));
   if (status) {
     tx_message->status = htons(STT_SUCCESS);
@@ -772,7 +891,9 @@ static void
 handle_modify_maxdelayratio(CMD_Request *rx_message, CMD_Reply *tx_message)
 {
   int status;
-  status = NSR_ModifyMaxdelayratio(ntohl(rx_message->data.modify_maxdelayratio.address),
+  IPAddr address;
+  UTI_IPNetworkToHost(&rx_message->data.modify_maxdelayratio.address, &address);
+  status = NSR_ModifyMaxdelayratio(&address,
                                    WIRE2REAL(rx_message->data.modify_maxdelayratio.new_max_delay_ratio));
   if (status) {
     tx_message->status = htons(STT_SUCCESS);
@@ -884,7 +1005,7 @@ handle_source_data(CMD_Request *rx_message, CMD_Reply *tx_message)
     tx_message->status = htons(STT_SUCCESS);
     tx_message->reply  = htons(RPY_SOURCE_DATA);
     
-    tx_message->data.source_data.ip_addr = htonl(report.ip_addr);
+    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) {
@@ -943,11 +1064,11 @@ handle_rekey(CMD_Request *rx_message, CMD_Reply *tx_message)
 static void
 handle_allow(CMD_Request *rx_message, CMD_Reply *tx_message)
 {
-  unsigned long ip;
+  IPAddr ip;
   int subnet_bits;
-  ip = ntohl(rx_message->data.allow_deny.ip);
+  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)) {
+  if (NCR_AddAccessRestriction(&ip, subnet_bits, 1, 0)) {
     tx_message->status = htons(STT_SUCCESS);
   } else {
     tx_message->status = htons(STT_BADSUBNET);
@@ -959,11 +1080,11 @@ handle_allow(CMD_Request *rx_message, CMD_Reply *tx_message)
 static void
 handle_allowall(CMD_Request *rx_message, CMD_Reply *tx_message)
 {
-  unsigned long ip;
+  IPAddr ip;
   int subnet_bits;
-  ip = ntohl(rx_message->data.allow_deny.ip);
+  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)) {
+  if (NCR_AddAccessRestriction(&ip, subnet_bits, 1, 1)) {
     tx_message->status = htons(STT_SUCCESS);
   } else {
     tx_message->status = htons(STT_BADSUBNET);
@@ -975,11 +1096,11 @@ handle_allowall(CMD_Request *rx_message, CMD_Reply *tx_message)
 static void
 handle_deny(CMD_Request *rx_message, CMD_Reply *tx_message)
 {
-  unsigned long ip;
+  IPAddr ip;
   int subnet_bits;
-  ip = ntohl(rx_message->data.allow_deny.ip);
+  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)) {
+  if (NCR_AddAccessRestriction(&ip, subnet_bits, 0, 0)) {
     tx_message->status = htons(STT_SUCCESS);
   } else {
     tx_message->status = htons(STT_BADSUBNET);
@@ -991,11 +1112,11 @@ handle_deny(CMD_Request *rx_message, CMD_Reply *tx_message)
 static void
 handle_denyall(CMD_Request *rx_message, CMD_Reply *tx_message)
 {
-  unsigned long ip;
+  IPAddr ip;
   int subnet_bits;
-  ip = ntohl(rx_message->data.allow_deny.ip);
+  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)) {
+  if (NCR_AddAccessRestriction(&ip, subnet_bits, 0, 1)) {
     tx_message->status = htons(STT_SUCCESS);
   } else {
     tx_message->status = htons(STT_BADSUBNET);
@@ -1007,11 +1128,11 @@ handle_denyall(CMD_Request *rx_message, CMD_Reply *tx_message)
 static void
 handle_cmdallow(CMD_Request *rx_message, CMD_Reply *tx_message)
 {
-  unsigned long ip;
+  IPAddr ip;
   int subnet_bits;
-  ip = ntohl(rx_message->data.allow_deny.ip);
+  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)) {
+  if (CAM_AddAccessRestriction(&ip, subnet_bits, 1, 0)) {
     tx_message->status = htons(STT_SUCCESS);
   } else {
     tx_message->status = htons(STT_BADSUBNET);
@@ -1023,11 +1144,11 @@ handle_cmdallow(CMD_Request *rx_message, CMD_Reply *tx_message)
 static void
 handle_cmdallowall(CMD_Request *rx_message, CMD_Reply *tx_message)
 {
-  unsigned long ip;
+  IPAddr ip;
   int subnet_bits;
-  ip = ntohl(rx_message->data.allow_deny.ip);
+  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)) {
+  if (CAM_AddAccessRestriction(&ip, subnet_bits, 1, 1)) {
     tx_message->status = htons(STT_SUCCESS);
   } else {
     tx_message->status = htons(STT_BADSUBNET);
@@ -1039,11 +1160,11 @@ handle_cmdallowall(CMD_Request *rx_message, CMD_Reply *tx_message)
 static void
 handle_cmddeny(CMD_Request *rx_message, CMD_Reply *tx_message)
 {
-  unsigned long ip;
+  IPAddr ip;
   int subnet_bits;
-  ip = ntohl(rx_message->data.allow_deny.ip);
+  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)) {
+  if (CAM_AddAccessRestriction(&ip, subnet_bits, 0, 0)) {
     tx_message->status = htons(STT_SUCCESS);
   } else {
     tx_message->status = htons(STT_BADSUBNET);
@@ -1055,11 +1176,11 @@ handle_cmddeny(CMD_Request *rx_message, CMD_Reply *tx_message)
 static void
 handle_cmddenyall(CMD_Request *rx_message, CMD_Reply *tx_message)
 {
-  unsigned long ip;
+  IPAddr ip;
   int subnet_bits;
-  ip = ntohl(rx_message->data.allow_deny.ip);
+  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)) {
+  if (CAM_AddAccessRestriction(&ip, subnet_bits, 0, 1)) {
     tx_message->status = htons(STT_SUCCESS);
   } else {
     tx_message->status = htons(STT_BADSUBNET);
@@ -1071,9 +1192,9 @@ handle_cmddenyall(CMD_Request *rx_message, CMD_Reply *tx_message)
 static void
 handle_accheck(CMD_Request *rx_message, CMD_Reply *tx_message)
 {
-  unsigned long ip;
-  ip = ntohl(rx_message->data.ac_check.ip);
-  if (NCR_CheckAccessRestriction(ip)) {
+  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);
@@ -1085,9 +1206,9 @@ handle_accheck(CMD_Request *rx_message, CMD_Reply *tx_message)
 static void
 handle_cmdaccheck(CMD_Request *rx_message, CMD_Reply *tx_message)
 {
-  unsigned long ip;
-  ip = ntohl(rx_message->data.ac_check.ip);
-  if (CAM_CheckAccessRestriction(ip)) {
+  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);
@@ -1103,8 +1224,8 @@ handle_add_server(CMD_Request *rx_message, CMD_Reply *tx_message)
   SourceParameters params;
   NSR_Status status;
   
-  rem_addr.ip_addr = ntohl(rx_message->data.ntp_source.ip_addr);
-  rem_addr.local_ip_addr = 0;
+  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);
@@ -1125,6 +1246,9 @@ handle_add_server(CMD_Request *rx_message, CMD_Reply *tx_message)
     case NSR_TooManySources:
       tx_message->status = htons(STT_TOOMANYSOURCES);
       break;
+    case NSR_InvalidAF:
+      tx_message->status = htons(STT_INVALIDAF);
+      break;
     case NSR_NoSuchSource:
       CROAK("Impossible");
       break;
@@ -1140,8 +1264,8 @@ handle_add_peer(CMD_Request *rx_message, CMD_Reply *tx_message)
   SourceParameters params;
   NSR_Status status;
   
-  rem_addr.ip_addr = ntohl(rx_message->data.ntp_source.ip_addr);
-  rem_addr.local_ip_addr = 0;
+  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);
@@ -1161,6 +1285,9 @@ handle_add_peer(CMD_Request *rx_message, CMD_Reply *tx_message)
     case NSR_TooManySources:
       tx_message->status = htons(STT_TOOMANYSOURCES);
       break;
+    case NSR_InvalidAF:
+      tx_message->status = htons(STT_INVALIDAF);
+      break;
     case NSR_NoSuchSource:
       CROAK("Impossible");
       break;
@@ -1175,8 +1302,8 @@ handle_del_source(CMD_Request *rx_message, CMD_Reply *tx_message)
   NTP_Remote_Address rem_addr;
   NSR_Status status;
   
-  rem_addr.ip_addr = ntohl(rx_message->data.del_source.ip_addr);
-  rem_addr.local_ip_addr = 0;
+  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);
@@ -1189,6 +1316,7 @@ handle_del_source(CMD_Request *rx_message, CMD_Reply *tx_message)
       break;
     case NSR_TooManySources:
     case NSR_AlreadyInUse:
+    case NSR_InvalidAF:
       CROAK("Impossible");
       break;
   }
@@ -1273,7 +1401,7 @@ handle_sourcestats(CMD_Request *rx_message, CMD_Reply *tx_message)
   if (status) {
     tx_message->status = htons(STT_SUCCESS);
     tx_message->reply = htons(RPY_SOURCESTATS);
-    tx_message->data.sourcestats.ip_addr = htonl(report.ip_addr);
+    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);
@@ -1345,8 +1473,8 @@ static void
 handle_subnets_accessed(CMD_Request *rx_message, CMD_Reply *tx_message)
 {
   int i, j;
-  unsigned long ns;
-  unsigned long ip, bits_specd;
+  unsigned long ns, bits_specd;
+  IPAddr ip;
   CLG_Status result;
   
   ns = ntohl(rx_message->data.subnets_accessed.n_subnets);
@@ -1355,13 +1483,13 @@ handle_subnets_accessed(CMD_Request *rx_message, CMD_Reply *tx_message)
   tx_message->data.subnets_accessed.n_subnets = htonl(ns);
 
   for (i=0; i<ns; i++) {
-    ip = ntohl(rx_message->data.subnets_accessed.subnets[i].ip);
+    UTI_IPNetworkToHost(&rx_message->data.subnets_accessed.subnets[i].ip, &ip);
     bits_specd = ntohl(rx_message->data.subnets_accessed.subnets[i].bits_specd);
 
-    tx_message->data.subnets_accessed.subnets[i].ip = htonl(ip);
+    UTI_IPHostToNetwork(&ip, &tx_message->data.subnets_accessed.subnets[i].ip);
     tx_message->data.subnets_accessed.subnets[i].bits_specd = htonl(bits_specd);
     
-    result = CLG_GetSubnetBitmap(ip, bits_specd, tx_message->data.subnets_accessed.subnets[i].bitmap);
+    result = CLG_GetSubnetBitmap(&ip, bits_specd, tx_message->data.subnets_accessed.subnets[i].bitmap);
     switch (result) {
       case CLG_SUCCESS:
       case CLG_EMPTYSUBNET:
@@ -1394,7 +1522,7 @@ handle_client_accesses(CMD_Request *rx_message, CMD_Reply *tx_message)
   CLG_Status result;
   RPT_ClientAccess_Report report;
   unsigned long nc;
-  unsigned long ip;
+  IPAddr ip;
   int i;
   struct timeval now;
   double local_time_error;
@@ -1409,10 +1537,10 @@ handle_client_accesses(CMD_Request *rx_message, CMD_Reply *tx_message)
   printf("%d %d\n", (int)sizeof(RPY_ClientAccesses_Client), (int)offsetof(CMD_Reply, data.client_accesses.clients));
 
   for (i=0; i<nc; i++) {
-    ip = ntohl(rx_message->data.client_accesses.client_ips[i]);
-    tx_message->data.client_accesses.clients[i].ip = htonl(ip);
+    UTI_IPNetworkToHost(&rx_message->data.client_accesses.client_ips[i], &ip);
+    UTI_IPHostToNetwork(&ip, &tx_message->data.client_accesses.clients[i].ip);
 
-    result = CLG_GetClientAccessReportByIP(ip, &report, now.tv_sec);
+    result = CLG_GetClientAccessReportByIP(&ip, &report, now.tv_sec);
     switch (result) {
       case CLG_SUCCESS:
         tx_message->data.client_accesses.clients[i].client_hits = htonl(report.client_hits);
@@ -1422,13 +1550,13 @@ handle_client_accesses(CMD_Request *rx_message, CMD_Reply *tx_message)
         tx_message->data.client_accesses.clients[i].cmd_hits_bad = htonl(report.cmd_hits_bad);
         tx_message->data.client_accesses.clients[i].last_ntp_hit_ago = htonl(report.last_ntp_hit_ago);
         tx_message->data.client_accesses.clients[i].last_cmd_hit_ago = htonl(report.last_cmd_hit_ago);
-        printf("%08lx %lu %lu %lu %lu %lu %lu %lu\n", ip, report.client_hits, report.peer_hits, report.cmd_hits_auth, report.cmd_hits_normal, report.cmd_hits_bad, report.last_ntp_hit_ago, report.last_cmd_hit_ago);
+        printf("%s %lu %lu %lu %lu %lu %lu %lu\n", UTI_IPToString(&ip), report.client_hits, report.peer_hits, report.cmd_hits_auth, report.cmd_hits_normal, report.cmd_hits_bad, report.last_ntp_hit_ago, report.last_cmd_hit_ago);
         break;
       case CLG_EMPTYSUBNET:
         /* Signal back to the client that this single client address
-           was unknown, by specifying the zero ip address, which will
-           always be invalid (hopefully) */
-        tx_message->data.client_accesses.clients[i].ip = htonl(0);
+           was unknown */
+        ip.family = IPADDR_UNSPEC;
+        UTI_IPHostToNetwork(&ip, &tx_message->data.client_accesses.clients[i].ip);
         break;
       case CLG_INACTIVE:
         tx_message->status = htons(STT_INACTIVE);
@@ -1471,7 +1599,7 @@ handle_client_accesses_by_index(CMD_Request *rx_message, CMD_Reply *tx_message)
 
     switch (result) {
       case CLG_SUCCESS:
-        tx_message->data.client_accesses_by_index.clients[j].ip = htonl(report.ip_addr);
+        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);
@@ -1594,9 +1722,10 @@ read_from_cmd_socket(void *anything)
   CMD_Request rx_message;
   CMD_Reply tx_message, *prev_tx_message;
   int rx_message_length, tx_message_length;
-  struct sockaddr_in where_from;
+  int sock_fd;
+  union sockaddr_in46 where_from;
   socklen_t from_length;
-  unsigned long remote_ip;
+  IPAddr remote_ip;
   unsigned short remote_port;
   int md5_ok;
   int utoken_ok, token_ok;
@@ -1617,14 +1746,14 @@ read_from_cmd_socket(void *anything)
   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,
-                    (struct sockaddr *)&where_from, &from_length);
+                    &where_from.u, &from_length);
 
   if (status < 0) {
-    LOG(LOGS_WARN, LOGF_CmdMon, "Error [%s] reading from control socket (IP=%s port=%d)",
-        strerror(errno),
-        UTI_IPToDottedQuad(ntohl(where_from.sin_addr.s_addr)),
-        ntohs(where_from.sin_port));
+    LOG(LOGS_WARN, LOGF_CmdMon, "Error [%s] reading from control socket %d",
+        strerror(errno), sock_fd);
+    return;
   }
 
   read_length = status;
@@ -1650,12 +1779,31 @@ read_from_cmd_socket(void *anything)
   tx_message.token = htonl(0xffffffffUL);
   memset(&tx_message.auth, 0, sizeof(tx_message.auth));
 
-  remote_ip = ntohl(where_from.sin_addr.s_addr);
-  remote_port = ntohs(where_from.sin_port);
-
-  localhost = (remote_ip == 0x7f000001UL);
+  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);
+  }
 
-  if ((!ADF_IsAllowed(access_auth_table, remote_ip)) &&
+  if ((!ADF_IsAllowed(access_auth_table, &remote_ip)) &&
       (!localhost)) {
     /* The client is not allowed access, so don't waste any more time
        on him.  Note that localhost is always allowed access
@@ -1667,7 +1815,7 @@ read_from_cmd_socket(void *anything)
        hitting us with bad packets until our log file(s) fill up. */
 
     LOG(LOGS_WARN, LOGF_CmdMon, "Command packet received from unauthorised host %s port %d",
-        UTI_IPToDottedQuad(remote_ip),
+        UTI_IPToString(&remote_ip),
         remote_port);
 
     tx_message.status = htons(STT_NOHOSTACCESS);
@@ -1678,8 +1826,8 @@ read_from_cmd_socket(void *anything)
 
 
   if (read_length != expected_length) {
-    LOG(LOGS_WARN, LOGF_CmdMon, "Read incorrectly sized packet from %s:%hu", UTI_IPToDottedQuad(remote_ip), remote_port);
-    CLG_LogCommandAccess(remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec);
+    LOG(LOGS_WARN, LOGF_CmdMon, "Read incorrectly sized packet from %s:%hu", UTI_IPToString(&remote_ip), remote_port);
+    CLG_LogCommandAccess(&remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec);
     /* For now, just ignore the packet.  We may want to send a reply
        back eventually */
     return;
@@ -1691,7 +1839,7 @@ read_from_cmd_socket(void *anything)
       (rx_message.res2 != 0)) {
 
     /* We don't know how to process anything like this */
-    CLG_LogCommandAccess(remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec);
+    CLG_LogCommandAccess(&remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec);
     
     return;
   }
@@ -1773,7 +1921,7 @@ read_from_cmd_socket(void *anything)
       status = sendto(sock_fd, (void *) prev_tx_message, tx_message_length, 0,
                       (struct sockaddr *) &where_from, sizeof(where_from));
       if (status < 0) {
-        LOG(LOGS_WARN, LOGF_CmdMon, "Could not send response to %s:%hu", UTI_IPToDottedQuad(remote_ip), remote_port);
+        LOG(LOGS_WARN, LOGF_CmdMon, "Could not send response to %s:%hu", UTI_IPToString(&remote_ip), remote_port);
       }
       return;
     }
@@ -1800,9 +1948,9 @@ read_from_cmd_socket(void *anything)
   authenticated = md5_ok & utoken_ok & token_ok;
 
   if (authenticated) {
-    CLG_LogCommandAccess(remote_ip, CLG_CMD_AUTH, cooked_now.tv_sec);
+    CLG_LogCommandAccess(&remote_ip, CLG_CMD_AUTH, cooked_now.tv_sec);
   } else {
-    CLG_LogCommandAccess(remote_ip, CLG_CMD_NORMAL, cooked_now.tv_sec);
+    CLG_LogCommandAccess(&remote_ip, CLG_CMD_NORMAL, cooked_now.tv_sec);
   }
 
   if (issue_token) {
@@ -1895,7 +2043,7 @@ read_from_cmd_socket(void *anything)
           if (!issue_token) {
             LOG(LOGS_WARN, LOGF_CmdMon,
                 "Bad command logon from %s port %d (md5_ok=%d valid_ts=%d)\n",
-                UTI_IPToDottedQuad(remote_ip),
+                UTI_IPToString(&remote_ip),
                 remote_port,
                 md5_ok, valid_ts);
           }
@@ -2092,7 +2240,7 @@ read_from_cmd_socket(void *anything)
 /* ================================================== */
 
 int
-CAM_AddAccessRestriction(unsigned long ip_addr, int subnet_bits, int allow, int all)
+CAM_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all)
  {
   ADF_Status status;
 
@@ -2122,7 +2270,7 @@ CAM_AddAccessRestriction(unsigned long ip_addr, int subnet_bits, int allow, int
 /* ================================================== */
 
 int
-CAM_CheckAccessRestriction(unsigned long ip_addr)
+CAM_CheckAccessRestriction(IPAddr *ip_addr)
 {
   return ADF_IsAllowed(access_auth_table, ip_addr);
 }
index 7dcd539c5e8e93c929e37b362c118e36ce1a01fc..9e634032cb367d799f699d95ddf31d6c6be8d571 100644 (file)
--- a/cmdmon.h
+++ b/cmdmon.h
 #ifndef GOT_CMDMON_H
 #define GOT_CMDMON_H
 
+#include "addressing.h"
+
 extern void CAM_Initialise(void);
 
 extern void CAM_Finalise(void);
 
-extern int CAM_AddAccessRestriction(unsigned long ip_addr, int subnet_bits, int allow, int all);
-extern int CAM_CheckAccessRestriction(unsigned long ip_addr);
+extern int CAM_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all);
+extern int CAM_CheckAccessRestriction(IPAddr *ip_addr);
 
 #endif /* GOT_CMDMON_H */
index e09db45938156a0983032a235764e2c7e7492ed0..609f5ba90185a19bc87da83074b37d5a633b4846 100644 (file)
@@ -61,8 +61,7 @@ CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src)
   
   ok = 0;
   if (sscanf(line, "%" SMAXLEN "s%n", hostname, &n) == 1) {
-    src->ip_addr = DNS_Name2IPAddressRetry(hostname);
-    if (src->ip_addr != DNS_Failed_Address) {
+    if (DNS_Name2IPAddress(hostname, &src->ip_addr, 1)) {
       ok = 1;
     }
   }
index 38cc74cbb74ce17ab955b5b2a36e850c158d1fcd..d9af657d8e98d2f513cb3b23035f77bc757586aa 100644 (file)
@@ -32,6 +32,7 @@
 #define GOT_CMDPARSE_H
 
 #include "srcparams.h"
+#include "addressing.h"
 
 typedef enum {
   CPS_Success,
@@ -47,7 +48,7 @@ typedef enum {
 } CPS_Status;
 
 typedef struct {
-  unsigned long ip_addr;
+  IPAddr ip_addr;
   unsigned short port;
   SourceParameters params;
 } CPS_NTP_Source;
diff --git a/conf.c b/conf.c
index 9bad6a174c9229d8c8d9184735a9e83ddf048421..2135c760d62820d95ca5b168d05f037af8170a0a 100644 (file)
--- a/conf.c
+++ b/conf.c
@@ -53,6 +53,7 @@
 #include "acquire.h"
 #include "cmdparse.h"
 #include "broadcast.h"
+#include "util.h"
 
 /* ================================================== */
 
@@ -136,7 +137,7 @@ static int n_init_srcs;
    than this, slew instead of stepping */
 static int init_slew_threshold = -1;
 #define MAX_INIT_SRCS 8
-static unsigned long init_srcs_ip[MAX_INIT_SRCS];
+static IPAddr init_srcs_ip[MAX_INIT_SRCS];
 
 static int enable_manual=0;
 
@@ -156,13 +157,13 @@ static double mail_change_threshold = 0.0;
    memory */
 static int no_client_log = 0;
 
-/* IP address (host order) for binding the NTP socket to.  0 means INADDR_ANY
+/* IP addresses for binding the NTP socket to.  UNSPEC family means INADDR_ANY
    will be used */
-static unsigned long bind_address = 0UL;
+static IPAddr bind_address4, bind_address6;
 
-/* IP address (host order) for binding the command socket to.  0 means
+/* IP addresses for binding the command socket to.  UNSPEC family means
    use the value of bind_address */
-static unsigned long bind_cmd_address = 0UL;
+static IPAddr bind_cmd_address4, bind_cmd_address6;
 
 /* Filename to use for storing pid of running chronyd, to prevent multiple
  * chronyds being started. */
@@ -243,7 +244,7 @@ typedef enum {
 
 typedef struct {
   NTP_Source_Type type;
-  unsigned long ip_addr;
+  IPAddr ip_addr;
   unsigned short port;
   SourceParameters params;
 } NTP_Source;
@@ -263,7 +264,7 @@ static int n_refclock_sources = 0;
 typedef struct _AllowDeny {
   struct _AllowDeny *next;
   struct _AllowDeny *prev;
-  unsigned long ip;
+  IPAddr ip;
   int subnet_bits;
   int all; /* 1 to override existing more specific defns */
   int allow; /* 0 for deny, 1 for allow */
@@ -697,7 +698,7 @@ parse_initstepslew(const char *line)
   char hostname[HOSTNAME_LEN+1];
   int n;
   int threshold;
-  unsigned long ip_addr;
+  IPAddr ip_addr;
 
   n_init_srcs = 0;
   p = line;
@@ -710,8 +711,7 @@ parse_initstepslew(const char *line)
   }
   while (*p) {
     if (sscanf(p, "%" SHOSTNAME_LEN "s%n", hostname, &n) == 1) {
-      ip_addr = DNS_Name2IPAddressRetry(hostname);
-      if (ip_addr != DNS_Failed_Address) {
+      if (DNS_Name2IPAddress(hostname, &ip_addr, 1)) {
         init_srcs_ip[n_init_srcs] = ip_addr;
         ++n_init_srcs;
       }
@@ -803,7 +803,7 @@ parse_allow_deny(const char *line, AllowDeny *list, int allow)
   unsigned long a, b, c, d, n;
   int all = 0;
   AllowDeny *new_node = NULL;
-  unsigned long ip_addr;
+  IPAddr ip_addr;
 
   p = line;
 
@@ -820,45 +820,54 @@ parse_allow_deny(const char *line, AllowDeny *list, int allow)
     new_node = MallocNew(AllowDeny);
     new_node->allow = allow;
     new_node->all = all;
-    new_node->ip = 0UL;
+    new_node->ip.family = IPADDR_UNSPEC;
     new_node->subnet_bits = 0;
   } else {
     char *slashpos;
     slashpos = strchr(p, '/');
     if (slashpos) *slashpos = 0;
 
-    n = sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d);
-   
-    if (n >= 1) {
+    n = 0;
+    if (UTI_StringToIP(p, &ip_addr) ||
+        (n = sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d)) >= 1) {
       new_node = MallocNew(AllowDeny);
       new_node->allow = allow;
       new_node->all = all;
 
-      a &= 0xff;
-      b &= 0xff;
-      c &= 0xff;
-      d &= 0xff;
-      
-      switch (n) {
-        case 1:
-          new_node->ip = (a<<24);
-          new_node->subnet_bits = 8;
-          break;
-        case 2:
-          new_node->ip = (a<<24) | (b<<16);
-          new_node->subnet_bits = 16;
-          break;
-        case 3:
-          new_node->ip = (a<<24) | (b<<16) | (c<<8);
-          new_node->subnet_bits = 24;
-          break;
-        case 4:
-          new_node->ip = (a<<24) | (b<<16) | (c<<8) | d;
+      if (n == 0) {
+        new_node->ip = ip_addr;
+        if (ip_addr.family == IPADDR_INET6)
+          new_node->subnet_bits = 128;
+        else
           new_node->subnet_bits = 32;
-          break;
-        default:
-          assert(0);
-          
+      } else {
+        new_node->ip.family = IPADDR_INET4;
+
+        a &= 0xff;
+        b &= 0xff;
+        c &= 0xff;
+        d &= 0xff;
+        
+        switch (n) {
+          case 1:
+            new_node->ip.addr.in4 = (a<<24);
+            new_node->subnet_bits = 8;
+            break;
+          case 2:
+            new_node->ip.addr.in4 = (a<<24) | (b<<16);
+            new_node->subnet_bits = 16;
+            break;
+          case 3:
+            new_node->ip.addr.in4 = (a<<24) | (b<<16) | (c<<8);
+            new_node->subnet_bits = 24;
+            break;
+          case 4:
+            new_node->ip.addr.in4 = (a<<24) | (b<<16) | (c<<8) | d;
+            new_node->subnet_bits = 32;
+            break;
+          default:
+            assert(0);
+        }
       }
       
       if (slashpos) {
@@ -872,13 +881,15 @@ parse_allow_deny(const char *line, AllowDeny *list, int allow)
       }
 
     } else {
-      ip_addr = DNS_Name2IPAddressRetry(p);
-      if (ip_addr != DNS_Failed_Address) {
+      if (DNS_Name2IPAddress(p, &ip_addr, 1)) {
         new_node = MallocNew(AllowDeny);
         new_node->allow = allow;
         new_node->all = all;
         new_node->ip = ip_addr;
-        new_node->subnet_bits = 32;
+        if (ip_addr.family == IPADDR_INET6)
+          new_node->subnet_bits = 128;
+        else
+          new_node->subnet_bits = 32;
       } else {
         LOG(LOGS_WARN, LOGF_Configure, "Could not read address at line %d", line_number);
       }      
@@ -931,27 +942,20 @@ parse_cmddeny(const char *line)
 
 /* ================================================== */
 
-static unsigned long
-parse_an_address(const char *line, const char *errmsg)
-{
-  unsigned long a, b, c, d;
-  int n;
-  n = sscanf(line, "%lu.%lu.%lu.%lu", &a, &b, &c, &d);
-  if (n == 4) {
-    return (((a&0xff)<<24) | ((b&0xff)<<16) | 
-            ((c&0xff)<<8) | (d&0xff));
-  } else {
-    LOG(LOGS_WARN, LOGF_Configure, errmsg, line_number);
-    return 0UL;
-  }    
-}
-
-/* ================================================== */
-
 static void
 parse_bindaddress(const char *line)
 {
-  bind_address = parse_an_address(line, "Could not read bind address at line %d\n");
+  IPAddr ip;
+  char addr[51];
+
+  if (sscanf(line, "%50s", addr) == 1 && UTI_StringToIP(addr, &ip)) {
+    if (ip.family == IPADDR_INET4)
+      bind_address4 = ip;
+    else if (ip.family == IPADDR_INET6)
+      bind_address6 = ip;
+  } else {
+    LOG(LOGS_WARN, LOGF_Configure, "Could not read bind address at line %d\n", line_number);
+  }
 }
 
 /* ================================================== */
@@ -959,7 +963,17 @@ parse_bindaddress(const char *line)
 static void
 parse_bindcmdaddress(const char *line)
 {
-  bind_cmd_address = parse_an_address(line, "Could not read bind command address at line %d\n");
+  IPAddr ip;
+  char addr[51];
+
+  if (sscanf(line, "%50s", addr) == 1 && UTI_StringToIP(addr, &ip)) {
+    if (ip.family == IPADDR_INET4)
+      bind_cmd_address4 = ip;
+    else if (ip.family == IPADDR_INET6)
+      bind_cmd_address6 = ip;
+  } else {
+    LOG(LOGS_WARN, LOGF_Configure, "Could not read bind command address at line %d\n", line_number);
+  }
 }
 
 /* ================================================== */
@@ -976,7 +990,7 @@ parse_pidfile(const char *line)
 
 typedef struct {
   /* Both in host (not necessarily network) order */
-  unsigned long addr;
+  IPAddr addr;
   unsigned short port;
   int interval;
 } NTP_Broadcast_Destination;
@@ -992,27 +1006,22 @@ parse_broadcast(const char *line)
 {
   /* Syntax : broadcast <interval> <broadcast-IP-addr> [<port>] */
   int port;
-  unsigned int a, b, c, d;
   int n;
   int interval;
-  unsigned long addr;
+  char addr[51];
+  IPAddr ip;
   
-  n = sscanf(line, "%d %u.%u.%u.%u %d", &interval, &a, &b, &c, &d, &port);
-  if (n < 5) {
+  n = sscanf(line, "%d %50s %d", &interval, addr, &port);
+  if (n < 2 || !UTI_StringToIP(addr, &ip)) {
     LOG(LOGS_WARN, LOGF_Configure, "Could not parse broadcast directive at line %d", line_number);
     return;
-  } else if (n == 5) {
+  } else if (n == 2) {
     /* default port */
     port = 123;
-  } else if (n > 6) {
+  } else if (n > 3) {
     LOG(LOGS_WARN, LOGF_Configure, "Too many fields in broadcast directive at line %d", line_number);
   }
 
-  addr = ((unsigned long) a << 24) |
-         ((unsigned long) b << 16) |
-         ((unsigned long) c <<  8) |
-         ((unsigned long) d      );
-    
   if (max_broadcasts == n_broadcasts) {
     /* Expand array */
     max_broadcasts += 8;
@@ -1023,7 +1032,7 @@ parse_broadcast(const char *line)
     }
   }
 
-  broadcasts[n_broadcasts].addr = addr;
+  broadcasts[n_broadcasts].addr = ip;
   broadcasts[n_broadcasts].port = port;
   broadcasts[n_broadcasts].interval = interval;
   ++n_broadcasts;
@@ -1074,7 +1083,7 @@ CNF_AddSources(void) {
 
   for (i=0; i<n_ntp_sources; i++) {
     server.ip_addr = ntp_sources[i].ip_addr;
-    server.local_ip_addr = 0;
+    memset(&server.local_ip_addr, 0, sizeof (server.local_ip_addr));
     server.port = ntp_sources[i].port;
 
     switch (ntp_sources[i].type) {
@@ -1111,7 +1120,7 @@ CNF_AddBroadcasts(void)
 {
   int i;
   for (i=0; i<n_broadcasts; i++) {
-    BRD_AddDestination(broadcasts[i].addr,
+    BRD_AddDestination(&broadcasts[i].addr,
                        broadcasts[i].port,
                        broadcasts[i].interval);
   }
@@ -1307,14 +1316,14 @@ CNF_SetupAccessRestrictions(void)
   int status;
 
   for (node = ntp_auth_list.next; node != &ntp_auth_list; node = node->next) {
-    status = NCR_AddAccessRestriction(node->ip, node->subnet_bits, node->allow, node->all);
+    status = NCR_AddAccessRestriction(&node->ip, node->subnet_bits, node->allow, node->all);
     if (!status) {
       LOG(LOGS_WARN, LOGF_Configure, "Bad subnet for %08lx", node->ip);
     }
   }
 
   for (node = cmd_auth_list.next; node != &cmd_auth_list; node = node->next) {
-    status = CAM_AddAccessRestriction(node->ip, node->subnet_bits, node->allow, node->all);
+    status = CAM_AddAccessRestriction(&node->ip, node->subnet_bits, node->allow, node->all);
     if (!status) {
       LOG(LOGS_WARN, LOGF_Configure, "Bad subnet for %08lx", node->ip);
     }
@@ -1334,17 +1343,27 @@ CNF_GetNoClientLog(void)
 /* ================================================== */
 
 void
-CNF_GetBindAddress(unsigned long *addr)
+CNF_GetBindAddress(int family, IPAddr *addr)
 {
-  *addr = bind_address;
+  if (family == IPADDR_INET4)
+    *addr = bind_address4;
+  else if (family == IPADDR_INET6)
+    *addr = bind_address6;
+  else
+    addr->family = IPADDR_UNSPEC;
 }
 
 /* ================================================== */
 
 void
-CNF_GetBindCommandAddress(unsigned long *addr)
-{
-  *addr = bind_cmd_address ? bind_cmd_address : bind_address;
+CNF_GetBindCommandAddress(int family, IPAddr *addr)
+{
+  if (family == IPADDR_INET4)
+    *addr = bind_cmd_address4.family != IPADDR_UNSPEC ? bind_cmd_address4 : bind_address4;
+  else if (family == IPADDR_INET6)
+    *addr = bind_cmd_address6.family != IPADDR_UNSPEC ? bind_cmd_address6 : bind_address6;
+  else
+    addr->family = IPADDR_UNSPEC;
 }
 
 /* ================================================== */
diff --git a/conf.h b/conf.h
index d2dd3613ed925a18b83b84ca5cef34872882a364..80e6120dc31d172d53ce1cdd6a53fe22fe06224a 100644 (file)
--- a/conf.h
+++ b/conf.h
@@ -31,6 +31,8 @@
 #ifndef GOT_CONF_H
 #define GOT_CONF_H
 
+#include "addressing.h"
+
 extern char *CNF_GetRtcDevice(void);
 
 extern void CNF_ReadFile(const char *filename);
@@ -60,8 +62,8 @@ extern int CNF_GetRTCOnUTC(void);
 extern void CNF_GetLogChange(int *enabled, double *threshold);
 extern void CNF_GetMailOnChange(int *enabled, double *threshold, char **user);
 extern int CNF_GetNoClientLog(void);
-extern void CNF_GetBindAddress(unsigned long *addr);
-extern void CNF_GetBindCommandAddress(unsigned long *addr);
+extern void CNF_GetBindAddress(int family, IPAddr *addr);
+extern void CNF_GetBindCommandAddress(int family, IPAddr *addr);
 extern char *CNF_GetPidFile(void);
 extern void CNF_GetLinuxHz(int *set, int *hz);
 extern void CNF_GetLinuxFreqScale(int *set, double *freq_scale);
index 3762903ea384d40e40a4cd0cba6a0414d13cbac3..d86efa1c1ffc4df161904129a6a9c4a6f4a867e3 100755 (executable)
--- a/configure
+++ b/configure
@@ -106,6 +106,32 @@ EOF
   echo $result
 }
 #}}}
+#{{{ test_for_ipv6
+test_for_ipv6 () {
+  cat >docheck.c <<EOF;
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+int main(int argc, char **argv) {
+  struct sockaddr_in6 n;
+  char p[100];
+  n.sin6_addr = in6addr_any;
+  return !inet_ntop(AF_INET6, &n.sin6_addr.s6_addr, p, sizeof(p));
+}
+EOF
+
+  ${MYCC} ${MYCFLAGS} -c -o docheck.o docheck.c >/dev/null 2>&1
+  if [ $? -eq 0 ]
+  then
+    result=0
+  else
+    result=1
+  fi
+
+  rm -f docheck.c docheck.o
+  echo $result
+}
+#}}}
 #{{{ usage
 usage () {
   cat <<EOF;
@@ -134,6 +160,7 @@ For better control, use the options below.
   --readline-inc-dir=DIR Specify where readline include directory is
   --readline-lib-dir=DIR Specify where readline lib directory is
   --with-ncurses-library=DIR Specify where ncurses lib directory is
+  --disable-ipv6         Disable IPv6 support
   --disable-rtc          Don't include RTC even on Linux
   --enable-linuxcaps     Enable Linux capabilities support
 
@@ -181,6 +208,7 @@ feat_linuxcaps=0
 readline_lib=""
 readline_inc=""
 ncurses_lib=""
+feat_ipv6=1
 
 SETINFODIR=""
 SETMANDIR=""
@@ -218,6 +246,9 @@ do
     --disable-rtc)
       feat_rtc=0
     ;;
+    --disable-ipv6)
+      feat_ipv6=0
+    ;;
     --enable-linuxcaps)
       feat_linuxcaps=1
     ;;
@@ -339,6 +370,14 @@ else
   printf "No\n"
 fi
 
+printf "Checking for IPv6 support : "
+if [ $feat_ipv6 -eq 1 -a `test_for_ipv6` -eq 0 ]; then
+  printf "Yes\n"
+  SYSDEFS="${SYSDEFS} -DHAVE_IPV6"
+else
+  printf "No\n"
+fi
+
 if [ "x${MYCC}" = "xgcc" ]; then
   CCWARNFLAGS="-Wmissing-prototypes -Wall"
 else
index 9a25254110443745448a297a928f795b61e51097..d5874d6755fbad52671e1e9f76378ce348ccccf2 100644 (file)
 #include "sysincl.h"
 
 #include "nameserv.h"
+#include "util.h"
 #include <resolv.h>
 
 /* ================================================== */
 
+#define MAXRETRIES 10
 static unsigned int retries = 0;
 
-static unsigned long
-Name2IPAddress(const char *name, int retry)
+int 
+DNS_Name2IPAddress(const char *name, IPAddr *addr, int retry)
 {
-  struct hostent *host;
-  unsigned char *address0;
-  unsigned long result;
+#ifdef HAVE_IPV6
+  struct addrinfo hints, *res, *ai;
+  int result;
+  
+  memset(&hints, 0, sizeof (hints));
+  hints.ai_family = AF_UNSPEC;
+  hints.ai_socktype = SOCK_STREAM;
+  hints.ai_flags = AI_ADDRCONFIG;
+
+try_again:
+  result = getaddrinfo(name, NULL, &hints, &res);
 
+  if (result) {
+    if (retry && result == EAI_AGAIN && retries < MAXRETRIES) {
+      sleep(2 << retries);
+      retries++;
+      res_init();
+      goto try_again;
+    }
+    return 0;
+  }
+
+  for (ai = res; !result && ai != NULL; ai = ai->ai_next) {
+    switch (ai->ai_family) {
+      case AF_INET:
+        addr->family = IPADDR_INET4;
+        addr->addr.in4 = ntohl(((struct sockaddr_in *)ai->ai_addr)->sin_addr.s_addr);
+        result = 1;
+        break;
+#ifdef HAVE_IPV6
+      case AF_INET6:
+        addr->family = IPADDR_INET6;
+        memcpy(&addr->addr.in6, &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr.s6_addr, sizeof (addr->addr.in6));
+        result = 1;
+        break;
+#endif
+    }
+  }
+
+  freeaddrinfo(res);
+  return result;
+#else
+  struct hostent *host;
+  char *address0;
+  
 try_again:
   host = gethostbyname(name);
+
   if (host == NULL) {
-    if (retry && h_errno == TRY_AGAIN && retries < 10) {
+    if (retry && h_errno == TRY_AGAIN && retries < MAXRETRIES) {
       sleep(2 << retries);
       retries++;
       res_init();
       goto try_again;
     }
-    result = DNS_Failed_Address;
   } else {
+    addr->family = IPADDR_INET4;
     address0 = host->h_addr_list[0];
-    result = ((((unsigned long)address0[0])<<24) |
-             (((unsigned long)address0[1])<<16) |
-             (((unsigned long)address0[2])<<8) |
-             (((unsigned long)address0[3])));
+    addr->addr.in4 = ((((unsigned long)address0[0])<<24) |
+                     (((unsigned long)address0[1])<<16) |
+                     (((unsigned long)address0[2])<<8) |
+                     (((unsigned long)address0[3])));
+    return 1;
   }
 
-  return result;
-}
-
-/* ================================================== */
-
-unsigned long
-DNS_Name2IPAddress(const char *name)
-{
-  return Name2IPAddress(name, 0);
+  return 0;
+#endif
 }
 
 /* ================================================== */
 
-unsigned long
-DNS_Name2IPAddressRetry(const char *name)
+void
+DNS_IPAddress2Name(IPAddr *ip_addr, char *name, int len)
 {
-  return Name2IPAddress(name, 1);
-}
-
-/* ================================================== */
+#ifdef HAVE_IPV6
+  int result;
+  struct sockaddr_in in4;
+  struct sockaddr_in6 in6;
+
+  switch (ip_addr->family) {
+    case IPADDR_INET4:
+      memset(&in4, 0, sizeof (in4));
+      in4.sin_family = AF_INET;
+      in4.sin_addr.s_addr = htonl(ip_addr->addr.in4);
+      result = getnameinfo((const struct sockaddr *)&in4, sizeof (in4), name, len, NULL, 0, 0);
+      break;
+    case IPADDR_INET6:
+      memset(&in6, 0, sizeof (in6));
+      in6.sin6_family = AF_INET6;
+      memcpy(&in6.sin6_addr.s6_addr, ip_addr->addr.in6, sizeof (in6.sin6_addr.s6_addr));
+      result = getnameinfo((const struct sockaddr *)&in6, sizeof (in6), name, len, NULL, 0, 0);
+      break;
+    default:
+      result = 1;
+  }
 
-const char *
-DNS_IPAddress2Name(unsigned long ip_addr)
-{
+  if (result)
+    snprintf(name, len, "%s", UTI_IPToString(ip_addr));
+#else
   struct hostent *host;
-  static char buffer[16];
-  unsigned int a, b, c, d;
   uint32_t addr;
 
-  addr = htonl(ip_addr);
-  if (addr == 0UL) {
-    /* Catch this as a special case that will never resolve to
-       anything */
-    strcpy(buffer, "0.0.0.0");
-    return buffer;
-  } else {
-    host = gethostbyaddr((const char *) &addr, sizeof(ip_addr), AF_INET);
-    if (!host) {
-      a = (ip_addr >> 24) & 0xff;
-      b = (ip_addr >> 16) & 0xff;
-      c = (ip_addr >>  8) & 0xff;
-      d = (ip_addr)       & 0xff;
-      snprintf(buffer, sizeof(buffer), "%u.%u.%u.%u", a, b, c, d);
-      return buffer;
-    } else {
-      return host->h_name;
-    }
+  switch (ip_addr->family) {
+    case IPADDR_INET4:
+      addr = htonl(ip_addr->addr.in4);
+      host = gethostbyaddr((const char *) &addr, sizeof (ip_addr), AF_INET);
+      break;
+#ifdef HAVE_IPV6
+    case IPADDR_INET6:
+      host = gethostbyaddr((const void *) ip_addr->addr.in6, sizeof (ip_addr->addr.in6), AF_INET6);
+      break;
+#endif
+    default:
+      host = NULL;
   }
+  snprintf(name, len, "%s", host ? host->h_name : UTI_IPToString(ip_addr));
+#endif
 }
 
 /* ================================================== */
index 69ceef8ea4507a0671124f83886f0059f858eaac..1451b9bf48362811df6b62951425de086ebf4006 100644 (file)
 #ifndef GOT_NAMESERV_H
 #define GOT_NAMESERV_H
 
-static const unsigned long DNS_Failed_Address = 0x0UL;
+#include "addressing.h"
 
-extern unsigned long DNS_Name2IPAddress(const char *name);
+extern int DNS_Name2IPAddress(const char *name, IPAddr *addr, int retry);
 
-extern unsigned long DNS_Name2IPAddressRetry(const char *name);
-
-const char *DNS_IPAddress2Name(unsigned long ip_addr);
+extern void DNS_IPAddress2Name(IPAddr *ip_addr, char *name, int len);
 
 #endif /* GOT_NAMESERV_H */
 
index 4f0eb4164833d04e74a595e80105e4bb859b3336..daee104d204f7a5d5f49b96ee8a44806df5a4d68 100644 (file)
@@ -319,7 +319,7 @@ create_instance(NTP_Remote_Address *remote_addr, NTP_Mode mode, SourceParameters
   result->local_poll = params->minpoll;
 
   /* Create a source instance for this NTP source */
-  result->source = SRC_CreateNewInstance(remote_addr->ip_addr, SRC_NTP);
+  result->source = SRC_CreateNewInstance(UTI_IPToRefid(&remote_addr->ip_addr), SRC_NTP, &result->remote_addr.ip_addr);
 
   result->local_rx.tv_sec = 0;
   result->local_rx.tv_usec = 0;
@@ -626,7 +626,7 @@ transmit_timeout(void *arg)
 
 #ifdef TRACEON
   LOG(LOGS_INFO, LOGF_NtpCore, "Transmit timeout for [%s:%d]",
-      UTI_IPToDottedQuad(inst->remote_addr.ip_addr), inst->remote_addr.port);
+      UTI_IPToString(&inst->remote_addr.ip_addr), inst->remote_addr.port);
 #endif
 
   /* Check whether we need to 'warm up' the link to the other end by
@@ -1043,8 +1043,8 @@ receive_packet(NTP_Packet *message, struct timeval *now, NCR_Instance inst, int
       message->lvm, message->stratum, message->poll, message->precision);
   LOG(LOGS_INFO, LOGF_NtpCore, "Root delay=%08lx (%f), dispersion=%08lx (%f)",
       message->root_delay, pkt_root_delay, message->root_dispersion, pkt_root_dispersion);
-  LOG(LOGS_INFO, LOGF_NtpCore, "Ref id=[%s], ref_time=%08lx.%08lx [%s]",
-      UTI_IPToDottedQuad(ntohl(message->reference_id)),
+  LOG(LOGS_INFO, LOGF_NtpCore, "Ref id=[%lx], ref_time=%08lx.%08lx [%s]",
+      ntohl(message->reference_id),
       message->reference_ts.hi, message->reference_ts.lo,
       UTI_TimestampToString(&message->reference_ts));
   LOG(LOGS_INFO, LOGF_NtpCore, "Originate=%08lx.%08lx [%s]",
@@ -1243,7 +1243,7 @@ receive_packet(NTP_Packet *message, struct timeval *now, NCR_Instance inst, int
         inst->maxpoll = inst->minpoll;
       if (inst->minpoll > inst->local_poll)
         inst->local_poll = inst->minpoll;
-      LOG(LOGS_INFO, LOGF_NtpCore, "Received KoD RATE from %s, minpoll set to %d", UTI_IPToDottedQuad(inst->remote_addr.ip_addr), inst->minpoll);
+      LOG(LOGS_INFO, LOGF_NtpCore, "Received KoD RATE from %s, minpoll set to %d", UTI_IPToString(&inst->remote_addr.ip_addr), inst->minpoll);
     }
     /* Back off for a while */
     delay_time += (double) (4 * (1UL << inst->minpoll));
@@ -1268,7 +1268,7 @@ receive_packet(NTP_Packet *message, struct timeval *now, NCR_Instance inst, int
 
     fprintf(logfile, "%s %-15s %1c %2d %1d%1d%1d%1d %1d%1d %1d%1d%1d%1d %2d %2d %2d %10.3e %10.3e %10.3e %10.3e %10.3e\n",
             UTI_TimeToLogForm(sample_time.tv_sec),
-            UTI_IPToDottedQuad(inst->remote_addr.ip_addr),
+            UTI_IPToString(&inst->remote_addr.ip_addr),
             sync_stats[pkt_leap],
             message->stratum,
             test1, test2, test3, test4,
@@ -1357,9 +1357,9 @@ process_known
          one of the secondaries to flywheel it. The behaviour coded here
          is required in the secondaries to make this possible. */
 
-      if (ADF_IsAllowed(access_auth_table, inst->remote_addr.ip_addr)) {
+      if (ADF_IsAllowed(access_auth_table, &inst->remote_addr.ip_addr)) {
 
-        CLG_LogNTPClientAccess(inst->remote_addr.ip_addr, (time_t) now->tv_sec);
+        CLG_LogNTPClientAccess(&inst->remote_addr.ip_addr, (time_t) now->tv_sec);
 
         if (do_auth) {
           auth_key_id = ntohl(message->auth_keyid);
@@ -1392,7 +1392,7 @@ process_known
 
       } else {
         LOG(LOGS_WARN, LOGF_NtpCore, "NTP packet received from unauthorised host %s port %d",
-            UTI_IPToDottedQuad(inst->remote_addr.ip_addr),
+            UTI_IPToString(&inst->remote_addr.ip_addr),
             inst->remote_addr.port);
       }
 
@@ -1403,7 +1403,7 @@ process_known
       switch(inst->mode) {
         case MODE_ACTIVE:
           /* Ordinary symmetric peering */
-          CLG_LogNTPPeerAccess(inst->remote_addr.ip_addr, (time_t) now->tv_sec);
+          CLG_LogNTPPeerAccess(&inst->remote_addr.ip_addr, (time_t) now->tv_sec);
           receive_packet(message, now, inst, do_auth);
           break;
         case MODE_PASSIVE:
@@ -1413,7 +1413,7 @@ process_known
         case MODE_CLIENT:
           /* This is where we have the remote configured as a server and he has
              us configured as a peer - fair enough. */
-          CLG_LogNTPPeerAccess(inst->remote_addr.ip_addr, (time_t) now->tv_sec);
+          CLG_LogNTPPeerAccess(&inst->remote_addr.ip_addr, (time_t) now->tv_sec);
           receive_packet(message, now, inst, do_auth);
           break;
         case MODE_SERVER:
@@ -1434,7 +1434,7 @@ process_known
       switch(inst->mode) {
         case MODE_ACTIVE:
           /* Slightly bizarre combination, but we can still process it */
-          CLG_LogNTPPeerAccess(inst->remote_addr.ip_addr, (time_t) now->tv_sec);
+          CLG_LogNTPPeerAccess(&inst->remote_addr.ip_addr, (time_t) now->tv_sec);
           receive_packet(message, now, inst, do_auth);
           break;
         case MODE_PASSIVE:
@@ -1462,7 +1462,7 @@ process_known
         case MODE_ACTIVE:
           /* This would arise if we have the remote configured as a peer and
              he does not have us configured */
-          CLG_LogNTPPeerAccess(inst->remote_addr.ip_addr, (time_t) now->tv_sec);
+          CLG_LogNTPPeerAccess(&inst->remote_addr.ip_addr, (time_t) now->tv_sec);
           receive_packet(message, now, inst, do_auth);
           break;
         case MODE_PASSIVE:
@@ -1524,19 +1524,19 @@ NCR_ProcessNoauthUnknown(NTP_Packet *message, struct timeval *now, NTP_Remote_Ad
   NTP_Mode my_mode;
   int my_poll;
 
-  if (ADF_IsAllowed(access_auth_table, remote_addr->ip_addr)) {
+  if (ADF_IsAllowed(access_auth_table, &remote_addr->ip_addr)) {
 
     his_mode = message->lvm & 0x07;
 
     if (his_mode == MODE_CLIENT) {
       /* We are server */
       my_mode = MODE_SERVER;
-      CLG_LogNTPClientAccess(remote_addr->ip_addr, (time_t) now->tv_sec);
+      CLG_LogNTPClientAccess(&remote_addr->ip_addr, (time_t) now->tv_sec);
 
     } else if (his_mode == MODE_ACTIVE) {
       /* We are symmetric passive, even though we don't ever lock to him */
       my_mode = MODE_PASSIVE;
-      CLG_LogNTPPeerAccess(remote_addr->ip_addr, (time_t) now->tv_sec);
+      CLG_LogNTPPeerAccess(&remote_addr->ip_addr, (time_t) now->tv_sec);
 
     } else {
       my_mode = MODE_UNDEFINED;
@@ -1560,7 +1560,7 @@ NCR_ProcessNoauthUnknown(NTP_Packet *message, struct timeval *now, NTP_Remote_Ad
     }
   } else {
     LOG(LOGS_WARN, LOGF_NtpCore, "NTP packet received from unauthorised host %s port %d",
-        UTI_IPToDottedQuad(remote_addr->ip_addr),
+        UTI_IPToString(&remote_addr->ip_addr),
         remote_addr->port);
   }
 
@@ -1594,19 +1594,19 @@ NCR_ProcessAuthUnknown(NTP_Packet *message, struct timeval *now, NTP_Remote_Addr
   int valid_key, valid_auth;
   unsigned long key_id;
 
-  if (ADF_IsAllowed(access_auth_table, remote_addr->ip_addr)) {
+  if (ADF_IsAllowed(access_auth_table, &remote_addr->ip_addr)) {
 
     his_mode = message->lvm & 0x07;
     
     if (his_mode == MODE_CLIENT) {
       /* We are server */
       my_mode = MODE_SERVER;
-      CLG_LogNTPClientAccess(remote_addr->ip_addr, (time_t) now->tv_sec);
+      CLG_LogNTPClientAccess(&remote_addr->ip_addr, (time_t) now->tv_sec);
 
     } else if (his_mode == MODE_ACTIVE) {
       /* We are symmetric passive, even though we don't ever lock to him */
       my_mode = MODE_PASSIVE;
-      CLG_LogNTPPeerAccess(remote_addr->ip_addr, (time_t) now->tv_sec);
+      CLG_LogNTPPeerAccess(&remote_addr->ip_addr, (time_t) now->tv_sec);
 
     } else {
       my_mode = MODE_UNDEFINED;
@@ -1678,7 +1678,7 @@ NCR_TakeSourceOnline(NCR_Instance inst)
     case MD_OFFLINE:
       if (!inst->timer_running) {
         /* We are not already actively polling it */
-        LOG(LOGS_INFO, LOGF_NtpCore, "Source %s online", UTI_IPToDottedQuad(inst->remote_addr.ip_addr));
+        LOG(LOGS_INFO, LOGF_NtpCore, "Source %s online", UTI_IPToString(&inst->remote_addr.ip_addr));
         inst->local_poll = inst->minpoll;
         inst->score = (ZONE_WIDTH >> 1);
         inst->opmode = MD_ONLINE;
@@ -1702,7 +1702,7 @@ NCR_TakeSourceOffline(NCR_Instance inst)
   switch (inst->opmode) {
     case MD_ONLINE:
       if (inst->timer_running) {
-        LOG(LOGS_INFO, LOGF_NtpCore, "Source %s offline", UTI_IPToDottedQuad(inst->remote_addr.ip_addr));
+        LOG(LOGS_INFO, LOGF_NtpCore, "Source %s offline", UTI_IPToString(&inst->remote_addr.ip_addr));
         SCH_RemoveTimeout(inst->timeout_id);
         inst->timer_running = 0;
         inst->opmode = MD_OFFLINE;
@@ -1725,7 +1725,7 @@ void
 NCR_ModifyMinpoll(NCR_Instance inst, int new_minpoll)
 {
   inst->minpoll = new_minpoll;
-  LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new minpoll %d", UTI_IPToDottedQuad(inst->remote_addr.ip_addr), new_minpoll);
+  LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new minpoll %d", UTI_IPToString(&inst->remote_addr.ip_addr), new_minpoll);
 }
 
 /* ================================================== */
@@ -1734,7 +1734,7 @@ void
 NCR_ModifyMaxpoll(NCR_Instance inst, int new_maxpoll)
 {
   inst->maxpoll = new_maxpoll;
-  LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new maxpoll %d", UTI_IPToDottedQuad(inst->remote_addr.ip_addr), new_maxpoll);
+  LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new maxpoll %d", UTI_IPToString(&inst->remote_addr.ip_addr), new_maxpoll);
 }
 
 /* ================================================== */
@@ -1744,7 +1744,7 @@ NCR_ModifyMaxdelay(NCR_Instance inst, double new_max_delay)
 {
   inst->max_delay = new_max_delay;
   LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new max delay %f",
-      UTI_IPToDottedQuad(inst->remote_addr.ip_addr), new_max_delay);
+      UTI_IPToString(&inst->remote_addr.ip_addr), new_max_delay);
 }
 
 /* ================================================== */
@@ -1754,7 +1754,7 @@ NCR_ModifyMaxdelayratio(NCR_Instance inst, double new_max_delay_ratio)
 {
   inst->max_delay_ratio = new_max_delay_ratio;
   LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new max delay ratio %f",
-      UTI_IPToDottedQuad(inst->remote_addr.ip_addr), new_max_delay_ratio);
+      UTI_IPToString(&inst->remote_addr.ip_addr), new_max_delay_ratio);
 }
 
 /* ================================================== */
@@ -1836,7 +1836,7 @@ NCR_ReportSource(NCR_Instance inst, RPT_SourceReport *report, struct timeval *no
 /* ================================================== */
 
 int
-NCR_AddAccessRestriction(unsigned long ip_addr, int subnet_bits, int allow, int all)
+NCR_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all)
  {
   ADF_Status status;
 
@@ -1866,7 +1866,7 @@ NCR_AddAccessRestriction(unsigned long ip_addr, int subnet_bits, int allow, int
 /* ================================================== */
 
 int
-NCR_CheckAccessRestriction(unsigned long ip_addr)
+NCR_CheckAccessRestriction(IPAddr *ip_addr)
 {
   return ADF_IsAllowed(access_auth_table, ip_addr);
 }
index 84b21d9391bf5798fab5fc0be1dbc3bc10d71053..86926c499f45614522c7b79231deb3d6e947189b 100644 (file)
@@ -94,8 +94,8 @@ extern void NCR_InitiateSampleBurst(NCR_Instance inst, int n_good_samples, int n
 
 extern void NCR_ReportSource(NCR_Instance inst, RPT_SourceReport *report, struct timeval *now);
 
-extern int NCR_AddAccessRestriction(unsigned long ip_addr, int subnet_bits, int allow, int all);
-extern int NCR_CheckAccessRestriction(unsigned long ip_addr);
+extern int NCR_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all);
+extern int NCR_CheckAccessRestriction(IPAddr *ip_addr);
 
 extern void NCR_CycleLogFile(void);
 
index d67310588ba8d2fc69a0ef41d10391abdec3a6fc..7d4f88098b581b27c869bc253882700f00d0ea5e 100644 (file)
--- a/ntp_io.c
+++ b/ntp_io.c
 
 #include <fcntl.h>
 
-/* The file descriptor for the socket */
-static int sock_fd;
+union sockaddr_in46 {
+  struct sockaddr_in in4;
+#ifdef HAVE_IPV6
+  struct sockaddr_in6 in6;
+#endif
+  struct sockaddr u;
+};
+
+/* The file descriptors for the IPv4 and IPv6 sockets */
+static int sock_fd4;
+#ifdef HAVE_IPV6
+static int sock_fd6;
+#endif
 
 /* Flag indicating that we have been initialised */
 static int initialised=0;
@@ -50,6 +61,7 @@ static int initialised=0;
 /* ================================================== */
 
 /* Forward prototypes */
+static int prepare_socket(int family);
 static void read_from_socket(void *anything);
 
 /* ================================================== */
@@ -81,30 +93,28 @@ do_size_checks(void)
 
 /* ================================================== */
 
-void
-NIO_Initialise(void)
+static int
+prepare_socket(int family)
 {
-  struct sockaddr_in my_addr;
+  union sockaddr_in46 my_addr;
+  int sock_fd;
   unsigned short port_number;
-  unsigned long bind_address;
+  IPAddr bind_address;
   int on_off = 1;
   
-  assert(!initialised);
-  initialised = 1;
-
-  do_size_checks();
-
   port_number = CNF_GetNTPPort();
 
   /* Open Internet domain UDP socket for NTP message transmissions */
 
 #if 0
-  sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+  sock_fd = socket(family, SOCK_DGRAM, IPPROTO_UDP);
 #else
-  sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
+  sock_fd = socket(family, SOCK_DGRAM, 0);
 #endif 
+
   if (sock_fd < 0) {
-    LOG_FATAL(LOGF_NtpIO, "Could not open socket : %s", strerror(errno));
+    LOG(LOGS_ERR, LOGF_NtpIO, "Could not open socket : %s", strerror(errno));
+    return -1;
   }
 
   /* Make the socket capable of re-using an old address */
@@ -125,34 +135,67 @@ NIO_Initialise(void)
     /* Don't quit - we might survive anyway */
   }
 
-  /* We want the local IP info too */
-  if (setsockopt(sock_fd, IPPROTO_IP, IP_PKTINFO, (char *)&on_off, sizeof(on_off)) < 0) {
-    LOG(LOGS_ERR, LOGF_NtpIO, "Could not request packet info using socket option");
-    /* Don't quit - we might survive anyway */
+  if (family == AF_INET) {
+    /* We want the local IP info too */
+    if (setsockopt(sock_fd, IPPROTO_IP, IP_PKTINFO, (char *)&on_off, sizeof(on_off)) < 0) {
+      LOG(LOGS_ERR, LOGF_NtpIO, "Could not request packet info using socket option");
+      /* Don't quit - we might survive anyway */
+    }
+  }
+#ifdef HAVE_IPV6
+  else 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_NtpIO, "Could not request IPV6_V6ONLY socket option");
+    }
+#endif
   }
+#endif
 
   /* Bind the port */
-  my_addr.sin_family = AF_INET;
-  my_addr.sin_port = htons(port_number);
-
-  CNF_GetBindAddress(&bind_address);
-
-  if (bind_address != 0UL) {
-    my_addr.sin_addr.s_addr = htonl(bind_address);
-  } else {
-    my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+  memset(&my_addr, 0, sizeof (my_addr));
+
+  switch (family) {
+    case AF_INET:
+      my_addr.in4.sin_family = family;
+      my_addr.in4.sin_port = htons(port_number);
+
+      CNF_GetBindAddress(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.in6.sin6_family = family;
+      my_addr.in6.sin6_port = htons(port_number);
+
+      CNF_GetBindAddress(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 0
   LOG(LOGS_INFO, LOGF_NtpIO, "Initialising, socket fd=%d", sock_fd);
 #endif
 
-  if (bind(sock_fd, (struct sockaddr *) &my_addr, sizeof(my_addr)) < 0) {
+  if (bind(sock_fd, &my_addr.u, sizeof(my_addr)) < 0) {
     LOG_FATAL(LOGF_NtpIO, "Could not bind socket : %s", strerror(errno));
   }
 
   /* Register handler for read events on the socket */
-  SCH_AddInputFileHandler(sock_fd, read_from_socket, NULL);
+  SCH_AddInputFileHandler(sock_fd, read_from_socket, (void *)(long)sock_fd);
 
 #if 0
   if (fcntl(sock_fd, F_SETFL, O_NONBLOCK | O_NDELAY) < 0) {
@@ -163,6 +206,29 @@ NIO_Initialise(void)
     LOG(LOGS_ERR, LOGF_NtpIO, "Could not enable signal");
   }
 #endif
+  return sock_fd;
+}
+
+void
+NIO_Initialise(void)
+{
+  assert(!initialised);
+  initialised = 1;
+
+  do_size_checks();
+
+  sock_fd4 = prepare_socket(AF_INET);
+#ifdef HAVE_IPV6
+  sock_fd6 = prepare_socket(AF_INET6);
+#endif
+
+  if (sock_fd4 < 0
+#ifdef HAVE_IPV6
+      && sock_fd6 < 0
+#endif
+      ) {
+    LOG_FATAL(LOGF_NtpIO, "Could not open any NTP socket");
+  }
 
   return;
 }
@@ -172,11 +238,18 @@ NIO_Initialise(void)
 void
 NIO_Finalise(void)
 {
-  if (sock_fd >= 0) {
-    SCH_RemoveInputFileHandler(sock_fd);
-    close(sock_fd);
+  if (sock_fd4 >= 0) {
+    SCH_RemoveInputFileHandler(sock_fd4);
+    close(sock_fd4);
   }
-  sock_fd = -1;
+  sock_fd4 = -1;
+#ifdef HAVE_IPV6
+  if (sock_fd6 >= 0) {
+    SCH_RemoveInputFileHandler(sock_fd6);
+    close(sock_fd6);
+  }
+  sock_fd6 = -1;
+#endif
   initialised = 0;
   return;
 }
@@ -192,9 +265,9 @@ read_from_socket(void *anything)
   /* This should only be called when there is something
      to read, otherwise it will block. */
 
-  int status;
+  int status, sock_fd;
   ReceiveBuffer message;
-  struct sockaddr_in where_from;
+  union sockaddr_in46 where_from;
   unsigned int flags = 0;
   struct timeval now;
   NTP_Remote_Address remote_addr;
@@ -218,6 +291,7 @@ read_from_socket(void *anything)
   msg.msg_controllen = sizeof(cmsgbuf);
   msg.msg_flags = 0;
 
+  sock_fd = (long)anything;
   status = recvmsg(sock_fd, &msg, flags);
 
   /* Don't bother checking if read failed or why if it did.  More
@@ -228,16 +302,33 @@ read_from_socket(void *anything)
      reponse on a subsequent recvfrom). */
 
   if (status > 0) {
-    remote_addr.ip_addr = ntohl(where_from.sin_addr.s_addr);
-    remote_addr.local_ip_addr = 0;
-    remote_addr.port = ntohs(where_from.sin_port);
+    memset(&remote_addr, 0, sizeof (remote_addr));
+
+    switch (where_from.u.sa_family) {
+      case AF_INET:
+        remote_addr.ip_addr.family = IPADDR_INET4;
+        remote_addr.ip_addr.addr.in4 = ntohl(where_from.in4.sin_addr.s_addr);
+        remote_addr.port = ntohs(where_from.in4.sin_port);
+        break;
+#ifdef HAVE_IPV6
+      case AF_INET6:
+        remote_addr.ip_addr.family = IPADDR_INET6;
+        memcpy(&remote_addr.ip_addr.addr.in6, where_from.in6.sin6_addr.s6_addr,
+            sizeof (remote_addr.ip_addr.addr.in6));
+        remote_addr.port = ntohs(where_from.in6.sin6_port);
+        break;
+#endif
+      default:
+        assert(0);
+    }
 
     for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
       if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) {
         struct in_pktinfo ipi;
 
         memcpy(&ipi, CMSG_DATA(cmsg), sizeof(ipi));
-        remote_addr.local_ip_addr = ntohl(ipi.ipi_spec_dst.s_addr);
+        remote_addr.local_ip_addr.addr.in4 = ntohl(ipi.ipi_spec_dst.s_addr);
+        remote_addr.local_ip_addr.family = IPADDR_INET4;
       }
 
       if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_TIMESTAMP) {
@@ -279,22 +370,43 @@ read_from_socket(void *anything)
 static void
 send_packet(void *packet, int packetlen, NTP_Remote_Address *remote_addr)
 {
-  struct sockaddr_in remote;
+  union sockaddr_in46 remote;
   struct msghdr msg;
   struct iovec iov;
   struct cmsghdr *cmsg;
   char cmsgbuf[256];
   int cmsglen;
+  int sock_fd;
 
   assert(initialised);
 
-  remote.sin_family = AF_INET;
-  remote.sin_port = htons(remote_addr->port);
-  remote.sin_addr.s_addr = htonl(remote_addr->ip_addr);
+  memset(&remote, 0, sizeof (remote));
+  switch (remote_addr->ip_addr.family) {
+    case IPADDR_INET4:
+      remote.in4.sin_family = AF_INET;
+      remote.in4.sin_port = htons(remote_addr->port);
+      remote.in4.sin_addr.s_addr = htonl(remote_addr->ip_addr.addr.in4);
+      sock_fd = sock_fd4;
+      break;
+#ifdef HAVE_IPV6
+    case IPADDR_INET6:
+      remote.in6.sin6_family = AF_INET6;
+      remote.in6.sin6_port = htons(remote_addr->port);
+      memcpy(&remote.in6.sin6_addr.s6_addr, &remote_addr->ip_addr.addr.in6,
+          sizeof (remote.in6.sin6_addr.s6_addr));
+      sock_fd = sock_fd6;
+      break;
+#endif
+    default:
+      return;
+  }
+
+  if (sock_fd < 0)
+    return;
 
   iov.iov_base = packet;
   iov.iov_len = packetlen;
-  msg.msg_name = &remote;
+  msg.msg_name = &remote.u;
   msg.msg_namelen = sizeof(remote);
   msg.msg_iov = &iov;
   msg.msg_iovlen = 1;
@@ -303,7 +415,7 @@ send_packet(void *packet, int packetlen, NTP_Remote_Address *remote_addr)
   msg.msg_flags = 0;
   cmsglen = 0;
 
-  if (remote_addr->local_ip_addr) {
+  if (remote_addr->local_ip_addr.family == IPADDR_INET4) {
     struct in_pktinfo *ipi;
 
     cmsg = CMSG_FIRSTHDR(&msg);
@@ -315,10 +427,10 @@ send_packet(void *packet, int packetlen, NTP_Remote_Address *remote_addr)
     cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
 
     ipi = (struct in_pktinfo *) CMSG_DATA(cmsg);
-    ipi->ipi_spec_dst.s_addr = htonl(remote_addr->local_ip_addr);
+    ipi->ipi_spec_dst.s_addr = htonl(remote_addr->local_ip_addr.addr.in4);
 #if 0
     LOG(LOGS_INFO, LOGF_NtpIO, "sending to %s:%d from %s",
-        UTI_IPToDottedQuad(remote_addr->ip_addr), remote_addr->port, UTI_IPToDottedQuad(remote_addr->local_ip_addr));
+        UTI_IPToString(&remote_addr->ip_addr), remote_addr->port, UTI_IPToString(&remote_addr->local_ip_addr));
 #endif
   }
 
@@ -326,7 +438,7 @@ send_packet(void *packet, int packetlen, NTP_Remote_Address *remote_addr)
 
   if (sendmsg(sock_fd, &msg, 0) < 0) {
     LOG(LOGS_WARN, LOGF_NtpIO, "Could not send to %s:%d : %s",
-        UTI_IPToDottedQuad(remote_addr->ip_addr), remote_addr->port, strerror(errno));
+        UTI_IPToString(&remote_addr->ip_addr), remote_addr->port, strerror(errno));
   }
 
   return;
index d47573ba6ef7cb82e90da19405b50c98f6bed50c..7d4c5ba86b46a324a89d2974720f488b0d5eba82 100644 (file)
@@ -120,17 +120,36 @@ static void
 find_slot(NTP_Remote_Address *remote_addr, int *slot, int *found)
 {
   unsigned long hash;
-  unsigned long ip = remote_addr->ip_addr;
-  unsigned short port = remote_addr->port;
+  unsigned long ip;
+  unsigned short port;
+  uint8_t *ip6;
 
   assert(N_RECORDS == 256);
   
+  switch (remote_addr->ip_addr.family) {
+    case IPADDR_INET6:
+      ip6 = remote_addr->ip_addr.addr.in6;
+      ip = (ip6[0] ^ ip6[4] ^ ip6[8] ^ ip6[12]) |
+           (ip6[1] ^ ip6[5] ^ ip6[9] ^ ip6[13]) << 8 |
+           (ip6[2] ^ ip6[6] ^ ip6[10] ^ ip6[14]) << 16 |
+           (ip6[3] ^ ip6[7] ^ ip6[11] ^ ip6[15]) << 24;
+      break;
+    case IPADDR_INET4:
+      ip = remote_addr->ip_addr.addr.in4;
+      break;
+    default:
+      *found = *slot = 0;
+      return;
+  }
+
+  port = remote_addr->port;
   /* Compute hash value just by xor'ing the 4 bytes of the address together */
   hash = ip ^ (ip >> 16);
   hash = (hash ^ (hash >> 8)) & 0xff;
 
   while ((records[hash].in_use) &&
-         (records[hash].remote_addr.ip_addr != ip)) {
+         UTI_CompareIPs(&records[hash].remote_addr.ip_addr,
+           &remote_addr->ip_addr, NULL)) {
     hash++;
     if (hash == 256) hash = 0;
   }
@@ -162,7 +181,7 @@ NSR_AddServer(NTP_Remote_Address *remote_addr, SourceParameters *params)
   assert(initialised);
 
 #if 0
-  LOG(LOGS_INFO, LOGF_NtpSources, "IP=%08lx port=%d", (unsigned long)remote_addr->ip_addr, remote_addr->port);
+  LOG(LOGS_INFO, LOGF_NtpSources, "IP=%s port=%d", UTI_IPToString(&remote_addr->ip_addr), remote_addr->port);
 #endif
 
   /* Find empty bin & check that we don't have the address already */
@@ -172,6 +191,9 @@ NSR_AddServer(NTP_Remote_Address *remote_addr, SourceParameters *params)
   } else {
     if (n_sources == MAX_SOURCES) {
       return NSR_TooManySources;
+    } else if (remote_addr->ip_addr.family != IPADDR_INET4 &&
+               remote_addr->ip_addr.family != IPADDR_INET6) {
+      return NSR_InvalidAF;
     } else {
       n_sources++;
       records[slot].remote_addr = *remote_addr;
@@ -193,7 +215,7 @@ NSR_AddPeer(NTP_Remote_Address *remote_addr, SourceParameters *params)
   assert(initialised);
 
 #if 0
-  LOG(LOGS_INFO, LOGF_NtpSources, "IP=%08lx port=%d", (unsigned long) remote_addr->ip_addr, remote_addr->port);
+  LOG(LOGS_INFO, LOGF_NtpSources, "IP=%s port=%d", UTI_IPToString(&remote_addr->ip_addr), remote_addr->port);
 #endif
 
   /* Find empty bin & check that we don't have the address already */
@@ -203,6 +225,9 @@ NSR_AddPeer(NTP_Remote_Address *remote_addr, SourceParameters *params)
   } else {
     if (n_sources == MAX_SOURCES) {
       return NSR_TooManySources;
+    } else if (remote_addr->ip_addr.family != IPADDR_INET4 &&
+               remote_addr->ip_addr.family != IPADDR_INET6) {
+      return NSR_InvalidAF;
     } else {
       n_sources++;
       records[slot].remote_addr = *remote_addr;
@@ -249,7 +274,7 @@ NSR_ProcessReceive(NTP_Packet *message, struct timeval *now, NTP_Remote_Address
 
 #if 0
   LOG(LOGS_INFO, LOGF_NtpSources, "from (%s,%d) at %s",
-      UTI_IPToDottedQuad(remote_addr->ip_addr),
+      UTI_IPToString(&remote_addr->ip_addr),
       remote_addr->port, UTI_TimevalToString(now));
 #endif
   
@@ -296,7 +321,7 @@ slew_sources(struct timeval *raw,
     if (records[i].in_use) {
 #if 0
       LOG(LOGS_INFO, LOGF_Sources, "IP=%s dfreq=%f doff=%f",
-          UTI_IPToDottedQuad(records[i].remote_addr.ip_addr), dfreq, doffset);
+          UTI_IPToString(&records[i].remote_addr.ip_addr), dfreq, doffset);
 #endif
 
       NCR_SlewTimes(records[i].data, cooked, dfreq, doffset);
@@ -308,17 +333,16 @@ slew_sources(struct timeval *raw,
 /* ================================================== */
 
 int
-NSR_TakeSourcesOnline(unsigned long mask, unsigned long address)
+NSR_TakeSourcesOnline(IPAddr *mask, IPAddr *address)
 {
   int i;
   int any;
-  unsigned long ip;
 
   any = 0;
   for (i=0; i<N_RECORDS; i++) {
     if (records[i].in_use) {
-      ip = records[i].remote_addr.ip_addr;
-      if ((ip & mask) == address) {
+      if (address->family == IPADDR_UNSPEC ||
+          !UTI_CompareIPs(&records[i].remote_addr.ip_addr, address, mask)) {
         any = 1;
         NCR_TakeSourceOnline(records[i].data);
       }
@@ -331,17 +355,16 @@ NSR_TakeSourcesOnline(unsigned long mask, unsigned long address)
 /* ================================================== */
 
 int
-NSR_TakeSourcesOffline(unsigned long mask, unsigned long address)
+NSR_TakeSourcesOffline(IPAddr *mask, IPAddr *address)
 {
   int i;
   int any;
-  unsigned long ip;
 
   any = 0;
   for (i=0; i<N_RECORDS; i++) {
     if (records[i].in_use) {
-      ip = records[i].remote_addr.ip_addr;
-      if ((ip & mask) == address) {
+      if (address->family == IPADDR_UNSPEC ||
+          !UTI_CompareIPs(&records[i].remote_addr.ip_addr, address, mask)) {
         any = 1;
         NCR_TakeSourceOffline(records[i].data);
       }
@@ -354,11 +377,11 @@ NSR_TakeSourcesOffline(unsigned long mask, unsigned long address)
 /* ================================================== */
 
 int
-NSR_ModifyMinpoll(unsigned long address, int new_minpoll)
+NSR_ModifyMinpoll(IPAddr *address, int new_minpoll)
 {
   int slot, found;
   NTP_Remote_Address addr;
-  addr.ip_addr = address;
+  addr.ip_addr = *address;
   addr.port = 0;
 
   find_slot(&addr, &slot, &found);
@@ -373,11 +396,11 @@ NSR_ModifyMinpoll(unsigned long address, int new_minpoll)
 /* ================================================== */
 
 int
-NSR_ModifyMaxpoll(unsigned long address, int new_maxpoll)
+NSR_ModifyMaxpoll(IPAddr *address, int new_maxpoll)
 {
   int slot, found;
   NTP_Remote_Address addr;
-  addr.ip_addr = address;
+  addr.ip_addr = *address;
   addr.port = 0;
 
   find_slot(&addr, &slot, &found);
@@ -392,11 +415,11 @@ NSR_ModifyMaxpoll(unsigned long address, int new_maxpoll)
 /* ================================================== */
 
 int
-NSR_ModifyMaxdelay(unsigned long address, double new_max_delay)
+NSR_ModifyMaxdelay(IPAddr *address, double new_max_delay)
 {
   int slot, found;
   NTP_Remote_Address addr;
-  addr.ip_addr = address;
+  addr.ip_addr = *address;
   addr.port = 0;
 
   find_slot(&addr, &slot, &found);
@@ -411,11 +434,11 @@ NSR_ModifyMaxdelay(unsigned long address, double new_max_delay)
 /* ================================================== */
 
 int
-NSR_ModifyMaxdelayratio(unsigned long address, double new_max_delay_ratio)
+NSR_ModifyMaxdelayratio(IPAddr *address, double new_max_delay_ratio)
 {
   int slot, found;
   NTP_Remote_Address addr;
-  addr.ip_addr = address;
+  addr.ip_addr = *address;
   addr.port = 0;
 
   find_slot(&addr, &slot, &found);
@@ -431,17 +454,16 @@ NSR_ModifyMaxdelayratio(unsigned long address, double new_max_delay_ratio)
 
 int
 NSR_InitiateSampleBurst(int n_good_samples, int n_total_samples,
-                        unsigned long mask, unsigned long address)
+                        IPAddr *mask, IPAddr *address)
 {
   int i;
   int any;
-  unsigned long ip;
 
   any = 0;
   for (i=0; i<N_RECORDS; i++) {
     if (records[i].in_use) {
-      ip = records[i].remote_addr.ip_addr;
-      if ((ip & mask) == address) {
+      if (address->family == IPADDR_UNSPEC ||
+          !UTI_CompareIPs(&records[i].remote_addr.ip_addr, address, mask)) {
         any = 1;
         NCR_InitiateSampleBurst(records[i].data, n_good_samples, n_total_samples);
       }
index 2e8499c116c9717d7c6715106e2c0147521860c3..c4ff8d71b14b170d1a67334bb6c97bea43b2fca8 100644 (file)
@@ -46,7 +46,8 @@ typedef enum {
   NSR_Success, /* Operation successful */
   NSR_NoSuchSource, /* Remove - attempt to remove a source that is not known */
   NSR_AlreadyInUse, /* AddServer, AddPeer - attempt to add a source that is already known */ 
-  NSR_TooManySources /* AddServer, AddPeer - too many sources already present */
+  NSR_TooManySources, /* AddServer, AddPeer - too many sources already present */
+  NSR_InvalidAF /* AddServer, AddPeer - attempt to add a source with invalid address family */
 } NSR_Status;
 
 /* Procedure to add a new server source (to which this machine will be
@@ -75,22 +76,22 @@ extern void NSR_Finalise(void);
 /* This routine is used to indicate that sources whose IP addresses
    match a particular subnet should be set online again.  Returns a
    flag indicating whether any hosts matched the address */
-extern int NSR_TakeSourcesOnline(unsigned long mask, unsigned long address);
+extern int NSR_TakeSourcesOnline(IPAddr *mask, IPAddr *address);
 
 /* This routine is used to indicate that sources whose IP addresses
    match a particular subnet should be set offline.  Returns a flag
    indicating whether any hosts matched the address */
-extern int NSR_TakeSourcesOffline(unsigned long mask, unsigned long address);
+extern int NSR_TakeSourcesOffline(IPAddr *mask, IPAddr *address);
 
-extern int NSR_ModifyMinpoll(unsigned long address, int new_minpoll);
+extern int NSR_ModifyMinpoll(IPAddr *address, int new_minpoll);
 
-extern int NSR_ModifyMaxpoll(unsigned long address, int new_maxpoll);
+extern int NSR_ModifyMaxpoll(IPAddr *address, int new_maxpoll);
 
-extern int NSR_ModifyMaxdelay(unsigned long address, double new_max_delay);
+extern int NSR_ModifyMaxdelay(IPAddr *address, double new_max_delay);
 
-extern int NSR_ModifyMaxdelayratio(unsigned long address, double new_max_delay_ratio);
+extern int NSR_ModifyMaxdelayratio(IPAddr *address, double new_max_delay_ratio);
 
-extern int NSR_InitiateSampleBurst(int n_good_samples, int n_total_samples, unsigned long mask, unsigned long address);
+extern int NSR_InitiateSampleBurst(int n_good_samples, int n_total_samples, IPAddr *mask, IPAddr *address);
 
 extern void NSR_ReportSource(RPT_SourceReport *report, struct timeval *now);
 
index 1d8167f3715156f84c4eaf39998c1b98784b6a73..50c3a429ba905be5290b52a5e26a3a30591d7fa4 100644 (file)
@@ -172,7 +172,7 @@ RCL_StartRefclocks(void)
   for (i = 0; i < n_sources; i++) {
     RCL_Instance inst = &refclocks[i];
 
-    inst->source = SRC_CreateNewInstance(inst->ref_id, SRC_REFCLOCK);
+    inst->source = SRC_CreateNewInstance(inst->ref_id, SRC_REFCLOCK, NULL);
     inst->timeout_id = SCH_AddTimeoutByDelay(0.0, poll_timeout, (void *)inst);
   }
 
@@ -186,7 +186,8 @@ RCL_ReportSource(RPT_SourceReport *report, struct timeval *now)
   int i;
   unsigned long ref_id;
 
-  ref_id = report->ip_addr;
+  assert(report->ip_addr.family == IPADDR_INET4);
+  ref_id = report->ip_addr.addr.in4;
 
   for (i = 0; i < n_sources; i++) {
     RCL_Instance inst = &refclocks[i];
index a2bdb97e63174799ce4e82a815fb87d951965c6b..06a0b424c27bd95863c8430d77f2e1abf03e7f27 100644 (file)
--- a/reports.h
+++ b/reports.h
 #define GOT_REPORTS_H
 
 #include "sysincl.h"
+#include "addressing.h"
 
 #define REPORT_INVALID_OFFSET 0x80000000
 
 typedef struct {
-  unsigned long ip_addr;
+  IPAddr ip_addr;
   int stratum;
   int poll;
   enum {RPT_NTP_CLIENT, RPT_NTP_PEER, RPT_LOCAL_REFERENCE} mode;
@@ -65,7 +66,7 @@ typedef struct {
 } RPT_TrackingReport;
 
 typedef struct {
-  unsigned long ip_addr;
+  IPAddr ip_addr;
   unsigned long n_samples;
   unsigned long n_runs;
   unsigned long span_seconds;
@@ -94,7 +95,7 @@ typedef struct {
 } RPT_ClientAccess_Report;
 
 typedef struct {
-  unsigned long ip_addr;
+  IPAddr ip_addr;
   unsigned long client_hits;
   unsigned long peer_hits;
   unsigned long cmd_hits_auth;
index db8795b6f2ca8e43298a0b63249263798427f596..ffe63cd422f0ca2dedb02d6983e61152cefa2d95 100644 (file)
--- a/sources.c
+++ b/sources.c
@@ -88,6 +88,7 @@ struct SRC_Instance_Record {
   unsigned long ref_id;         /* The reference ID of this source
                                    (i.e. its IP address, NOT the
                                    reference _it_ is sync'd to) */
+  IPAddr *ip_addr;              /* Its IP address if NTP source */
 
   /* Flag indicating that we are receiving packets with valid headers
      from this source and can use it as a reference */
@@ -160,7 +161,7 @@ void SRC_Finalise(void)
 /* Function to create a new instance.  This would be called by one of
    the individual source-type instance creation routines. */
 
-SRC_Instance SRC_CreateNewInstance(unsigned long ref_id, SRC_Type type)
+SRC_Instance SRC_CreateNewInstance(unsigned long ref_id, SRC_Type type, IPAddr *addr)
 {
   SRC_Instance result;
 
@@ -189,6 +190,7 @@ SRC_Instance SRC_CreateNewInstance(unsigned long ref_id, SRC_Type type)
   result->index = n_sources;
   result->leap_status = LEAP_Normal;
   result->ref_id = ref_id;
+  result->ip_addr = addr;
   result->reachable = 0;
   result->status = SRC_BAD_STATS;
   result->type = type;
@@ -362,7 +364,7 @@ source_to_string(SRC_Instance inst)
 {
   switch (inst->type) {
     case SRC_NTP:
-      return UTI_IPToDottedQuad(inst->ref_id);
+      return UTI_IPToString(inst->ip_addr);
     case SRC_REFCLOCK:
       return UTI_RefidToString(inst->ref_id);
     default:
@@ -912,7 +914,16 @@ SRC_ReportSource(int index, RPT_SourceReport *report, struct timeval *now)
     return 0;
   } else {
     src = sources[index];
-    report->ip_addr = src->ref_id;
+
+    memset(&report->ip_addr, 0, sizeof (report->ip_addr));
+    if (src->ip_addr)
+      report->ip_addr = *src->ip_addr;
+    else {
+      /* Use refid as an address */
+      report->ip_addr.addr.in4 = src->ref_id;
+      report->ip_addr.family = IPADDR_INET4;
+    }
+
     switch (src->status) {
       case SRC_SYNC:
         report->state = RPT_SYNC;
@@ -949,7 +960,10 @@ SRC_ReportSourcestats(int index, RPT_SourcestatsReport *report)
     return 0;
   } else {
     src = sources[index];
-    report->ip_addr = src->ref_id;
+    if (src->ip_addr)
+      report->ip_addr = *src->ip_addr;
+    else
+      report->ip_addr.family = IPADDR_UNSPEC; 
     SST_DoSourcestatsReport(src->stats, report);
     return 1;
   }
index 3afd80636a7f77860c780019cc29af1234c4121d..e563036c6637f7c77b2e6d96e26df144e037a10f 100644 (file)
--- a/sources.h
+++ b/sources.h
@@ -58,7 +58,7 @@ typedef enum {
 /* Function to create a new instance.  This would be called by one of
    the individual source-type instance creation routines. */
 
-extern SRC_Instance SRC_CreateNewInstance(unsigned long ref_id, SRC_Type type);
+extern SRC_Instance SRC_CreateNewInstance(unsigned long ref_id, SRC_Type type, IPAddr *addr);
 
 /* Function to get rid of a source when it is being unconfigured.
    This may cause the current reference source to be reselected, if this
index 4cb1da83af32a0812f92e137a7367623950b8bdb..34cc3b7c93c450299bacbf77299aaf60381b6442 100644 (file)
--- a/sysincl.h
+++ b/sysincl.h
 
 #endif
 
+#ifdef HAVE_IPV6
+/* For inet_ntop() */
+#include <arpa/inet.h>
+#endif
+
 #if defined (SOLARIS) || defined(SUNOS)
 /* Only needed on these platforms, and doesn't exist on some Linux
    versions. */
diff --git a/util.c b/util.c
index b5f3cdf1abf1091a52974028a157873acf7660df..5717d547eb78a7bb9dc4522416db9fdf821bbf4c 100644 (file)
--- a/util.c
+++ b/util.c
@@ -31,6 +31,7 @@
 #include "sysincl.h"
 
 #include "util.h"
+#include "md5.h"
 
 /* ================================================== */
 
@@ -271,6 +272,169 @@ UTI_IPToDottedQuad(unsigned long ip)
 
 /* ================================================== */
 
+char *
+UTI_IPToString(IPAddr *addr)
+{
+  unsigned long a, b, c, d, ip;
+  uint8_t *ip6;
+  char *result;
+
+  result = NEXT_BUFFER;
+  switch (addr->family) {
+    case IPADDR_UNSPEC:
+      snprintf(result, BUFFER_LENGTH, "[UNSPEC]");
+      break;
+    case IPADDR_INET4:
+      ip = addr->addr.in4;
+      a = (ip>>24) & 0xff;
+      b = (ip>>16) & 0xff;
+      c = (ip>> 8) & 0xff;
+      d = (ip>> 0) & 0xff;
+      snprintf(result, BUFFER_LENGTH, "%ld.%ld.%ld.%ld", a, b, c, d);
+      break;
+    case IPADDR_INET6:
+      ip6 = addr->addr.in6;
+#ifdef HAVE_IPV6
+      inet_ntop(AF_INET6, ip6, result, BUFFER_LENGTH);
+#else
+      snprintf(result, BUFFER_LENGTH, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
+               ip6[0], ip6[1], ip6[2], ip6[3], ip6[4], ip6[5], ip6[6], ip6[7],
+               ip6[8], ip6[9], ip6[10], ip6[11], ip6[12], ip6[13], ip6[14], ip6[15]);
+#endif
+      break;
+    default:
+      snprintf(result, BUFFER_LENGTH, "[UNKNOWN]");
+  }
+  return result;
+}
+
+/* ================================================== */
+
+int
+UTI_StringToIP(const char *addr, IPAddr *ip)
+{
+#ifdef HAVE_IPV6
+  struct in_addr in4;
+  struct in6_addr in6;
+
+  if (inet_pton(AF_INET, addr, &in4) > 0) {
+    ip->family = IPADDR_INET4;
+    ip->addr.in4 = ntohl(in4.s_addr);
+    return 1;
+  }
+
+  if (inet_pton(AF_INET6, addr, &in6) > 0) {
+    ip->family = IPADDR_INET6;
+    memcpy(ip->addr.in6, in6.s6_addr, sizeof (ip->addr.in6));
+    return 1;
+  }
+#else
+  unsigned long a, b, c, d, n;
+
+  n = sscanf(addr, "%lu.%lu.%lu.%lu", &a, &b, &c, &d);
+  if (n == 4) {
+    ip->family = IPADDR_INET4;
+    ip->addr.in4 = ((a & 0xff) << 24) | ((b & 0xff) << 16) | 
+                   ((c & 0xff) << 8) | (d & 0xff);
+    return 1;
+  }
+#endif
+
+  return 0;
+}
+
+/* ================================================== */
+
+unsigned long
+UTI_IPToRefid(IPAddr *ip)
+{
+  MD5_CTX ctx;
+
+  switch (ip->family) {
+    case IPADDR_INET4:
+      return ip->addr.in4;
+    case IPADDR_INET6:
+      MD5Init(&ctx);
+      MD5Update(&ctx, (unsigned const char *) ip->addr.in6, sizeof (ip->addr.in6));
+      MD5Final(&ctx);
+      return ctx.digest[0] << 24 | ctx.digest[1] << 16 | ctx.digest[2] << 8 | ctx.digest[3];
+  }
+  return 0;
+}
+
+/* ================================================== */
+
+void
+UTI_IPHostToNetwork(IPAddr *src, IPAddr *dest)
+{
+  /* Don't send uninitialized bytes over network */
+  memset(dest, 0, sizeof (IPAddr));
+
+  dest->family = htons(src->family);
+
+  switch (src->family) {
+    case IPADDR_INET4:
+      dest->addr.in4 = htonl(src->addr.in4);
+      break;
+    case IPADDR_INET6:
+      memcpy(dest->addr.in6, src->addr.in6, sizeof (dest->addr.in6));
+      break;
+  }
+}
+
+/* ================================================== */
+
+void
+UTI_IPNetworkToHost(IPAddr *src, IPAddr *dest)
+{
+  dest->family = ntohs(src->family);
+
+  switch (dest->family) {
+    case IPADDR_INET4:
+      dest->addr.in4 = ntohl(src->addr.in4);
+      break;
+    case IPADDR_INET6:
+      memcpy(dest->addr.in6, src->addr.in6, sizeof (dest->addr.in6));
+      break;
+  }
+}
+
+/* ================================================== */
+
+int
+UTI_CompareIPs(IPAddr *a, IPAddr *b, IPAddr *mask)
+{
+  int i, d;
+
+  if (a->family != b->family)
+    return a->family - b->family;
+
+  if (mask && mask->family != b->family)
+    mask = NULL;
+
+  switch (a->family) {
+    case IPADDR_UNSPEC:
+      return 0;
+    case IPADDR_INET4:
+      if (mask)
+        return (a->addr.in4 & mask->addr.in4) - (b->addr.in4 & mask->addr.in4);
+      else
+        return a->addr.in4 - b->addr.in4;
+    case IPADDR_INET6:
+      for (i = 0, d = 0; !d && i < 16; i++) {
+        if (mask)
+          d = (a->addr.in6[i] & mask->addr.in6[i]) -
+              (b->addr.in6[i] & mask->addr.in6[i]);
+        else
+          d = a->addr.in6[i] - b->addr.in6[i];
+      }
+      return d;
+  }
+  return 0;
+}
+
+/* ================================================== */
+
 char *
 UTI_TimeToLogForm(time_t t)
 {
diff --git a/util.h b/util.h
index 1c41b74d8ffcd8c5bfe69f3896db9e19c43346e1..1ec21842e308a769020f68f589f5dfedc69cc960 100644 (file)
--- a/util.h
+++ b/util.h
@@ -33,6 +33,7 @@
 
 #include "sysincl.h"
 
+#include "addressing.h"
 #include "ntp.h"
 
 /* Convert a timeval into a floating point number of seconds */
@@ -75,8 +76,15 @@ extern char *UTI_TimestampToString(NTP_int64 *ts);
 /* Convert ref_id into a temporary string, for diagnostics */
 extern char *UTI_RefidToString(unsigned long ref_id);
 
-/* Convert an IP address to dotted quad notation, for diagnostics */
+/* Convert an IP address to string, for diagnostics */
 extern char *UTI_IPToDottedQuad(unsigned long ip);
+extern char *UTI_IPToString(IPAddr *ip);
+
+extern int UTI_StringToIP(const char *addr, IPAddr *ip);
+extern unsigned long UTI_IPToRefid(IPAddr *ip);
+extern void UTI_IPHostToNetwork(IPAddr *src, IPAddr *dest);
+extern void UTI_IPNetworkToHost(IPAddr *src, IPAddr *dest);
+extern int UTI_CompareIPs(IPAddr *a, IPAddr *b, IPAddr *mask);
 
 extern char *UTI_TimeToLogForm(time_t t);