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