So I wrote this NTP client. Not an NTP daemon, it just queries an NTP server once. The point was to try a bit of network programming with Zig and get more familiar with NTP. It worked out quite nicely. I think I even got the arithmetic across the NTP era change right ^^
Now here comes the “but” and the question. It’s working fine via IPv4, but fails via IPv6. The query packet, which is just one UDP datagram, gets sent but there’s no response. Here are the steps to reproduce the problem. You can find the full code in this branch.
const std = @import("std");
// make a src address. use the default adapter.
const addr_src = try std.net.Address.resolveIp("0:0:0:0:0:0:0:0", 0);
// make a socket to send from.
const sock = try std.posix.socket(
posix.AF.INET6,
posix.SOCK.DGRAM | posix.SOCK.CLOEXEC,
posix.IPPROTO.UDP,
);
try posix.bind(sock, &addr_src.any, addr_src.getOsSockLen());
// obtain addresses for server to query. for this example, it will be an
// IPv6 in the list.
const addrlist = try net.getAddressList(allocator, "ntp.ubuntu.com", port);
// iterate the list, send an NTP query packet and wait for reply.
var buf: [1024]u8 = std.mem.zeroes([1024]u8);
for (addrlist.addrs) |dst| {
var dst_addr_sock = dst.any; // std.posix.sockaddr
var dst_addr_len: posix.socklen_t = dst.getOsSockLen();
// make the NTP query packet and fill the bytes into send-buffer:
ntp.Packet.toBytesBuffer(proto_vers, true, &buf);
const n_sent = try std.posix.sendto(
sock,
buf[0..ntp.packet_len], // 48 bytes
0, // no flags
&dst_addr_sock,
dst_addr_len,
);
// wait for reply etc.
}
No error, the packet gets sent but: no reply. Inspecting the sent packet with Wireshark, I found that the destination address seems wrong: ntp.ubuntu.com
resolves to 2620:2d:4000:1::40
, but the dst address that the packet from my program has is 2620:2d:4000:1:1c00:0:a00:7b
:
So the first 8 address bytes seem correct, but after that it’s nonsense? As a sanity-check, I triggered a system time sync by restarting systemd-timesyncd
, and everything is as expected (packets #5439 and #5440):
Can anybody give me a hint what I’m doing wrong? Am I using the socket incorrectly maybe?