]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
ntp: add support for IP_RECVDSTADDR and IP_SENDSRCADDR
authorMiroslav Lichvar <mlichvar@redhat.com>
Thu, 30 Aug 2018 09:15:11 +0000 (11:15 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Thu, 30 Aug 2018 09:56:13 +0000 (11:56 +0200)
FreeBSD doesn't support IP_PKTINFO. Instead it provides IP_RECVDSTADDR
and IP_SENDSRCADDR, which can be used to get/set the destination/source
address.

In future IP_RECVIF and IP_SENDIF may be supported to get and set also
the interface.

ntp_io.c

index ec844cb6ee054ac0eb61482f1eb1184ed5abc9b7..b71a1d46493200b2fea3ed55ac0087a444f8dbf0 100644 (file)
--- a/ntp_io.c
+++ b/ntp_io.c
@@ -231,11 +231,11 @@ prepare_socket(int family, int port_number, int client_only)
 
   if (family == AF_INET) {
 #ifdef HAVE_IN_PKTINFO
-    /* We want the local IP info on server sockets */
-    if (setsockopt(sock_fd, IPPROTO_IP, IP_PKTINFO, (char *)&on_off, sizeof(on_off)) < 0) {
+    if (setsockopt(sock_fd, IPPROTO_IP, IP_PKTINFO, (char *)&on_off, sizeof(on_off)) < 0)
       LOG(LOGS_ERR, "Could not set %s socket option", "IP_PKTINFO");
-      /* Don't quit - we might survive anyway */
-    }
+#elif defined(IP_RECVDSTADDR)
+    if (setsockopt(sock_fd, IPPROTO_IP, IP_RECVDSTADDR, (char *)&on_off, sizeof(on_off)) < 0)
+      LOG(LOGS_ERR, "Could not set %s socket option", "IP_RECVDSTADDR");
 #endif
   }
 #ifdef FEAT_IPV6
@@ -642,6 +642,14 @@ process_message(struct msghdr *hdr, int length, int sock_fd)
       local_addr.ip_addr.family = IPADDR_INET4;
       local_addr.if_index = ipi.ipi_ifindex;
     }
+#elif defined(IP_RECVDSTADDR)
+    if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_RECVDSTADDR) {
+      struct in_addr addr;
+
+      memcpy(&addr, CMSG_DATA(cmsg), sizeof (addr));
+      local_addr.ip_addr.addr.in4 = ntohl(addr.s_addr);
+      local_addr.ip_addr.family = IPADDR_INET4;
+    }
 #endif
 
 #ifdef HAVE_IN6_PKTINFO
@@ -813,8 +821,8 @@ NIO_SendPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr,
   msg.msg_flags = 0;
   cmsglen = 0;
 
-#ifdef HAVE_IN_PKTINFO
   if (local_addr->ip_addr.family == IPADDR_INET4) {
+#ifdef HAVE_IN_PKTINFO
     struct in_pktinfo *ipi;
 
     cmsg = CMSG_FIRSTHDR(&msg);
@@ -829,8 +837,21 @@ NIO_SendPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr,
     ipi->ipi_spec_dst.s_addr = htonl(local_addr->ip_addr.addr.in4);
     if (local_addr->if_index != INVALID_IF_INDEX)
       ipi->ipi_ifindex = local_addr->if_index;
-  }
+#elif defined(IP_SENDSRCADDR)
+    struct in_addr *addr;
+
+    cmsg = CMSG_FIRSTHDR(&msg);
+    memset(cmsg, 0, CMSG_SPACE(sizeof (struct in_addr)));
+    cmsglen += CMSG_SPACE(sizeof (struct in_addr));
+
+    cmsg->cmsg_level = IPPROTO_IP;
+    cmsg->cmsg_type = IP_SENDSRCADDR;
+    cmsg->cmsg_len = CMSG_LEN(sizeof (struct in_addr));
+
+    addr = (struct in_addr *)CMSG_DATA(cmsg);
+    addr->s_addr = htonl(local_addr->ip_addr.addr.in4);
 #endif
+  }
 
 #ifdef HAVE_IN6_PKTINFO
   if (local_addr->ip_addr.family == IPADDR_INET6) {