mirror of
https://gitlab.com/chrony/chrony.git
synced 2025-12-04 06:55:06 -05:00
sources: improve handling of dump files and their format
Check for write errors when saving dump files. Don't save files with no samples. Add more sanity checks for loaded data. Extend the file format to include an identifier, the reachability register, leap status, name, and authentication flag. Avoid loading unauthenticated data after switching authentication on. Change format and order of some fields to simplify parsing. Drop fields that were kept only for compatibility. The dump files now contain all information needed to perform the source selection and update the reference. There is no support kept for the old file format. Loading of old dump files will fail after upgrading to new version.
This commit is contained in:
133
sources.c
133
sources.c
@@ -177,6 +177,9 @@ static double reselect_distance;
|
||||
static double stratum_weight;
|
||||
static double combine_limit;
|
||||
|
||||
/* Identifier of the dump file */
|
||||
#define DUMP_IDENTIFIER "SRC0\n"
|
||||
|
||||
/* ================================================== */
|
||||
/* Forward prototype */
|
||||
|
||||
@@ -1325,24 +1328,60 @@ add_dispersion(double dispersion, void *anything)
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static
|
||||
FILE *open_dumpfile(SRC_Instance inst, char mode)
|
||||
static int
|
||||
get_dumpfile(SRC_Instance inst, char *filename, size_t len)
|
||||
{
|
||||
char filename[64], *dumpdir;
|
||||
/* Use the IP address, or reference ID with reference clocks */
|
||||
switch (inst->type) {
|
||||
case SRC_NTP:
|
||||
if (!UTI_IsIPReal(inst->ip_addr) ||
|
||||
snprintf(filename, len, "%s", source_to_string(inst)) >= len)
|
||||
return 0;
|
||||
break;
|
||||
case SRC_REFCLOCK:
|
||||
if (snprintf(filename, len, "refid:%08"PRIx32, inst->ref_id) >= len)
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
save_source(SRC_Instance inst)
|
||||
{
|
||||
char filename[64], *dumpdir, *ntp_name;
|
||||
FILE *f;
|
||||
|
||||
dumpdir = CNF_GetDumpDir();
|
||||
if (!dumpdir)
|
||||
return NULL;
|
||||
return;
|
||||
|
||||
/* Include IP address in the name for NTP sources, or reference ID in hex */
|
||||
if (inst->type == SRC_NTP && UTI_IsIPReal(inst->ip_addr))
|
||||
snprintf(filename, sizeof (filename), "%s", source_to_string(inst));
|
||||
else if (inst->type == SRC_REFCLOCK)
|
||||
snprintf(filename, sizeof (filename), "refid:%08"PRIx32, inst->ref_id);
|
||||
else
|
||||
return NULL;
|
||||
if (!get_dumpfile(inst, filename, sizeof (filename)))
|
||||
return;
|
||||
|
||||
return UTI_OpenFile(dumpdir, filename, ".dat", mode, 0644);
|
||||
f = UTI_OpenFile(dumpdir, filename, ".dat", 'w', 0644);
|
||||
if (!f)
|
||||
return;
|
||||
|
||||
ntp_name = inst->type == SRC_NTP ? NSR_GetName(inst->ip_addr) : NULL;
|
||||
|
||||
if (fprintf(f, "%s%s\n%d %o %d %d %d\n",
|
||||
DUMP_IDENTIFIER, ntp_name, inst->authenticated,
|
||||
(unsigned int)inst->reachability, inst->reachability_size,
|
||||
inst->stratum, (int)inst->leap) < 0 ||
|
||||
!SST_SaveToFile(inst->stats, f)) {
|
||||
fclose(f);
|
||||
if (!UTI_RemoveFile(dumpdir, filename, ".dat"))
|
||||
;
|
||||
return;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -1351,16 +1390,60 @@ FILE *open_dumpfile(SRC_Instance inst, char mode)
|
||||
void
|
||||
SRC_DumpSources(void)
|
||||
{
|
||||
FILE *out;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n_sources; i++) {
|
||||
out = open_dumpfile(sources[i], 'w');
|
||||
if (!out)
|
||||
continue;
|
||||
SST_SaveToFile(sources[i]->stats, out);
|
||||
fclose(out);
|
||||
for (i = 0; i < n_sources; i++)
|
||||
save_source(sources[i]);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
#define MAX_WORDS 1
|
||||
|
||||
static void
|
||||
load_source(SRC_Instance inst)
|
||||
{
|
||||
char filename[64], line[256], *dumpdir, *ntp_name, *words[MAX_WORDS];
|
||||
int auth, leap, reach_size, stratum;
|
||||
unsigned int reach;
|
||||
FILE *f;
|
||||
|
||||
dumpdir = CNF_GetDumpDir();
|
||||
if (!dumpdir)
|
||||
return;
|
||||
|
||||
if (!get_dumpfile(inst, filename, sizeof (filename)))
|
||||
return;
|
||||
|
||||
f = UTI_OpenFile(dumpdir, filename, ".dat", 'r', 0);
|
||||
if (!f)
|
||||
return;
|
||||
|
||||
ntp_name = inst->type == SRC_NTP ? NSR_GetName(inst->ip_addr) : NULL;
|
||||
|
||||
if (!fgets(line, sizeof (line), f) || strcmp(line, DUMP_IDENTIFIER) != 0 ||
|
||||
!fgets(line, sizeof (line), f) || UTI_SplitString(line, words, MAX_WORDS) != 1 ||
|
||||
(inst->type == SRC_NTP && (!ntp_name || strcmp(words[0], ntp_name) != 0)) ||
|
||||
!fgets(line, sizeof (line), f) ||
|
||||
sscanf(words[0], "%d %o %d %d %d",
|
||||
&auth, &reach, &reach_size, &stratum, &leap) != 5 ||
|
||||
(!auth && inst->authenticated) ||
|
||||
stratum < 1 || stratum >= NTP_MAX_STRATUM ||
|
||||
leap < LEAP_Normal || leap >= LEAP_Unsynchronised ||
|
||||
!SST_LoadFromFile(inst->stats, f)) {
|
||||
LOG(LOGS_WARN, "Could not load dump file for %s", source_to_string(inst));
|
||||
fclose(f);
|
||||
return;
|
||||
}
|
||||
|
||||
inst->reachability = reach & ((1U << SOURCE_REACH_BITS) - 1);
|
||||
inst->reachability_size = CLAMP(0, reach_size, SOURCE_REACH_BITS);
|
||||
inst->stratum = stratum;
|
||||
inst->leap = leap;
|
||||
|
||||
LOG(LOGS_INFO, "Loaded dump file for %s", source_to_string(inst));
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -1368,20 +1451,10 @@ SRC_DumpSources(void)
|
||||
void
|
||||
SRC_ReloadSources(void)
|
||||
{
|
||||
FILE *in;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n_sources; i++) {
|
||||
in = open_dumpfile(sources[i], 'r');
|
||||
if (!in)
|
||||
continue;
|
||||
if (!SST_LoadFromFile(sources[i]->stats, in))
|
||||
LOG(LOGS_WARN, "Could not load dump file for %s",
|
||||
source_to_string(sources[i]));
|
||||
else
|
||||
LOG(LOGS_INFO, "Loaded dump file for %s",
|
||||
source_to_string(sources[i]));
|
||||
fclose(in);
|
||||
load_source(sources[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user