amiga-ntimed/ntp_peer.c

168 lines
4.1 KiB
C
Raw Permalink Normal View History

2014-12-21 22:31:18 +00:00
/*-
* Copyright (c) 2014 Poul-Henning Kamp
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
2015-01-04 12:05:26 +00:00
#include <errno.h>
2014-12-21 22:31:18 +00:00
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <sys/socket.h>
#include "ntimed.h"
2015-04-15 21:52:40 +00:00
#include "mem.h"
2014-12-21 22:31:18 +00:00
#include "udp.h"
#include "ntp.h"
2015-03-19 11:40:19 +00:00
#include "net_getaddrinfo.h"
2015-03-07 22:29:12 +00:00
2014-12-21 22:31:18 +00:00
struct ntp_peer *
NTP_Peer_New(const char *hostname, const void *sa, unsigned salen)
{
struct ntp_peer *np;
char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
AZ(getnameinfo(sa, salen, hbuf, sizeof(hbuf), sbuf,
sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV));
ALLOC_OBJ(np, NTP_PEER_MAGIC);
AN(np);
np->sa_len = salen;
2015-03-17 15:52:05 +00:00
np->sa = allocmem(np->sa_len);
2014-12-21 22:31:18 +00:00
AN(np->sa);
memcpy(np->sa, sa, np->sa_len);
2015-04-15 21:52:40 +00:00
np->hostname = strdup(hostname);
2014-12-21 22:31:18 +00:00
AN(np->hostname);
2015-04-15 21:52:40 +00:00
np->ip = strdup(hbuf);
2014-12-21 22:31:18 +00:00
AN(np->ip);
ALLOC_OBJ(np->tx_pkt, NTP_PACKET_MAGIC);
AN(np->tx_pkt);
ALLOC_OBJ(np->rx_pkt, NTP_PACKET_MAGIC);
AN(np->rx_pkt);
NTP_Tool_Client_Req(np->tx_pkt);
return (np);
}
struct ntp_peer *
NTP_Peer_NewLookup(struct ocx *ocx, const char *hostname)
{
struct addrinfo hints, *res0;
int error;
struct ntp_peer *np;
memset(&hints, 0, sizeof hints);
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
2015-03-07 22:29:12 +00:00
error = getaddrinfo(hostname, "123", &hints, &res0);
2014-12-21 22:31:18 +00:00
if (error)
2015-03-07 22:29:12 +00:00
Fail(ocx, 0, "hostname '%s', port '123': %s\n",
2014-12-21 22:31:18 +00:00
hostname, gai_strerror(error));
np = NTP_Peer_New(hostname, res0->ai_addr, res0->ai_addrlen);
freeaddrinfo(res0);
return (np);
}
void
NTP_Peer_Destroy(struct ntp_peer *np)
{
CHECK_OBJ_NOTNULL(np, NTP_PEER_MAGIC);
2015-03-17 15:52:05 +00:00
freemem(np->sa);
freemem(np->hostname);
freemem(np->ip);
freemem(np->tx_pkt);
freemem(np->rx_pkt);
2014-12-21 22:31:18 +00:00
FREE_OBJ(np);
}
int
2015-01-04 12:05:26 +00:00
NTP_Peer_Poll(struct ocx *ocx, const struct udp_socket *usc,
const struct ntp_peer *np, double tmo)
2014-12-21 22:31:18 +00:00
{
char buf[100];
2015-01-16 21:21:15 +00:00
size_t len;
2014-12-21 22:31:18 +00:00
struct sockaddr_storage rss;
socklen_t rssl;
ssize_t l;
2015-01-04 12:05:26 +00:00
int i;
2014-12-21 22:31:18 +00:00
struct timestamp t0, t1, t2;
double d;
2015-01-04 12:05:26 +00:00
AN(usc);
2014-12-21 22:31:18 +00:00
CHECK_OBJ_NOTNULL(np, NTP_PEER_MAGIC);
assert(tmo > 0.0 && tmo <= 1.0);
len = NTP_Packet_Pack(buf, sizeof buf, np->tx_pkt);
2015-01-04 12:05:26 +00:00
l = Udp_Send(ocx, usc, np->sa, np->sa_len, buf, len);
2015-01-16 21:21:15 +00:00
if (l != (ssize_t)len) {
2015-01-04 12:05:26 +00:00
Debug(ocx, "Tx peer %s %s got %zd (%s)\n",
np->hostname, np->ip, l, strerror(errno));
return (0);
}
2014-12-21 22:31:18 +00:00
(void)TB_Now(&t0);
while (1) {
(void)TB_Now(&t1);
d = TS_Diff(&t1, &t0);
i = UdpTimedRx(ocx, usc, np->sa->sa_family, &rss, &rssl, &t2,
2015-01-04 12:05:26 +00:00
buf, sizeof buf, tmo - d);
2014-12-21 22:31:18 +00:00
if (i == 0)
return (0);
if (i < 0)
Fail(ocx, 1, "Rx failed\n");
if (i != 48) {
2014-12-21 22:56:50 +00:00
Debug(ocx, "Rx peer %s %s got len=%d\n",
np->hostname, np->ip, i);
2014-12-21 22:31:18 +00:00
continue;
}
/* Ignore packets from other hosts */
if (!SA_Equal(np->sa, np->sa_len, &rss, rssl))
2014-12-21 22:31:18 +00:00
continue;
AN(NTP_Packet_Unpack(np->rx_pkt, buf, i));
np->rx_pkt->ts_rx = t2;
/* Ignore packets which are not replies to our packet */
if (TS_Diff(&np->tx_pkt->ntp_transmit,
&np->rx_pkt->ntp_origin) != 0.0) {
continue;
}
return (1);
}
}