]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
ntp: count references to NTP server sockets
authorMiroslav Lichvar <mlichvar@redhat.com>
Mon, 5 Jan 2015 16:18:50 +0000 (17:18 +0100)
committerMiroslav Lichvar <mlichvar@redhat.com>
Tue, 6 Jan 2015 15:33:49 +0000 (16:33 +0100)
Server sockets are now explicitly opened and closed for normal NTP
server, NTP broadcast and NTP peering. This will allow closing the
NTP port when not needed.

ntp_core.c
ntp_io.c
ntp_io.h

index f179dbf95744ea4c32d14499ac9a8bf80adeb58b..e936a094e45808b03f5e3e6b82046225c072f777 100644 (file)
@@ -229,6 +229,10 @@ static ARR_Instance broadcasts;
 
 /* ================================================== */
 
+/* Server IPv4/IPv6 sockets */
+static int server_sock_fd4;
+static int server_sock_fd6;
+
 static ADF_AuthTable access_auth_table;
 
 /* ================================================== */
@@ -305,6 +309,8 @@ do_time_checks(void)
 void
 NCR_Initialise(void)
 {
+  NTP_Remote_Address addr;
+
   do_size_checks();
   do_time_checks();
 
@@ -314,6 +320,11 @@ NCR_Initialise(void)
 
   access_auth_table = ADF_CreateTable();
   broadcasts = ARR_CreateInstance(sizeof (BroadcastDestination));
+
+  addr.ip_addr.family = IPADDR_INET4;
+  server_sock_fd4 = NIO_OpenServerSocket(&addr);
+  addr.ip_addr.family = IPADDR_INET6;
+  server_sock_fd6 = NIO_OpenServerSocket(&addr);
 }
 
 /* ================================================== */
@@ -321,6 +332,16 @@ NCR_Initialise(void)
 void
 NCR_Finalise(void)
 {
+  unsigned int i;
+
+  if (server_sock_fd4 != INVALID_SOCK_FD)
+    NIO_CloseServerSocket(server_sock_fd4);
+  if (server_sock_fd6 != INVALID_SOCK_FD)
+    NIO_CloseServerSocket(server_sock_fd6);
+
+  for (i = 0; i < ARR_GetSize(broadcasts); i++)
+    NIO_CloseServerSocket(((BroadcastDestination *)ARR_GetElement(broadcasts, i))->local_addr.sock_fd);
+
   ARR_DestroyInstance(broadcasts);
   ADF_DestroyTable(access_auth_table);
 }
@@ -490,6 +511,9 @@ NCR_DestroyInstance(NCR_Instance instance)
   if (instance->opmode != MD_OFFLINE)
     take_offline(instance);
 
+  if (instance->mode == MODE_ACTIVE)
+    NIO_CloseServerSocket(instance->local_addr.sock_fd);
+
   /* This will destroy the source instance inside the
      structure, which will cause reselection if this was the
      synchronising source etc. */
@@ -550,8 +574,10 @@ NCR_ChangeRemoteAddress(NCR_Instance inst, NTP_Remote_Address *remote_addr)
 
   if (inst->mode == MODE_CLIENT)
     close_client_socket(inst);
