Showing 4 changed files with 117 additions and 0 deletions
+2
README.md
... ...
@@ -23,4 +23,6 @@ Utilities to check NTP resolution
23 23
   - Kerlink iFemto Legacy
24 24
 - riscv64
25 25
   - Lichee Nano RV
26
+- win64
27
+  - ntpprint only Windows 10 & Windows 11
26 28
  
+6
build-win64.sh
... ...
@@ -0,0 +1,6 @@
1
+#!/bin/bash
2
+OUTPUTDIR="win64"
3
+mkdir -p $OUTPUTDIR
4
+x86_64-w64-mingw32-gcc-posix -O2 -o $OUTPUTDIR/ntpprint ntpprint-win.c -lws2_32 -Wl,-subsystem,console
5
+x86_64-w64-mingw32-strip $OUTPUTDIR/*
6
+
+109
ntpprint-win.c
... ...
@@ -0,0 +1,109 @@
1
+#include <stdio.h>
2
+#include <stdlib.h>
3
+#include <string.h>
4
+#include <winsock2.h>
5
+#include <windows.h>
6
+#include <time.h>
7
+
8
+#pragma comment(lib, "ws2_32.lib")
9
+
10
+#define NTP_TIMESTAMP_DELTA 2208988800ull
11
+
12
+typedef struct {
13
+    unsigned char li_vn_mode;      // Eight bits. li, vn, and mode.
14
+    unsigned char stratum;         // Stratum level of the local clock.
15
+    unsigned char poll;            // Maximum interval between successive messages.
16
+    unsigned char precision;       // Precision of the local clock.
17
+
18
+    unsigned int rootDelay;
19
+    unsigned int rootDispersion;
20
+    unsigned int refId;
21
+
22
+    unsigned int refTm_s;
23
+    unsigned int refTm_f;
24
+
25
+    unsigned int origTm_s;
26
+    unsigned int origTm_f;
27
+
28
+    unsigned int rxTm_s;
29
+    unsigned int rxTm_f;
30
+
31
+    unsigned int txTm_s;
32
+    unsigned int txTm_f;
33
+} NTPPacket;
34
+
35
+int main(int argc, char *argv[]) {
36
+    if (argc < 2) {
37
+        printf("Usage: %s <ntp_server>\n", argv[0]);
38
+        return 1;
39
+    }
40
+
41
+    const char* ntp_server = argv[1];
42
+    WSADATA wsaData;
43
+    SOCKET sock;
44
+    struct sockaddr_in serverAddr;
45
+    NTPPacket packet;
46
+
47
+    WSAStartup(MAKEWORD(2, 2), &wsaData);
48
+
49
+    memset(&packet, 0, sizeof(NTPPacket));
50
+    packet.li_vn_mode = 0x1B;  // LI = 0, VN = 3 (version), Mode = 3 (client)
51
+
52
+    sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
53
+    if (sock == INVALID_SOCKET) {
54
+        perror("socket");
55
+        return 1;
56
+    }
57
+
58
+    struct timeval timeout;
59
+    timeout.tv_sec = 5;
60
+    timeout.tv_usec = 0;
61
+    setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));
62
+
63
+    struct hostent* server = gethostbyname(ntp_server);
64
+    if (!server) {
65
+        printf("Error: Cannot resolve hostname %s\n", ntp_server);
66
+        closesocket(sock);
67
+        WSACleanup();
68
+        return 1;
69
+    }
70
+
71
+    memset(&serverAddr, 0, sizeof(serverAddr));
72
+    serverAddr.sin_family = AF_INET;
73
+    serverAddr.sin_port = htons(123); // NTP port
74
+    memcpy(&serverAddr.sin_addr, server->h_addr, server->h_length);
75
+
76
+    int sent = sendto(sock, (char*)&packet, sizeof(NTPPacket), 0,
77
+                      (struct sockaddr*)&serverAddr, sizeof(serverAddr));
78
+    if (sent == SOCKET_ERROR) {
79
+        perror("sendto");
80
+        closesocket(sock);
81
+        WSACleanup();
82
+        return 1;
83
+    }
84
+
85
+    struct sockaddr_in recvAddr;
86
+    int recvAddrLen = sizeof(recvAddr);
87
+    int recvLen = recvfrom(sock, (char*)&packet, sizeof(NTPPacket), 0,
88
+                           (struct sockaddr*)&recvAddr, &recvAddrLen);
89
+    if (recvLen == SOCKET_ERROR) {
90
+        //perror("recvfrom");
91
+        if (WSAGetLastError() == WSAETIMEDOUT) {
92
+            printf("Timeout: No response from NTP server within 5 seconds.\n");
93
+        } else {
94
+            perror("recvfrom");
95
+        }
96
+        closesocket(sock);
97
+        WSACleanup();
98
+        return 1;
99
+    }
100
+
101
+    packet.txTm_s = ntohl(packet.txTm_s);  // Convert from network byte order
102
+    time_t txTime = (time_t)(packet.txTm_s - NTP_TIMESTAMP_DELTA);
103
+
104
+    printf("Received time: %s", ctime(&txTime));
105
+
106
+    closesocket(sock);
107
+    WSACleanup();
108
+    return 0;
109
+}
BIN
win64/ntpprint.exe
Binary file not shown.