]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
ntp+cmdmon: fix responding to link-local addresses
authorMiroslav Lichvar <mlichvar@redhat.com>
Tue, 30 Jun 2020 14:13:48 +0000 (16:13 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Wed, 1 Jul 2020 14:19:44 +0000 (16:19 +0200)
After commit e49aececceaa ("socket: don't set interface for sent
packets") the NTP and cmdmon server stopped responding to requests from
link-local addresses.

Set the interface specifically for packets sent to a link-local address.

cmdmon.c
ntp_io.c
socket.c
socket.h

index 37dc94498abaf152683f47194ce74e566ee0242d..2fdb86780980d5400fd39722b9b572bba9218384 100644 (file)
--- a/cmdmon.c
+++ b/cmdmon.c
@@ -301,8 +301,10 @@ transmit_reply(int sock_fd, SCK_Message *message)
 {
   message->length = PKL_ReplyLength((CMD_Reply *)message->data);
 
-  /* Don't require the response to use the same interface */
-  message->if_index = INVALID_IF_INDEX;
+  /* Don't require responses to non-link-local addresses to use the same
+     interface */
+  if (!SCK_IsLinkLocalIPAddress(&message->remote_addr.ip.ip_addr))
+    message->if_index = INVALID_IF_INDEX;
 
   if (!SCK_SendMessage(sock_fd, message, 0))
     return;
index 58b22243aa0d8e8cfa9db8bc14e672fdf3d2b8df..4bf3457ee0fd77f266fc2ff9173ee3ebecca5616 100644 (file)
--- a/ntp_io.c
+++ b/ntp_io.c
@@ -454,8 +454,10 @@ NIO_SendPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr,
 
   message.local_addr.ip = local_addr->ip_addr;
 
-  /* Don't require the response to use the same interface */
-  message.if_index = INVALID_IF_INDEX;
+  /* Don't require responses to non-link-local addresses to use the same
+     interface */
+  message.if_index = SCK_IsLinkLocalIPAddress(&message.remote_addr.ip.ip_addr) ?
+                       local_addr->if_index : INVALID_IF_INDEX;
 
 #if !defined(HAVE_IN_PKTINFO) && defined(IP_SENDSRCADDR)
   /* On FreeBSD a local IPv4 address cannot be specified on bound socket */
index dbcf6240cf66fb5099dcd31ae775a33097e6e344..99b43f5e9ef3b8d15925bcab2fc35241edcee6b3 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -1228,6 +1228,23 @@ SCK_GetLoopbackIPAddress(int family, IPAddr *local_addr)
 
 /* ================================================== */
 
+int
+SCK_IsLinkLocalIPAddress(IPAddr *addr)
+{
+  switch (addr->family) {
+    case IPADDR_INET4:
+      /* 169.254.0.0/16 */
+      return (addr->addr.in4 & 0xffff0000) == 0xa9fe0000;
+    case IPADDR_INET6:
+      /* fe80::/10 */
+      return addr->addr.in6[0] == 0xfe && (addr->addr.in6[1] & 0xc0) == 0x80;
+    default:
+      return 0;
+  }
+}
+
+/* ================================================== */
+
 void
 SCK_SetPrivBind(int (*function)(int sock_fd, struct sockaddr *address,
                                 socklen_t address_len))
index 9207a43c6cf7bc1097b5ba3cc13f3d1cfdc183ad..7d3fa9d9984843cd083e1b4f6081c05f267007ed 100644 (file)
--- a/socket.h
+++ b/socket.h
@@ -87,6 +87,9 @@ extern int SCK_IsIpFamilyEnabled(int family);
 extern void SCK_GetAnyLocalIPAddress(int family, IPAddr *local_addr);
 extern void SCK_GetLoopbackIPAddress(int family, IPAddr *local_addr);
 
+/* Check if an IP address is a link-local address */
+extern int SCK_IsLinkLocalIPAddress(IPAddr *addr);
+
 /* Specify a bind()-like function for binding sockets to privileged ports when
    running in a restricted process (e.g. after dropping root privileges) */
 extern void SCK_SetPrivBind(int (*function)(int sock_fd, struct sockaddr *address,