]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
ntp: use separate connected sockets for each server
authorMiroslav Lichvar <mlichvar@redhat.com>
Tue, 25 Mar 2014 13:26:50 +0000 (14:26 +0100)
committerMiroslav Lichvar <mlichvar@redhat.com>
Tue, 25 Mar 2014 14:27:18 +0000 (15:27 +0100)
If acquisitionport is set to 0 (default), create and connect a new
socket for each server instead of using one socket per address family
for all servers.

ntp_core.c
ntp_io.c
ntp_io.h

index 14d267b7404152c6b101b6b9d0b6392fc34f39f0..4e6eaffad72428328ef79217b7c082adaa2a5bd6 100644 (file)
@@ -385,6 +385,8 @@ NCR_DestroyInstance(NCR_Instance instance)
     instance->timer_running = 0;
   }
 
+  NIO_CloseClientSocket(instance->local_addr.sock_fd);
+
   /* Free the data structure */
   Free(instance);
 }
index 81acfd4c74587106d885b3e350a2ed5c30dbbe98..1c57540f67abf9ecc97de47e81c4ae04849746ad 100644 (file)
--- a/ntp_io.c
+++ b/ntp_io.c
@@ -57,6 +57,10 @@ static int server_sock_fd6;
 static int client_sock_fd6;
 #endif
 
+/* Flag indicating we create a new connected client socket for each
+   server instead of sharing client_sock_fd4 and client_sock_fd6 */
+static int separate_client_sockets;
+
 /* Flag indicating that we have been initialised */
 static int initialised=0;
 
@@ -233,6 +237,46 @@ prepare_socket(int family, int port_number)
 
 /* ================================================== */
 
