From eb7db0adcdcc5baf155d5c3860677be8ac9aa476 Mon Sep 17 00:00:00 2001 From: Poul-Henning Kamp Date: Sun, 4 Jan 2015 12:05:26 +0000 Subject: [PATCH] Fix IPv6 by wrapping UDP in a struct. --- combine_delta.c | 1 - main_client.c | 8 ++-- main_poll_server.c | 10 ++--- ntimed.h | 2 +- ntp.h | 7 ++-- ntp_peer.c | 38 ++++++----------- ntp_peerset.c | 11 ++--- pll_std.c | 6 +-- udp.c | 100 +++++++++++++++++++++++++++++++++++++++++---- udp.h | 12 ++++-- 10 files changed, 137 insertions(+), 58 deletions(-) diff --git a/combine_delta.c b/combine_delta.c index abd0c2a..71e79a8 100644 --- a/combine_delta.c +++ b/combine_delta.c @@ -49,7 +49,6 @@ #include "ntimed.h" -struct combine_delta; struct cd_stat { double x; diff --git a/main_client.c b/main_client.c index d1e3b97..37932e6 100644 --- a/main_client.c +++ b/main_client.c @@ -52,7 +52,7 @@ main_client(int argc, char *const *argv) struct ntp_peerset *npl; struct todolist *tdl; struct combine_delta *cd; - int fd; + struct udp_socket *usc; int npeer = 0; setbuf(stdout, NULL); @@ -96,8 +96,8 @@ main_client(int argc, char *const *argv) Param_Report(NULL, OCX_TRACE); - fd = UdpTimedSocket(NULL, AF_INET); - if (fd < 0) + usc = UdpTimedSocket(NULL); + if (usc == NULL) Fail(NULL, errno, "Could not open UDP socket"); cd = CD_New(); @@ -107,7 +107,7 @@ main_client(int argc, char *const *argv) np->combiner = CD_AddSource(cd, np->hostname, np->ip); } - NTP_PeerSet_Poll(NULL, npl, fd, tdl); + NTP_PeerSet_Poll(NULL, npl, usc, tdl); (void)TODO_Run(NULL, tdl); diff --git a/main_poll_server.c b/main_poll_server.c index 0f515ea..1da8381 100644 --- a/main_poll_server.c +++ b/main_poll_server.c @@ -40,7 +40,7 @@ #include "ntp.h" #include "udp.h" -static int fd; +static struct udp_socket *usc; static void mps_filter(struct ocx *ocx, const struct ntp_peer *np) @@ -61,7 +61,7 @@ mps_mon(struct ocx *ocx, struct todolist *tdl, void *priv) (void)ocx; (void)tdl; CAST_OBJ_NOTNULL(np, priv, NTP_PEER_MAGIC); - i = NTP_Peer_Poll(ocx, fd, np, 0.2); + i = NTP_Peer_Poll(ocx, usc, np, 0.2); if (i == 1) { NTP_Tool_Format(buf, sizeof buf, np->rx_pkt); Put(ocx, OCX_TRACE, @@ -146,15 +146,15 @@ main_poll_server(int argc, char *const *argv) Put(NULL, OCX_TRACE, "# Monitor %s %s\n", mon->hostname, mon->ip); - fd = UdpTimedSocket(NULL, AF_INET); - assert(fd >= 0); + usc = UdpTimedSocket(NULL); + assert(usc != NULL); TODO_ScheduleRel(tdl, mps_end, NULL, duration, 0, "End task"); if (mon != NULL) TODO_ScheduleRel(tdl, mps_mon, mon, 0, 32, "Monitor"); - NTP_PeerSet_Poll(NULL, npl, fd, tdl); + NTP_PeerSet_Poll(NULL, npl, usc, tdl); (void)TODO_Run(NULL, tdl); return (0); } diff --git a/ntimed.h b/ntimed.h index 69342dc..f172041 100644 --- a/ntimed.h +++ b/ntimed.h @@ -38,6 +38,7 @@ #include "ntimed_tricks.h" struct todolist; +struct udp_socket; /* ocx_*.c -- Operational Context *************************************/ @@ -133,7 +134,6 @@ void TS_RunTest(struct ocx *ocx); /* todo.c -- todo-list scheduler **************************************/ -struct todo; // private enum todo_e { TODO_FAIL = -1, // Break out of TODO_Run() diff --git a/ntp.h b/ntp.h index 11fc752..e2f75ac 100644 --- a/ntp.h +++ b/ntp.h @@ -28,7 +28,6 @@ * */ -struct sockaddr; struct ntp_peer; #ifdef NTP_H_INCLUDED @@ -90,7 +89,6 @@ void NF_Init(void); /* ntp_peer.c -- State management *************************************/ -struct ntp_group; struct ntp_peer { unsigned magic; @@ -115,7 +113,8 @@ struct ntp_peer { struct ntp_peer *NTP_Peer_New(const char *name, const void *, unsigned); struct ntp_peer *NTP_Peer_NewLookup(struct ocx *ocx, const char *name); void NTP_Peer_Destroy(struct ntp_peer *np); -int NTP_Peer_Poll(struct ocx *, int fd, const struct ntp_peer *, double tmo); +int NTP_Peer_Poll(struct ocx *, const struct udp_socket *, + const struct ntp_peer *, double tmo); /* ntp_peerset.c -- Peer set management ****************************/ @@ -124,7 +123,7 @@ void NTP_PeerSet_AddPeer(struct ocx *ocx, struct ntp_peerset *npl, struct ntp_peer *np); int NTP_PeerSet_Add(struct ocx *, struct ntp_peerset *, const char *hostname); -void NTP_PeerSet_Poll(struct ocx *, struct ntp_peerset *, int, +void NTP_PeerSet_Poll(struct ocx *, struct ntp_peerset *, struct udp_socket *, struct todolist *); struct ntp_peer *NTP_PeerSet_Iter0(const struct ntp_peerset *); diff --git a/ntp_peer.c b/ntp_peer.c index 79095e3..94c5904 100644 --- a/ntp_peer.c +++ b/ntp_peer.c @@ -25,10 +25,9 @@ * */ -#include +#include #include #include -#include #include #include @@ -103,28 +102,30 @@ NTP_Peer_Destroy(struct ntp_peer *np) } int -NTP_Peer_Poll(struct ocx *ocx, int fd, const struct ntp_peer *np, double tmo) +NTP_Peer_Poll(struct ocx *ocx, const struct udp_socket *usc, + const struct ntp_peer *np, double tmo) { char buf[100]; ssize_t len; struct sockaddr_storage rss; socklen_t rssl; ssize_t l; - int i, timeout_msec; - struct pollfd pfd[1]; + int i; struct timestamp t0, t1, t2; double d; - assert(fd >= 0); + AN(usc); CHECK_OBJ_NOTNULL(np, NTP_PEER_MAGIC); assert(tmo > 0.0 && tmo <= 1.0); len = NTP_Packet_Pack(buf, sizeof buf, np->tx_pkt); - l = sendto(fd, buf, len, 0, np->sa, np->sa_len); - if (l != len) - Fail(ocx, l < 0 ? 1 : 0, - "Tx peer %s %s got %zd", np->hostname, np->ip, l); + l = Udp_Send(ocx, usc, np->sa, np->sa_len, buf, len); + if (l != len) { + Debug(ocx, "Tx peer %s %s got %zd (%s)\n", + np->hostname, np->ip, l, strerror(errno)); + return (0); + } (void)TB_Now(&t0); @@ -132,25 +133,12 @@ NTP_Peer_Poll(struct ocx *ocx, int fd, const struct ntp_peer *np, double tmo) (void)TB_Now(&t1); d = TS_Diff(&t1, &t0); - timeout_msec = lround(1e3 * (tmo - d)); - - pfd[0].fd = fd; - pfd[0].events = POLLIN; - pfd[0].revents = 0; - - if (timeout_msec <= 0) - i = 0; - else - i = poll(pfd, 1, timeout_msec); - - if (i < 0) - Fail(ocx, 1, "poll(2) failed\n"); + i = UdpTimedRx(ocx, usc, &rss, &rssl, &t2, + buf, sizeof buf, tmo - d); if (i == 0) return (0); - i = UdpTimedRx(ocx, fd, &rss, &rssl, &t2, buf, sizeof buf); - if (i < 0) Fail(ocx, 1, "Rx failed\n"); diff --git a/ntp_peerset.c b/ntp_peerset.c index 1bf6910..07f9936 100644 --- a/ntp_peerset.c +++ b/ntp_peerset.c @@ -53,7 +53,7 @@ struct ntp_peerset { TAILQ_HEAD(,ntp_group) group; int ngroup; - int fd; + struct udp_socket *usc; double t0; double init_duration; double poll_period; @@ -186,7 +186,7 @@ ntp_peerset_poll(struct ocx *ocx, struct todolist *tdl, void *priv) } npl->t0 += d; TODO_ScheduleRel(tdl, ntp_peerset_poll, npl, d, 0.0, "NTP_PeerSet"); - if (NTP_Peer_Poll(ocx, npl->fd, np, 0.8)) { + if (NTP_Peer_Poll(ocx, npl->usc, np, 0.8)) { if (np->filter_func != NULL) np->filter_func(ocx, np); } @@ -214,16 +214,17 @@ ntp_peerset_herd(struct ocx *ocx, struct todolist *tdl, void *priv) /**********************************************************************/ void -NTP_PeerSet_Poll(struct ocx *ocx, struct ntp_peerset *npl, int fd, +NTP_PeerSet_Poll(struct ocx *ocx, struct ntp_peerset *npl, + struct udp_socket *usc, struct todolist *tdl) { (void)ocx; CHECK_OBJ_NOTNULL(npl, NTP_PEERSET_MAGIC); - assert(fd >= 0); + AN(usc); AN(tdl); - npl->fd = fd; + npl->usc = usc; npl->t0 = 1.0; npl->init_duration = 64.; npl->init_packets = 6.; diff --git a/pll_std.c b/pll_std.c index 18ba543..6344963 100644 --- a/pll_std.c +++ b/pll_std.c @@ -102,16 +102,16 @@ pll_std(struct ocx *ocx, double offset, double weight) * Ideally, we should scale the pll_[ab] terms and the * stiffening of them based on the weight. That is harder * than it sounds -- or at least I have not found a good - * candidate function yet. + * candidate function yet. * In the meantime this is a simple threshold based * prevention of horribly distant servers injecting too * much noise into the very reactive default PLL. * Some averaging of the weight may be required. */ - if (weight < 50) { + if (weight < 50) { used_a = 3e-2; used_b = 5e-4; - } else if (weight < 150) { + } else if (weight < 150) { used_a = 6e-2; used_b = 1e-3; } else { diff --git a/udp.c b/udp.c index 0ef1cae..a13a12e 100644 --- a/udp.c +++ b/udp.c @@ -24,21 +24,32 @@ * SUCH DAMAGE. */ +#include +#include +#include #include #include #include "ntimed.h" #include "udp.h" -int -UdpTimedSocket(struct ocx *ocx, int fam) +struct udp_socket { + unsigned magic; +#define UDP_SOCKET_MAGIC 0x302a563f + + int fd4; + int fd6; +}; + +static int +udp_sock(int fam) { int fd; int i; fd = socket(fam, SOCK_DGRAM, 0); if (fd < 0) - Fail(ocx, 1, "socket(2) failed"); + return (fd); #ifdef IP_RECVDSTADDR i = 1; @@ -57,23 +68,69 @@ UdpTimedSocket(struct ocx *ocx, int fam) return (fd); } +struct udp_socket * +UdpTimedSocket(struct ocx *ocx) +{ + struct udp_socket *usc; + + ALLOC_OBJ(usc, UDP_SOCKET_MAGIC); + AN(usc); + usc->fd4 = udp_sock(AF_INET); + usc->fd6 = udp_sock(AF_INET6); + if (usc->fd4 < 0 && usc->fd6 < 0) + Fail(ocx, 1, "socket(2) failed"); + return (usc); +} + ssize_t -UdpTimedRx(struct ocx *ocx, int fd, struct sockaddr_storage *ss, socklen_t *sl, - struct timestamp *ts, void *buf, ssize_t len) +UdpTimedRx(struct ocx *ocx, const struct udp_socket *usc, + struct sockaddr_storage *ss, socklen_t *sl, + struct timestamp *ts, void *buf, ssize_t len, double tmo) { struct msghdr msg; struct iovec iov; struct cmsghdr *cmsg; u_char ctrl[1024]; ssize_t rl; + int i, j; + int tmo_msec; + struct pollfd pfd[2]; - assert(fd >= 0); + CHECK_OBJ_NOTNULL(usc, UDP_SOCKET_MAGIC); AN(ss); AN(sl); AN(ts); AN(buf); assert(len > 0); + + j = 0; + if (usc->fd4 >= 0) { + pfd[j].fd = usc->fd4; + pfd[j].events = POLLIN; + pfd[j++].revents = 0; + } + if (usc->fd6 >= 0) { + pfd[j].fd = usc->fd6; + pfd[j].events = POLLIN; + pfd[j++].revents = 0; + } + + if (tmo == 0.0) { + tmo_msec = -1; + } else { + tmo_msec = lround(1e3 * tmo); + if (tmo_msec <= 0) + tmo_msec = 0; + } + i = poll(pfd, j, tmo_msec); + + if (i < 0) + Fail(ocx, 1, "poll(2) failed\n"); + + if (i == 0) + return (0); + memset(&msg, 0, sizeof msg); msg.msg_name = (void*)ss; msg.msg_namelen = sizeof *ss; @@ -86,7 +143,14 @@ UdpTimedRx(struct ocx *ocx, int fd, struct sockaddr_storage *ss, socklen_t *sl, memset(ctrl, 0, sizeof ctrl); cmsg = (void*)ctrl; - rl = recvmsg(fd, &msg, 0); + for (i = 0; i < j; i++) + if (pfd[i].revents & POLLIN) + break; + + if (i == j) + return (0); + + rl = recvmsg(pfd[i].fd, &msg, 0); if (rl <= 0) return (rl); @@ -129,3 +193,25 @@ UdpTimedRx(struct ocx *ocx, int fd, struct sockaddr_storage *ss, socklen_t *sl, } return (rl); } + +ssize_t +Udp_Send(struct ocx *ocx, const struct udp_socket *usc, + const void *ss, socklen_t sl, const void *buf, ssize_t len) +{ + const struct sockaddr *sa; + + (void)ocx; + CHECK_OBJ_NOTNULL(usc, UDP_SOCKET_MAGIC); + AN(ss); + AN(sl); + AN(buf); + AN(len); + sa = ss; + if (sa->sa_family == AF_INET) + return (sendto(usc->fd4, buf, len, 0, ss, sl)); + if (sa->sa_family == AF_INET6) + return (sendto(usc->fd6, buf, len, 0, ss, sl)); + + WRONG("Wrong AF_"); + return (0); +} diff --git a/udp.h b/udp.h index cd19c19..5916efe 100644 --- a/udp.h +++ b/udp.h @@ -33,7 +33,13 @@ * UDP sockets */ -int UdpTimedSocket(struct ocx *ocx, int fam); -ssize_t UdpTimedRx(struct ocx *ocx, int fd, struct sockaddr_storage *ss, - socklen_t *sl, struct timestamp *ts, void *buf, ssize_t len); + +struct udp_socket *UdpTimedSocket(struct ocx *ocx); +ssize_t UdpTimedRx(struct ocx *, const struct udp_socket *, + struct sockaddr_storage *, socklen_t *, + struct timestamp *, + void *, ssize_t len, + double tmo); +ssize_t Udp_Send(struct ocx *, const struct udp_socket *, + const void *sa, socklen_t, const void *ptr, ssize_t);