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