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.
This commit is contained in:
Miroslav Lichvar 2015-01-05 17:18:50 +01:00
parent 40bbe2539b
commit 5214d42c07
3 changed files with 90 additions and 4 deletions

View 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),

View file

@ -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)
{

View file

@ -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);