1 /*
2 * Copyright (c) 2025-2026 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 <cstddef>
17 #include <cerrno>
18 #include <cstring>
19 #include <fcntl.h>
20 #include <memory>
21 #include <sys/socket.h>
22 #include <unistd.h>
23 #include <sys/epoll.h>
24 #include "c/executor_task.h"
25 #include "securec.h"
26 #include "networkslice_submodule.h"
27 #include "netmgr_ext_log_wrapper.h"
28 #include "networkslice_service.h"
29 #include "networkslice_kernel_proxy.h"
30
31 namespace OHOS {
32 namespace NetManagerStandard {
33 namespace {
34 constexpr int32_t NETLINK_BUFFER_MAX_SIZE = 4080;
35 constexpr int32_t NETLINK_NETMANAGEREXT = 49;
36 constexpr int32_t NETWORKSLICE_REG_MSG = 0;
37 constexpr int32_t NETWORKSLICE_DATA_MSG = 1;
38 constexpr int32_t DEFAULT_SLEEP_TIME_US = 100000;
39 }
40
NetworkSliceKernelProxy()41 NetworkSliceKernelProxy::NetworkSliceKernelProxy()
42 {
43 NETMGR_EXT_LOG_I("NetworkSliceKernelProxy()");
44 }
45
~NetworkSliceKernelProxy()46 NetworkSliceKernelProxy::~NetworkSliceKernelProxy()
47 {
48 NETMGR_EXT_LOG_I("~NetworkSliceKernelProxy()");
49 StopRecvThread();
50 }
51
RegistHandler(NetworkSliceSubModule moduleId,NetworkSliceServiceBase * handler,const std::vector<int16_t> & msgTypeVec)52 void NetworkSliceKernelProxy::RegistHandler(NetworkSliceSubModule moduleId, NetworkSliceServiceBase* handler,
53 const std::vector<int16_t>& msgTypeVec)
54 {
55 if (handler == nullptr || msgTypeVec.empty()) {
56 NETMGR_EXT_LOG_E("invalid para");
57 return;
58 }
59
60 std::unique_lock<std::shared_timed_mutex> lock(mutex_);
61 if (moduleIdHandlerMap_.find(moduleId) == moduleIdHandlerMap_.end()) {
62 moduleIdHandlerMap_.insert(std::make_pair(moduleId, handler));
63 }
64
65 moduleIdMsgTypesMap_[moduleId].assign(msgTypeVec.begin(), msgTypeVec.end());
66 for (auto msgType : msgTypeVec) {
67 msgTypeModuleIdsMap_[msgType].insert(moduleId);
68 }
69 }
70
UnRegistHandler(NetworkSliceSubModule moduleId)71 void NetworkSliceKernelProxy::UnRegistHandler(NetworkSliceSubModule moduleId)
72 {
73 std::unique_lock<std::shared_timed_mutex> lock(mutex_);
74 auto iter = moduleIdHandlerMap_.find(moduleId);
75 if (iter != moduleIdHandlerMap_.end()) {
76 moduleIdHandlerMap_.erase(iter);
77 }
78
79 for (auto msgType : moduleIdMsgTypesMap_[moduleId]) {
80 msgTypeModuleIdsMap_[msgType].erase(moduleId);
81 }
82
83 moduleIdMsgTypesMap_.erase(moduleId);
84 }
85
StartNetlink()86 int32_t NetworkSliceKernelProxy::StartNetlink()
87 {
88 NETMGR_EXT_LOG_I("NetworkSlice StartNetlink start");
89 int32_t ret = -1;
90 if (netlinkSocket_ < 0) {
91 netlinkSocket_ = NetlinkInit();
92 if (netlinkSocket_ < 0) {
93 NETMGR_EXT_LOG_E("NetworkSlice StartNetlink: socket open failed");
94 return ret;
95 }
96 NETMGR_EXT_LOG_I("NetworkSlice socket connect:%{public}d", netlinkSocket_);
97 }
98 NetlinkInfo nlreq = {};
99 ret = SendMsgToKernel(NETWORKSLICE_REG_MSG, reinterpret_cast<nlmsghdr*>(&nlreq), NLMSG_LENGTH(0));
100 if (ret < 0) {
101 NETMGR_EXT_LOG_E("NetworkSlice StartNetlink: send msg failed, ret:%{public}d", ret);
102 }
103 NETMGR_EXT_LOG_I("NetworkSlice StartNetlink success");
104 return ret;
105 }
106
NetlinkInit()107 int32_t NetworkSliceKernelProxy::NetlinkInit()
108 {
109 std::unique_lock<std::shared_timed_mutex> lock(mutex_);
110 NETMGR_EXT_LOG_I("NetworkSlice NetlinkInit start");
111 int32_t fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_NETMANAGEREXT);
112 NETMGR_EXT_LOG_I("NetworkSlice NetlinkInit fd = %{public}d", fd);
113 if (fd < 0) {
114 NETMGR_EXT_LOG_E("NetlinkInitCant:create netlink socket,error:%{public}s\n", strerror(errno));
115 return -1;
116 }
117 int32_t ret = fcntl(fd, F_SETFL, O_NONBLOCK);
118 if (ret < 0) {
119 NETMGR_EXT_LOG_E("NetlinkInit:Error on fcntl:%{public}s", strerror(errno));
120 close(fd);
121 return -1;
122 }
123 sockaddr_nl ntlAddr = {};
124 ntlAddr.nl_family = AF_NETLINK;
125 ntlAddr.nl_pid = static_cast<uint32_t>(getprocpid());
126 NETMGR_EXT_LOG_I("Netmanager_ext PID:%{public}d", ntlAddr.nl_pid);
127 ntlAddr.nl_groups = 0;
128 if (bind(fd, reinterpret_cast<sockaddr*>(&ntlAddr), sizeof(ntlAddr)) != 0) {
129 NETMGR_EXT_LOG_E("NetlinkInit:Cant bind netlink socket\n");
130 close(fd);
131 return -1;
132 }
133 NETMGR_EXT_LOG_I("Netmanager_ext_NetlinkInit success");
134 return fd;
135 }
136
SendMsgToKernel(int32_t type,nlmsghdr * nlmsg,size_t nlmsgLen)137 int32_t NetworkSliceKernelProxy::SendMsgToKernel(int32_t type, nlmsghdr *nlmsg, size_t nlmsgLen)
138 {
139 NETMGR_EXT_LOG_I("NetworkSliceKernelProxy::SendMsgToKernel");
140 int32_t ret = -1;
141 if (!nlmsg) {
142 NETMGR_EXT_LOG_E("SendMsgToKernel:null nlmsg");
143 return ret;
144 }
145 if (netlinkSocket_ < 0) {
146 NETMGR_EXT_LOG_E("SendMsgToKernel:socket not open");
147 return ret;
148 }
149 if (nlmsgLen < sizeof(nlmsghdr)) {
150 NETMGR_EXT_LOG_E("SendMsgToKernel:nlmsgLen too short");
151 return ret;
152 }
153 nlmsg->nlmsg_len = nlmsgLen;
154 nlmsg->nlmsg_flags = 0;
155 nlmsg->nlmsg_type = type;
156 nlmsg->nlmsg_pid = static_cast<uint32_t>(getprocpid());
157 sockaddr_nl ntlAddr = {};
158 ntlAddr.nl_family = AF_NETLINK;
159 ntlAddr.nl_pid = 0;
160 ntlAddr.nl_groups = 0;
161 ret = sendto(netlinkSocket_, nlmsg, nlmsgLen, 0, reinterpret_cast<sockaddr*>(&ntlAddr),
162 sizeof(sockaddr_nl));
163 if (ret < 0) {
164 NETMGR_EXT_LOG_E("SendMsgToKernel: (%{public}d) failed", type);
165 }
166 return ret;
167 }
168
SendDataToKernel(KernelMsg & msgData)169 int32_t NetworkSliceKernelProxy::SendDataToKernel(KernelMsg &msgData)
170 {
171 NETMGR_EXT_LOG_I("SendDataToKernel");
172 int32_t ret = -1;
173 if (netlinkSocket_ < 0) {
174 netlinkSocket_ = NetlinkInit();
175 if (netlinkSocket_ < 0) {
176 NETMGR_EXT_LOG_E("SendDataToKernel:socket open fail");
177 return ret;
178 }
179 NETMGR_EXT_LOG_I("socket change:%{public}d", netlinkSocket_);
180 }
181
182 int16_t length = msgData.len;
183 if (length > NETLINK_BUFFER_MAX_SIZE || length <= 0) {
184 NETMGR_EXT_LOG_E("SendDataToKernel: length error");
185 return ret;
186 }
187 uint32_t len = length + sizeof(nlmsghdr);
188 std::unique_ptr<char[]> buffer = std::make_unique<char[]>(len);
189 if (!buffer) {
190 NETMGR_EXT_LOG_E("SendDataToKernel: malloc failed");
191 return ret;
192 }
193 const auto &pnlmsg = reinterpret_cast<NetlinkInfo*>(buffer.get());
194
195 if (memcpy_s(reinterpret_cast<char*>(pnlmsg->data), length, &msgData, length) != EOK) {
196 NETMGR_EXT_LOG_E("SendDataToKernel: memcpy_s error");
197 return ret;
198 }
199 ret = SendMsgToKernel(NETWORKSLICE_DATA_MSG, reinterpret_cast<nlmsghdr*>(pnlmsg), length + sizeof(nlmsghdr));
200 if (ret < 0) {
201 NETMGR_EXT_LOG_E("SendDataToKernel :send msg failed");
202 }
203 NETMGR_EXT_LOG_I("SendDataToKernel:send msg success");
204 return ret;
205 }
206
StartRecvThread()207 void NetworkSliceKernelProxy::StartRecvThread()
208 {
209 taskQos_ = ffrt_this_task_get_qos();
210 ffrt_epoll_ctl(taskQos_, EPOLL_CTL_ADD, netlinkSocket_, EPOLLIN, (void*)this,
211 NetworkSliceKernelProxy::RecvKernelData);
212 NETMGR_EXT_LOG_I("StartRecvThread success");
213 }
214
StopRecvThread()215 void NetworkSliceKernelProxy::StopRecvThread()
216 {
217 ffrt_epoll_ctl(taskQos_, EPOLL_CTL_DEL, netlinkSocket_, 0, nullptr, nullptr);
218 if (netlinkSocket_ >= 0) {
219 close(netlinkSocket_);
220 netlinkSocket_ = -1;
221 }
222 NETMGR_EXT_LOG_E("RecvThread: poll pthread_exit");
223 }
224
RecvKernelData(void * data,uint32_t event)225 void NetworkSliceKernelProxy::RecvKernelData(void *data, uint32_t event)
226 {
227 NETMGR_EXT_LOG_I("NetworkSliceKernelProxy RecvKernelData");
228 if (data == nullptr) {
229 return;
230 }
231 NetworkSliceKernelProxy *proxy = reinterpret_cast<NetworkSliceKernelProxy*>(data);
232
233 if (proxy->netlinkSocket_ < 0) {
234 NETMGR_EXT_LOG_E("Recvkerneldata: socket error!");
235 return;
236 }
237
238 uint32_t len = NETLINK_BUFFER_MAX_SIZE + sizeof(nlmsghdr);
239 std::unique_ptr<char[]> buffer = std::make_unique<char[]>(len);
240 if (!buffer) {
241 NETMGR_EXT_LOG_E("RecvKernelData: malloc failed");
242 return;
243 }
244 const auto &pnlmsg = reinterpret_cast<NetlinkInfo*>(buffer.get());
245 sockaddr_nl ntlAddr = {};
246 ntlAddr.nl_family = AF_NETLINK;
247 ntlAddr.nl_pid = 0;
248 ntlAddr.nl_groups = 0;
249 uint32_t ntlLen = sizeof(sockaddr_nl);
250
251 int32_t totalLen = recvfrom(proxy->netlinkSocket_, pnlmsg, (NETLINK_BUFFER_MAX_SIZE + sizeof(nlmsghdr)), 0,
252 (sockaddr *)&ntlAddr, (socklen_t *)&ntlLen);
253 int32_t dataLen = totalLen - static_cast<int32_t>(sizeof(nlmsghdr));
254 if (!proxy->IsValidDataLen(dataLen)) {
255 NETMGR_EXT_LOG_E("RecvKernelData: dataLen is invalid, %{public}d", dataLen);
256 return;
257 }
258
259 proxy->DispatchKernelMsg(&pnlmsg->data[0], dataLen);
260 }
261
DispatchKernelMsg(void * msg,int32_t dataLen)262 void NetworkSliceKernelProxy::DispatchKernelMsg(void *msg, int32_t dataLen)
263 {
264 NETMGR_EXT_LOG_I("NetworkSliceKernelProxy::DispatchKernelMsg datalen:%{public}d", dataLen);
265 if (!msg) {
266 NETMGR_EXT_LOG_E("NetworkSliceKernelProxy msg is null");
267 return;
268 }
269 DelayedSingleton<NetworkSliceService>::GetInstance()->RecvKernelData(msg, dataLen);
270 }
271
IsValidDataLen(int32_t dataLen)272 bool NetworkSliceKernelProxy::IsValidDataLen(int32_t dataLen)
273 {
274 return dataLen >= static_cast<int32_t>(sizeof(KernelMsg)) && dataLen <= NETLINK_BUFFER_MAX_SIZE;
275 }
276 } // namespace NetManagerStandard
277 } // namespace OHOS
278