Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package chrony for openSUSE:Factory checked 
in at 2025-07-10 23:14:56
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/chrony (Old)
 and      /work/SRC/openSUSE:Factory/.chrony.new.7373 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "chrony"

Thu Jul 10 23:14:56 2025 rev:47 rq:1291542 version:4.7

Changes:
--------
--- /work/SRC/openSUSE:Factory/chrony/chrony.changes    2025-02-13 
18:37:47.877063244 +0100
+++ /work/SRC/openSUSE:Factory/.chrony.new.7373/chrony.changes  2025-07-10 
23:15:10.600859568 +0200
@@ -1,0 +2,26 @@
+Wed Jul  2 17:42:22 UTC 2025 - Reinhard Max <m...@suse.com>
+
+- Update to version 4.5:
+  * Add opencommands directive to select remote monitoring
+    commands
+  * Add interval option to driftfile directive
+  * Add waitsynced and waitunsynced options to local directive
+  * Add sanity checks for integer values in configuration
+  * Add support for systemd Type=notify service
+  * Add RTC refclock driver
+  * Allow PHC refclock to be specified with network interface name
+  * Don’t require multiple refclock samples per poll to simplify
+    filter configuration
+  * Keep refclock reachable when dropping samples with large delay
+  * Improve quantile-based filtering to adapt faster to larger
+    delay
+  * Improve logging of selection failures
+  * Detect clock interference from other processes
+  * Try to reopen message log (-l option) on cyclelogs command
+  * Fix sourcedir reloading to not multiply sources
+  * Fix tracking offset after failed clock step
+  * Drop support for NTS with Nettle < 3.6 and GnuTLS < 3.6.14
+  * Drop support for building without POSIX threads
+- Update clknetsim to snapshot 530d1a5.
+
+-------------------------------------------------------------------

Old:
----
  chrony-4.6.1.tar.gz
  chrony-4.6.1.tar.gz.sig
  clknetsim-633a0be.tar.gz

New:
----
  chrony-4.7.tar.gz
  chrony-4.7.tar.gz.sig
  clknetsim-530d1a5.tar.gz

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

Other differences:
------------------
++++++ chrony.spec ++++++
--- /var/tmp/diff_new_pack.H2SM0p/_old  2025-07-10 23:15:11.520897894 +0200
+++ /var/tmp/diff_new_pack.H2SM0p/_new  2025-07-10 23:15:11.520897894 +0200
@@ -33,7 +33,7 @@
 %bcond_without testsuite
 
 %define _systemdutildir %(pkg-config --variable systemdutildir systemd)
-%global clknetsim_ver 633a0be
+%global clknetsim_ver 530d1a5
 #Compat macro for new _fillupdir macro introduced in Nov 2017
 %if ! %{defined _fillupdir}
   %define _fillupdir %{_localstatedir}/adm/fillup-templates
@@ -41,7 +41,7 @@
 %define chrony_helper %{_libexecdir}/chrony/helper
 %define chrony_rundir %{_rundir}/%{name}
 Name:           chrony
-Version:        4.6.1
+Version:        4.7
 Release:        0
 Summary:        System Clock Synchronization Client and Server
 License:        GPL-2.0-only

++++++ chrony-4.6.1.tar.gz -> chrony-4.7.tar.gz ++++++
++++ 9612 lines of diff (skipped)

++++++ chrony-config.patch ++++++
--- /var/tmp/diff_new_pack.H2SM0p/_old  2025-07-10 23:15:11.740907059 +0200
+++ /var/tmp/diff_new_pack.H2SM0p/_new  2025-07-10 23:15:11.744907225 +0200
@@ -1,7 +1,7 @@
 --- examples/chrony.conf.example3.orig
 +++ examples/chrony.conf.example3
-@@ -27,12 +27,38 @@
- # you can access at http://support.ntp.org/bin/view/Servers/WebHome or
+@@ -29,12 +29,38 @@
+ # you can access at https://support.ntp.org/bin/view/Servers/WebHome or
  # you can use servers from the pool.ntp.org project.
  
 -! server ntp1.example.net iburst
@@ -43,7 +43,7 @@
  #######################################################################
  ### AVOIDING POTENTIALLY BOGUS CHANGES TO YOUR CLOCK
  #
-@@ -79,7 +105,7 @@
+@@ -81,7 +107,7 @@
  # immediately so that it doesn't gain or lose any more time.  You
  # generally want this, so it is uncommented.
  
@@ -52,7 +52,7 @@
  
  # If you want to enable NTP authentication with symmetric keys, you will need
  # to uncomment the following line and edit the file to set up the keys.
-@@ -165,8 +191,8 @@ ntsdumpdir /var/lib/chrony
+@@ -167,8 +193,8 @@ ntsdumpdir /var/lib/chrony
  # produce some graphs of your system's timekeeping performance, or you
  # need help in debugging a problem.
  

++++++ chrony-service-helper.patch ++++++
--- /var/tmp/diff_new_pack.H2SM0p/_old  2025-07-10 23:15:11.792909225 +0200
+++ /var/tmp/diff_new_pack.H2SM0p/_new  2025-07-10 23:15:11.796909391 +0200
@@ -1,11 +1,11 @@
 --- examples/chronyd.service.orig
 +++ examples/chronyd.service
-@@ -10,6 +10,7 @@ Type=forking
+@@ -10,6 +10,7 @@ Type=notify
  PIDFile=/run/chrony/chronyd.pid
+ Environment="OPTIONS="
  EnvironmentFile=-/etc/sysconfig/chronyd
- ExecStart=/usr/sbin/chronyd $OPTIONS
 +ExecStartPost=@CHRONY_HELPER@ update-daemon
+ ExecStart=/usr/sbin/chronyd -n $OPTIONS
  
  CapabilityBoundingSet=~CAP_AUDIT_CONTROL CAP_AUDIT_READ CAP_AUDIT_WRITE
- CapabilityBoundingSet=~CAP_BLOCK_SUSPEND CAP_KILL CAP_LEASE 
CAP_LINUX_IMMUTABLE
 


++++++ clknetsim-633a0be.tar.gz -> clknetsim-530d1a5.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/clknetsim-633a0be069bac00e5aa562c0e5e15a3bf30b6af2/README 
new/clknetsim-530d1a579a8ae1a0bb0f26079d8eef32136699e2/README
--- old/clknetsim-633a0be069bac00e5aa562c0e5e15a3bf30b6af2/README       
2024-06-10 14:23:41.000000000 +0200
+++ new/clknetsim-530d1a579a8ae1a0bb0f26079d8eef32136699e2/README       
2025-06-24 15:51:35.000000000 +0200
@@ -57,7 +57,9 @@
 networks with IPv4 addressing. All nodes have interfaces to all networks.
 Their addresses are 192.168.122+s.n, where n is the number of the node
 (starting at 1) and s is the number of the network (starting at 1). The
