From 5214d42c077245bc380fac505e7fe7f887658cca Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Mon, 5 Jan 2015 17:18:50 +0100 Subject: [PATCH] ntp: count references to NTP server sockets 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 | 28 +++++++++++++++++++++++- ntp_io.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++--- ntp_io.h | 3 +++ 3 files changed, 90 insertions(+), 4 deletions(-) diff --git a/ntp_core.c b/ntp_core.c index f179dbf..e936a09 100644 --- a/ntp_core.c +++ b/ntp_core.c @@ -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), diff --git a/ntp_io.c b/ntp_io.c index d45dba6..fdf4bb6 100644 --- 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) { diff --git a/ntp_io.h b/ntp_io.h index 6714bfe..cbdee56 100644 --- 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);