1 /*
2  * Copyright (C) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "sntp_client.h"
17 #include "ntp_trusted_time.h"
18 
19 #include <chrono>
20 #include <cstdio>
21 #include <ctime>
22 #include <iomanip>
23 #include <netdb.h>
24 #include <netinet/in.h>
25 #include <securec.h>
26 #include <sstream>
27 #include <string>
28 #include <sys/socket.h>
29 #include <sys/time.h>
30 #include <sys/types.h>
31 #include <unistd.h>
32 
33 #include "time_common.h"
34 
35 namespace OHOS {
36 namespace MiscServices {
37 namespace {
38 constexpr uint64_t SECONDS_SINCE_FIRST_EPOCH = 2208988800; // Seconds from 1/1/1900 00.00 to 1/1/1970 00.00;
39 constexpr uint64_t MILLISECOND_TO_SECOND = 1000;
40 constexpr uint64_t FRACTION_TO_SECOND = 0x100000000;
41 constexpr uint64_t UINT32_MASK = 0xFFFFFFFF;
42 const int VERSION_MASK = 0x38;
43 const int MODE_MASK = 0x7;
44 constexpr int32_t INDEX_ZERO = 0;
45 constexpr int32_t INDEX_ONE = 1;
46 constexpr int32_t INDEX_TWO = 2;
47 constexpr int32_t INDEX_THREE = 3;
48 constexpr int32_t INDEX_FOUR = 4;
49 constexpr int32_t TIME_OUT = 5;
50 constexpr unsigned char MODE_THREE = 3;
51 constexpr unsigned char VERSION_THREE = 3;
52 constexpr double TEN_TO_MINUS_SIX_POWER = 1.0e-6;
53 char const *NTP_PORT = "123";
54 constexpr int32_t NTP_MSG_OFFSET_ROOT_DELAY = 4;
55 constexpr int32_t NTP_MSG_OFFSET_ROOT_DISPERSION = 8;
56 constexpr int32_t NTP_MSG_OFFSET_REFERENCE_IDENTIFIER = 12;
57 constexpr int32_t REFERENCE_TIMESTAMP_OFFSET = 16;
58 constexpr int32_t ORIGINATE_TIMESTAMP_OFFSET = 24;
59 constexpr int32_t RECEIVE_TIMESTAMP_OFFSET = 32;
60 constexpr int32_t TRANSMIT_TIMESTAMP_OFFSET = 40;
61 constexpr int32_t NTP_PACKAGE_SIZE = 48;
62 constexpr int32_t SNTP_MSG_OFFSET_SIX = 6;
63 constexpr int32_t SNTP_MSG_OFFSET_THREE = 3;
64 } // namespace
65 
RequestTime(const std::string & host)66 bool SNTPClient::RequestTime(const std::string &host)
67 {
68     int bufLen = NTP_PACKAGE_SIZE;
69     struct addrinfo hints = { 0 }, *addrs;
70     hints.ai_family = AF_INET;
71     hints.ai_socktype = SOCK_DGRAM;
72     hints.ai_protocol = IPPROTO_UDP;
73     int error = getaddrinfo(host.c_str(), NTP_PORT, &hints, &addrs);
74     if (error != 0) {
75         TIME_HILOGE(TIME_MODULE_SERVICE, "getaddrinfo failed error %{public}d", error);
76         return false;
77     }
78 
79     // Create a socket for sending data
80     int sendSocket = socket(addrs->ai_family, addrs->ai_socktype, addrs->ai_protocol);
81     if (sendSocket < 0) {
82         TIME_HILOGE(TIME_MODULE_SERVICE,
83                     "create socket failed: %{public}s family: %{public}d socktype: %{public}d protocol: %{public}d",
84                     strerror(errno), addrs->ai_family, addrs->ai_socktype, addrs->ai_protocol);
85         return false;
86     }
87 
88     // Set send and recv function timeout
89     struct timeval timeout = { TIME_OUT, 0 };
90     setsockopt(sendSocket, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(struct timeval));
91     setsockopt(sendSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval));
92     if (connect(sendSocket, addrs->ai_addr, addrs->ai_addrlen) < 0) {
93         TIME_HILOGE(TIME_MODULE_SERVICE, "socket connect failed: %{public}s", strerror(errno));
94         close(sendSocket);
95         return false;
96     }
97 
98     // Create the NTP tx timestamp and fill the fields in the msg to be tx
99     char sendBuf[NTP_PACKAGE_SIZE] = { 0 };
100     CreateMessage(sendBuf);
101     if (send(sendSocket, sendBuf, bufLen, 0) < 0) {
102         TIME_HILOGE(TIME_MODULE_SERVICE, "Send socket message failed: %{public}s, Host: %{public}s",
103                     strerror(errno), host.c_str());
104         close(sendSocket);
105         return false;
106     }
107 
108     char bufferRx[NTP_PACKAGE_SIZE] = { 0 };
109     // Receive until the peer closes the connection
110     if (recv(sendSocket, bufferRx, NTP_PACKAGE_SIZE, 0) < 0) {
111         TIME_HILOGE(TIME_MODULE_SERVICE, "Receive socket message failed: %{public}s, Host: %{public}s",
112                     strerror(errno), host.c_str());
113         close(sendSocket);
114         return false;
115     }
116     close(sendSocket);
117     if (!ReceivedMessage(bufferRx)) {
118         TIME_HILOGE(TIME_MODULE_SERVICE, "ReceivedMessage failed: Host: %{public}s", host.c_str());
119         return false;
120     }
121     return true;
122 }
123 
SetClockOffset(int clockOffset)124 void SNTPClient::SetClockOffset(int clockOffset)
125 {
126     m_clockOffset = clockOffset;
127 }
128 
GetNtpTimestamp64(int offset,const char * buffer)129 uint64_t SNTPClient::GetNtpTimestamp64(int offset, const char *buffer)
130 {
131     TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
132     const int _len = sizeof(uint64_t);
133     char valueRx[_len];
134     errno_t ret = memset_s(valueRx, sizeof(uint64_t), 0, sizeof(uint64_t));
135     if (ret != EOK) {
136         TIME_HILOGE(TIME_MODULE_SERVICE, "memcpy_s failed, err = %{public}d", ret);
137         return false;
138     }
139     int numOfBit = sizeof(uint64_t) - 1;
140     for (int loop = offset; loop < offset + _len; loop++) {
141         valueRx[numOfBit] = buffer[loop];
142         numOfBit--;
143     }
144 
145     uint64_t milliseconds;
146     ret = memcpy_s(&milliseconds, sizeof(uint64_t), valueRx, sizeof(uint64_t));
147     if (ret != EOK) {
148         TIME_HILOGE(TIME_MODULE_SERVICE, "memcpy_s failed, err = %{public}d", ret);
149         return false;
150     }
151     return le64toh(milliseconds);
152 }
153 
ConvertUnixToNtp(struct ntp_timestamp * ntpTs,struct timeval * unixTs)154 void SNTPClient::ConvertUnixToNtp(struct ntp_timestamp *ntpTs, struct timeval *unixTs)
155 {
156     TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
157     // 0x83AA7E80; the seconds from Jan 1, 1900 to Jan 1, 1970
158     ntpTs->second = unixTs->tv_sec + SECONDS_SINCE_FIRST_EPOCH; // 0x83AA7E80;
159     ntpTs->fraction =
160         static_cast<uint64_t>((unixTs->tv_usec + 1) * (1LL << RECEIVE_TIMESTAMP_OFFSET) * TEN_TO_MINUS_SIX_POWER);
161     TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
162 }
163 
164 /*
165   *	/// SNTP Timestamp Format (as described in RFC 2030)
166   *                         1                   2                   3
167   *   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
168   *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
169   *   |                           Seconds                             |
170   *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
171   *   |                  Seconds Fraction (0-padded)                  |
172   *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
173   */
ConvertNtpToStamp(uint64_t _ntpTs)174 int64_t SNTPClient::ConvertNtpToStamp(uint64_t _ntpTs)
175 {
176     auto second = static_cast<uint32_t>((_ntpTs >> RECEIVE_TIMESTAMP_OFFSET) & UINT32_MASK);
177     auto fraction = static_cast<uint32_t>(_ntpTs & UINT32_MASK);
178     if (second == 0 && fraction == 0) {
179         return 0;
180     }
181     if (second < SECONDS_SINCE_FIRST_EPOCH) {
182         return 0;
183     }
184     // convert sntp timestamp to seconds
185     return ((second - SECONDS_SINCE_FIRST_EPOCH) * MILLISECOND_TO_SECOND) +
186            ((fraction * MILLISECOND_TO_SECOND) / FRACTION_TO_SECOND);
187 }
188 
CreateMessage(char * buffer)189 void SNTPClient::CreateMessage(char *buffer)
190 {
191     TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
192     struct ntp_timestamp ntp{};
193     struct timeval unix;
194 
195     gettimeofday(&unix, nullptr);
196     // convert unix time to ntp time
197     ConvertUnixToNtp(&ntp, &unix);
198     uint64_t _ntpTs = ntp.second;
199     _ntpTs = (_ntpTs << RECEIVE_TIMESTAMP_OFFSET) | ntp.fraction;
200     errno_t ret = TimeUtils::GetBootTimeMs(m_originateTimestamp);
201     if (ret != E_TIME_OK) {
202         return;
203     }
204 
205     SNTPMessage _sntpMsg{};
206     // Important, if you don't set the version/mode, the server will ignore you.
207     _sntpMsg.clear();
208     _sntpMsg._leapIndicator = 0;
209     _sntpMsg._versionNumber = VERSION_THREE;
210     _sntpMsg._mode = MODE_THREE;
211     // optional (?)
212     _sntpMsg._originateTimestamp = _ntpTs;
213     char value[sizeof(uint64_t)];
214     ret = memcpy_s(value, sizeof(uint64_t), &_sntpMsg._originateTimestamp, sizeof(uint64_t));
215     if (ret != EOK) {
216         TIME_HILOGE(TIME_MODULE_SERVICE, "memcpy_s failed, err = %{public}d", ret);
217         return;
218     }
219     int numOfBit = sizeof(uint64_t) - 1;
220     int offsetEnd = ORIGINATE_TIMESTAMP_OFFSET + sizeof(uint64_t);
221     for (int loop = ORIGINATE_TIMESTAMP_OFFSET; loop < offsetEnd; loop++) {
222         buffer[loop] = value[numOfBit];
223         numOfBit--;
224     }
225     // create the 1-byte info in one go... the result should be 27 :)
226     buffer[INDEX_ZERO] = (_sntpMsg._leapIndicator << SNTP_MSG_OFFSET_SIX) |
227                          (_sntpMsg._versionNumber << SNTP_MSG_OFFSET_THREE) | _sntpMsg._mode;
228     TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
229 }
230 
ReceivedMessage(char * buffer)231 bool SNTPClient::ReceivedMessage(char *buffer)
232 {
233     int64_t receiveBootTime = 0;
234     errno_t ret = TimeUtils::GetBootTimeMs(receiveBootTime);
235     if (ret != E_TIME_OK) {
236         return false;
237     }
238     SNTPMessage _sntpMsg;
239     _sntpMsg.clear();
240     _sntpMsg._leapIndicator = buffer[INDEX_ZERO] >> SNTP_MSG_OFFSET_SIX;
241     _sntpMsg._versionNumber = (buffer[INDEX_ZERO] & VERSION_MASK) >> SNTP_MSG_OFFSET_THREE;
242     _sntpMsg._mode = (buffer[INDEX_ZERO] & MODE_MASK);
243     _sntpMsg._stratum = buffer[INDEX_ONE];
244     _sntpMsg._pollInterval = buffer[INDEX_TWO];
245     _sntpMsg._precision = buffer[INDEX_THREE];
246     _sntpMsg._rootDelay = GetNtpField32(NTP_MSG_OFFSET_ROOT_DELAY, buffer);
247     _sntpMsg._rootDispersion = GetNtpField32(NTP_MSG_OFFSET_ROOT_DISPERSION, buffer);
248     int _refId[INDEX_FOUR];
249     GetReferenceId(NTP_MSG_OFFSET_REFERENCE_IDENTIFIER, buffer, _refId);
250     _sntpMsg._referenceIdentifier[INDEX_ZERO] = _refId[INDEX_ZERO];
251     _sntpMsg._referenceIdentifier[INDEX_ONE] = _refId[INDEX_ONE];
252     _sntpMsg._referenceIdentifier[INDEX_TWO] = _refId[INDEX_TWO];
253     _sntpMsg._referenceIdentifier[INDEX_THREE] = _refId[INDEX_THREE];
254     _sntpMsg._referenceTimestamp = GetNtpTimestamp64(REFERENCE_TIMESTAMP_OFFSET, buffer);
255     _sntpMsg._originateTimestamp = GetNtpTimestamp64(ORIGINATE_TIMESTAMP_OFFSET, buffer);
256     _sntpMsg._receiveTimestamp = GetNtpTimestamp64(RECEIVE_TIMESTAMP_OFFSET, buffer);
257     _sntpMsg._transmitTimestamp = GetNtpTimestamp64(TRANSMIT_TIMESTAMP_OFFSET, buffer);
258     int64_t _originClient = m_originateTimestamp;
259     int64_t _receiveServer = ConvertNtpToStamp(_sntpMsg._receiveTimestamp);
260     if (_receiveServer == 0) {
261         return false;
262     }
263     int64_t _transmitServer = ConvertNtpToStamp(_sntpMsg._transmitTimestamp);
264     if (_transmitServer == 0) {
265         return false;
266     }
267     int64_t _receiveClient = receiveBootTime;
268     int64_t _clockOffset = (((_receiveServer - _originClient) + (_transmitServer - _receiveClient)) / INDEX_TWO);
269     int64_t _roundTripDelay = (_receiveClient - _originClient) - (_transmitServer - _receiveServer);
270     mRoundTripTime = _roundTripDelay;
271     mNtpTime = receiveBootTime + _clockOffset;
272     mNtpTimeReference = std::chrono::duration_cast<std::chrono::milliseconds>(
273         NtpTrustedTime::GetInstance().GetBootTimeNs().time_since_epoch()).count();
274     SetClockOffset(_clockOffset);
275     TIME_HILOGI(TIME_MODULE_SERVICE, "_originClient:%{public}s, _receiveServer:%{public}s, _transmitServer:%{public}s,"
276                 "_receiveClient:%{public}s", std::to_string(_originClient).c_str(),
277                 std::to_string(_receiveServer).c_str(), std::to_string(_transmitServer).c_str(),
278                 std::to_string(_receiveClient).c_str());
279     return true;
280 }
281 
GetNtpField32(int offset,const char * buffer)282 unsigned int SNTPClient::GetNtpField32(int offset, const char *buffer)
283 {
284     TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
285     const int _len = sizeof(int);
286     char valueRx[_len];
287     errno_t ret = memset_s(valueRx, _len, 0, _len);
288     if (ret != EOK) {
289         TIME_HILOGE(TIME_MODULE_SERVICE, "memcpy_s failed, err = %{public}d", ret);
290         return false;
291     }
292     int numOfBit = sizeof(int) - 1;
293     for (int loop = offset; loop < offset + _len; loop++) {
294         valueRx[numOfBit] = buffer[loop];
295         numOfBit--;
296     }
297 
298     unsigned int milliseconds;
299     errno_t retValue = memcpy_s(&milliseconds, sizeof(int), valueRx, sizeof(int));
300     if (retValue != EOK) {
301         TIME_HILOGE(TIME_MODULE_SERVICE, "memcpy_s failed, err = %{public}d", retValue);
302         return false;
303     }
304     TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
305     return milliseconds;
306 }
307 
GetReferenceId(int offset,char * buffer,int * _outArray)308 void SNTPClient::GetReferenceId(int offset, char *buffer, int *_outArray)
309 {
310     TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
311     const int _len = sizeof(int);
312     int num = 0;
313     for (int loop = offset; loop < offset + _len; loop++) {
314         _outArray[num] = buffer[loop];
315         num++;
316     }
317     TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
318 }
319 
clear()320 void SNTPClient::SNTPMessage::clear()
321 {
322     TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
323     errno_t ret = memset_s(this, sizeof(*this), 0, sizeof(*this));
324     if (ret != EOK) {
325         TIME_HILOGE(TIME_MODULE_SERVICE, "memcpy_s failed, err = %{public}d", ret);
326     }
327 }
328 
getNtpTime()329 int64_t SNTPClient::getNtpTime()
330 {
331     return mNtpTime;
332 }
333 
getNtpTimeReference()334 int64_t SNTPClient::getNtpTimeReference()
335 {
336     return mNtpTimeReference;
337 }
338 
getRoundTripTime()339 int64_t SNTPClient::getRoundTripTime()
340 {
341     return mRoundTripTime;
342 }
343 } // namespace MiscServices
344 } // namespace OHOS