cmdmon: fix responding to IPv4 addresses on FreeBSD

On FreeBSD, the source address cannot be specified when sending a
message on a socket bound to a non-any IPv4 address, e.g. in default
configuration 127.0.0.1. In this case, make the address unspecified.

This is similar to commit 6af39d63aa ("ntp: don't use IP_SENDSRCADDR
on bound socket").

Fixes: f06c1cfa97 ("cmdmon: respond from same address")
This commit is contained in:
Miroslav Lichvar 2021-03-02 13:10:13 +01:00
parent 517b1ae29a
commit 2d39a12f51

View file

@ -62,6 +62,9 @@ static int sock_fdu;
static int sock_fd4;
static int sock_fd6;
/* Flag indicating the IPv4 socket is bound to an address */
static int bound_sock_fd4;
/* Flag indicating whether this module has been initialised or not */
static int initialised = 0;
@ -179,6 +182,9 @@ open_socket(int family)
return INVALID_SOCK_FD;
}
if (family == IPADDR_INET4)
bound_sock_fd4 = local_addr.ip_addr.addr.in4 != INADDR_ANY;
break;
case IPADDR_UNSPEC:
local_path = CNF_GetBindCommandPath();
@ -244,6 +250,8 @@ CAM_Initialise(void)
initialised = 1;
bound_sock_fd4 = 0;
sock_fdu = INVALID_SOCK_FD;
sock_fd4 = open_socket(IPADDR_INET4);
sock_fd6 = open_socket(IPADDR_INET6);
@ -310,6 +318,12 @@ transmit_reply(int sock_fd, int request_length, SCK_Message *message)
!SCK_IsLinkLocalIPAddress(&message->remote_addr.ip.ip_addr))
message->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 */
if (message->local_addr.ip.family == IPADDR_INET4 && (sock_fd != sock_fd4 || bound_sock_fd4))
message->local_addr.ip.family = IPADDR_UNSPEC;
#endif
if (!SCK_SendMessage(sock_fd, message, 0))
return;
}