static int
open_socket(int family)
{
+ const char *local_path, *iface;
IPSockAddr local_addr;
- const char *local_path;
int sock_fd, port;
switch (family) {
SCK_GetLoopbackIPAddress(family, &local_addr.ip_addr);
local_addr.port = port;
- sock_fd = SCK_OpenUdpSocket(NULL, &local_addr, NULL, SCK_FLAG_RX_DEST_ADDR);
+ iface = CNF_GetBindCommandInterface();
+
+ sock_fd = SCK_OpenUdpSocket(NULL, &local_addr, iface, SCK_FLAG_RX_DEST_ADDR);
if (sock_fd < 0) {
LOG(LOGS_ERR, "Could not open command socket on %s",
UTI_IPSockAddrToString(&local_addr));
the loopback address will be used */
static IPAddr bind_cmd_address4, bind_cmd_address6;
+/* Interface names to bind the NTP server, NTP client, and command socket */
+static char *bind_ntp_iface = NULL;
+static char *bind_acq_iface = NULL;
+static char *bind_cmd_iface = NULL;
+
/* Path to the Unix domain command socket. */
static char *bind_cmd_path = NULL;
Free(keys_file);
Free(leapsec_tz);
Free(logdir);
+ Free(bind_ntp_iface);
+ Free(bind_acq_iface);
+ Free(bind_cmd_iface);
Free(bind_cmd_path);
Free(ntp_signd_socket);
Free(pidfile);
parse_authselectmode(p);
} else if (!strcasecmp(command, "bindacqaddress")) {
parse_bindacqaddress(p);
+ } else if (!strcasecmp(command, "bindacqdevice")) {
+ parse_string(p, &bind_acq_iface);
} else if (!strcasecmp(command, "bindaddress")) {
parse_bindaddress(p);
} else if (!strcasecmp(command, "bindcmdaddress")) {
parse_bindcmdaddress(p);
+ } else if (!strcasecmp(command, "bindcmddevice")) {
+ parse_string(p, &bind_cmd_iface);
+ } else if (!strcasecmp(command, "binddevice")) {
+ parse_string(p, &bind_ntp_iface);
} else if (!strcasecmp(command, "broadcast")) {
parse_broadcast(p);
} else if (!strcasecmp(command, "clientloglimit")) {
/* ================================================== */
+char *
+CNF_GetBindNtpInterface(void)
+{
+ return bind_ntp_iface;
+}
+
+/* ================================================== */
+
+char *
+CNF_GetBindAcquisitionInterface(void)
+{
+ return bind_acq_iface;
+}
+
+/* ================================================== */
+
+char *
+CNF_GetBindCommandInterface(void)
+{
+ return bind_cmd_iface;
+}
+
+/* ================================================== */
+
char *
CNF_GetBindCommandPath(void)
{
extern void CNF_GetBindAddress(int family, IPAddr *addr);
extern void CNF_GetBindAcquisitionAddress(int family, IPAddr *addr);
extern void CNF_GetBindCommandAddress(int family, IPAddr *addr);
+extern char *CNF_GetBindNtpInterface(void);
+extern char *CNF_GetBindAcquisitionInterface(void);
+extern char *CNF_GetBindCommandInterface(void);
extern char *CNF_GetBindCommandPath(void);
extern char *CNF_GetNtpSigndSocket(void);
extern char *CNF_GetPidFile(void);
You could then persuade the firewall administrator to open that port.
[[bindacqaddress]]*bindacqaddress* _address_::
-The *bindacqaddress* directive sets the network interface to which
+The *bindacqaddress* directive specifies a local IP address to which
*chronyd* will bind its NTP client sockets. The syntax is similar to the
<<bindaddress,*bindaddress*>> and <<bindcmdaddress,*bindcmdaddress*>>
directives.
For each of the IPv4 and IPv6 protocols, only one *bindacqaddress* directive
can be specified.
+[[bindacqdevice]]*bindacqdevice* _interface_::
+The *bindacqdevice* directive binds the client sockets to a network device
+specified by the interface name. This can be useful when the local address is
+dynamic, or to enable an NTP source specified with a link-local IPv6 address.
+This directive can specify only one interface and it is supported on Linux
+only.
++
+An example of the directive is:
++
+----
+bindacqdevice eth0
+----
+
[[dumpdir]]*dumpdir* _directory_::
To compute the rate of gain or loss of time, *chronyd* has to store a
measurement history for each of the time sources it uses.
directive can be specified. Therefore, it is not useful on computers which
should serve NTP on multiple network interfaces.
+[[binddevice]]*binddevice* _interface_::
+The *binddevice* directive binds the NTP server sockets to a network device
+specified by the interface name. This directive can specify only one interface
+and it is supported on Linux only.
++
+An example of the directive is:
++
+----
+binddevice eth0
+----
+
[[broadcast]]*broadcast* _interval_ _address_ [_port_]::
The *broadcast* directive is used to declare a broadcast address to which
chronyd should send packets in the NTP broadcast mode (i.e. make *chronyd* act
=== Command and monitoring access
[[bindcmdaddress]]*bindcmdaddress* _address_::
-The *bindcmdaddress* directive allows you to specify an IP address of an
-interface on which *chronyd* will listen for monitoring command packets (issued
+The *bindcmdaddress* directive specifies a local IP address to which *chronyd*
+will bind the UDP socket listening for monitoring command packets (issued
by *chronyc*). On systems other than Linux, the address of the interface needs
to be already configured when *chronyd* is started.
+
path of the socket is _@CHRONYRUNDIR@/chronyd.sock_. The socket can be
disabled by setting the path to _/_.
+
-By default, *chronyd* binds to the loopback interface (with addresses
-_127.0.0.1_ and _::1_). This blocks all access except from localhost. To listen
-for command packets on all interfaces, you can add the lines:
+By default, *chronyd* binds the UDP sockets to the addresses _127.0.0.1_ and
+_::1_ (i.e. the loopback interface). This blocks all access except from
+localhost. To listen for command packets on all interfaces, you can add the
+lines:
+
----
bindcmdaddress 0.0.0.0
bindcmdaddress /var/run/chrony/chronyd.sock
----
+[[bindcmddevice]]*bindcmddevice* _interface_::
+The *bindcmddevice* directive binds the UDP command sockets to a network device
+specified by the interface name. This directive can specify only one interface
+and it is supported on Linux only.
++
+An example of the directive is:
++
+----
+bindcmddevice eth0
+----
+
[[cmdallow]]*cmdallow* [*all*] [_subnet_]::
This is similar to the <<allow,*allow*>> directive, except that it allows
monitoring access (rather than NTP client access) to a particular subnet or
{
int sock_fd, sock_flags, events = SCH_FILE_INPUT;
IPSockAddr local_addr;
+ char *iface;
if (!SCK_IsIpFamilyEnabled(family))
return INVALID_SOCK_FD;
- if (!client_only)
+ if (!client_only) {
CNF_GetBindAddress(family, &local_addr.ip_addr);
- else
+ iface = CNF_GetBindNtpInterface();
+ } else {
CNF_GetBindAcquisitionAddress(family, &local_addr.ip_addr);
+ iface = CNF_GetBindAcquisitionInterface();
+ }
if (local_addr.ip_addr.family != family)
SCK_GetAnyLocalIPAddress(family, &local_addr.ip_addr);
if (!client_only)
sock_flags |= SCK_FLAG_BROADCAST;
- sock_fd = SCK_OpenUdpSocket(remote_addr, &local_addr, NULL, sock_flags);
+ sock_fd = SCK_OpenUdpSocket(remote_addr, &local_addr, iface, sock_flags);
if (sock_fd < 0) {
if (!client_only)
LOG(LOGS_ERR, "Could not open NTP socket on %s", UTI_IPSockAddrToString(&local_addr));
Keep CAP_SYS_TIME if the clock control is enabled. */
if (snprintf(cap_text, sizeof (cap_text), "%s %s %s",
CNF_GetNTPPort() ? "cap_net_bind_service=ep" : "",
- 0 ? "cap_net_raw=ep" : "",
+ CNF_GetBindNtpInterface() || CNF_GetBindAcquisitionInterface() ?
+ "cap_net_raw=ep" : "",
clock_control ? "cap_sys_time=ep" : "") >= sizeof (cap_text))
assert(0);