ntp+cmdmon: fix responding to link-local addresses

After commit e49aececce ("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.
This commit is contained in:
Miroslav Lichvar 2020-06-30 16:13:48 +02:00
parent 99e3c67a81
commit 4e747da4b4
4 changed files with 28 additions and 4 deletions

View file

@ -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;

View file

@ -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 */

View file

@ -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))

View file

@ -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,