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