1 /*
2 * Copyright (c) 2021-2025 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 <cerrno>
17 #include <netdb.h>
18
19 #include "net_address.h"
20 #include "netstack_log.h"
21 #include "socket_exec_common.h"
22 #include "securec.h"
23
24 namespace OHOS::NetStack::Socket {
25
NetAddress()26 NetAddress::NetAddress() : family_(Family::IPv4), port_(0) {}
27
NetAddress(const NetAddress & other)28 NetAddress::NetAddress(const NetAddress &other) : address_(other.address_), family_(other.family_), port_(other.port_)
29 {
30 }
31
SetIpAddress(const std::string & address)32 void NetAddress::SetIpAddress(const std::string &address)
33 {
34 if (address.empty()) {
35 return;
36 }
37 if (address == "localhost") {
38 if (family_ == Family::IPv4) {
39 address_ = ConvertAddressToIp(address, AF_INET);
40 } else if (family_ == Family::IPv6) {
41 address_ = ConvertAddressToIp(address, AF_INET6);
42 }
43 return;
44 }
45 if (family_ == Family::IPv4) {
46 in6_addr ipv6{};
47 if (inet_pton(AF_INET6, address.c_str(), &ipv6) > 0) {
48 return;
49 }
50 auto pos = address.find('%');
51 if (pos != std::string::npos) {
52 auto subAddr = address.substr(0, pos);
53 in6_addr newIpv6{};
54 if (inet_pton(AF_INET6, subAddr.c_str(), &newIpv6) > 0) {
55 return;
56 }
57 }
58 in_addr ipv4{};
59 if (inet_pton(AF_INET, address.c_str(), &(ipv4.s_addr)) > 0) {
60 address_ = address;
61 return;
62 }
63 } else {
64 in6_addr ipv6{};
65 if (inet_pton(AF_INET6, address.c_str(), &ipv6) > 0) {
66 address_ = address;
67 return;
68 }
69 }
70 SetIpAddressInner(address);
71 }
72
SetIpAddressInner(const std::string & address)73 void NetAddress::SetIpAddressInner(const std::string &address)
74 {
75 if (family_ == Family::IPv4) {
76 constexpr int LONG_BASE = 10;
77 char *error = nullptr;
78 auto inet = std::strtol(address.c_str(), &error, LONG_BASE);
79 if (error && *error == '\0' && inet >= 0 && inet <= UINT32_MAX) {
80 in_addr addr{};
81 addr.s_addr = static_cast<in_addr_t>(inet);
82 address_ = inet_ntoa(addr);
83 }
84 } else if (family_ == Family::IPv6) {
85 auto pos = address.find('%');
86 if (pos == std::string::npos) {
87 return;
88 }
89 auto subAddr = address.substr(0, pos);
90 in6_addr ipv6{};
91 if (inet_pton(AF_INET6, subAddr.c_str(), &ipv6) > 0) {
92 address_ = subAddr;
93 return;
94 }
95 }
96 }
97
SetRawAddress(const std::string & address)98 void NetAddress::SetRawAddress(const std::string &address)
99 {
100 address_ = address;
101 }
102
SetAddress(const std::string & address)103 void NetAddress::SetAddress(const std::string &address)
104 {
105 if (family_ == Family::IPv4) {
106 struct in_addr ipv4;
107 if (inet_pton(AF_INET, address.c_str(), &(ipv4.s_addr)) > 0) {
108 address_ = address;
109 return;
110 }
111 } else {
112 struct in6_addr ipv6;
113 if (inet_pton(AF_INET6, address.c_str(), &ipv6) > 0) {
114 address_ = address;
115 return;
116 }
117 }
118
119 struct addrinfo hints;
120 sa_family_t saFamily = GetSaFamily();
121 if (memset_s(&hints, sizeof hints, 0, sizeof hints) != EOK) {
122 NETSTACK_LOGE("memory operation fail");
123 }
124 hints.ai_family = saFamily;
125 char ipStr[INET6_ADDRSTRLEN];
126 struct addrinfo *res = nullptr;
127 int status = getaddrinfo(address.c_str(), nullptr, &hints, &res);
128 if (status != 0 || res == nullptr) {
129 NETSTACK_LOGE("getaddrinfo status is %{public}d, error is %{public}s", status, gai_strerror(status));
130 return;
131 }
132
133 void *addr = nullptr;
134 if (res->ai_family == AF_INET) {
135 auto *ipv4 = reinterpret_cast<struct sockaddr_in *>(res->ai_addr);
136 addr = &(ipv4->sin_addr);
137 } else {
138 struct sockaddr_in6 *ipv6 = reinterpret_cast<struct sockaddr_in6 *>(res->ai_addr);
139 addr = &(ipv6->sin6_addr);
140 }
141 inet_ntop(res->ai_family, addr, ipStr, sizeof ipStr);
142 address_ = ipStr;
143 freeaddrinfo(res);
144 }
145
SetAddress(const std::string & address,bool resolveDns)146 void NetAddress::SetAddress(const std::string &address, bool resolveDns)
147 {
148 if (!resolveDns && family_ == Family::DOMAIN_NAME) {
149 address_ = address;
150 } else {
151 SetAddress(address);
152 }
153 }
154
SetFamilyByJsValue(uint32_t family)155 void NetAddress::SetFamilyByJsValue(uint32_t family)
156 {
157 if (static_cast<Family>(family) == Family::IPv4) {
158 family_ = Family::IPv4;
159 } else if (static_cast<Family>(family) == Family::IPv6) {
160 family_ = Family::IPv6;
161 } else if (static_cast<Family>(family) == Family::DOMAIN_NAME) {
162 family_ = Family::DOMAIN_NAME;
163 } else {
164 // do nothing
165 }
166 }
167
SetFamilyBySaFamily(sa_family_t family)168 void NetAddress::SetFamilyBySaFamily(sa_family_t family)
169 {
170 if (family == AF_INET6) {
171 family_ = Family::IPv6;
172 }
173 }
174
SetPort(uint16_t port)175 void NetAddress::SetPort(uint16_t port)
176 {
177 port_ = port;
178 }
179
GetAddress() const180 const std::string &NetAddress::GetAddress() const
181 {
182 return address_;
183 }
184
GetSaFamily() const185 sa_family_t NetAddress::GetSaFamily() const
186 {
187 if (family_ == Family::IPv6) {
188 return AF_INET6;
189 }
190 return AF_INET;
191 }
192
GetJsValueFamily() const193 uint32_t NetAddress::GetJsValueFamily() const
194 {
195 return static_cast<uint32_t>(family_);
196 }
197
GetPort() const198 uint16_t NetAddress::GetPort() const
199 {
200 return port_;
201 }
202
GetFamily() const203 NetAddress::Family NetAddress::GetFamily() const
204 {
205 return family_;
206 }
207
operator =(const NetAddress & other)208 NetAddress &NetAddress::operator=(const NetAddress &other)
209 {
210 address_ = other.GetAddress();
211 family_ = other.GetFamily();
212 port_ = other.GetPort();
213 return *this;
214 }
215 } // namespace OHOS::NetStack::Socket
216