1/* 2 * Copyright (c) 2021-2024 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 "interface_manager.h" 17 18#include <arpa/inet.h> 19#include <cerrno> 20#include <cstdlib> 21#include <cstring> 22#include <dirent.h> 23#include <fcntl.h> 24#include <linux/if_ether.h> 25#include <net/if.h> 26#include <netinet/in.h> 27#include <sys/ioctl.h> 28#include <sys/socket.h> 29#include <sys/types.h> 30#include <system_error> 31#include <unistd.h> 32#include <regex> 33 34#include "netlink_manager.h" 35#include "netlink_msg.h" 36#include "netlink_socket.h" 37#include "netlink_socket_diag.h" 38#include "net_manager_constants.h" 39#include "netmanager_base_common_utils.h" 40#include "netnative_log_wrapper.h" 41#include "securec.h" 42 43namespace OHOS { 44namespace nmd { 45using namespace NetManagerStandard; 46using namespace NetManagerStandard::CommonUtils; 47 48namespace { 49constexpr const char *SYS_NET_PATH = "/sys/class/net/"; 50constexpr const char *MTU_PATH = "/mtu"; 51constexpr int32_t FILE_PERMISSION = 0666; 52constexpr uint32_t ARRAY_OFFSET_1_INDEX = 1; 53constexpr uint32_t ARRAY_OFFSET_2_INDEX = 2; 54constexpr uint32_t ARRAY_OFFSET_3_INDEX = 3; 55constexpr uint32_t ARRAY_OFFSET_4_INDEX = 4; 56constexpr uint32_t ARRAY_OFFSET_5_INDEX = 5; 57constexpr uint32_t MOVE_BIT_LEFT31 = 31; 58constexpr uint32_t BIT_MAX = 32; 59constexpr uint32_t IOCTL_RETRY_TIME = 32; 60constexpr int32_t MAX_MTU_LEN = 11; 61constexpr int32_t MAC_ADDRESS_STR_LEN = 18; 62constexpr int32_t MAC_ADDRESS_INT_LEN = 6; 63constexpr int32_t MAC_SSCANF_SPACE = 3; 64const std::regex REGEX_CMD_MAC_ADDRESS("^[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}$"); 65 66bool CheckFilePath(const std::string &fileName, std::string &realPath) 67{ 68 char tmpPath[PATH_MAX] = {0}; 69 if (!realpath(fileName.c_str(), tmpPath)) { 70 NETNATIVE_LOGE("file name is illegal"); 71 return false; 72 } 73 realPath = tmpPath; 74 return true; 75} 76} // namespace 77 78int InterfaceManager::GetMtu(const char *interfaceName) 79{ 80 if (interfaceName == nullptr) { 81 NETNATIVE_LOGE("interfaceName is null"); 82 return -1; 83 } 84 85 if (!CheckIfaceName(interfaceName)) { 86 NETNATIVE_LOGE("GetMtu isIfaceName fail %{public}d", errno); 87 return -1; 88 } 89 std::string mtuPath = std::string(SYS_NET_PATH).append(interfaceName).append(MTU_PATH); 90 std::string realPath; 91 if (!CheckFilePath(mtuPath, realPath)) { 92 NETNATIVE_LOGE("file does not exist! "); 93 return -1; 94 } 95 int fd = open(realPath.c_str(), 0, FILE_PERMISSION); 96 if (fd == -1) { 97 NETNATIVE_LOGE("GetMtu open fail %{public}d", errno); 98 return -1; 99 } 100 101 char originMtuValue[MAX_MTU_LEN] = {0}; 102 int nread = read(fd, originMtuValue, (sizeof(char) * (MAX_MTU_LEN - 1))); 103 if (nread == -1 || nread == 0) { 104 NETNATIVE_LOGE("GetMtu read fail %{public}d", errno); 105 close(fd); 106 return -1; 107 } 108 close(fd); 109 110 int32_t mtu = -1; 111 mtu = StrToInt(originMtuValue); 112 return mtu; 113} 114 115int InterfaceManager::SetMtu(const char *interfaceName, const char *mtuValue) 116{ 117 if (interfaceName == nullptr || mtuValue == nullptr) { 118 NETNATIVE_LOGE("interfaceName or mtuValue is null"); 119 return -1; 120 } 121 122 if (!CheckIfaceName(interfaceName)) { 123 NETNATIVE_LOGE("SetMtu isIfaceName fail %{public}d", errno); 124 } 125 int32_t sockfd = socket(AF_INET, SOCK_DGRAM, 0); 126 if (sockfd < 0) { 127 NETNATIVE_LOGE("SetMtu socket fail %{public}d", errno); 128 return -1; 129 } 130 131 struct ifreq ifr; 132 if (memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)) != EOK) { 133 close(sockfd); 134 return -1; 135 } 136 if (strncpy_s(ifr.ifr_name, IFNAMSIZ, interfaceName, strlen(interfaceName)) != EOK) { 137 close(sockfd); 138 return -1; 139 } 140 141 int32_t mtu = StrToInt(mtuValue); 142 ifr.ifr_mtu = mtu; 143 144 if (ioctl(sockfd, SIOCSIFMTU, &ifr) < 0) { 145 NETNATIVE_LOGE("SetMtu ioctl fail %{public}d", errno); 146 close(sockfd); 147 return -1; 148 } 149 150 close(sockfd); 151 return 0; 152} 153 154std::vector<std::string> InterfaceManager::GetInterfaceNames() 155{ 156 std::vector<std::string> ifaceNames; 157 DIR *dir(nullptr); 158 struct dirent *de(nullptr); 159 160 dir = opendir(SYS_NET_PATH); 161 if (dir == nullptr) { 162 NETNATIVE_LOGE("GetInterfaceNames opendir fail %{public}d", errno); 163 return ifaceNames; 164 } 165 166 de = readdir(dir); 167 while (de != nullptr) { 168 if ((de->d_name[0] != '.') && ((de->d_type == DT_DIR) || (de->d_type == DT_LNK))) { 169 ifaceNames.push_back(std::string(de->d_name)); 170 } 171 de = readdir(dir); 172 } 173 closedir(dir); 174 175 return ifaceNames; 176} 177 178int InterfaceManager::ModifyAddress(uint32_t action, const char *interfaceName, const char *addr, int prefixLen) 179{ 180 if (interfaceName == nullptr || addr == nullptr) { 181 return -1; 182 } 183 uint32_t index = if_nametoindex(interfaceName); 184 if (index == 0) { 185 NETNATIVE_LOGE("ModifyAddress, if_nametoindex error %{public}d", errno); 186 return -errno; 187 } 188 auto family = CommonUtils::GetAddrFamily(addr); 189 if (family != AF_INET && family != AF_INET6) { 190 NETNATIVE_LOGE("Ivalid ip address: %{public}s", CommonUtils::ToAnonymousIp(addr).c_str()); 191 return NETMANAGER_ERR_PARAMETER_ERROR; 192 } 193 194 ifaddrmsg ifm = {static_cast<uint8_t>(family), static_cast<uint8_t>(prefixLen), 0, 0, index}; 195 nmd::NetlinkMsg nlmsg(NLM_F_CREATE | NLM_F_EXCL, nmd::NETLINK_MAX_LEN, getpid()); 196 nlmsg.AddAddress(action, ifm); 197 198 if (family == AF_INET6) { 199 in6_addr in6Addr; 200 if (inet_pton(AF_INET6, addr, &in6Addr) == -1) { 201 NETNATIVE_LOGE("Modify ipv6 address, inet_pton error %{public}d", errno); 202 return NETMANAGER_ERR_INTERNAL; 203 } 204 nlmsg.AddAttr(IFA_LOCAL, &in6Addr, sizeof(in6Addr)); 205 } else { 206 in_addr inAddr; 207 if (inet_pton(AF_INET, addr, &inAddr) == -1) { 208 NETNATIVE_LOGE("Modify ipv4 address, inet_pton error %{public}d", errno); 209 return NETMANAGER_ERR_INTERNAL; 210 } 211 nlmsg.AddAttr(IFA_LOCAL, &inAddr, sizeof(inAddr)); 212 if (action == RTM_NEWADDR) { 213 inAddr.s_addr |= htonl((1U << (BIT_MAX - prefixLen)) - 1); 214 nlmsg.AddAttr(IFA_BROADCAST, &inAddr, sizeof(inAddr)); 215 } 216 } 217 218 NETNATIVE_LOGI("ModifyAddress:%{public}u %{public}s %{public}s %{public}d", action, interfaceName, 219 ToAnonymousIp(addr).c_str(), prefixLen); 220 221 return SendNetlinkMsgToKernel(nlmsg.GetNetLinkMessage()); 222} 223 224int InterfaceManager::AddAddress(const char *interfaceName, const char *addr, int prefixLen) 225{ 226 return ModifyAddress(RTM_NEWADDR, interfaceName, addr, prefixLen); 227} 228 229int InterfaceManager::DelAddress(const char *interfaceName, const char *addr, int prefixLen) 230{ 231 NetLinkSocketDiag socketDiag; 232 socketDiag.DestroyLiveSockets(addr, true); 233 return ModifyAddress(RTM_DELADDR, interfaceName, addr, prefixLen); 234} 235 236int InterfaceManager::DelAddress(const char *interfaceName, const char *addr, int prefixLen, 237 const std::string &netCapabilities) 238{ 239 NetLinkSocketDiag socketDiag; 240 socketDiag.SetSocketDestroyType(netCapabilities); 241 socketDiag.DestroyLiveSockets(addr, true); 242 return 0; 243} 244 245int Ipv4NetmaskToPrefixLength(in_addr_t mask) 246{ 247 int prefixLength = 0; 248 uint32_t m = ntohl(mask); 249 const uint32_t referenceValue = 1; 250 while (m & (referenceValue << MOVE_BIT_LEFT31)) { 251 prefixLength++; 252 m = m << referenceValue; 253 } 254 return prefixLength; 255} 256 257std::string HwAddrToStr(char *hwaddr) 258{ 259 char buf[64] = {'\0'}; 260 if (hwaddr != nullptr) { 261 errno_t result = 262 sprintf_s(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x", hwaddr[0], hwaddr[ARRAY_OFFSET_1_INDEX], 263 hwaddr[ARRAY_OFFSET_2_INDEX], hwaddr[ARRAY_OFFSET_3_INDEX], hwaddr[ARRAY_OFFSET_4_INDEX], 264 hwaddr[ARRAY_OFFSET_5_INDEX]); 265 if (result != 0) { 266 NETNATIVE_LOGE("[hwAddrToStr]: result %{public}d", result); 267 } 268 } 269 return std::string(buf); 270} 271 272void UpdateIfaceConfigFlags(unsigned flags, nmd::InterfaceConfigurationParcel &ifaceConfig) 273{ 274 ifaceConfig.flags.emplace_back(flags & IFF_UP ? "up" : "down"); 275 if (flags & IFF_BROADCAST) { 276 ifaceConfig.flags.emplace_back("broadcast"); 277 } 278 if (flags & IFF_LOOPBACK) { 279 ifaceConfig.flags.emplace_back("loopback"); 280 } 281 if (flags & IFF_POINTOPOINT) { 282 ifaceConfig.flags.emplace_back("point-to-point"); 283 } 284 if (flags & IFF_RUNNING) { 285 ifaceConfig.flags.emplace_back("running"); 286 } 287 if (flags & IFF_MULTICAST) { 288 ifaceConfig.flags.emplace_back("multicast"); 289 } 290} 291 292InterfaceConfigurationParcel InterfaceManager::GetIfaceConfig(const std::string &ifName) 293{ 294 NETNATIVE_LOGI("GetIfaceConfig in. ifName %{public}s", ifName.c_str()); 295 struct in_addr addr = {}; 296 nmd::InterfaceConfigurationParcel ifaceConfig; 297 298 int fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); 299 struct ifreq ifr = {}; 300 auto ret = strncpy_s(ifr.ifr_name, IFNAMSIZ, ifName.c_str(), ifName.length()); 301 if (ret != 0) { 302 NETNATIVE_LOGW("IfName copy failed, no need to return."); 303 } 304 305 ifaceConfig.ifName = ifName; 306 if (ioctl(fd, SIOCGIFADDR, &ifr) != -1) { 307 addr.s_addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr; 308 ifaceConfig.ipv4Addr = std::string(inet_ntoa(addr)); 309 } 310 if (ioctl(fd, SIOCGIFNETMASK, &ifr) != -1) { 311 ifaceConfig.prefixLength = Ipv4NetmaskToPrefixLength(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr); 312 } 313 if (ioctl(fd, SIOCGIFFLAGS, &ifr) != -1) { 314 UpdateIfaceConfigFlags(ifr.ifr_flags, ifaceConfig); 315 } 316 if (ioctl(fd, SIOCGIFHWADDR, &ifr) != -1) { 317 ifaceConfig.hwAddr = HwAddrToStr(ifr.ifr_hwaddr.sa_data); 318 } 319 close(fd); 320 return ifaceConfig; 321} 322 323int InterfaceManager::SetIfaceConfig(const nmd::InterfaceConfigurationParcel &ifaceConfig) 324{ 325 struct ifreq ifr = {}; 326 if (strncpy_s(ifr.ifr_name, IFNAMSIZ, ifaceConfig.ifName.c_str(), ifaceConfig.ifName.length()) != 0) { 327 NETNATIVE_LOGE("ifaceConfig strncpy_s error."); 328 return -1; 329 } 330 331 if (ifaceConfig.flags.empty()) { 332 NETNATIVE_LOGE("ifaceConfig flags is empty."); 333 return -1; 334 } 335 int fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); 336 if (fd < 0) { 337 NETNATIVE_LOGE("ifaceConfig socket error, errno[%{public}d]", errno); 338 return -1; 339 } 340 if (ioctl(fd, SIOCGIFFLAGS, &ifr) == -1) { 341 char errmsg[INTERFACE_ERR_MAX_LEN] = {0}; 342 strerror_r(errno, errmsg, INTERFACE_ERR_MAX_LEN); 343 NETNATIVE_LOGE("fail to set interface config. strerror[%{public}s]", errmsg); 344 close(fd); 345 return -1; 346 } 347 short flags = ifr.ifr_flags; 348 auto fit = std::find(ifaceConfig.flags.begin(), ifaceConfig.flags.end(), "up"); 349 if (fit != std::end(ifaceConfig.flags)) { 350 uint16_t ifrFlags = static_cast<uint16_t>(ifr.ifr_flags); 351 ifrFlags = ifrFlags | IFF_UP; 352 ifr.ifr_flags = static_cast<short>(ifrFlags); 353 } 354 fit = std::find(ifaceConfig.flags.begin(), ifaceConfig.flags.end(), "down"); 355 if (fit != std::end(ifaceConfig.flags)) { 356 ifr.ifr_flags = (short)((uint16_t)ifr.ifr_flags & (~IFF_UP)); 357 } 358 if (ifr.ifr_flags == flags) { 359 close(fd); 360 return 1; 361 } 362 uint32_t retry = 0; 363 do { 364 if (ioctl(fd, SIOCSIFFLAGS, &ifr) != -1) { 365 break; 366 } 367 ++retry; 368 } while (errno == ETIMEDOUT && retry < IOCTL_RETRY_TIME); 369 NETNATIVE_LOGI("set ifr flags=[%{public}d] strerror=[%{public}s] retry=[%{public}u]", ifr.ifr_flags, 370 strerror(errno), retry); 371 close(fd); 372 return 1; 373} 374 375int InterfaceManager::SetIpAddress(const std::string &ifaceName, const std::string &ipAddress) 376{ 377 struct ifreq ifr; 378 struct in_addr ipv4Addr = {INADDR_ANY}; 379 380 if (memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)) != EOK) { 381 NETNATIVE_LOGE("memset is false"); 382 return -1; 383 } 384 if (strncpy_s(ifr.ifr_name, IFNAMSIZ, ifaceName.c_str(), strlen(ifaceName.c_str())) != EOK) { 385 NETNATIVE_LOGE("strncpy is false"); 386 return -1; 387 } 388 if (inet_aton(ipAddress.c_str(), &ipv4Addr) == 0) { 389 NETNATIVE_LOGE("set net ip is false"); 390 return -1; 391 } 392 sockaddr_in *sin = reinterpret_cast<struct sockaddr_in *>(&ifr.ifr_addr); 393 sin->sin_family = AF_INET; 394 sin->sin_port = 0; 395 sin->sin_addr = ipv4Addr; 396 int32_t inetSocket = socket(AF_INET, SOCK_DGRAM, 0); 397 if (ioctl(inetSocket, SIOCSIFADDR, &ifr) < 0) { 398 NETNATIVE_LOGE("set ip address ioctl SIOCSIFADDR error: %{public}s", strerror(errno)); 399 close(inetSocket); 400 return -1; 401 } 402 close(inetSocket); 403 return 0; 404} 405 406int InterfaceManager::SetIffUp(const std::string &ifaceName) 407{ 408 struct ifreq ifr; 409 410 if (memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)) != EOK) { 411 NETNATIVE_LOGE("memset is false"); 412 return -1; 413 } 414 if (strncpy_s(ifr.ifr_name, IFNAMSIZ, ifaceName.c_str(), strlen(ifaceName.c_str())) != EOK) { 415 NETNATIVE_LOGE("strncpy is false"); 416 return -1; 417 } 418 uint32_t flagVal = (IFF_UP | IFF_MULTICAST); 419 ifr.ifr_flags = static_cast<short int>(flagVal); 420 421 int32_t inetSocket = socket(AF_INET, SOCK_DGRAM, 0); 422 if (ioctl(inetSocket, SIOCSIFFLAGS, &ifr) < 0) { 423 NETNATIVE_LOGE("set iface up ioctl SIOCSIFFLAGS error: %{public}s", strerror(errno)); 424 close(inetSocket); 425 return -1; 426 } 427 close(inetSocket); 428 return 0; 429} 430 431int32_t InterfaceManager::AddStaticArp(const std::string &ipAddr, const std::string &macAddr, 432 const std::string &ifName) 433{ 434 arpreq req = {}; 435 req.arp_flags = ATF_PERM; 436 int32_t res = AssembleArp(ipAddr, macAddr, ifName, req); 437 if (res != NETMANAGER_SUCCESS) { 438 NETNATIVE_LOGE("AssembleArp error"); 439 return res; 440 } 441 442 int32_t inetSocket = socket(AF_INET, SOCK_DGRAM, 0); 443 if (ioctl(inetSocket, SIOCSARP, &req) < 0) { 444 NETNATIVE_LOGE("AddStaticArp ioctl SIOCSARP error: %{public}s", strerror(errno)); 445 close(inetSocket); 446 return NETMANAGER_ERR_OPERATION_FAILED; 447 } 448 close(inetSocket); 449 return NETMANAGER_SUCCESS; 450} 451 452int32_t InterfaceManager::DelStaticArp(const std::string &ipAddr, const std::string &macAddr, 453 const std::string &ifName) 454{ 455 arpreq req = {}; 456 req.arp_flags = ATF_PERM; 457 int32_t res = AssembleArp(ipAddr, macAddr, ifName, req); 458 if (res != NETMANAGER_SUCCESS) { 459 NETNATIVE_LOGE("AssembleArp error"); 460 return res; 461 } 462 463 int32_t inetSocket = socket(AF_INET, SOCK_DGRAM, 0); 464 if (ioctl(inetSocket, SIOCDARP, &req) < 0) { 465 NETNATIVE_LOGE("DelStaticArp ioctl SIOCDARP error: %{public}s", strerror(errno)); 466 close(inetSocket); 467 return NETMANAGER_ERR_OPERATION_FAILED; 468 } 469 close(inetSocket); 470 return NETMANAGER_SUCCESS; 471} 472 473int32_t InterfaceManager::AssembleArp(const std::string &ipAddr, const std::string &macAddr, 474 const std::string &ifName, arpreq &req) 475{ 476 if (!IsValidIPV4(ipAddr)) { 477 NETNATIVE_LOGE("ipAddr error"); 478 return NETMANAGER_ERR_PARAMETER_ERROR; 479 } 480 481 if (!regex_match(macAddr, REGEX_CMD_MAC_ADDRESS)) { 482 NETNATIVE_LOGE("macAddr error"); 483 return NETMANAGER_ERR_PARAMETER_ERROR; 484 } 485 486 sockaddr& ethAddrStruct = req.arp_ha; 487 ethAddrStruct.sa_family = ARPHRD_ETHER; 488 if (MacStringToArray(macAddr, ethAddrStruct) != 0) { 489 NETNATIVE_LOGE("macStringToArray error"); 490 return NETMANAGER_ERR_OPERATION_FAILED; 491 } 492 493 in_addr ipv4Addr = {}; 494 if (inet_aton(ipAddr.c_str(), &ipv4Addr) == 0) { 495 NETNATIVE_LOGE("addr inet_aton error"); 496 return NETMANAGER_ERR_OPERATION_FAILED; 497 } 498 auto sin = reinterpret_cast<sockaddr_in *>(&req.arp_pa); 499 sin->sin_family = AF_INET; 500 sin->sin_addr = ipv4Addr; 501 502 if (strncpy_s(req.arp_dev, sizeof(req.arp_dev), 503 ifName.c_str(), ifName.size()) != 0) { 504 NETNATIVE_LOGE("strncpy_s is false"); 505 return NETMANAGER_ERR_OPERATION_FAILED; 506 } 507 508 auto uFlags = static_cast<unsigned int>(req.arp_flags); 509 uFlags |= ATF_COM; 510 req.arp_flags = static_cast<int>(uFlags); 511 512 return NETMANAGER_SUCCESS; 513} 514 515int32_t InterfaceManager::MacStringToArray(const std::string &macAddr, sockaddr &macSock) 516{ 517 char strMac[MAC_ADDRESS_INT_LEN] = {}; 518 char strAddr[MAC_ADDRESS_STR_LEN] = {}; 519 uint32_t v = 0; 520 if (memcpy_s(strAddr, MAC_ADDRESS_STR_LEN, macAddr.c_str(), macAddr.size()) != 0) { 521 NETNATIVE_LOGE("memcpy_s is false"); 522 return NETMANAGER_ERR_OPERATION_FAILED; 523 } 524 525 for (int i = 0; i < MAC_ADDRESS_INT_LEN; i++) { 526 if (sscanf_s(strAddr+MAC_SSCANF_SPACE*i, "%2x", &v) <= 0) { 527 NETNATIVE_LOGE("sscanf_s is false"); 528 return NETMANAGER_ERR_OPERATION_FAILED; 529 } 530 strMac[i] = (char)v; 531 } 532 533 if (memcpy_s(macSock.sa_data, sizeof(macSock.sa_data), 534 strMac, MAC_ADDRESS_INT_LEN) != 0) { 535 NETNATIVE_LOGE("memcpy_s is false"); 536 return NETMANAGER_ERR_OPERATION_FAILED; 537 } 538 539 return NETMANAGER_SUCCESS; 540} 541} // namespace nmd 542} // namespace OHOS 543