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