1 /*
2 * Copyright (c) 2021-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 <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
SetFamilyByJsValue(uint32_t family)146 void NetAddress::SetFamilyByJsValue(uint32_t family)
147 {
148 if (static_cast<Family>(family) == Family::IPv6) {
149 family_ = Family::IPv6;
150 }
151 }
152
SetFamilyBySaFamily(sa_family_t family)153 void NetAddress::SetFamilyBySaFamily(sa_family_t family)
154 {
155 if (family == AF_INET6) {
156 family_ = Family::IPv6;
157 }
158 }
159
SetPort(uint16_t port)160 void NetAddress::SetPort(uint16_t port)
161 {
162 port_ = port;
163 }
164
GetAddress() const165 const std::string &NetAddress::GetAddress() const
166 {
167 return address_;
168 }
169
GetSaFamily() const170 sa_family_t NetAddress::GetSaFamily() const
171 {
172 if (family_ == Family::IPv6) {
173 return AF_INET6;
174 }
175 return AF_INET;
176 }
177
GetJsValueFamily() const178 uint32_t NetAddress::GetJsValueFamily() const
179 {
180 return static_cast<uint32_t>(family_);
181 }
182
GetPort() const183 uint16_t NetAddress::GetPort() const
184 {
185 return port_;
186 }
187
GetFamily() const188 NetAddress::Family NetAddress::GetFamily() const
189 {
190 return family_;
191 }
192
operator =(const NetAddress & other)193 NetAddress &NetAddress::operator=(const NetAddress &other)
194 {
195 address_ = other.GetAddress();
196 family_ = other.GetFamily();
197 port_ = other.GetPort();
198 return *this;
199 }
200 } // namespace OHOS::NetStack::Socket
201