Hello community,

here is the log from the commit of package chrony for openSUSE:Factory checked 
in at 2020-02-15 22:21:54
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/chrony (Old)
 and      /work/SRC/openSUSE:Factory/.chrony.new.26092 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "chrony"

Sat Feb 15 22:21:54 2020 rev:22 rq:774160 version:3.5

Changes:
--------
--- /work/SRC/openSUSE:Factory/chrony/chrony.changes    2019-11-08 
15:22:06.470765136 +0100
+++ /work/SRC/openSUSE:Factory/.chrony.new.26092/chrony.changes 2020-02-15 
22:21:56.459196853 +0100
@@ -1,0 +2,12 @@
+Thu Feb 13 12:45:44 UTC 2020 - Martin Liška <mli...@suse.cz>
+
+- Add chrony-test-update-processing-of-packet-log.patch in order
+  to fix test-suite failure.
+
+-------------------------------------------------------------------
+Wed Feb 12 09:24:24 UTC 2020 - Martin Liška <mli...@suse.cz>
+
+- Update clknetsim to version 79ffe44 (fixes boo#1162964).
+- Backport chrony-test-fix-util-unit-test-for-NTP-era-split.patch.
+
+-------------------------------------------------------------------

Old:
----
  clknetsim-58c5e8b.tar.gz

New:
----
  chrony-test-fix-util-unit-test-for-NTP-era-split.patch
  chrony-test-update-processing-of-packet-log.patch
  clknetsim-79ffe44.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ chrony.spec ++++++
--- /var/tmp/diff_new_pack.hEGU6o/_old  2020-02-15 22:21:57.779197567 +0100
+++ /var/tmp/diff_new_pack.hEGU6o/_new  2020-02-15 22:21:57.783197569 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package chrony
 #
-# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2020 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -17,7 +17,7 @@
 
 
 %define vendorzone opensuse.
-%global clknetsim_ver 58c5e8b
+%global clknetsim_ver 79ffe44
 #Compat macro for new _fillupdir macro introduced in Nov 2017
 %if ! %{defined _fillupdir}
   %define _fillupdir %{_localstatedir}/adm/fillup-templates
@@ -46,6 +46,8 @@
 Patch1:         chrony-service-helper.patch
 Patch2:         chrony-logrotate.patch
 Patch3:         chrony-service-ordering.patch
+Patch4:         chrony-test-fix-util-unit-test-for-NTP-era-split.patch
+Patch5:         chrony-test-update-processing-of-packet-log.patch
 BuildRequires:  NetworkManager-devel
 BuildRequires:  bison
 BuildRequires:  gcc-c++
@@ -98,6 +100,8 @@
 %patch1 -p1
 %patch2 -p1
 %patch3
+%patch4 -p1
+%patch5 -p1
 
 # If this is an openSUSE build, use our vendor zone
 # (2.*pool.ntp.org names include IPv6 addresses). If not


++++++ chrony-test-fix-util-unit-test-for-NTP-era-split.patch ++++++
>From 2d9eb5b6fa5225a7300c8eed95712969249900fb Mon Sep 17 00:00:00 2001
From: Miroslav Lichvar <mlich...@redhat.com>
Date: Fri, 3 Jan 2020 11:25:55 +0100
Subject: [PATCH] test: fix util unit test for NTP era split

The current default NTP era split passed the Unix epoch (~50 years ago),
which means the epoch converted to an NTP timestamp and back ends up in
the next NTP era (year 2106).

Fix the test to take into account the era split.
---
 test/unit/util.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/test/unit/util.c b/test/unit/util.c
index f4d9f33..af9e90c 100644
--- a/test/unit/util.c
+++ b/test/unit/util.c
@@ -100,11 +100,19 @@ void test_unit(void) {
   ntp_ts.hi = htonl(JAN_1970);
   ntp_ts.lo = 0xffffffff;
   UTI_Ntp64ToTimespec(&ntp_ts, &ts);
+#if defined(HAVE_LONG_TIME_T) && NTP_ERA_SPLIT > 0
+  TEST_CHECK(ts.tv_sec == 0x100000000LL * (1 + (NTP_ERA_SPLIT - 1) / 
0x100000000LL));
+#else
   TEST_CHECK(ts.tv_sec == 0);
+#endif
   TEST_CHECK(ts.tv_nsec == 999999999);
 
   UTI_AddDoubleToTimespec(&ts, 1e-9, &ts);
+#if defined(HAVE_LONG_TIME_T) && NTP_ERA_SPLIT > 0
+  TEST_CHECK(ts.tv_sec == 1 + 0x100000000LL * (1 + (NTP_ERA_SPLIT - 1) / 
0x100000000LL));
+#else
   TEST_CHECK(ts.tv_sec == 1);
+#endif
   TEST_CHECK(ts.tv_nsec == 0);
 
   ntp_fuzz.hi = 0;
-- 
2.25.0

++++++ chrony-test-update-processing-of-packet-log.patch ++++++
>From 62d6aed6a64b887c9e3b7f03d9e0db1deaa2696a Mon Sep 17 00:00:00 2001
From: Miroslav Lichvar <mlich...@redhat.com>
Date: Tue, 18 Jun 2019 15:41:50 +0200
Subject: [PATCH] test: update processing of packet log

Two new fields have been added to the packet log, which broke some
of the simulation tests.
---
 test/simulation/test.common | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/test/simulation/test.common b/test/simulation/test.common
index 951a794..8ed6ad9 100644
--- a/test/simulation/test.common
+++ b/test/simulation/test.common
@@ -391,9 +391,9 @@ check_packet_port() {
        for i in $(seq 1 $(get_chronyd_nodes)); do
                test_message 3 0 "node $i:"
 
-               grep -E -q "    $port   [0-9]+\$" tmp/log.packets && \
+               grep -E -q "^([0-9e.+-]+        ){5}$port       " 
tmp/log.packets && \
                        ! grep -E "^[0-9e.+-]+  $i      " tmp/log.packets | \
-                       grep -E -q -v " $port   [0-9]+\$" && \
+                       grep -E -q -v "^([0-9e.+-]+     ){5}$port       " && \
                        test_ok || test_bad
                [ $? -eq 0 ] || ret=1
        done
-- 
2.25.0


++++++ clknetsim-58c5e8b.tar.gz -> clknetsim-79ffe44.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/clknetsim-58c5e8bd6d041ff30e9c7dbe45162a73e99f3d24/Makefile 
new/clknetsim-79ffe448f262d0a411fe44380df94d504b965b2e/Makefile
--- old/clknetsim-58c5e8bd6d041ff30e9c7dbe45162a73e99f3d24/Makefile     
2019-01-28 10:35:17.000000000 +0100
+++ new/clknetsim-79ffe448f262d0a411fe44380df94d504b965b2e/Makefile     
2019-11-26 10:05:32.000000000 +0100
@@ -1,10 +1,11 @@
-CC ?= gcc
-CXX ?= g++
 CFLAGS += -O2 -Wall -g -fPIC
 CXXFLAGS += $(CFLAGS)
+CPPFLAGS += $(apiflags)
 
 all: clknetsim.so clknetsim
 
+apiflags := $(shell grep -q __timezone_ptr_t /usr/include/sys/time.h || echo 
-DGETTIMEOFDAY_VOID)
+
 clientobjs = client.o
 serverobjs = $(patsubst %.cc,%.o,$(wildcard *.cc))
 
@@ -15,7 +16,7 @@
        $(CXX) $(CFLAGS) -o $@ $^ $(LDFLAGS)
 
 clean:
-       rm -rf server *.so *.o core.* .deps
+       rm -rf clknetsim *.so *.o core.* .deps
 
 .deps:
        @mkdir .deps
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/clknetsim-58c5e8bd6d041ff30e9c7dbe45162a73e99f3d24/client.c 
new/clknetsim-79ffe448f262d0a411fe44380df94d504b965b2e/client.c
--- old/clknetsim-58c5e8bd6d041ff30e9c7dbe45162a73e99f3d24/client.c     
2019-01-28 10:35:17.000000000 +0100
+++ new/clknetsim-79ffe448f262d0a411fe44380df94d504b965b2e/client.c     
2019-11-26 10:05:32.000000000 +0100
@@ -21,6 +21,7 @@
 #include <sys/timex.h>
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <sys/stat.h>
 #include <sys/syscall.h>
 #include <sys/timerfd.h>
 #include <sys/ipc.h>
@@ -38,6 +39,7 @@
 #include <errno.h>
 #include <sys/ioctl.h>
 #include <net/if.h>
+#include <netdb.h>
 #include <pwd.h>
 #include <stdarg.h>
 #include <signal.h>
@@ -65,12 +67,15 @@
 #define PTP_PRIMARY_MCAST_ADDR 0xe0000181 /* 224.0.1.129 */
 #define PTP_PDELAY_MCAST_ADDR 0xe000006b /* 224.0.0.107 */
 
+#define LINK_SPEED 100000
+
 #define REFCLK_FD 1000
 #define REFCLK_ID ((~(clockid_t)REFCLK_FD << 3) | 3)
 #define REFCLK_PHC_INDEX 0
 #define SYSCLK_FD 1001
 #define SYSCLK_CLOCKID ((~(clockid_t)SYSCLK_FD << 3) | 3)
 #define SYSCLK_PHC_INDEX 1
+#define URANDOM_FD 1010
 
 #define MAX_SOCKETS 20
 #define BASE_SOCKET_FD 100
@@ -83,10 +88,13 @@
 #define URANDOM_FILE (void *)0xD1230123
 
 static FILE *(*_fopen)(const char *path, const char *mode);
+static FILE *(*_fdopen)(int fd, const char *mode);
 static size_t (*_fread)(void *ptr, size_t size, size_t nmemb, FILE *stream);
 static int (*_fileno)(FILE *stream);
 static int (*_fclose)(FILE *fp);
-static int (*_open)(const char *pathname, int flags);
+static int (*_fcntl)(int fd, int cmd, ...);
+static int (*_open)(const char *pathname, int flags, mode_t mode);
+static ssize_t (*_read)(int fd, void *buf, size_t count);
 static int (*_close)(int fd);
 static int (*_socket)(int domain, int type, int protocol);
 static int (*_connect)(int sockfd, const struct sockaddr *addr, socklen_t 
addrlen);
@@ -112,7 +120,7 @@
        IFACE_ETH0,
 };
 
-struct ts_message {
+struct message {
        char data[MAX_PACKET_SIZE];
        unsigned int len;
        unsigned int subnet;
@@ -127,10 +135,13 @@
        int iface;
        int remote_node;
        int remote_port;
+       int listening;
+       int connected;
        int broadcast;
        int pkt_info;
        int time_stamping;
-       struct ts_message last_ts_msg;
+       struct message last_ts_msg;
+       struct message buffer;
 };
 
 static struct socket sockets[MAX_SOCKETS];
@@ -197,10 +208,13 @@
                return;
 
        _fopen = (FILE *(*)(const char *path, const char 
*mode))dlsym(RTLD_NEXT, "fopen");
+       _fdopen = (FILE *(*)(int fd, const char *mode))dlsym(RTLD_NEXT, 
"fdopen");
        _fread = (size_t (*)(void *ptr, size_t size, size_t nmemb, FILE 
*stream))dlsym(RTLD_NEXT, "fread");
        _fileno = (int (*)(FILE *stream))dlsym(RTLD_NEXT, "fileno");
        _fclose = (int (*)(FILE *fp))dlsym(RTLD_NEXT, "fclose");
-       _open = (int (*)(const char *pathname, int flags))dlsym(RTLD_NEXT, 
"open");
+       _fcntl = (int (*)(int fd, int cmd, ...))dlsym(RTLD_NEXT, "fcntl");
+       _open = (int (*)(const char *pathname, int flags, mode_t 
mode))dlsym(RTLD_NEXT, "open");
+       _read = (ssize_t (*)(int fd, void *buf, size_t count))dlsym(RTLD_NEXT, 
"read");
        _close = (int (*)(int fd))dlsym(RTLD_NEXT, "close");
        _socket = (int (*)(int domain, int type, int protocol))dlsym(RTLD_NEXT, 
"socket");
        _connect = (int (*)(int sockfd, const struct sockaddr *addr, socklen_t 
addrlen))dlsym(RTLD_NEXT, "connect");
@@ -285,7 +299,7 @@
        assert(initialized);
 
        if (fuzz_mode) {
-               fuzz_process_reply(request_id, request_data, reply, replylen);
+               fuzz_process_request(request_id, request_data, reply, replylen);
                return;
        }
 
@@ -466,25 +480,71 @@
        return s + BASE_SOCKET_FD;
 }
 
-static int find_recv_socket(int subnet, int port, int broadcast) {
+static int find_recv_socket(struct Reply_select *rep) {
        int i, s = -1;
 
        for (i = 0; i < MAX_SOCKETS; i++) {
-               if (!sockets[i].used ||
-                               !socket_in_subnet(i, subnet) ||
-                               sockets[i].type != SOCK_DGRAM ||
-                               (port && sockets[i].port != port))
+               if (!sockets[i].used)
+                       continue;
+
+               if (rep == NULL)
+                       return i;
+
+               if (!socket_in_subnet(i, rep->subnet) ||
+                   (rep->dst_port && sockets[i].port != rep->dst_port) ||
+                   (sockets[i].remote_node != -1 && sockets[i].remote_node != 
rep->from) ||
+                   (sockets[i].remote_port && sockets[i].remote_port != 
rep->src_port))
                        continue;
+
+               switch (rep->type) {
+                       case MSG_TYPE_NO_MSG:
+                               break;
+                       case MSG_TYPE_UDP_DATA:
+                               if (sockets[i].type != SOCK_DGRAM)
+                                       continue;
+                               break;
+                       case MSG_TYPE_TCP_CONNECT:
+                               if (sockets[i].type != SOCK_STREAM || 
sockets[i].connected)
+                                       continue;
+                               break;
+                       case MSG_TYPE_TCP_DATA:
+                       case MSG_TYPE_TCP_DISCONNECT:
+                               if (sockets[i].type != SOCK_STREAM ||
+                                   sockets[i].listening || 
!sockets[i].connected)
+                                       continue;
+                               break;
+                       default:
+                               assert(0);
+               }
+
                if (s < 0 || sockets[s].iface < sockets[i].iface ||
-                               (broadcast && sockets[i].broadcast) ||
-                               (!broadcast && sockets[s].broadcast &&
-                                !sockets[i].broadcast))
+                   (rep->ret == REPLY_SELECT_BROADCAST && 
sockets[i].broadcast) ||
+                   (rep->ret != REPLY_SELECT_BROADCAST && sockets[s].broadcast 
&&
+                    !sockets[i].broadcast))
                        s = i;
        }
 
        return s;
 }
 
+static void send_msg_to_peer(int s, int type) {
+       struct Request_send req;
+
+       assert(sockets[s].type == SOCK_STREAM);
+
+       if (sockets[s].remote_node == -1)
+               return;
+
+       req.type = type;
+       req.subnet = sockets[s].iface - IFACE_ETH0;
+       req.to = sockets[s].remote_node;
+       req.src_port = sockets[s].port;
+       req.dst_port = sockets[s].remote_port;
+       req.len = 0;
+
+       make_request(REQ_SEND, &req, offsetof(struct Request_send, data), NULL, 
0);
+}
+
 static int get_free_timer(void) {
        int i;
 
@@ -563,7 +623,30 @@
        return tp->tv_sec + offset + tp->tv_nsec / 1e9;
 }
 
-int gettimeofday(struct timeval *tv, struct timezone *tz) {
+static void normalize_timespec(struct timespec *tp) {
+       while (tp->tv_nsec >= 1000000000) {
+               tp->tv_nsec -= 1000000000;
+               tp->tv_sec++;
+       }
+       while (tp->tv_nsec < 0) {
+               tp->tv_nsec += 1000000000;
+               tp->tv_sec--;
+       }
+}
+
+static void add_to_timespec(struct timespec *tp, double offset) {
+       tp->tv_sec += floor(offset);
+       tp->tv_nsec += (offset - floor(offset)) * 1e9;
+       normalize_timespec(tp);
+}
+
+int gettimeofday(struct timeval *tv,
+#if !defined(__GLIBC_PREREQ) || __GLIBC_PREREQ(2, 31) || 
defined(GETTIMEOFDAY_VOID)
+                void *tz
+#else
+                struct timezone *tz
+#endif
+                ) {
        double time;
 
        time = get_real_time() + 0.5e-6;
@@ -583,10 +666,12 @@
 
        switch (which_clock) {
                case CLOCK_REALTIME:
+               case CLOCK_REALTIME_COARSE:
                case SYSCLK_CLOCKID:
                        time = get_real_time();
                        break;
                case CLOCK_MONOTONIC:
+               case CLOCK_MONOTONIC_COARSE:
                        time = get_monotonic_time();
                        break;
                case REFCLK_ID:
@@ -720,11 +805,28 @@
        int i, timer, s, recv_fd = -1;
        double elapsed = 0.0;
 
-       if (writefds)
+       if (writefds) {
+               for (i = 0; i < nfds; i++) {
+                       if (!FD_ISSET(i, writefds))
+                               continue;
+                       s = get_socket_from_fd(i);
+                       if (s < 0 ||
+                           (sockets[s].type == SOCK_STREAM && 
!sockets[s].connected))
+                               continue;
+                       FD_ZERO(writefds);
+                       FD_SET(i, writefds);
+                       if (exceptfds)
+                               FD_ZERO(exceptfds);
+                       if (readfds)
+                               FD_ZERO(readfds);
+                       return 1;
+               }
+
                FD_ZERO(writefds);
+       }
 
        if (exceptfds) {
-               /* chronyd waiting for TX timestamp from the error queue */
+               /* TX timestamp available in the error queue */
                for (i = 0; i < nfds; i++) {
                        if (!FD_ISSET(i, exceptfds) || get_socket_from_fd(i) < 
0 ||
                                        
!sockets[get_socket_from_fd(i)].last_ts_msg.len)
@@ -749,8 +851,9 @@
                for (i = 0; i < nfds; i++) {
                        if (!FD_ISSET(i, readfds))
                                continue;
-                       if (get_socket_from_fd(i) < 0 &&
-                                       get_timer_from_fd(i) < 0) {
+                       s = get_socket_from_fd(i);
+                       if ((s < 0 && get_timer_from_fd(i) < 0) ||
+                           (s >= 0 && sockets[s].buffer.len > 0)) {
                                FD_ZERO(readfds);
                                FD_SET(i, readfds);
                                return 1;
@@ -762,7 +865,7 @@
        timer = get_first_timer(readfds);
 
        assert((timeout && (timeout->tv_sec > 0 || timeout->tv_usec > 0)) ||
-                       timer >= 0 || find_recv_socket(0, 0, 0) >= 0);
+              timer >= 0 || find_recv_socket(NULL) >= 0);
 
        fetch_time();
 
@@ -821,8 +924,7 @@
 
                case REPLY_SELECT_NORMAL:
                case REPLY_SELECT_BROADCAST:
-                       s = find_recv_socket(rep.subnet, rep.dst_port,
-                                       rep.ret == REPLY_SELECT_BROADCAST);
+                       s = find_recv_socket(&rep);
                        recv_fd = s >= 0 ? get_socket_fd(s) : 0;
 
                        /* fetch and drop the packet if no fd is waiting for it 
*/
@@ -831,15 +933,29 @@
 
                                make_request(REQ_RECV, NULL, 0, &recv_rep, 
sizeof (recv_rep));
                                if (rep.ret != REPLY_SELECT_BROADCAST)
-                                       fprintf(stderr, "clknetsim: dropped 
packet from "
+                                       fprintf(stderr, "clknetsim: dropped 
packet of type %d from "
                                                        "node %d on port %d in 
subnet %d\n",
-                                                       recv_rep.from + 1, 
recv_rep.dst_port,
-                                                       recv_rep.subnet + 1);
+                                                       recv_rep.type, 
recv_rep.from + 1,
+                                                       recv_rep.dst_port, 
recv_rep.subnet + 1);
 
                                goto try_again;
                        }
-                       break;
 
+                       if (rep.type == MSG_TYPE_TCP_CONNECT &&
+                           !sockets[s].listening && !sockets[s].connected) {
+                               struct Reply_recv recv_rep;
+
+                               /* drop the connection packet and let the 
client repeat the call
+                                  in order to see that the socket is ready for 
writing */
+                               make_request(REQ_RECV, NULL, 0, &recv_rep, 
sizeof (recv_rep));
+
+                               assert(recv_rep.type == MSG_TYPE_TCP_CONNECT);
+                               assert(sockets[s].type == SOCK_STREAM);
+                               sockets[s].connected = 1;
+                               errno = EINTR;
+                               return -1;
+                       }
+                       break;
                default:
                        assert(0);
                        return 0;
@@ -869,39 +985,27 @@
 #ifndef CLKNETSIM_DISABLE_POLL
 int poll(struct pollfd *fds, nfds_t nfds, int timeout) {
        struct timeval tv, *ptv = NULL;
+       fd_set rfds, wfds, efds;
        int r, maxfd = 0;
        nfds_t i;
-       fd_set rfds;
-
-       /* ptp4l waiting for tx SO_TIMESTAMPING */
-       if (nfds == 1 && fds[0].events != POLLOUT && 
get_socket_from_fd(fds[0].fd) >= 0 &&
-           sockets[get_socket_from_fd(fds[0].fd)].time_stamping &
-           (SOF_TIMESTAMPING_TX_SOFTWARE | SOF_TIMESTAMPING_TX_HARDWARE)) {
-               if (!fds[0].events) {
-                       fds[0].revents = POLLERR;
-                       return 1;
-               } else if (fds[0].events == POLLPRI) {
-                       /* SO_SELECT_ERR_QUEUE option enabled */
-                       fds[0].revents = POLLPRI;
-                       return 1;
-               }
-       }
-
-       /* pmc waiting to send packet */
-       if (nfds == 2 && (fds[1].events & POLLOUT) && 
get_socket_from_fd(fds[1].fd) >= 0) {
-               fds[0].revents = 0;
-               fds[1].revents = POLLOUT;
-               return 1;
-       }
 
        FD_ZERO(&rfds);
+       FD_ZERO(&wfds);
+       FD_ZERO(&efds);
 
-       for (i = 0; i < nfds; i++)
-               if (fds[i].fd >= 0 && fds[i].events & POLLIN) {
+       for (i = 0; i < nfds; i++) {
+               if (fds[i].fd < 0)
+                      continue;
+               assert(fds[i].fd < FD_SETSIZE);
+               if (fds[i].events & POLLIN)
                        FD_SET(fds[i].fd, &rfds);
-                       if (maxfd < fds[i].fd)
-                               maxfd = fds[i].fd;
-               }
+               if (fds[i].events & POLLOUT)
+                       FD_SET(fds[i].fd, &wfds);
+               if (fds[i].events & POLLPRI)
+                       FD_SET(fds[i].fd, &efds);
+               if (maxfd < fds[i].fd)
+                       maxfd = fds[i].fd;
+       }
 
        if (timeout >= 0) {
                tv.tv_sec = timeout / 1000;
@@ -909,11 +1013,23 @@
                ptv = &tv;
        }
 
-       r = select(maxfd + 1, &rfds, NULL, NULL, ptv);
+       r = select(maxfd + 1, &rfds, &wfds, &efds, ptv);
+       if (r < 0)
+               return r;
 
-       for (i = 0; i < nfds; i++)
-               fds[i].revents = r > 0 && fds[i].fd >= 0 &&
-                       FD_ISSET(fds[i].fd, &rfds) ? POLLIN : 0;
+       for (i = 0, r = 0; i < nfds; i++) {
+               fds[i].revents = 0;
+               if (fds[i].fd < 0)
+                       continue;
+               if (FD_ISSET(fds[i].fd, &rfds))
+                       fds[i].revents |= POLLIN;
+               if (FD_ISSET(fds[i].fd, &wfds))
+                       fds[i].revents |= POLLOUT;
+               if (FD_ISSET(fds[i].fd, &efds))
+                       fds[i].revents |= POLLPRI;
+               if (fds[i].revents)
+                       r++;
+       }
 
        return r;
 }
@@ -965,6 +1081,11 @@
        return nanosleep(request, remain);
 }
 
+int eventfd(unsigned int initval, int flags) {
+       /* dummy file descriptor to disable libevent thread notification */
+       return timerfd_create(CLOCK_REALTIME, 0);
+}
+
 FILE *fopen(const char *path, const char *mode) {
        if (!strcmp(path, "/proc/net/if_inet6")) {
                errno = ENOENT;
@@ -980,19 +1101,17 @@
        return _fopen(path, mode);
 }
 
+FILE *fdopen(int fd, const char *mode) {
+       if (fd == URANDOM_FD)
+               return URANDOM_FILE;
+
+       return _fdopen(fd, mode);
+}
+
 size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) {
        if (stream == URANDOM_FILE) {
-               size_t i, l = size * nmemb;
-               long r;
-
-               assert(RAND_MAX >= 0xffffff);
-               for (i = r = 0; i < l; i++) {
-                       if (i % 3)
-                               r >>= 8;
-                       else
-                               r = random();
-                       ((unsigned char *)ptr)[i] = r;
-               }
+               if (read(URANDOM_FD, ptr, size * nmemb) != size * nmemb)
+                   assert(0);
 
                return nmemb;
        }
@@ -1013,7 +1132,7 @@
        return _fclose(fp);
 }
 
-int open(const char *pathname, int flags) {
+int open(const char *pathname, int flags, mode_t mode) {
        int r;
 
        assert(REFCLK_PHC_INDEX == 0 && SYSCLK_PHC_INDEX == 1);
@@ -1021,21 +1140,45 @@
                return REFCLK_FD;
        else if (!strcmp(pathname, "/dev/ptp1"))
                return SYSCLK_FD;
+       else if (!strcmp(pathname, "/dev/urandom"))
+               return URANDOM_FD;
 
-       r = _open(pathname, flags);
+       r = _open(pathname, flags, mode);
        assert(r < 0 || (r < BASE_SOCKET_FD && r < BASE_TIMER_FD));
 
        return r;
 }
 
+ssize_t read(int fd, void *buf, size_t count) {
+       if (fd == URANDOM_FD) {
+               size_t i;
+               long r;
+
+               assert(RAND_MAX >= 0xffffff);
+               for (i = r = 0; i < count; i++) {
+                       if (i % 3)
+                               r >>= 8;
+                       else
+                               r = random();
+                       ((unsigned char *)buf)[i] = r;
+               }
+
+               return count;
+       }
+
+       return _read(fd, buf, count);
+}
+
 int close(int fd) {
        int t, s;
 
-       if (fd == REFCLK_FD || fd == SYSCLK_FD) {
+       if (fd == REFCLK_FD || fd == SYSCLK_FD || fd == URANDOM_FD) {
                return 0;
        } else if ((t = get_timer_from_fd(fd)) >= 0) {
                return timer_delete(get_timerid(t));
        } else if ((s = get_socket_from_fd(fd)) >= 0) {
+               if (sockets[s].type == SOCK_STREAM)
+                       shutdown(fd, SHUT_RDWR);
                sockets[s].used = 0;
                return 0;
        }
@@ -1067,6 +1210,73 @@
        return get_socket_fd(s);
 }
 
+int listen(int sockfd, int backlog) {
+       int s = get_socket_from_fd(sockfd);
+
+       if (s < 0 || sockets[s].type != SOCK_STREAM) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       sockets[s].listening = 1;
+
+       return 0;
+}
+
+int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
+       int s = get_socket_from_fd(sockfd), r;
+       struct sockaddr_in *in;
+       struct Reply_recv rep;
+
+       if (s < 0 || sockets[s].type != SOCK_STREAM) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       make_request(REQ_RECV, NULL, 0, &rep, sizeof (rep));
+       assert(rep.type == MSG_TYPE_TCP_CONNECT);
+
+       r = socket(AF_INET, SOCK_STREAM, 0);
+       s = get_socket_from_fd(r);
+       assert(s >= 0);
+
+       sockets[s].port = rep.dst_port;
+       sockets[s].iface = IFACE_ETH0 + rep.subnet;
+       sockets[s].remote_node = rep.from;
+       sockets[s].remote_port = rep.src_port;
+       sockets[s].connected = 1;
+
+       in = (struct sockaddr_in *)addr;
+       assert(*addrlen >= sizeof (*in));
+       *addrlen = sizeof (*in);
+       in->sin_family = AF_INET;
+       in->sin_port = htons(sockets[s].remote_port);
+       in->sin_addr.s_addr = htonl(NODE_ADDR(sockets[s].iface - IFACE_ETH0, 
node));
+
+       send_msg_to_peer(s, MSG_TYPE_TCP_CONNECT);
+
+       return r;
+}
+
+int shutdown(int sockfd, int how) {
+       int s = get_socket_from_fd(sockfd);
+
+       if (s < 0) {
+               assert(0);
+               errno = EINVAL;
+               return -1;
+       }
+
+       assert(sockets[s].type == SOCK_STREAM);
+
+       if (sockets[s].connected) {
+               send_msg_to_peer(s, MSG_TYPE_TCP_DISCONNECT);
+               sockets[s].connected = 0;
+       }
+
+       return 0;
+}
+
 int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
        /* ntpd uses connect() and getsockname() to find the interface
           which will be used to send packets to an address */
@@ -1088,6 +1298,9 @@
        sockets[s].remote_node = node;
        sockets[s].remote_port = port;
 
+       if (sockets[s].type == SOCK_STREAM)
+               send_msg_to_peer(s, MSG_TYPE_TCP_CONNECT);
+
        return 0;
 }
 
@@ -1195,7 +1408,41 @@
        return 0;
 }
 
+int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t 
*optlen) {
+       int s = get_socket_from_fd(sockfd);
+
+       if (s < 0) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       if (level == SOL_SOCKET && optname == SO_ERROR && *optlen == sizeof 
(int)) {
+               *(int *)optval = 0;
+       } else {
+               errno = EINVAL;
+               return -1;
+       }
+
+       return 0;
+}
+
 int fcntl(int fd, int cmd, ...) {
+       int i, s = get_socket_from_fd(fd);
+       va_list ap;
+
+       if (s < 0) {
+               switch (cmd) {
+                       /* including fcntl.h breaks open() declaration */
+                       case 0: /* F_DUPFD */
+                       case 3: /* F_GETFL */
+                       case 4: /* F_SETFL */
+                               va_start(ap, cmd);
+                               i = va_arg(ap, int);
+                               va_end(ap);
+                               return _fcntl(fd, cmd, i);
+               }
+       }
+
        return 0;
 }
 
@@ -1262,23 +1509,32 @@
                } else
                        ret = -1, errno = EINVAL;
                req->ifr_netmask.sa_family = AF_UNSPEC;
-#ifdef ETHTOOL_GET_TS_INFO
        } else if (request == SIOCETHTOOL) {
-               struct ethtool_ts_info *info;
+               struct ethtool_cmd *cmd;
                req = va_arg(ap, struct ifreq *);
-               info = (struct ethtool_ts_info *)req->ifr_data;
-               memset(info, 0, sizeof (*info));
-               if (get_network_from_iface(req->ifr_name) >= 0) {
-                       info->phc_index = timestamping > 1 ? REFCLK_PHC_INDEX : 
SYSCLK_PHC_INDEX;
-                       info->so_timestamping = SOF_TIMESTAMPING_SOFTWARE |
-                               SOF_TIMESTAMPING_TX_SOFTWARE | 
SOF_TIMESTAMPING_RX_SOFTWARE |
-                               SOF_TIMESTAMPING_RAW_HARDWARE |
-                               SOF_TIMESTAMPING_TX_HARDWARE | 
SOF_TIMESTAMPING_RX_HARDWARE;
-                       info->tx_types = HWTSTAMP_TX_ON;
-                       info->rx_filters = 1 << HWTSTAMP_FILTER_NONE | 1 << 
HWTSTAMP_FILTER_ALL;
+               cmd = (struct ethtool_cmd *)req->ifr_data;
+
+               if (cmd->cmd == ETHTOOL_GSET) {
+                       memset(cmd, 0, sizeof (*cmd));
+                       ethtool_cmd_speed_set(cmd, LINK_SPEED);
+#ifdef ETHTOOL_GET_TS_INFO
+               } else if (cmd->cmd == ETHTOOL_GET_TS_INFO) {
+                       struct ethtool_ts_info *info;
+                       info = (struct ethtool_ts_info *)req->ifr_data;
+                       memset(info, 0, sizeof (*info));
+                       if (get_network_from_iface(req->ifr_name) >= 0) {
+                               info->phc_index = timestamping > 1 ? 
REFCLK_PHC_INDEX : SYSCLK_PHC_INDEX;
+                               info->so_timestamping = 
SOF_TIMESTAMPING_SOFTWARE |
+                                       SOF_TIMESTAMPING_TX_SOFTWARE | 
SOF_TIMESTAMPING_RX_SOFTWARE |
+                                       SOF_TIMESTAMPING_RAW_HARDWARE |
+                                       SOF_TIMESTAMPING_TX_HARDWARE | 
SOF_TIMESTAMPING_RX_HARDWARE;
+                               info->tx_types = HWTSTAMP_TX_ON;
+                               info->rx_filters = 1 << HWTSTAMP_FILTER_NONE | 
1 << HWTSTAMP_FILTER_ALL;
+                       } else
+                               ret = -1, errno = EINVAL;
+#endif
                } else
                        ret = -1, errno = EINVAL;
-#endif
 #ifdef PTP_CLOCK_GETCAPS
        } else if (request == PTP_CLOCK_GETCAPS && (fd == REFCLK_FD || fd == 
SYSCLK_FD)) {
                struct ptp_clock_caps *caps = va_arg(ap, struct ptp_clock_caps 
*);
@@ -1323,6 +1579,17 @@
 #ifdef SIOCSHWTSTAMP
        } else if (request == SIOCSHWTSTAMP && s >= 0) {
 #endif
+#ifdef SIOCGHWTSTAMP
+       } else if (request == SIOCGHWTSTAMP && s >= 0) {
+               struct hwtstamp_config *ts_config;
+
+               req = va_arg(ap, struct ifreq *);
+               ts_config = (struct hwtstamp_config *)req->ifr_data;
+
+               ts_config->flags = 0;
+               ts_config->tx_type = HWTSTAMP_TX_ON;
+               ts_config->rx_filter = HWTSTAMP_FILTER_ALL;
+#endif
        } else {
                ret = -1;
                errno = EINVAL;
@@ -1388,9 +1655,10 @@
 ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags) {
        struct Request_send req;
        struct sockaddr_in connected_sa, *sa;
-       int s = get_socket_from_fd(sockfd);
+       struct cmsghdr *cmsg;
+       int i, s = get_socket_from_fd(sockfd), timestamping;
 
-       if (s < 0 || sockets[s].type != SOCK_DGRAM) {
+       if (s < 0) {
                assert(0);
                errno = EINVAL;
                return -1;
@@ -1412,21 +1680,39 @@
                assert(sa->sin_family == AF_INET);
        }
 
-       assert(msg->msg_iovlen == 1);
-       assert(msg->msg_iov[0].iov_len <= sizeof (req.data));
+       switch (sockets[s].type) {
+               case SOCK_DGRAM:
+                       req.type = MSG_TYPE_UDP_DATA;
+                       break;
+               case SOCK_STREAM:
+                       assert(sockets[s].connected);
+                       req.type = MSG_TYPE_TCP_DATA;
+                       break;
+               default:
+                       assert(0);
+       }
 
        get_target(s, ntohl(sa->sin_addr.s_addr), &req.subnet, &req.to);
        req.src_port = sockets[s].port;
        req.dst_port = ntohs(sa->sin_port);
        assert(req.src_port && req.dst_port);
 
-       req.len = msg->msg_iov[0].iov_len;
-       memcpy(req.data, msg->msg_iov[0].iov_base, req.len);
+       for (req.len = 0, i = 0; i < msg->msg_iovlen; i++) {
+               assert(req.len + msg->msg_iov[i].iov_len <= sizeof (req.data));
+               memcpy(req.data + req.len, msg->msg_iov[i].iov_base, 
msg->msg_iov[i].iov_len);
+               req.len += msg->msg_iov[i].iov_len;
+       }
 
        make_request(REQ_SEND, &req, offsetof(struct Request_send, data) + 
req.len, NULL, 0);
 
-       if (sockets[s].time_stamping & (SOF_TIMESTAMPING_TX_SOFTWARE | 
SOF_TIMESTAMPING_TX_HARDWARE)) {
-               struct ts_message *last_ts_msg = &sockets[s].last_ts_msg;
+       timestamping = sockets[s].time_stamping;
+       for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR((struct msghdr 
*)msg, cmsg)) {
+               if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == 
SCM_TIMESTAMPING)
+                       memcpy(&timestamping, CMSG_DATA(cmsg), sizeof 
(timestamping));
+       }
+
+       if (timestamping & (SOF_TIMESTAMPING_TX_SOFTWARE | 
SOF_TIMESTAMPING_TX_HARDWARE)) {
+               struct message *last_ts_msg = &sockets[s].last_ts_msg;
 
                assert(req.len <= sizeof (last_ts_msg->data));
                memcpy(last_ts_msg->data, req.data, req.len);
@@ -1502,6 +1788,7 @@
 }
 
 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags) {
+       struct message *last_ts_msg = NULL;
        struct Reply_recv rep;
        struct sockaddr_in *sa;
        struct cmsghdr *cmsg;
@@ -1510,21 +1797,20 @@
        if (sockfd == clknetsim_fd)
                return _recvmsg(sockfd, msg, flags);
 
-       assert(s >= 0 && sockets[s].type == SOCK_DGRAM);
+       assert(s >= 0);
 
-       if (sockets[s].time_stamping & (SOF_TIMESTAMPING_TX_SOFTWARE | 
SOF_TIMESTAMPING_TX_HARDWARE) &&
-           flags & MSG_ERRQUEUE) {
-               struct ts_message *last_ts_msg;
+       if (sockets[s].last_ts_msg.len && flags & MSG_ERRQUEUE) {
                uint32_t addr;
                uint16_t port;
 
                /* last message looped back to the error queue */
 
                last_ts_msg = &sockets[s].last_ts_msg;
-               assert(last_ts_msg->len);
 
                msg->msg_flags = MSG_ERRQUEUE;
 
+               assert(sockets[s].type == SOCK_DGRAM);
+               rep.type = MSG_TYPE_UDP_DATA;
                rep.subnet = last_ts_msg->subnet;
                rep.from = last_ts_msg->to;
                rep.src_port = last_ts_msg->port;
@@ -1547,12 +1833,46 @@
                rep.len = 42 + last_ts_msg->len;
 
                last_ts_msg->len = 0;
-       } else
+       } else if (sockets[s].buffer.len > 0) {
+               assert(sockets[s].type == SOCK_STREAM && sockets[s].remote_node 
!= -1);
+               assert(sockets[s].buffer.len <= sizeof (rep.data));
+
+               memcpy(rep.data, sockets[s].buffer.data, sockets[s].buffer.len);
+               rep.type = MSG_TYPE_TCP_DATA;
+               rep.subnet = sockets[s].iface - IFACE_ETH0;
+               rep.from = sockets[s].remote_node;
+               rep.src_port = sockets[s].remote_port;
+               rep.dst_port = sockets[s].port;
+               rep.len = sockets[s].buffer.len;
+
+               sockets[s].buffer.len = 0;
+       } else {
                make_request(REQ_RECV, NULL, 0, &rep, sizeof (rep));
 
-       if (rep.len == 0 && rep.from == -1) {
-               errno = EWOULDBLOCK;
-               return -1;
+               switch (rep.type) {
+                       case MSG_TYPE_NO_MSG:
+                               errno = EWOULDBLOCK;
+                               return -1;
+                       case MSG_TYPE_UDP_DATA:
+                               assert(sockets[s].type == SOCK_DGRAM);
+                               break;
+                       case MSG_TYPE_TCP_DATA:
+                       case MSG_TYPE_TCP_DISCONNECT:
+                               assert(sockets[s].type == SOCK_STREAM);
+                               assert(sockets[s].remote_port && 
sockets[s].remote_node != -1);
+
+                               if (!sockets[s].connected) {
+                                       errno = ENOTCONN;
+                                       return -1;
+                               }
+                               if (rep.type == MSG_TYPE_TCP_DISCONNECT) {
+                                       assert(rep.len == 0);
+                                       sockets[s].connected = 0;
+                               }
+                               break;
+                       default:
+                               assert(0);
+               }
        }
 
        assert(socket_in_subnet(s, rep.subnet));
@@ -1573,6 +1893,16 @@
        msglen = msg->msg_iov[0].iov_len < rep.len ? msg->msg_iov[0].iov_len : 
rep.len;
        memcpy(msg->msg_iov[0].iov_base, rep.data, msglen);
 
+       if (sockets[s].type == SOCK_STREAM) {
+              if (msglen < rep.len) {
+                      sockets[s].buffer.len = rep.len - msglen;
+                      assert(sockets[s].buffer.len <= sizeof 
(sockets[s].buffer.data));
+                      memcpy(sockets[s].buffer.data, rep.data + msglen, 
rep.len - msglen);
+              } else {
+                      sockets[s].buffer.len = 0;
+              }
+       }
+
        cmsglen = 0;
 
        if (sockets[s].pkt_info) {
@@ -1596,8 +1926,7 @@
        }
 
 #ifdef SO_TIMESTAMPING
-       if ((sockets[s].time_stamping & (SOF_TIMESTAMPING_TX_SOFTWARE | 
SOF_TIMESTAMPING_TX_HARDWARE) &&
-            flags & MSG_ERRQUEUE) ||
+       if (last_ts_msg ||
            (sockets[s].time_stamping & (SOF_TIMESTAMPING_RX_SOFTWARE | 
SOF_TIMESTAMPING_RX_HARDWARE) &&
             !(flags & MSG_ERRQUEUE))) {
                struct timespec ts;
@@ -1609,7 +1938,7 @@
 
                memset(cmsg, 0, CMSG_SPACE(3 * sizeof (ts)));
                cmsg->cmsg_level = SOL_SOCKET;
-               cmsg->cmsg_type = SO_TIMESTAMPING;
+               cmsg->cmsg_type = SCM_TIMESTAMPING;
                cmsg->cmsg_len = CMSG_LEN(3 * sizeof (ts));
 
                if (sockets[s].time_stamping & SOF_TIMESTAMPING_SOFTWARE) {
@@ -1618,7 +1947,31 @@
                }
                if (sockets[s].time_stamping & SOF_TIMESTAMPING_RAW_HARDWARE) {
                        clock_gettime(timestamping > 1 ? REFCLK_ID : 
CLOCK_REALTIME, &ts);
+                       if (!(flags & MSG_ERRQUEUE))
+                               add_to_timespec(&ts, -(8 * (msglen + 42 + 4) / 
(1e6 * LINK_SPEED)));
+
                        memcpy((struct timespec *)CMSG_DATA(cmsg) + 2, &ts, 
sizeof (ts));
+
+#ifdef SCM_TIMESTAMPING_PKTINFO
+                       if (!(flags & MSG_ERRQUEUE) &&
+                           (sockets[s].time_stamping & 
SOF_TIMESTAMPING_OPT_PKTINFO) ==
+                           SOF_TIMESTAMPING_OPT_PKTINFO) {
+                               struct scm_ts_pktinfo tpi;
+
+                               cmsg = (struct cmsghdr *)((char 
*)CMSG_FIRSTHDR(msg) + cmsglen);
+                               cmsglen += CMSG_SPACE(sizeof (tpi));
+                               assert(msg->msg_control && msg->msg_controllen 
>= cmsglen);
+                               cmsg->cmsg_level = SOL_SOCKET;
+                               cmsg->cmsg_type = SCM_TIMESTAMPING_PKTINFO;
+                               cmsg->cmsg_len = CMSG_LEN(sizeof (tpi));
+
+                               memset(&tpi, 0, sizeof (tpi));
+                               tpi.if_index = rep.subnet + 1;
+                               tpi.pkt_length = msglen + 42;
+
+                               memcpy(CMSG_DATA(cmsg), &tpi, sizeof (tpi));
+                       }
+#endif
                }
        }
 #endif
@@ -1838,10 +2191,6 @@
        return 0;
 }
 
-uid_t getuid(void) {
-       return 0;
-}
-
 int uname(struct utsname *buf) {
        memset(buf, 0, sizeof (*buf));
        sprintf(buf->sysname, "Linux (clknetsim)");
@@ -1894,6 +2243,15 @@
                        r = clock_adjtime(clock_id, timex);
                        break;
 #endif
+#ifdef __NR_getrandom
+               case __NR_getrandom:
+                       if (1) {
+                               void *buf = va_arg(ap, void *);
+                               size_t length = va_arg(ap, size_t);
+                               r = read(URANDOM_FD, buf, length);
+                       }
+                       break;
+#endif
                default:
                        assert(0);
        }
@@ -1904,8 +2262,7 @@
 #endif
 
 ssize_t getrandom(void *buf, size_t length, unsigned int flags) {
-       errno = ENOTSUP;
-       return -1;
+       return read(URANDOM_FD, buf, length);
 }
 
 void srandom(unsigned int seed) {
@@ -1945,6 +2302,22 @@
        return 0;
 }
 
+uid_t getuid(void) {
+       return 0;
+}
+
+uid_t geteuid(void) {
+       return 0;
+}
+
+gid_t getgid(void) {
+       return 0;
+}
+
+gid_t getegid(void) {
+       return 0;
+}
+
 int setegid(gid_t gid) {
        return 0;
 }
@@ -1964,3 +2337,136 @@
 int cap_set_proc() {
        return 0;
 }
+
+static struct addrinfo *get_addrinfo(uint32_t addr, int port, int type, struct 
addrinfo *next) {
+       struct sockaddr_in *sin;
+       struct addrinfo *r;
+
+       sin = malloc(sizeof *sin);
+       sin->sin_family = AF_INET;
+       sin->sin_port = htons(port);
+       sin->sin_addr.s_addr = htonl(addr);
+
+       r = malloc(sizeof *r);
+       memset(r, 0, sizeof *r);
+
+       r->ai_family = AF_INET;
+       r->ai_socktype = type;
+       r->ai_addrlen = sizeof *sin;
+       r->ai_addr = (struct sockaddr *)sin;
+
+       r->ai_next = next;
+
+       return r;
+}
+
+int getaddrinfo(const char *node, const char *service, const struct addrinfo 
*hints,
+               struct addrinfo **res) {
+       int port = 0, type = SOCK_DGRAM;
+       struct in_addr addr;
+
+       if (hints) {
+               if ((hints->ai_family != AF_UNSPEC && hints->ai_family != 
AF_INET) ||
+                   (hints->ai_socktype != SOCK_STREAM && hints->ai_socktype != 
SOCK_DGRAM &&
+                    hints->ai_socktype != 0))
+                       return EAI_NONAME;
+               if (hints->ai_socktype == SOCK_STREAM)
+                       type = SOCK_STREAM;
+       }
+
+       if (service) {
+               if (strcmp(service, "ntp") == 0)
+                       port = 123;
+               else if (service[0] >= '0' && service[0] <= '9')
+                       port = atoi(service);
+               else
+                       return EAI_NONAME;
+       }
+
+       if (node == NULL) {
+               *res = get_addrinfo(INADDR_ANY, port, type, NULL);
+       } else if (inet_aton(node, &addr)) {
+               *res = get_addrinfo(ntohl(addr.s_addr), port, type, NULL);
+       } else if (strcmp(node + strlen(node) - 4, ".clk") == 0) {
+               const char *s = strstr(node, ".net");
+               int subnet;
+
+               if (s == NULL)
+                       return EAI_NONAME;
+
+               subnet = atoi(s + 4) - 1;
+
+               if (strncmp(node, "nodes-", 6) == 0) {
+                       s = node + 5;
+                       *res = NULL;
+                       do {
+                               *res = get_addrinfo(NODE_ADDR(subnet, atoi(s + 
1) - 1), port, type, *res);
+                               s = strchr(s + 1, '-');
+                       } while (s);
+               } else if (strncmp(node, "node", 4) == 0) {
+                       *res = get_addrinfo(NODE_ADDR(subnet, atoi(node + 4) - 
1), port, type, NULL);
+               } else {
+                       return EAI_NONAME;
+               }
+       } else {
+               return EAI_NONAME;
+       }
+
+       return 0;
+}
+
+void freeaddrinfo(struct addrinfo *res) {
+       if (res->ai_next)
+               freeaddrinfo(res->ai_next);
+       free(res->ai_addr);
+       free(res);
+}
+
+int getnameinfo(const struct sockaddr *addr, socklen_t addrlen,
+               char *host, socklen_t hostlen,
+               char *serv, socklen_t servlen, int flags) {
+       const struct sockaddr_in *sin = (const struct sockaddr_in *)addr;
+       int node, subnet;
+
+       if (addrlen < sizeof *sin || sin->sin_family != AF_INET)
+               return EAI_NONAME;
+
+       assert(!(flags & NI_NOFQDN));
+       assert(!(flags & NI_NUMERICHOST));
+       assert(!(flags & NI_NUMERICSERV));
+
+       if (host && hostlen > 0) {
+               node = NODE_FROM_ADDR(ntohl(sin->sin_addr.s_addr));
+               subnet = SUBNET_FROM_ADDR(ntohl(sin->sin_addr.s_addr));
+               if (subnet < 0 || subnet > 100) {
+                       assert(flags & NI_NAMEREQD);
+                       return EAI_NONAME;
+               }
+               if (snprintf(host, hostlen, "node%d.net%d.clk", node + 1, 
subnet + 1) >= hostlen)
+                       return EAI_OVERFLOW;
+       }
+
+       if (serv && servlen > 0) {
+               switch (ntohs(sin->sin_port)) {
+                       case 123:
+                               if (snprintf(serv, servlen, "ntp") >= servlen)
+                                       return EAI_OVERFLOW;
+                               break;
+                       default:
+                               if (snprintf(serv, servlen, "%u", 
ntohs(sin->sin_port)) >= servlen)
+                                       return EAI_OVERFLOW;
+               }
+       }
+
+       return 0;
+}
+
+struct hostent *gethostbyname(const char *name) {
+       h_errno = HOST_NOT_FOUND;
+       return NULL;
+}
+
+struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type) {
+       h_errno = HOST_NOT_FOUND;
+       return NULL;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/clknetsim-58c5e8bd6d041ff30e9c7dbe45162a73e99f3d24/client_fuzz.c 
new/clknetsim-79ffe448f262d0a411fe44380df94d504b965b2e/client_fuzz.c
--- old/clknetsim-58c5e8bd6d041ff30e9c7dbe45162a73e99f3d24/client_fuzz.c        
2019-01-28 10:35:17.000000000 +0100
+++ new/clknetsim-79ffe448f262d0a411fe44380df94d504b965b2e/client_fuzz.c        
2019-11-26 10:05:32.000000000 +0100
@@ -34,6 +34,7 @@
 #define MAX_FUZZ_PORTS 16
 
 static int fuzz_mode;
+static int fuzz_msg_type;
 static int fuzz_ports[MAX_FUZZ_PORTS];
 static int fuzz_port_index, fuzz_ports_n;
 static int fuzz_timeout;
@@ -61,6 +62,9 @@
                exit(1);
        }
 
+       env = getenv("CLKNETSIM_FUZZ_MSG_TYPE");
+       fuzz_msg_type = env ? atoi(env) : MSG_TYPE_UDP_DATA;
+
        env = getenv("CLKNETSIM_FUZZ_PORT");
 
        for (fuzz_ports_n = 0; env && fuzz_ports_n < MAX_FUZZ_PORTS; 
fuzz_ports_n++) {
@@ -131,11 +135,31 @@
        fwrite(data, 1, len, stdout);
 }
 
-static void fuzz_process_reply(int request_id, const union Request_data 
*request, union Reply_data *reply, int replylen) {
+static void get_recv_data(int valid_packet, int received, int last_tx_src_port,
+                         unsigned int *type, unsigned int *subnet, unsigned 
int *from,
+                         unsigned int *src_port, unsigned int *dst_port) {
+       if (valid_packet) {
+               if (fuzz_msg_type == MSG_TYPE_TCP_DATA && received == 0)
+                       *type = MSG_TYPE_TCP_CONNECT;
+               else
+                       *type = fuzz_msg_type;
+               *from = 1;
+       } else {
+               *type = MSG_TYPE_NO_MSG;
+               *from = -1;
+       }
+
+       *subnet = 0;
+       *src_port = fuzz_get_fuzz_port();
+       *dst_port = last_tx_src_port ? last_tx_src_port : fuzz_get_fuzz_port();
+}
+
+static void fuzz_process_request(int request_id, const union Request_data 
*request,
+                                union Reply_data *reply, int replylen) {
        static double network_time = 0.0;
        static int received = 0;
        static int sent = 0;
-       static int dst_port = 0;
+       static int last_tx_src_port = 0;
        static int packet_len = 0;
        static int valid_packet = 0;
        static char packet[MAX_PACKET_SIZE];
@@ -187,8 +211,9 @@
                                }
                        }
 
-                       reply->select.subnet = 0;
-                       reply->select.dst_port = dst_port ? dst_port : 
fuzz_get_fuzz_port();
+                       get_recv_data(valid_packet, received, last_tx_src_port,
+                                     &reply->select.type, 
&reply->select.subnet, &reply->select.from,
+                                     &reply->select.src_port, 
&reply->select.dst_port);
                        reply->select.time.real_time = network_time;
                        reply->select.time.monotonic_time = network_time;
                        reply->select.time.network_time = network_time;
@@ -200,7 +225,7 @@
                        if (fuzz_mode == FUZZ_MODE_REPLY) {
                                if (!fuzz_is_fuzz_port(request->send.dst_port))
                                        break;
-                               dst_port = request->send.src_port;
+                               last_tx_src_port = request->send.src_port;
                        } else if (!fuzz_is_fuzz_port(request->send.src_port))
                                break;
 
@@ -209,13 +234,19 @@
                        break;
                case REQ_RECV:
                        network_time += 1e-5;
-                       reply->recv.subnet = 0;
-                       reply->recv.from = valid_packet ? 1 : -1;
-                       reply->recv.src_port = fuzz_get_fuzz_port();
-                       reply->recv.dst_port = dst_port ? dst_port : 
fuzz_get_fuzz_port();
+                       get_recv_data(valid_packet, received, last_tx_src_port,
+                                     &reply->recv.type, &reply->recv.subnet, 
&reply->recv.from,
+                                     &reply->recv.src_port, 
&reply->recv.dst_port);
+
+                       received++;
+
+                       if (reply->recv.type != fuzz_msg_type) {
+                               reply->recv.len = 0;
+                               break;
+                       }
+
                        memcpy(reply->recv.data, packet, packet_len);
                        reply->recv.len = packet_len;
-                       received++;
                        valid_packet = 0;
                        packet_len = 0;
                        fuzz_switch_fuzz_port();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/clknetsim-58c5e8bd6d041ff30e9c7dbe45162a73e99f3d24/examples/ntpdate.test 
new/clknetsim-79ffe448f262d0a411fe44380df94d504b965b2e/examples/ntpdate.test
--- 
old/clknetsim-58c5e8bd6d041ff30e9c7dbe45162a73e99f3d24/examples/ntpdate.test    
    2019-01-28 10:35:17.000000000 +0100
+++ 
new/clknetsim-79ffe448f262d0a411fe44380df94d504b965b2e/examples/ntpdate.test    
    2019-11-26 10:05:32.000000000 +0100
@@ -5,13 +5,13 @@
 
 generate_config1 3 10.0 "(sum (* 1e-9 (normal)))" "(+ 1e-3 (* 1e-3 
(exponential)))"
 
-echo "node2_start = 100" >> tmp/conf
-echo "node3_start = 100" >> tmp/conf
+echo "node2_start = 330" >> tmp/conf
+echo "node3_start = 330" >> tmp/conf
 
 start_client 1 ntpd "server 127.127.1.0"
 start_client 2 ntpdate "-B 192.168.123.1"
 start_client 3 ntpdate "-b 192.168.123.1"
 
-start_server 3 -v 2 -o log.offset -r 110 -l 200
+start_server 3 -v 2 -o log.offset -r 340 -l 350
 
 cat tmp/stats
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/clknetsim-58c5e8bd6d041ff30e9c7dbe45162a73e99f3d24/examples/sntp.test 
new/clknetsim-79ffe448f262d0a411fe44380df94d504b965b2e/examples/sntp.test
--- old/clknetsim-58c5e8bd6d041ff30e9c7dbe45162a73e99f3d24/examples/sntp.test   
2019-01-28 10:35:17.000000000 +0100
+++ new/clknetsim-79ffe448f262d0a411fe44380df94d504b965b2e/examples/sntp.test   
2019-11-26 10:05:32.000000000 +0100
@@ -1,17 +1,19 @@
 #!/bin/bash
 
+export EVENT_NOEPOLL=1
+
 CLKNETSIM_PATH=..
 . ../clknetsim.bash
 
 generate_config1 3 10.0 "(sum (* 1e-9 (normal)))" "(+ 1e-3 (* 1e-3 
(exponential)))"
 
-echo "node2_start = 100" >> tmp/conf
-echo "node3_start = 100" >> tmp/conf
+echo "node2_start = 330" >> tmp/conf
+echo "node3_start = 330" >> tmp/conf
 
 start_client 1 ntpd "server 127.127.1.0"
-start_client 2 sntp "-j 192.168.123.1"
-start_client 3 sntp "-s 192.168.123.1"
+start_client 2 sntp "-s 192.168.123.1"
+start_client 3 sntp "-S 192.168.123.1"
 
-start_server 3 -v 2 -o log.offset -r 110 -l 200
+start_server 3 -v 2 -o log.offset -r 340 -l 350
 
 cat tmp/stats
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/clknetsim-58c5e8bd6d041ff30e9c7dbe45162a73e99f3d24/network.cc 
new/clknetsim-79ffe448f262d0a411fe44380df94d504b965b2e/network.cc
--- old/clknetsim-58c5e8bd6d041ff30e9c7dbe45162a73e99f3d24/network.cc   
2019-01-28 10:35:17.000000000 +0100
+++ new/clknetsim-79ffe448f262d0a411fe44380df94d504b965b2e/network.cc   
2019-11-26 10:05:32.000000000 +0100
@@ -18,6 +18,8 @@
 #include "sysheaders.h"
 #include "network.h"
 
+#define CONNECT_TIMEOUT 10
+
 Packet_queue::Packet_queue() {
 }
 
@@ -100,6 +102,7 @@
 
 bool Network::prepare_clients() {
        struct sockaddr_un s;
+       struct timeval tv;
        int sockfd, fd;
         unsigned int i;
 
@@ -108,18 +111,26 @@
 
        sockfd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
        if (sockfd < 0) {
-               fprintf(stderr, "socket() failed\n");
+               fprintf(stderr, "socket() failed: %s\n", strerror(errno));
                return false;
        }
 
        unlink(socket_name);
        if (bind(sockfd, (struct sockaddr *)&s, sizeof (s)) < 0) {
-               fprintf(stderr, "bind() failed\n");
+               fprintf(stderr, "bind() failed: %s\n", strerror(errno));
                return false;
        }
 
        if (listen(sockfd, nodes.size()) < 0) {
-               fprintf(stderr, "listen() failed\n");
+               fprintf(stderr, "listen() failed: %s\n", strerror(errno));
+               return false;
+       }
+
+       tv.tv_sec = CONNECT_TIMEOUT;
+       tv.tv_usec = 0;
+
+       if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof (tv))) {
+               fprintf(stderr, "setsockopt() failed: %s\n", strerror(errno));
                return false;
        }
 