+static int
+connect_socket(int sock_fd, NTP_Remote_Address *remote_addr)
+{
+  union sockaddr_in46 addr;
+  socklen_t addr_len;
+
+  memset(&addr, 0, sizeof (addr));
+
+  switch (remote_addr->ip_addr.family) {
+    case IPADDR_INET4:
+      addr_len = sizeof (addr.in4);
+      addr.in4.sin_family = AF_INET;
+      addr.in4.sin_addr.s_addr = htonl(remote_addr->ip_addr.addr.in4);
+      addr.in4.sin_port = htons(remote_addr->port);
+      break;
+#ifdef HAVE_IPV6
+    case IPADDR_INET6:
+      addr_len = sizeof (addr.in6);
+      addr.in6.sin6_family = AF_INET6;
+      memcpy(addr.in6.sin6_addr.s6_addr, remote_addr->ip_addr.addr.in6,
+             sizeof (addr.in6.sin6_addr.s6_addr));
+      addr.in6.sin6_port = htons(remote_addr->port);
+      break;
+#endif
+    default:
+      assert(0);
+  }
+
+  if (connect(sock_fd, &addr.u, addr_len) < 0) {
+    LOG(LOGS_ERR, LOGF_NtpIO, "Could not connect NTP socket to %s:%d : %s",
+        UTI_IPToString(&remote_addr->ip_addr), remote_addr->port,
+        strerror(errno));
+    return 0;
+  }
+
+  return 1;
+}
+
+/* ================================================== */
+
 static void
 close_socket(int sock_fd)
 {
@@ -258,6 +302,9 @@ NIO_Initialise(int family)
   server_port = CNF_GetNTPPort();
   client_port = CNF_GetAcquisitionPort();
 
+  /* Use separate connected sockets if client port is not set */
+  separate_client_sockets = client_port == 0;
+
   server_sock_fd4 = INVALID_SOCK_FD;
   client_sock_fd4 = INVALID_SOCK_FD;
 #ifdef HAVE_IPV6
@@ -267,18 +314,22 @@ NIO_Initialise(int family)
 
   if (family == IPADDR_UNSPEC || family == IPADDR_INET4) {
     server_sock_fd4 = prepare_socket(AF_INET, server_port);
-    if (client_port != server_port || !server_port)
-      client_sock_fd4 = prepare_socket(AF_INET, client_port);
-    else
-      client_sock_fd4 = server_sock_fd4;
+    if (!separate_client_sockets) {
+      if (client_port != server_port || !server_port)
+        client_sock_fd4 = prepare_socket(AF_INET, client_port);
+      else
+        client_sock_fd4 = server_sock_fd4;
+    }
   }
 #ifdef HAVE_IPV6
   if (family == IPADDR_UNSPEC || family == IPADDR_INET6) {
     server_sock_fd6 = prepare_socket(AF_INET6, server_port);
-    if (client_port != server_port || !server_port)
-      client_sock_fd6 = prepare_socket(AF_INET6, client_port);
-    else
-      client_sock_fd6 = server_sock_fd6;
+    if (!separate_client_sockets) {
+      if (client_port != server_port || !server_port)
+        client_sock_fd6 = prepare_socket(AF_INET6, client_port);
+      else
+        client_sock_fd6 = server_sock_fd6;
+    }
   }
 #endif
 
@@ -286,7 +337,7 @@ NIO_Initialise(int family)
 #ifdef HAVE_IPV6
        && server_sock_fd6 == INVALID_SOCK_FD
 #endif
-      ) || (client_sock_fd4 == INVALID_SOCK_FD
+      ) || (!separate_client_sockets && client_sock_fd4 == INVALID_SOCK_FD
 #ifdef HAVE_IPV6
        && client_sock_fd6 == INVALID_SOCK_FD
 #endif
@@ -318,15 +369,42 @@ NIO_Finalise(void)
 int
 NIO_GetClientSocket(NTP_Remote_Address *remote_addr)
 {
-  switch (remote_addr->ip_addr.family) {
-    case IPADDR_INET4:
-      return client_sock_fd4;
+  if (separate_client_sockets) {
+    int sock_fd;
+
+    switch (remote_addr->ip_addr.family) {
+      case IPADDR_INET4:
+        sock_fd = prepare_socket(AF_INET, 0);
+        break;
 #ifdef HAVE_IPV6
-    case IPADDR_INET6:
-      return client_sock_fd6;
+      case IPADDR_INET6:
+        sock_fd = prepare_socket(AF_INET6, 0);
+        break;
 #endif
-    default:
+      default:
+        sock_fd = INVALID_SOCK_FD;
+    }
+
+    if (sock_fd == INVALID_SOCK_FD)
+      return INVALID_SOCK_FD;
+
+    if (!connect_socket(sock_fd, remote_addr)) {
+      close_socket(sock_fd);
       return INVALID_SOCK_FD;
+    }
+
+    return sock_fd;
+  } else {
+    switch (remote_addr->ip_addr.family) {
+      case IPADDR_INET4:
+        return client_sock_fd4;
+#ifdef HAVE_IPV6
+      case IPADDR_INET6:
+        return client_sock_fd6;
+#endif
+      default:
+        return INVALID_SOCK_FD;
+    }
   }
 }
 
@@ -349,6 +427,15 @@ NIO_GetServerSocket(NTP_Remote_Address *remote_addr)
 
 /* ================================================== */
 
+void
+NIO_CloseClientSocket(int sock_fd)
+{
+  if (separate_client_sockets)
+    close_socket(sock_fd);
+}
+
+/* ================================================== */
+
 static void
 read_from_socket(void *anything)
 {
index 2c4d862b29aa5dd013a194be14b075c474104318..b323fbac61f57cd25fee0acdca1f341631a0d4df 100644 (file)
--- a/ntp_io.h
+++ b/ntp_io.h
@@ -43,6 +43,9 @@ extern int NIO_GetClientSocket(NTP_Remote_Address *remote_addr);
 /* Function to obtain a socket for sending server/peer packets */
 extern int NIO_GetServerSocket(NTP_Remote_Address *remote_addr);
 
+/* Function to close a socket returned by NIO_GetClientSocket() */
+extern void NIO_CloseClientSocket(int sock_fd);
+
 /* Function to transmit a packet */
 extern void NIO_SendNormalPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr);