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_name.h"
17
18 #include "fwmark_client.h"
19 #include "net_manager_constants.h"
20
21 namespace OHOS {
22 namespace nmd {
23 using namespace NetManagerStandard;
24 static constexpr int32_t HOST_NAME_LEN = 10;
25 static constexpr int32_t TEMPORARY_FAILURE = 2;
26 static constexpr int32_t NO_ERROR = 3;
27
28 static constexpr uint32_t ADDR_SECOND_LAST_BIT = 15;
29 static constexpr int32_t PREFIX_SIZE = 128;
30 static constexpr int32_t PREFIX_LEN = 8;
31 static constexpr int32_t BUFF_NUM = 2;
32
33 static constexpr int32_t ALENS_MAX_LEN = 4;
34 static constexpr int32_t SEARCH_MAX_LEN = 256;
35
36 static constexpr int32_t DAS_USABLE = 0x40000000;
37 static constexpr int32_t DAS_MATCHINGSCOPE = 0x20000000;
38 static constexpr int32_t DAS_MATCHINGLABEL = 0x10000000;
39 static constexpr int32_t DAS_PREC_SHIFT = 20;
40 static constexpr int32_t DAS_SCOPE_SHIFT = 16;
41 static constexpr int32_t DAS_PREFIX_SHIFT = 8;
42 static constexpr int32_t DAS_ORDER_SHIFT = 0;
43 static constexpr int32_t NAMESERVICES_LEN = 12;
44 static constexpr int32_t ADDR_LEN = 4;
45 static constexpr int32_t CNT_NUM = 2;
46
47 static constexpr int32_t SCOPEOF_RESULT_2 = 2;
48 static constexpr int32_t SCOPEOF_RESULT_5 = 5;
49 static constexpr int32_t SCOPEOF_RESULT_14 = 14;
50 static constexpr int32_t DSCOPE_MAX_LEN = 15;
51
52 static const struct policy {
53 uint8_t addr[ADDR_A6_LEN];
54 uint8_t len;
55 uint8_t mask;
56 uint8_t prec;
57 uint8_t label;
58 } DEF_POLICY[] = {
59 {{'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\1'}, 15, 0xff, 50, 0},
60 {"\0\0\0\0\0\0\0\0\0\0\xff\xff", 11, 0xff, 35, 4},
61 {"\x20\2", 1, 0xff, 30, 2},
62 {"\x20\1", 3, 0xff, 5, 5},
63 {"\xfc", 0, 0xfe, 3, 13},
64 {"", 0, 0, 40, 1},
65 };
66
NameFromNull(AddrData buf[SECOND_ADDR_IN_BUFF],const std::string name,int32_t family,int32_t flags)67 int32_t DnsLookUpName::NameFromNull(AddrData buf[SECOND_ADDR_IN_BUFF], const std::string name, int32_t family,
68 int32_t flags)
69 {
70 if (!name.empty()) {
71 return DNS_ERR_NONE;
72 }
73 int32_t cnt = 0;
74 if (static_cast<uint32_t>(flags) & AI_PASSIVE) {
75 if (family != AF_INET6) {
76 buf[cnt++] = (AddrData){.family = AF_INET};
77 }
78 if (family != AF_INET) {
79 buf[cnt++] = (AddrData){.family = AF_INET6};
80 }
81 } else {
82 if (family != AF_INET6) {
83 buf[cnt++] = (AddrData){.family = AF_INET, .addr = {127, 0, 0, 1}};
84 }
85 if (family != AF_INET) {
86 buf[cnt] = (AddrData){.family = AF_INET6};
87 buf[cnt].addr[ADDR_SECOND_LAST_BIT] = ADDR_FIRST_BIT;
88 ++cnt;
89 }
90 }
91 NETNATIVE_LOG_D("NameFromNull cnt %{public}d", cnt);
92 return cnt;
93 }
94
NameFromNumeric(AddrData buf[ADDR_FIRST_BIT],const std::string name,int32_t family)95 int32_t DnsLookUpName::NameFromNumeric(AddrData buf[ADDR_FIRST_BIT], const std::string name, int32_t family)
96 {
97 return DnsLookUpParse().LookupIpLiteral(buf, name, family);
98 }
99
ProcessMdnsFailed(int32_t answersLens[],uint8_t answersBuf[][PACKET_LINE])100 int32_t DnsLookUpName::ProcessMdnsFailed(int32_t answersLens[], uint8_t answersBuf[][PACKET_LINE])
101 {
102 if (answersLens[ARG_INDEX_0] < ALENS_MAX_LEN ||
103 (answersBuf[ARG_INDEX_0][ARG_INDEX_3] & ADDR_SECOND_LAST_BIT) == TEMPORARY_FAILURE) {
104 NETNATIVE_LOGE("NameFromDns failed try again");
105 return EAI_AGAIN;
106 }
107 if ((answersBuf[ARG_INDEX_0][ARG_INDEX_3] & ADDR_SECOND_LAST_BIT) == SERVER_FAILURE) {
108 NETNATIVE_LOGE("NameFromDns failed return server failure");
109 return EAI_NONAME;
110 }
111 if ((answersBuf[ARG_INDEX_0][ARG_INDEX_3] & ADDR_SECOND_LAST_BIT) == NO_ERROR) {
112 return DNS_ERR_NONE;
113 }
114 NETNATIVE_LOGE("NameFromDns failed non-recoverable failure in name res.");
115 return EAI_FAIL;
116 }
117
NameFromDns(AddrData buf[MAXADDRS],char canon[CANON_LINE],const std::string name,int32_t family,const ResolvConf * conf,uint16_t netId)118 int32_t DnsLookUpName::NameFromDns(AddrData buf[MAXADDRS], char canon[CANON_LINE], const std::string name,
119 int32_t family, const ResolvConf *conf, uint16_t netId)
120 {
121 static const struct {
122 int32_t af;
123 int32_t rr;
124 } afrr[BUFF_NUM] = {
125 {.af = AF_INET6, .rr = RR_A},
126 {.af = AF_INET, .rr = RR_AAAA},
127 };
128 uint8_t queriesBuf[ARG_INDEX_2][BUFF_MAX_LEN], answersBuf[ARG_INDEX_2][PACKET_LINE];
129 int32_t queriesLens[ARG_INDEX_2], answersLens[ARG_INDEX_2];
130 int32_t queriesNum = 0;
131 for (int32_t i = 0; i < BUFF_NUM; i++) {
132 if (family != afrr[i].af) {
133 queriesLens[queriesNum] = DnsLookUpParse().ResMkQuery(0, name, 1, afrr[i].rr, nullptr, 0, nullptr,
134 queriesBuf[queriesNum], sizeof(*queriesBuf));
135 if (queriesLens[queriesNum] == -1) {
136 NETNATIVE_LOGE("NameFromDns failed to make query");
137 return EAI_NONAME;
138 }
139 queriesNum++;
140 }
141 }
142 const uint8_t *queries[ARG_INDEX_2] = {queriesBuf[ARG_INDEX_0], queriesBuf[ARG_INDEX_1]};
143 uint8_t *answers[ARG_INDEX_2] = {answersBuf[ARG_INDEX_0], answersBuf[ARG_INDEX_1]};
144 if (DnsLookUpParse().ResMSendRc(queriesNum, queries, queriesLens, answers, answersLens, sizeof(*answersBuf), conf,
145 netId) < 0) {
146 NETNATIVE_LOGE("NameFromDns failed return to send or recv data");
147 return EAI_SYSTEM;
148 }
149
150 DpcCtx ctx = {.addrs = buf, .canon = canon};
151 for (int32_t i = 0; i < queriesNum; i++) {
152 DnsLookUpParse().DnsParse(answersBuf[i], answersLens[i], DnsLookUpParse().DnsParseCallback, &ctx);
153 }
154
155 if (ctx.cnt) {
156 return ctx.cnt;
157 }
158 return ProcessMdnsFailed(answersLens, answersBuf);
159 }
160
NameFromDnsSearch(AddrData buf[MAXADDRS],char canon[CANON_LINE],const std::string name,int32_t family,uint16_t netId)161 int32_t DnsLookUpName::NameFromDnsSearch(AddrData buf[MAXADDRS], char canon[CANON_LINE], const std::string name,
162 int32_t family, uint16_t netId)
163 {
164 char search[SEARCH_MAX_LEN] = {0};
165 ResolvConf conf{};
166 if (DnsLookUpParse().GetResolvConf(&conf, search, sizeof(search), netId) < 0 || name.empty()) {
167 NETNATIVE_LOGE("Get resolv from conf failed or the param name is empty.");
168 return EAI_NONAME;
169 }
170
171 size_t nameLen;
172 auto ret = NameFromDnsSearch(nameLen, name, conf, search, canon);
173 if (ret != 0) {
174 return ret;
175 }
176 char *pos, *temp;
177 for (pos = search; *pos; pos = temp) {
178 for (; isspace(*pos); pos++) {
179 };
180 for (temp = pos; *temp && !isspace(*temp); temp++) {
181 };
182 if (temp == pos) {
183 break;
184 }
185 if (temp - pos < static_cast<long>(SEARCH_MAX_LEN - LOOKUP_NAME_ONE) - static_cast<long>(nameLen)) {
186 uint32_t cannonAddLen = nameLen + LOOKUP_NAME_ONE;
187 uint32_t posLen = temp - pos;
188 if (memcpy_s(canon + cannonAddLen, posLen, pos, posLen) != 0) {
189 NETNATIVE_LOGE("memcpy_s faild");
190 return NETMANAGER_ERR_MEMCPY_FAIL;
191 }
192 canon[temp - pos + LOOKUP_NAME_ONE + nameLen] = LOOKUP_NAME_ZERO;
193 int32_t cnt = NameFromDns(buf, canon, canon, family, &conf, netId);
194 if (cnt) {
195 return cnt;
196 }
197 }
198 }
199
200 canon[nameLen] = LOOKUP_NAME_ZERO;
201 return NameFromDns(buf, canon, name, family, &conf, netId);
202 }
203
NameFromDnsSearch(size_t & nameLen,const std::string name,ResolvConf conf,char search[],char canon[])204 int32_t DnsLookUpName::NameFromDnsSearch(size_t &nameLen, const std::string name, ResolvConf conf, char search[],
205 char canon[])
206 {
207 size_t dots;
208 for (dots = nameLen = 0; name[nameLen]; nameLen++) {
209 if (name[nameLen] == DOT) {
210 dots++;
211 }
212 }
213 if (dots >= conf.nDots || name[nameLen - LOOKUP_NAME_ONE] == DOT) {
214 *search = LOOKUP_NAME_ZERO;
215 }
216
217 if (name[nameLen - LOOKUP_NAME_ONE] == DOT) {
218 nameLen--;
219 }
220 if (!nameLen || name[nameLen - LOOKUP_NAME_ONE] == DOT || nameLen >= SEARCH_MAX_LEN) {
221 NETNATIVE_LOGE("name is unknown");
222 return EAI_NONAME;
223 }
224 if (strcpy_s(canon, name.length() + 1, name.c_str()) != 0) {
225 return EAI_AGAIN;
226 }
227 canon[nameLen] = DOT;
228 return 0;
229 }
PolicyOf(const in6_addr * in6Addr)230 const struct policy *DnsLookUpName::PolicyOf(const in6_addr *in6Addr)
231 {
232 for (int32_t i = 0;; i++) {
233 if (memcmp(in6Addr->s6_addr, DEF_POLICY[i].addr, DEF_POLICY[i].len)) {
234 continue;
235 }
236 if ((in6Addr->s6_addr[DEF_POLICY[i].len] & DEF_POLICY[i].mask) != DEF_POLICY[i].addr[DEF_POLICY[i].len]) {
237 continue;
238 }
239 return DEF_POLICY + i;
240 }
241 return {};
242 }
243
LabelOf(const in6_addr * in6Addr)244 int32_t DnsLookUpName::LabelOf(const in6_addr *in6Addr)
245 {
246 return PolicyOf(in6Addr)->label;
247 }
248
ScopeOf(const in6_addr * in6Addr)249 int32_t DnsLookUpName::ScopeOf(const in6_addr *in6Addr)
250 {
251 if (IN6_IS_ADDR_MULTICAST(in6Addr)) {
252 return in6Addr->s6_addr[ARG_INDEX_1] & DSCOPE_MAX_LEN;
253 }
254 if (IN6_IS_ADDR_LINKLOCAL(in6Addr)) {
255 return SCOPEOF_RESULT_2;
256 }
257 if (IN6_IS_ADDR_LOOPBACK(in6Addr)) {
258 return SCOPEOF_RESULT_2;
259 }
260 if (IN6_IS_ADDR_SITELOCAL(in6Addr)) {
261 return SCOPEOF_RESULT_5;
262 }
263 return SCOPEOF_RESULT_14;
264 }
265
PreFixMatch(const in6_addr * s,const in6_addr * d)266 int32_t DnsLookUpName::PreFixMatch(const in6_addr *s, const in6_addr *d)
267 {
268 int32_t i;
269 for (i = 0; i < PREFIX_SIZE &&
270 !((s->s6_addr[i / PREFIX_LEN] ^ d->s6_addr[i / PREFIX_LEN]) & (PREFIX_SIZE >> (i % PREFIX_LEN)));
271 i++) {
272 };
273 return i;
274 }
275
AddrCmp(const void * addrA,const void * addrB)276 int32_t DnsLookUpName::AddrCmp(const void *addrA, const void *addrB)
277 {
278 const auto *a = static_cast<const AddrData *>(addrA);
279 const auto *b = static_cast<const AddrData *>(addrB);
280 return b->sortKey - a->sortKey;
281 }
282
CheckNameParam(const std::string name,int32_t & flags,int32_t & family)283 int32_t DnsLookUpName::CheckNameParam(const std::string name, int32_t &flags, int32_t &family)
284 {
285 if (!name.empty()) {
286 size_t len = name.length() > HOST_MAX_LEN ? HOST_MAX_LEN : name.length();
287 if (len - 1 >= HOST_MAX_LEN_MINUS_ONE) {
288 NETNATIVE_LOGE("name is too long : %{public}d", static_cast<int32_t>(len));
289 return EAI_NONAME;
290 }
291 }
292
293 if (static_cast<uint32_t>(flags) & AI_V4MAPPED) {
294 if (family == AF_INET6) {
295 family = AF_UNSPEC;
296 } else {
297 flags -= AI_V4MAPPED;
298 }
299 }
300 return DNS_ERR_NONE;
301 }
302
RefreshBuf(AddrData * buf,int32_t num,int32_t & cnt)303 void DnsLookUpName::RefreshBuf(AddrData *buf, int32_t num, int32_t &cnt)
304 {
305 int32_t j = 0;
306 for (j = 0; num < cnt; num++) {
307 if (buf[num].family == AF_INET6) {
308 buf[j++] = buf[num];
309 }
310 }
311 cnt = j;
312 }
313
UpdateBuf(int32_t flags,int32_t family,AddrData * buf,int32_t & cnt)314 bool DnsLookUpName::UpdateBuf(int32_t flags, int32_t family, AddrData *buf, int32_t &cnt)
315 {
316 if ((static_cast<uint32_t>(flags) & AI_V4MAPPED)) {
317 int32_t i = 0;
318 if (!(static_cast<uint32_t>(flags) & AI_ALL)) {
319 for (; i < cnt && buf[i].family != AF_INET6; i++) {
320 };
321 if (i < cnt) {
322 RefreshBuf(buf, i, cnt);
323 }
324 }
325 for (i = 0; i < cnt; i++) {
326 if (buf[i].family != AF_INET) {
327 continue;
328 }
329 int32_t ret = memcpy_s(buf[i].addr + NAMESERVICES_LEN, ADDR_LEN, buf[i].addr, ADDR_LEN);
330 ret += memcpy_s(buf[i].addr, NAMESERVICES_LEN, ADDR_BUF, NAMESERVICES_LEN);
331 if (ret != 0) {
332 NETNATIVE_LOGE("memcpy_s faild");
333 return false;
334 }
335 buf[i].family = AF_INET6;
336 }
337 }
338 if (cnt < CNT_NUM || family == AF_INET) {
339 NETNATIVE_LOGE("cnt is less two or there are only IPv4 results, cnt : %{public}d", cnt);
340 return false;
341 }
342 int32_t i = 0;
343 for (i = 0; i < cnt; i++) {
344 if (buf[i].family != AF_INET) {
345 break;
346 }
347 }
348 return i != cnt;
349 }
350
SockAddrCopy(ScokAddrCopy addrBuff,void * da,void * sa,int32_t & dScope,int32_t & preFixLen,uint32_t & key)351 void DnsLookUpName::SockAddrCopy(ScokAddrCopy addrBuff, void *da, void *sa, int32_t &dScope, int32_t &preFixLen,
352 uint32_t &key)
353 {
354 if (!connect(addrBuff.lookUpNameFd, static_cast<sockaddr *>(da), addrBuff.daLen)) {
355 key = key | DAS_USABLE;
356 int32_t res = getsockname(addrBuff.lookUpNameFd, static_cast<sockaddr *>(sa), &addrBuff.saLen);
357 if (res) {
358 (void)close(addrBuff.lookUpNameFd);
359 return;
360 }
361 if (addrBuff.family == AF_INET) {
362 if (memcpy_s(addrBuff.sa6.sin6_addr.s6_addr + NAMESERVICES_LEN, ADDR_A4_LEN, &addrBuff.sa4.sin_addr,
363 ADDR_A4_LEN) != 0) {
364 NETNATIVE_LOGE("memcpy_s faild");
365 return;
366 }
367 }
368 if (dScope == ScopeOf(&addrBuff.sa6.sin6_addr)) {
369 key = key | DAS_MATCHINGSCOPE;
370 }
371 if (addrBuff.dLabel == LabelOf(&addrBuff.sa6.sin6_addr)) {
372 key = key | DAS_MATCHINGLABEL;
373 }
374 preFixLen = PreFixMatch(&addrBuff.sa6.sin6_addr, &addrBuff.da6.sin6_addr);
375 }
376 (void)close(addrBuff.lookUpNameFd);
377 }
378
FindName(AddrData * buf,char * canon,const std::string name,int32_t family,int32_t flags,uint16_t netId)379 int32_t DnsLookUpName::FindName(AddrData *buf, char *canon, const std::string name, int32_t family, int32_t flags,
380 uint16_t netId)
381 {
382 int32_t cnt = NameFromNull(buf, name, family, flags);
383 if (!cnt) {
384 cnt = NameFromNumeric(buf, name, family);
385 }
386 if (!cnt && !(static_cast<uint32_t>(flags) & AI_NUMERICHOST)) {
387 cnt = NameFromDnsSearch(buf, canon, name.c_str(), family, netId);
388 }
389 NETNATIVE_LOG_D("FindName cnt : %{public}d", cnt);
390 return cnt;
391 }
392
MemcpySockaddr(sockaddr_in6 & sa6,sockaddr_in6 & da6,sockaddr_in & da4,AddrData * buf,uint32_t cnt)393 int32_t DnsLookUpName::MemcpySockaddr(sockaddr_in6 &sa6, sockaddr_in6 &da6, sockaddr_in &da4, AddrData *buf,
394 uint32_t cnt)
395 {
396 int32_t ret = memcpy_s(sa6.sin6_addr.s6_addr, NAMESERVICES_LEN, ADDR_BUF, NAMESERVICES_LEN);
397 ret += memcpy_s(da6.sin6_addr.s6_addr + NAMESERVICES_LEN, ADDR_A4_LEN, buf[cnt].addr, ADDR_A4_LEN);
398 ret += memcpy_s(da6.sin6_addr.s6_addr, NAMESERVICES_LEN, ADDR_BUF, NAMESERVICES_LEN);
399 ret += memcpy_s(da6.sin6_addr.s6_addr + NAMESERVICES_LEN, ADDR_A4_LEN, buf[cnt].addr, ADDR_A4_LEN);
400 ret += memcpy_s(&da4.sin_addr, ADDR_A4_LEN, buf[cnt].addr, ADDR_A4_LEN);
401 if (ret != 0) {
402 NETNATIVE_LOGE("memcpy_s faild");
403 return -1;
404 }
405 return 0;
406 }
407
LookUpNameParam(AddrData * buf,int32_t cnt,int32_t netId)408 void DnsLookUpName::LookUpNameParam(AddrData *buf, int32_t cnt, int32_t netId)
409 {
410 for (int32_t i = 0; i < cnt; i++) {
411 int32_t family = buf[i].family;
412 uint32_t key = 0;
413 sockaddr_in6 sa6 = {0};
414 sockaddr_in6 da6 = {.sin6_family = AF_INET6, .sin6_port = PORT_NUM, .sin6_scope_id = buf[i].scopeid};
415 sockaddr_in sa4 = {0};
416 sockaddr_in da4 = {.sin_family = AF_INET, .sin_port = PORT_NUM};
417 void *sa, *da;
418 socklen_t saLen, daLen;
419 if (family == AF_INET6) {
420 if (memcpy_s(da6.sin6_addr.s6_addr, ADDR_A6_LEN, buf[i].addr, ADDR_A6_LEN) != 0) {
421 NETNATIVE_LOGE("memcpy_s faild");
422 return;
423 }
424 da = &da6;
425 daLen = sizeof(da6);
426 sa = &sa6;
427 saLen = sizeof(da6);
428 } else {
429 if (MemcpySockaddr(sa6, da6, da4, buf, i) < 0) {
430 return;
431 }
432 da = &da4;
433 daLen = sizeof(da4);
434 sa = &sa4;
435 saLen = sizeof(sa4);
436 }
437 const policy *dPolicy = PolicyOf(&da6.sin6_addr);
438 int32_t dScope = ScopeOf(&da6.sin6_addr);
439 int32_t dLabel = dPolicy->label;
440 uint32_t dPrec = dPolicy->prec;
441 int32_t preFixLen = 0;
442 int32_t lookUpNameFd = socket(family, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
443 if (lookUpNameFd >= 0) {
444 ScokAddrCopy addrBuff = {.lookUpNameFd = lookUpNameFd, .sa6 = sa6, .da6 = da6, .sa4 = sa4,
445 .saLen = saLen, .daLen = daLen, .dLabel = dLabel, .family = family};
446 SockAddrCopy(addrBuff, da, sa, dScope, preFixLen, key);
447 }
448 key |= dPrec << DAS_PREC_SHIFT;
449 key |= static_cast<uint32_t>(DSCOPE_MAX_LEN - dScope) << DAS_SCOPE_SHIFT;
450 key |= static_cast<uint32_t>(preFixLen) << DAS_PREFIX_SHIFT;
451 key |= static_cast<uint32_t>(MAXADDRS - i) << DAS_ORDER_SHIFT;
452 buf[i].sortKey = static_cast<int32_t>(key);
453 }
454 }
455
LookUpName(AddrData buf[MAXADDRS],char canon[CANON_LINE],const std::string & name,int32_t family,int32_t flags,uint16_t netId)456 int32_t DnsLookUpName::LookUpName(AddrData buf[MAXADDRS], char canon[CANON_LINE], const std::string &name,
457 int32_t family, int32_t flags, uint16_t netId)
458 {
459 *canon = 0;
460 int32_t error = CheckNameParam(name, flags, family);
461 if (error < 0) {
462 return error;
463 }
464 int32_t cnt = FindName(buf, canon, name, family, flags, netId);
465 if (cnt <= 0) {
466 NETNATIVE_LOGE("find name failed: %{public}d", cnt);
467 return cnt ? cnt : EAI_NONAME;
468 }
469
470 if (!UpdateBuf(flags, family, buf, cnt)) {
471 return cnt;
472 }
473
474 LookUpNameParam(buf, cnt, netId);
475 qsort(buf, cnt, sizeof(*buf), AddrCmp);
476
477 return cnt;
478 }
479
SwitchSocketType(int32_t sockType,const std::string name,int32_t & proto,ServData * buf)480 int32_t DnsLookUpName::SwitchSocketType(int32_t sockType, const std::string name, int32_t &proto, ServData *buf)
481 {
482 switch (sockType) {
483 case SOCK_STREAM:
484 switch (proto) {
485 case 0:
486 proto = IPPROTO_TCP;
487 [[fallthrough]];
488 case IPPROTO_TCP:
489 break;
490 default:
491 return EAI_SERVICE;
492 }
493 break;
494 case SOCK_DGRAM:
495 switch (proto) {
496 case 0:
497 proto = IPPROTO_UDP;
498 [[fallthrough]];
499 case IPPROTO_UDP:
500 break;
501 default:
502 return EAI_SERVICE;
503 }
504 [[fallthrough]];
505 case 0:
506 break;
507 default:
508 if (!name.empty()) {
509 return EAI_SERVICE;
510 }
511 buf[0].port = 0;
512 buf[0].proto = proto;
513 buf[0].sockType = sockType;
514 break;
515 }
516 return DNS_ERR_NONE;
517 }
518
LookUpServer(ServData buf[MAXSERVS],const std::string name,int32_t proto,int32_t sockType,int32_t flags)519 int32_t DnsLookUpName::LookUpServer(ServData buf[MAXSERVS], const std::string name, int32_t proto, int32_t sockType,
520 int32_t flags)
521 {
522 char* end = nullptr;
523 unsigned long port = 0;
524 int32_t error = SwitchSocketType(sockType, name, proto, buf);
525 if (error < 0) {
526 return error;
527 }
528 const char *serv = (name.length() > 0 ? name.c_str() : nullptr);
529 if (serv) {
530 if (!*serv) {
531 return EAI_SERVICE;
532 }
533 port = strtoul(serv, &end, HOST_NAME_LEN);
534 }
535 if (!end) {
536 if (port > PORT_NUM) {
537 return EAI_SERVICE;
538 }
539 int32_t cnt = 0;
540 if (proto != IPPROTO_UDP) {
541 buf[cnt].port = port;
542 buf[cnt].sockType = SOCK_STREAM;
543 buf[cnt++].proto = IPPROTO_TCP;
544 }
545 if (proto != IPPROTO_TCP) {
546 buf[cnt].port = port;
547 buf[cnt].sockType = SOCK_DGRAM;
548 buf[cnt++].proto = IPPROTO_UDP;
549 }
550 return cnt;
551 }
552
553 if (static_cast<uint32_t>(flags) & AI_NUMERICSERV) {
554 return EAI_NONAME;
555 }
556 return EAI_SERVICE;
557 }
558 } // namespace nmd
559 } // namespace OHOS
560