-broadcast addresses are 192.168.122+s.255.
+broadcast addresses are 192.168.122+s.255. The CLKNETSIM_IP_FAMILY variable
+can be set to 6 to enable IPv6 and disable IPv4. The supported IPv6 addresses
+are fc00::123:SSNN, where SS is s-1 in hexadecimal and NN is n in hexadecimal.
 
 At the end of the simulation clock and network statistics are printed.
 clknetsim has options which can be used to control for how long the
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/clknetsim-633a0be069bac00e5aa562c0e5e15a3bf30b6af2/client.c 
new/clknetsim-530d1a579a8ae1a0bb0f26079d8eef32136699e2/client.c
--- old/clknetsim-633a0be069bac00e5aa562c0e5e15a3bf30b6af2/client.c     
2024-06-10 14:23:41.000000000 +0200
+++ new/clknetsim-530d1a579a8ae1a0bb0f26079d8eef32136699e2/client.c     
2025-06-24 15:51:35.000000000 +0200
@@ -77,8 +77,16 @@
 #define NODE_FROM_ADDR(addr) (((addr) & ~NETMASK) - 1)
 #define SUBNET_FROM_ADDR(addr) ((((addr) & NETMASK) - BASE_ADDR) / 0x100)
 
+#define IP6_NET 
"\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x23\x00\x00"
+#define IS_SIN6_KNOWN(sin6) (memcmp(IP6_NET, &(sin6)->sin6_addr.s6_addr, 14) 
== 0)
+#define NODE_FROM_SIN6(sin6) ((sin6)->sin6_addr.s6_addr[15])
+#define SUBNET_FROM_SIN6(sin6) ((sin6)->sin6_addr.s6_addr[14])
+#define ADDR_FROM_SIN6(sin6) (BASE_ADDR + (SUBNET_FROM_SIN6(sin6) << 8) + 
NODE_FROM_SIN6(sin6))
+
 #define PTP_PRIMARY_MCAST_ADDR 0xe0000181 /* 224.0.1.129 */
 #define PTP_PDELAY_MCAST_ADDR 0xe000006b /* 224.0.0.107 */
+#define PTP_PRIMARY_MCAST_ADDR6 
"\xff\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x81"
+#define PTP_PDELAY_MCAST_ADDR6 
"\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x6b"
 
 #define REFCLK_FD 1000
 #define REFCLK_ID ((clockid_t)(((unsigned int)~REFCLK_FD << 3) | 3))
@@ -134,15 +142,18 @@
 static int initializing = 0;
 static int initialized_symbols = 0;
 static int initialized = 0;
-static int clknetsim_fd;
+static int clknetsim_fd = -1;
 static int precision_hack = 1;
 static unsigned int random_seed = 0;
+static int ip_family = 4;
 static int recv_multiply = 1;
 static int timestamping = 1;
 
 static double phc_delay = 0.0;
 static double phc_jitter = 0.0;
 static double phc_jitter_asym = 0.0;
+static int phc_jitter_off = 0;
+static int phc_jitter_on = 1;
 static int phc_swap = 0;
 
 /* Ethernet speed in Mb/s */
@@ -240,6 +251,7 @@
 
 static FILE *pcap = NULL;
 
+static int timer_delete_(timer_t timerid);
 static void write_pcap_header(void);
 
 static void make_request(int request_id, const void *request_data, int reqlen, 
void *reply, int replylen);
@@ -307,6 +319,10 @@
        if (env)
                random_seed = atoi(env);
 
+       env = getenv("CLKNETSIM_IP_FAMILY");
+       if (env)
+               ip_family = atoi(env);
+
        env = getenv("CLKNETSIM_RECV_MULTIPLY");
        if (env)
                recv_multiply = atoi(env);
@@ -331,6 +347,14 @@
        if (env)
                phc_jitter_asym = atof(env);
 
+       env = getenv("CLKNETSIM_PHC_JITTER_OFF");
+       if (env)
+               phc_jitter_off = atoi(env);
+
+       env = getenv("CLKNETSIM_PHC_JITTER_ON");
+       if (env)
+               phc_jitter_on = atoi(env);
+
        env = getenv("CLKNETSIM_PHC_SWAP");
        if (env)
                phc_swap = atoi(env);
@@ -418,6 +442,9 @@
 
        if (pcap)
                fclose(pcap);
+
+       if (clknetsim_fd >= 0)
+               close(clknetsim_fd);
 }
 
 static void make_request(int request_id, const void *request_data, int reqlen, 
void *reply, int replylen) {
@@ -577,24 +604,103 @@
        }
 }
 
