1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
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 <cctype>
17 #include <cerrno>
18 #include <cstdint>
19 #include <fcntl.h>
20 #include <sys/socket.h>
21 #include <netlink/genl/genl.h>
22 #include <netlink/genl/family.h>
23 #include <netlink/genl/ctrl.h>
24 #include <linux/rtnetlink.h>
25 #include <netpacket/packet.h>
26 #include <linux/filter.h>
27 #include <linux/errqueue.h>
28 #include <linux/nl80211.h>
29 #include <linux/pkt_sched.h>
30 #include <netlink/object-api.h>
31 #include <netlink/netlink.h>
32 #include <netlink/socket.h>
33 #include <netlink/handlers.h>
34 #include "common.h"
35 #include "cpp_bindings.h"
36 #include "wifi_hal.h"
37
38 static pthread_mutex_t g_responseMutex;
39 static volatile bool g_isAvailableResponseLock;
40
InitResponseLock()41 void InitResponseLock()
42 {
43 pthread_mutex_init(&g_responseMutex, nullptr);
44 g_isAvailableResponseLock = true;
45 }
46
DestroyResponseLock()47 void DestroyResponseLock()
48 {
49 g_isAvailableResponseLock = false;
50 pthread_mutex_destroy(&g_responseMutex);
51 }
52
Parse()53 int WifiEvent::Parse()
54 {
55 if (mHeader != nullptr) {
56 return HAL_SUCCESS;
57 }
58 mHeader = reinterpret_cast<genlmsghdr *>(nlmsg_data(nlmsg_hdr(mMsg)));
59 int result = nla_parse(mAttributes, nL80211AttrMaxInternal, genlmsg_attrdata(mHeader, 0),
60 genlmsg_attrlen(mHeader, 0), NULL);
61 return result;
62 }
63
Create(int family,uint8_t cmd,int flags,int hdrlen)64 int WifiRequest::Create(int family, uint8_t cmd, int flags, int hdrlen)
65 {
66 Destroy();
67
68 mMsg = nlmsg_alloc();
69 if (mMsg != nullptr) {
70 genlmsg_put(mMsg, 0, 0, family, hdrlen, flags, cmd, 0); //pid = 0 seq = 0 version = 0
71 return HAL_SUCCESS;
72 } else {
73 return HAL_OUT_OF_MEMORY;
74 }
75 }
76
Create(uint32_t id,int subcmd)77 int WifiRequest::Create(uint32_t id, int subcmd)
78 {
79 int res = Create(NL80211_CMD_VENDOR);
80 if (res < 0) {
81 return res;
82 }
83
84 res = PutU32(NL80211_ATTR_VENDOR_ID, id);
85 if (res < 0) {
86 return res;
87 }
88
89 res = PutU32(NL80211_ATTR_VENDOR_SUBCMD, subcmd);
90 if (res < 0) {
91 return res;
92 }
93
94 if (mIface != -1) {
95 res = SetIfaceId(mIface);
96 }
97
98 return res;
99 }
100
NoSeqCheck(struct nl_msg * msg,void * arg)101 static int NoSeqCheck(struct nl_msg *msg, void *arg)
102 {
103 return NL_OK;
104 }
105
RequestResponse()106 int WifiCommand::RequestResponse()
107 {
108 int err = Create(); /* create the message */
109 if (err < 0) {
110 return err;
111 }
112
113 return RequestResponse(mMsg);
114 }
115
RequestResponse(WifiRequest & request)116 int WifiCommand::RequestResponse(WifiRequest& request)
117 {
118 if (!g_isAvailableResponseLock || !mInfo || !mInfo->cmdSock) {
119 return 0;
120 }
121 pthread_mutex_lock(&g_responseMutex);
122 int err = 0;
123
124 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
125 if (!cb) {
126 HDF_LOGE("nl_cb_alloc fail");
127 goto out;
128 }
129
130 err = nl_send_auto_complete(mInfo->cmdSock, request.GetMessage()); /* send message */
131 if (err < 0) {
132 HDF_LOGE("nl_send_auto_complete fail");
133 goto out;
134 }
135 err = 1;
136
137 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, NoSeqCheck, NULL);
138 nl_cb_err(cb, NL_CB_CUSTOM, ErrorHandler, &err);
139 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, FinishHandler, &err);
140 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, AckHandler, &err);
141 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, ResponseHandler, this);
142
143 while (err > 0) { /* Wait for reply */
144 int res = nl_recvmsgs(mInfo->cmdSock, cb);
145 if (res) {
146 HDF_LOGE("nl80211: %{public}s->nl_recvmsgs failed: %{public}d", __func__, res);
147 if (res == -NLE_NOMEM) {
148 break;
149 }
150 }
151 }
152 out:
153 nl_cb_put(cb);
154 pthread_mutex_unlock(&g_responseMutex);
155 return err;
156 }
157
RequestEvent(int cmd)158 int WifiCommand::RequestEvent(int cmd)
159 {
160 HDF_LOGD("requesting event %{public}d", cmd);
161 int res = WifiRegisterHandler(WifiHandle(), cmd, EventHandler, this);
162 if (res < 0) {
163 return res;
164 }
165
166 res = Create(); /* create the message */
167 if (res < 0) {
168 goto out;
169 }
170
171 HDF_LOGD("waiting for response %{public}d", cmd);
172
173 res = nl_send_auto_complete(mInfo->cmdSock, mMsg.GetMessage()); /* send message */
174 if (res < 0) {
175 goto out;
176 }
177
178 HDF_LOGD("waiting for event %{public}d", cmd);
179 res = mCondition.Wait();
180 if (res < 0) {
181 goto out;
182 }
183
184 out:
185 WifiUnregisterHandler(WifiHandle(), cmd);
186 return res;
187 }
188
RequestVendorEvent(uint32_t id,int subcmd)189 int WifiCommand::RequestVendorEvent(uint32_t id, int subcmd)
190 {
191 int res = WifiRegisterVendorHandler(WifiHandle(), id, subcmd, EventHandler, this);
192 if (res < 0) {
193 return res;
194 }
195
196 res = Create(); /* create the message */
197 if (res < 0) {
198 goto out;
199 }
200
201 res = nl_send_auto_complete(mInfo->cmdSock, mMsg.GetMessage()); /* send message */
202 if (res < 0) {
203 goto out;
204 }
205
206 res = mCondition.Wait();
207 if (res < 0) {
208 goto out;
209 }
210
211 out:
212 WifiUnregisterVendorHandler(WifiHandle(), id, subcmd);
213 return res;
214 }
215
216 /* Event handlers */
ResponseHandler(struct nl_msg * msg,void * arg)217 int WifiCommand::ResponseHandler(struct nl_msg *msg, void *arg)
218 {
219 WifiCommand *cmd = (WifiCommand *)arg;
220 WifiEvent reply(msg);
221 int res = reply.Parse();
222 if (res < 0) {
223 HDF_LOGE("Failed to Parse reply message = %{public}d", res);
224 return NL_SKIP;
225 } else {
226 return cmd->HandleResponse(reply);
227 }
228 }
229
EventHandler(struct nl_msg * msg,void * arg)230 int WifiCommand::EventHandler(struct nl_msg *msg, void *arg)
231 {
232 WifiCommand *cmd = reinterpret_cast<WifiCommand *>(arg);
233 WifiEvent event(msg);
234 int res = event.Parse();
235 if (res < 0) {
236 HDF_LOGE("Failed to Parse event = %{public}d", res);
237 res = NL_SKIP;
238 } else {
239 res = cmd->HandleEvent(event);
240 }
241
242 cmd->mCondition.Signal();
243 return res;
244 }
245
ValidHandler(struct nl_msg * msg,void * arg)246 int WifiCommand::ValidHandler(struct nl_msg *msg, void *arg)
247 {
248 int *err = (int *)arg;
249 *err = 0;
250 return NL_SKIP;
251 }
252
253 /* Other event handlers */
AckHandler(struct nl_msg * msg,void * arg)254 int WifiCommand::AckHandler(struct nl_msg *msg, void *arg)
255 {
256 int *err = (int *)arg;
257 *err = 0;
258 return NL_STOP;
259 }
260
FinishHandler(struct nl_msg * msg,void * arg)261 int WifiCommand::FinishHandler(struct nl_msg *msg, void *arg)
262 {
263 int *ret = (int *)arg;
264 *ret = 0;
265 return NL_SKIP;
266 }
267
ErrorHandler(struct sockaddr_nl * nla,struct nlmsgerr * err,void * arg)268 int WifiCommand::ErrorHandler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
269 {
270 int *ret = (int *)arg;
271 *ret = err->error;
272 return NL_SKIP;
273 }