• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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