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