1 /*
2  * Copyright (c) 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 "wrapper_distributor.h"
17 
18 #include "netmanager_base_common_utils.h"
19 #include "netnative_log_wrapper.h"
20 
21 namespace OHOS {
22 namespace nmd {
23 using namespace NetManagerStandard::CommonUtils;
24 namespace {
IsValidMessage(const std::shared_ptr<NetsysEventMessage> & message)25 bool IsValidMessage(const std::shared_ptr<NetsysEventMessage> &message)
26 {
27     return message->GetAction() != NetsysEventMessage::Action::UNKNOWN &&
28            message->GetSubSys() != NetsysEventMessage::SubSys::UNKNOWN;
29 }
30 } // namespace
WrapperDistributor(int32_t socket,const int32_t format,std::mutex & externMutex)31 WrapperDistributor::WrapperDistributor(int32_t socket, const int32_t format, std::mutex& externMutex)
32     : netlinkCallbacksMutex_(externMutex)
33 {
34     NETNATIVE_LOG_D("WrapperDistributor::WrapperDistributor: Socket: %{public}d, Format: %{public}d", socket, format);
35     receiver_ = std::make_unique<DataReceiver>(socket, format);
36     receiver_->RegisterCallback(
37         [this](const std::shared_ptr<NetsysEventMessage> message) { HandleDecodeSuccess(message); });
38 }
39 
Start()40 int32_t WrapperDistributor::Start()
41 {
42     return receiver_->Start();
43 }
44 
Stop()45 int32_t WrapperDistributor::Stop()
46 {
47     return receiver_->Stop();
48 }
49 
RegisterNetlinkCallbacks(std::shared_ptr<std::vector<sptr<NetsysNative::INotifyCallback>>> netlinkCallbacks)50 int32_t WrapperDistributor::RegisterNetlinkCallbacks(
51     std::shared_ptr<std::vector<sptr<NetsysNative::INotifyCallback>>> netlinkCallbacks)
52 {
53     std::lock_guard<std::mutex> lock(netlinkCallbacksMutex_);
54     if (netlinkCallbacks == nullptr) {
55         NETNATIVE_LOGE("netlinkCallbacks is nullptr");
56         return NetlinkResult::ERR_NULL_PTR;
57     }
58     netlinkCallbacks_ = netlinkCallbacks;
59     return NetlinkResult::OK;
60 }
61 
HandleDecodeSuccess(const std::shared_ptr<NetsysEventMessage> & message)62 void WrapperDistributor::HandleDecodeSuccess(const std::shared_ptr<NetsysEventMessage> &message)
63 {
64     if (message == nullptr) {
65         NETNATIVE_LOGE("NetlinkProcessor: OnEvent: message is nullptr");
66         return;
67     }
68     if (netlinkCallbacks_ == nullptr) {
69         NETNATIVE_LOGE("netlinkCallbacks_ is nullptr");
70         return;
71     }
72     if (!IsValidMessage(message)) {
73         return;
74     }
75     HandleStateChanged(message);
76 }
77 
HandleStateChanged(const std::shared_ptr<NetsysEventMessage> & message)78 void WrapperDistributor::HandleStateChanged(const std::shared_ptr<NetsysEventMessage> &message)
79 {
80     message->DumpMessage();
81     const NetsysEventMessage::SubSys subSys = message->GetSubSys();
82     switch (subSys) {
83         case NetsysEventMessage::SubSys::NET:
84             HandleSubSysNet(message);
85             break;
86         case NetsysEventMessage::SubSys::QLOG:
87             HandleSubSysQlog(message);
88             break;
89         default:
90             break;
91     }
92 }
93 
HandleSubSysNet(const std::shared_ptr<NetsysEventMessage> & message)94 void WrapperDistributor::HandleSubSysNet(const std::shared_ptr<NetsysEventMessage> &message)
95 {
96     NetsysEventMessage::Action action = message->GetAction();
97     const std::string &iface = message->GetMessage(NetsysEventMessage::Type::INTERFACE);
98 
99     switch (action) {
100         case NetsysEventMessage::Action::ADD:
101             NotifyInterfaceAdd(iface);
102             break;
103         case NetsysEventMessage::Action::REMOVE:
104             NotifyInterfaceRemove(iface);
105             break;
106         case NetsysEventMessage::Action::CHANGE:
107             NotifyInterfaceChange(iface, true);
108             break;
109         case NetsysEventMessage::Action::LINKUP:
110             NotifyInterfaceLinkStateChange(iface, true);
111             break;
112         case NetsysEventMessage::Action::LINKDOWN:
113             NotifyInterfaceLinkStateChange(iface, false);
114             break;
115         case NetsysEventMessage::Action::ADDRESSUPDATE:
116         case NetsysEventMessage::Action::ADDRESSREMOVED:
117             HandleAddressChange(message);
118             break;
119         case NetsysEventMessage::Action::ROUTEUPDATED:
120         case NetsysEventMessage::Action::ROUTEREMOVED:
121             HandleRouteChange(message);
122             break;
123         default:
124             break;
125     }
126 }
127 
HandleAddressChange(const std::shared_ptr<NetsysEventMessage> & message)128 void WrapperDistributor::HandleAddressChange(const std::shared_ptr<NetsysEventMessage> &message)
129 {
130     NetsysEventMessage::Action action = message->GetAction();
131     const std::string &iface = message->GetMessage(NetsysEventMessage::Type::INTERFACE);
132     const std::string &address = message->GetMessage(NetsysEventMessage::Type::ADDRESS);
133     const std::string &flags = message->GetMessage(NetsysEventMessage::Type::FLAGS);
134     const std::string &scope = message->GetMessage(NetsysEventMessage::Type::SCOPE);
135     const bool addrUpdated = (action == NetsysEventMessage::Action::ADDRESSUPDATE);
136 
137     if (!iface.empty() && iface[0] && !address.empty() && !flags.empty() && !scope.empty()) {
138         if (addrUpdated) {
139             NotifyInterfaceAddressUpdate(address, iface, ConvertToInt64(flags), ConvertToInt64(scope));
140         } else {
141             NotifyInterfaceAddressRemove(address, iface, ConvertToInt64(flags), ConvertToInt64(scope));
142         }
143     }
144 }
145 
HandleRouteChange(const std::shared_ptr<NetsysEventMessage> & message)146 void WrapperDistributor::HandleRouteChange(const std::shared_ptr<NetsysEventMessage> &message)
147 {
148     NetsysEventMessage::Action action = message->GetAction();
149     const std::string &route = message->GetMessage(NetsysEventMessage::Type::ROUTE);
150     const std::string &gateway = message->GetMessage(NetsysEventMessage::Type::GATEWAY);
151     const std::string &iface = message->GetMessage(NetsysEventMessage::Type::INTERFACE);
152     if (!route.empty() && (!gateway.empty() || !iface.empty())) {
153         NotifyRouteChange((action == NetsysEventMessage::Action::ROUTEUPDATED), route, gateway, iface);
154     }
155 }
156 
HandleSubSysQlog(const std::shared_ptr<NetsysEventMessage> & message)157 void WrapperDistributor::HandleSubSysQlog(const std::shared_ptr<NetsysEventMessage> &message)
158 {
159     const std::string &alertName = message->GetMessage(NetsysEventMessage::Type::ALERT_NAME);
160     const std::string &iface = message->GetMessage(NetsysEventMessage::Type::INTERFACE);
161     if (iface.empty()) {
162         NETNATIVE_LOGW("No interface name in event message");
163         return;
164     }
165     NotifyQuotaLimitReache(alertName, iface);
166 }
167 
NotifyInterfaceAdd(const std::string & ifName)168 void WrapperDistributor::NotifyInterfaceAdd(const std::string &ifName)
169 {
170     NETNATIVE_LOG_D("interface added: %{public}s", ifName.c_str());
171     std::lock_guard<std::mutex> lock(netlinkCallbacksMutex_);
172     if (netlinkCallbacks_ == nullptr) {
173         NETNATIVE_LOGE("netlinkCallbacks_ is nullptr");
174         return;
175     }
176     for (auto &callback : *netlinkCallbacks_) {
177         if (callback != nullptr) {
178             callback->OnInterfaceAdded(ifName);
179         }
180     }
181 }
182 
NotifyInterfaceRemove(const std::string & ifName)183 void WrapperDistributor::NotifyInterfaceRemove(const std::string &ifName)
184 {
185     NETNATIVE_LOG_D("interface removed: %{public}s", ifName.c_str());
186     std::lock_guard<std::mutex> lock(netlinkCallbacksMutex_);
187     if (netlinkCallbacks_ == nullptr) {
188         NETNATIVE_LOGE("netlinkCallbacks_ is nullptr");
189         return;
190     }
191     for (auto &callback : *netlinkCallbacks_) {
192         if (callback != nullptr) {
193             callback->OnInterfaceRemoved(ifName);
194         }
195     }
196 }
197 
NotifyInterfaceChange(const std::string & ifName,bool up)198 void WrapperDistributor::NotifyInterfaceChange(const std::string &ifName, bool up)
199 {
200     NETNATIVE_LOG_D("interface Change: %{public}s, %{public}d", ifName.c_str(), up);
201     std::lock_guard<std::mutex> lock(netlinkCallbacksMutex_);
202     if (netlinkCallbacks_ == nullptr) {
203         NETNATIVE_LOGE("netlinkCallbacks_ is nullptr");
204         return;
205     }
206     for (auto &callback : *netlinkCallbacks_) {
207         if (callback != nullptr) {
208             callback->OnInterfaceChanged(ifName, up);
209         }
210     }
211 }
212 
NotifyInterfaceLinkStateChange(const std::string & ifName,bool up)213 void WrapperDistributor::NotifyInterfaceLinkStateChange(const std::string &ifName, bool up)
214 {
215     NETNATIVE_LOG_D("interface link state Change: %{public}s, %{public}d", ifName.c_str(), up);
216     std::lock_guard<std::mutex> lock(netlinkCallbacksMutex_);
217     if (netlinkCallbacks_ == nullptr) {
218         NETNATIVE_LOGE("netlinkCallbacks_ is nullptr");
219         return;
220     }
221     for (auto &callback : *netlinkCallbacks_) {
222         if (callback != nullptr) {
223             callback->OnInterfaceLinkStateChanged(ifName, up);
224         }
225     }
226 }
227 
NotifyQuotaLimitReache(const std::string & labelName,const std::string & ifName)228 void WrapperDistributor::NotifyQuotaLimitReache(const std::string &labelName, const std::string &ifName)
229 {
230     NETNATIVE_LOG_D("NotifyQuotaLimitReache: %{public}s, %{public}s", labelName.c_str(), ifName.c_str());
231     std::lock_guard<std::mutex> lock(netlinkCallbacksMutex_);
232     if (netlinkCallbacks_ == nullptr) {
233         NETNATIVE_LOGE("netlinkCallbacks_ is nullptr");
234         return;
235     }
236     for (auto &callback : *netlinkCallbacks_) {
237         if (callback != nullptr) {
238             callback->OnBandwidthReachedLimit(labelName, ifName);
239         }
240     }
241 }
242 
NotifyInterfaceAddressUpdate(const std::string & addr,const std::string & ifName,int32_t flags,int32_t scope)243 void WrapperDistributor::NotifyInterfaceAddressUpdate(const std::string &addr, const std::string &ifName,
244                                                       int32_t flags, int32_t scope)
245 {
246     NETNATIVE_LOG_D("OnInterfaceAddressUpdated: %{public}s, %{public}s, %{public}d, %{public}d",
247                     ToAnonymousIp(addr).c_str(), ifName.c_str(), flags, scope);
248     std::lock_guard<std::mutex> lock(netlinkCallbacksMutex_);
249     if (netlinkCallbacks_ == nullptr) {
250         NETNATIVE_LOGE("netlinkCallbacks_ is nullptr");
251         return;
252     }
253     for (auto &callback : *netlinkCallbacks_) {
254         if (callback != nullptr) {
255             callback->OnInterfaceAddressUpdated(addr, ifName, flags, scope);
256         }
257     }
258 }
259 
NotifyInterfaceAddressRemove(const std::string & addr,const std::string & ifName,int32_t flags,int32_t scope)260 void WrapperDistributor::NotifyInterfaceAddressRemove(const std::string &addr, const std::string &ifName,
261                                                       int32_t flags, int32_t scope)
262 {
263     NETNATIVE_LOG_D("NotifyInterfaceAddressRemove: %{public}s, %{public}s, %{public}d, %{public}d",
264                     ToAnonymousIp(addr).c_str(), ifName.c_str(), flags, scope);
265     std::lock_guard<std::mutex> lock(netlinkCallbacksMutex_);
266     if (netlinkCallbacks_ == nullptr) {
267         NETNATIVE_LOGE("netlinkCallbacks_ is nullptr");
268         return;
269     }
270     for (auto &callback : *netlinkCallbacks_) {
271         if (callback != nullptr) {
272             callback->OnInterfaceAddressRemoved(addr, ifName, flags, scope);
273         }
274     }
275 }
276 
NotifyRouteChange(bool updated,const std::string & route,const std::string & gateway,const std::string & ifName)277 void WrapperDistributor::NotifyRouteChange(bool updated, const std::string &route, const std::string &gateway,
278                                            const std::string &ifName)
279 {
280     NETNATIVE_LOG_D("NotifyRouteChange: %{public}s, %{public}s, %{public}s, %{public}s",
281                     updated ? "updated" : "removed", ToAnonymousIp(route).c_str(), ToAnonymousIp(gateway).c_str(),
282                     ifName.c_str());
283     std::lock_guard<std::mutex> lock(netlinkCallbacksMutex_);
284     if (netlinkCallbacks_ == nullptr) {
285         NETNATIVE_LOGE("netlinkCallbacks_ is nullptr");
286         return;
287     }
288     for (auto &callback : *netlinkCallbacks_) {
289         if (callback != nullptr) {
290             callback->OnRouteChanged(updated, route, gateway, ifName);
291         }
292     }
293 }
294 } // namespace nmd
295 } // namespace OHOS
296