* 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
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
#include "memory.h"
#include "reports.h"
#include "util.h"
+#include "logging.h"
/* Number of bits of address per layer of the table. This value has
been chosen on the basis that a server will predominantly be serving
/* 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
max_nodes = 0;
n_nodes = 0;
+ alloced = 0;
+ alloc_limit = CNF_GetClientLogLimit();
+ alloc_limit_reached = 0;
}
/* ================================================== */
/* ================================================== */
+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();
}
/* ================================================== */
parent_subnet->entry[the_entry] = (void *) new_node;
clear_node(new_node);
+ alloced += sizeof (Node);
+
if (n_nodes == max_nodes) {
if (nodes) {
max_nodes += NODE_TABLE_INCREMENT;
max_nodes = NODE_TABLE_INCREMENT;
nodes = MallocArray(Node *, max_nodes);
}
+ alloced += sizeof (Node *) * (max_nodes - n_nodes);
}
nodes[n_nodes++] = (Node *) new_node;
+ check_alloc_limit();
}
/* ================================================== */
if (new_bits_left > 0) {
if (!subnet->entry[this_subnet]) {
+ if (alloc_limit_reached)
+ return NULL;
create_subnet(subnet, this_subnet);
}
return find_subnet((Subnet *) subnet->entry[this_subnet], new_subnet, new_bits_left);
} else {
if (!subnet->entry[this_subnet]) {
+ if (alloc_limit_reached)
+ return NULL;
create_node(subnet, this_subnet);
}
return subnet->entry[this_subnet];
Node *node;
if (active) {
node = (Node *) find_subnet(&top_subnet, client, 32);
+ if (node == NULL)
+ return;
node->ip_addr = client;
++node->client_hits;
node->last_ntp_hit = now;
Node *node;
if (active) {
node = (Node *) find_subnet(&top_subnet, client, 32);
+ if (node == NULL)
+ return;
node->ip_addr = client;
++node->peer_hits;
node->last_ntp_hit = now;
Node *node;
if (active) {
node = (Node *) find_subnet(&top_subnet, client, 32);
+ if (node == NULL)
+ return;
node->ip_addr = client;
node->last_cmd_hit = now;
switch (type) {
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 *);
memory */
static int no_client_log = 0;
+/* Limit memory allocated for the clients log */
+static unsigned long client_log_limit = 524288;
+
/* IP address (host order) for binding the NTP socket to. 0 means INADDR_ANY
will be used */
static unsigned long bind_address = 0UL;
{"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},
/* ================================================== */
+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)
{
/* ================================================== */
+unsigned long
+CNF_GetClientLogLimit(void)
+{
+ return client_log_limit;
+}
+
+/* ================================================== */
+
void
CNF_GetBindAddress(unsigned long *addr)
{
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(unsigned long *addr);
extern void CNF_GetBindCommandAddress(unsigned long *addr);
extern char *CNF_GetPidFile(void);
LOGF_Local,
LOGF_Util,
LOGF_Main,
+ LOGF_ClientLog,
LOGF_Configure,
LOGF_CmdMon,
LOGF_Acquire,