1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Portions copyright (C) 2017 Broadcom Limited
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 *     http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19#include "wifi_hal.h"
20#include "common.h"
21#include "sync.h"
22
23class WifiEvent
24{
25    /* TODO: remove this when nl headers are updated */
26    static const unsigned NL80211_ATTR_MAX_INTERNAL = 256;
27private:
28    struct nl_msg *mMsg;
29    struct genlmsghdr *mHeader;
30    struct nlattr *mAttributes[NL80211_ATTR_MAX_INTERNAL + 1];
31
32public:
33    WifiEvent(nl_msg *msg) {
34        mMsg = msg;
35        mHeader = NULL;
36        memset(mAttributes, 0, sizeof(mAttributes));
37    }
38    ~WifiEvent() {
39        /* don't destroy mMsg; it doesn't belong to us */
40    }
41
42    void log();
43
44    int parse();
45
46    genlmsghdr *header() {
47        return mHeader;
48    }
49
50    int get_cmd() {
51        return mHeader->cmd;
52    }
53
54    int get_vendor_id() {
55        return get_u32(NL80211_ATTR_VENDOR_ID);
56    }
57
58    int get_vendor_subcmd() {
59        return get_u32(NL80211_ATTR_VENDOR_SUBCMD);
60    }
61
62    void *get_vendor_data() {
63        return get_data(NL80211_ATTR_VENDOR_DATA);
64    }
65
66    int get_vendor_data_len() {
67        return get_len(NL80211_ATTR_VENDOR_DATA);
68    }
69
70    const char *get_cmdString();
71
72    nlattr ** attributes() {
73        return mAttributes;
74    }
75
76    nlattr *get_attribute(int attribute) {
77        return mAttributes[attribute];
78    }
79
80    uint8_t get_u8(int attribute) {
81        return mAttributes[attribute] ? nla_get_u8(mAttributes[attribute]) : 0;
82    }
83
84    uint16_t get_u16(int attribute) {
85        return mAttributes[attribute] ? nla_get_u16(mAttributes[attribute]) : 0;
86    }
87
88    uint32_t get_u32(int attribute) {
89        return mAttributes[attribute] ? nla_get_u32(mAttributes[attribute]) : 0;
90    }
91
92    uint64_t get_u64(int attribute) {
93        return mAttributes[attribute] ? nla_get_u64(mAttributes[attribute]) : 0;
94    }
95
96    int get_len(int attribute) {
97        return mAttributes[attribute] ? nla_len(mAttributes[attribute]) : 0;
98    }
99
100    void *get_data(int attribute) {
101        return mAttributes[attribute] ? nla_data(mAttributes[attribute]) : NULL;
102    }
103
104private:
105    WifiEvent(const WifiEvent&);        // hide copy constructor to prevent copies
106};
107
108class nl_iterator {
109    struct nlattr *pos;
110    int rem;
111public:
112    nl_iterator(struct nlattr *attr) {
113        pos = (struct nlattr *)nla_data(attr);
114        rem = nla_len(attr);
115    }
116    bool has_next() {
117        return nla_ok(pos, rem);
118    }
119    void next() {
120        pos = (struct nlattr *)nla_next(pos, &(rem));
121    }
122    struct nlattr *get() {
123        return pos;
124    }
125    uint16_t get_type() {
126        return pos->nla_type;
127    }
128    uint8_t get_u8() {
129        return nla_get_u8(pos);
130    }
131    uint16_t get_u16() {
132        return nla_get_u16(pos);
133    }
134    uint32_t get_u32() {
135        return nla_get_u32(pos);
136    }
137    uint64_t get_u64() {
138        return nla_get_u64(pos);
139    }
140    void* get_data() {
141        return nla_data(pos);
142    }
143    int get_len() {
144        return nla_len(pos);
145    }
146private:
147    nl_iterator(const nl_iterator&);    // hide copy constructor to prevent copies
148};
149
150class WifiRequest
151{
152private:
153    int mFamily;
154    int mIface;
155    struct nl_msg *mMsg;
156
157public:
158    WifiRequest(int family) {
159        mMsg = NULL;
160        mFamily = family;
161        mIface = -1;
162    }
163
164    WifiRequest(int family, int iface) {
165        mMsg = NULL;
166        mFamily = family;
167        mIface = iface;
168    }
169
170    ~WifiRequest() {
171        destroy();
172    }
173
174    void destroy() {
175        if (mMsg) {
176            nlmsg_free(mMsg);
177            mMsg = NULL;
178        }
179    }
180
181    nl_msg *getMessage() {
182        return mMsg;
183    }
184
185    /* Command assembly helpers */
186    int create(int family, uint8_t cmd, int flags, int hdrlen);
187    int create(uint8_t cmd) {
188        return create(mFamily, cmd, 0, 0);
189    }
190
191    int create(uint32_t id, int subcmd);
192
193    int put(int attribute, void *ptr, unsigned len) {
194        return nla_put(mMsg, attribute, len, ptr);
195    }
196    int put_u8(int attribute, uint8_t value) {
197        return nla_put(mMsg, attribute, sizeof(value), &value);
198    }
199    int put_u16(int attribute, uint16_t value) {
200        return nla_put(mMsg, attribute, sizeof(value), &value);
201    }
202    int put_u32(int attribute, uint32_t value) {
203        return nla_put(mMsg, attribute, sizeof(value), &value);
204    }
205    int put_u64(int attribute, uint64_t value) {
206        return nla_put(mMsg, attribute, sizeof(value), &value);
207    }
208    int put_string(int attribute, const char *value) {
209        return nla_put(mMsg, attribute, strlen(value) + 1, value);
210    }
211    int put_addr(int attribute, mac_addr value) {
212        return nla_put(mMsg, attribute, sizeof(mac_addr), value);
213    }
214
215    struct nlattr * attr_start(int attribute) {
216        return nla_nest_start(mMsg, attribute);
217    }
218    void attr_end(struct nlattr *attr) {
219        nla_nest_end(mMsg, attr);
220    }
221
222    int set_iface_id(int ifindex) {
223        return put_u32(NL80211_ATTR_IFINDEX, ifindex);
224    }
225private:
226    WifiRequest(const WifiRequest&);        // hide copy constructor to prevent copies
227
228};
229
230class WifiCommand
231{
232protected:
233    const char *mType;
234    hal_info *mInfo;
235    WifiRequest mMsg;
236    Condition mCondition;
237    wifi_request_id mId;
238    interface_info *mIfaceInfo;
239    int mRefs;
240public:
241    WifiCommand(const char *type, wifi_handle handle, wifi_request_id id)
242            : mType(type), mMsg(getHalInfo(handle)->nl80211_family_id), mId(id), mRefs(1)
243    {
244        mIfaceInfo = NULL;
245        mInfo = getHalInfo(handle);
246        // ALOGD("WifiCommand %p created, mInfo = %p, mIfaceInfo = %p", this, mInfo, mIfaceInfo);
247    }
248
249    WifiCommand(const char *type, wifi_interface_handle iface, wifi_request_id id)
250            : mType(type), mMsg(getHalInfo(iface)->nl80211_family_id, getIfaceInfo(iface)->id),
251            mId(id), mRefs(1)
252    {
253        mIfaceInfo = getIfaceInfo(iface);
254        mInfo = getHalInfo(iface);
255        // ALOGD("WifiCommand %p created, mInfo = %p, mIfaceInfo = %p", this, mInfo, mIfaceInfo);
256    }
257
258    virtual ~WifiCommand() {
259        // ALOGD("WifiCommand %p destroyed", this);
260    }
261
262    wifi_request_id id() {
263        return mId;
264    }
265
266    const char *getType() {
267        return mType;
268    }
269
270    virtual void addRef() {
271        int refs = __sync_add_and_fetch(&mRefs, 1);
272        // ALOGD("addRef: WifiCommand %p has %d references", this, refs);
273    }
274
275    virtual void releaseRef() {
276        int refs = __sync_sub_and_fetch(&mRefs, 1);
277        if (refs == 0) {
278            delete this;
279        } else {
280            // ALOGD("releaseRef: WifiCommand %p has %d references", this, refs);
281        }
282    }
283
284    virtual int create() {
285        /* by default there is no way to cancel */
286        ALOGD("WifiCommand %p can't be created", this);
287        return WIFI_ERROR_NOT_SUPPORTED;
288    }
289
290    virtual int cancel() {
291        /* by default there is no way to cancel */
292        return WIFI_ERROR_NOT_SUPPORTED;
293    }
294
295    int requestResponse();
296    int requestEvent(int cmd);
297    int requestVendorEvent(uint32_t id, int subcmd);
298    int requestResponse(WifiRequest& request);
299
300protected:
301    wifi_handle wifiHandle() {
302        return getWifiHandle(mInfo);
303    }
304
305    wifi_interface_handle ifaceHandle() {
306        return getIfaceHandle(mIfaceInfo);
307    }
308
309    int familyId() {
310        return mInfo->nl80211_family_id;
311    }
312
313    int ifaceId() {
314        return mIfaceInfo->id;
315    }
316
317    /* Override this method to parse reply and dig out data; save it in the object */
318    virtual int handleResponse(WifiEvent& reply) {
319        ALOGI("skipping a response");
320        return NL_SKIP;
321    }
322
323    /* Override this method to parse event and dig out data; save it in the object */
324    virtual int handleEvent(WifiEvent& event) {
325        ALOGI("skipping an event");
326        return NL_SKIP;
327    }
328
329    int registerHandler(int cmd) {
330        return wifi_register_handler(wifiHandle(), cmd, &event_handler, this);
331    }
332
333    void unregisterHandler(int cmd) {
334        wifi_unregister_handler(wifiHandle(), cmd);
335    }
336
337    int registerVendorHandler(uint32_t id, int subcmd) {
338        return wifi_register_vendor_handler(wifiHandle(), id, subcmd, &event_handler, this);
339    }
340
341    void unregisterVendorHandler(uint32_t id, int subcmd) {
342        wifi_unregister_vendor_handler(wifiHandle(), id, subcmd);
343    }
344
345private:
346    WifiCommand(const WifiCommand& );           // hide copy constructor to prevent copies
347
348    /* Event handling */
349    static int response_handler(struct nl_msg *msg, void *arg);
350
351    static int event_handler(struct nl_msg *msg, void *arg);
352
353    /* Other event handlers */
354    static int valid_handler(struct nl_msg *msg, void *arg);
355
356    static int ack_handler(struct nl_msg *msg, void *arg);
357
358    static int finish_handler(struct nl_msg *msg, void *arg);
359
360    static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg);
361};
362
363/* nl message processing macros (required to pass C++ type checks) */
364
365#define for_each_attr(pos, nla, rem) \
366    for (pos = (nlattr *)nla_data(nla), rem = nla_len(nla); \
367        nla_ok(pos, rem); \
368        pos = (nlattr *)nla_next(pos, &(rem)))
369
370