mirror of
https://gitlab.com/chrony/chrony.git
synced 2025-12-04 05:15:07 -05:00
Compare commits
16 Commits
1.28-pre1
...
1.29-secur
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2afdd4544d | ||
|
|
c4e61835d3 | ||
|
|
e15ce69d08 | ||
|
|
d537ed11fd | ||
|
|
dba458d50c | ||
|
|
3e23430926 | ||
|
|
b5658f4d9c | ||
|
|
ad58baa13b | ||
|
|
c6fdeeb6bb | ||
|
|
7712455d9a | ||
|
|
a9a5f98406 | ||
|
|
9ac8f64d89 | ||
|
|
0da5cf9163 | ||
|
|
f6a39d75a7 | ||
|
|
25aa9f5b42 | ||
|
|
829b3adac3 |
24
NEWS
24
NEWS
@@ -1,3 +1,25 @@
|
|||||||
|
New in version 1.29.1
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Security fixes
|
||||||
|
--------------
|
||||||
|
* Modify chronyc protocol to prevent amplification attacks (CVE-2014-0021)
|
||||||
|
(incompatible with previous protocol version, chronyc supports both)
|
||||||
|
|
||||||
|
New in version 1.29
|
||||||
|
===================
|
||||||
|
|
||||||
|
Security fixes
|
||||||
|
--------------
|
||||||
|
* Fix crash when processing crafted commands (CVE-2012-4502)
|
||||||
|
(possible with IP addresses allowed by cmdallow and localhost)
|
||||||
|
* Don't send uninitialized data in SUBNETS_ACCESSED and CLIENT_ACCESSES
|
||||||
|
replies (CVE-2012-4503) (not used by chronyc)
|
||||||
|
|
||||||
|
Other changes
|
||||||
|
-------------
|
||||||
|
* Drop support for SUBNETS_ACCESSED and CLIENT_ACCESSES commands
|
||||||
|
|
||||||
New in version 1.28
|
New in version 1.28
|
||||||
===================
|
===================
|
||||||
|
|
||||||
@@ -8,6 +30,7 @@ New in version 1.28
|
|||||||
* Add generatecommandkey, minsamples, maxsamples and user directives
|
* Add generatecommandkey, minsamples, maxsamples and user directives
|
||||||
* Improve compatibility with NTPv1 and NTPv2 clients
|
* Improve compatibility with NTPv1 and NTPv2 clients
|
||||||
* Create sockets only in selected family with -4/-6 option
|
* Create sockets only in selected family with -4/-6 option
|
||||||
|
* Treat address bind errors as non-fatal
|
||||||
* Extend tracking log
|
* Extend tracking log
|
||||||
* Accept float values as initstepslew threshold
|
* Accept float values as initstepslew threshold
|
||||||
* Allow hostnames in offline, online and burst commands
|
* Allow hostnames in offline, online and burst commands
|
||||||
@@ -18,6 +41,7 @@ New in version 1.28
|
|||||||
* Set local stratum correctly
|
* Set local stratum correctly
|
||||||
* Remove unnecessary adjtimex calls
|
* Remove unnecessary adjtimex calls
|
||||||
* Set paths in documentation by configure
|
* Set paths in documentation by configure
|
||||||
|
* Update chrony.spec
|
||||||
|
|
||||||
New in version 1.27
|
New in version 1.27
|
||||||
===================
|
===================
|
||||||
|
|||||||
62
candm.h
62
candm.h
@@ -298,22 +298,10 @@ typedef struct {
|
|||||||
uint32_t bits_specd;
|
uint32_t bits_specd;
|
||||||
} REQ_SubnetsAccessed_Subnet;
|
} REQ_SubnetsAccessed_Subnet;
|
||||||
|
|
||||||
#define MAX_SUBNETS_ACCESSED 8
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint32_t n_subnets;
|
|
||||||
REQ_SubnetsAccessed_Subnet subnets[MAX_SUBNETS_ACCESSED];
|
|
||||||
} REQ_SubnetsAccessed;
|
|
||||||
|
|
||||||
/* This is based on the response size rather than the
|
/* This is based on the response size rather than the
|
||||||
request size */
|
request size */
|
||||||
#define MAX_CLIENT_ACCESSES 8
|
#define MAX_CLIENT_ACCESSES 8
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint32_t n_clients;
|
|
||||||
IPAddr client_ips[MAX_CLIENT_ACCESSES];
|
|
||||||
} REQ_ClientAccesses;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t first_index;
|
uint32_t first_index;
|
||||||
uint32_t n_indices;
|
uint32_t n_indices;
|
||||||
@@ -370,14 +358,26 @@ typedef struct {
|
|||||||
modify polltarget, modify maxdelaydevratio, reselect, reselectdistance
|
modify polltarget, modify maxdelaydevratio, reselect, reselectdistance
|
||||||
|
|
||||||
Version 5 : auth data moved to the end of the packet to allow hashes with
|
Version 5 : auth data moved to the end of the packet to allow hashes with
|
||||||
different sizes, extended sources, tracking and activity reports
|
different sizes, extended sources, tracking and activity reports, dropped
|
||||||
|
subnets accessed and client accesses
|
||||||
|
|
||||||
|
Version 6 : added padding to requests to prevent amplification attack,
|
||||||
|
changed maximum number of samples in manual list to 16
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PROTO_VERSION_NUMBER 5
|
#define PROTO_VERSION_NUMBER 6
|
||||||
|
|
||||||
/* The oldest protocol version that is compatible enough with
|
/* The oldest protocol versions that are compatible enough with the current
|
||||||
the current version to report a version mismatch */
|
version to report a version mismatch for the server and the client */
|
||||||
#define PROTO_VERSION_MISMATCH_COMPAT 4
|
#define PROTO_VERSION_MISMATCH_COMPAT_SERVER 5
|
||||||
|
#define PROTO_VERSION_MISMATCH_COMPAT_CLIENT 4
|
||||||
|
|
||||||
|
/* The first protocol version using padding in requests */
|
||||||
|
#define PROTO_VERSION_PADDING 6
|
||||||
|
|
||||||
|
/* The maximum length of padding in request packet, currently
|
||||||
|
defined by CLIENT_ACCESSES_BY_INDEX and MANUAL_LIST */
|
||||||
|
#define MAX_PADDING_LENGTH 396
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
@@ -426,8 +426,6 @@ typedef struct {
|
|||||||
REQ_RTCReport rtcreport;
|
REQ_RTCReport rtcreport;
|
||||||
REQ_TrimRTC trimrtc;
|
REQ_TrimRTC trimrtc;
|
||||||
REQ_CycleLogs cyclelogs;
|
REQ_CycleLogs cyclelogs;
|
||||||
REQ_SubnetsAccessed subnets_accessed;
|
|
||||||
REQ_ClientAccesses client_accesses;
|
|
||||||
REQ_ClientAccessesByIndex client_accesses_by_index;
|
REQ_ClientAccessesByIndex client_accesses_by_index;
|
||||||
REQ_ManualList manual_list;
|
REQ_ManualList manual_list;
|
||||||
REQ_ManualDelete manual_delete;
|
REQ_ManualDelete manual_delete;
|
||||||
@@ -437,8 +435,13 @@ typedef struct {
|
|||||||
REQ_ReselectDistance reselect_distance;
|
REQ_ReselectDistance reselect_distance;
|
||||||
} data; /* Command specific parameters */
|
} data; /* Command specific parameters */
|
||||||
|
|
||||||
/* authentication of the packet, there is no hole after the actual data
|
/* The following fields only set the maximum size of the packet.
|
||||||
from the data union, this field only sets the maximum auth size */
|
There are no holes between them and the actual data. */
|
||||||
|
|
||||||
|
/* Padding used to prevent traffic amplification */
|
||||||
|
uint8_t padding[MAX_PADDING_LENGTH];
|
||||||
|
|
||||||
|
/* Authentication data */
|
||||||
uint8_t auth[MAX_HASH_LENGTH];
|
uint8_t auth[MAX_HASH_LENGTH];
|
||||||
|
|
||||||
} CMD_Request;
|
} CMD_Request;
|
||||||
@@ -478,6 +481,7 @@ typedef struct {
|
|||||||
#define STT_BADSUBNET 7
|
#define STT_BADSUBNET 7
|
||||||
#define STT_ACCESSALLOWED 8
|
#define STT_ACCESSALLOWED 8
|
||||||
#define STT_ACCESSDENIED 9
|
#define STT_ACCESSDENIED 9
|
||||||
|
/* Deprecated */
|
||||||
#define STT_NOHOSTACCESS 10
|
#define STT_NOHOSTACCESS 10
|
||||||
#define STT_SOURCEALREADYKNOWN 11
|
#define STT_SOURCEALREADYKNOWN 11
|
||||||
#define STT_TOOMANYSOURCES 12
|
#define STT_TOOMANYSOURCES 12
|
||||||
@@ -582,11 +586,6 @@ typedef struct {
|
|||||||
uint32_t bitmap[8];
|
uint32_t bitmap[8];
|
||||||
} RPY_SubnetsAccessed_Subnet;
|
} RPY_SubnetsAccessed_Subnet;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint32_t n_subnets;
|
|
||||||
RPY_SubnetsAccessed_Subnet subnets[MAX_SUBNETS_ACCESSED];
|
|
||||||
} RPY_SubnetsAccessed;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
IPAddr ip;
|
IPAddr ip;
|
||||||
uint32_t client_hits;
|
uint32_t client_hits;
|
||||||
@@ -598,19 +597,15 @@ typedef struct {
|
|||||||
uint32_t last_cmd_hit_ago;
|
uint32_t last_cmd_hit_ago;
|
||||||
} RPY_ClientAccesses_Client;
|
} RPY_ClientAccesses_Client;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint32_t n_clients;
|
|
||||||
RPY_ClientAccesses_Client clients[MAX_CLIENT_ACCESSES];
|
|
||||||
} RPY_ClientAccesses;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t n_indices; /* how many indices there are in the server's table */
|
uint32_t n_indices; /* how many indices there are in the server's table */
|
||||||
uint32_t next_index; /* the index 1 beyond those processed on this call */
|
uint32_t next_index; /* the index 1 beyond those processed on this call */
|
||||||
uint32_t n_clients; /* the number of valid entries in the following array */
|
uint32_t n_clients; /* the number of valid entries in the following array */
|
||||||
RPY_ClientAccesses_Client clients[MAX_CLIENT_ACCESSES];
|
RPY_ClientAccesses_Client clients[MAX_CLIENT_ACCESSES];
|
||||||
|
int32_t EOR;
|
||||||
} RPY_ClientAccessesByIndex;
|
} RPY_ClientAccessesByIndex;
|
||||||
|
|
||||||
#define MAX_MANUAL_LIST_SAMPLES 32
|
#define MAX_MANUAL_LIST_SAMPLES 16
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Timeval when;
|
Timeval when;
|
||||||
@@ -622,6 +617,7 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t n_samples;
|
uint32_t n_samples;
|
||||||
RPY_ManualListSample samples[MAX_MANUAL_LIST_SAMPLES];
|
RPY_ManualListSample samples[MAX_MANUAL_LIST_SAMPLES];
|
||||||
|
int32_t EOR;
|
||||||
} RPY_ManualList;
|
} RPY_ManualList;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -656,8 +652,6 @@ typedef struct {
|
|||||||
RPY_Tracking tracking;
|
RPY_Tracking tracking;
|
||||||
RPY_Sourcestats sourcestats;
|
RPY_Sourcestats sourcestats;
|
||||||
RPY_Rtc rtc;
|
RPY_Rtc rtc;
|
||||||
RPY_SubnetsAccessed subnets_accessed;
|
|
||||||
RPY_ClientAccesses client_accesses;
|
|
||||||
RPY_ClientAccessesByIndex client_accesses_by_index;
|
RPY_ClientAccessesByIndex client_accesses_by_index;
|
||||||
RPY_ManualList manual_list;
|
RPY_ManualList manual_list;
|
||||||
RPY_Activity activity;
|
RPY_Activity activity;
|
||||||
|
|||||||
@@ -1,38 +1,43 @@
|
|||||||
|
%global chrony_version @@VERSION@@
|
||||||
|
%if 0%(echo %{chrony_version} | grep -q pre && echo 1)
|
||||||
|
%global prerelease %(echo %{chrony_version} | sed 's/.*-//')
|
||||||
|
%endif
|
||||||
Summary: An NTP client/server
|
Summary: An NTP client/server
|
||||||
Name: chrony
|
Name: chrony
|
||||||
Version: @@VERSION@@
|
Version: %(echo %{chrony_version} | sed 's/-.*//')
|
||||||
Release: 1
|
Release: %{!?prerelease:1}%{?prerelease:0.1.%{prerelease}}
|
||||||
Source: chrony-%{version}.tar.gz
|
Source: chrony-%{version}%{?prerelease:-%{prerelease}}.tar.gz
|
||||||
Copyright: GPL
|
License: GPLv2
|
||||||
Group: Applications/Utilities
|
Group: Applications/Utilities
|
||||||
Packager: Richard P. Curnow <rc@rc0.org.uk>
|
|
||||||
BuildRoot: %{_tmppath}/%{name}-%{version}-root-%(id -u -n)
|
BuildRoot: %{_tmppath}/%{name}-%{version}-root-%(id -u -n)
|
||||||
Requires: info
|
Requires: info
|
||||||
|
|
||||||
%description
|
%description
|
||||||
A pair of programs for keeping computer clocks accurate. chronyd is a
|
chrony is a client and server for the Network Time Protocol (NTP).
|
||||||
background (daemon) program and chronyc is a command-line interface to it.
|
This program keeps your computer's clock accurate. It was specially
|
||||||
Time reference sources for chronyd can be RFC1305 NTP servers, human (via
|
designed to support systems with intermittent Internet connections,
|
||||||
keyboard and chronyc), and the computer's real-time clock at boot time (Linux
|
but it also works well in permanently connected environments. It can
|
||||||
only). chronyd can determine the rate at which the computer gains or loses
|
also use hardware reference clocks, the system real-time clock, or
|
||||||
time and compensate for it whilst no external reference is present. chronyd's
|
manual input as time references.
|
||||||
use of NTP servers can be switched on and off (through chronyc) to support
|
|
||||||
computers with dial-up/intermittent access to the Internet. chronyd can also
|
|
||||||
act as an RFC1305-compatible NTP server.
|
|
||||||
|
|
||||||
%prep
|
%prep
|
||||||
%setup
|
%setup -q -n %{name}-%{version}%{?prerelease:-%{prerelease}}
|
||||||
|
|
||||||
%build
|
%build
|
||||||
./configure --prefix=%{_prefix} --mandir=%{_mandir}
|
./configure \
|
||||||
make CC=gcc CFLAGS=-O2 prefix=%{_prefix}
|
--prefix=%{_prefix} \
|
||||||
make chrony.txt prefix=%{_prefix}
|
--bindir=%{_bindir} \
|
||||||
make chrony.info prefix=%{_prefix}
|
--sbindir=%{_sbindir} \
|
||||||
|
--infodir=%{_infodir} \
|
||||||
|
--mandir=%{_mandir}
|
||||||
|
make
|
||||||
|
make chrony.txt
|
||||||
|
make chrony.info
|
||||||
|
|
||||||
%install
|
%install
|
||||||
rm -rf $RPM_BUILD_ROOT
|
rm -rf $RPM_BUILD_ROOT
|
||||||
cd $RPM_BUILD_DIR/chrony-%{version}
|
make install DESTDIR=$RPM_BUILD_ROOT
|
||||||
make install DESTDIR=$RPM_BUILD_ROOT prefix=%{_prefix}
|
rm -rf $RPM_BUILD_ROOT%{_docdir}
|
||||||
mkdir -p $RPM_BUILD_ROOT%{_infodir}
|
mkdir -p $RPM_BUILD_ROOT%{_infodir}
|
||||||
cp chrony.info* $RPM_BUILD_ROOT%{_infodir}
|
cp chrony.info* $RPM_BUILD_ROOT%{_infodir}
|
||||||
|
|
||||||
@@ -47,6 +52,6 @@ cp chrony.info* $RPM_BUILD_ROOT%{_infodir}
|
|||||||
%doc README
|
%doc README
|
||||||
%doc chrony.txt
|
%doc chrony.txt
|
||||||
%doc COPYING
|
%doc COPYING
|
||||||
%doc examples/chrony.conf.example
|
%doc examples/chrony.conf.example*
|
||||||
%doc examples/chrony.keys.example
|
%doc examples/chrony.keys.example
|
||||||
|
|
||||||
|
|||||||
@@ -125,9 +125,7 @@ different quirks in its behaviour.
|
|||||||
|
|
||||||
The software is known to work in the following environments:
|
The software is known to work in the following environments:
|
||||||
@itemize @bullet
|
@itemize @bullet
|
||||||
@item Linux on i386, x86_64 and PowerPC architectures. The software is known
|
@item Linux 2.2 and newer
|
||||||
to work on Linux 2.0.x and newer. Prior to 2.0.31, the real time clock can't
|
|
||||||
be used.
|
|
||||||
|
|
||||||
@item NetBSD
|
@item NetBSD
|
||||||
@item BSD/386
|
@item BSD/386
|
||||||
@@ -826,18 +824,10 @@ compiled into the kernel). An estimate is made of the RTC error at a
|
|||||||
particular RTC second, and the rate at which the RTC gains or loses time
|
particular RTC second, and the rate at which the RTC gains or loses time
|
||||||
relative to true time.
|
relative to true time.
|
||||||
|
|
||||||
The RTC is fully supported in 2.2, 2.4 and 2.6 kernels.
|
On 2.6 and later kernels, if your motherboard has a HPET, you need to enable the
|
||||||
|
|
||||||
On 2.6 kernels, if your motherboard has a HPET, you need to enable the
|
|
||||||
@samp{HPET_EMULATE_RTC} option in your kernel configuration. Otherwise, chrony
|
@samp{HPET_EMULATE_RTC} option in your kernel configuration. Otherwise, chrony
|
||||||
will not be able to interact with the RTC device and will give up using it.
|
will not be able to interact with the RTC device and will give up using it.
|
||||||
|
|
||||||
For kernels in the 2.0 series prior to 2.0.32, the kernel was set up to
|
|
||||||
trim the RTC every 11 minutes. This would be disasterous for
|
|
||||||
@code{chronyd} -- there is no reliable way of synchronising with this
|
|
||||||
trimming. For this reason, @code{chronyd} only supports the RTC in 2.0
|
|
||||||
kernels from v2.0.32 onwards.
|
|
||||||
|
|
||||||
When the computer is powered down, the measurement histories for all the
|
When the computer is powered down, the measurement histories for all the
|
||||||
NTP servers are saved to files (if the @code{dumponexit} directive is
|
NTP servers are saved to files (if the @code{dumponexit} directive is
|
||||||
specified in the configuration file), and the RTC tracking information
|
specified in the configuration file), and the RTC tracking information
|
||||||
@@ -2637,8 +2627,7 @@ conditions apply:
|
|||||||
|
|
||||||
@enumerate 1
|
@enumerate 1
|
||||||
@item
|
@item
|
||||||
You are running Linux version 2.2.x or 2.4.x (for any value of x), or v2.0.x
|
You are running Linux version 2.2.x or later.
|
||||||
with x>=32.
|
|
||||||
|
|
||||||
@item
|
@item
|
||||||
You have compiled the kernel with extended real-time clock support
|
You have compiled the kernel with extended real-time clock support
|
||||||
|
|||||||
237
client.c
237
client.c
@@ -1242,6 +1242,7 @@ static unsigned long token = 0;
|
|||||||
|
|
||||||
static int max_retries = 2;
|
static int max_retries = 2;
|
||||||
static int initial_timeout = 1000;
|
static int initial_timeout = 1000;
|
||||||
|
static int proto_version = PROTO_VERSION_NUMBER;
|
||||||
|
|
||||||
/* This is the core protocol module. Complete particular fields in
|
/* This is the core protocol module. Complete particular fields in
|
||||||
the outgoing packet, send it, wait for a response, handle retries,
|
the outgoing packet, send it, wait for a response, handle retries,
|
||||||
@@ -1260,13 +1261,13 @@ submit_request(CMD_Request *request, CMD_Reply *reply, int *reply_auth_ok)
|
|||||||
int read_length;
|
int read_length;
|
||||||
int expected_length;
|
int expected_length;
|
||||||
int command_length;
|
int command_length;
|
||||||
|
int padding_length;
|
||||||
int auth_length;
|
int auth_length;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
int timeout;
|
int timeout;
|
||||||
int n_attempts;
|
int n_attempts;
|
||||||
fd_set rdfd, wrfd, exfd;
|
fd_set rdfd, wrfd, exfd;
|
||||||
|
|
||||||
request->version = PROTO_VERSION_NUMBER;
|
|
||||||
request->pkt_type = PKT_TYPE_CMD_REQUEST;
|
request->pkt_type = PKT_TYPE_CMD_REQUEST;
|
||||||
request->res1 = 0;
|
request->res1 = 0;
|
||||||
request->res2 = 0;
|
request->res2 = 0;
|
||||||
@@ -1281,6 +1282,14 @@ submit_request(CMD_Request *request, CMD_Reply *reply, int *reply_auth_ok)
|
|||||||
n_attempts = 0;
|
n_attempts = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
request->version = proto_version;
|
||||||
|
command_length = PKL_CommandLength(request);
|
||||||
|
padding_length = PKL_CommandPaddingLength(request);
|
||||||
|
assert(command_length > 0 && command_length > padding_length);
|
||||||
|
|
||||||
|
/* Zero the padding to avoid sending uninitialized data. This needs to be
|
||||||
|
done before generating auth data as it includes the padding. */
|
||||||
|
memset(((char *)request) + command_length - padding_length, 0, padding_length);
|
||||||
|
|
||||||
/* Decide whether to authenticate */
|
/* Decide whether to authenticate */
|
||||||
if (password) {
|
if (password) {
|
||||||
@@ -1294,9 +1303,6 @@ submit_request(CMD_Request *request, CMD_Reply *reply, int *reply_auth_ok)
|
|||||||
auth_length = 0;
|
auth_length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
command_length = PKL_CommandLength(request);
|
|
||||||
assert(command_length > 0);
|
|
||||||
|
|
||||||
/* add empty MD5 auth so older servers will not drop the request
|
/* add empty MD5 auth so older servers will not drop the request
|
||||||
due to bad length */
|
due to bad length */
|
||||||
if (!auth_length) {
|
if (!auth_length) {
|
||||||
@@ -1371,7 +1377,8 @@ submit_request(CMD_Request *request, CMD_Reply *reply, int *reply_auth_ok)
|
|||||||
read_length = recvfrom_status;
|
read_length = recvfrom_status;
|
||||||
expected_length = PKL_ReplyLength(reply);
|
expected_length = PKL_ReplyLength(reply);
|
||||||
|
|
||||||
bad_length = (read_length < expected_length);
|
bad_length = (read_length < expected_length ||
|
||||||
|
expected_length < offsetof(CMD_Reply, data));
|
||||||
bad_sender = (where_from.u.sa_family != his_addr.u.sa_family ||
|
bad_sender = (where_from.u.sa_family != his_addr.u.sa_family ||
|
||||||
(where_from.u.sa_family == AF_INET &&
|
(where_from.u.sa_family == AF_INET &&
|
||||||
(where_from.in4.sin_addr.s_addr != his_addr.in4.sin_addr.s_addr ||
|
(where_from.in4.sin_addr.s_addr != his_addr.in4.sin_addr.s_addr ||
|
||||||
@@ -1398,8 +1405,8 @@ submit_request(CMD_Request *request, CMD_Reply *reply, int *reply_auth_ok)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bad_header = ((reply->version != PROTO_VERSION_NUMBER &&
|
bad_header = ((reply->version != proto_version &&
|
||||||
!(reply->version >= PROTO_VERSION_MISMATCH_COMPAT &&
|
!(reply->version >= PROTO_VERSION_MISMATCH_COMPAT_CLIENT &&
|
||||||
ntohs(reply->status) == STT_BADPKTVERSION)) ||
|
ntohs(reply->status) == STT_BADPKTVERSION)) ||
|
||||||
(reply->pkt_type != PKT_TYPE_CMD_REPLY) ||
|
(reply->pkt_type != PKT_TYPE_CMD_REPLY) ||
|
||||||
(reply->res1 != 0) ||
|
(reply->res1 != 0) ||
|
||||||
@@ -1414,6 +1421,19 @@ submit_request(CMD_Request *request, CMD_Reply *reply, int *reply_auth_ok)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if PROTO_VERSION_NUMBER == 6
|
||||||
|
/* Protocol version 5 is similar to 6 except there is no padding.
|
||||||
|
If a version 5 reply with STT_BADPKTVERSION is received,
|
||||||
|
switch our version and try again. */
|
||||||
|
if (proto_version == PROTO_VERSION_NUMBER &&
|
||||||
|
reply->version == PROTO_VERSION_NUMBER - 1) {
|
||||||
|
proto_version = PROTO_VERSION_NUMBER - 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#error unknown compatibility with PROTO_VERSION - 1
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Good packet received, print out results */
|
/* Good packet received, print out results */
|
||||||
#if 0
|
#if 0
|
||||||
printf("Reply cmd=%d reply=%d stat=%d num=%d tot=%d seq=%d utok=%08lx tok=%d\n",
|
printf("Reply cmd=%d reply=%d stat=%d num=%d tot=%d seq=%d utok=%08lx tok=%d\n",
|
||||||
@@ -1990,207 +2010,6 @@ process_cmd_rtcreport(char *line)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
/* This is a previous attempt at implementing the clients command. It
|
|
||||||
could be re-instated sometime as a way of looking at all clients in a
|
|
||||||
particular subnet. The problem with it is that is requires at least 5
|
|
||||||
round trips to the server even if the server only has one client to
|
|
||||||
report. */
|
|
||||||
|
|
||||||
typedef struct XSubnetToDo {
|
|
||||||
struct XSubnetToDo *next;
|
|
||||||
unsigned long ip;
|
|
||||||
unsigned long bits;
|
|
||||||
} SubnetToDo;
|
|
||||||
|
|
||||||
static void
|
|
||||||
process_cmd_clients(char *line)
|
|
||||||
{
|
|
||||||
CMD_Request request;
|
|
||||||
CMD_Reply reply;
|
|
||||||
SubnetToDo *head, *todo, *tail, *p, *next_node, *new_node;
|
|
||||||
int i, j, nets_looked_up, clients_looked_up;
|
|
||||||
int word;
|
|
||||||
unsigned long mask;
|
|
||||||
unsigned long ip, bits;
|
|
||||||
unsigned long client_hits;
|
|
||||||
unsigned long peer_hits;
|
|
||||||
unsigned long cmd_hits_auth;
|
|
||||||
unsigned long cmd_hits_normal;
|
|
||||||
unsigned long cmd_hits_bad;
|
|
||||||
unsigned long last_ntp_hit_ago;
|
|
||||||
unsigned long last_cmd_hit_ago;
|
|
||||||
char hostname_buf[50];
|
|
||||||
|
|
||||||
int n_replies;
|
|
||||||
|
|
||||||
head = todo = MallocNew(SubnetToDo);
|
|
||||||
todo->next = NULL;
|
|
||||||
/* Set up initial query = root subnet */
|
|
||||||
todo->ip = 0;
|
|
||||||
todo->bits = 0;
|
|
||||||
tail = todo;
|
|
||||||
|
|
||||||
do {
|
|
||||||
|
|
||||||
request.command = htons(REQ_SUBNETS_ACCESSED);
|
|
||||||
/* Build list of subnets to examine */
|
|
||||||
i=0;
|
|
||||||
p=todo;
|
|
||||||
while((i < MAX_SUBNETS_ACCESSED) &&
|
|
||||||
p &&
|
|
||||||
(p->bits < 32)) {
|
|
||||||
|
|
||||||
request.data.subnets_accessed.subnets[i].ip = htonl(p->ip);
|
|
||||||
request.data.subnets_accessed.subnets[i].bits_specd = htonl(p->bits);
|
|
||||||
p = p->next;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
nets_looked_up = i;
|
|
||||||
|
|
||||||
if (nets_looked_up == 0) {
|
|
||||||
/* No subnets need examining */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
request.data.subnets_accessed.n_subnets = htonl(nets_looked_up);
|
|
||||||
|
|
||||||
if (request_reply(&request, &reply, RPY_SUBNETS_ACCESSED, 0)) {
|
|
||||||
n_replies = ntohl(reply.data.subnets_accessed.n_subnets);
|
|
||||||
for (j=0; j<n_replies; j++) {
|
|
||||||
ip = ntohl(reply.data.subnets_accessed.subnets[j].ip);
|
|
||||||
bits = ntohl(reply.data.subnets_accessed.subnets[j].bits_specd);
|
|
||||||
for (i=0; i<256; i++) {
|
|
||||||
word = i/32;
|
|
||||||
mask = 1UL << (i%32);
|
|
||||||
if (ntohl(reply.data.subnets_accessed.subnets[j].bitmap[word]) & mask) {
|
|
||||||
/* Add this subnet to the todo list */
|
|
||||||
new_node = MallocNew(SubnetToDo);
|
|
||||||
new_node->next = NULL;
|
|
||||||
new_node->bits = bits + 8;
|
|
||||||
new_node->ip = ip | (i << (24 - bits));
|
|
||||||
tail->next = new_node;
|
|
||||||
tail = new_node;
|
|
||||||
#if 0
|
|
||||||
printf("%08lx %2d %3d %08lx\n", ip, bits, i, new_node->ip);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Skip the todo pointer forwards by the number of nets looked
|
|
||||||
up. Can't do this earlier, because we might have to point
|
|
||||||
at the next layer of subnets that have only just been
|
|
||||||
concatenated to the linked list. */
|
|
||||||
for (i=0; i<nets_looked_up; i++) {
|
|
||||||
todo = todo->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} while (1); /* keep going until all subnets have been expanded,
|
|
||||||
down to single nodes */
|
|
||||||
|
|
||||||
/* Now the todo list consists of client records */
|
|
||||||
request.command = htons(REQ_CLIENT_ACCESSES);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
printf("%d %d\n", sizeof (RPY_ClientAccesses_Client), offsetof(CMD_Reply, data.client_accesses.clients));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
printf("Hostname Client Peer CmdAuth CmdNorm CmdBad LstN LstC\n"
|
|
||||||
"========================= ====== ====== ====== ====== ====== ==== ====\n");
|
|
||||||
|
|
||||||
do {
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
p = todo;
|
|
||||||
while ((i < MAX_CLIENT_ACCESSES) &&
|
|
||||||
p) {
|
|
||||||
|
|
||||||
request.data.client_accesses.client_ips[i] = htonl(p->ip);
|
|
||||||
p = p->next;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
clients_looked_up = i;
|
|
||||||
|
|
||||||
if (clients_looked_up == 0) {
|
|
||||||
/* No more clients to do */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
request.data.client_accesses.n_clients = htonl(clients_looked_up);
|
|
||||||
|
|
||||||
if (request_reply(&request, &reply, RPY_CLIENT_ACCESSES, 0)) {
|
|
||||||
n_replies = ntohl(reply.data.client_accesses.n_clients);
|
|
||||||
for (j=0; j<n_replies; j++) {
|
|
||||||
ip = ntohl(reply.data.client_accesses.clients[j].ip);
|
|
||||||
if (ip != 0UL) {
|
|
||||||
/* ip == 0 implies that the node could not be found in
|
|
||||||
the daemon's tables; we shouldn't ever generate this
|
|
||||||
case, but ignore it if we do. (In future there might
|
|
||||||
be a protocol to reset the client logging; if another
|
|
||||||
administrator runs that while we're doing the clients
|
|
||||||
command, there will be a race condition that could
|
|
||||||
cause this). */
|
|
||||||
|
|
||||||
client_hits = ntohl(reply.data.client_accesses.clients[j].client_hits);
|
|
||||||
peer_hits = ntohl(reply.data.client_accesses.clients[j].peer_hits);
|
|
||||||
cmd_hits_auth = ntohl(reply.data.client_accesses.clients[j].cmd_hits_auth);
|
|
||||||
cmd_hits_normal = ntohl(reply.data.client_accesses.clients[j].cmd_hits_normal);
|
|
||||||
cmd_hits_bad = ntohl(reply.data.client_accesses.clients[j].cmd_hits_bad);
|
|
||||||
last_ntp_hit_ago = ntohl(reply.data.client_accesses.clients[j].last_ntp_hit_ago);
|
|
||||||
last_cmd_hit_ago = ntohl(reply.data.client_accesses.clients[j].last_cmd_hit_ago);
|
|
||||||
|
|
||||||
if (no_dns) {
|
|
||||||
snprintf(hostname_buf, sizeof(hostname_buf),
|
|
||||||
"%s", UTI_IPToDottedQuad(ip));
|
|
||||||
} else {
|
|
||||||
DNS_IPAddress2Name(ip, hostname_buf, sizeof(hostname_buf));
|
|
||||||
hostname_buf[25] = 0;
|
|
||||||
}
|
|
||||||
printf("%-25s %6d %6d %6d %6d %6d ",
|
|
||||||
hostname_buf,
|
|
||||||
client_hits, peer_hits,
|
|
||||||
cmd_hits_auth, cmd_hits_normal, cmd_hits_bad);
|
|
||||||
print_seconds(last_ntp_hit_ago);
|
|
||||||
printf(" ");
|
|
||||||
print_seconds(last_cmd_hit_ago);
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Skip the todo pointer forwards by the number of nets looked
|
|
||||||
up. Can't do this earlier, because we might have to point
|
|
||||||
at the next layer of subnets that have only just been
|
|
||||||
concatenated to the linked list. */
|
|
||||||
for (i=0; i<clients_looked_up; i++) {
|
|
||||||
todo = todo->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} while (1);
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
for (p = head; p; ) {
|
|
||||||
next_node = p->next;
|
|
||||||
Free(p);
|
|
||||||
p = next_node;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* New implementation of clients command */
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
process_cmd_clients(char *line)
|
process_cmd_clients(char *line)
|
||||||
{
|
{
|
||||||
@@ -2856,7 +2675,7 @@ static void
|
|||||||
display_gpl(void)
|
display_gpl(void)
|
||||||
{
|
{
|
||||||
printf("chrony version %s\n"
|
printf("chrony version %s\n"
|
||||||
"Copyright (C) 1997-2003, 2007, 2009-2012 Richard P. Curnow and others\n"
|
"Copyright (C) 1997-2003, 2007, 2009-2013 Richard P. Curnow and others\n"
|
||||||
"chrony comes with ABSOLUTELY NO WARRANTY. This is free software, and\n"
|
"chrony comes with ABSOLUTELY NO WARRANTY. This is free software, and\n"
|
||||||
"you are welcome to redistribute it under certain conditions. See the\n"
|
"you are welcome to redistribute it under certain conditions. See the\n"
|
||||||
"GNU General Public License version 2 for details.\n\n",
|
"GNU General Public License version 2 for details.\n\n",
|
||||||
|
|||||||
223
cmdmon.c
223
cmdmon.c
@@ -248,8 +248,10 @@ prepare_socket(int family)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (bind(sock_fd, &my_addr.u, my_addr_len) < 0) {
|
if (bind(sock_fd, &my_addr.u, my_addr_len) < 0) {
|
||||||
LOG_FATAL(LOGF_CmdMon, "Could not bind %s command socket : %s",
|
LOG(LOGS_ERR, LOGF_CmdMon, "Could not bind %s command socket : %s",
|
||||||
family == AF_INET ? "IPv4" : "IPv6", strerror(errno));
|
family == AF_INET ? "IPv4" : "IPv6", strerror(errno));
|
||||||
|
close(sock_fd);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Register handler for read events on the socket */
|
/* Register handler for read events on the socket */
|
||||||
@@ -263,11 +265,25 @@ prepare_socket(int family)
|
|||||||
void
|
void
|
||||||
CAM_Initialise(int family)
|
CAM_Initialise(int family)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
assert(!initialised);
|
assert(!initialised);
|
||||||
initialised = 1;
|
initialised = 1;
|
||||||
|
|
||||||
assert(sizeof (permissions) / sizeof (permissions[0]) == N_REQUEST_TYPES);
|
assert(sizeof (permissions) / sizeof (permissions[0]) == N_REQUEST_TYPES);
|
||||||
|
|
||||||
|
for (i = 0; i < N_REQUEST_TYPES; i++) {
|
||||||
|
CMD_Request r;
|
||||||
|
int command_length, padding_length;
|
||||||
|
|
||||||
|
r.version = PROTO_VERSION_NUMBER;
|
||||||
|
r.command = htons(i);
|
||||||
|
command_length = PKL_CommandLength(&r);
|
||||||
|
padding_length = PKL_CommandPaddingLength(&r);
|
||||||
|
assert(padding_length <= MAX_PADDING_LENGTH && padding_length <= command_length);
|
||||||
|
assert(command_length == 0 || command_length >= offsetof(CMD_Reply, data));
|
||||||
|
}
|
||||||
|
|
||||||
utoken = (unsigned long) time(NULL);
|
utoken = (unsigned long) time(NULL);
|
||||||
|
|
||||||
issued_tokens = returned_tokens = issue_pointer = 0;
|
issued_tokens = returned_tokens = issue_pointer = 0;
|
||||||
@@ -1477,107 +1493,6 @@ handle_cyclelogs(CMD_Request *rx_message, CMD_Reply *tx_message)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
#define FLIPL(X) ((X) = htonl(X))
|
|
||||||
|
|
||||||
static void
|
|
||||||
handle_subnets_accessed(CMD_Request *rx_message, CMD_Reply *tx_message)
|
|
||||||
{
|
|
||||||
int i, j;
|
|
||||||
unsigned long ns, bits_specd;
|
|
||||||
IPAddr ip;
|
|
||||||
CLG_Status result;
|
|
||||||
|
|
||||||
ns = ntohl(rx_message->data.subnets_accessed.n_subnets);
|
|
||||||
tx_message->status = htons(STT_SUCCESS);
|
|
||||||
tx_message->reply = htons(RPY_SUBNETS_ACCESSED);
|
|
||||||
tx_message->data.subnets_accessed.n_subnets = htonl(ns);
|
|
||||||
|
|
||||||
for (i=0; i<ns; i++) {
|
|
||||||
UTI_IPNetworkToHost(&rx_message->data.subnets_accessed.subnets[i].ip, &ip);
|
|
||||||
bits_specd = ntohl(rx_message->data.subnets_accessed.subnets[i].bits_specd);
|
|
||||||
|
|
||||||
UTI_IPHostToNetwork(&ip, &tx_message->data.subnets_accessed.subnets[i].ip);
|
|
||||||
tx_message->data.subnets_accessed.subnets[i].bits_specd = htonl(bits_specd);
|
|
||||||
|
|
||||||
result = CLG_GetSubnetBitmap(&ip, bits_specd, tx_message->data.subnets_accessed.subnets[i].bitmap);
|
|
||||||
switch (result) {
|
|
||||||
case CLG_SUCCESS:
|
|
||||||
case CLG_EMPTYSUBNET:
|
|
||||||
/* Flip endianness of each 4 byte word. Don't care if subnet
|
|
||||||
is empty - just return an all-zero bitmap. */
|
|
||||||
for (j=0; j<8; j++) {
|
|
||||||
FLIPL(tx_message->data.subnets_accessed.subnets[i].bitmap[j]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CLG_BADSUBNET:
|
|
||||||
tx_message->status = htons(STT_BADSUBNET);
|
|
||||||
return;
|
|
||||||
case CLG_INACTIVE:
|
|
||||||
tx_message->status = htons(STT_INACTIVE);
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
static void
|
|
||||||
handle_client_accesses(CMD_Request *rx_message, CMD_Reply *tx_message)
|
|
||||||
{
|
|
||||||
CLG_Status result;
|
|
||||||
RPT_ClientAccess_Report report;
|
|
||||||
unsigned long nc;
|
|
||||||
IPAddr ip;
|
|
||||||
int i;
|
|
||||||
struct timeval now;
|
|
||||||
|
|
||||||
LCL_ReadCookedTime(&now, NULL);
|
|
||||||
|
|
||||||
nc = ntohl(rx_message->data.client_accesses.n_clients);
|
|
||||||
tx_message->status = htons(STT_SUCCESS);
|
|
||||||
tx_message->reply = htons(RPY_CLIENT_ACCESSES);
|
|
||||||
tx_message->data.client_accesses.n_clients = htonl(nc);
|
|
||||||
|
|
||||||
printf("%d %d\n", (int)sizeof(RPY_ClientAccesses_Client), (int)offsetof(CMD_Reply, data.client_accesses.clients));
|
|
||||||
|
|
||||||
for (i=0; i<nc; i++) {
|
|
||||||
UTI_IPNetworkToHost(&rx_message->data.client_accesses.client_ips[i], &ip);
|
|
||||||
UTI_IPHostToNetwork(&ip, &tx_message->data.client_accesses.clients[i].ip);
|
|
||||||
|
|
||||||
result = CLG_GetClientAccessReportByIP(&ip, &report, now.tv_sec);
|
|
||||||
switch (result) {
|
|
||||||
case CLG_SUCCESS:
|
|
||||||
tx_message->data.client_accesses.clients[i].client_hits = htonl(report.client_hits);
|
|
||||||
tx_message->data.client_accesses.clients[i].peer_hits = htonl(report.peer_hits);
|
|
||||||
tx_message->data.client_accesses.clients[i].cmd_hits_auth = htonl(report.cmd_hits_auth);
|
|
||||||
tx_message->data.client_accesses.clients[i].cmd_hits_normal = htonl(report.cmd_hits_normal);
|
|
||||||
tx_message->data.client_accesses.clients[i].cmd_hits_bad = htonl(report.cmd_hits_bad);
|
|
||||||
tx_message->data.client_accesses.clients[i].last_ntp_hit_ago = htonl(report.last_ntp_hit_ago);
|
|
||||||
tx_message->data.client_accesses.clients[i].last_cmd_hit_ago = htonl(report.last_cmd_hit_ago);
|
|
||||||
printf("%s %lu %lu %lu %lu %lu %lu %lu\n", UTI_IPToString(&ip), report.client_hits, report.peer_hits, report.cmd_hits_auth, report.cmd_hits_normal, report.cmd_hits_bad, report.last_ntp_hit_ago, report.last_cmd_hit_ago);
|
|
||||||
break;
|
|
||||||
case CLG_EMPTYSUBNET:
|
|
||||||
/* Signal back to the client that this single client address
|
|
||||||
was unknown */
|
|
||||||
ip.family = IPADDR_UNSPEC;
|
|
||||||
UTI_IPHostToNetwork(&ip, &tx_message->data.client_accesses.clients[i].ip);
|
|
||||||
break;
|
|
||||||
case CLG_INACTIVE:
|
|
||||||
tx_message->status = htons(STT_INACTIVE);
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_client_accesses_by_index(CMD_Request *rx_message, CMD_Reply *tx_message)
|
handle_client_accesses_by_index(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||||
{
|
{
|
||||||
@@ -1779,29 +1694,10 @@ read_from_cmd_socket(void *anything)
|
|||||||
}
|
}
|
||||||
|
|
||||||
read_length = status;
|
read_length = status;
|
||||||
expected_length = PKL_CommandLength(&rx_message);
|
|
||||||
rx_command = ntohs(rx_message.command);
|
|
||||||
|
|
||||||
LCL_ReadRawTime(&now);
|
LCL_ReadRawTime(&now);
|
||||||
LCL_CookTime(&now, &cooked_now, NULL);
|
LCL_CookTime(&now, &cooked_now, NULL);
|
||||||
|
|
||||||
tx_message.version = PROTO_VERSION_NUMBER;
|
|
||||||
tx_message.pkt_type = PKT_TYPE_CMD_REPLY;
|
|
||||||
tx_message.res1 = 0;
|
|
||||||
tx_message.res2 = 0;
|
|
||||||
tx_message.command = rx_message.command;
|
|
||||||
tx_message.sequence = rx_message.sequence;
|
|
||||||
tx_message.reply = htons(RPY_NULL);
|
|
||||||
tx_message.number = htons(1);
|
|
||||||
tx_message.total = htons(1);
|
|
||||||
tx_message.pad1 = 0;
|
|
||||||
tx_message.utoken = htonl(utoken);
|
|
||||||
/* Set this to a default (invalid) value. This protects against the
|
|
||||||
token field being set to an arbitrary value if we reject the
|
|
||||||
message, e.g. due to the host failing the access check. */
|
|
||||||
tx_message.token = htonl(0xffffffffUL);
|
|
||||||
memset(&tx_message.auth, 0, sizeof(tx_message.auth));
|
|
||||||
|
|
||||||
switch (where_from.u.sa_family) {
|
switch (where_from.u.sa_family) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
remote_ip.family = IPADDR_INET4;
|
remote_ip.family = IPADDR_INET4;
|
||||||
@@ -1826,34 +1722,63 @@ read_from_cmd_socket(void *anything)
|
|||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
allowed = ADF_IsAllowed(access_auth_table, &remote_ip) || localhost;
|
if (!(localhost || ADF_IsAllowed(access_auth_table, &remote_ip))) {
|
||||||
|
/* The client is not allowed access, so don't waste any more time
|
||||||
|
on him. Note that localhost is always allowed access
|
||||||
|
regardless of the defined access rules - otherwise, we could
|
||||||
|
shut ourselves out completely! */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (read_length < offsetof(CMD_Request, data) ||
|
/* Message size sanity check */
|
||||||
|
if (read_length >= offsetof(CMD_Request, data)) {
|
||||||
|
expected_length = PKL_CommandLength(&rx_message);
|
||||||
|
} else {
|
||||||
|
expected_length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expected_length < offsetof(CMD_Request, data) ||
|
||||||
|
read_length < offsetof(CMD_Reply, data) ||
|
||||||
rx_message.pkt_type != PKT_TYPE_CMD_REQUEST ||
|
rx_message.pkt_type != PKT_TYPE_CMD_REQUEST ||
|
||||||
rx_message.res1 != 0 ||
|
rx_message.res1 != 0 ||
|
||||||
rx_message.res2 != 0) {
|
rx_message.res2 != 0) {
|
||||||
|
|
||||||
/* We don't know how to process anything like this */
|
/* We don't know how to process anything like this */
|
||||||
if (allowed)
|
CLG_LogCommandAccess(&remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec);
|
||||||
CLG_LogCommandAccess(&remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rx_command = ntohs(rx_message.command);
|
||||||
|
|
||||||
|
tx_message.version = PROTO_VERSION_NUMBER;
|
||||||
|
tx_message.pkt_type = PKT_TYPE_CMD_REPLY;
|
||||||
|
tx_message.res1 = 0;
|
||||||
|
tx_message.res2 = 0;
|
||||||
|
tx_message.command = rx_message.command;
|
||||||
|
tx_message.sequence = rx_message.sequence;
|
||||||
|
tx_message.reply = htons(RPY_NULL);
|
||||||
|
tx_message.number = htons(1);
|
||||||
|
tx_message.total = htons(1);
|
||||||
|
tx_message.pad1 = 0;
|
||||||
|
tx_message.utoken = htonl(utoken);
|
||||||
|
/* Set this to a default (invalid) value. This protects against the
|
||||||
|
token field being set to an arbitrary value if we reject the
|
||||||
|
message, e.g. due to the host failing the access check. */
|
||||||
|
tx_message.token = htonl(0xffffffffUL);
|
||||||
|
memset(&tx_message.auth, 0, sizeof(tx_message.auth));
|
||||||
|
|
||||||
if (rx_message.version != PROTO_VERSION_NUMBER) {
|
if (rx_message.version != PROTO_VERSION_NUMBER) {
|
||||||
tx_message.status = htons(STT_NOHOSTACCESS);
|
tx_message.status = htons(STT_NOHOSTACCESS);
|
||||||
if (!LOG_RateLimited()) {
|
if (!LOG_RateLimited()) {
|
||||||
LOG(LOGS_WARN, LOGF_CmdMon, "Read command packet with protocol version %d (expected %d) from %s:%hu", rx_message.version, PROTO_VERSION_NUMBER, UTI_IPToString(&remote_ip), remote_port);
|
LOG(LOGS_WARN, LOGF_CmdMon, "Read command packet with protocol version %d (expected %d) from %s:%hu", rx_message.version, PROTO_VERSION_NUMBER, UTI_IPToString(&remote_ip), remote_port);
|
||||||
}
|
}
|
||||||
if (allowed)
|
|
||||||
CLG_LogCommandAccess(&remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec);
|
|
||||||
|
|
||||||
if (rx_message.version >= PROTO_VERSION_MISMATCH_COMPAT) {
|
CLG_LogCommandAccess(&remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec);
|
||||||
|
|
||||||
|
if (rx_message.version >= PROTO_VERSION_MISMATCH_COMPAT_SERVER) {
|
||||||
tx_message.status = htons(STT_BADPKTVERSION);
|
tx_message.status = htons(STT_BADPKTVERSION);
|
||||||
/* add empty MD5 auth so older clients will not drop
|
transmit_reply(&tx_message, &where_from, 0);
|
||||||
the reply due to bad length */
|
|
||||||
memset(((char *)&tx_message) + PKL_ReplyLength(&tx_message), 0, 16);
|
|
||||||
transmit_reply(&tx_message, &where_from, 16);
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1862,8 +1787,8 @@ read_from_cmd_socket(void *anything)
|
|||||||
if (!LOG_RateLimited()) {
|
if (!LOG_RateLimited()) {
|
||||||
LOG(LOGS_WARN, LOGF_CmdMon, "Read command packet with invalid command %d from %s:%hu", rx_command, UTI_IPToString(&remote_ip), remote_port);
|
LOG(LOGS_WARN, LOGF_CmdMon, "Read command packet with invalid command %d from %s:%hu", rx_command, UTI_IPToString(&remote_ip), remote_port);
|
||||||
}
|
}
|
||||||
if (allowed)
|
|
||||||
CLG_LogCommandAccess(&remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec);
|
CLG_LogCommandAccess(&remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec);
|
||||||
|
|
||||||
tx_message.status = htons(STT_INVALID);
|
tx_message.status = htons(STT_INVALID);
|
||||||
transmit_reply(&tx_message, &where_from, 0);
|
transmit_reply(&tx_message, &where_from, 0);
|
||||||
@@ -1874,32 +1799,14 @@ read_from_cmd_socket(void *anything)
|
|||||||
if (!LOG_RateLimited()) {
|
if (!LOG_RateLimited()) {
|
||||||
LOG(LOGS_WARN, LOGF_CmdMon, "Read incorrectly sized command packet from %s:%hu", UTI_IPToString(&remote_ip), remote_port);
|
LOG(LOGS_WARN, LOGF_CmdMon, "Read incorrectly sized command packet from %s:%hu", UTI_IPToString(&remote_ip), remote_port);
|
||||||
}
|
}
|
||||||
if (allowed)
|
|
||||||
CLG_LogCommandAccess(&remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec);
|
CLG_LogCommandAccess(&remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec);
|
||||||
|
|
||||||
tx_message.status = htons(STT_BADPKTLENGTH);
|
tx_message.status = htons(STT_BADPKTLENGTH);
|
||||||
transmit_reply(&tx_message, &where_from, 0);
|
transmit_reply(&tx_message, &where_from, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!allowed) {
|
|
||||||
/* The client is not allowed access, so don't waste any more time
|
|
||||||
on him. Note that localhost is always allowed access
|
|
||||||
regardless of the defined access rules - otherwise, we could
|
|
||||||
shut ourselves out completely! */
|
|
||||||
|
|
||||||
if (!LOG_RateLimited()) {
|
|
||||||
LOG(LOGS_WARN, LOGF_CmdMon, "Command packet received from unauthorised host %s port %d",
|
|
||||||
UTI_IPToString(&remote_ip),
|
|
||||||
remote_port);
|
|
||||||
}
|
|
||||||
|
|
||||||
tx_message.status = htons(STT_NOHOSTACCESS);
|
|
||||||
transmit_reply(&tx_message, &where_from, 0);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* OK, we have a valid message. Now dispatch on message type and process it. */
|
/* OK, we have a valid message. Now dispatch on message type and process it. */
|
||||||
|
|
||||||
/* Do authentication stuff and command tokens here. Well-behaved
|
/* Do authentication stuff and command tokens here. Well-behaved
|
||||||
@@ -2231,14 +2138,6 @@ read_from_cmd_socket(void *anything)
|
|||||||
handle_cyclelogs(&rx_message, &tx_message);
|
handle_cyclelogs(&rx_message, &tx_message);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case REQ_SUBNETS_ACCESSED:
|
|
||||||
handle_subnets_accessed(&rx_message, &tx_message);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case REQ_CLIENT_ACCESSES:
|
|
||||||
handle_client_accesses(&rx_message, &tx_message);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case REQ_CLIENT_ACCESSES_BY_INDEX:
|
case REQ_CLIENT_ACCESSES_BY_INDEX:
|
||||||
handle_client_accesses_by_index(&rx_message, &tx_message);
|
handle_client_accesses_by_index(&rx_message, &tx_message);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ driftfile /var/lib/chrony/drift
|
|||||||
rtcsync
|
rtcsync
|
||||||
|
|
||||||
# In first three updates step the system clock instead of slew
|
# In first three updates step the system clock instead of slew
|
||||||
# if the adjustment is larger than 100 seconds.
|
# if the adjustment is larger than 10 seconds.
|
||||||
makestep 100 3
|
makestep 10 3
|
||||||
|
|
||||||
# Allow NTP client access from local network.
|
# Allow NTP client access from local network.
|
||||||
#allow 192.168/16
|
#allow 192.168/16
|
||||||
|
|||||||
21
faq.txt
21
faq.txt
@@ -68,7 +68,7 @@ support hardware reference clocks to your computer, then xntpd will work fine.
|
|||||||
Apart from not supporting hardware clocks, chrony will work fine too.
|
Apart from not supporting hardware clocks, chrony will work fine too.
|
||||||
|
|
||||||
If your computer connects to the 'net for 5 minutes once a day (or something
|
If your computer connects to the 'net for 5 minutes once a day (or something
|
||||||
like that), or you turn your (Linux v2.0) computer off when you're not using
|
like that), or you turn your Linux computer off when you're not using
|
||||||
it, or you want to use NTP on an isolated network with no hardware clocks in
|
it, or you want to use NTP on an isolated network with no hardware clocks in
|
||||||
sight, chrony will work much better for you.
|
sight, chrony will work much better for you.
|
||||||
|
|
||||||
@@ -153,23 +153,10 @@ arise. You should always make X quite high (e.g. 10) in this directive.
|
|||||||
|
|
||||||
S: Issues with chronyc
|
S: Issues with chronyc
|
||||||
|
|
||||||
Q: I keep getting the error '510 No command access from this host --- Reply not authenticated'.
|
Q: I keep getting the error '506 Cannot talk to daemon'.
|
||||||
Make sure that the chrony.conf file (on the computer where chronyd is running)
|
Make sure that the chrony.conf file (on the computer where chronyd is running)
|
||||||
has a 'cmdallow' entry for the computer you are running chronyc on. This
|
has a 'cmdallow' entry for the computer you are running chronyc on. This
|
||||||
shouldn't be necessary for localhost, but some people still seem to need an
|
isn't necessary for localhost.
|
||||||
entry like 'cmdallow 127.0.0.1'. (It would be good to understand why problem
|
|
||||||
only affects some people).
|
|
||||||
|
|
||||||
Q: I cannot log in from chronyc to carry out privileged tasks.
|
|
||||||
This is the second most common problem.
|
|
||||||
|
|
||||||
Perhaps your /etc/chrony.keys file is badly formatted. Make sure that the
|
|
||||||
final line has a line feed at the end, otherwise the key on that line will work
|
|
||||||
as though the last character is missing. (Note, this bug was fixed in version
|
|
||||||
1.16.)
|
|
||||||
|
|
||||||
Q: When I enter a command and hit <Return>, chronyc hangs
|
|
||||||
This probably means that chronyc cannot communicate with chronyd.
|
|
||||||
|
|
||||||
Perhaps chronyd is not running. Try using the ps command (e.g. on Linux, 'ps
|
Perhaps chronyd is not running. Try using the ps command (e.g. on Linux, 'ps
|
||||||
-auxw') to see if it's running. Or try 'netstat -a' and see if the ports
|
-auxw') to see if it's running. Or try 'netstat -a' and see if the ports
|
||||||
@@ -271,7 +258,7 @@ The program needs to see the definitions of structures used to interact with
|
|||||||
the real time clock (via /dev/rtc) and with the adjtimex() system call. Sadly
|
the real time clock (via /dev/rtc) and with the adjtimex() system call. Sadly
|
||||||
this has led to a number of compilation problems with newer kernels which have
|
this has led to a number of compilation problems with newer kernels which have
|
||||||
been increasingly hard to fix in a way that makes the code compilable on all
|
been increasingly hard to fix in a way that makes the code compilable on all
|
||||||
Linux kernel versions (from 2.0 up anyway, I doubt 1.x still works.) Hopefully
|
Linux kernel versions. Hopefully
|
||||||
the situation will not deteriorate further with future kernel versions.
|
the situation will not deteriorate further with future kernel versions.
|
||||||
|
|
||||||
Q: I get "Could not open /dev/rtc, Device or resource busy" in my syslog file.
|
Q: I get "Could not open /dev/rtc, Device or resource busy" in my syslog file.
|
||||||
|
|||||||
4
ntp_io.c
4
ntp_io.c
@@ -210,8 +210,10 @@ prepare_socket(int family)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (bind(sock_fd, &my_addr.u, my_addr_len) < 0) {
|
if (bind(sock_fd, &my_addr.u, my_addr_len) < 0) {
|
||||||
LOG_FATAL(LOGF_NtpIO, "Could not bind %s NTP socket : %s",
|
LOG(LOGS_ERR, LOGF_NtpIO, "Could not bind %s NTP socket : %s",
|
||||||
family == AF_INET ? "IPv4" : "IPv6", strerror(errno));
|
family == AF_INET ? "IPv4" : "IPv6", strerror(errno));
|
||||||
|
close(sock_fd);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Register handler for read events on the socket */
|
/* Register handler for read events on the socket */
|
||||||
|
|||||||
185
pktlength.c
185
pktlength.c
@@ -35,8 +35,8 @@
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
int
|
static int
|
||||||
PKL_CommandLength(CMD_Request *r)
|
command_unpadded_length(CMD_Request *r)
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
type = ntohs(r->command);
|
type = ntohs(r->command);
|
||||||
@@ -124,19 +124,9 @@ PKL_CommandLength(CMD_Request *r)
|
|||||||
case REQ_CYCLELOGS :
|
case REQ_CYCLELOGS :
|
||||||
return offsetof(CMD_Request, data.cyclelogs.EOR);
|
return offsetof(CMD_Request, data.cyclelogs.EOR);
|
||||||
case REQ_SUBNETS_ACCESSED :
|
case REQ_SUBNETS_ACCESSED :
|
||||||
{
|
|
||||||
unsigned long ns;
|
|
||||||
ns = ntohl(r->data.subnets_accessed.n_subnets);
|
|
||||||
return (offsetof(CMD_Request, data.subnets_accessed.subnets) +
|
|
||||||
ns * sizeof(REQ_SubnetsAccessed_Subnet));
|
|
||||||
}
|
|
||||||
case REQ_CLIENT_ACCESSES:
|
case REQ_CLIENT_ACCESSES:
|
||||||
{
|
/* No longer supported */
|
||||||
unsigned long nc;
|
return 0;
|
||||||
nc = ntohl(r->data.client_accesses.n_clients);
|
|
||||||
return (offsetof(CMD_Request, data.client_accesses.client_ips) +
|
|
||||||
nc * sizeof(unsigned long));
|
|
||||||
}
|
|
||||||
case REQ_CLIENT_ACCESSES_BY_INDEX:
|
case REQ_CLIENT_ACCESSES_BY_INDEX:
|
||||||
return offsetof(CMD_Request, data.client_accesses_by_index.EOR);
|
return offsetof(CMD_Request, data.client_accesses_by_index.EOR);
|
||||||
case REQ_MANUAL_LIST:
|
case REQ_MANUAL_LIST:
|
||||||
@@ -167,6 +157,149 @@ PKL_CommandLength(CMD_Request *r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
int
|
||||||
|
PKL_CommandLength(CMD_Request *r)
|
||||||
|
{
|
||||||
|
int command_length;
|
||||||
|
|
||||||
|
command_length = command_unpadded_length(r);
|
||||||
|
if (!command_length)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return command_length + PKL_CommandPaddingLength(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
#define PADDING_LENGTH_(request_length, reply_length) \
|
||||||
|
((request_length) < (reply_length) ? (reply_length) - (request_length) : 0)
|
||||||
|
|
||||||
|
#define PADDING_LENGTH(request_data, reply_data) \
|
||||||
|
PADDING_LENGTH_(offsetof(CMD_Request, request_data), offsetof(CMD_Reply, reply_data))
|
||||||
|
|
||||||
|
int
|
||||||
|
PKL_CommandPaddingLength(CMD_Request *r)
|
||||||
|
{
|
||||||
|
int type;
|
||||||
|
|
||||||
|
if (r->version < PROTO_VERSION_PADDING)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
type = ntohs(r->command);
|
||||||
|
|
||||||
|
if (type < 0 || type >= N_REQUEST_TYPES)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case REQ_NULL:
|
||||||
|
return PADDING_LENGTH(data, data.null.EOR);
|
||||||
|
case REQ_ONLINE:
|
||||||
|
return PADDING_LENGTH(data.online.EOR, data.null.EOR);
|
||||||
|
case REQ_OFFLINE:
|
||||||
|
return PADDING_LENGTH(data.offline.EOR, data.null.EOR);
|
||||||
|
case REQ_BURST:
|
||||||
|
return PADDING_LENGTH(data.burst.EOR, data.null.EOR);
|
||||||
|
case REQ_MODIFY_MINPOLL:
|
||||||
|
return PADDING_LENGTH(data.modify_minpoll.EOR, data.null.EOR);
|
||||||
|
case REQ_MODIFY_MAXPOLL:
|
||||||
|
return PADDING_LENGTH(data.modify_maxpoll.EOR, data.null.EOR);
|
||||||
|
case REQ_DUMP:
|
||||||
|
return PADDING_LENGTH(data.dump.EOR, data.null.EOR);
|
||||||
|
case REQ_MODIFY_MAXDELAY:
|
||||||
|
return PADDING_LENGTH(data.modify_maxdelay.EOR, data.null.EOR);
|
||||||
|
case REQ_MODIFY_MAXDELAYRATIO:
|
||||||
|
return PADDING_LENGTH(data.modify_maxdelayratio.EOR, data.null.EOR);
|
||||||
|
case REQ_MODIFY_MAXDELAYDEVRATIO:
|
||||||
|
return PADDING_LENGTH(data.modify_maxdelaydevratio.EOR, data.null.EOR);
|
||||||
|
case REQ_MODIFY_MAXUPDATESKEW:
|
||||||
|
return PADDING_LENGTH(data.modify_maxupdateskew.EOR, data.null.EOR);
|
||||||
|
case REQ_LOGON:
|
||||||
|
return PADDING_LENGTH(data.logon.EOR, data.null.EOR);
|
||||||
|
case REQ_SETTIME:
|
||||||
|
return PADDING_LENGTH(data.settime.EOR, data.manual_timestamp.EOR);
|
||||||
|
case REQ_LOCAL:
|
||||||
|
return PADDING_LENGTH(data.local.EOR, data.null.EOR);
|
||||||
|
case REQ_MANUAL:
|
||||||
|
return PADDING_LENGTH(data.manual.EOR, data.null.EOR);
|
||||||
|
case REQ_N_SOURCES:
|
||||||
|
return PADDING_LENGTH(data.n_sources.EOR, data.n_sources.EOR);
|
||||||
|
case REQ_SOURCE_DATA:
|
||||||
|
return PADDING_LENGTH(data.source_data.EOR, data.source_data.EOR);
|
||||||
|
case REQ_REKEY:
|
||||||
|
return PADDING_LENGTH(data.rekey.EOR, data.null.EOR);
|
||||||
|
case REQ_ALLOW:
|
||||||
|
return PADDING_LENGTH(data.allow_deny.EOR, data.null.EOR);
|
||||||
|
case REQ_ALLOWALL:
|
||||||
|
return PADDING_LENGTH(data.allow_deny.EOR, data.null.EOR);
|
||||||
|
case REQ_DENY:
|
||||||
|
return PADDING_LENGTH(data.allow_deny.EOR, data.null.EOR);
|
||||||
|
case REQ_DENYALL:
|
||||||
|
return PADDING_LENGTH(data.allow_deny.EOR, data.null.EOR);
|
||||||
|
case REQ_CMDALLOW:
|
||||||
|
return PADDING_LENGTH(data.allow_deny.EOR, data.null.EOR);
|
||||||
|
case REQ_CMDALLOWALL:
|
||||||
|
return PADDING_LENGTH(data.allow_deny.EOR, data.null.EOR);
|
||||||
|
case REQ_CMDDENY:
|
||||||
|
return PADDING_LENGTH(data.allow_deny.EOR, data.null.EOR);
|
||||||
|
case REQ_CMDDENYALL:
|
||||||
|
return PADDING_LENGTH(data.allow_deny.EOR, data.null.EOR);
|
||||||
|
case REQ_ACCHECK:
|
||||||
|
return PADDING_LENGTH(data.ac_check.EOR, data.null.EOR);
|
||||||
|
case REQ_CMDACCHECK:
|
||||||
|
return PADDING_LENGTH(data.ac_check.EOR, data.null.EOR);
|
||||||
|
case REQ_ADD_SERVER:
|
||||||
|
return PADDING_LENGTH(data.ntp_source.EOR, data.null.EOR);
|
||||||
|
case REQ_ADD_PEER:
|
||||||
|
return PADDING_LENGTH(data.ntp_source.EOR, data.null.EOR);
|
||||||
|
case REQ_DEL_SOURCE:
|
||||||
|
return PADDING_LENGTH(data.del_source.EOR, data.null.EOR);
|
||||||
|
case REQ_WRITERTC:
|
||||||
|
return PADDING_LENGTH(data.writertc.EOR, data.null.EOR);
|
||||||
|
case REQ_DFREQ:
|
||||||
|
return PADDING_LENGTH(data.dfreq.EOR, data.null.EOR);
|
||||||
|
case REQ_DOFFSET:
|
||||||
|
return PADDING_LENGTH(data.doffset.EOR, data.null.EOR);
|
||||||
|
case REQ_TRACKING:
|
||||||
|
return PADDING_LENGTH(data.tracking.EOR, data.tracking.EOR);
|
||||||
|
case REQ_SOURCESTATS:
|
||||||
|
return PADDING_LENGTH(data.sourcestats.EOR, data.sourcestats.EOR);
|
||||||
|
case REQ_RTCREPORT:
|
||||||
|
return PADDING_LENGTH(data.rtcreport.EOR, data.rtc.EOR);
|
||||||
|
case REQ_TRIMRTC:
|
||||||
|
return PADDING_LENGTH(data.trimrtc.EOR, data.null.EOR);
|
||||||
|
case REQ_CYCLELOGS:
|
||||||
|
return PADDING_LENGTH(data.cyclelogs.EOR, data.null.EOR);
|
||||||
|
case REQ_SUBNETS_ACCESSED:
|
||||||
|
case REQ_CLIENT_ACCESSES:
|
||||||
|
/* No longer supported */
|
||||||
|
return 0;
|
||||||
|
case REQ_CLIENT_ACCESSES_BY_INDEX:
|
||||||
|
return PADDING_LENGTH(data.client_accesses_by_index.EOR, data.client_accesses_by_index.EOR);
|
||||||
|
case REQ_MANUAL_LIST:
|
||||||
|
return PADDING_LENGTH(data.manual_list.EOR, data.manual_list.EOR);
|
||||||
|
case REQ_MANUAL_DELETE:
|
||||||
|
return PADDING_LENGTH(data.manual_delete.EOR, data.null.EOR);
|
||||||
|
case REQ_MAKESTEP:
|
||||||
|
return PADDING_LENGTH(data.make_step.EOR, data.null.EOR);
|
||||||
|
case REQ_ACTIVITY:
|
||||||
|
return PADDING_LENGTH(data.activity.EOR, data.activity.EOR);
|
||||||
|
case REQ_RESELECT:
|
||||||
|
return PADDING_LENGTH(data.reselect.EOR, data.null.EOR);
|
||||||
|
case REQ_RESELECTDISTANCE:
|
||||||
|
return PADDING_LENGTH(data.reselect_distance.EOR, data.null.EOR);
|
||||||
|
case REQ_MODIFY_MINSTRATUM:
|
||||||
|
return PADDING_LENGTH(data.modify_minstratum.EOR, data.null.EOR);
|
||||||
|
case REQ_MODIFY_POLLTARGET:
|
||||||
|
return PADDING_LENGTH(data.modify_polltarget.EOR, data.null.EOR);
|
||||||
|
default:
|
||||||
|
/* If we fall through the switch, it most likely means we've forgotten to implement a new case */
|
||||||
|
assert(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -194,29 +327,15 @@ PKL_ReplyLength(CMD_Reply *r)
|
|||||||
case RPY_RTC:
|
case RPY_RTC:
|
||||||
return offsetof(CMD_Reply, data.rtc.EOR);
|
return offsetof(CMD_Reply, data.rtc.EOR);
|
||||||
case RPY_SUBNETS_ACCESSED :
|
case RPY_SUBNETS_ACCESSED :
|
||||||
{
|
|
||||||
unsigned long ns = ntohl(r->data.subnets_accessed.n_subnets);
|
|
||||||
if (r->status == htons(STT_SUCCESS)) {
|
|
||||||
return (offsetof(CMD_Reply, data.subnets_accessed.subnets) +
|
|
||||||
ns * sizeof(RPY_SubnetsAccessed_Subnet));
|
|
||||||
} else {
|
|
||||||
return offsetof(CMD_Reply, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case RPY_CLIENT_ACCESSES:
|
case RPY_CLIENT_ACCESSES:
|
||||||
{
|
/* No longer supported */
|
||||||
unsigned long nc = ntohl(r->data.client_accesses.n_clients);
|
return 0;
|
||||||
if (r->status == htons(STT_SUCCESS)) {
|
|
||||||
return (offsetof(CMD_Reply, data.client_accesses.clients) +
|
|
||||||
nc * sizeof(RPY_ClientAccesses_Client));
|
|
||||||
} else {
|
|
||||||
return offsetof(CMD_Reply, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case RPY_CLIENT_ACCESSES_BY_INDEX:
|
case RPY_CLIENT_ACCESSES_BY_INDEX:
|
||||||
{
|
{
|
||||||
unsigned long nc = ntohl(r->data.client_accesses_by_index.n_clients);
|
unsigned long nc = ntohl(r->data.client_accesses_by_index.n_clients);
|
||||||
if (r->status == htons(STT_SUCCESS)) {
|
if (r->status == htons(STT_SUCCESS)) {
|
||||||
|
if (nc > MAX_CLIENT_ACCESSES)
|
||||||
|
return 0;
|
||||||
return (offsetof(CMD_Reply, data.client_accesses_by_index.clients) +
|
return (offsetof(CMD_Reply, data.client_accesses_by_index.clients) +
|
||||||
nc * sizeof(RPY_ClientAccesses_Client));
|
nc * sizeof(RPY_ClientAccesses_Client));
|
||||||
} else {
|
} else {
|
||||||
@@ -226,6 +345,8 @@ PKL_ReplyLength(CMD_Reply *r)
|
|||||||
case RPY_MANUAL_LIST:
|
case RPY_MANUAL_LIST:
|
||||||
{
|
{
|
||||||
unsigned long ns = ntohl(r->data.manual_list.n_samples);
|
unsigned long ns = ntohl(r->data.manual_list.n_samples);
|
||||||
|
if (ns > MAX_MANUAL_LIST_SAMPLES)
|
||||||
|
return 0;
|
||||||
if (r->status == htons(STT_SUCCESS)) {
|
if (r->status == htons(STT_SUCCESS)) {
|
||||||
return (offsetof(CMD_Reply, data.manual_list.samples) +
|
return (offsetof(CMD_Reply, data.manual_list.samples) +
|
||||||
ns * sizeof(RPY_ManualListSample));
|
ns * sizeof(RPY_ManualListSample));
|
||||||
|
|||||||
@@ -33,6 +33,8 @@
|
|||||||
|
|
||||||
extern int PKL_CommandLength(CMD_Request *r);
|
extern int PKL_CommandLength(CMD_Request *r);
|
||||||
|
|
||||||
|
extern int PKL_CommandPaddingLength(CMD_Request *r);
|
||||||
|
|
||||||
extern int PKL_ReplyLength(CMD_Reply *r);
|
extern int PKL_ReplyLength(CMD_Reply *r);
|
||||||
|
|
||||||
#endif /* GOT_PKTLENGTH_H */
|
#endif /* GOT_PKTLENGTH_H */
|
||||||
|
|||||||
Reference in New Issue
Block a user