]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
Set source IPv6 address on NTP reply
authorMiroslav Lichvar <mlichvar@redhat.com>
Tue, 24 May 2011 16:06:01 +0000 (18:06 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Tue, 24 May 2011 16:07:06 +0000 (18:07 +0200)
This is needed on systems with multiple IPv6 addresses to reply with
the same source address as the destination address of the NTP request.

configure
ntp_io.c

index cf2555f505ecc481613a95719186c706b4729697..3fa76dbb72ded24b907d613da0776954502cabba 100755 (executable)
--- a/configure
+++ b/configure
@@ -360,6 +360,15 @@ if [ $feat_ipv6 = "1" ] && \
     return !inet_ntop(AF_INET6, &n.sin6_addr.s6_addr, p, sizeof(p));'
 then
   add_def HAVE_IPV6
+  if ! test_code 'in6_pktinfo' 'sys/socket.h netinet/in.h' '' '' '
+    return sizeof(struct in6_pktinfo);'
+  then
+    if test_code 'in6_pktinfo with _GNU_SOURCE' 'sys/socket.h netinet/in.h' \
+      '-D_GNU_SOURCE' '' 'return sizeof(struct in6_pktinfo);'
+    then
+      add_def _GNU_SOURCE
+    fi
+  fi
 fi
 
 if [ $feat_pps = "1" ] && \
index 9bad2bca5cb7d22d17852e517a69d9886fb1513e..7fdff425cce54befc78ca92a70d20e0e88557a3c 100644 (file)
--- a/ntp_io.c
+++ b/ntp_io.c
@@ -159,6 +159,16 @@ prepare_socket(int family)
       LOG(LOGS_ERR, LOGF_NtpIO, "Could not request IPV6_V6ONLY socket option");
     }
 #endif
+
+#ifdef IPV6_RECVPKTINFO
+    if (setsockopt(sock_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, (char *)&on_off, sizeof(on_off)) < 0) {
+      LOG(LOGS_ERR, LOGF_NtpIO, "Could not request IPv6 packet info socket option");
+    }
+#elif defined(IPV6_PKTINFO)
+    if (setsockopt(sock_fd, IPPROTO_IPV6, IPV6_PKTINFO, (char *)&on_off, sizeof(on_off)) < 0) {
+      LOG(LOGS_ERR, LOGF_NtpIO, "Could not request IPv6 packet info socket option");
+    }
+#endif
   }
 #endif
 
@@ -345,6 +355,17 @@ read_from_socket(void *anything)
       }
 #endif
 
+#ifdef IPV6_PKTINFO
+      if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
+        struct in6_pktinfo ipi;
+
+        memcpy(&ipi, CMSG_DATA(cmsg), sizeof(ipi));
+        memcpy(&remote_addr.local_ip_addr.addr.in6, &ipi.ipi6_addr.s6_addr,
+            sizeof (remote_addr.local_ip_addr.addr.in6));
+        remote_addr.local_ip_addr.family = IPADDR_INET6;
+      }
+#endif
+
 #ifdef SO_TIMESTAMP
       if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_TIMESTAMP) {
         struct timeval tv;
@@ -445,6 +466,25 @@ send_packet(void *packet, int packetlen, NTP_Remote_Address *remote_addr)
   }
 #endif
 
+#ifdef IPV6_PKTINFO
+  if (remote_addr->local_ip_addr.family == IPADDR_INET6) {
+    struct cmsghdr *cmsg;
+    struct in6_pktinfo *ipi;
+
+    cmsg = CMSG_FIRSTHDR(&msg);
+    memset(cmsg, 0, CMSG_SPACE(sizeof(struct in6_pktinfo)));
+    cmsglen += CMSG_SPACE(sizeof(struct in6_pktinfo));
+
+    cmsg->cmsg_level = IPPROTO_IPV6;
+    cmsg->cmsg_type = IPV6_PKTINFO;
+    cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
+
+    ipi = (struct in6_pktinfo *) CMSG_DATA(cmsg);
+    memcpy(&ipi->ipi6_addr.s6_addr, &remote_addr->local_ip_addr.addr.in6,
+        sizeof(ipi->ipi6_addr.s6_addr));
+  }
+#endif
+
 #if 0
     LOG(LOGS_INFO, LOGF_NtpIO, "sending to %s:%d from %s",
         UTI_IPToString(&remote_addr->ip_addr), remote_addr->port, UTI_IPToString(&remote_addr->local_ip_addr));