1
2 /*
3 * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <cstdint>
18 #include <fcntl.h>
19 #include <sys/socket.h>
20 #include <netlink/genl/genl.h>
21 #include <netlink/genl/family.h>
22 #include <netlink/genl/ctrl.h>
23 #include <linux/rtnetlink.h>
24 #include <netpacket/packet.h>
25 #include <linux/filter.h>
26 #include <linux/errqueue.h>
27
28 #include <linux/pkt_sched.h>
29 #include <netlink/object-api.h>
30 #include <netlink/netlink.h>
31 #include <netlink/socket.h>
32 #include <netlink/handlers.h>
33
34 #include "wifi_hal.h"
35 #include "common.h"
36 #include "cpp_bindings.h"
37 #include "securec.h"
38
39 #define MAX_CMD_SIZE 64
40
41 /* test mode flag for halutil only */
42 bool g_halutilMode = false;
43 static std::shared_mutex g_rwMutex;
44
ReadLockData()45 std::shared_lock<std::shared_mutex> ReadLockData()
46 {
47 return std::shared_lock<std::shared_mutex>{g_rwMutex};
48 }
49
WriteLock()50 std::unique_lock<std::shared_mutex> WriteLock()
51 {
52 return std::unique_lock<std::shared_mutex>{g_rwMutex};
53 }
GetIfaceInfo(wifiInterfaceHandle handle)54 InterfaceInfo *GetIfaceInfo(wifiInterfaceHandle handle)
55 {
56 return (InterfaceInfo *)handle;
57 }
58
GetWifiHandle(wifiInterfaceHandle handle)59 wifiHandle GetWifiHandle(wifiInterfaceHandle handle)
60 {
61 InterfaceInfo *info = GetIfaceInfo(handle);
62 if (info != nullptr) {
63 return GetIfaceInfo(handle)->handle;
64 }
65 return nullptr;
66 }
67
GetHalInfo(wifiHandle handle)68 HalInfo *GetHalInfo(wifiHandle handle)
69 {
70 return (HalInfo *)handle;
71 }
72
GetHalInfo(wifiInterfaceHandle handle)73 HalInfo *GetHalInfo(wifiInterfaceHandle handle)
74 {
75 return GetHalInfo(GetWifiHandle(handle));
76 }
77
GetWifiHandle(HalInfo * info)78 wifiHandle GetWifiHandle(HalInfo *info)
79 {
80 return (wifiHandle)info;
81 }
82
GetIfaceHandle(InterfaceInfo * info)83 wifiInterfaceHandle GetIfaceHandle(InterfaceInfo *info)
84 {
85 return (wifiInterfaceHandle)info;
86 }
87
WifiRegisterHandler(wifiHandle handle,int cmd,nl_recvmsg_msg_cb_t func,void * arg)88 WifiError WifiRegisterHandler(wifiHandle handle, int cmd, nl_recvmsg_msg_cb_t func, void *arg)
89 {
90 HalInfo *info = (HalInfo *)handle;
91 pthread_mutex_lock(&info->cbLock);
92 WifiError result = HAL_OUT_OF_MEMORY;
93
94 if (info->numEventCb < info->allocEventCb) {
95 info->eventCb[info->numEventCb].nlCmd = cmd;
96 info->eventCb[info->numEventCb].vendorId = 0;
97 info->eventCb[info->numEventCb].vendorSubcmd = 0;
98 info->eventCb[info->numEventCb].cbFunc = func;
99 info->eventCb[info->numEventCb].cbArg = arg;
100 HDF_LOGD("Successfully added event handler %{public}p:%{public}p for command %{public}d at %{public}d",
101 arg, func, cmd, info->numEventCb);
102 info->numEventCb++;
103 result = HAL_SUCCESS;
104 }
105
106 pthread_mutex_unlock(&info->cbLock);
107 return result;
108 }
109
WifiRegisterVendorHandler(wifiHandle handle,uint32_t id,int subcmd,nl_recvmsg_msg_cb_t func,void * arg)110 WifiError WifiRegisterVendorHandler(wifiHandle handle,
111 uint32_t id, int subcmd, nl_recvmsg_msg_cb_t func, void *arg)
112 {
113 HalInfo *info = (HalInfo *)handle;
114 pthread_mutex_lock(&info->cbLock);
115 WifiError result = HAL_OUT_OF_MEMORY;
116 if (info->numEventCb < info->allocEventCb) {
117 int i = 0;
118 bool isUpdate = false;
119 for (i = 0; i < info->numEventCb; i++) {
120 if ((info->eventCb[i].nlCmd == NL80211_CMD_VENDOR) &&
121 (info->eventCb[i].vendorId == id) &&
122 (info->eventCb[i].vendorSubcmd == subcmd)) {
123 isUpdate = true;
124 break;
125 }
126 }
127 if (isUpdate) {
128 info->eventCb[i].cbFunc = func;
129 info->eventCb[i].cbArg = arg;
130 } else {
131 info->eventCb[info->numEventCb].nlCmd = NL80211_CMD_VENDOR;
132 info->eventCb[info->numEventCb].vendorId = id;
133 info->eventCb[info->numEventCb].vendorSubcmd = subcmd;
134 info->eventCb[info->numEventCb].cbFunc = func;
135 info->eventCb[info->numEventCb].cbArg = arg;
136 info->numEventCb++;
137 }
138 HDF_LOGI("%{public}s ""event handler for vendor 0x%{public}0x and subcmd 0x%{public}0x at %{public}d",
139 isUpdate ? "Updated" : "Added", id, subcmd, info->numEventCb);
140 result = HAL_SUCCESS;
141 }
142
143 pthread_mutex_unlock(&info->cbLock);
144 return result;
145 }
146
WifiUnregisterHandler(wifiHandle handle,int cmd)147 void WifiUnregisterHandler(wifiHandle handle, int cmd)
148 {
149 HalInfo *info = (HalInfo *)handle;
150
151 if (cmd == NL80211_CMD_VENDOR) {
152 HDF_LOGE("Must use WifiUnregisterVendorHandler to remove vendor handlers");
153 return;
154 }
155
156 pthread_mutex_lock(&info->cbLock);
157
158 for (int i = 0; i < info->numEventCb; i++) {
159 if (info->eventCb[i].nlCmd == cmd) {
160 HDF_LOGD("Successfully removed event handler for cmd = 0x%{public}0x from %{public}d",
161 cmd, i);
162
163 if (memmove_s(&info->eventCb[i], (info->numEventCb - i) * sizeof(CbInfo), &info->eventCb[i + 1],
164 (info->numEventCb - i - 1) * sizeof(CbInfo)) != EOK) {
165 break;
166 }
167 info->numEventCb--;
168 break;
169 }
170 }
171
172 pthread_mutex_unlock(&info->cbLock);
173 }
174
WifiUnregisterVendorHandlerWithoutLock(wifiHandle handle,uint32_t id,int subcmd)175 void WifiUnregisterVendorHandlerWithoutLock(wifiHandle handle, uint32_t id, int subcmd)
176 {
177 HalInfo *info = (HalInfo *)handle;
178
179 for (int i = 0; i < info->numEventCb; i++) {
180 if (info->eventCb[i].nlCmd == NL80211_CMD_VENDOR &&
181 info->eventCb[i].vendorId == id &&
182 info->eventCb[i].vendorSubcmd == subcmd) {
183 HDF_LOGI("Successfully removed event handler for vendor 0x%{public}0x,"
184 "subcmd 0x%{public}0x from %{public}d", id, subcmd, i);
185 if (memmove_s(&info->eventCb[i], (info->numEventCb - i) * sizeof(CbInfo), &info->eventCb[i + 1],
186 (info->numEventCb - i - 1) * sizeof(CbInfo)) != EOK) {
187 break;
188 }
189 break;
190 }
191 }
192 }
193
WifiUnregisterVendorHandler(wifiHandle handle,uint32_t id,int subcmd)194 void WifiUnregisterVendorHandler(wifiHandle handle, uint32_t id, int subcmd)
195 {
196 HalInfo *info = (HalInfo *)handle;
197
198 pthread_mutex_lock(&info->cbLock);
199 WifiUnregisterVendorHandlerWithoutLock(handle, id, subcmd);
200 pthread_mutex_unlock(&info->cbLock);
201 }
202
203
WifiRegisterCmd(wifiHandle handle,int id,WifiCommand * cmd)204 WifiError WifiRegisterCmd(wifiHandle handle, int id, WifiCommand *cmd)
205 {
206 HalInfo *info = (HalInfo *)handle;
207
208 HDF_LOGD("registering command %{public}d", id);
209
210 WifiError result = HAL_OUT_OF_MEMORY;
211 if (info == nullptr) {
212 HDF_LOGE("wifi info is null");
213 return result;
214 }
215 if (info->numCmd < info->allocCmd) {
216 info->cmd[info->numCmd].id = id;
217 info->cmd[info->numCmd].cmd = cmd;
218 HDF_LOGD("Successfully added command %{public}d: at %{public}d", id, info->numCmd);
219 info->numCmd++;
220 result = HAL_SUCCESS;
221 } else {
222 HDF_LOGE("Failed to add command %{public}d: at %{public}d, reached MAX limit %{public}d",
223 id, info->numCmd, info->allocCmd);
224 }
225
226 return result;
227 }
228
WifiUnregisterCmd(wifiHandle handle,int id)229 WifiCommand *WifiUnregisterCmd(wifiHandle handle, int id)
230 {
231 HalInfo *info = (HalInfo *)handle;
232
233 HDF_LOGD("un-registering command %{public}d", id);
234
235 WifiCommand *cmd = nullptr;
236
237 if (info->numCmd > MAX_CMD_SIZE) {
238 HDF_LOGE("invilid cmd size");
239 return cmd;
240 }
241 for (int i = 0; i < info->numCmd; i++) {
242 if (info->cmd[i].id == id) {
243 cmd = info->cmd[i].cmd;
244 if (memmove_s(&info->cmd[i], (info->numCmd - i) * sizeof(CmdInfo), &info->cmd[i + 1],
245 (info->numCmd - i - 1) * sizeof(CmdInfo)) != EOK) {
246 break;
247 }
248 info->numCmd--;
249 HDF_LOGD("Successfully removed command %{public}d: from %{public}d", id, i);
250 break;
251 }
252 }
253
254 if (!cmd) {
255 HDF_LOGI("Failed to remove command %{public}d", id);
256 }
257
258 return cmd;
259 }
260
WifiUnregisterCmd(wifiHandle handle,WifiCommand * cmd)261 void WifiUnregisterCmd(wifiHandle handle, WifiCommand *cmd)
262 {
263 HalInfo *info = (HalInfo *)handle;
264
265 for (int i = 0; i < info->numCmd; i++) {
266 if (info->cmd[i].cmd == cmd) {
267 int id = info->cmd[i].id;
268 if (memmove_s(&info->cmd[i], (info->numCmd - i) * sizeof(CmdInfo), &info->cmd[i + 1],
269 (info->numCmd - i - 1) * sizeof(CmdInfo)) != EOK) {
270 break;
271 }
272 info->numCmd--;
273 HDF_LOGD("Successfully removed command %{public}d: from %{public}d", id, i);
274 break;
275 }
276 }
277 }
278
SetHautilMode(bool halutilMode)279 void SetHautilMode(bool halutilMode)
280 {
281 g_halutilMode = halutilMode;
282 }
GetGHalutilMode()283 bool GetGHalutilMode()
284 {
285 return g_halutilMode;
286 }
287