Set source IPv6 address on NTP reply

This is needed on systems with multiple IPv6 addresses to reply with
the same source address as the destination address of the NTP request.
This commit is contained in:
Miroslav Lichvar 2011-05-24 18:06:01 +02:00
parent 18605795a7
commit de4d14843f
2 changed files with 49 additions and 0 deletions

9
configure vendored
View file

@ -360,6 +360,15 @@ if [ $feat_ipv6 = "1" ] && \
return !inet_ntop(AF_INET6, &n.sin6_addr.s6_addr, p, sizeof(p));' return !inet_ntop(AF_INET6, &n.sin6_addr.s6_addr, p, sizeof(p));'
then then
add_def HAVE_IPV6 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 fi
if [ $feat_pps = "1" ] && \ if [ $feat_pps = "1" ] && \

View file

@ -159,6 +159,16 @@ prepare_socket(int family)
LOG(LOGS_ERR, LOGF_NtpIO, "Could not request IPV6_V6ONLY socket option"); LOG(LOGS_ERR, LOGF_NtpIO, "Could not request IPV6_V6ONLY socket option");
} }
#endif #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 #endif
@ -345,6 +355,17 @@ read_from_socket(void *anything)
} }
#endif #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 #ifdef SO_TIMESTAMP
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_TIMESTAMP) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_TIMESTAMP) {
struct timeval tv; struct timeval tv;
@ -445,6 +466,25 @@ send_packet(void *packet, int packetlen, NTP_Remote_Address *remote_addr)
} }
#endif #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 #if 0
LOG(LOGS_INFO, LOGF_NtpIO, "sending to %s:%d from %s", 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)); UTI_IPToString(&remote_addr->ip_addr), remote_addr->port, UTI_IPToString(&remote_addr->local_ip_addr));