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 for command %{public}d at %{public}d", cmd, info->numEventCb);
101 info->numEventCb++;
102 result = HAL_SUCCESS;
103 }
104
105 pthread_mutex_unlock(&info->cbLock);
106 return result;
107 }
108
WifiRegisterVendorHandler(wifiHandle handle,uint32_t id,int subcmd,nl_recvmsg_msg_cb_t func,void * arg)109 WifiError WifiRegisterVendorHandler(wifiHandle handle,
110 uint32_t id, int subcmd, nl_recvmsg_msg_cb_t func, void *arg)
111 {
112 HalInfo *info = (HalInfo *)handle;
113 pthread_mutex_lock(&info->cbLock);
114 WifiError result = HAL_OUT_OF_MEMORY;
115 if (info->numEventCb < info->allocEventCb) {
116 int i = 0;
117 bool isUpdate = false;
118 for (i = 0; i < info->numEventCb; i++) {
119 if ((info->eventCb[i].nlCmd == NL80211_CMD_VENDOR) &&
120 (info->eventCb[i].vendorId == id) &&
121 (info->eventCb[i].vendorSubcmd == subcmd)) {
122 isUpdate = true;
123 break;
124 }
125 }
126 if (isUpdate) {
127 info->eventCb[i].cbFunc = func;
128 info->eventCb[i].cbArg = arg;
129 } else {
130 info->eventCb[info->numEventCb].nlCmd = NL80211_CMD_VENDOR;
131 info->eventCb[info->numEventCb].vendorId = id;
132 info->eventCb[info->numEventCb].vendorSubcmd = subcmd;
133 info->eventCb[info->numEventCb].cbFunc = func;
134 info->eventCb[info->numEventCb].cbArg = arg;
135 info->numEventCb++;
136 }
137 HDF_LOGI("%{public}s ""event handler for vendor 0x%{public}0x and subcmd 0x%{public}0x at %{public}d",
138 isUpdate ? "Updated" : "Added", id, subcmd, info->numEventCb);
139 result = HAL_SUCCESS;
140 }
141
142 pthread_mutex_unlock(&info->cbLock);
143 return result;
144 }
145
WifiUnregisterHandler(wifiHandle handle,int cmd)146 void WifiUnregisterHandler(wifiHandle handle, int cmd)
147 {
148 HalInfo *info = (HalInfo *)handle;
149
150 if (cmd == NL80211_CMD_VENDOR) {
151 HDF_LOGE("Must use WifiUnregisterVendorHandler to remove vendor handlers");
152 return;
153 }
154
155 pthread_mutex_lock(&info->cbLock);
156
157 for (int i = 0; i < info->numEventCb; i++) {
158 if (info->eventCb[i].nlCmd == cmd) {
159 HDF_LOGD("Successfully removed event handler for cmd = 0x%{public}0x from %{public}d",
160 cmd, i);
161
162 if (memmove_s(&info->eventCb[i], (info->numEventCb - i) * sizeof(CbInfo), &info->eventCb[i + 1],
163 (info->numEventCb - i - 1) * sizeof(CbInfo)) != EOK) {
164 break;
165 }
166 info->numEventCb--;
167 break;
168 }
169 }
170
171 pthread_mutex_unlock(&info->cbLock);
172 }
173
WifiUnregisterVendorHandlerWithoutLock(wifiHandle handle,uint32_t id,int subcmd)174 void WifiUnregisterVendorHandlerWithoutLock(wifiHandle handle, uint32_t id, int subcmd)
175 {
176 HalInfo *info = (HalInfo *)handle;
177
178 for (int i = 0; i < info->numEventCb; i++) {
179 if (info->eventCb[i].nlCmd == NL80211_CMD_VENDOR &&
180 info->eventCb[i].vendorId == id &&
181 info->eventCb[i].vendorSubcmd == subcmd) {
182 HDF_LOGI("Successfully removed event handler for vendor 0x%{public}0x,"
183 "subcmd 0x%{public}0x from %{public}d", id, subcmd, i);
184 if (memmove_s(&info->eventCb[i], (info->numEventCb - i) * sizeof(CbInfo), &info->eventCb[i + 1],
185 (info->numEventCb - i - 1) * sizeof(CbInfo)) != EOK) {
186 break;
187 }
188 break;
189 }
190 }
191 }
192
WifiUnregisterVendorHandler(wifiHandle handle,uint32_t id,int subcmd)193 void WifiUnregisterVendorHandler(wifiHandle handle, uint32_t id, int subcmd)
194 {
195 HalInfo *info = (HalInfo *)handle;
196
197 pthread_mutex_lock(&info->cbLock);
198 WifiUnregisterVendorHandlerWithoutLock(handle, id, subcmd);
199 pthread_mutex_unlock(&info->cbLock);
200 }
201
202
WifiRegisterCmd(wifiHandle handle,int id,WifiCommand * cmd)203 WifiError WifiRegisterCmd(wifiHandle handle, int id, WifiCommand *cmd)
204 {
205 HalInfo *info = (HalInfo *)handle;
206
207 HDF_LOGD("registering command %{public}d", id);
208
209 WifiError result = HAL_OUT_OF_MEMORY;
210 if (info == nullptr) {
211 HDF_LOGE("wifi info is null");
212 return result;
213 }
214 if (info->numCmd < info->allocCmd) {
215 info->cmd[info->numCmd].id = id;
216 info->cmd[info->numCmd].cmd = cmd;
217 HDF_LOGD("Successfully added command %{public}d: at %{public}d", id, info->numCmd);
218 info->numCmd++;
219 result = HAL_SUCCESS;
220 } else {
221 HDF_LOGE("Failed to add command %{public}d: at %{public}d, reached MAX limit %{public}d",
222 id, info->numCmd, info->allocCmd);
223 }
224
225 return result;
226 }
227
WifiUnregisterCmd(wifiHandle handle,int id)228 WifiCommand *WifiUnregisterCmd(wifiHandle handle, int id)
229 {
230 HalInfo *info = (HalInfo *)handle;
231
232 HDF_LOGD("un-registering command %{public}d", id);
233
234 WifiCommand *cmd = nullptr;
235
236 if (info->numCmd > MAX_CMD_SIZE) {
237 HDF_LOGE("invilid cmd size");
238 return cmd;
239 }
240 for (int i = 0; i < info->numCmd; i++) {
241 if (info->cmd[i].id == id) {
242 cmd = info->cmd[i].cmd;
243 if (memmove_s(&info->cmd[i], (info->numCmd - i) * sizeof(CmdInfo), &info->cmd[i + 1],
244 (info->numCmd - i - 1) * sizeof(CmdInfo)) != EOK) {
245 break;
246 }
247 info->numCmd--;
248 HDF_LOGD("Successfully removed command %{public}d: from %{public}d", id, i);
249 break;
250 }
251 }
252
253 if (!cmd) {
254 HDF_LOGI("Failed to remove command %{public}d", id);
255 }
256
257 return cmd;
258 }
259
WifiUnregisterCmd(wifiHandle handle,WifiCommand * cmd)260 void WifiUnregisterCmd(wifiHandle handle, WifiCommand *cmd)
261 {
262 HalInfo *info = (HalInfo *)handle;
263
264 for (int i = 0; i < info->numCmd; i++) {
265 if (info->cmd[i].cmd == cmd) {
266 int id = info->cmd[i].id;
267 if (memmove_s(&info->cmd[i], (info->numCmd - i) * sizeof(CmdInfo), &info->cmd[i + 1],
268 (info->numCmd - i - 1) * sizeof(CmdInfo)) != EOK) {
269 break;
270 }
271 info->numCmd--;
272 HDF_LOGD("Successfully removed command %{public}d: from %{public}d", id, i);
273 break;
274 }
275 }
276 }
277
SetHautilMode(bool halutilMode)278 void SetHautilMode(bool halutilMode)
279 {
280 g_halutilMode = halutilMode;
281 }
GetGHalutilMode()282 bool GetGHalutilMode()
283 {
284 return g_halutilMode;
285 }
286