]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
Add option to limit clientlog memory
authorMiroslav Lichvar <mlichvar@redhat.com>
Tue, 24 Nov 2009 15:05:47 +0000 (16:05 +0100)
committerMiroslav Lichvar <mlichvar@redhat.com>
Wed, 25 Nov 2009 13:37:36 +0000 (14:37 +0100)
chrony.texi
clientlog.c
conf.c
conf.h
logging.h

index 396d41958e89b0c4820c078610f48c52dd0c85cc..3629d3522f977117e970dccf63ceecb012c7d655 100644 (file)
@@ -1182,6 +1182,7 @@ directives can occur in any order in the file.
 * manual directive::            Allow manual entry using chronyc's settime cmd.
 * maxupdateskew directive::     Stop bad estimates upsetting machine clock
 * noclientlog directive::       Prevent chronyd from gathering data about clients
+* clientloglimit directive::    Set client log memory limit
 * peer directive::              Specify an NTP peer
 * pidfile directive::           Specify the file where chronyd's pid is written
 * port directive::              Set port to use for NTP packets
@@ -2087,6 +2088,21 @@ This directive, which takes no arguments, specifies that client accesses
 are not to be logged.  Normally they are logged, allowing statistics to
 be reported using the @code{clients} command in @code{chronyc}.
 @c }}}
+@c {{{ clientloglimit
+@node clientloglimit directive
+@subsection clientloglimit
+This directive specifies the maximum size of the memory allocated to
+log client accesses.  When the limit is reached, only information for
+clients that have already been logged will be updated.  If 0 is
+specified, the memory size will be unlimited.  The default is 524288
+bytes.
+
+An example of the use of this directive is
+
+@example
+clientloglimit 1048576
+@end example
+@c }}}
 @c {{{ peer
 @node peer directive
 @subsection peer
index cd7fdac39c4919ef3275e5d52d439249a119a553..d4f304d65b66a07ca5a38ed8de7aa968311e38dd 100644 (file)
@@ -88,6 +88,13 @@ static int max_nodes = 0;
 /* Flag indicating whether facility is turned on or not */
 static int active = 0;
 
+/* Flag indicating whether memory allocation limit has been reached
+   and no new nodes or subnets should be allocated */
+static int alloc_limit_reached;
+
+static unsigned long alloc_limit;
+static unsigned long alloced;
+
 /* ================================================== */
 
 static void
@@ -159,6 +166,9 @@ CLG_Initialise(void)
   max_nodes = 0;
   n_nodes = 0;
 
+  alloced = 0;
+  alloc_limit = CNF_GetClientLogLimit();
+  alloc_limit_reached = 0;
 }
 
 /* ================================================== */
@@ -171,11 +181,25 @@ CLG_Finalise(void)
 
 /* ================================================== */
 
+static void check_alloc_limit() {
+  if (alloc_limit_reached)
+    return;
+
+  if (alloced >= alloc_limit) {
+    LOG(LOGS_WARN, LOGF_ClientLog, "Client log memory limit reached");
+    alloc_limit_reached = 1;
+  }
+}
+
+/* ================================================== */
+
 static void
 create_subnet(Subnet *parent_subnet, int the_entry)
 {
   parent_subnet->entry[the_entry] = (void *) MallocNew(Subnet);
   clear_subnet((Subnet *) parent_subnet->entry[the_entry]);
+  alloced += sizeof (Subnet);
+  check_alloc_limit();
 }
 
 /* ================================================== */
@@ -188,6 +212,8 @@ create_node(Subnet *parent_subnet, int the_entry)
   parent_subnet->entry[the_entry] = (void *) new_node;
   clear_node(new_node);
 
+  alloced += sizeof (Node);
+
   if (n_nodes == max_nodes) {
     if (nodes) {
       assert(max_nodes > 0);
@@ -198,8 +224,10 @@ create_node(Subnet *parent_subnet, int the_entry)
       max_nodes = 16;
       nodes = MallocArray(Node *, max_nodes);
     }
+    alloced += sizeof (Node *) * (max_nodes - n_nodes);
   }
   nodes[n_nodes++] = (Node *) new_node;
+  check_alloc_limit();
 }
 
 /* ================================================== */
@@ -216,11 +244,15 @@ find_subnet(Subnet *subnet, uint32_t *addr, int addr_len, int bits_consumed)
 
   if (bits_consumed < 32 * addr_len) {
     if (!subnet->entry[this_subnet]) {
+      if (alloc_limit_reached)
+        return NULL;
       create_subnet(subnet, this_subnet);
     }
     return find_subnet((Subnet *) subnet->entry[this_subnet], addr, addr_len, bits_consumed);
   } else {
     if (!subnet->entry[this_subnet]) {
+      if (alloc_limit_reached)
+        return NULL;
       create_node(subnet, this_subnet);
     }
     return subnet->entry[this_subnet];
@@ -273,6 +305,9 @@ CLG_LogNTPClientAccess (IPAddr *client, time_t now)
         assert(0);
     }
 
+    if (node == NULL)
+      return;
+
     node->ip_addr = *client;
     ++node->client_hits;
     node->last_ntp_hit = now;
@@ -300,6 +335,9 @@ CLG_LogNTPPeerAccess(IPAddr *client, time_t now)
         assert(0);
     }
 