-  else
+  else {
+    NIO_CloseServerSocket(inst->local_addr.sock_fd);
     inst->local_addr.sock_fd = NIO_OpenServerSocket(remote_addr);
+  }
 
   /* Update the reference ID and reset the source/sourcestats instances */
   SRC_SetRefid(inst->source, UTI_IPToRefid(&remote_addr->ip_addr),
index d45dba69c6b4d3dce784697d9cc542cbf797db68..fdf4bb6d9139ce6793ff9faa632fab1d5865dee1 100644 (file)
--- a/ntp_io.c
+++ b/ntp_io.c
@@ -57,10 +57,22 @@ static int server_sock_fd6;
 static int client_sock_fd6;
 #endif
 
+/* Reference counters for server sockets to keep them open only when needed */
+static int server_sock_ref4;
+#ifdef FEAT_IPV6
+static int server_sock_ref6;
+#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 the server sockets are not created dynamically when needed,
+   either to have a socket for client requests when separate client sockets
+   are disabled and client port is equal to server port, or the server port is
+   disabled */
+static int permanent_server_sockets;
+
 /* Flag indicating that we have been initialised */
 static int initialised=0;
 
@@ -283,15 +295,20 @@ NIO_Initialise(int family)
   if (client_port < 0)
     client_port = 0;
 
+  permanent_server_sockets = !server_port || (!separate_client_sockets &&
+                                              client_port == server_port);
+
   server_sock_fd4 = INVALID_SOCK_FD;
   client_sock_fd4 = INVALID_SOCK_FD;
+  server_sock_ref4 = 0;
 #ifdef FEAT_IPV6
   server_sock_fd6 = INVALID_SOCK_FD;
   client_sock_fd6 = INVALID_SOCK_FD;
+  server_sock_ref6 = 0;
 #endif
 
   if (family == IPADDR_UNSPEC || family == IPADDR_INET4) {
-    if (server_port)
+    if (permanent_server_sockets && server_port)
       server_sock_fd4 = prepare_socket(AF_INET, server_port, 0);
     if (!separate_client_sockets) {
       if (client_port != server_port || !server_port)
@@ -302,7 +319,7 @@ NIO_Initialise(int family)
   }
 #ifdef FEAT_IPV6
   if (family == IPADDR_UNSPEC || family == IPADDR_INET6) {
-    if (server_port)
+    if (permanent_server_sockets && server_port)
       server_sock_fd6 = prepare_socket(AF_INET6, server_port, 0);
     if (!separate_client_sockets) {
       if (client_port != server_port || !server_port)
@@ -313,7 +330,8 @@ NIO_Initialise(int family)
   }
 #endif
 
-  if ((server_port && server_sock_fd4 == INVALID_SOCK_FD
+  if ((server_port && server_sock_fd4 == INVALID_SOCK_FD &&
+       permanent_server_sockets 
 #ifdef FEAT_IPV6
        && server_sock_fd6 == INVALID_SOCK_FD
 #endif
@@ -382,9 +400,21 @@ NIO_OpenServerSocket(NTP_Remote_Address *remote_addr)
 {
   switch (remote_addr->ip_addr.family) {
     case IPADDR_INET4:
+      if (permanent_server_sockets)
+        return server_sock_fd4;
+      if (server_sock_fd4 == INVALID_SOCK_FD)
+        server_sock_fd4 = prepare_socket(AF_INET, CNF_GetNTPPort(), 0);
+      if (server_sock_fd4 != INVALID_SOCK_FD)
+        server_sock_ref4++;
       return server_sock_fd4;
 #ifdef FEAT_IPV6
     case IPADDR_INET6:
+      if (permanent_server_sockets)
+        return server_sock_fd6;
+      if (server_sock_fd6 == INVALID_SOCK_FD)
+        server_sock_fd6 = prepare_socket(AF_INET6, CNF_GetNTPPort(), 0);
+      if (server_sock_fd6 != INVALID_SOCK_FD)
+        server_sock_ref6++;
       return server_sock_fd6;
 #endif
     default:
@@ -403,6 +433,33 @@ NIO_CloseClientSocket(int sock_fd)
 
 /* ================================================== */
 
+void
+NIO_CloseServerSocket(int sock_fd)
+{
+  if (permanent_server_sockets || sock_fd == INVALID_SOCK_FD)
+    return;
+
+  if (sock_fd == server_sock_fd4) {
+    if (--server_sock_ref4 <= 0) {
+      close_socket(server_sock_fd4);
+      server_sock_fd4 = INVALID_SOCK_FD;
+    }
+  }
+#ifdef FEAT_IPV6
+  else if (sock_fd == server_sock_fd6) {
+    if (--server_sock_ref6 <= 0) {
+      close_socket(server_sock_fd6);
+      server_sock_fd6 = INVALID_SOCK_FD;
+    }
+  }
+#endif
+  else {
+    assert(0);
+  }
+}
+
+/* ================================================== */
+
 int
 NIO_IsServerSocket(int sock_fd)
 {
index 6714bfee8dd998373f5b2f2e86abfdcaeb7fe9c1..cbdee56737c65da22ea15be7d3b41353ec23c7f1 100644 (file)
--- a/ntp_io.h
+++ b/ntp_io.h
@@ -47,6 +47,9 @@ extern int NIO_OpenServerSocket(NTP_Remote_Address *remote_addr);
 /* Function to close a socket returned by NIO_OpenClientSocket() */
 extern void NIO_CloseClientSocket(int sock_fd);
 
+/* Function to close a socket returned by NIO_OpenServerSocket() */
+extern void NIO_CloseServerSocket(int sock_fd);
+
 /* Function to check if socket is a server socket */
 extern int NIO_IsServerSocket(int sock_fd);