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_getaddrinfo.h"
17
18 #include <netdb.h>
19
20 #include "fwmark_client.h"
21 #include "netnative_log_wrapper.h"
22 #include "securec.h"
23
24 namespace OHOS {
25 namespace nmd {
26 static constexpr int32_t CANNO_LEN = 256;
CheckHints(const AddrInfo & hints)27 int32_t DnsGetAddrInfo::CheckHints(const AddrInfo &hints)
28 {
29 uint32_t flags = hints.aiFlags;
30 const uint32_t mask =
31 AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_V4MAPPED | AI_ALL | AI_ADDRCONFIG | AI_NUMERICSERV;
32 if ((flags & mask) != flags) {
33 NETNATIVE_LOGE("flags in hints is Invalid, flags: [%{public}d]", flags);
34 return EAI_BADFLAGS;
35 }
36 uint32_t family = hints.aiFamily;
37 switch (family) {
38 case AF_INET:
39 case AF_INET6:
40 case AF_UNSPEC:
41 break;
42 default:
43 NETNATIVE_LOGE("family not supported, family : [%{public}d]", family);
44 return EAI_FAMILY;
45 }
46 return DNS_ERR_NONE;
47 }
48
SwitchFamilyInet(AddrInfo & node,AddrData addrs,uint16_t port)49 void DnsGetAddrInfo::SwitchFamilyInet(AddrInfo &node, AddrData addrs, uint16_t port)
50 {
51 node.aiAddr.sin.sin_family = AF_INET;
52 node.aiAddr.sin.sin_port = htons(port);
53 if (memcpy_s(&node.aiAddr.sin.sin_addr, ADDR_A4_LEN, &addrs.addr, ADDR_A4_LEN) != 0) {
54 return;
55 }
56 }
57
SwitchFamilyInet6(AddrInfo & node,AddrData addrs,uint16_t port)58 void DnsGetAddrInfo::SwitchFamilyInet6(AddrInfo &node, AddrData addrs, uint16_t port)
59 {
60 node.aiAddr.sin6.sin6_family = AF_INET6;
61 node.aiAddr.sin6.sin6_port = htons(port);
62 node.aiAddr.sin6.sin6_scope_id = addrs.scopeid;
63 if (memcpy_s(&node.aiAddr.sin6.sin6_addr, ADDR_A6_LEN, &addrs.addr, ADDR_A6_LEN) != 0) {
64 return;
65 }
66 }
67
ParseAddr(int32_t nAddrs,int32_t nServs,ServData (& ports)[MAXSERVS],AddrData (& addrs)[MAXADDRS],char * outCanon,int32_t canonLen,std::vector<AddrInfo> & out)68 void DnsGetAddrInfo::ParseAddr(int32_t nAddrs, int32_t nServs, ServData (&ports)[MAXSERVS], AddrData (&addrs)[MAXADDRS],
69 char *outCanon, int32_t canonLen, std::vector<AddrInfo> &out)
70 {
71 int16_t k = 0;
72 for (int32_t i = 0; i < nAddrs; i++) {
73 for (int32_t j = 0; j < nServs; j++, k++) {
74 AddrInfo info = {};
75 info.aiFamily = static_cast<uint32_t>(addrs[i].family);
76 info.aiSockType = ports[j].sockType;
77 info.aiProtocol = ports[j].proto;
78 info.aiAddrLen = addrs[i].family == AF_INET ? static_cast<socklen_t>(sizeof(sockaddr_in))
79 : static_cast<socklen_t>(sizeof(sockaddr_in6));
80 if (memcpy_s(info.aiCanonName, sizeof(info.aiCanonName), outCanon, canonLen) != 0) {
81 return;
82 }
83 switch (addrs[i].family) {
84 case AF_INET:
85 SwitchFamilyInet(info, addrs[i], ports[j].port);
86 break;
87 case AF_INET6:
88 SwitchFamilyInet6(info, addrs[i], ports[j].port);
89 break;
90 default:
91 break;
92 }
93 out.emplace_back(info);
94 }
95 }
96 }
97
GetAddrInfo(const std::string & hostName,const std::string & serverName,const AddrInfo & hints,uint16_t netId,std::vector<AddrInfo> & res)98 int32_t DnsGetAddrInfo::GetAddrInfo(const std::string &hostName, const std::string &serverName, const AddrInfo &hints,
99 uint16_t netId, std::vector<AddrInfo> &res)
100 {
101 (void)this;
102 if (hostName.empty() && serverName.empty()) {
103 return EAI_NONAME;
104 }
105 uint32_t family = AF_UNSPEC;
106 uint32_t flags = 0;
107 uint32_t proto = 0;
108 uint32_t sockType = 0;
109 if (hints.aiFamily > 0) {
110 int32_t error = CheckHints(hints);
111 if (error < DNS_ERR_NONE) {
112 return error;
113 }
114 family = hints.aiFamily;
115 flags = hints.aiFlags;
116 proto = hints.aiProtocol;
117 sockType = hints.aiSockType;
118 } else {
119 family = AF_INET;
120 }
121
122 ServData servBuf[MAXSERVS] = {{0}};
123 int32_t nServ = DnsLookUpName().LookUpServer(servBuf, serverName, static_cast<int32_t>(proto),
124 static_cast<int32_t>(sockType), static_cast<int32_t>(flags));
125 if (nServ < 0) {
126 NETNATIVE_LOGE("failed to LookupServ %{public}d", nServ);
127 return nServ;
128 }
129 AddrData addrs[MAXADDRS] = {{0}};
130 char canon[CANNO_LEN] = {0};
131 int32_t nAddrs = DnsLookUpName().LookUpName(addrs, canon, hostName, static_cast<int32_t>(family),
132 static_cast<int32_t>(flags), netId);
133 if (nAddrs < 0) {
134 NETNATIVE_LOGE("failed to LookupName %{public}d", nAddrs);
135 return nAddrs;
136 }
137
138 char *outCanon = canon;
139 auto canonLen = strlen(canon);
140 ParseAddr(nAddrs, nServ, servBuf, addrs, outCanon, static_cast<int32_t>(canonLen), res);
141 return DNS_ERR_NONE;
142 }
143 } // namespace nmd
144 } // namespace OHOS
145