+    if (node == NULL)
+      return;
+
     node->ip_addr = *client;
     ++node->peer_hits;
     node->last_ntp_hit = now;
@@ -327,6 +365,9 @@ CLG_LogCommandAccess(IPAddr *client, CLG_Command_Type type, time_t now)
         assert(0);
     }
 
+    if (node == NULL)
+      return;
+
     node->ip_addr = *client;
     node->last_cmd_hit = now;
     switch (type) {
diff --git a/conf.c b/conf.c
index d9a1f47fbd3b61a65b763dcb552834e7c146b062..d7e42dbd6800f6a447da2083dc2216f711b378b8 100644 (file)
--- a/conf.c
+++ b/conf.c
@@ -87,6 +87,7 @@ static void parse_cmddeny(const char *);
 static void parse_cmdport(const char *);
 static void parse_rtconutc(const char *);
 static void parse_noclientlog(const char *);
+static void parse_clientloglimit(const char *);
 static void parse_logchange(const char *);
 static void parse_mailonchange(const char *);
 static void parse_bindaddress(const char *);
@@ -158,6 +159,9 @@ static double mail_change_threshold = 0.0;
    memory */
 static int no_client_log = 0;
 
+/* Limit memory allocated for the clients log */
+static unsigned long client_log_limit = 524288;
+
 /* IP addresses for binding the NTP socket to.  UNSPEC family means INADDR_ANY
    will be used */
 static IPAddr bind_address4, bind_address6;
@@ -213,6 +217,7 @@ static const Command commands[] = {
   {"cmdport", 7, parse_cmdport},
   {"rtconutc", 8, parse_rtconutc},
   {"noclientlog", 11, parse_noclientlog},
+  {"clientloglimit", 14, parse_clientloglimit},
   {"logchange", 9, parse_logchange},
   {"mailonchange", 12, parse_mailonchange},
   {"bindaddress", 11, parse_bindaddress},
@@ -771,6 +776,21 @@ parse_noclientlog(const char *line)
 
 /* ================================================== */
 
+static void
+parse_clientloglimit(const char *line)
+{
+  if (sscanf(line, "%lu", &client_log_limit) != 1) {
+    LOG(LOGS_WARN, LOGF_Configure, "Could not read clientlog memory limit at line %d", line_number);
+  }
+
+  if (client_log_limit == 0) {
+    /* unlimited */
+    client_log_limit = (unsigned long)-1;
+  }
+}
+
+/* ================================================== */
+
 static void
 parse_logchange(const char *line)
 {
@@ -1353,6 +1373,14 @@ CNF_GetNoClientLog(void)
 
 /* ================================================== */
 
+unsigned long
+CNF_GetClientLogLimit(void)
+{
+  return client_log_limit;
+}
+
+/* ================================================== */
+
 void
 CNF_GetBindAddress(int family, IPAddr *addr)
 {
diff --git a/conf.h b/conf.h
index dc20397fd276521322a7864c982deecda3582b5d..9c90bb8be5a90598e1ca842fc3e44947dcf01083 100644 (file)
--- a/conf.h
+++ b/conf.h
@@ -62,6 +62,7 @@ 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 unsigned long CNF_GetClientLogLimit(void);
 extern void CNF_GetBindAddress(int family, IPAddr *addr);
 extern void CNF_GetBindCommandAddress(int family, IPAddr *addr);
 extern char *CNF_GetPidFile(void);
index f95a8088786d1bd3cf5d1aae4ef33ac131f2c8fb..81505e129f290f95e97285e5ab868861414ea7e9 100644 (file)
--- a/logging.h
+++ b/logging.h
@@ -53,6 +53,7 @@ typedef enum {
   LOGF_Local,
   LOGF_Util,
   LOGF_Main,
+  LOGF_ClientLog,
   LOGF_Configure,
   LOGF_CmdMon,
   LOGF_Acquire,