1 /*
2 * Copyright (C) 2022-2023 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 "dns_lookup_parse.h"
17
18 #include <net/if.h>
19
20 #include "fwmark_client.h"
21 #include "net_manager_constants.h"
22 #include "netmanager_base_common_utils.h"
23
24 namespace OHOS {
25 namespace nmd {
26 using namespace NetManagerStandard;
27 static constexpr int32_t HOST_BIT_SIZE = 0x80;
28
29 static constexpr int32_t MAX_SPACE_SIZE = 254;
30 static constexpr int32_t INVALID_LENGTH = -1;
31 static constexpr int32_t STEP_SIZE = 2;
32 static constexpr uint8_t MASK_HIGH_TWO_BITS = 0xc0;
33 static constexpr uint8_t MASK_LOW_SIX_BITS = 0x3f;
34 static constexpr uint8_t BIT_NUM_OF_BYTE = 8;
35 static constexpr uint32_t HOST_NAME_LEN = 1;
36 static constexpr uint32_t HOST_NAME_LEN_MAX = 62;
37 static constexpr uint64_t MAX_BIT = 65536;
38 static constexpr int32_t NAME_MAX_BIT = 256;
39
40 static constexpr int32_t TIMEMSTOS = 1000;
41 static constexpr int32_t TIMEUSTOS = 1000000;
42 static constexpr int32_t DEFAULT_TIME_OUT = 5;
43 static constexpr int32_t DEFAULT_DOTS = 1;
44 static constexpr int32_t DEFAULT_ATTEMPTS = 2;
45 static constexpr int32_t DEFAULT_MAX_ATTEMPTS = 10;
46 static constexpr int32_t MINE_CLASS_MAX = 255;
47 static constexpr int32_t ONE_MINUTE = 60;
48 static constexpr int32_t HOSTNAME_LEN_DIFFER = 17;
49 static constexpr int32_t HOSTNAME_SIZE_DIFFER = 13;
50 static constexpr int32_t HOSTNAME_BUFF_COMPUTE = 8;
51 static constexpr int32_t OP_MAX = 15;
52 static constexpr int32_t TMP_LINE = 256;
53 static constexpr int32_t TYPE_MAX = 255;
54
55 static constexpr int32_t RR_CNAME = 5;
56 static constexpr int32_t CTX_DEFAULT_SCOPEID = 0;
57
58 static constexpr int32_t ANSWERS_OPERATION = 15;
59 static constexpr int32_t DEFAULT_PORT = 53;
60
61 static constexpr int32_t ADDR_A6_NOTES_LEN = 12;
62 static constexpr int32_t RLEN_MAXNS = 12;
63
64 static constexpr int32_t COUNT_CONVERT = 256;
65 static constexpr int32_t COUNT_MAX_LEN = 64;
66 static constexpr int32_t ANSWER_MAX_LEN = 254;
67 static constexpr int32_t ANSWER_LEN = 193;
68 static constexpr int32_t ANSWER_SIZE = 127;
69 static constexpr int32_t ANSWER_SIZE_DIFFER = 6;
70 static constexpr int32_t ANSWER_LEN_DIFFER = 10;
71 static constexpr int32_t ANSWER_STR = 5;
72 static constexpr int32_t NAME_IS_IPV4 = 1;
73
74 static constexpr int32_t MAX_FOR_KEY = 0x10000000;
75
76 #ifdef SERVER_SUPPORT_IPV6
77 static constexpr int32_t HOSTNAME_NOTES_LEN = 10;
78 static constexpr int32_t NAME_MAX_LEN = 64;
79 constexpr char SEP = '%';
80 #endif
81
LookupIpLiteralForIPV6(const char * hostName,int32_t & family,struct AddrData buf[ARG_INDEX_1])82 int32_t DnsLookUpParse::LookupIpLiteralForIPV6(const char *hostName, int32_t &family, struct AddrData buf[ARG_INDEX_1])
83 {
84 #ifdef SERVER_SUPPORT_IPV6
85 char tmp[NAME_MAX_LEN] = {0};
86 char *p = const_cast<char *>(strchr(hostName, SEP));
87 if (p && (p - hostName < NAME_MAX_LEN)) {
88 if (memcpy_s(tmp, p - hostName, hostName, p - hostName) != 0) {
89 return EAI_AGAIN;
90 }
91 tmp[p - hostName] = 0;
92 hostName = tmp;
93 }
94 in6_addr a6{};
95 if (inet_pton(AF_INET6, hostName, &a6) <= 0) {
96 return DNS_ERR_NONE;
97 }
98 if (family == AF_INET) {
99 NETNATIVE_LOGE("family wrong;");
100 return EAI_NONAME;
101 }
102
103 if (memcpy_s(&buf[ARG_INDEX_0].addr, sizeof(a6), &a6, sizeof(a6)) != 0) {
104 NETNATIVE_LOGE("memcpy_s faild");
105 return NETMANAGER_ERR_MEMCPY_FAIL;
106 }
107 buf[ARG_INDEX_0].family = AF_INET6;
108 uint64_t scopeid = 0;
109 if (p) {
110 char *z;
111 if (isdigit(*++p)) {
112 scopeid = strtoull(p, &z, HOSTNAME_NOTES_LEN);
113 } else {
114 z = p - 1;
115 }
116 if (*z) {
117 if (!IN6_IS_ADDR_LINKLOCAL(&a6) && !IN6_IS_ADDR_MC_LINKLOCAL(&a6)) {
118 return EAI_NONAME;
119 }
120 scopeid = if_nametoindex(p);
121 if (!scopeid) {
122 return EAI_NONAME;
123 }
124 }
125 if (scopeid > UINT_MAX) {
126 return EAI_NONAME;
127 }
128 }
129 buf[ARG_INDEX_0].scopeid = scopeid;
130 #endif
131 return DNS_ERR_NONE;
132 }
133
LookupIpLiteral(struct AddrData buf[ARG_INDEX_1],const std::string name,int32_t family)134 int32_t DnsLookUpParse::LookupIpLiteral(struct AddrData buf[ARG_INDEX_1], const std::string name, int32_t family)
135 {
136 if (name[0] == 0) {
137 return DNS_ERR_NONE;
138 }
139 const char *hostName = const_cast<char *>(name.c_str());
140 in_addr a4{};
141 if (inet_aton(hostName, &a4) > 0) {
142 if (family == AF_INET6) {
143 return EAI_NONAME;
144 }
145 if (memcpy_s(&buf[ARG_INDEX_0].addr, sizeof(a4), &a4, sizeof(a4)) != 0) {
146 NETNATIVE_LOGE("memcpy_s faild");
147 return NETMANAGER_ERR_MEMCPY_FAIL;
148 }
149 buf[ARG_INDEX_0].family = AF_INET;
150 buf[ARG_INDEX_0].scopeid = 0;
151 return NAME_IS_IPV4;
152 }
153
154 return LookupIpLiteralForIPV6(hostName, family, buf);
155 }
156
GetResolvConf(struct ResolvConf * conf,char * search,size_t search_sz,uint16_t netId)157 int32_t DnsLookUpParse::GetResolvConf(struct ResolvConf *conf, char *search, size_t search_sz, uint16_t netId)
158 {
159 (void)search_sz;
160 conf->nDots = DEFAULT_DOTS;
161 conf->timeOut = DEFAULT_TIME_OUT;
162 conf->attempts = DEFAULT_ATTEMPTS;
163 if (search) {
164 *search = 0;
165 }
166
167 uint16_t timeOutMs = 0;
168 uint8_t retry = 0;
169 std::vector<std::string> nameServers;
170 std::vector<std::string> domains;
171 int32_t ret = OHOS::DelayedSingleton<OHOS::nmd::DnsParamCache>::GetInstance()->GetResolverConfig(
172 netId, nameServers, domains, timeOutMs, retry);
173 if (ret < 0) {
174 return -1;
175 }
176
177 int32_t timeOutSecond = timeOutMs / TIMEMSTOS;
178 if (timeOutSecond > 0) {
179 if (timeOutSecond >= ONE_MINUTE) {
180 conf->timeOut = ONE_MINUTE;
181 } else {
182 conf->timeOut = static_cast<uint32_t>(timeOutSecond);
183 }
184 }
185 if (retry > 0) {
186 if (retry >= DEFAULT_MAX_ATTEMPTS) {
187 conf->attempts = DEFAULT_MAX_ATTEMPTS;
188 } else {
189 conf->attempts = retry;
190 }
191 }
192 uint32_t nns = 0;
193 for (auto &nameServer : nameServers) {
194 if (LookupIpLiteral(conf->ns + nns, nameServer, AF_UNSPEC) > 0) {
195 nns++;
196 }
197 }
198 conf->nns = nns;
199 return DNS_ERR_NONE;
200 }
201
mTime()202 uint64_t DnsLookUpParse::mTime()
203 {
204 timespec ts{};
205 clock_gettime(CLOCK_REALTIME, &ts);
206 return static_cast<uint64_t>(ts.tv_sec) * TIMEMSTOS + static_cast<uint64_t>(ts.tv_nsec) / TIMEUSTOS;
207 }
208
GetNsFromConf(const ResolvConf * conf,uint32_t & nns,int32_t & family,socklen_t & saLen)209 void DnsLookUpParse::GetNsFromConf(const ResolvConf *conf, uint32_t &nns, int32_t &family, socklen_t &saLen)
210 {
211 for (nns = 0; nns < conf->nns; nns++) {
212 const AddrData *ipLit = &conf->ns[nns];
213 if (ipLit->family == AF_INET) {
214 if (memcpy_s(&nSockAddr[nns].sin.sin_addr, ADDR_A4_LEN, ipLit->addr, ADDR_A4_LEN)) {
215 NETNATIVE_LOGE("memcpy_s faild");
216 return;
217 }
218 nSockAddr[nns].sin.sin_port = htons(DEFAULT_PORT);
219 nSockAddr[nns].sin.sin_family = AF_INET;
220 } else {
221 saLen = sizeof(sockAddr.sin6);
222 if (memcpy_s(&nSockAddr[nns].sin6.sin6_addr, ADDR_A6_LEN, ipLit->addr, ADDR_A6_LEN) != 0) {
223 NETNATIVE_LOGE("memcpy_s faild");
224 return;
225 }
226 nSockAddr[nns].sin6.sin6_port = htons(DEFAULT_PORT);
227 nSockAddr[nns].sin6.sin6_scope_id = ipLit->scopeid;
228 nSockAddr[nns].sin6.sin6_family = family = AF_INET6;
229 }
230 }
231 }
232
SetSocAddr(int32_t fd,uint32_t & nns)233 void DnsLookUpParse::SetSocAddr(int32_t fd, uint32_t &nns)
234 {
235 int32_t opt = 0;
236 if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1) {
237 NETNATIVE_LOGE("setsockopt failed error: [%{public}d]", errno);
238 return;
239 }
240 for (uint32_t i = 0; i < nns; i++) {
241 if (nSockAddr[i].sin.sin_family != AF_INET) {
242 continue;
243 }
244 int32_t ret = memcpy_s(nSockAddr[i].sin6.sin6_addr.s6_addr + ADDR_A6_NOTES_LEN, ADDR_A4_LEN,
245 &nSockAddr[i].sin.sin_addr, ADDR_A4_LEN);
246 ret += memcpy_s(nSockAddr[i].sin6.sin6_addr.s6_addr, ADDR_A6_NOTES_LEN, ADDR_BUF, ADDR_A6_NOTES_LEN);
247 if (ret != 0) {
248 NETNATIVE_LOGE("memcpy_s faild");
249 return;
250 }
251 nSockAddr[i].sin6.sin6_family = AF_INET6;
252 nSockAddr[i].sin6.sin6_flowinfo = 0;
253 nSockAddr[i].sin6.sin6_scope_id = 0;
254 }
255 }
256
SearchNameServer(GetAnswers * getAnswers,int32_t * answersLens,const uint8_t * const * queries,const int32_t * queriesLens)257 void DnsLookUpParse::SearchNameServer(GetAnswers *getAnswers, int32_t *answersLens, const uint8_t *const *queries,
258 const int32_t *queriesLens)
259 {
260 for (int32_t i = 0; i < getAnswers->queriesNum; i++) {
261 if (answersLens[i]) {
262 break;
263 }
264 for (uint32_t j = 0; j < getAnswers->nns; j++) {
265 std::string dnsServerIp = std::string(inet_ntoa(nSockAddr[j].sin.sin_addr));
266 NETNATIVE_LOGI("DNS send to server is %{public}s", CommonUtils::ToAnonymousIp(dnsServerIp).c_str());
267 sendto(getAnswers->fd, queries[i], queriesLens[i], MSG_NOSIGNAL,
268 reinterpret_cast<sockaddr *>(&nSockAddr[j]), getAnswers->saLen);
269 }
270 }
271 }
272
DnsGetAnswers(GetAnswers getAnswers,const uint8_t * const * queries,const int32_t * queriesLens,uint8_t * const * answers,int32_t * answersLens,int32_t servFailRetry)273 void DnsLookUpParse::DnsGetAnswers(GetAnswers getAnswers, const uint8_t *const *queries, const int32_t *queriesLens,
274 uint8_t *const *answers, int32_t *answersLens, int32_t servFailRetry)
275 {
276 socklen_t psl[1] = {getAnswers.saLen};
277 int32_t recvLen = 0;
278 int32_t next = 0;
279 while ((recvLen = recvfrom(getAnswers.fd, answers[next], getAnswers.answersSize, 0,
280 reinterpret_cast<sockaddr *>(&sockAddr), psl)) >= 0) {
281 psl[0] = getAnswers.saLen;
282
283 uint32_t j = 0;
284 for (; j < getAnswers.nns && memcmp(nSockAddr + j, &sockAddr, getAnswers.saLen); j++)
285 ;
286 if (j == getAnswers.nns) {
287 continue;
288 }
289 int32_t i = next;
290 for (; i < getAnswers.queriesNum && (answers[next][0] != queries[i][0] || answers[next][1] != queries[i][1]);
291 i++)
292 ;
293 if (i == getAnswers.queriesNum || answersLens[i]) {
294 continue;
295 }
296
297 switch (answers[next][ARG_INDEX_3] & ANSWERS_OPERATION) {
298 case ARG_INDEX_0:
299 case ARG_INDEX_3:
300 break;
301 case ARG_INDEX_2:
302 if (servFailRetry) {
303 (void)sendto(getAnswers.fd, queries[i], queriesLens[i], MSG_NOSIGNAL,
304 reinterpret_cast<sockaddr *>(&nSockAddr[j]), getAnswers.saLen);
305 servFailRetry--;
306 }
307 [[fallthrough]];
308 default:
309 continue;
310 }
311
312 answersLens[i] = recvLen;
313 if (i == next) {
314 for (; next < getAnswers.queriesNum && answersLens[next]; next++)
315 ;
316 } else {
317 if (memcpy_s(answers[i], recvLen, answers[next], recvLen) != 0) {
318 NETNATIVE_LOGE("memcpy_s faild");
319 return;
320 }
321 }
322
323 if (next == getAnswers.queriesNum) {
324 return;
325 }
326 }
327 }
328
DnsSendQueries(GetAnswers getAnswers,const uint8_t * const * queries,const int32_t * queriesLens,uint8_t * const * answers,int32_t * answersLens)329 int32_t DnsLookUpParse::DnsSendQueries(GetAnswers getAnswers, const uint8_t *const *queries, const int32_t *queriesLens,
330 uint8_t *const *answers, int32_t *answersLens)
331 {
332 pollfd pfd{};
333 pfd.fd = getAnswers.fd;
334 pfd.events = POLLIN;
335 int32_t retryInterval = getAnswers.timeOut / getAnswers.attempts;
336 uint64_t time0 = mTime();
337 uint64_t time2 = mTime();
338 uint64_t time1 = time2 - static_cast<uint64_t>(retryInterval);
339 int32_t servFailRetry = 0;
340 for (; time2 - time0 < static_cast<uint64_t>(getAnswers.timeOut); time2 = mTime()) {
341 if (time2 - time1 >= static_cast<uint64_t>(retryInterval)) {
342 SearchNameServer(&getAnswers, answersLens, queries, queriesLens);
343 time1 = time2;
344 servFailRetry = ARG_INDEX_2 * getAnswers.queriesNum;
345 }
346
347 if (poll(&pfd, 1, time1 + retryInterval - time2) <= 0) {
348 continue;
349 }
350 DnsGetAnswers(getAnswers, queries, queriesLens, answers, answersLens, servFailRetry);
351 }
352 return DNS_ERR_NONE;
353 }
354
ResMSendRc(int32_t queriesNum,const uint8_t * const * queries,const int32_t * queriesLens,uint8_t * const * answers,int32_t * answersLens,int32_t answersSize,const struct ResolvConf * conf,uint16_t netId)355 int32_t DnsLookUpParse::ResMSendRc(int32_t queriesNum, const uint8_t *const *queries, const int32_t *queriesLens,
356 uint8_t *const *answers, int32_t *answersLens, int32_t answersSize,
357 const struct ResolvConf *conf, uint16_t netId)
358 {
359 (void)memset_s(static_cast<void *>(&sockAddr), sizeof(sockAddr), 0x00, sizeof(sockAddr));
360 for (auto &i : nSockAddr) {
361 (void)memset_s(static_cast<void *>(&i), sizeof(sockAddr), 0x00, sizeof(sockAddr));
362 }
363
364 int32_t timeOut = TIMEMSTOS * conf->timeOut;
365 int32_t attempts = conf->attempts;
366 socklen_t saLen = sizeof(sockAddr.sin);
367 uint32_t nns = 0;
368 int32_t family = AF_INET;
369 GetNsFromConf(conf, nns, family, saLen);
370 sockAddr.sin.sin_family = family;
371 int32_t fd = socket(family, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
372 if (fd < 0 && family == AF_INET6 && errno == EAFNOSUPPORT) {
373 NETNATIVE_LOGE("socker creat or bind error: [%{public}d], %{public}s", errno, strerror(errno));
374 fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
375 family = AF_INET;
376 }
377
378 if (FwmarkClient().BindSocket(fd, netId) < 0) {
379 NETNATIVE_LOGE("BindSocket error: [%{public}d]", errno);
380 return -1;
381 }
382 if (fd < 0 || bind(fd, reinterpret_cast<sockaddr *>(&sockAddr), saLen) < 0) {
383 NETNATIVE_LOGE("socker creat or bind error: [%{public}d], %{public}s", errno, strerror(errno));
384 if (fd >= 0) {
385 close(fd);
386 }
387 return -1;
388 }
389
390 if (family == AF_INET6) {
391 SetSocAddr(fd, nns);
392 }
393
394 int32_t answersAllLens = sizeof(*answersLens) * queriesNum;
395 (void)memset_s(answersLens, answersAllLens, 0, answersAllLens);
396
397 GetAnswers getAnswers = {
398 .queriesNum = queriesNum,
399 .answersSize = answersSize,
400 .nns = nns,
401 .fd = fd,
402 .attempts = attempts,
403 .timeOut = timeOut,
404 .saLen = saLen,
405 };
406 DnsSendQueries(getAnswers, queries, queriesLens, answers, answersLens);
407 (void)close(fd);
408
409 return DNS_ERR_NONE;
410 }
411
IsValidHostname(const std::string host)412 int32_t DnsLookUpParse::IsValidHostname(const std::string host)
413 {
414 if (strnlen(host.c_str(), HOST_MAX_LEN) - LOOKUP_NAME_ONE >= HOST_MAX_LEN_MINUS_ONE ||
415 static_cast<int>(mbstowcs(0, host.c_str(), 0)) == -1) {
416 return DNS_ERR_NONE;
417 }
418 uint8_t *hostBit = reinterpret_cast<uint8_t *>(const_cast<char *>(host.c_str()));
419
420 for (; *hostBit >= HOST_BIT_SIZE || *hostBit == '.' || *hostBit == '-' || isalnum(*hostBit); hostBit++) {
421 };
422 return !*hostBit;
423 }
424
DnsParseCallback(void * c,int32_t rr,const void * data,int32_t len,const void * packet)425 int32_t DnsLookUpParse::DnsParseCallback(void *c, int32_t rr, const void *data, int32_t len, const void *packet)
426 {
427 auto *ctx = static_cast<DpcCtx *>(c);
428 if (ctx->cnt >= MAXADDRS) {
429 return -1;
430 }
431 char tmp[TMP_LINE] = {0};
432 switch (rr) {
433 case RR_A:
434 if (len != ADDR_A4_LEN) {
435 return -1;
436 }
437 ctx->addrs[ctx->cnt].family = AF_INET;
438 ctx->addrs[ctx->cnt].scopeid = CTX_DEFAULT_SCOPEID;
439 if (memcpy_s(ctx->addrs[ctx->cnt++].addr, ADDR_A4_LEN, data, ADDR_A4_LEN) != 0) {
440 NETNATIVE_LOGE("memcpy_s faild");
441 return NETMANAGER_ERR_MEMCPY_FAIL;
442 }
443 break;
444 case RR_AAAA:
445 if (len != ADDR_A6_LEN) {
446 return -1;
447 }
448 ctx->addrs[ctx->cnt].family = AF_INET6;
449 ctx->addrs[ctx->cnt].scopeid = CTX_DEFAULT_SCOPEID;
450 if (memcpy_s(ctx->addrs[ctx->cnt++].addr, ADDR_A6_LEN, data, ADDR_A6_LEN) != 0) {
451 NETNATIVE_LOGE("memcpy_s faild");
452 return NETMANAGER_ERR_MEMCPY_FAIL;
453 }
454 break;
455 case RR_CNAME:
456 if (DnsLookUpParse().DnsExpand(static_cast<uint8_t *>(const_cast<void *>(packet)),
457 static_cast<const uint8_t *>(packet) + PACKET_LINE,
458 static_cast<uint8_t *>(const_cast<void *>(data)), tmp, sizeof(tmp)) > 0 &&
459 IsValidHostname(tmp)) {
460 if (strcpy_s(ctx->canon, sizeof(tmp), tmp) != 0) {
461 return EAI_AGAIN;
462 }
463 }
464 break;
465 }
466 return DNS_ERR_NONE;
467 }
468
DnsParse(const uint8_t * answers,int32_t answersLen,int32_t (* callback)(void *,int,const void *,int,const void *),void * ctx)469 int32_t DnsLookUpParse::DnsParse(const uint8_t *answers, int32_t answersLen,
470 int32_t (*callback)(void *, int, const void *, int, const void *), void *ctx)
471 {
472 if (answersLen < RLEN_MAXNS) {
473 NETNATIVE_LOGE("answersLen is less than %{public}d", RLEN_MAXNS);
474 return -1;
475 }
476 if ((answers[ARG_INDEX_3] & ANSWERS_OPERATION)) {
477 return DNS_ERR_NONE;
478 }
479 const uint8_t *anSize = answers + RLEN_MAXNS;
480 int32_t qdCount = answers[ARG_INDEX_4] * COUNT_CONVERT + answers[ARG_INDEX_5];
481 int32_t anCount = answers[ARG_INDEX_6] * COUNT_CONVERT + answers[ARG_INDEX_7];
482 if (qdCount + anCount > COUNT_MAX_LEN) {
483 NETNATIVE_LOGE("get data count greater than %{public}d", COUNT_MAX_LEN);
484 return -1;
485 }
486 while (qdCount--) {
487 while ((anSize - answers < answersLen) && (*anSize - 1U < ANSWER_SIZE)) {
488 anSize++;
489 }
490 if (*anSize > ANSWER_LEN || (*anSize == ANSWER_LEN && anSize[ARG_INDEX_1] > ANSWER_MAX_LEN) ||
491 anSize > answers + answersLen - ANSWER_SIZE_DIFFER) {
492 NETNATIVE_LOGE("qdCount error");
493 return -1;
494 }
495 anSize += ANSWER_STR + !!*anSize;
496 }
497 while (anCount--) {
498 while (anSize - answers < answersLen && *anSize - 1U < ANSWER_SIZE) {
499 anSize++;
500 }
501 if (*anSize > ANSWER_LEN || (*anSize == ANSWER_LEN && anSize[ARG_INDEX_1] > ANSWER_MAX_LEN) ||
502 anSize > answers + answersLen - ANSWER_SIZE_DIFFER) {
503 return -1;
504 }
505 anSize += 1 + !!*anSize;
506 int32_t len = anSize[ARG_INDEX_8] * COUNT_CONVERT + anSize[ARG_INDEX_9];
507 if (anSize + len > answers + answersLen) {
508 NETNATIVE_LOGE("anSize has greater than answers len");
509 return -1;
510 }
511 if (callback(ctx, anSize[ARG_INDEX_1], anSize + ANSWER_LEN_DIFFER, len, answers) < 0) {
512 NETNATIVE_LOGE("DnsParseCallback failed");
513 return -1;
514 }
515 anSize += ANSWER_LEN_DIFFER + len;
516 }
517 return DNS_ERR_NONE;
518 }
519
DnsExpand(const uint8_t * base,const uint8_t * end,const uint8_t * src,char * dest,int32_t space)520 int32_t DnsLookUpParse::DnsExpand(const uint8_t *base, const uint8_t *end, const uint8_t *src, char *dest,
521 int32_t space)
522 {
523 const uint8_t *snapSrc = src;
524 if (snapSrc == end || space <= 0) {
525 NETNATIVE_LOGE("snapSrc is null");
526 return INVALID_LENGTH;
527 }
528 int32_t len = INVALID_LENGTH;
529 char *dBegin = dest;
530 char *dEnd = dest + (space > MAX_SPACE_SIZE ? MAX_SPACE_SIZE : space);
531 for (int32_t i = 0; i < end - base; i += STEP_SIZE) {
532 if (*snapSrc & MASK_HIGH_TWO_BITS) {
533 if (snapSrc + 1 == end) {
534 NETNATIVE_LOGE("snapSrc is invalid");
535 return INVALID_LENGTH;
536 }
537 int32_t j = ((snapSrc[ARG_INDEX_0] & MASK_LOW_SIX_BITS) << BIT_NUM_OF_BYTE) | snapSrc[1];
538 len = (len < 0) ? static_cast<int>(snapSrc + STEP_SIZE - src) : len;
539 if (j >= end - base) {
540 NETNATIVE_LOGE("space length error");
541 return INVALID_LENGTH;
542 }
543 snapSrc = base + j;
544 } else if (*snapSrc) {
545 if (dest != dBegin) {
546 *dest = DOT;
547 ++dest;
548 }
549 int32_t j = *snapSrc;
550 ++snapSrc;
551 if (j >= end - snapSrc || j >= dEnd - dest) {
552 NETNATIVE_LOGE("space length error");
553 return INVALID_LENGTH;
554 }
555 while (j) {
556 *dest = static_cast<char>(*snapSrc);
557 ++dest;
558 ++snapSrc;
559 --j;
560 }
561 } else {
562 *dest = 0;
563 len = (len < 0) ? static_cast<int>(snapSrc + 1 - src) : len;
564 return len;
565 }
566 }
567 return INVALID_LENGTH;
568 }
569
ResMkQuery(int32_t op,const std::string dName,int32_t mineClass,int32_t type,const uint8_t * data,int32_t dataLen,const uint8_t * newrr,uint8_t * buf,int32_t bufLen)570 int32_t DnsLookUpParse::ResMkQuery(int32_t op, const std::string dName, int32_t mineClass, int32_t type,
571 const uint8_t *data, int32_t dataLen, const uint8_t *newrr, uint8_t *buf,
572 int32_t bufLen)
573 {
574 size_t nameLen = dName.length() > HOST_MAX_LEN ? HOST_MAX_LEN : dName.length();
575 if (nameLen && dName[nameLen - 1] == DOT) {
576 nameLen--;
577 }
578 int32_t nameNum = HOSTNAME_LEN_DIFFER + static_cast<int32_t>(nameLen) + !!nameLen;
579 if (nameLen > HOST_MAX_LEN_MINUS_TWO || bufLen < nameNum || op > OP_MAX || mineClass > MINE_CLASS_MAX ||
580 type > TYPE_MAX) {
581 NETNATIVE_LOGE("make query failed");
582 return -1;
583 }
584
585 uint8_t snapName[BUFF_MAX_LEN];
586 if (memset_s(snapName, BUFF_MAX_LEN, 0, BUFF_MAX_LEN) != 0) {
587 return EAI_AGAIN;
588 }
589 snapName[ARG_INDEX_2] = op * HOSTNAME_BUFF_COMPUTE + 1;
590 snapName[ARG_INDEX_5] = 1;
591 if (memcpy_s(reinterpret_cast<char *>(snapName) + HOSTNAME_SIZE_DIFFER, nameLen, dName.c_str(), nameLen) != 0) {
592 NETNATIVE_LOGE("memcpy_s faild");
593 return NETMANAGER_ERR_MEMCPY_FAIL;
594 }
595 uint32_t i = 0;
596 uint32_t j = 0;
597 for (i = HOSTNAME_SIZE_DIFFER; snapName[i]; i = j + 1) {
598 for (j = i; snapName[j] && snapName[j] != DOT; j++) {
599 };
600 if (j - i - HOST_NAME_LEN > HOST_NAME_LEN_MAX) {
601 NETNATIVE_LOGE("make query is to long");
602 return -1;
603 }
604 snapName[i - ARG_INDEX_1] = j - i;
605 }
606 snapName[i + ARG_INDEX_1] = type;
607 snapName[i + ARG_INDEX_3] = mineClass;
608
609 timespec ts;
610 clock_gettime(CLOCK_REALTIME, &ts);
611 int32_t id = ts.tv_nsec + (static_cast<uint64_t>(ts.tv_nsec / MAX_BIT) & MAX_FOR_KEY);
612 snapName[ARG_INDEX_0] = id / NAME_MAX_BIT;
613 snapName[ARG_INDEX_1] = id;
614
615 if (memcpy_s(buf, nameNum, snapName, nameNum) != 0) {
616 NETNATIVE_LOGE("memcpy_s faild");
617 return NETMANAGER_ERR_MEMCPY_FAIL;
618 }
619 return nameNum;
620 }
621 } // namespace nmd
622 } // namespace OHOS
623