diff --git a/addressing.h b/addressing.h index aa20ed9..89e82d4 100644 --- a/addressing.h +++ b/addressing.h @@ -35,6 +35,7 @@ number. Both parts are in HOST order, NOT network order. */ typedef struct { unsigned long ip_addr; + unsigned long local_ip_addr; unsigned short port; } NTP_Remote_Address; diff --git a/broadcast.c b/broadcast.c index be217e7..35df56f 100644 --- a/broadcast.c +++ b/broadcast.c @@ -145,6 +145,7 @@ BRD_AddDestination(unsigned long addr, unsigned short port, int interval) } destinations[n_destinations].addr.ip_addr = addr; + destinations[n_destinations].addr.local_ip_addr = 0; destinations[n_destinations].addr.port = port; destinations[n_destinations].interval = interval; diff --git a/cmdmon.c b/cmdmon.c index e2d2ded..f5e3c8b 100644 --- a/cmdmon.c +++ b/cmdmon.c @@ -1104,6 +1104,7 @@ handle_add_server(CMD_Request *rx_message, CMD_Reply *tx_message) NSR_Status status; rem_addr.ip_addr = ntohl(rx_message->data.ntp_source.ip_addr); + rem_addr.local_ip_addr = 0; rem_addr.port = (unsigned short)(ntohl(rx_message->data.ntp_source.port)); params.minpoll = ntohl(rx_message->data.ntp_source.minpoll); params.maxpoll = ntohl(rx_message->data.ntp_source.maxpoll); @@ -1140,6 +1141,7 @@ handle_add_peer(CMD_Request *rx_message, CMD_Reply *tx_message) NSR_Status status; rem_addr.ip_addr = ntohl(rx_message->data.ntp_source.ip_addr); + rem_addr.local_ip_addr = 0; rem_addr.port = (unsigned short)(ntohl(rx_message->data.ntp_source.port)); params.minpoll = ntohl(rx_message->data.ntp_source.minpoll); params.maxpoll = ntohl(rx_message->data.ntp_source.maxpoll); @@ -1174,6 +1176,7 @@ handle_del_source(CMD_Request *rx_message, CMD_Reply *tx_message) NSR_Status status; rem_addr.ip_addr = ntohl(rx_message->data.del_source.ip_addr); + rem_addr.local_ip_addr = 0; rem_addr.port = 0; status = NSR_RemoveSource(&rem_addr); diff --git a/conf.c b/conf.c index b64f390..fdd9d97 100644 --- a/conf.c +++ b/conf.c @@ -1059,6 +1059,7 @@ CNF_AddSources(void) { for (i=0; i 0) { remote_addr.ip_addr = ntohl(where_from.sin_addr.s_addr); + remote_addr.local_ip_addr = 0; remote_addr.port = ntohs(where_from.sin_port); + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) { + struct in_pktinfo ipi; + + memcpy(&ipi, CMSG_DATA(cmsg), sizeof(ipi)); + remote_addr.local_ip_addr = ntohl(ipi.ipi_spec_dst.s_addr); + } + } + if (status == NTP_NORMAL_PACKET_SIZE) { NSR_ProcessReceive((NTP_Packet *) &message.ntp_pkt, &now, &remote_addr); @@ -245,6 +262,9 @@ send_packet(void *packet, int packetlen, NTP_Remote_Address *remote_addr) struct sockaddr_in remote; struct msghdr msg; struct iovec iov; + struct cmsghdr *cmsg; + char cmsgbuf[256]; + int cmsglen; assert(initialised); @@ -258,9 +278,30 @@ send_packet(void *packet, int packetlen, NTP_Remote_Address *remote_addr) msg.msg_namelen = sizeof(remote); msg.msg_iov = &iov; msg.msg_iovlen = 1; - msg.msg_control = NULL; - msg.msg_controllen = 0; + msg.msg_control = cmsgbuf; + msg.msg_controllen = sizeof(cmsgbuf); msg.msg_flags = 0; + cmsglen = 0; + + if (remote_addr->local_ip_addr) { + struct in_pktinfo *ipi; + + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level = IPPROTO_IP; + cmsg->cmsg_type = IP_PKTINFO; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); + cmsglen += CMSG_SPACE(sizeof(struct in_pktinfo)); + + ipi = (struct in_pktinfo *) CMSG_DATA(cmsg); + memset(ipi, 0, sizeof(struct in_pktinfo)); + ipi->ipi_spec_dst.s_addr = htonl(remote_addr->local_ip_addr); +#if 0 + LOG(LOGS_INFO, LOGF_NtpIO, "sending to %s:%d from %s", + UTI_IPToDottedQuad(remote_addr->ip_addr), remote_addr->port, UTI_IPToDottedQuad(remote_addr->local_ip_addr)); +#endif + } + + msg.msg_controllen = cmsglen; if (sendmsg(sock_fd, &msg, 0) < 0) { LOG(LOGS_WARN, LOGF_NtpIO, "Could not send to %s:%d : %s",