• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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