aboutsummaryrefslogtreecommitdiffstats
path: root/main/chrony/chrony-1.23-reply-ip.diff
diff options
context:
space:
mode:
Diffstat (limited to 'main/chrony/chrony-1.23-reply-ip.diff')
-rw-r--r--main/chrony/chrony-1.23-reply-ip.diff242
1 files changed, 242 insertions, 0 deletions
diff --git a/main/chrony/chrony-1.23-reply-ip.diff b/main/chrony/chrony-1.23-reply-ip.diff
new file mode 100644
index 0000000000..f4e5d8eff4
--- /dev/null
+++ b/main/chrony/chrony-1.23-reply-ip.diff
@@ -0,0 +1,242 @@
+
+Currently, on multihomed host, when chrony is not bound to a specific
+IP address, a query is sent to an interface and the default source IP
+hint for the back route differs, the reply will have a source IP
+different than where the query was destinied to. This will cause
+problems because connection tracking firewalls will drop the replies
+and most likely the client program will get confused too.
+
+This patch uses the IP_PKTINFO mechanism to get the IP address where
+received packets where targetted to and use that IP address as source
+hint when sending a reply.
+---
+ addressing.h | 1 +
+ broadcast.c | 1 +
+ cmdmon.c | 3 ++
+ conf.c | 1 +
+ ntp_io.c | 92 +++++++++++++++++++++++++++++++++++++++++----------------
+ 5 files changed, 72 insertions(+), 26 deletions(-)
+
+diff --git a/addressing.h b/addressing.h
+index aa20ed9..05152f4 100644
+--- a/addressing.h
++++ b/addressing.h
+@@ -36,6 +36,7 @@
+ typedef struct {
+ unsigned long ip_addr;
+ unsigned short port;
++ unsigned long local_ip_addr;
+ } NTP_Remote_Address;
+
+ #if 0
+diff --git a/broadcast.c b/broadcast.c
+index be217e7..c979741 100644
+--- a/broadcast.c
++++ b/broadcast.c
+@@ -146,6 +146,7 @@ BRD_AddDestination(unsigned long addr, unsigned short port, int interval)
+
+ destinations[n_destinations].addr.ip_addr = addr;
+ destinations[n_destinations].addr.port = port;
++ destinations[n_destinations].addr.local_ip_addr = 0;
+ destinations[n_destinations].interval = interval;
+
+ SCH_AddTimeoutInClass((double) interval, 1.0,
+diff --git a/cmdmon.c b/cmdmon.c
+index 819977c..8affb0b 100644
+--- a/cmdmon.c
++++ b/cmdmon.c
+@@ -1097,6 +1097,7 @@ handle_add_server(CMD_Request *rx_message, CMD_Reply *tx_message)
+
+ rem_addr.ip_addr = ntohl(rx_message->data.ntp_source.ip_addr);
+ rem_addr.port = (unsigned short)(ntohl(rx_message->data.ntp_source.port));
++ rem_addr.local_ip_addr = 0;
+ params.minpoll = ntohl(rx_message->data.ntp_source.minpoll);
+ params.maxpoll = ntohl(rx_message->data.ntp_source.maxpoll);
+ params.presend_minpoll = ntohl(rx_message->data.ntp_source.presend_minpoll);
+@@ -1133,6 +1134,7 @@ handle_add_peer(CMD_Request *rx_message, CMD_Reply *tx_message)
+
+ rem_addr.ip_addr = ntohl(rx_message->data.ntp_source.ip_addr);
+ rem_addr.port = (unsigned short)(ntohl(rx_message->data.ntp_source.port));
++ rem_addr.local_ip_addr = 0;
+ params.minpoll = ntohl(rx_message->data.ntp_source.minpoll);
+ params.maxpoll = ntohl(rx_message->data.ntp_source.maxpoll);
+ params.presend_minpoll = ntohl(rx_message->data.ntp_source.presend_minpoll);
+@@ -1167,6 +1169,7 @@ handle_del_source(CMD_Request *rx_message, CMD_Reply *tx_message)
+
+ rem_addr.ip_addr = ntohl(rx_message->data.del_source.ip_addr);
+ rem_addr.port = 0;
++ rem_addr.local_ip_addr = 0;
+
+ status = NSR_RemoveSource(&rem_addr);
+ switch (status) {
+diff --git a/conf.c b/conf.c
+index e34927e..ddd13f1 100644
+--- a/conf.c
++++ b/conf.c
+@@ -949,6 +949,7 @@ CNF_AddSources(void) {
+ for (i=0; i<n_ntp_sources; i++) {
+ server.ip_addr = ntp_sources[i].ip_addr;
+ server.port = ntp_sources[i].port;
++ server.local_ip_addr = 0;
+
+ switch (ntp_sources[i].type) {
+ case SERVER:
+diff --git a/ntp_io.c b/ntp_io.c
+index afb6ad1..db89758 100644
+--- a/ntp_io.c
++++ b/ntp_io.c
+@@ -118,6 +118,12 @@ NIO_Initialise(void)
+ LOG(LOGS_ERR, LOGF_NtpIO, "Could not set broadcast socket options");
+ /* Don't quit - we might survive anyway */
+ }
++ /* We want the local IP info too */
++ if (setsockopt(sock_fd, IPPROTO_IP, IP_PKTINFO, (char *)&on_off, sizeof(on_off)) < 0) {
++ LOG(LOGS_ERR, LOGF_NtpIO, "Could not request packet info using socket option");
++ /* Don't quit - we might survive anyway */
++ }
++
+
+ /* Bind the port */
+ my_addr.sin_family = AF_INET;
+@@ -182,22 +188,30 @@ read_from_socket(void *anything)
+
+ int status;
+ ReceiveBuffer message;
+- int message_length;
+ struct sockaddr_in where_from;
+- socklen_t from_length;
+ unsigned int flags = 0;
+ struct timeval now;
+ NTP_Remote_Address remote_addr;
+ double local_clock_err;
++ char cmsgbuf[256];
++ struct cmsghdr *cmsg;
++ struct msghdr msg;
++ struct iovec iov;
+
+ assert(initialised);
+
+- from_length = sizeof(where_from);
+- message_length = sizeof(message);
++ iov.iov_base = message.arbitrary;
++ iov.iov_len = sizeof(message);
++ msg.msg_name = &where_from;
++ msg.msg_namelen = sizeof(where_from);
++ msg.msg_iov = &iov;
++ msg.msg_iovlen = 1;
++ msg.msg_control = (void *) cmsgbuf;
++ msg.msg_controllen = sizeof(cmsgbuf);
++ msg.msg_flags = 0;
+
+ LCL_ReadCookedTime(&now, &local_clock_err);
+- status = recvfrom(sock_fd, (char *)&message, message_length, flags,
+- (struct sockaddr *)&where_from, &from_length);
++ status = recvmsg(sock_fd, &msg, flags);
+
+ /* Don't bother checking if read failed or why if it did. More
+ likely than not, it will be connection refused, resulting from a
+@@ -209,6 +223,13 @@ read_from_socket(void *anything)
+ if (status > 0) {
+ remote_addr.ip_addr = ntohl(where_from.sin_addr.s_addr);
+ remote_addr.port = ntohs(where_from.sin_port);
++ remote_addr.local_ip_addr = 0;
++
++ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
++ if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO)
++ remote_addr.local_ip_addr =
++ ntohl(((struct in_pktinfo *) CMSG_DATA(cmsg))->ipi_spec_dst.s_addr);
++ }
+
+ if (status == NTP_NORMAL_PACKET_SIZE) {
+
+@@ -229,21 +250,45 @@ read_from_socket(void *anything)
+ }
+
+ /* ================================================== */
+-/* Send an unauthenticated packet to a given address */
++/* Send a packet to given address */
+
+-void
+-NIO_SendNormalPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr)
++static void
++NIO_SendPacket(NTP_Packet *packet, int packetlen, NTP_Remote_Address *remote_addr)
+ {
+ struct sockaddr_in remote;
++ struct msghdr msg;
++ struct iovec iov;
++ struct {
++ struct cmsghdr cm;
++ struct in_pktinfo ipi;
++ } cmsg;
+
+ assert(initialised);
+
+ remote.sin_family = AF_INET;
+ remote.sin_port = htons(remote_addr->port);
+ remote.sin_addr.s_addr = htonl(remote_addr->ip_addr);
++ iov.iov_base = (void *) packet;
++ iov.iov_len = packetlen;
++ msg.msg_name = &remote;
++ msg.msg_namelen = sizeof(remote);
++ msg.msg_iov = &iov;
++ msg.msg_iovlen = 1;
++ if (remote_addr->local_ip_addr) {
++ cmsg.cm.cmsg_len = sizeof(cmsg);
++ cmsg.cm.cmsg_level = IPPROTO_IP;
++ cmsg.cm.cmsg_type = IP_PKTINFO;
++ memset(&cmsg.ipi, 0, sizeof(cmsg.ipi));
++ cmsg.ipi.ipi_spec_dst.s_addr = htonl(remote_addr->local_ip_addr);
++ msg.msg_control = (void *) &cmsg;
++ msg.msg_controllen = sizeof(cmsg);
++ } else {
++ msg.msg_control = NULL;
++ msg.msg_controllen = 0;
++ }
++ msg.msg_flags = 0;
+
+- if (sendto(sock_fd, (void *) packet, NTP_NORMAL_PACKET_SIZE, 0,
+- (struct sockaddr *) &remote, sizeof(remote)) < 0) {
++ if (sendmsg(sock_fd, &msg, 0) < 0) {
+ LOG(LOGS_WARN, LOGF_NtpIO, "Could not send to %s:%d : %s",
+ UTI_IPToDottedQuad(remote_addr->ip_addr), remote_addr->port, strerror(errno));
+ }
+@@ -252,26 +297,21 @@ NIO_SendNormalPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr)
+ }
+
+ /* ================================================== */
+-/* Send an authenticated packet to a given address */
++/* Send an unauthenticated packet to a given address */
+
+ void
+-NIO_SendAuthenticatedPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr)
++NIO_SendNormalPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr)
+ {
+- struct sockaddr_in remote;
+-
+- assert(initialised);
+-
+- remote.sin_family = AF_INET;
+- remote.sin_port = htons(remote_addr->port);
+- remote.sin_addr.s_addr = htonl(remote_addr->ip_addr);
++ NIO_SendPacket(packet, NTP_NORMAL_PACKET_SIZE, remote_addr);
++}
+
+- if (sendto(sock_fd, (void *) packet, sizeof(NTP_Packet), 0,
+- (struct sockaddr *) &remote, sizeof(remote)) < 0) {
+- LOG(LOGS_WARN, LOGF_NtpIO, "Could not send to %s:%d : %s",
+- UTI_IPToDottedQuad(remote_addr->ip_addr), remote_addr->port, strerror(errno));
+- }
++/* ================================================== */
++/* Send an authenticated packet to a given address */
+
+- return;
++void
++NIO_SendAuthenticatedPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr)
++{
++ NIO_SendPacket(packet, sizeof(NTP_Packet), remote_addr);
+ }
+
+ /* ================================================== */
+--
+1.5.6.3
+