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 "route_utils.h" 17 18#include <arpa/inet.h> 19 20#include "net_mgr_log_wrapper.h" 21#include "netsys_controller.h" 22 23namespace OHOS { 24namespace NetManagerStandard { 25static constexpr const char *IPV6_DEFAULT_PRIFX = "fe80::"; 26static constexpr const char *IPV6_DEFAULT_GATEWAY = "::"; 27static constexpr int32_t IPV6_PRIFX_LEN = 64; 28static constexpr int32_t IPV4_PRIFX_LEN = 32; 29static constexpr int32_t IPV6_UINT_LEN = 16; 30static constexpr int32_t IPV4_UINT_LEN = 4; 31static constexpr int32_t IP_PER_UINT_SIZE = 8; 32static constexpr int32_t IP_PER_UINT_MASK = 0xFF; 33 34int32_t RouteUtils::AddRoutesToLocal(const std::string &iface, const std::list<Route> &routes) 35{ 36 std::list<Route>::const_iterator iter; 37 for (iter = routes.begin(); iter != routes.end(); ++iter) { 38 if (!(iter->rtnType_ == RTN_UNICAST && iter->destination_.prefixlen_ == 0)) { 39 NETMGR_LOG_D("AddRoutesToLocalNetwork: dest addr, gw addr"); 40 AddRoute(LOCAL_NET_ID, *iter); 41 } 42 } 43 44 Route ipv6Rt; 45 ipv6Rt.iface_ = iface; 46 ipv6Rt.destination_.type_ = INetAddr::IPV6; 47 ipv6Rt.destination_.address_ = IPV6_DEFAULT_PRIFX; 48 ipv6Rt.destination_.prefixlen_ = IPV6_PRIFX_LEN; 49 ipv6Rt.gateway_.address_ = IPV6_DEFAULT_GATEWAY; 50 ipv6Rt.gateway_.prefixlen_ = 0; 51 ipv6Rt.hasGateway_ = false; 52 ipv6Rt.rtnType_ = RTN_UNICAST; 53 ipv6Rt.isDefaultRoute_ = false; 54 return AddRoute(LOCAL_NET_ID, ipv6Rt); 55} 56 57int32_t RouteUtils::RemoveRoutesFromLocal(const std::list<Route> &routes) 58{ 59 std::list<Route>::const_iterator iter; 60 for (iter = routes.begin(); iter != routes.end(); ++iter) { 61 RemoveRoute(LOCAL_NET_ID, *iter); 62 } 63 64 return 0; 65} 66 67int32_t RouteUtils::AddRoute(int32_t netId, const Route &route) 68{ 69 return ModifyRoute(ROUTE_ADD, netId, route); 70} 71 72int32_t RouteUtils::RemoveRoute(int32_t netId, const Route &route) 73{ 74 return ModifyRoute(ROUTE_REMOVE, netId, route); 75} 76 77int32_t RouteUtils::UpdateRoutes(int32_t netId, const NetLinkInfo &newnl, const NetLinkInfo &oldnl) 78{ 79 std::list<Route> added; 80 std::list<Route> updated; 81 std::list<Route> removed; 82 std::list<Route>::const_iterator itero; 83 std::list<Route>::const_iterator itern; 84 std::list<Route>::const_iterator iterf; 85 86 for (itero = oldnl.routeList_.begin(); itero != oldnl.routeList_.end(); ++itero) { 87 iterf = std::find(newnl.routeList_.begin(), newnl.routeList_.end(), *itero); 88 if (iterf == newnl.routeList_.end()) { 89 removed.push_back(*itero); 90 } else { 91 if (itero->rtnType_ != iterf->rtnType_ || itero->mtu_ != iterf->mtu_) { 92 updated.push_back(*iterf); 93 } 94 } 95 } 96 97 for (itern = newnl.routeList_.begin(); itern != newnl.routeList_.end(); ++itern) { 98 if (std::find(oldnl.routeList_.begin(), oldnl.routeList_.end(), *itern) == oldnl.routeList_.end()) { 99 added.push_back(*itern); 100 } 101 } 102 103 for (itern = added.begin(); itern != added.end(); ++itern) { 104 if (itern->hasGateway_) { 105 continue; 106 } 107 AddRoute(netId, *itern); 108 } 109 110 for (itern = added.begin(); itern != added.end(); ++itern) { 111 if (!itern->hasGateway_) { 112 continue; 113 } 114 AddRoute(netId, *itern); 115 } 116 117 for (itern = removed.begin(); itern != removed.end(); ++itern) { 118 RemoveRoute(netId, *itern); 119 } 120 121 return (!added.empty() || !updated.empty() || !removed.empty()) ? 1 : 0; 122} 123 124int32_t RouteUtils::ModifyRoute(routeOperateType op, int32_t netId, const Route &route) 125{ 126 int32_t ret = -1; 127 std::string nextHop; 128 std::string dest; 129 130 NETMGR_LOG_D("ModifyRoute: netId[%{public}d], dest addr, gw addr", netId); 131 132 switch (route.rtnType_) { 133 case RTN_UNICAST: 134 if (route.hasGateway_) { 135 nextHop = route.gateway_.address_; 136 } 137 break; 138 case RTN_UNREACHABLE: 139 nextHop = NEXTHOP_UNREACHABLE; 140 break; 141 case RTN_THROW: 142 nextHop = NEXTHOP_THROW; 143 break; 144 default: 145 break; 146 } 147 148 ToPrefixString(route.destination_.address_, route.destination_.prefixlen_, dest); 149 if (dest.empty()) { 150 NETMGR_LOG_E("route dest is empty."); 151 return ret; 152 } 153 154 switch (op) { 155 case ROUTE_ADD: 156 ret = NetsysController::GetInstance().NetworkAddRoute(netId, route.iface_, dest, nextHop); 157 break; 158 case ROUTE_REMOVE: 159 ret = NetsysController::GetInstance().NetworkRemoveRoute(netId, route.iface_, dest, nextHop); 160 break; 161 default: 162 break; 163 } 164 165 return ret; 166} 167 168void RouteUtils::ToPrefixString(const std::string &src, int32_t prefixLen, std::string &dest) 169{ 170 dest = MaskAddress(src, prefixLen); 171 NETMGR_LOG_D("ToPrefixString: src addr, src prefixlen[%{public}d], mask dest addr", prefixLen); 172 if (!dest.empty()) { 173 dest += "/"; 174 dest += std::to_string(prefixLen); 175 } 176} 177 178std::string RouteUtils::MaskAddress(const std::string &addr, int32_t prefixLen) 179{ 180 int32_t netScope = 0; 181 int32_t hostScope = 0; 182 uint8_t mask = 0; 183 uint8_t array[IPV6_UINT_LEN] = {0}; 184 char str[INET6_ADDRSTRLEN] = {0}; 185 int32_t af = prefixLen > IPV4_PRIFX_LEN ? AF_INET6 : AF_INET; 186 int32_t arrayLen = (af == AF_INET ? IPV4_UINT_LEN : IPV6_UINT_LEN); 187 188 netScope = prefixLen / IP_PER_UINT_SIZE; 189 hostScope = prefixLen % IP_PER_UINT_SIZE; 190 mask = (uint8_t)(IP_PER_UINT_MASK << (IP_PER_UINT_SIZE - hostScope)); 191 192 if (inet_pton(af, addr.c_str(), array) != 1) { 193 return std::string(""); 194 } 195 196 if (netScope < arrayLen) { 197 array[netScope] = (uint8_t)(array[netScope] & mask); 198 } 199 200 netScope++; 201 for (; netScope < arrayLen; netScope++) { 202 array[netScope] = 0; 203 } 204 205 if (inet_ntop(af, array, str, INET6_ADDRSTRLEN) == nullptr) { 206 return std::string(""); 207 } 208 209 return std::string(str); 210} 211} // namespace NetManagerStandard 212} // namespace OHOS 213