1b1b8bc3fSopenharmony_ci/*
2b1b8bc3fSopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3b1b8bc3fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4b1b8bc3fSopenharmony_ci * you may not use this file except in compliance with the License.
5b1b8bc3fSopenharmony_ci * You may obtain a copy of the License at
6b1b8bc3fSopenharmony_ci *
7b1b8bc3fSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8b1b8bc3fSopenharmony_ci *
9b1b8bc3fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10b1b8bc3fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11b1b8bc3fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12b1b8bc3fSopenharmony_ci * See the License for the specific language governing permissions and
13b1b8bc3fSopenharmony_ci * limitations under the License.
14b1b8bc3fSopenharmony_ci */
15b1b8bc3fSopenharmony_ci
16b1b8bc3fSopenharmony_ci#include "route_utils.h"
17b1b8bc3fSopenharmony_ci
18b1b8bc3fSopenharmony_ci#include <arpa/inet.h>
19b1b8bc3fSopenharmony_ci
20b1b8bc3fSopenharmony_ci#include "net_mgr_log_wrapper.h"
21b1b8bc3fSopenharmony_ci#include "netsys_controller.h"
22b1b8bc3fSopenharmony_ci
23b1b8bc3fSopenharmony_cinamespace OHOS {
24b1b8bc3fSopenharmony_cinamespace NetManagerStandard {
25b1b8bc3fSopenharmony_cistatic constexpr const char *IPV6_DEFAULT_PRIFX = "fe80::";
26b1b8bc3fSopenharmony_cistatic constexpr const char *IPV6_DEFAULT_GATEWAY = "::";
27b1b8bc3fSopenharmony_cistatic constexpr int32_t IPV6_PRIFX_LEN = 64;
28b1b8bc3fSopenharmony_cistatic constexpr int32_t IPV4_PRIFX_LEN = 32;
29b1b8bc3fSopenharmony_cistatic constexpr int32_t IPV6_UINT_LEN = 16;
30b1b8bc3fSopenharmony_cistatic constexpr int32_t IPV4_UINT_LEN = 4;
31b1b8bc3fSopenharmony_cistatic constexpr int32_t IP_PER_UINT_SIZE = 8;
32b1b8bc3fSopenharmony_cistatic constexpr int32_t IP_PER_UINT_MASK = 0xFF;
33b1b8bc3fSopenharmony_ci
34b1b8bc3fSopenharmony_ciint32_t RouteUtils::AddRoutesToLocal(const std::string &iface, const std::list<Route> &routes)
35b1b8bc3fSopenharmony_ci{
36b1b8bc3fSopenharmony_ci    std::list<Route>::const_iterator iter;
37b1b8bc3fSopenharmony_ci    for (iter = routes.begin(); iter != routes.end(); ++iter) {
38b1b8bc3fSopenharmony_ci        if (!(iter->rtnType_ == RTN_UNICAST && iter->destination_.prefixlen_ == 0)) {
39b1b8bc3fSopenharmony_ci            NETMGR_LOG_D("AddRoutesToLocalNetwork: dest addr, gw addr");
40b1b8bc3fSopenharmony_ci            AddRoute(LOCAL_NET_ID, *iter);
41b1b8bc3fSopenharmony_ci        }
42b1b8bc3fSopenharmony_ci    }
43b1b8bc3fSopenharmony_ci
44b1b8bc3fSopenharmony_ci    Route ipv6Rt;
45b1b8bc3fSopenharmony_ci    ipv6Rt.iface_ = iface;
46b1b8bc3fSopenharmony_ci    ipv6Rt.destination_.type_ = INetAddr::IPV6;
47b1b8bc3fSopenharmony_ci    ipv6Rt.destination_.address_ = IPV6_DEFAULT_PRIFX;
48b1b8bc3fSopenharmony_ci    ipv6Rt.destination_.prefixlen_ = IPV6_PRIFX_LEN;
49b1b8bc3fSopenharmony_ci    ipv6Rt.gateway_.address_ = IPV6_DEFAULT_GATEWAY;
50b1b8bc3fSopenharmony_ci    ipv6Rt.gateway_.prefixlen_ = 0;
51b1b8bc3fSopenharmony_ci    ipv6Rt.hasGateway_ = false;
52b1b8bc3fSopenharmony_ci    ipv6Rt.rtnType_ = RTN_UNICAST;
53b1b8bc3fSopenharmony_ci    ipv6Rt.isDefaultRoute_ = false;
54b1b8bc3fSopenharmony_ci    return AddRoute(LOCAL_NET_ID, ipv6Rt);
55b1b8bc3fSopenharmony_ci}
56b1b8bc3fSopenharmony_ci
57b1b8bc3fSopenharmony_ciint32_t RouteUtils::RemoveRoutesFromLocal(const std::list<Route> &routes)
58b1b8bc3fSopenharmony_ci{
59b1b8bc3fSopenharmony_ci    std::list<Route>::const_iterator iter;
60b1b8bc3fSopenharmony_ci    for (iter = routes.begin(); iter != routes.end(); ++iter) {
61b1b8bc3fSopenharmony_ci        RemoveRoute(LOCAL_NET_ID, *iter);
62b1b8bc3fSopenharmony_ci    }
63b1b8bc3fSopenharmony_ci
64b1b8bc3fSopenharmony_ci    return 0;
65b1b8bc3fSopenharmony_ci}
66b1b8bc3fSopenharmony_ci
67b1b8bc3fSopenharmony_ciint32_t RouteUtils::AddRoute(int32_t netId, const Route &route)
68b1b8bc3fSopenharmony_ci{
69b1b8bc3fSopenharmony_ci    return ModifyRoute(ROUTE_ADD, netId, route);
70b1b8bc3fSopenharmony_ci}
71b1b8bc3fSopenharmony_ci
72b1b8bc3fSopenharmony_ciint32_t RouteUtils::RemoveRoute(int32_t netId, const Route &route)
73b1b8bc3fSopenharmony_ci{
74b1b8bc3fSopenharmony_ci    return ModifyRoute(ROUTE_REMOVE, netId, route);
75b1b8bc3fSopenharmony_ci}
76b1b8bc3fSopenharmony_ci
77b1b8bc3fSopenharmony_ciint32_t RouteUtils::UpdateRoutes(int32_t netId, const NetLinkInfo &newnl, const NetLinkInfo &oldnl)
78b1b8bc3fSopenharmony_ci{
79b1b8bc3fSopenharmony_ci    std::list<Route> added;
80b1b8bc3fSopenharmony_ci    std::list<Route> updated;
81b1b8bc3fSopenharmony_ci    std::list<Route> removed;
82b1b8bc3fSopenharmony_ci    std::list<Route>::const_iterator itero;
83b1b8bc3fSopenharmony_ci    std::list<Route>::const_iterator itern;
84b1b8bc3fSopenharmony_ci    std::list<Route>::const_iterator iterf;
85b1b8bc3fSopenharmony_ci
86b1b8bc3fSopenharmony_ci    for (itero = oldnl.routeList_.begin(); itero != oldnl.routeList_.end(); ++itero) {
87b1b8bc3fSopenharmony_ci        iterf = std::find(newnl.routeList_.begin(), newnl.routeList_.end(), *itero);
88b1b8bc3fSopenharmony_ci        if (iterf == newnl.routeList_.end()) {
89b1b8bc3fSopenharmony_ci            removed.push_back(*itero);
90b1b8bc3fSopenharmony_ci        } else {
91b1b8bc3fSopenharmony_ci            if (itero->rtnType_ != iterf->rtnType_ || itero->mtu_ != iterf->mtu_) {
92b1b8bc3fSopenharmony_ci                updated.push_back(*iterf);
93b1b8bc3fSopenharmony_ci            }
94b1b8bc3fSopenharmony_ci        }
95b1b8bc3fSopenharmony_ci    }
96b1b8bc3fSopenharmony_ci
97b1b8bc3fSopenharmony_ci    for (itern = newnl.routeList_.begin(); itern != newnl.routeList_.end(); ++itern) {
98b1b8bc3fSopenharmony_ci        if (std::find(oldnl.routeList_.begin(), oldnl.routeList_.end(), *itern) == oldnl.routeList_.end()) {
99b1b8bc3fSopenharmony_ci            added.push_back(*itern);
100b1b8bc3fSopenharmony_ci        }
101b1b8bc3fSopenharmony_ci    }
102b1b8bc3fSopenharmony_ci
103b1b8bc3fSopenharmony_ci    for (itern = added.begin(); itern != added.end(); ++itern) {
104b1b8bc3fSopenharmony_ci        if (itern->hasGateway_) {
105b1b8bc3fSopenharmony_ci            continue;
106b1b8bc3fSopenharmony_ci        }
107b1b8bc3fSopenharmony_ci        AddRoute(netId, *itern);
108b1b8bc3fSopenharmony_ci    }
109b1b8bc3fSopenharmony_ci
110b1b8bc3fSopenharmony_ci    for (itern = added.begin(); itern != added.end(); ++itern) {
111b1b8bc3fSopenharmony_ci        if (!itern->hasGateway_) {
112b1b8bc3fSopenharmony_ci            continue;
113b1b8bc3fSopenharmony_ci        }
114b1b8bc3fSopenharmony_ci        AddRoute(netId, *itern);
115b1b8bc3fSopenharmony_ci    }
116b1b8bc3fSopenharmony_ci
117b1b8bc3fSopenharmony_ci    for (itern = removed.begin(); itern != removed.end(); ++itern) {
118b1b8bc3fSopenharmony_ci        RemoveRoute(netId, *itern);
119b1b8bc3fSopenharmony_ci    }
120b1b8bc3fSopenharmony_ci
121b1b8bc3fSopenharmony_ci    return (!added.empty() || !updated.empty() || !removed.empty()) ? 1 : 0;
122b1b8bc3fSopenharmony_ci}
123b1b8bc3fSopenharmony_ci
124b1b8bc3fSopenharmony_ciint32_t RouteUtils::ModifyRoute(routeOperateType op, int32_t netId, const Route &route)
125b1b8bc3fSopenharmony_ci{
126b1b8bc3fSopenharmony_ci    int32_t ret = -1;
127b1b8bc3fSopenharmony_ci    std::string nextHop;
128b1b8bc3fSopenharmony_ci    std::string dest;
129b1b8bc3fSopenharmony_ci
130b1b8bc3fSopenharmony_ci    NETMGR_LOG_D("ModifyRoute: netId[%{public}d], dest addr, gw addr", netId);
131b1b8bc3fSopenharmony_ci
132b1b8bc3fSopenharmony_ci    switch (route.rtnType_) {
133b1b8bc3fSopenharmony_ci        case RTN_UNICAST:
134b1b8bc3fSopenharmony_ci            if (route.hasGateway_) {
135b1b8bc3fSopenharmony_ci                nextHop = route.gateway_.address_;
136b1b8bc3fSopenharmony_ci            }
137b1b8bc3fSopenharmony_ci            break;
138b1b8bc3fSopenharmony_ci        case RTN_UNREACHABLE:
139b1b8bc3fSopenharmony_ci            nextHop = NEXTHOP_UNREACHABLE;
140b1b8bc3fSopenharmony_ci            break;
141b1b8bc3fSopenharmony_ci        case RTN_THROW:
142b1b8bc3fSopenharmony_ci            nextHop = NEXTHOP_THROW;
143b1b8bc3fSopenharmony_ci            break;
144b1b8bc3fSopenharmony_ci        default:
145b1b8bc3fSopenharmony_ci            break;
146b1b8bc3fSopenharmony_ci    }
147b1b8bc3fSopenharmony_ci
148b1b8bc3fSopenharmony_ci    ToPrefixString(route.destination_.address_, route.destination_.prefixlen_, dest);
149b1b8bc3fSopenharmony_ci    if (dest.empty()) {
150b1b8bc3fSopenharmony_ci        NETMGR_LOG_E("route dest is empty.");
151b1b8bc3fSopenharmony_ci        return ret;
152b1b8bc3fSopenharmony_ci    }
153b1b8bc3fSopenharmony_ci
154b1b8bc3fSopenharmony_ci    switch (op) {
155b1b8bc3fSopenharmony_ci        case ROUTE_ADD:
156b1b8bc3fSopenharmony_ci            ret = NetsysController::GetInstance().NetworkAddRoute(netId, route.iface_, dest, nextHop);
157b1b8bc3fSopenharmony_ci            break;
158b1b8bc3fSopenharmony_ci        case ROUTE_REMOVE:
159b1b8bc3fSopenharmony_ci            ret = NetsysController::GetInstance().NetworkRemoveRoute(netId, route.iface_, dest, nextHop);
160b1b8bc3fSopenharmony_ci            break;
161b1b8bc3fSopenharmony_ci        default:
162b1b8bc3fSopenharmony_ci            break;
163b1b8bc3fSopenharmony_ci    }
164b1b8bc3fSopenharmony_ci
165b1b8bc3fSopenharmony_ci    return ret;
166b1b8bc3fSopenharmony_ci}
167b1b8bc3fSopenharmony_ci
168b1b8bc3fSopenharmony_civoid RouteUtils::ToPrefixString(const std::string &src, int32_t prefixLen, std::string &dest)
169b1b8bc3fSopenharmony_ci{
170b1b8bc3fSopenharmony_ci    dest = MaskAddress(src, prefixLen);
171b1b8bc3fSopenharmony_ci    NETMGR_LOG_D("ToPrefixString: src addr, src prefixlen[%{public}d], mask dest addr", prefixLen);
172b1b8bc3fSopenharmony_ci    if (!dest.empty()) {
173b1b8bc3fSopenharmony_ci        dest += "/";
174b1b8bc3fSopenharmony_ci        dest += std::to_string(prefixLen);
175b1b8bc3fSopenharmony_ci    }
176b1b8bc3fSopenharmony_ci}
177b1b8bc3fSopenharmony_ci
178b1b8bc3fSopenharmony_cistd::string RouteUtils::MaskAddress(const std::string &addr, int32_t prefixLen)
179b1b8bc3fSopenharmony_ci{
180b1b8bc3fSopenharmony_ci    int32_t netScope = 0;
181b1b8bc3fSopenharmony_ci    int32_t hostScope = 0;
182b1b8bc3fSopenharmony_ci    uint8_t mask = 0;
183b1b8bc3fSopenharmony_ci    uint8_t array[IPV6_UINT_LEN] = {0};
184b1b8bc3fSopenharmony_ci    char str[INET6_ADDRSTRLEN] = {0};
185b1b8bc3fSopenharmony_ci    int32_t af = prefixLen > IPV4_PRIFX_LEN ? AF_INET6 : AF_INET;
186b1b8bc3fSopenharmony_ci    int32_t arrayLen = (af == AF_INET ? IPV4_UINT_LEN : IPV6_UINT_LEN);
187b1b8bc3fSopenharmony_ci
188b1b8bc3fSopenharmony_ci    netScope = prefixLen / IP_PER_UINT_SIZE;
189b1b8bc3fSopenharmony_ci    hostScope = prefixLen % IP_PER_UINT_SIZE;
190b1b8bc3fSopenharmony_ci    mask = (uint8_t)(IP_PER_UINT_MASK << (IP_PER_UINT_SIZE - hostScope));
191b1b8bc3fSopenharmony_ci
192b1b8bc3fSopenharmony_ci    if (inet_pton(af, addr.c_str(), array) != 1) {
193b1b8bc3fSopenharmony_ci        return std::string("");
194b1b8bc3fSopenharmony_ci    }
195b1b8bc3fSopenharmony_ci
196b1b8bc3fSopenharmony_ci    if (netScope < arrayLen) {
197b1b8bc3fSopenharmony_ci        array[netScope] = (uint8_t)(array[netScope] & mask);
198b1b8bc3fSopenharmony_ci    }
199b1b8bc3fSopenharmony_ci
200b1b8bc3fSopenharmony_ci    netScope++;
201b1b8bc3fSopenharmony_ci    for (; netScope < arrayLen; netScope++) {
202b1b8bc3fSopenharmony_ci        array[netScope] = 0;
203b1b8bc3fSopenharmony_ci    }
204b1b8bc3fSopenharmony_ci
205b1b8bc3fSopenharmony_ci    if (inet_ntop(af, array, str, INET6_ADDRSTRLEN) == nullptr) {
206b1b8bc3fSopenharmony_ci        return std::string("");
207b1b8bc3fSopenharmony_ci    }
208b1b8bc3fSopenharmony_ci
209b1b8bc3fSopenharmony_ci    return std::string(str);
210b1b8bc3fSopenharmony_ci}
211b1b8bc3fSopenharmony_ci} // namespace NetManagerStandard
212b1b8bc3fSopenharmony_ci} // namespace OHOS
213