-static void get_target(int socket, uint32_t addr, unsigned int *subnet, 
unsigned int *node) {
-       if (addr == PTP_PRIMARY_MCAST_ADDR || addr == PTP_PDELAY_MCAST_ADDR) {
-               assert(sockets[socket].iface >= IFACE_ETH0);
-               *subnet = sockets[socket].iface - IFACE_ETH0;
-               *node = -1; /* multicast as broadcast */
-       } else {
-               *subnet = SUBNET_FROM_ADDR(addr);
-               if (fuzz_mode && (*subnet >= subnets || *subnet == unix_subnet))
-                       *subnet = 0;
+static int get_ip_target(int socket, const struct sockaddr *saddr, socklen_t 
saddrlen,
+                        unsigned int *subnet, unsigned int *node, unsigned int 
*port) {
+       const struct sockaddr_in6 *sin6;
+       const struct sockaddr_in *sin;
+       uint32_t addr;
 
-               assert(*subnet >= 0 && *subnet < subnets);
-               assert(socket_in_subnet(socket, *subnet));
+       switch (saddr->sa_family) {
+               case AF_INET:
+                       sin = (const struct sockaddr_in *)saddr;
+                       if (saddrlen < sizeof (*sin))
+                               return 0;
+                       addr = ntohl(sin->sin_addr.s_addr);
+                       *port = ntohs(sin->sin_port);
+
+                       if (addr == PTP_PRIMARY_MCAST_ADDR || addr == 
PTP_PDELAY_MCAST_ADDR) {
+                               assert(sockets[socket].iface >= IFACE_ETH0);
+                               *subnet = sockets[socket].iface - IFACE_ETH0;
+                               *node = -1; /* multicast as broadcast */
+                               return 1;
+                       }
+                       break;
+               case AF_INET6:
+                       sin6 = (const struct sockaddr_in6 *)saddr;
+                       if (saddrlen < sizeof (*sin6))
+                               return 0;
+                       *port = ntohs(sin6->sin6_port);
+                       if (memcmp(sin6->sin6_addr.s6_addr, 
PTP_PRIMARY_MCAST_ADDR6, 16) == 0 ||
+                           memcmp(sin6->sin6_addr.s6_addr, 
PTP_PDELAY_MCAST_ADDR6, 16) == 0) {
+                               assert(sockets[socket].iface >= IFACE_ETH0);
+                               *subnet = sockets[socket].iface - IFACE_ETH0;
+                               *node = -1;
+                               return 1;
+                       }
+                       if (!IS_SIN6_KNOWN(sin6))
+                               return 0;
+                       addr = ADDR_FROM_SIN6(sin6);
+                       break;
+               default:
+                       return 0;
+       }
 
-               if (addr == BROADCAST_ADDR(*subnet))
-                       *node = -1; /* broadcast */
-               else
-                       *node = NODE_FROM_ADDR(addr);
+       *subnet = SUBNET_FROM_ADDR(addr);
+       if (fuzz_mode && (*subnet >= subnets || *subnet == unix_subnet))
+               *subnet = 0;
+
+       assert(*subnet >= 0 && *subnet < subnets);
+       assert(socket_in_subnet(socket, *subnet));
+
+       if (addr == BROADCAST_ADDR(*subnet))
+               *node = -1; /* broadcast */
+       else
+               *node = NODE_FROM_ADDR(addr);
+
+       return 1;
+}
+
+static int set_sockaddr(int domain, unsigned int subnet, unsigned int node, 
unsigned int port,
+                       struct sockaddr *saddr, socklen_t *saddrlen) {
+       struct sockaddr_in6 *sin6;
+       struct sockaddr_in *sin;
+       struct sockaddr_un *sun;
+
+       switch (domain) {
+               case AF_INET:
+                       assert(*saddrlen >= sizeof (*sin));
+                       sin = (struct sockaddr_in *)saddr;
+                       memset(sin, 0, sizeof (*sin));
+                       sin->sin_family = AF_INET;
+                       sin->sin_port = htons(port);
+                       sin->sin_addr.s_addr = htonl(NODE_ADDR(subnet, node));
+                       *saddrlen = sizeof (*sin);
+                       break;
+               case AF_INET6:
+                       assert(*saddrlen >= sizeof (*sin6));
+                       sin6 = (struct sockaddr_in6 *)saddr;
+                       memset(sin6, 0, sizeof (*sin6));
+                       sin6->sin6_family = AF_INET6;
+                       sin6->sin6_port = htons(port);
+                       memcpy(sin6->sin6_addr.s6_addr, IP6_NET, 14);
+                       sin6->sin6_addr.s6_addr[14] = subnet;
+                       sin6->sin6_addr.s6_addr[15] = node + 1;
+                       *saddrlen = sizeof (*sin6);
+                       break;
+               case AF_UNIX:
+                       assert(*saddrlen >= sizeof (*sun));
+                       sun = (struct sockaddr_un *)saddr;
+                       memset(sun, 0, sizeof (*sun));
+                       sun->sun_family = AF_UNIX;
+                       snprintf(sun->sun_path, sizeof (sun->sun_path),
+                                "/clknetsim/unix/%d:%d", node + 1, port);
+                       *saddrlen = sizeof (*sun);
+                       break;
+               default:
+                       return 0;
        }
+
+       return 1;
 }
 
 static int get_network_from_iface(const char *iface) {
@@ -676,7 +782,7 @@
 static void send_msg_to_peer(int s, int type) {
        struct Request_send req;
 
-       assert(sockets[s].domain == AF_INET);
+       assert(sockets[s].domain == AF_INET || sockets[s].domain == AF_INET6);
        assert(sockets[s].type == SOCK_STREAM);
 
        if (sockets[s].remote_node == -1)
@@ -784,7 +890,7 @@
 
 static void add_to_timespec(struct timespec *tp, double offset) {
        tp->tv_sec += floor(offset);
-       tp->tv_nsec += (offset - floor(offset)) * 1e9;
+       tp->tv_nsec += round((offset - floor(offset)) * 1e9);
        normalize_timespec(tp);
 }
 
@@ -793,60 +899,85 @@
 }
 
 static double get_phc_delay(int dir) {
+       static unsigned int count = 0;
        double L, p, delay = 0.0;
        int k, lambda = 5;
 
        /* Poisson with uniform steps */
-       if (phc_jitter > 0.0) {
+       if (phc_jitter > 0.0 && count >= phc_jitter_off) {
                for (L = exp(-lambda), p = 1.0, k = 0; k < 100 && p > L; k++)
                        p *= get_random_double();
                delay += (k + get_random_double()) / (lambda + 0.5) *
                        phc_jitter * (0.5 + dir * phc_jitter_asym);
        }
 
+       count++;
+       if (count >= phc_jitter_on + phc_jitter_off)
+               count = 0;
+
        return (delay + phc_delay / 2.0) * (freq_error + 1.0);
 }
 
 static int generate_eth_frame(unsigned int type, unsigned int subnet, unsigned 
int from,
                              unsigned int to, unsigned int src_port, unsigned 
int dst_port,
                              char *data, unsigned int data_len, char *frame, 
unsigned int buf_len) {
-       uint16_t port1, port2, ip_len, udp_len;
+       uint16_t port1, port2, ip_len, udp_len, len_offset, proto_offset, 
ip_header_len;
        uint32_t addr1, addr2;
 
+       ip_header_len = ip_family == 6 ? 40 : 20;
+
        assert(type == SOCK_DGRAM || type == SOCK_STREAM);
 
-       if ((type == SOCK_DGRAM && data_len + 42 > buf_len) ||
-           (type == SOCK_STREAM && data_len + 54 > buf_len))
+       if ((type == SOCK_DGRAM && data_len + 14 + ip_header_len + 8 > buf_len) 
||
+           (type == SOCK_STREAM && data_len + 14 + ip_header_len + 20 > 
buf_len))
                return 0;
 
-       addr1 = htonl(NODE_ADDR(subnet, from));
-       addr2 = htonl(NODE_ADDR(subnet, to));
+       memset(frame, 0, buf_len);
+       if (ip_family == 6) {
+               frame[12] = 0x86;
+               frame[13] = 0xDD;
+               frame[14] = 0x60;
+               len_offset = 14 + 4;
+               ip_len = 0;
+               proto_offset = 14 + 6;
+               memcpy(frame + 14 + 8, IP6_NET, 16);
+               frame[14 + 8 + 14] = subnet;
+               frame[14 + 8 + 15] = from + 1;
+               memcpy(frame + 14 + 24, IP6_NET, 16);
+               frame[14 + 24 + 14] = subnet;
+               frame[14 + 24 + 15] = to + 1;
+       } else {
+               frame[12] = 0x08;
+               frame[14] = 0x45;
+               len_offset = 14 + 2;
+               ip_len = ip_header_len;
+               proto_offset = 14 + 9;
+               addr1 = htonl(NODE_ADDR(subnet, from));
+               addr2 = htonl(NODE_ADDR(subnet, to));
+               memcpy(frame + 14 + 12, &addr1, sizeof (addr1));
+               memcpy(frame + 14 + 16, &addr2, sizeof (addr2));
+       }
+
        port1 = htons(src_port);
        port2 = htons(dst_port);
-
-       memset(frame, 0, buf_len);
-       frame[12] = 0x08;
-       frame[14] = 0x45;
-       memcpy(frame + 26, &addr1, sizeof (addr1));
-       memcpy(frame + 30, &addr2, sizeof (addr2));
-       memcpy(frame + 34, &port1, sizeof (port1));
-       memcpy(frame + 36, &port2, sizeof (port2));
+       memcpy(frame + 14 + ip_header_len + 0, &port1, sizeof (port1));
+       memcpy(frame + 14 + ip_header_len + 2, &port2, sizeof (port2));
 
        if (type == SOCK_DGRAM) {
-               ip_len = htons(data_len + 28);
+               ip_len = htons(ip_len + 8 + data_len);
                udp_len = htons(data_len + 8);
-               memcpy(frame + 16, &ip_len, sizeof (ip_len));
-               frame[23] = 17;
-               memcpy(frame + 38, &udp_len, sizeof (udp_len));
-               memcpy(frame + 42, data, data_len);
-               return data_len + 42;
+               memcpy(frame + len_offset, &ip_len, sizeof (ip_len));
+               frame[proto_offset] = 17;
+               memcpy(frame + 14 + ip_header_len + 4, &udp_len, sizeof 
(udp_len));
+               memcpy(frame + 14 + ip_header_len + 8, data, data_len);
+               return 14 + ip_header_len + 8 + data_len;
        } else {
-               ip_len = htons(data_len + 40);
-               memcpy(frame + 16, &ip_len, sizeof (ip_len));
-               frame[23] = 6;
-               frame[46] = 5 << 4;
-               memcpy(frame + 54, data, data_len);
-               return data_len + 54;
+               ip_len = htons(ip_len + 8 + data_len);
+               memcpy(frame + len_offset, &ip_len, sizeof (ip_len));
+               frame[proto_offset] = 6;
+               frame[14 + ip_header_len + 12] = 5 << 4;
+               memcpy(frame + 14 + ip_header_len + 20, data, data_len);
+               return 14 + ip_header_len + 20 + data_len;
        }
 }
 
@@ -972,7 +1103,7 @@
 }
 
 int clock_settime(clockid_t which_clock, const struct timespec *tp) {
-       assert(tp && which_clock == CLOCK_REALTIME);
+       assert(which_clock == CLOCK_REALTIME);
 
        if (tp->tv_sec < 0 || tp->tv_sec > ((1LLU << 63) / 1000000000)) {
                errno = EINVAL;
@@ -996,6 +1127,8 @@
                req.timex.freq = buf->freq;
        if (buf->modes & ADJ_MAXERROR)
                req.timex.maxerror = buf->maxerror;
+       if (buf->modes & ADJ_ESTERROR)
+               req.timex.esterror = buf->esterror;
        if (buf->modes & ADJ_STATUS)
                req.timex.status = buf->status;
        if ((buf->modes & ADJ_TIMECONST) || (buf->modes & ADJ_TAI))
@@ -1086,14 +1219,20 @@
        int i, timer, s, recv_fd = -1;
        double elapsed = 0.0;
 
+       req.read = 0;
+       req._pad = 0;
+
        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))
+                       if (s < 0)
+                               continue;
+                       if (sockets[s].type == SOCK_STREAM && 
!sockets[s].connected) {
+                               req.read = 1;
                                continue;
+                       }
                        FD_ZERO(writefds);
                        FD_SET(i, writefds);
                        if (exceptfds)
@@ -1122,9 +1261,6 @@
                FD_ZERO(exceptfds);
        }
 
-       req.read = 0;
-       req._pad = 0;
-
        /* unknown reading fds are always ready (e.g. chronyd waiting
           for name resolving notification, or OpenSSL waiting for
           /dev/urandom) */
@@ -1152,8 +1288,7 @@
 
        timer = get_first_timer(readfds);
 
-       assert((timeout && (timeout->tv_sec > 0 || timeout->tv_usec > 0)) ||
-              timer >= 0 || find_recv_socket(NULL) >= 0);
+       assert(timeout || timer >= 0 || find_recv_socket(NULL) >= 0);
 
        fetch_time();
 
@@ -1296,6 +1431,8 @@
        FD_ZERO(&wfds);
        FD_ZERO(&efds);
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
        for (i = 0; i < nfds; i++) {
                if (fds[i].fd < 0)
                       continue;
@@ -1309,6 +1446,7 @@
                if (maxfd < fds[i].fd)
                        maxfd = fds[i].fd;
        }
+#pragma GCC diagnostic pop
 
        if (timeout >= 0) {
                tv.tv_sec = timeout / 1000;
@@ -1412,6 +1550,8 @@
        if (fd == URANDOM_FD)
                return URANDOM_FILE;
 
+       init_symbols();
+
        return _fdopen(fd, mode);
 }
 
@@ -1493,6 +1633,10 @@
        return r;
 }
 
+int __open_2(const char *pathname, int oflag) {
+       return open(pathname, oflag);
+}
+
 ssize_t read(int fd, void *buf, size_t count) {
        int t;
 
@@ -1533,6 +1677,10 @@
        return _read(fd, buf, count);
 }
 
+ssize_t __read_chk(int fd, void *buf, size_t count, size_t buflen) {
+       return read(fd, buf, count);
+}
+
 int close(int fd) {
        int t, s;
 
@@ -1542,7 +1690,7 @@
                pps_fds--;
                return 0;
        } else if ((t = get_timer_from_fd(fd)) >= 0) {
-               return timer_delete(get_timerid(t));
+               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);
@@ -1556,7 +1704,9 @@
 int socket(int domain, int type, int protocol) {
        int s;
 
-       if ((domain != AF_INET && (domain != AF_UNIX || unix_subnet < 0)) ||
+       if (((domain != AF_INET || ip_family == 6) &&
+            (domain != AF_INET6 || ip_family == 4) &&
+            (domain != AF_UNIX || unix_subnet < 0)) ||
            (type != SOCK_DGRAM && type != SOCK_STREAM)) {
                errno = EINVAL;
                return -1;
@@ -1583,7 +1733,8 @@
 int listen(int sockfd, int backlog) {
        int s = get_socket_from_fd(sockfd);
 
-       if (s < 0 || sockets[s].domain != AF_INET || sockets[s].type != 
SOCK_STREAM) {
+       if (s < 0 || (sockets[s].domain != AF_INET && sockets[s].domain != 
AF_INET6) ||
+           sockets[s].type != SOCK_STREAM) {
                errno = EINVAL;
                return -1;
        }
@@ -1595,10 +1746,10 @@
 
 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].domain != AF_INET || sockets[s].type != 
SOCK_STREAM) {
+       if (s < 0 || (sockets[s].domain != AF_INET && sockets[s].domain != 
AF_INET6) ||
+           sockets[s].type != SOCK_STREAM) {
                errno = EINVAL;
                return -1;
        }
@@ -1606,7 +1757,7 @@
        make_request(REQ_RECV, NULL, 0, &rep, sizeof (rep));
        assert(rep.type == MSG_TYPE_TCP_CONNECT);
 
-       r = socket(AF_INET, SOCK_STREAM, 0);
+       r = socket(sockets[s].domain, SOCK_STREAM, 0);
        s = get_socket_from_fd(r);
        assert(s >= 0);
 
@@ -1616,12 +1767,8 @@
        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));
+       set_sockaddr(sockets[s].domain, sockets[s].iface - IFACE_ETH0, node,
+                    sockets[s].remote_port, addr, addrlen);
 
        send_msg_to_peer(s, MSG_TYPE_TCP_CONNECT);
 
@@ -1637,7 +1784,7 @@
                return -1;
        }
 
-       assert(sockets[s].domain == AF_INET);
+       assert(sockets[s].domain == AF_INET || sockets[s].domain == AF_INET6);
        assert(sockets[s].type == SOCK_STREAM);
 
        if (sockets[s].connected) {
@@ -1652,8 +1799,7 @@
        /* ntpd uses connect() and getsockname() to find the interface
           which will be used to send packets to an address */
        int s = get_socket_from_fd(sockfd);
-       unsigned int node, subnet;
-       struct sockaddr_in *sin;
+       unsigned int node, subnet, port;
        struct sockaddr_un *sun;
 
        if (s < 0) {
@@ -1663,21 +1809,20 @@
 
        switch (addr->sa_family) {
                case AF_INET:
-                       sin = (struct sockaddr_in *)addr;
-                       assert(addrlen >= sizeof (*sin));
-                       get_target(s, ntohl(sin->sin_addr.s_addr), &subnet, 
&node);
-                       if (node == -1) {
+               case AF_INET6:
+                       if (!get_ip_target(s, addr, addrlen, &subnet, &node, 
&port) ||
+                           node == -1) {
                                errno = EINVAL;
                                return -1;
                        }
 
                        sockets[s].iface = IFACE_ETH0 + subnet;
                        sockets[s].remote_node = node;
-                       sockets[s].remote_port = ntohs(sin->sin_port);
+                       sockets[s].remote_port = port;
                        break;
                case AF_UNIX:
                        sun = (struct sockaddr_un *)addr;
-                       assert(addrlen >= sizeof (*sun));
+                       assert(addrlen > offsetof(struct sockaddr_un, sun_path) 
+ 1);
 
                        assert(sockets[s].iface == IFACE_UNIX);
                        if (sscanf(sun->sun_path, "/clknetsim/unix/%d:%d",
@@ -1700,8 +1845,8 @@
 
 int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
        int s = get_socket_from_fd(sockfd), port;
+       struct sockaddr_in6 *sin6;
        struct sockaddr_in *sin;
-       struct sockaddr_un *sun;
        uint32_t a;
        static int unix_sockets = 0;
 
@@ -1738,9 +1883,28 @@
                                }
                        }
                        break;
+               case AF_INET6:
+                       assert(addrlen >= sizeof (*sin6));
+                       sin6 = (struct sockaddr_in6 *)addr;
+
+                       port = ntohs(sin6->sin6_port);
+                       if (port)
+                               sockets[s].port = port;
+
+                       if (memcmp(sin6->sin6_addr.s6_addr, 
in6addr_any.s6_addr, 16) == 0) {
+                               sockets[s].iface = IFACE_ALL;
+                       } else if (memcmp(sin6->sin6_addr.s6_addr, 
in6addr_loopback.s6_addr, 16) == 0) {
+                               sockets[s].iface = IFACE_LO;
+                       } else {
+                               int subnet = SUBNET_FROM_SIN6(sin6);
+                               assert(IS_SIN6_KNOWN(sin6));
+                               assert(subnet >= 0 && subnet < subnets);
+                               assert(NODE_FROM_SIN6(sin6) == node);
+                               sockets[s].iface = IFACE_ETH0 + subnet;
+                       }
+                       break;
                case AF_UNIX:
-                       assert(addrlen >= sizeof (*sun));
-                       sun = (struct sockaddr_un *)addr;
+                       assert(addrlen > offsetof(struct sockaddr_un, sun_path) 
+ 1);
 
                        assert(sockets[s].iface == IFACE_UNIX);
                        sockets[s].port = ++unix_sockets;
@@ -1757,11 +1921,16 @@
        int s = get_socket_from_fd(sockfd);
        uint32_t a;
 
-       if (s < 0 || sockets[s].domain != AF_INET) {
+       if (s < 0 || (sockets[s].domain != AF_INET && sockets[s].domain != 
AF_INET6)) {
                errno = EINVAL;
                return -1;
        }
 
+       if (sockets[s].domain == AF_INET6) {
+               return !set_sockaddr(sockets[s].domain, sockets[s].iface - 
IFACE_ETH0,
+                                    node, sockets[s].port, addr, addrlen);
+       }
+
        struct sockaddr_in *in;
        in = (struct sockaddr_in *)addr;
        assert(*addrlen >= sizeof (*in));
@@ -1793,7 +1962,7 @@
 int setsockopt(int sockfd, int level, int optname, const void *optval, 
socklen_t optlen) {
        int subnet, s = get_socket_from_fd(sockfd);
 
-       if (s < 0 || sockets[s].domain != AF_INET) {
+       if (s < 0 || (sockets[s].domain != AF_INET && sockets[s].domain != 
AF_INET6)) {
                errno = EINVAL;
                return -1;
        }
@@ -1808,7 +1977,8 @@
                        return -1;
                }
        }
-       else if (level == IPPROTO_IP && optname == IP_PKTINFO && optlen == 
sizeof (int))
+       else if (optlen == sizeof (int) && ((level == IPPROTO_IP && optname == 
IP_PKTINFO) ||
+                                           (level == IPPROTO_IPV6 && optname 
== IPV6_RECVPKTINFO)))
                sockets[s].pkt_info = !!(int *)optval;
 #ifdef SO_TIMESTAMPING
        else if (level == SOL_SOCKET && optname == SO_TIMESTAMPING && optlen >= 
sizeof (int)) {
@@ -1827,7 +1997,7 @@
 int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t 
*optlen) {
        int s = get_socket_from_fd(sockfd);
 
-       if (s < 0 || sockets[s].domain != AF_INET) {
+       if (s < 0 || (sockets[s].domain != AF_INET && sockets[s].domain != 
AF_INET6)) {
                errno = EINVAL;
                return -1;
        }
@@ -2048,24 +2218,24 @@
        } else if (request == PTP_SYS_OFFSET_EXTENDED && fd == REFCLK_FD) {
                struct ptp_sys_offset_extended *sys_off = va_arg(ap, struct 
ptp_sys_offset_extended *);
                struct timespec ts, ts1, ts2;
+               double delay;
                int i;
 
                if (sys_off->n_samples > PTP_MAX_SAMPLES)
                        sys_off->n_samples = PTP_MAX_SAMPLES;
 
                for (i = 0; i < sys_off->n_samples; i++) {
+                       clock_gettime(CLOCK_REALTIME, &ts2);
                        clock_gettime(REFCLK_ID, &ts);
-                       sys_off->ts[i][1].sec = ts.tv_sec;
-                       sys_off->ts[i][1].nsec = ts.tv_nsec;
-               }
-
-               clock_gettime(CLOCK_REALTIME, &ts);
-               for (i = 0; i < sys_off->n_samples; i++) {
-                       ts1 = ts, ts2 = ts;
-                       add_to_timespec(&ts1, -get_phc_delay(-1));
-                       add_to_timespec(&ts2, get_phc_delay(1));
+                       delay = get_phc_delay(1);
+                       add_to_timespec(&ts, -delay);
+                       delay += get_phc_delay(-1);
+                       ts1 = ts2;
+                       add_to_timespec(&ts1, -delay);
                        sys_off->ts[i][0].sec = ts1.tv_sec;
                        sys_off->ts[i][0].nsec = ts1.tv_nsec;
+                       sys_off->ts[i][1].sec = ts.tv_sec;
+                       sys_off->ts[i][1].nsec = ts.tv_nsec;
                        sys_off->ts[i][2].sec = ts2.tv_sec;
                        sys_off->ts[i][2].nsec = ts2.tv_nsec;
                }
@@ -2239,7 +2409,6 @@
 
 ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags) {
        struct Request_send req;
-       struct sockaddr_in *sin;
        struct sockaddr_un *sun;
        struct cmsghdr *cmsg;
        int i, s = get_socket_from_fd(sockfd), timestamping;
@@ -2262,15 +2431,16 @@
        } else {
                switch (sockets[s].domain) {
                        case AF_INET:
-                               sin = msg->msg_name;
-                               assert(sin && msg->msg_namelen >= sizeof 
(*sin));
-                               assert(sin->sin_family == AF_INET);
-                               get_target(s, ntohl(sin->sin_addr.s_addr), 
&req.subnet, &req.to);
-                               req.dst_port = ntohs(sin->sin_port);
+                       case AF_INET6:
+                               if (!get_ip_target(s, msg->msg_name, 
msg->msg_namelen, &req.subnet,
+                                                    &req.to, &req.dst_port)) {
+                                       errno = EINVAL;
+                                       return -1;
+                               }
                                break;
                        case AF_UNIX:
                                sun = msg->msg_name;
-                               assert(sun && msg->msg_namelen >= sizeof 
(*sun));
+                               assert(sun && msg->msg_namelen > 
offsetof(struct sockaddr_un, sun_path) + 1);
                                assert(sun->sun_family == AF_UNIX);
                                req.subnet = unix_subnet;
                                if (sscanf(sun->sun_path, 
"/clknetsim/unix/%u:%u",
@@ -2398,8 +2568,6 @@
 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags) {
        struct message *last_ts_msg = NULL;
        struct Reply_recv rep;
-       struct sockaddr_in *sin;
-       struct sockaddr_un *sun;
        struct cmsghdr *cmsg;
        int msglen, cmsglen, s = get_socket_from_fd(sockfd);
 
@@ -2428,7 +2596,6 @@
                                             sockets[s].port, last_ts_msg->port,
                                             last_ts_msg->data, 
last_ts_msg->len,
                                             rep.data, sizeof (rep.data));
-               rep.len = 42 + last_ts_msg->len;
 
                last_ts_msg->len = 0;
        } else if (sockets[s].buffer.len > 0) {
@@ -2492,25 +2659,8 @@
        assert(sockets[s].remote_port == -1 || sockets[s].remote_port == 
rep.src_port);
 
        if (msg->msg_name) {
-               switch (sockets[s].domain) {
-                       case AF_INET:
-                               assert(msg->msg_namelen >= sizeof (*sin));
-                               sin = msg->msg_name;
-                               sin->sin_family = AF_INET;
-                               sin->sin_port = htons(rep.src_port);
-                               sin->sin_addr.s_addr = 
htonl(NODE_ADDR(rep.subnet, rep.from));
-                               msg->msg_namelen = sizeof (struct sockaddr_in);
-                               break;
-                       case AF_UNIX:
-                               assert(msg->msg_namelen >= sizeof (*sun));
-                               sun = msg->msg_name;
-                               sun->sun_family = AF_UNIX;
-                               snprintf(sun->sun_path, sizeof (sun->sun_path),
-                                        "/clknetsim/unix/%d:%d", rep.from + 1, 
rep.src_port);
-                               break;
-                       default:
-                               assert(0);
-               }
+               set_sockaddr(sockets[s].domain, rep.subnet, rep.from, 
rep.src_port,
+                            msg->msg_name, &msg->msg_namelen);
        }
 
        assert(msg->msg_iovlen == 1);
@@ -2532,7 +2682,7 @@
 
        cmsglen = 0;
 
-       if (sockets[s].pkt_info) {
+       if (sockets[s].pkt_info && sockets[s].domain == AF_INET) {
                struct in_pktinfo ipi;
 
                cmsglen = CMSG_SPACE(sizeof (ipi));
@@ -2550,6 +2700,25 @@
                ipi.ipi_ifindex = rep.subnet + 1;
 
                memcpy(CMSG_DATA(cmsg), &ipi, sizeof (ipi));
+       } else if (sockets[s].pkt_info && sockets[s].domain == AF_INET6) {
+               struct in6_pktinfo ipi;
+
+               cmsglen = CMSG_SPACE(sizeof (ipi));
+               assert(msg->msg_control && msg->msg_controllen >= cmsglen);
+
+               cmsg = CMSG_FIRSTHDR(msg);
+               memset(cmsg, 0, sizeof (*cmsg));
+               cmsg->cmsg_level = IPPROTO_IPV6;
+               cmsg->cmsg_type = IPV6_PKTINFO;
+               cmsg->cmsg_len = CMSG_LEN(sizeof (ipi));
+
+               memset(&ipi, 0, sizeof (ipi));
+               memcpy(ipi.ipi6_addr.s6_addr, IP6_NET, 14);
+               ipi.ipi6_addr.s6_addr[14] = rep.subnet;
+               ipi.ipi6_addr.s6_addr[15] = node + 1;
+               ipi.ipi6_ifindex = rep.subnet + 1;
+
+               memcpy(CMSG_DATA(cmsg), &ipi, sizeof (ipi));
        }
 
 #ifdef SO_TIMESTAMPING
@@ -2646,7 +2815,7 @@
        return recv(fd, buf, len, flags);
 }
 
-int timer_create(clockid_t which_clock, struct sigevent *timer_event_spec, 
timer_t *created_timer_id) {
+static int timer_create_(clockid_t which_clock, struct sigevent 
*timer_event_spec, timer_t *created_timer_id) {
        int t;
 
        assert(which_clock == CLOCK_REALTIME && timer_event_spec == NULL);
@@ -2669,7 +2838,11 @@
        return 0;
 }
 
-int timer_delete(timer_t timerid) {
+int timer_create(clockid_t which_clock, struct sigevent *timer_event_spec, 
timer_t *created_timer_id) {
+       return timer_create_(which_clock, timer_event_spec, created_timer_id);
+}
+
+static int timer_delete_(timer_t timerid) {
        int t = get_timer_from_id(timerid);
 
        if (t < 0) {
@@ -2682,7 +2855,11 @@
        return 0;
 }
 
-int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, 
struct itimerspec *ovalue) {
+int timer_delete(timer_t timerid) {
+       return timer_delete_(timerid);
+}
+
+static int timer_settime_(timer_t timerid, int flags, const struct itimerspec 
*value, struct itimerspec *ovalue) {
        int t = get_timer_from_id(timerid);
 
        if (t < 0) {
@@ -2707,7 +2884,11 @@
        return 0;
 }
 
-int timer_gettime(timer_t timerid, struct itimerspec *value) {
+int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, 
struct itimerspec *ovalue) {
+       return timer_settime_(timerid, flags, value, ovalue);
+}
+
+int timer_gettime_(timer_t timerid, struct itimerspec *value) {
        double timeout;
        int t = get_timer_from_id(timerid);
 
@@ -2728,6 +2909,10 @@
        return 0;
 }
 
+int timer_gettime(timer_t timerid, struct itimerspec *value) {
+       return timer_gettime_(timerid, value);
+}
+
 #ifndef CLKNETSIM_DISABLE_ITIMER
 int setitimer(__itimer_which_t which, const struct itimerval *new_value, 
struct itimerval *old_value) {
        struct itimerspec timerspec;
@@ -2790,11 +2975,11 @@
        else
                assert(!flags);
 
-       return timer_settime(get_timerid(get_timer_from_fd(fd)), flags, 
new_value, old_value);
+       return timer_settime_(get_timerid(get_timer_from_fd(fd)), flags, 
new_value, old_value);
 }
 
 int timerfd_gettime(int fd, struct itimerspec *curr_value) {
-       return timer_gettime(get_timerid(get_timer_from_fd(fd)), curr_value);
+       return timer_gettime_(get_timerid(get_timer_from_fd(fd)), curr_value);
 }
 
 int shmget(key_t key, size_t size, int shmflg) {
@@ -2986,22 +3171,34 @@
        return 0;
 }
 
-static struct addrinfo *get_addrinfo(uint32_t addr, int port, int type, struct 
addrinfo *next) {
+static struct addrinfo *get_addrinfo(int family, uint32_t addr, int port, int 
type, struct addrinfo *next) {
+       struct sockaddr_in6 *sin6;
        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);
+       socklen_t len;
 
        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;
+       if (family == 6) {
+               sin6 = malloc(sizeof *sin6);
+               len = sizeof (*sin6);
+               set_sockaddr(AF_INET6, SUBNET_FROM_ADDR(addr), 
NODE_FROM_ADDR(addr), port,
+                            (struct sockaddr *)sin6, &len);
+               r->ai_family = AF_INET6;
+               r->ai_socktype = type;
+               r->ai_addrlen = sizeof *sin6;
+               r->ai_addr = (struct sockaddr *)sin6;
+       } else {
+               sin = malloc(sizeof *sin);
+               sin->sin_family = AF_INET;
+               sin->sin_port = htons(port);
+               sin->sin_addr.s_addr = htonl(addr);
+               r->ai_family = AF_INET;
+               r->ai_socktype = type;
+               r->ai_addrlen = sizeof *sin;
+               r->ai_addr = (struct sockaddr *)sin;
+       }
 
        r->ai_next = next;
 
@@ -3010,14 +3207,21 @@
 
 int getaddrinfo(const char *node, const char *service, const struct addrinfo 
*hints,
                struct addrinfo **res) {
-       int port = 0, type = SOCK_DGRAM;
+       int family = ip_family, 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))
+               if (hints->ai_family == AF_INET)
+                      family = 4;
+               else if (hints->ai_family == AF_INET6)
+                      family = 6;
+               else if (hints->ai_family != AF_UNSPEC)
+                       return EAI_NONAME;
+
+               if (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;
        }
@@ -3032,9 +3236,10 @@
        }
 
        if (node == NULL) {
-               *res = get_addrinfo(INADDR_ANY, port, type, NULL);
+               assert(ip_family != 6);
+               *res = get_addrinfo(4, INADDR_ANY, port, type, NULL);
        } else if (inet_aton(node, &addr)) {
-               *res = get_addrinfo(ntohl(addr.s_addr), port, type, NULL);
+               *res = get_addrinfo(4, ntohl(addr.s_addr), port, type, NULL);
        } else if ((strlen(node) > 4 && strcmp(node + strlen(node) - 4, ".clk") 
== 0) ||
                   (strlen(node) > 5 && strcmp(node + strlen(node) - 5, 
".clk.") == 0)) {
                const char *s = strstr(node, ".net");
@@ -3049,11 +3254,13 @@
                        s = node + 5;
                        *res = NULL;
                        do {
-                               *res = get_addrinfo(NODE_ADDR(subnet, atoi(s + 
1) - 1), port, type, *res);
+                               *res = get_addrinfo(family, 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);
+                       *res = get_addrinfo(family, NODE_ADDR(subnet, atoi(node 
+ 4) - 1),
+                                           port, type, NULL);
                } else {
                        return EAI_NONAME;
                }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/clknetsim-633a0be069bac00e5aa562c0e5e15a3bf30b6af2/clknetsim.bash 
new/clknetsim-530d1a579a8ae1a0bb0f26079d8eef32136699e2/clknetsim.bash
--- old/clknetsim-633a0be069bac00e5aa562c0e5e15a3bf30b6af2/clknetsim.bash       
2024-06-10 14:23:41.000000000 +0200
+++ new/clknetsim-530d1a579a8ae1a0bb0f26079d8eef32136699e2/clknetsim.bash       
2025-06-24 15:51:35.000000000 +0200
@@ -94,9 +94,10 @@
            ;;
     esac
 
+    unset LISTEN_FDS NOTIFY_SOCKET
+
     if [[ $CLKNETSIM_CLIENT_WRAPPER == *valgrind* ]]; then
-           unset DEBUGINFOD_URLS
-           wrapper_options="--log-file=$CLKNETSIM_TMPDIR/valgrind.$node"
+           wrapper_options="--log-file=$CLKNETSIM_TMPDIR/valgrind.$node 
--enable-debuginfod=no"
     fi
 
     
LD_PRELOAD=${CLKNETSIM_PRELOAD:+$CLKNETSIM_PRELOAD:}$CLKNETSIM_PATH/clknetsim.so
 \
@@ -111,11 +112,11 @@
 }
 
 start_server() {
-    local nodes=$1 ret=0 wrapper_options=""
+    local nodes=$1 ret=0 wrapper_options="" i j
     shift
 
     if [[ $CLKNETSIM_SERVER_WRAPPER == *valgrind* ]]; then
-           wrapper_options="--log-file=$CLKNETSIM_TMPDIR/valgrind.0"
+           wrapper_options="--log-file=$CLKNETSIM_TMPDIR/valgrind.0 
--enable-debuginfod=no"
     fi
 
     $CLKNETSIM_SERVER_WRAPPER $wrapper_options \
@@ -128,14 +129,30 @@
     fi
 
     kill $client_pids &> /dev/null
+
+    i=0
+    for pid in $client_pids; do
+       i=$[i + 1]
+       j=0
+       while kill -0 $pid &> /dev/null; do
+           j=$[j + 1]
+           if [ $j -gt 30 ]; then
+               echo " node $i did not terminate" 1>&2
+               ret=1
+               break
+           fi
+           sleep 0.1
+       done
+    done
+
     client_pids=" "
 
-    if ls tmp/valgrind.* &> /dev/null; then
-       if grep -q 'ERROR SUMMARY: [^0]' tmp/valgrind.*; then
+    if ls $CLKNETSIM_TMPDIR/valgrind.* &> /dev/null; then
+       if grep -q 'ERROR SUMMARY: [^0]' $CLKNETSIM_TMPDIR/valgrind.*; then
                echo " valgrind error" 1>&2
                ret=1
        fi
-       sed -i '/^ERROR: ld.so: object.*from LD_PRELOAD cannot/d' tmp/log.[0-9]*
+       sed -i '/^ERROR: ld.so: object.*from LD_PRELOAD cannot/d' 
$CLKNETSIM_TMPDIR/log.[0-9]*
     fi
 
     return $ret
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/clknetsim-633a0be069bac00e5aa562c0e5e15a3bf30b6af2/clock.cc 
new/clknetsim-530d1a579a8ae1a0bb0f26079d8eef32136699e2/clock.cc
--- old/clknetsim-633a0be069bac00e5aa562c0e5e15a3bf30b6af2/clock.cc     
2024-06-10 14:23:41.000000000 +0200
+++ new/clknetsim-530d1a579a8ae1a0bb0f26079d8eef32136699e2/clock.cc     
2025-06-24 15:51:35.000000000 +0200
@@ -21,6 +21,7 @@
 #define MAXSEC 2048
 #define MAXTIMECONST 10
 #define MAXMAXERROR 16000000
+#define MAXERROR_RATE 500
 #define SHIFT_FLL 2
 #define SCALE_FREQ 65536.0e6
 #define MAXFREQ_SCALED 32768000
@@ -47,6 +48,9 @@
        ntp_timex.tick = base_tick;
        ntp_timex.tolerance = MAXFREQ_SCALED;
        ntp_timex.precision = 1;
+       ntp_timex.maxerror = MAXMAXERROR;
+       ntp_timex.esterror = MAXMAXERROR;
+       ntp_timex.status = STA_UNSYNC;
 
        ntp_state = TIME_OK;
 
@@ -194,6 +198,12 @@
        } else
                ss_slew = 0;
 
+       ntp_timex.maxerror += MAXERROR_RATE;
+       if (ntp_timex.maxerror >= MAXMAXERROR) {
+               ntp_timex.maxerror = MAXMAXERROR;
+               ntp_timex.status |= STA_UNSYNC;
+       }
+
        switch (ntp_state) {
                case TIME_OK:
                        if (ntp_timex.status & STA_INS)
@@ -293,8 +303,20 @@
                else if (ntp_timex.freq < -MAXFREQ_SCALED)
                        ntp_timex.freq = -MAXFREQ_SCALED;
        }
-       if (buf->modes & ADJ_MAXERROR)
+       if (buf->modes & ADJ_MAXERROR) {
                ntp_timex.maxerror = buf->maxerror;
+               if (ntp_timex.maxerror > MAXMAXERROR)
+                       ntp_timex.maxerror = MAXMAXERROR;
+               if (ntp_timex.maxerror < 0)
+                       ntp_timex.maxerror = 0;
+       }
+       if (buf->modes & ADJ_ESTERROR) {
+               ntp_timex.esterror = buf->esterror;
+               if (ntp_timex.esterror > MAXMAXERROR)
+                       ntp_timex.esterror = MAXMAXERROR;
+               if (ntp_timex.esterror < 0)
+                       ntp_timex.esterror = 0;
+       }
        if (buf->modes & ADJ_STATUS) {
                if ((buf->status & STA_PLL) && !(ntp_timex.status & STA_PLL))
                        ntp_update_interval = 0;
@@ -336,6 +358,7 @@
        }
 
        t = ntp_timex;
+       t.modes = buf->modes;
 
        if ((buf->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT) {
                if ((buf->modes & ADJ_OFFSET_SS_READ) == ADJ_OFFSET_SINGLESHOT) 
{
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/clknetsim-633a0be069bac00e5aa562c0e5e15a3bf30b6af2/network.cc 
new/clknetsim-530d1a579a8ae1a0bb0f26079d8eef32136699e2/network.cc
--- old/clknetsim-633a0be069bac00e5aa562c0e5e15a3bf30b6af2/network.cc   
2024-06-10 14:23:41.000000000 +0200
+++ new/clknetsim-530d1a579a8ae1a0bb0f26079d8eef32136699e2/network.cc   
2025-06-24 15:51:35.000000000 +0200
@@ -56,10 +56,12 @@
        return 1e20;
 }
 
-Network::Network(const char *socket, unsigned int n, unsigned int subnets, 
unsigned int rate) {
+Network::Network(const char *socket, const char *executable,
+                unsigned int n, unsigned int subnets, unsigned int rate) {
                time = 0.0;
        this->subnets = subnets;
        socket_name = socket;
+       update_executable = executable;
        update_rate = rate;
        update_count = 0;
        offset_log = NULL;
@@ -282,6 +284,19 @@
        }
 
        update_clock_stats();
+
+       if (update_executable) {
+               pid_t pid = fork();
+               char buf[16];
+
+               if (pid == 0) {
+                       snprintf(buf, sizeof (buf), "%g", time);
+                       execl(update_executable, update_executable, buf, (char 
*)NULL);
+                       exit(1);
+               } else if (pid > 0) {
+                       waitpid(pid, NULL, 0);
+               }
+       }
 }
 
 void Network::update_clock_stats() {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/clknetsim-633a0be069bac00e5aa562c0e5e15a3bf30b6af2/network.h 
new/clknetsim-530d1a579a8ae1a0bb0f26079d8eef32136699e2/network.h
--- old/clknetsim-633a0be069bac00e5aa562c0e5e15a3bf30b6af2/network.h    
2024-06-10 14:23:41.000000000 +0200
+++ new/clknetsim-530d1a579a8ae1a0bb0f26079d8eef32136699e2/network.h    
2025-06-24 15:51:35.000000000 +0200
@@ -57,6 +57,7 @@
        unsigned int update_count;
 
        const char *socket_name;
+       const char *update_executable;
        vector<Node *> nodes;
        vector<Generator *> link_delays;
        vector<Generator *> link_corrections;
@@ -77,7 +78,7 @@
        void write_correction(struct Packet *packet, double correction);
 
        public:
-       Network(const char *socket, unsigned int n, unsigned int s, unsigned 
int rate);
+       Network(const char *socket, const char *executable, unsigned int n, 
unsigned int s, unsigned int rate);
        ~Network();
        bool prepare_clients();
        Node *get_node(unsigned int node);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/clknetsim-633a0be069bac00e5aa562c0e5e15a3bf30b6af2/server.cc 
new/clknetsim-530d1a579a8ae1a0bb0f26079d8eef32136699e2/server.cc
--- old/clknetsim-633a0be069bac00e5aa562c0e5e15a3bf30b6af2/server.cc    
2024-06-10 14:23:41.000000000 +0200
+++ new/clknetsim-530d1a579a8ae1a0bb0f26079d8eef32136699e2/server.cc    
2025-06-24 15:51:35.000000000 +0200
@@ -119,13 +119,13 @@
        int nodes, subnets = 1, help = 0, verbosity = 2, generate_only = 0, 
rate = 1;
        double limit = 10000.0, reset = 0.0;
        const char *offset_log = NULL, *freq_log = NULL, *rawfreq_log = NULL,
-             *packet_log = NULL, *config, *socket = "clknetsim.sock", *env;
+             *packet_log = NULL, *config, *socket = "clknetsim.sock", *env, 
*executable = NULL;
        struct timeval tv;
 
        int r, opt;
        Network *network;
 
-       while ((opt = getopt(argc, argv, "l:r:R:n:o:f:Gg:p:s:v:h")) != -1) {
+       while ((opt = getopt(argc, argv, "l:r:R:n:o:f:Gg:p:s:v:e:h")) != -1) {
                switch (opt) {
                        case 'l':
                                limit = atof(optarg);
@@ -160,6 +160,9 @@
                        case 'v':
                                verbosity = atoi(optarg);
                                break;
+                       case 'e':
+                               executable = optarg;
+                               break;
                        case 'h':
                        default:
                                help = 1;
@@ -179,6 +182,7 @@
                printf("       -p file       log packet delays to file\n");
                printf("       -s socket     set server socket name (default 
clknetsim.sock)\n");
                printf("       -v level      set verbosity level (default 
2)\n");
+               printf("       -e file       execute file on every 
freq/log/stats update\n");
                printf("       -G            print num numbers generated by 
expr\n");
                printf("       -h            print usage\n");
                return 1;
@@ -200,7 +204,7 @@
                return 0;
        }
 
-       network = new Network(socket, nodes, subnets, rate);
+       network = new Network(socket, executable, nodes, subnets, rate);
        
        if (offset_log)
                network->open_offset_log(offset_log);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/clknetsim-633a0be069bac00e5aa562c0e5e15a3bf30b6af2/sysheaders.h 
new/clknetsim-530d1a579a8ae1a0bb0f26079d8eef32136699e2/sysheaders.h
--- old/clknetsim-633a0be069bac00e5aa562c0e5e15a3bf30b6af2/sysheaders.h 
2024-06-10 14:23:41.000000000 +0200
+++ new/clknetsim-530d1a579a8ae1a0bb0f26079d8eef32136699e2/sysheaders.h 
2025-06-24 15:51:35.000000000 +0200
@@ -17,6 +17,8 @@
 #include <math.h>
 #include <stddef.h>
 #include <stdlib.h>
+#include <sys/wait.h>
+#include <unistd.h>
 
 #ifdef __linux__
 #ifndef ADJ_SETOFFSET

Reply via email to