• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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 "netlink_manager.h"
17 
18 #include <cerrno>
19 #include <linux/netlink.h>
20 #include <linux/rtnetlink.h>
21 #include <map>
22 #include <mutex>
23 #include <sys/socket.h>
24 #include <unistd.h>
25 
26 #include "netlink_define.h"
27 #include "netnative_log_wrapper.h"
28 #include "wrapper_distributor.h"
29 
30 namespace OHOS {
31 namespace nmd {
32 using namespace NetlinkDefine;
33 namespace {
34 constexpr int32_t NFLOG_QUOTA_GROUP = 1;
35 constexpr int32_t UEVENT_GROUP = 0xffffffff;
36 struct DistributorParam {
37     int32_t groups;
38     int32_t format;
39     bool flag;
40 };
41 
42 const std::map<int32_t, DistributorParam> distributorParamList_ = {
43     {NETLINK_KOBJECT_UEVENT, {UEVENT_GROUP, NETLINK_FORMAT_ASCII, false}},
44     {NETLINK_ROUTE,
45      {RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR | RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE |
46           (1 << (RTNLGRP_ND_USEROPT - 1)),
47       NETLINK_FORMAT_BINARY, false}},
48     {NETLINK_NFLOG, {NFLOG_QUOTA_GROUP, NETLINK_FORMAT_BINARY, false}},
49     {NETLINK_NETFILTER, {0, NETLINK_FORMAT_BINARY_UNICAST, true}}};
50 
51 std::map<int32_t, std::unique_ptr<WrapperDistributor>> distributorMap_;
52 
CreateNetlinkDistributor(int32_t netlinkType,const DistributorParam & param)53 bool CreateNetlinkDistributor(int32_t netlinkType, const DistributorParam &param)
54 {
55     sockaddr_nl sockAddr;
56     int32_t size = BUFFER_SIZE;
57     int32_t on = 1;
58     int32_t socketFd;
59 
60     sockAddr.nl_family = AF_NETLINK;
61     sockAddr.nl_pid = 0;
62     sockAddr.nl_groups = param.groups;
63 
64     if ((socketFd = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, netlinkType)) < 0) {
65         NETNATIVE_LOGE("Creat socket for family failed NetLinkType is %{public}d: %{public}s = %{public}d",
66                        netlinkType, strerror(errno), errno);
67         return false;
68     }
69 
70     if (setsockopt(socketFd, SOL_SOCKET, SO_RCVBUFFORCE, &size, sizeof(size)) < 0 &&
71         setsockopt(socketFd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) < 0) {
72         NETNATIVE_LOGE("Set buffer for revieve msg failed the error is : %{public}d, EMSG: %{public}s", errno,
73                        strerror(errno));
74         close(socketFd);
75         return false;
76     }
77 
78     if (setsockopt(socketFd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) {
79         NETNATIVE_LOGE("Uevent socket SO_PASSCRED set failed dump for this: %{public}d, EMSG: %{public}s", errno,
80                        strerror(errno));
81         close(socketFd);
82         return false;
83     }
84 
85     if (bind(socketFd, reinterpret_cast<sockaddr *>(&sockAddr), sizeof(sockAddr)) < 0) {
86         NETNATIVE_LOGE("Bind netlink socket failed dumps is this : %{public}d, EMSG: %{public}s", errno,
87                        strerror(errno));
88         close(socketFd);
89         return false;
90     }
91     NETNATIVE_LOGI("CreateNetlinkDistributor netlinkType: %{public}d, socketFd: %{public}d", netlinkType, socketFd);
92     distributorMap_[netlinkType] = std::make_unique<WrapperDistributor>(socketFd, param.format);
93     return true;
94 }
95 } // namespace
96 
97 std::shared_ptr<std::vector<sptr<NetsysNative::INotifyCallback>>> NetlinkManager::callbacks_ =
98     std::make_shared<std::vector<sptr<NetsysNative::INotifyCallback>>>();
99 std::mutex NetlinkManager::linkCallbackMutex_;
NetlinkManager()100 NetlinkManager::NetlinkManager()
101 {
102     for (const auto &it : distributorParamList_) {
103         CreateNetlinkDistributor(it.first, it.second);
104     }
105     if (callbacks_ == nullptr) {
106         callbacks_ = std::make_shared<std::vector<sptr<NetsysNative::INotifyCallback>>>();
107     }
108 }
109 
~NetlinkManager()110 NetlinkManager::~NetlinkManager()
111 {
112     callbacks_->clear();
113     callbacks_ = nullptr;
114 }
115 
StartListener()116 int32_t NetlinkManager::StartListener()
117 {
118     for (auto &it : distributorMap_) {
119         if (it.second == nullptr) {
120             continue;
121         }
122         it.second->RegisterNetlinkCallbacks(callbacks_);
123         if (it.second->Start() != 0) {
124             NETNATIVE_LOGE("Start netlink listener failed");
125             return NetlinkResult::ERROR;
126         }
127     }
128     return NetlinkResult::OK;
129 }
130 
StopListener()131 int32_t NetlinkManager::StopListener()
132 {
133     for (auto &it : distributorMap_) {
134         if (it.second == nullptr) {
135             continue;
136         }
137         if (it.second->Stop() != 0) {
138             NETNATIVE_LOGE("Stop netlink listener failed");
139             return NetlinkResult::ERROR;
140         }
141     }
142     return NetlinkResult::OK;
143 }
144 
RegisterNetlinkCallback(sptr<NetsysNative::INotifyCallback> callback)145 int32_t NetlinkManager::RegisterNetlinkCallback(sptr<NetsysNative::INotifyCallback> callback)
146 {
147     if (callback == nullptr) {
148         NETNATIVE_LOGE("callback is nullptr");
149         return NetlinkResult::ERR_NULL_PTR;
150     }
151     std::lock_guard<std::mutex> lock(linkCallbackMutex_);
152     for (const auto &cb : *callbacks_) {
153         if (cb == callback) {
154             NETNATIVE_LOGI("callback is already registered");
155             return NetlinkResult::OK;
156         }
157     }
158     callbacks_->push_back(callback);
159     NETNATIVE_LOGI("callback is registered successfully current size is %{public}zu", callbacks_->size());
160     return NetlinkResult::OK;
161 }
162 
UnregisterNetlinkCallback(sptr<NetsysNative::INotifyCallback> callback)163 int32_t NetlinkManager::UnregisterNetlinkCallback(sptr<NetsysNative::INotifyCallback> callback)
164 {
165     if (callback == nullptr) {
166         NETNATIVE_LOGE("callback is nullptr");
167         return NetlinkResult::ERR_NULL_PTR;
168     }
169     std::lock_guard<std::mutex> lock(linkCallbackMutex_);
170     for (auto it = callbacks_->begin(); it != callbacks_->end(); ++it) {
171         if (*it == callback) {
172             callbacks_->erase(it);
173             NETNATIVE_LOGI("callback is unregistered successfully");
174             return NetlinkResult::OK;
175         }
176     }
177     NETNATIVE_LOGI("callback has not registered current callback number is %{public}zu", callbacks_->size());
178     return NetlinkResult::ERR_INVALID_PARAM;
179 }
180 } // namespace nmd
181 } // namespace OHOS
182