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