@@ -130,7 +141,7 @@
                fprintf(stderr, "\rWaiting for %u clients...", (unsigned 
int)nodes.size() - i);
                fd = accept(sockfd, NULL, NULL);
                if (fd < 0) {
-                       fprintf(stderr, "accept() failed\n");
+                       fprintf(stderr, "\naccept() failed: %s\n", 
strerror(errno));
                        return false;
                }
 
@@ -351,7 +362,10 @@
 
        i = packet->from * nodes.size() + packet->to;
 
-       if (link_delays[i]) {
+       if (packet->type != MSG_TYPE_UDP_DATA) {
+               /* constant delay to not break the order of TCP packets */
+               delay = 1.0e-3;
+       } else if (link_delays[i]) {
                link_delay_variables["time"] = time;
                link_delay_variables["from"] = packet->from + 1;
                link_delay_variables["to"] = packet->to + 1;
@@ -365,24 +379,24 @@
        stats[packet->from].update_packet_stats(false, time, delay);
 
        if (packet_log)
-               fprintf(packet_log, "%e\t%d\t%d\t%e\t%d\t%d\t%d\n", time,
+               fprintf(packet_log, "%e\t%d\t%d\t%e\t%d\t%d\t%d\t%d\t%d\n", 
time,
                                packet->from + 1, packet->to + 1, delay,
                                packet->src_port, packet->dst_port,
-                               packet->subnet + 1);
+                               packet->subnet + 1, packet->len, packet->type);
 
        if (delay > 0.0) {
                packet->receive_time = time + delay;
                packet->delay = delay;
                packet_queue.insert(packet);
 #ifdef DEBUG
-               printf("sending packet from %d to %d:%d:%d at %f delay %f \n",
-                               packet->from, packet->subnet, packet->to,
+               printf("sending packet of type %d from %d to %d:%d:%d at %f 
delay %f \n",
+                               packet->type, packet->from, packet->subnet, 
packet->to,
                                packet->dst_port, time, delay);
 #endif
        } else {
 #ifdef DEBUG
-               printf("dropping packet from %d to %d:%d:%d at %f\n",
-                               packet->from, packet->subnet, packet->to,
+               printf("dropping packet of type %d from %d to %d:%d:%d at %f\n",
+                               packet->type, packet->from, packet->subnet, 
packet->to,
                                packet->dst_port, time);
 #endif
                delete packet;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/clknetsim-58c5e8bd6d041ff30e9c7dbe45162a73e99f3d24/network.h 
new/clknetsim-79ffe448f262d0a411fe44380df94d504b965b2e/network.h
--- old/clknetsim-58c5e8bd6d041ff30e9c7dbe45162a73e99f3d24/network.h    
2019-01-28 10:35:17.000000000 +0100
+++ new/clknetsim-79ffe448f262d0a411fe44380df94d504b965b2e/network.h    
2019-11-26 10:05:32.000000000 +0100
@@ -30,6 +30,7 @@
        double receive_time;
        double delay;
        int broadcast;
+       unsigned int type;
        unsigned int subnet;
        unsigned int from;
        unsigned int to;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/clknetsim-58c5e8bd6d041ff30e9c7dbe45162a73e99f3d24/node.cc 
new/clknetsim-79ffe448f262d0a411fe44380df94d504b965b2e/node.cc
--- old/clknetsim-58c5e8bd6d041ff30e9c7dbe45162a73e99f3d24/node.cc      
2019-01-28 10:35:17.000000000 +0100
+++ new/clknetsim-79ffe448f262d0a411fe44380df94d504b965b2e/node.cc      
2019-11-26 10:05:32.000000000 +0100
@@ -63,6 +63,8 @@
        int received, reqlen;
 
        received = recv(fd, &request, sizeof (request), 0);
+       if (received < 0)
+               fprintf(stderr, "recv() failed: %s\n", strerror(errno));
        if (received < (int)sizeof (request.header))
                return false;
 
@@ -190,7 +192,10 @@
                rep.ret = incoming_packets.back()->broadcast ?
                        REPLY_SELECT_BROADCAST :
                        REPLY_SELECT_NORMAL;
+               rep.type = incoming_packets.back()->type;
                rep.subnet = incoming_packets.back()->subnet;
+               rep.from = incoming_packets.back()->from;
+               rep.src_port = incoming_packets.back()->src_port;
                rep.dst_port = incoming_packets.back()->dst_port;
 #ifdef DEBUG
                printf("select returned for packet in %d at %f\n", index, 
clock.get_real_time());
@@ -222,6 +227,7 @@
 
        if (!terminate) {
                packet = new struct Packet;
+               packet->type = req->type;
                packet->broadcast = req->to == (unsigned int)-1;
                packet->subnet = req->subnet;
                packet->from = index;
@@ -241,6 +247,7 @@
        struct Packet *packet;
 
        if (incoming_packets.empty()) {
+               rep.type = MSG_TYPE_NO_MSG;
                rep.subnet = 0;
                rep.from = -1;
                rep.src_port = 0;
@@ -253,6 +260,7 @@
 
        packet = incoming_packets.back();
 
+       rep.type = packet->type;
        rep.subnet = packet->subnet;
        rep.from = packet->from;
        rep.src_port = packet->src_port;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/clknetsim-58c5e8bd6d041ff30e9c7dbe45162a73e99f3d24/protocol.h 
new/clknetsim-79ffe448f262d0a411fe44380df94d504b965b2e/protocol.h
--- old/clknetsim-58c5e8bd6d041ff30e9c7dbe45162a73e99f3d24/protocol.h   
2019-01-28 10:35:17.000000000 +0100
+++ new/clknetsim-79ffe448f262d0a411fe44380df94d504b965b2e/protocol.h   
2019-11-26 10:05:32.000000000 +0100
@@ -86,14 +86,24 @@
 
 struct Reply_select {
        int ret;
+       unsigned int type; /* for NORMAL */
        unsigned int subnet; /* for NORMAL or BROADCAST */
+       unsigned int from; /* for NORMAL or BROADCAST */
+       unsigned int src_port; /* for NORMAL or BROADCAST */
        unsigned int dst_port; /* for NORMAL or BROADCAST */
        struct Reply_gettime time;
 };
 
 #define MAX_PACKET_SIZE 4000
 
+#define MSG_TYPE_NO_MSG 0
+#define MSG_TYPE_UDP_DATA 1
+#define MSG_TYPE_TCP_CONNECT 2
+#define MSG_TYPE_TCP_DATA 3
+#define MSG_TYPE_TCP_DISCONNECT 4
+
 struct Request_send {
+       unsigned int type;
        unsigned int subnet;
        unsigned int to;
        unsigned int src_port;
@@ -103,6 +113,7 @@
 };
 
 struct Reply_recv {
+       unsigned int type;
        unsigned int subnet;
        unsigned int from;
        unsigned int src_port;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/clknetsim-58c5e8bd6d041ff30e9c7dbe45162a73e99f3d24/sysheaders.h 
new/clknetsim-79ffe448f262d0a411fe44380df94d504b965b2e/sysheaders.h
--- old/clknetsim-58c5e8bd6d041ff30e9c7dbe45162a73e99f3d24/sysheaders.h 
2019-01-28 10:35:17.000000000 +0100
+++ new/clknetsim-79ffe448f262d0a411fe44380df94d504b965b2e/sysheaders.h 
2019-11-26 10:05:32.000000000 +0100
@@ -1,6 +1,8 @@
 #ifndef SYSTEM_H
 
+#include <errno.h>
 #include <stdio.h>
+#include <string.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/socket.h>


Reply via email to