1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
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 <stdint.h>
18 #include <errno.h>
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 
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-private/object-api.h>
34 #include <netlink-private/types.h>
35 
36 #include "nl80211_copy.h"
37 
38 #include <dirent.h>
39 #include <net/if.h>
40 #include <netinet/in.h>
41 #include <cld80211_lib.h>
42 
43 #include <sys/types.h>
44 #include "list.h"
45 #include <unistd.h>
46 
47 #include "sync.h"
48 
49 #define LOG_TAG  "WifiHAL"
50 
51 #include "wifi_hal.h"
52 #include "wifi_hal_ctrl.h"
53 #include "common.h"
54 #include "cpp_bindings.h"
55 #include "ifaceeventhandler.h"
56 #include "wifiloggercmd.h"
57 
58 /*
59  BUGBUG: normally, libnl allocates ports for all connections it makes; but
60  being a static library, it doesn't really know how many other netlink
61  connections are made by the same process, if connections come from different
62  shared libraries. These port assignments exist to solve that
63  problem - temporarily. We need to fix libnl to try and allocate ports across
64  the entire process.
65  */
66 
67 #define WIFI_HAL_CMD_SOCK_PORT       644
68 #define WIFI_HAL_EVENT_SOCK_PORT     645
69 
70 #define MAX_HW_VER_LENGTH 100
71 /*
72  * Defines for wifi_wait_for_driver_ready()
73  * Specify durations between polls and max wait time
74  */
75 #define POLL_DRIVER_DURATION_US (100000)
76 #define POLL_DRIVER_MAX_TIME_MS (10000)
77 
78 static int attach_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg);
79 
80 static int dettach_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg);
81 
82 static int register_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg, int attach);
83 
84 static int send_nl_data(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg);
85 
86 static int internal_pollin_handler(wifi_handle handle, struct nl_sock *sock);
87 
88 static void internal_event_handler_app(wifi_handle handle, int events,
89                                        struct ctrl_sock *sock);
90 
91 static void internal_event_handler(wifi_handle handle, int events,
92                                    struct nl_sock *sock);
93 static int internal_valid_message_handler(nl_msg *msg, void *arg);
94 static int user_sock_message_handler(nl_msg *msg, void *arg);
95 static int wifi_get_multicast_id(wifi_handle handle, const char *name,
96         const char *group);
97 static int wifi_add_membership(wifi_handle handle, const char *group);
98 static wifi_error wifi_init_interfaces(wifi_handle handle);
99 static wifi_error wifi_set_packet_filter(wifi_interface_handle iface,
100                                          const u8 *program, u32 len);
101 static wifi_error wifi_get_packet_filter_capabilities(wifi_interface_handle handle,
102                                               u32 *version, u32 *max_len);
103 static wifi_error wifi_read_packet_filter(wifi_interface_handle handle,
104                                    u32 src_offset, u8 *host_dst, u32 length);
105 static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface,
106                                             u8 enable);
107 wifi_error wifi_get_wake_reason_stats(wifi_interface_handle iface,
108                              WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt);
109 
110 /* Initialize/Cleanup */
111 
wifi_get_iface_handle(wifi_handle handle,char * name)112 wifi_interface_handle wifi_get_iface_handle(wifi_handle handle, char *name)
113 {
114     hal_info *info = (hal_info *)handle;
115     for (int i=0;i<info->num_interfaces;i++)
116     {
117         if (!strcmp(info->interfaces[i]->name, name))
118         {
119             return ((wifi_interface_handle )(info->interfaces)[i]);
120         }
121     }
122     return NULL;
123 }
124 
wifi_socket_set_local_port(struct nl_sock * sock,uint32_t port)125 void wifi_socket_set_local_port(struct nl_sock *sock, uint32_t port)
126 {
127     /* Release local port pool maintained by libnl and assign a own port
128      * identifier to the socket.
129      */
130     nl_socket_set_local_port(sock, ((uint32_t)getpid() & 0x3FFFFFU) | (port << 22));
131 }
132 
wifi_create_nl_socket(int port,int protocol)133 static nl_sock * wifi_create_nl_socket(int port, int protocol)
134 {
135     // ALOGI("Creating socket");
136     struct nl_sock *sock = nl_socket_alloc();
137     if (sock == NULL) {
138         ALOGE("Failed to create NL socket");
139         return NULL;
140     }
141 
142     wifi_socket_set_local_port(sock, port);
143 
144     if (nl_connect(sock, protocol)) {
145         ALOGE("Could not connect handle");
146         nl_socket_free(sock);
147         return NULL;
148     }
149 
150     return sock;
151 }
152 
wifi_create_ctrl_socket(hal_info * info)153 void wifi_create_ctrl_socket(hal_info *info)
154 {
155 #ifdef ANDROID
156    struct group *grp_wifi;
157    gid_t gid_wifi;
158    struct passwd *pwd_system;
159    uid_t uid_system;
160 #endif
161 
162     int flags;
163 
164     info->wifihal_ctrl_sock.s = socket(PF_UNIX, SOCK_DGRAM, 0);
165 
166     if (info->wifihal_ctrl_sock.s < 0) {
167         ALOGE("socket(PF_UNIX): %s", strerror(errno));
168         return;
169     }
170     memset(&info->wifihal_ctrl_sock.local, 0, sizeof(info->wifihal_ctrl_sock.local));
171 
172     info->wifihal_ctrl_sock.local.sun_family = AF_UNIX;
173 
174     snprintf(info->wifihal_ctrl_sock.local.sun_path,
175              sizeof(info->wifihal_ctrl_sock.local.sun_path), "%s", WIFI_HAL_CTRL_IFACE);
176 
177     if (bind(info->wifihal_ctrl_sock.s, (struct sockaddr *) &info->wifihal_ctrl_sock.local,
178              sizeof(info->wifihal_ctrl_sock.local)) < 0) {
179         ALOGD("ctrl_iface bind(PF_UNIX) failed: %s",
180                strerror(errno));
181         if (connect(info->wifihal_ctrl_sock.s, (struct sockaddr *) &info->wifihal_ctrl_sock.local,
182                     sizeof(info->wifihal_ctrl_sock.local)) < 0) {
183                 ALOGD("ctrl_iface exists, but does not"
184                       " allow connections - assuming it was left"
185                       "over from forced program termination");
186                 if (unlink(info->wifihal_ctrl_sock.local.sun_path) < 0) {
187                    ALOGE("Could not unlink existing ctrl_iface socket '%s': %s",
188                           info->wifihal_ctrl_sock.local.sun_path, strerror(errno));
189                    goto out;
190 
191                 }
192                 if (bind(info->wifihal_ctrl_sock.s ,
193                          (struct sockaddr *) &info->wifihal_ctrl_sock.local,
194                          sizeof(info->wifihal_ctrl_sock.local)) < 0) {
195                         ALOGE("wifihal-ctrl-iface-init: bind(PF_UNIX): %s",
196                                strerror(errno));
197                         goto out;
198                 }
199                 ALOGD("Successfully replaced leftover "
200                       "ctrl_iface socket '%s'", info->wifihal_ctrl_sock.local.sun_path);
201         } else {
202              ALOGI("ctrl_iface exists and seems to "
203                    "be in use - cannot override it");
204              ALOGI("Delete '%s' manually if it is "
205                    "not used anymore", info->wifihal_ctrl_sock.local.sun_path);
206              goto out;
207         }
208     }
209 
210     /*
211      * Make socket non-blocking so that we don't hang forever if
212      * target dies unexpectedly.
213      */
214 
215 #ifdef ANDROID
216     if (chmod(info->wifihal_ctrl_sock.local.sun_path, S_IRWXU | S_IRWXG) < 0)
217     {
218       ALOGE("Failed to give permissions: %s", strerror(errno));
219     }
220 
221     /* Set group even if we do not have privileges to change owner */
222     grp_wifi = getgrnam("wifi");
223     gid_wifi = grp_wifi ? grp_wifi->gr_gid : 0;
224     pwd_system = getpwnam("system");
225     uid_system = pwd_system ? pwd_system->pw_uid : 0;
226     if (!gid_wifi || !uid_system) {
227       ALOGE("Failed to get grp ids");
228       unlink(info->wifihal_ctrl_sock.local.sun_path);
229       goto out;
230     }
231     chown(info->wifihal_ctrl_sock.local.sun_path, -1, gid_wifi);
232     chown(info->wifihal_ctrl_sock.local.sun_path, uid_system, gid_wifi);
233 #endif
234 
235     flags = fcntl(info->wifihal_ctrl_sock.s, F_GETFL);
236     if (flags >= 0) {
237         flags |= O_NONBLOCK;
238         if (fcntl(info->wifihal_ctrl_sock.s, F_SETFL, flags) < 0) {
239             ALOGI("fcntl(ctrl, O_NONBLOCK): %s",
240                    strerror(errno));
241             /* Not fatal, continue on.*/
242         }
243     }
244   return;
245 
246 out:
247   close(info->wifihal_ctrl_sock.s);
248   info->wifihal_ctrl_sock.s = 0;
249   return;
250 }
251 
ack_handler(struct nl_msg * msg,void * arg)252 int ack_handler(struct nl_msg *msg, void *arg)
253 {
254     int *err = (int *)arg;
255     *err = 0;
256     return NL_STOP;
257 }
258 
finish_handler(struct nl_msg * msg,void * arg)259 int finish_handler(struct nl_msg *msg, void *arg)
260 {
261     int *ret = (int *)arg;
262     *ret = 0;
263     return NL_SKIP;
264 }
265 
error_handler(struct sockaddr_nl * nla,struct nlmsgerr * err,void * arg)266 int error_handler(struct sockaddr_nl *nla,
267                   struct nlmsgerr *err, void *arg)
268 {
269     int *ret = (int *)arg;
270     *ret = err->error;
271 
272     ALOGV("%s invoked with error: %d", __func__, err->error);
273     return NL_SKIP;
274 }
no_seq_check(struct nl_msg * msg,void * arg)275 static int no_seq_check(struct nl_msg *msg, void *arg)
276 {
277     return NL_OK;
278 }
279 
acquire_supported_features(wifi_interface_handle iface,feature_set * set)280 static wifi_error acquire_supported_features(wifi_interface_handle iface,
281         feature_set *set)
282 {
283     wifi_error ret;
284     interface_info *iinfo = getIfaceInfo(iface);
285     wifi_handle handle = getWifiHandle(iface);
286     *set = 0;
287 
288     WifihalGeneric supportedFeatures(handle, 0,
289             OUI_QCA,
290             QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES);
291 
292     /* create the message */
293     ret = supportedFeatures.create();
294     if (ret != WIFI_SUCCESS)
295         goto cleanup;
296 
297     ret = supportedFeatures.set_iface_id(iinfo->name);
298     if (ret != WIFI_SUCCESS)
299         goto cleanup;
300 
301     ret = supportedFeatures.requestResponse();
302     if (ret != WIFI_SUCCESS) {
303         ALOGE("%s: requestResponse Error:%d",__func__, ret);
304         goto cleanup;
305     }
306 
307     supportedFeatures.getResponseparams(set);
308 
309 cleanup:
310     return ret;
311 }
312 
acquire_driver_supported_features(wifi_interface_handle iface,features_info * driver_features)313 static wifi_error acquire_driver_supported_features(wifi_interface_handle iface,
314                                           features_info *driver_features)
315 {
316     wifi_error ret;
317     interface_info *iinfo = getIfaceInfo(iface);
318     wifi_handle handle = getWifiHandle(iface);
319 
320     WifihalGeneric driverFeatures(handle, 0,
321             OUI_QCA,
322             QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES);
323 
324     /* create the message */
325     ret = driverFeatures.create();
326     if (ret != WIFI_SUCCESS)
327         goto cleanup;
328 
329     ret = driverFeatures.set_iface_id(iinfo->name);
330     if (ret != WIFI_SUCCESS)
331         goto cleanup;
332 
333     ret = driverFeatures.requestResponse();
334     if (ret != WIFI_SUCCESS) {
335         ALOGE("%s: requestResponse Error:%d",__func__, ret);
336         goto cleanup;
337     }
338 
339     driverFeatures.getDriverFeatures(driver_features);
340 
341 cleanup:
342     return mapKernelErrortoWifiHalError(ret);
343 }
344 
wifi_get_capabilities(wifi_interface_handle handle)345 static wifi_error wifi_get_capabilities(wifi_interface_handle handle)
346 {
347     wifi_error ret;
348     int requestId;
349     WifihalGeneric *wifihalGeneric;
350     wifi_handle wifiHandle = getWifiHandle(handle);
351     hal_info *info = getHalInfo(wifiHandle);
352 
353     if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
354         ALOGE("%s: GSCAN is not supported by driver", __FUNCTION__);
355         return WIFI_ERROR_NOT_SUPPORTED;
356     }
357 
358     /* No request id from caller, so generate one and pass it on to the driver.
359      * Generate it randomly.
360      */
361     requestId = get_requestid();
362 
363     wifihalGeneric = new WifihalGeneric(
364                             wifiHandle,
365                             requestId,
366                             OUI_QCA,
367                             QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CAPABILITIES);
368     if (!wifihalGeneric) {
369         ALOGE("%s: Failed to create object of WifihalGeneric class", __FUNCTION__);
370         return WIFI_ERROR_OUT_OF_MEMORY;
371     }
372 
373     ret = wifihalGeneric->wifiGetCapabilities(handle);
374 
375     delete wifihalGeneric;
376     return ret;
377 }
378 
get_firmware_bus_max_size_supported(wifi_interface_handle iface)379 static wifi_error get_firmware_bus_max_size_supported(
380                                                 wifi_interface_handle iface)
381 {
382     wifi_error ret;
383     interface_info *iinfo = getIfaceInfo(iface);
384     wifi_handle handle = getWifiHandle(iface);
385     hal_info *info = (hal_info *)handle;
386 
387     WifihalGeneric busSizeSupported(handle, 0,
388                                     OUI_QCA,
389                                     QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE);
390 
391     /* create the message */
392     ret = busSizeSupported.create();
393     if (ret != WIFI_SUCCESS)
394         goto cleanup;
395 
396     ret = busSizeSupported.set_iface_id(iinfo->name);
397     if (ret != WIFI_SUCCESS)
398         goto cleanup;
399 
400     ret = busSizeSupported.requestResponse();
401     if (ret != WIFI_SUCCESS) {
402         ALOGE("%s: requestResponse Error:%d", __FUNCTION__, ret);
403         goto cleanup;
404     }
405     info->firmware_bus_max_size = busSizeSupported.getBusSize();
406 
407 cleanup:
408     return ret;
409 }
410 
wifi_init_user_sock(hal_info * info)411 static wifi_error wifi_init_user_sock(hal_info *info)
412 {
413     struct nl_sock *user_sock =
414         wifi_create_nl_socket(WIFI_HAL_USER_SOCK_PORT, NETLINK_USERSOCK);
415     if (user_sock == NULL) {
416         ALOGE("Could not create diag sock");
417         return WIFI_ERROR_UNKNOWN;
418     }
419 
420     /* Set the socket buffer size */
421     if (nl_socket_set_buffer_size(user_sock, (256*1024), 0) < 0) {
422         ALOGE("Could not set size for user_sock: %s",
423                    strerror(errno));
424         /* continue anyway with the default (smaller) buffer */
425     }
426     else {
427         ALOGV("nl_socket_set_buffer_size successful for user_sock");
428     }
429 
430     struct nl_cb *cb = nl_socket_get_cb(user_sock);
431     if (cb == NULL) {
432         ALOGE("Could not get cb");
433         return WIFI_ERROR_UNKNOWN;
434     }
435 
436     info->user_sock_arg = 1;
437     nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
438     nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &info->user_sock_arg);
439     nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &info->user_sock_arg);
440     nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &info->user_sock_arg);
441 
442     nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, user_sock_message_handler, info);
443     nl_cb_put(cb);
444 
445     int ret = nl_socket_add_membership(user_sock, 1);
446     if (ret < 0) {
447         ALOGE("Could not add membership");
448         return WIFI_ERROR_UNKNOWN;
449     }
450 
451     info->user_sock = user_sock;
452     ALOGV("Initiialized diag sock successfully");
453     return WIFI_SUCCESS;
454 }
455 
wifi_init_cld80211_sock_cb(hal_info * info)456 static wifi_error wifi_init_cld80211_sock_cb(hal_info *info)
457 {
458     struct nl_cb *cb = nl_socket_get_cb(info->cldctx->sock);
459     if (cb == NULL) {
460         ALOGE("Could not get cb");
461         return WIFI_ERROR_UNKNOWN;
462     }
463 
464     info->user_sock_arg = 1;
465     nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
466     nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &info->user_sock_arg);
467     nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &info->user_sock_arg);
468     nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &info->user_sock_arg);
469 
470     nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, user_sock_message_handler, info);
471     nl_cb_put(cb);
472 
473     return WIFI_SUCCESS;
474 }
475 
476 
477 /*initialize function pointer table with Qualcomm HAL API*/
init_wifi_vendor_hal_func_table(wifi_hal_fn * fn)478 wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn) {
479     if (fn == NULL) {
480         return WIFI_ERROR_UNKNOWN;
481     }
482 
483     fn->wifi_initialize = wifi_initialize;
484     fn->wifi_wait_for_driver_ready = wifi_wait_for_driver_ready;
485     fn->wifi_cleanup = wifi_cleanup;
486     fn->wifi_event_loop = wifi_event_loop;
487     fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set;
488     fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix;
489     fn->wifi_set_scanning_mac_oui =  wifi_set_scanning_mac_oui;
490     fn->wifi_get_ifaces = wifi_get_ifaces;
491     fn->wifi_get_iface_name = wifi_get_iface_name;
492     fn->wifi_set_iface_event_handler = wifi_set_iface_event_handler;
493     fn->wifi_reset_iface_event_handler = wifi_reset_iface_event_handler;
494     fn->wifi_start_gscan = wifi_start_gscan;
495     fn->wifi_stop_gscan = wifi_stop_gscan;
496     fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results;
497     fn->wifi_set_bssid_hotlist = wifi_set_bssid_hotlist;
498     fn->wifi_reset_bssid_hotlist = wifi_reset_bssid_hotlist;
499     fn->wifi_set_significant_change_handler = wifi_set_significant_change_handler;
500     fn->wifi_reset_significant_change_handler = wifi_reset_significant_change_handler;
501     fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities;
502     fn->wifi_set_link_stats = wifi_set_link_stats;
503     fn->wifi_get_link_stats = wifi_get_link_stats;
504     fn->wifi_clear_link_stats = wifi_clear_link_stats;
505     fn->wifi_get_valid_channels = wifi_get_valid_channels;
506     fn->wifi_rtt_range_request = wifi_rtt_range_request;
507     fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel;
508     fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities;
509     fn->wifi_rtt_get_responder_info = wifi_rtt_get_responder_info;
510     fn->wifi_enable_responder = wifi_enable_responder;
511     fn->wifi_disable_responder = wifi_disable_responder;
512     fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag;
513     fn->wifi_start_logging = wifi_start_logging;
514     fn->wifi_set_epno_list = wifi_set_epno_list;
515     fn->wifi_reset_epno_list = wifi_reset_epno_list;
516     fn->wifi_set_country_code = wifi_set_country_code;
517     fn->wifi_enable_tdls = wifi_enable_tdls;
518     fn->wifi_disable_tdls = wifi_disable_tdls;
519     fn->wifi_get_tdls_status = wifi_get_tdls_status;
520     fn->wifi_get_tdls_capabilities = wifi_get_tdls_capabilities;
521     fn->wifi_get_firmware_memory_dump = wifi_get_firmware_memory_dump;
522     fn->wifi_set_log_handler = wifi_set_log_handler;
523     fn->wifi_reset_log_handler = wifi_reset_log_handler;
524     fn->wifi_set_alert_handler = wifi_set_alert_handler;
525     fn->wifi_reset_alert_handler = wifi_reset_alert_handler;
526     fn->wifi_get_firmware_version = wifi_get_firmware_version;
527     fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status;
528     fn->wifi_get_logger_supported_feature_set = wifi_get_logger_supported_feature_set;
529     fn->wifi_get_ring_data = wifi_get_ring_data;
530     fn->wifi_get_driver_version = wifi_get_driver_version;
531     fn->wifi_set_passpoint_list = wifi_set_passpoint_list;
532     fn->wifi_reset_passpoint_list = wifi_reset_passpoint_list;
533     fn->wifi_set_lci = wifi_set_lci;
534     fn->wifi_set_lcr = wifi_set_lcr;
535     fn->wifi_start_sending_offloaded_packet =
536             wifi_start_sending_offloaded_packet;
537     fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet;
538     fn->wifi_start_rssi_monitoring = wifi_start_rssi_monitoring;
539     fn->wifi_stop_rssi_monitoring = wifi_stop_rssi_monitoring;
540     fn->wifi_nan_enable_request = nan_enable_request;
541     fn->wifi_nan_disable_request = nan_disable_request;
542     fn->wifi_nan_publish_request = nan_publish_request;
543     fn->wifi_nan_publish_cancel_request = nan_publish_cancel_request;
544     fn->wifi_nan_subscribe_request = nan_subscribe_request;
545     fn->wifi_nan_subscribe_cancel_request = nan_subscribe_cancel_request;
546     fn->wifi_nan_transmit_followup_request = nan_transmit_followup_request;
547     fn->wifi_nan_stats_request = nan_stats_request;
548     fn->wifi_nan_config_request = nan_config_request;
549     fn->wifi_nan_tca_request = nan_tca_request;
550     fn->wifi_nan_beacon_sdf_payload_request = nan_beacon_sdf_payload_request;
551     fn->wifi_nan_register_handler = nan_register_handler;
552     fn->wifi_nan_get_version = nan_get_version;
553     fn->wifi_set_packet_filter = wifi_set_packet_filter;
554     fn->wifi_get_packet_filter_capabilities = wifi_get_packet_filter_capabilities;
555     fn->wifi_read_packet_filter = wifi_read_packet_filter;
556     fn->wifi_nan_get_capabilities = nan_get_capabilities;
557     fn->wifi_nan_data_interface_create = nan_data_interface_create;
558     fn->wifi_nan_data_interface_delete = nan_data_interface_delete;
559     fn->wifi_nan_data_request_initiator = nan_data_request_initiator;
560     fn->wifi_nan_data_indication_response = nan_data_indication_response;
561     fn->wifi_nan_data_end = nan_data_end;
562     fn->wifi_configure_nd_offload = wifi_configure_nd_offload;
563     fn->wifi_get_driver_memory_dump = wifi_get_driver_memory_dump;
564     fn->wifi_get_wake_reason_stats = wifi_get_wake_reason_stats;
565     fn->wifi_start_pkt_fate_monitoring = wifi_start_pkt_fate_monitoring;
566     fn->wifi_get_tx_pkt_fates = wifi_get_tx_pkt_fates;
567     fn->wifi_get_rx_pkt_fates = wifi_get_rx_pkt_fates;
568     fn->wifi_get_roaming_capabilities = wifi_get_roaming_capabilities;
569     fn->wifi_configure_roaming = wifi_configure_roaming;
570     fn->wifi_enable_firmware_roaming = wifi_enable_firmware_roaming;
571     fn->wifi_select_tx_power_scenario = wifi_select_tx_power_scenario;
572     fn->wifi_reset_tx_power_scenario = wifi_reset_tx_power_scenario;
573     fn->wifi_set_radio_mode_change_handler = wifi_set_radio_mode_change_handler;
574     fn->wifi_set_latency_mode = wifi_set_latency_mode;
575 
576     return WIFI_SUCCESS;
577 }
578 
cld80211lib_cleanup(hal_info * info)579 static void cld80211lib_cleanup(hal_info *info)
580 {
581     if (!info->cldctx)
582         return;
583     cld80211_remove_mcast_group(info->cldctx, "host_logs");
584     cld80211_remove_mcast_group(info->cldctx, "fw_logs");
585     cld80211_remove_mcast_group(info->cldctx, "per_pkt_stats");
586     cld80211_remove_mcast_group(info->cldctx, "diag_events");
587     cld80211_remove_mcast_group(info->cldctx, "fatal_events");
588     cld80211_remove_mcast_group(info->cldctx, "oem_msgs");
589     exit_cld80211_recv(info->cldctx);
590     cld80211_deinit(info->cldctx);
591     info->cldctx = NULL;
592 }
593 
wifi_get_iface_id(hal_info * info,const char * iface)594 static int wifi_get_iface_id(hal_info *info, const char *iface)
595 {
596     int i;
597     for (i = 0; i < info->num_interfaces; i++)
598         if (!strcmp(info->interfaces[i]->name, iface))
599             return i;
600     return -1;
601 }
602 
wifi_initialize(wifi_handle * handle)603 wifi_error wifi_initialize(wifi_handle *handle)
604 {
605     wifi_error ret = WIFI_SUCCESS;
606     wifi_interface_handle iface_handle;
607     struct nl_sock *cmd_sock = NULL;
608     struct nl_sock *event_sock = NULL;
609     struct nl_cb *cb = NULL;
610     int status = 0;
611     int index;
612     char hw_ver_type[MAX_HW_VER_LENGTH];
613     char *hw_name = NULL;
614 
615     ALOGI("Initializing wifi");
616     hal_info *info = (hal_info *)malloc(sizeof(hal_info));
617     if (info == NULL) {
618         ALOGE("Could not allocate hal_info");
619         return WIFI_ERROR_OUT_OF_MEMORY;
620     }
621 
622     memset(info, 0, sizeof(*info));
623 
624     cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT,
625                                                      NETLINK_GENERIC);
626     if (cmd_sock == NULL) {
627         ALOGE("Failed to create command socket port");
628         ret = WIFI_ERROR_UNKNOWN;
629         goto unload;
630     }
631 
632     /* Set the socket buffer size */
633     if (nl_socket_set_buffer_size(cmd_sock, (256*1024), 0) < 0) {
634         ALOGE("Could not set nl_socket RX buffer size for cmd_sock: %s",
635                    strerror(errno));
636         /* continue anyway with the default (smaller) buffer */
637     }
638 
639     event_sock =
640         wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT, NETLINK_GENERIC);
641     if (event_sock == NULL) {
642         ALOGE("Failed to create event socket port");
643         ret = WIFI_ERROR_UNKNOWN;
644         goto unload;
645     }
646 
647     /* Set the socket buffer size */
648     if (nl_socket_set_buffer_size(event_sock, (256*1024), 0) < 0) {
649         ALOGE("Could not set nl_socket RX buffer size for event_sock: %s",
650                    strerror(errno));
651         /* continue anyway with the default (smaller) buffer */
652     }
653 
654     cb = nl_socket_get_cb(event_sock);
655     if (cb == NULL) {
656         ALOGE("Failed to get NL control block for event socket port");
657         ret = WIFI_ERROR_UNKNOWN;
658         goto unload;
659     }
660 
661     info->event_sock_arg = 1;
662     nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
663     nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &info->event_sock_arg);
664     nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &info->event_sock_arg);
665     nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &info->event_sock_arg);
666 
667     nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler,
668             info);
669     nl_cb_put(cb);
670 
671     info->cmd_sock = cmd_sock;
672     info->event_sock = event_sock;
673     info->clean_up = false;
674     info->in_event_loop = false;
675 
676     info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE);
677     if (info->event_cb == NULL) {
678         ALOGE("Could not allocate event_cb");
679         ret = WIFI_ERROR_OUT_OF_MEMORY;
680         goto unload;
681     }
682     info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE;
683     info->num_event_cb = 0;
684 
685     info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211");
686     if (info->nl80211_family_id < 0) {
687         ALOGE("Could not resolve nl80211 familty id");
688         ret = WIFI_ERROR_UNKNOWN;
689         goto unload;
690     }
691 
692     pthread_mutex_init(&info->cb_lock, NULL);
693     pthread_mutex_init(&info->pkt_fate_stats_lock, NULL);
694 
695     *handle = (wifi_handle) info;
696 
697     wifi_add_membership(*handle, "scan");
698     wifi_add_membership(*handle, "mlme");
699     wifi_add_membership(*handle, "regulatory");
700     wifi_add_membership(*handle, "vendor");
701 
702     info->wifihal_ctrl_sock.s = 0;
703 
704     wifi_create_ctrl_socket(info);
705 
706     //! Initailise the monitoring clients list
707     INITIALISE_LIST(&info->monitor_sockets);
708 
709     info->cldctx = cld80211_init();
710     if (info->cldctx != NULL) {
711         info->user_sock = info->cldctx->sock;
712         ret = wifi_init_cld80211_sock_cb(info);
713         if (ret != WIFI_SUCCESS) {
714             ALOGE("Could not set cb for CLD80211 family");
715             goto cld80211_cleanup;
716         }
717 
718         status = cld80211_add_mcast_group(info->cldctx, "host_logs");
719         if (status) {
720             ALOGE("Failed to add mcast group host_logs :%d", status);
721             goto cld80211_cleanup;
722         }
723         status = cld80211_add_mcast_group(info->cldctx, "fw_logs");
724         if (status) {
725             ALOGE("Failed to add mcast group fw_logs :%d", status);
726             goto cld80211_cleanup;
727         }
728         status = cld80211_add_mcast_group(info->cldctx, "per_pkt_stats");
729         if (status) {
730             ALOGE("Failed to add mcast group per_pkt_stats :%d", status);
731             goto cld80211_cleanup;
732         }
733         status = cld80211_add_mcast_group(info->cldctx, "diag_events");
734         if (status) {
735             ALOGE("Failed to add mcast group diag_events :%d", status);
736             goto cld80211_cleanup;
737         }
738         status = cld80211_add_mcast_group(info->cldctx, "fatal_events");
739         if (status) {
740             ALOGE("Failed to add mcast group fatal_events :%d", status);
741             goto cld80211_cleanup;
742         }
743 
744         if(info->wifihal_ctrl_sock.s > 0)
745         {
746           status = cld80211_add_mcast_group(info->cldctx, "oem_msgs");
747           if (status) {
748              ALOGE("Failed to add mcast group oem_msgs :%d", status);
749              goto cld80211_cleanup;
750           }
751         }
752     } else {
753         ret = wifi_init_user_sock(info);
754         if (ret != WIFI_SUCCESS) {
755             ALOGE("Failed to alloc user socket");
756             goto unload;
757         }
758     }
759 
760     ret = wifi_init_interfaces(*handle);
761     if (ret != WIFI_SUCCESS) {
762         ALOGE("Failed to init interfaces");
763         goto unload;
764     }
765 
766     if (info->num_interfaces == 0) {
767         ALOGE("No interfaces found");
768         ret = WIFI_ERROR_UNINITIALIZED;
769         goto unload;
770     }
771 
772     index = wifi_get_iface_id(info, "wlan0");
773     if (index == -1) {
774         int i;
775         for (i = 0; i < info->num_interfaces; i++)
776         {
777             free(info->interfaces[i]);
778         }
779         ALOGE("%s no iface with wlan0", __func__);
780         goto unload;
781     }
782     iface_handle = (wifi_interface_handle)info->interfaces[index];
783 
784     ret = acquire_supported_features(iface_handle,
785             &info->supported_feature_set);
786     if (ret != WIFI_SUCCESS) {
787         ALOGI("Failed to get supported feature set : %d", ret);
788         //acquire_supported_features failure is acceptable condition as legacy
789         //drivers might not support the required vendor command. So, do not
790         //consider it as failure of wifi_initialize
791         ret = WIFI_SUCCESS;
792     }
793 
794     ret = acquire_driver_supported_features(iface_handle,
795                                   &info->driver_supported_features);
796     if (ret != WIFI_SUCCESS) {
797         ALOGI("Failed to get vendor feature set : %d", ret);
798         ret = WIFI_SUCCESS;
799     }
800 
801     ret =  wifi_get_logger_supported_feature_set(iface_handle,
802                          &info->supported_logger_feature_set);
803     if (ret != WIFI_SUCCESS)
804         ALOGE("Failed to get supported logger feature set: %d", ret);
805 
806     ret =  wifi_get_firmware_version(iface_handle, hw_ver_type,
807                                      MAX_HW_VER_LENGTH);
808     if (ret == WIFI_SUCCESS) {
809         hw_name = strstr(hw_ver_type, "HW:");
810         if (hw_name) {
811             hw_name += strlen("HW:");
812             if (strncmp(hw_name, "QCA6174", 7) == 0)
813                info->pkt_log_ver = PKT_LOG_V1;
814             else
815                info->pkt_log_ver = PKT_LOG_V2;
816         } else {
817            info->pkt_log_ver = PKT_LOG_V0;
818         }
819         ALOGV("%s: hardware version type %d", __func__, info->pkt_log_ver);
820     } else {
821         ALOGE("Failed to get firmware version: %d", ret);
822     }
823 
824     ret = get_firmware_bus_max_size_supported(iface_handle);
825     if (ret != WIFI_SUCCESS) {
826         ALOGE("Failed to get supported bus size, error : %d", ret);
827         info->firmware_bus_max_size = 1520;
828     }
829 
830     ret = wifi_logger_ring_buffers_init(info);
831     if (ret != WIFI_SUCCESS)
832         ALOGE("Wifi Logger Ring Initialization Failed");
833 
834     ret = wifi_get_capabilities(iface_handle);
835     if (ret != WIFI_SUCCESS)
836         ALOGE("Failed to get wifi Capabilities, error: %d", ret);
837 
838     info->pkt_stats = (struct pkt_stats_s *)malloc(sizeof(struct pkt_stats_s));
839     if (!info->pkt_stats) {
840         ALOGE("%s: malloc Failed for size: %zu",
841                 __FUNCTION__, sizeof(struct pkt_stats_s));
842         ret = WIFI_ERROR_OUT_OF_MEMORY;
843         goto unload;
844     }
845 
846     info->rx_buf_size_allocated = MAX_RXMPDUS_PER_AMPDU * MAX_MSDUS_PER_MPDU
847                                   * PKT_STATS_BUF_SIZE;
848 
849     info->rx_aggr_pkts =
850         (wifi_ring_buffer_entry  *)malloc(info->rx_buf_size_allocated);
851     if (!info->rx_aggr_pkts) {
852         ALOGE("%s: malloc Failed for size: %d",
853                 __FUNCTION__, info->rx_buf_size_allocated);
854         ret = WIFI_ERROR_OUT_OF_MEMORY;
855         info->rx_buf_size_allocated = 0;
856         goto unload;
857     }
858     memset(info->rx_aggr_pkts, 0, info->rx_buf_size_allocated);
859 
860     info->exit_sockets[0] = -1;
861     info->exit_sockets[1] = -1;
862 
863     if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->exit_sockets) == -1) {
864         ALOGE("Failed to create exit socket pair");
865         ret = WIFI_ERROR_UNKNOWN;
866         goto unload;
867     }
868 
869     ALOGV("Initializing Gscan Event Handlers");
870     ret = initializeGscanHandlers(info);
871     if (ret != WIFI_SUCCESS) {
872         ALOGE("Initializing Gscan Event Handlers Failed");
873         goto unload;
874     }
875 
876     ret = initializeRSSIMonitorHandler(info);
877     if (ret != WIFI_SUCCESS) {
878         ALOGE("Initializing RSSI Event Handler Failed");
879         goto unload;
880     }
881 
882     ALOGV("Initialized Wifi HAL Successfully; vendor cmd = %d Supported"
883             " features : %x", NL80211_CMD_VENDOR, info->supported_feature_set);
884 
885 cld80211_cleanup:
886     if (status != 0 || ret != WIFI_SUCCESS) {
887         ret = WIFI_ERROR_UNKNOWN;
888         cld80211lib_cleanup(info);
889     }
890 unload:
891     if (ret != WIFI_SUCCESS) {
892         if (cmd_sock)
893             nl_socket_free(cmd_sock);
894         if (event_sock)
895             nl_socket_free(event_sock);
896         if (info) {
897             if (info->cldctx) {
898                 cld80211lib_cleanup(info);
899             } else if (info->user_sock) {
900                 nl_socket_free(info->user_sock);
901             }
902             if (info->pkt_stats) free(info->pkt_stats);
903             if (info->rx_aggr_pkts) free(info->rx_aggr_pkts);
904             wifi_logger_ring_buffers_deinit(info);
905             cleanupGscanHandlers(info);
906             cleanupRSSIMonitorHandler(info);
907             free(info->event_cb);
908             if (info->driver_supported_features.flags) {
909                 free(info->driver_supported_features.flags);
910                 info->driver_supported_features.flags = NULL;
911             }
912             free(info);
913         }
914     }
915 
916     return ret;
917 }
918 
wifi_wait_for_driver_ready(void)919 wifi_error wifi_wait_for_driver_ready(void)
920 {
921     // This function will wait to make sure basic client netdev is created
922     // Function times out after 10 seconds
923     int count = (POLL_DRIVER_MAX_TIME_MS * 1000) / POLL_DRIVER_DURATION_US;
924     FILE *fd;
925 
926     do {
927         if ((fd = fopen("/sys/class/net/wlan0", "r")) != NULL) {
928             fclose(fd);
929             return WIFI_SUCCESS;
930         }
931         usleep(POLL_DRIVER_DURATION_US);
932     } while(--count > 0);
933 
934     ALOGE("Timed out wating on Driver ready ... ");
935     return WIFI_ERROR_TIMED_OUT;
936 }
937 
wifi_add_membership(wifi_handle handle,const char * group)938 static int wifi_add_membership(wifi_handle handle, const char *group)
939 {
940     hal_info *info = getHalInfo(handle);
941 
942     int id = wifi_get_multicast_id(handle, "nl80211", group);
943     if (id < 0) {
944         ALOGE("Could not find group %s", group);
945         return id;
946     }
947 
948     int ret = nl_socket_add_membership(info->event_sock, id);
949     if (ret < 0) {
950         ALOGE("Could not add membership to group %s", group);
951     }
952 
953     return ret;
954 }
955 
internal_cleaned_up_handler(wifi_handle handle)956 static void internal_cleaned_up_handler(wifi_handle handle)
957 {
958     hal_info *info = getHalInfo(handle);
959     wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler;
960     wifihal_mon_sock_t *reg, *tmp;
961 
962     if (info->cmd_sock != 0) {
963         nl_socket_free(info->cmd_sock);
964         nl_socket_free(info->event_sock);
965         info->cmd_sock = NULL;
966         info->event_sock = NULL;
967     }
968 
969     if (info->wifihal_ctrl_sock.s != 0) {
970         close(info->wifihal_ctrl_sock.s);
971         unlink(info->wifihal_ctrl_sock.local.sun_path);
972         info->wifihal_ctrl_sock.s = 0;
973     }
974 
975    list_for_each_entry_safe(reg, tmp, &info->monitor_sockets, list) {
976         del_from_list(&reg->list);
977         if(reg) {
978            free(reg);
979         }
980     }
981 
982     if (info->interfaces) {
983         for (int i = 0; i < info->num_interfaces; i++)
984             free(info->interfaces[i]);
985         free(info->interfaces);
986     }
987 
988     if (info->cldctx != NULL) {
989         cld80211lib_cleanup(info);
990     } else if (info->user_sock != 0) {
991         nl_socket_free(info->user_sock);
992         info->user_sock = NULL;
993     }
994 
995     if (info->pkt_stats)
996         free(info->pkt_stats);
997     if (info->rx_aggr_pkts)
998         free(info->rx_aggr_pkts);
999     wifi_logger_ring_buffers_deinit(info);
1000     cleanupGscanHandlers(info);
1001     cleanupRSSIMonitorHandler(info);
1002 
1003     if (info->num_event_cb)
1004         ALOGE("%d events were leftover without being freed",
1005               info->num_event_cb);
1006     free(info->event_cb);
1007 
1008     if (info->exit_sockets[0] >= 0) {
1009         close(info->exit_sockets[0]);
1010         info->exit_sockets[0] = -1;
1011     }
1012 
1013     if (info->exit_sockets[1] >= 0) {
1014         close(info->exit_sockets[1]);
1015         info->exit_sockets[1] = -1;
1016     }
1017 
1018     if (info->pkt_fate_stats) {
1019         free(info->pkt_fate_stats);
1020         info->pkt_fate_stats = NULL;
1021     }
1022 
1023     if (info->driver_supported_features.flags) {
1024         free(info->driver_supported_features.flags);
1025         info->driver_supported_features.flags = NULL;
1026     }
1027 
1028     (*cleaned_up_handler)(handle);
1029     pthread_mutex_destroy(&info->cb_lock);
1030     pthread_mutex_destroy(&info->pkt_fate_stats_lock);
1031     free(info);
1032 }
1033 
wifi_cleanup(wifi_handle handle,wifi_cleaned_up_handler handler)1034 void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
1035 {
1036     if (!handle) {
1037         ALOGE("Handle is null");
1038         return;
1039     }
1040 
1041     hal_info *info = getHalInfo(handle);
1042     info->cleaned_up_handler = handler;
1043     info->clean_up = true;
1044 
1045     TEMP_FAILURE_RETRY(write(info->exit_sockets[0], "E", 1));
1046     ALOGI("Sent msg on exit sock to unblock poll()");
1047 }
1048 
1049 
1050 
validate_cld80211_msg(nlmsghdr * nlh,int family,int cmd)1051 static int validate_cld80211_msg(nlmsghdr *nlh, int family, int cmd)
1052 {
1053     //! Enhance this API
1054     struct genlmsghdr *hdr;
1055     hdr = (genlmsghdr *)nlmsg_data(nlh);
1056 
1057     if (nlh->nlmsg_len > DEFAULT_PAGE_SIZE - sizeof(wifihal_ctrl_req_t))
1058     {
1059       ALOGE("%s: Invalid nlmsg length", __FUNCTION__);
1060       return -1;
1061     }
1062     if(hdr->cmd == WLAN_NL_MSG_OEM)
1063     {
1064       ALOGV("%s: FAMILY ID : %d ,NL CMD : %d received", __FUNCTION__,
1065              nlh->nlmsg_type, hdr->cmd);
1066 
1067       //! Update pid with the wifihal pid
1068       nlh->nlmsg_pid = getpid();
1069       return 0;
1070     }
1071     else
1072     {
1073       ALOGE("%s: NL CMD : %d received is not allowed", __FUNCTION__, hdr->cmd);
1074       return -1;
1075     }
1076 }
1077 
1078 
validate_genl_msg(nlmsghdr * nlh,int family,int cmd)1079 static int validate_genl_msg(nlmsghdr *nlh, int family, int cmd)
1080 {
1081     //! Enhance this API
1082     struct genlmsghdr *hdr;
1083     hdr = (genlmsghdr *)nlmsg_data(nlh);
1084 
1085     if (nlh->nlmsg_len > DEFAULT_PAGE_SIZE - sizeof(wifihal_ctrl_req_t))
1086     {
1087       ALOGE("%s: Invalid nlmsg length", __FUNCTION__);
1088       return -1;
1089     }
1090     if(hdr->cmd == NL80211_CMD_FRAME ||
1091        hdr->cmd == NL80211_CMD_REGISTER_ACTION)
1092     {
1093       ALOGV("%s: FAMILY ID : %d ,NL CMD : %d received", __FUNCTION__,
1094              nlh->nlmsg_type, hdr->cmd);
1095       return 0;
1096     }
1097     else
1098     {
1099       ALOGE("%s: NL CMD : %d received is not allowed", __FUNCTION__, hdr->cmd);
1100       return -1;
1101     }
1102 }
1103 
send_nl_data(wifi_handle handle,wifihal_ctrl_req_t * ctrl_msg)1104 static int send_nl_data(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg)
1105 {
1106     hal_info *info = getHalInfo(handle);
1107     struct nl_msg *msg = NULL;
1108     int retval = -1;
1109 
1110     //! attach monitor socket if it was not it the list
1111     if(ctrl_msg->monsock_len)
1112     {
1113       retval = attach_monitor_sock(handle, ctrl_msg);
1114       if(retval)
1115         goto nl_out;
1116     }
1117 
1118     msg = nlmsg_alloc();
1119     if (!msg)
1120     {
1121        ALOGE("%s: Memory allocation failed \n", __FUNCTION__);
1122        goto nl_out;
1123     }
1124 
1125     if (ctrl_msg->data_len > nlmsg_get_max_size(msg))
1126     {
1127         ALOGE("%s: Invalid ctrl msg length \n", __FUNCTION__);
1128         retval = -1;
1129         goto nl_out;
1130     }
1131     memcpy((char *)msg->nm_nlh, (char *)ctrl_msg->data, ctrl_msg->data_len);
1132 
1133    if(ctrl_msg->family_name == GENERIC_NL_FAMILY)
1134    {
1135      //! Before sending the received gennlmsg to kernel,
1136      //! better to have checks for allowed commands
1137      retval = validate_genl_msg(msg->nm_nlh, ctrl_msg->family_name, ctrl_msg->cmd_id);
1138      if (retval < 0)
1139          goto nl_out;
1140 
1141      retval = nl_send_auto_complete(info->event_sock, msg);    /* send message */
1142      if (retval < 0)
1143      {
1144        ALOGE("%s: nl_send_auto_complete - failed : %d \n", __FUNCTION__, retval);
1145        goto nl_out;
1146      }
1147 
1148      retval = internal_pollin_handler(handle, info->event_sock);
1149   }
1150   else if (ctrl_msg->family_name == CLD80211_FAMILY)
1151   {
1152     if (info->cldctx != NULL)
1153     {
1154       //! Before sending the received cld80211 msg to kernel,
1155       //! better to have checks for allowed commands
1156       retval = validate_cld80211_msg(msg->nm_nlh, ctrl_msg->family_name, ctrl_msg->cmd_id);
1157       if (retval < 0)
1158          goto nl_out;
1159 
1160       retval = cld80211_send_msg(info->cldctx, msg);
1161       if (retval != 0)
1162       {
1163         ALOGE("%s: send cld80211 message - failed\n", __FUNCTION__);
1164         goto nl_out;
1165       }
1166       ALOGD("%s: sent cld80211 message for pid %d\n", __FUNCTION__, getpid());
1167     }
1168     else
1169     {
1170       ALOGE("%s: cld80211 ctx not present \n", __FUNCTION__);
1171     }
1172   }
1173   else
1174   {
1175     ALOGE("%s: Unknown family name : %d \n", __FUNCTION__, ctrl_msg->family_name);
1176     retval = -1;
1177   }
1178 nl_out:
1179   if (msg)
1180   {
1181     nlmsg_free(msg);
1182   }
1183   return retval;
1184 }
1185 
register_monitor_sock(wifi_handle handle,wifihal_ctrl_req_t * ctrl_msg,int attach)1186 static int register_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg, int attach)
1187 {
1188     hal_info *info = getHalInfo(handle);
1189 
1190     wifihal_mon_sock_t *reg, *nreg;
1191     char *match = NULL;
1192     unsigned int match_len = 0;
1193     unsigned int type;
1194 
1195     //! For Register Action frames, compare the match length and match buffer.
1196     //! For other registrations such as oem messages,
1197     //! diag messages check for respective commands
1198 
1199     if((ctrl_msg->family_name == GENERIC_NL_FAMILY) &&
1200        (ctrl_msg->cmd_id == NL80211_CMD_REGISTER_ACTION))
1201     {
1202        struct genlmsghdr *genlh;
1203        struct  nlmsghdr *nlh = (struct  nlmsghdr *)ctrl_msg->data;
1204        genlh = (struct genlmsghdr *)nlmsg_data(nlh);
1205        struct nlattr *nlattrs[NL80211_ATTR_MAX + 1];
1206 
1207        if (nlh->nlmsg_len > DEFAULT_PAGE_SIZE - sizeof(*ctrl_msg))
1208        {
1209          ALOGE("%s: Invalid nlmsg length", __FUNCTION__);
1210          return -1;
1211        }
1212        if (nla_parse(nlattrs, NL80211_ATTR_MAX, genlmsg_attrdata(genlh, 0),
1213                  genlmsg_attrlen(genlh, 0), NULL))
1214        {
1215          ALOGE("unable to parse nl attributes");
1216          return -1;
1217        }
1218        if (!nlattrs[NL80211_ATTR_FRAME_TYPE])
1219        {
1220          ALOGD("No Valid frame type");
1221        }
1222        else
1223        {
1224          type = nla_get_u16(nlattrs[NL80211_ATTR_FRAME_TYPE]);
1225        }
1226        if (!nlattrs[NL80211_ATTR_FRAME_MATCH])
1227        {
1228          ALOGE("No Frame Match");
1229          return -1;
1230        }
1231        else
1232        {
1233          match_len = nla_len(nlattrs[NL80211_ATTR_FRAME_MATCH]);
1234          match = (char *)nla_data(nlattrs[NL80211_ATTR_FRAME_MATCH]);
1235 
1236          list_for_each_entry(reg, &info->monitor_sockets, list) {
1237 
1238            if(reg == NULL)
1239               break;
1240 
1241            int mlen = min(match_len, reg->match_len);
1242 
1243            if (reg->match_len == 0)
1244                continue;
1245 
1246            if (memcmp(reg->match, match, mlen) == 0) {
1247 
1248               if((ctrl_msg->monsock_len == reg->monsock_len) &&
1249                  (memcmp((char *)&reg->monsock, (char *)&ctrl_msg->monsock, ctrl_msg->monsock_len) == 0))
1250               {
1251                 if(attach)
1252                 {
1253                   ALOGE(" %s :Action frame already registered for this client ", __FUNCTION__);
1254                   return -2;
1255                 }
1256                 else
1257                 {
1258                   del_from_list(&reg->list);
1259                   free(reg);
1260                   return 0;
1261                 }
1262               }
1263               else
1264               {
1265                 //! when action frame registered for other client,
1266                 //! you can't attach or dettach for new client
1267                 ALOGE(" %s :Action frame registered for other client ", __FUNCTION__);
1268                 return -2;
1269               }
1270            }
1271          }
1272        }
1273     }
1274     else
1275     {
1276       list_for_each_entry(reg, &info->monitor_sockets, list) {
1277 
1278          //! Checking for monitor sock in the list :
1279 
1280          //! For attach request :
1281          //! if sock is not present, then it is a new entry , so add to list.
1282          //! if sock is present,  and cmd_id does not match, add another entry to list.
1283          //! if sock is present, and cmd_id matches, return 0.
1284 
1285          //! For dettach req :
1286          //! if sock is not present, return error -2.
1287          //! if sock is present,  and cmd_id does not match, return error -2.
1288          //! if sock is present, and cmd_id matches, delete entry and return 0.
1289          if(reg == NULL)
1290             break;
1291 
1292          if (ctrl_msg->monsock_len != reg->monsock_len)
1293              continue;
1294 
1295          if (memcmp((char *)&reg->monsock, (char *)&ctrl_msg->monsock, ctrl_msg->monsock_len) == 0) {
1296 
1297             if((reg->family_name == ctrl_msg->family_name) && (reg->cmd_id == ctrl_msg->cmd_id))
1298             {
1299                if(!attach)
1300                {
1301                  del_from_list(&reg->list);
1302                  free(reg);
1303                }
1304                return 0;
1305             }
1306          }
1307       }
1308     }
1309 
1310     if(attach)
1311     {
1312        if (ctrl_msg->monsock_len > sizeof(struct sockaddr_un))
1313        {
1314          ALOGE("%s: Invalid monitor socket length \n", __FUNCTION__);
1315          return -3;
1316        }
1317 
1318        nreg = (wifihal_mon_sock_t *)malloc(sizeof(*reg) + match_len);
1319         if (!nreg)
1320            return -1;
1321 
1322        memset((char *)nreg, 0, sizeof(*reg) + match_len);
1323        nreg->family_name = ctrl_msg->family_name;
1324        nreg->cmd_id = ctrl_msg->cmd_id;
1325        nreg->monsock_len = ctrl_msg->monsock_len;
1326        memcpy((char *)&nreg->monsock, (char *)&ctrl_msg->monsock, ctrl_msg->monsock_len);
1327 
1328        if(match_len && match)
1329        {
1330          nreg->match_len = match_len;
1331          memcpy(nreg->match, match, match_len);
1332        }
1333        add_to_list(&nreg->list, &info->monitor_sockets);
1334     }
1335     else
1336     {
1337        //! Not attached, so cant be dettached
1338        ALOGE("%s: Dettaching the unregistered socket \n", __FUNCTION__);
1339        return -2;
1340     }
1341 
1342    return 0;
1343 }
1344 
attach_monitor_sock(wifi_handle handle,wifihal_ctrl_req_t * ctrl_msg)1345 static int attach_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg)
1346 {
1347    return register_monitor_sock(handle, ctrl_msg, 1);
1348 }
1349 
dettach_monitor_sock(wifi_handle handle,wifihal_ctrl_req_t * ctrl_msg)1350 static int dettach_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg)
1351 {
1352    return register_monitor_sock(handle, ctrl_msg, 0);
1353 }
1354 
internal_pollin_handler_app(wifi_handle handle,struct ctrl_sock * sock)1355 static int internal_pollin_handler_app(wifi_handle handle,  struct ctrl_sock *sock)
1356 {
1357     int retval = -1;
1358     int res;
1359     struct sockaddr_un from;
1360     socklen_t fromlen = sizeof(from);
1361     wifihal_ctrl_req_t *ctrl_msg;
1362     wifihal_ctrl_sync_rsp_t ctrl_reply;
1363 
1364     ctrl_msg = (wifihal_ctrl_req_t *)malloc(DEFAULT_PAGE_SIZE);
1365     if(ctrl_msg == NULL)
1366     {
1367       ALOGE ("Memory allocation failure");
1368       return -1;
1369     }
1370 
1371     memset((char *)ctrl_msg, 0, DEFAULT_PAGE_SIZE);
1372 
1373     res = recvfrom(sock->s, (char *)ctrl_msg, DEFAULT_PAGE_SIZE, 0,
1374                    (struct sockaddr *)&from, &fromlen);
1375     if (res < 0) {
1376         ALOGE("recvfrom(ctrl_iface): %s",
1377                strerror(errno));
1378         if(ctrl_msg)
1379            free(ctrl_msg);
1380 
1381         return 0;
1382     }
1383     switch(ctrl_msg->ctrl_cmd)
1384     {
1385        case WIFIHAL_CTRL_MONITOR_ATTACH:
1386          retval = attach_monitor_sock(handle, ctrl_msg);
1387        break;
1388        case WIFIHAL_CTRL_MONITOR_DETTACH:
1389          retval = dettach_monitor_sock(handle, ctrl_msg);
1390        break;
1391        case WIFIHAL_CTRL_SEND_NL_DATA:
1392          retval = send_nl_data(handle, ctrl_msg);
1393        break;
1394        default:
1395        break;
1396     }
1397 
1398     ctrl_reply.ctrl_cmd = ctrl_msg->ctrl_cmd;
1399     ctrl_reply.family_name = ctrl_msg->family_name;
1400     ctrl_reply.cmd_id = ctrl_msg->cmd_id;
1401     ctrl_reply.status = retval;
1402 
1403     if(ctrl_msg)
1404        free(ctrl_msg);
1405 
1406     if (sendto(sock->s, (char *)&ctrl_reply, sizeof(ctrl_reply), 0, (struct sockaddr *)&from,
1407                fromlen) < 0) {
1408                   int _errno = errno;
1409                   ALOGE("socket send failed : %d",_errno);
1410 
1411        if (_errno == ENOBUFS || _errno == EAGAIN) {
1412            /*
1413             * The socket send buffer could be full. This
1414             * may happen if client programs are not
1415             * receiving their pending messages. Close and
1416             * reopen the socket as a workaround to avoid
1417             * getting stuck being unable to send any new
1418             * responses.
1419             */
1420           }
1421         }
1422       return res;
1423 }
1424 
internal_pollin_handler(wifi_handle handle,struct nl_sock * sock)1425 static int internal_pollin_handler(wifi_handle handle, struct nl_sock *sock)
1426 {
1427     struct nl_cb *cb = nl_socket_get_cb(sock);
1428 
1429     int res = nl_recvmsgs(sock, cb);
1430     if(res)
1431         ALOGE("Error :%d while reading nl msg", res);
1432     nl_cb_put(cb);
1433     return res;
1434 }
1435 
internal_event_handler_app(wifi_handle handle,int events,struct ctrl_sock * sock)1436 static void internal_event_handler_app(wifi_handle handle, int events,
1437                                     struct ctrl_sock *sock)
1438 {
1439     if (events & POLLERR) {
1440         ALOGE("Error reading from wifi_hal ctrl socket");
1441         internal_pollin_handler_app(handle, sock);
1442     } else if (events & POLLHUP) {
1443         ALOGE("Remote side hung up");
1444     } else if (events & POLLIN) {
1445         //ALOGI("Found some events!!!");
1446         internal_pollin_handler_app(handle, sock);
1447     } else {
1448         ALOGE("Unknown event - %0x", events);
1449     }
1450 }
1451 
internal_event_handler(wifi_handle handle,int events,struct nl_sock * sock)1452 static void internal_event_handler(wifi_handle handle, int events,
1453                                    struct nl_sock *sock)
1454 {
1455     if (events & POLLERR) {
1456         ALOGE("Error reading from socket");
1457         internal_pollin_handler(handle, sock);
1458     } else if (events & POLLHUP) {
1459         ALOGE("Remote side hung up");
1460     } else if (events & POLLIN) {
1461         //ALOGI("Found some events!!!");
1462         internal_pollin_handler(handle, sock);
1463     } else {
1464         ALOGE("Unknown event - %0x", events);
1465     }
1466 }
1467 
1468 /* Run event handler */
wifi_event_loop(wifi_handle handle)1469 void wifi_event_loop(wifi_handle handle)
1470 {
1471     hal_info *info = getHalInfo(handle);
1472     if (info->in_event_loop) {
1473         return;
1474     } else {
1475         info->in_event_loop = true;
1476     }
1477 
1478     pollfd pfd[4];
1479     memset(&pfd, 0, 4*sizeof(pfd[0]));
1480 
1481     pfd[0].fd = nl_socket_get_fd(info->event_sock);
1482     pfd[0].events = POLLIN;
1483 
1484     pfd[1].fd = nl_socket_get_fd(info->user_sock);
1485     pfd[1].events = POLLIN;
1486 
1487     pfd[2].fd = info->exit_sockets[1];
1488     pfd[2].events = POLLIN;
1489 
1490     if(info->wifihal_ctrl_sock.s > 0) {
1491       pfd[3].fd = info->wifihal_ctrl_sock.s ;
1492       pfd[3].events = POLLIN;
1493     }
1494     /* TODO: Add support for timeouts */
1495 
1496     do {
1497         pfd[0].revents = 0;
1498         pfd[1].revents = 0;
1499         pfd[2].revents = 0;
1500         pfd[3].revents = 0;
1501         //ALOGI("Polling sockets");
1502         int result = poll(pfd, 4, -1);
1503         if (result < 0) {
1504             ALOGE("Error polling socket");
1505         } else {
1506             if (pfd[0].revents & (POLLIN | POLLHUP | POLLERR)) {
1507                 internal_event_handler(handle, pfd[0].revents, info->event_sock);
1508             }
1509             if (pfd[1].revents & (POLLIN | POLLHUP | POLLERR)) {
1510                 internal_event_handler(handle, pfd[1].revents, info->user_sock);
1511             }
1512             if ((info->wifihal_ctrl_sock.s > 0) && (pfd[3].revents & (POLLIN | POLLHUP | POLLERR))) {
1513                 internal_event_handler_app(handle, pfd[3].revents, &info->wifihal_ctrl_sock);
1514             }
1515         }
1516         rb_timerhandler(info);
1517     } while (!info->clean_up);
1518     internal_cleaned_up_handler(handle);
1519 }
1520 
user_sock_message_handler(nl_msg * msg,void * arg)1521 static int user_sock_message_handler(nl_msg *msg, void *arg)
1522 {
1523     wifi_handle handle = (wifi_handle)arg;
1524     hal_info *info = getHalInfo(handle);
1525 
1526     diag_message_handler(info, msg);
1527 
1528     return NL_OK;
1529 }
1530 
internal_valid_message_handler(nl_msg * msg,void * arg)1531 static int internal_valid_message_handler(nl_msg *msg, void *arg)
1532 {
1533     wifi_handle handle = (wifi_handle)arg;
1534     hal_info *info = getHalInfo(handle);
1535 
1536     WifiEvent event(msg);
1537     int res = event.parse();
1538     if (res < 0) {
1539         ALOGE("Failed to parse event: %d", res);
1540         return NL_SKIP;
1541     }
1542 
1543     int cmd = event.get_cmd();
1544     uint32_t vendor_id = 0;
1545     int subcmd = 0;
1546 
1547     if (cmd == NL80211_CMD_VENDOR) {
1548         vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID);
1549         subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD);
1550         /* Restrict printing GSCAN_FULL_RESULT which is causing lot
1551            of logs in bug report */
1552         if (subcmd != QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT) {
1553             ALOGI("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x",
1554                   event.get_cmdString(), vendor_id, subcmd);
1555         }
1556     }
1557     else if((info->wifihal_ctrl_sock.s > 0) && (cmd == NL80211_CMD_FRAME))
1558     {
1559        struct genlmsghdr *genlh;
1560        struct  nlmsghdr *nlh = nlmsg_hdr(msg);
1561        genlh = (struct genlmsghdr *)nlmsg_data(nlh);
1562        struct nlattr *nlattrs[NL80211_ATTR_MAX + 1];
1563 
1564        wifihal_ctrl_event_t *ctrl_evt;
1565        char *buff;
1566        wifihal_mon_sock_t *reg;
1567 
1568        nla_parse(nlattrs, NL80211_ATTR_MAX, genlmsg_attrdata(genlh, 0),
1569                  genlmsg_attrlen(genlh, 0), NULL);
1570 
1571        if (!nlattrs[NL80211_ATTR_FRAME])
1572        {
1573          ALOGD("No Frame body");
1574          return WIFI_SUCCESS;
1575        }
1576        ctrl_evt = (wifihal_ctrl_event_t *)malloc(sizeof(*ctrl_evt) + nlh->nlmsg_len);
1577        if(ctrl_evt == NULL)
1578        {
1579          ALOGE("Memory allocation failure");
1580          return -1;
1581        }
1582        memset((char *)ctrl_evt, 0, sizeof(*ctrl_evt) + nlh->nlmsg_len);
1583        ctrl_evt->family_name = GENERIC_NL_FAMILY;
1584        ctrl_evt->cmd_id = cmd;
1585        ctrl_evt->data_len = nlh->nlmsg_len;
1586        memcpy(ctrl_evt->data, (char *)nlh, ctrl_evt->data_len);
1587 
1588 
1589        buff = (char *)nla_data(nlattrs[NL80211_ATTR_FRAME]) + 24; //! Size of Wlan80211FrameHeader
1590 
1591        list_for_each_entry(reg, &info->monitor_sockets, list) {
1592 
1593                  if(reg == NULL)
1594                     break;
1595 
1596                  if (memcmp(reg->match, buff, reg->match_len))
1597                      continue;
1598 
1599                  /* found match! */
1600                  /* Indicate the received Action frame to respective client */
1601                  if (sendto(info->wifihal_ctrl_sock.s, (char *)ctrl_evt,
1602                             sizeof(*ctrl_evt) + ctrl_evt->data_len,
1603                             0, (struct sockaddr *)&reg->monsock, reg->monsock_len) < 0)
1604                  {
1605                    int _errno = errno;
1606                    ALOGE("socket send failed : %d",_errno);
1607 
1608                    if (_errno == ENOBUFS || _errno == EAGAIN) {
1609                    }
1610                  }
1611 
1612         }
1613         free(ctrl_evt);
1614     }
1615 
1616     else {
1617         ALOGV("event received %s", event.get_cmdString());
1618     }
1619 
1620     // event.log();
1621 
1622     bool dispatched = false;
1623 
1624     pthread_mutex_lock(&info->cb_lock);
1625 
1626     for (int i = 0; i < info->num_event_cb; i++) {
1627         if (cmd == info->event_cb[i].nl_cmd) {
1628             if (cmd == NL80211_CMD_VENDOR
1629                 && ((vendor_id != info->event_cb[i].vendor_id)
1630                 || (subcmd != info->event_cb[i].vendor_subcmd)))
1631             {
1632                 /* event for a different vendor, ignore it */
1633                 continue;
1634             }
1635 
1636             cb_info *cbi = &(info->event_cb[i]);
1637             pthread_mutex_unlock(&info->cb_lock);
1638             if (cbi->cb_func) {
1639                 (*(cbi->cb_func))(msg, cbi->cb_arg);
1640                 dispatched = true;
1641             }
1642             return NL_OK;
1643         }
1644     }
1645 
1646 #ifdef QC_HAL_DEBUG
1647     if (!dispatched) {
1648         ALOGI("event ignored!!");
1649     }
1650 #endif
1651 
1652     pthread_mutex_unlock(&info->cb_lock);
1653     return NL_OK;
1654 }
1655 
1656 ////////////////////////////////////////////////////////////////////////////////
1657 
1658 class GetMulticastIdCommand : public WifiCommand
1659 {
1660 private:
1661     const char *mName;
1662     const char *mGroup;
1663     int   mId;
1664 public:
GetMulticastIdCommand(wifi_handle handle,const char * name,const char * group)1665     GetMulticastIdCommand(wifi_handle handle, const char *name,
1666             const char *group) : WifiCommand(handle, 0)
1667     {
1668         mName = name;
1669         mGroup = group;
1670         mId = -1;
1671     }
1672 
getId()1673     int getId() {
1674         return mId;
1675     }
1676 
create()1677     virtual wifi_error create() {
1678         int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl");
1679         // ALOGI("ctrl family = %d", nlctrlFamily);
1680         wifi_error ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0);
1681         if (ret != WIFI_SUCCESS)
1682             return ret;
1683 
1684         ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName);
1685         return ret;
1686     }
1687 
handleResponse(WifiEvent & reply)1688     virtual int handleResponse(WifiEvent& reply) {
1689 
1690         // ALOGI("handling reponse in %s", __func__);
1691 
1692         struct nlattr **tb = reply.attributes();
1693         struct nlattr *mcgrp = NULL;
1694         int i;
1695 
1696         if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
1697             ALOGI("No multicast groups found");
1698             return NL_SKIP;
1699         } else {
1700             // ALOGI("Multicast groups attr size = %d",
1701             // nla_len(tb[CTRL_ATTR_MCAST_GROUPS]));
1702         }
1703 
1704         for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
1705 
1706             // ALOGI("Processing group");
1707             struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
1708             nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp),
1709                 nla_len(mcgrp), NULL);
1710             if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID])
1711             {
1712                 continue;
1713             }
1714 
1715             char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
1716             int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
1717 
1718             // ALOGI("Found group name %s", grpName);
1719 
1720             if (strncmp(grpName, mGroup, grpNameLen) != 0)
1721                 continue;
1722 
1723             mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
1724             break;
1725         }
1726 
1727         return NL_SKIP;
1728     }
1729 
1730 };
1731 
wifi_get_multicast_id(wifi_handle handle,const char * name,const char * group)1732 static int wifi_get_multicast_id(wifi_handle handle, const char *name,
1733         const char *group)
1734 {
1735     GetMulticastIdCommand cmd(handle, name, group);
1736     int res = cmd.requestResponse();
1737     if (res < 0)
1738         return res;
1739     else
1740         return cmd.getId();
1741 }
1742 
1743 /////////////////////////////////////////////////////////////////////////
1744 
is_wifi_interface(const char * name)1745 static bool is_wifi_interface(const char *name)
1746 {
1747     if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0) {
1748         /* not a wifi interface; ignore it */
1749         return false;
1750     } else {
1751         return true;
1752     }
1753 }
1754 
get_interface(const char * name,interface_info * info)1755 static int get_interface(const char *name, interface_info *info)
1756 {
1757     strlcpy(info->name, name, (IFNAMSIZ + 1));
1758     info->id = if_nametoindex(name);
1759     // ALOGI("found an interface : %s, id = %d", name, info->id);
1760     return WIFI_SUCCESS;
1761 }
1762 
wifi_init_interfaces(wifi_handle handle)1763 wifi_error wifi_init_interfaces(wifi_handle handle)
1764 {
1765     hal_info *info = (hal_info *)handle;
1766 
1767     struct dirent *de;
1768 
1769     DIR *d = opendir("/sys/class/net");
1770     if (d == 0)
1771         return WIFI_ERROR_UNKNOWN;
1772 
1773     int n = 0;
1774     while ((de = readdir(d))) {
1775         if (de->d_name[0] == '.')
1776             continue;
1777         if (is_wifi_interface(de->d_name) ) {
1778             n++;
1779         }
1780     }
1781 
1782     closedir(d);
1783 
1784     d = opendir("/sys/class/net");
1785     if (d == 0)
1786         return WIFI_ERROR_UNKNOWN;
1787 
1788     info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n);
1789     if (info->interfaces == NULL) {
1790         ALOGE("%s: Error info->interfaces NULL", __func__);
1791         return WIFI_ERROR_OUT_OF_MEMORY;
1792     }
1793 
1794     int i = 0;
1795     while ((de = readdir(d))) {
1796         if (de->d_name[0] == '.')
1797             continue;
1798         if (is_wifi_interface(de->d_name)) {
1799             interface_info *ifinfo
1800                 = (interface_info *)malloc(sizeof(interface_info));
1801             if (ifinfo == NULL) {
1802                 ALOGE("%s: Error ifinfo NULL", __func__);
1803                 while (i > 0) {
1804                     free(info->interfaces[i-1]);
1805                     i--;
1806                 }
1807                 free(info->interfaces);
1808                 return WIFI_ERROR_OUT_OF_MEMORY;
1809             }
1810             if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {
1811                 free(ifinfo);
1812                 continue;
1813             }
1814             ifinfo->handle = handle;
1815             info->interfaces[i] = ifinfo;
1816             i++;
1817         }
1818     }
1819 
1820     closedir(d);
1821 
1822     info->num_interfaces = n;
1823 
1824     return WIFI_SUCCESS;
1825 }
1826 
wifi_get_ifaces(wifi_handle handle,int * num,wifi_interface_handle ** interfaces)1827 wifi_error wifi_get_ifaces(wifi_handle handle, int *num,
1828         wifi_interface_handle **interfaces)
1829 {
1830     hal_info *info = (hal_info *)handle;
1831 
1832     *interfaces = (wifi_interface_handle *)info->interfaces;
1833     *num = info->num_interfaces;
1834 
1835     return WIFI_SUCCESS;
1836 }
1837 
wifi_get_iface_name(wifi_interface_handle handle,char * name,size_t size)1838 wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name,
1839         size_t size)
1840 {
1841     interface_info *info = (interface_info *)handle;
1842     strlcpy(name, info->name, size);
1843     return WIFI_SUCCESS;
1844 }
1845 
1846 /* Get the supported Feature set */
wifi_get_supported_feature_set(wifi_interface_handle iface,feature_set * set)1847 wifi_error wifi_get_supported_feature_set(wifi_interface_handle iface,
1848         feature_set *set)
1849 {
1850     int ret = 0;
1851     wifi_handle handle = getWifiHandle(iface);
1852     *set = 0;
1853     hal_info *info = getHalInfo(handle);
1854 
1855     ret = acquire_supported_features(iface, set);
1856     if (ret != WIFI_SUCCESS) {
1857         *set = info->supported_feature_set;
1858         ALOGV("Supported feature set acquired at initialization : %x", *set);
1859     } else {
1860         info->supported_feature_set = *set;
1861         ALOGV("Supported feature set acquired : %x", *set);
1862     }
1863     return WIFI_SUCCESS;
1864 }
1865 
wifi_get_concurrency_matrix(wifi_interface_handle handle,int set_size_max,feature_set set[],int * set_size)1866 wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle,
1867                                        int set_size_max,
1868                                        feature_set set[], int *set_size)
1869 {
1870     wifi_error ret;
1871     struct nlattr *nlData;
1872     WifihalGeneric *vCommand = NULL;
1873     interface_info *ifaceInfo = getIfaceInfo(handle);
1874     wifi_handle wifiHandle = getWifiHandle(handle);
1875 
1876     if (set == NULL) {
1877         ALOGE("%s: NULL set pointer provided. Exit.",
1878             __func__);
1879         return WIFI_ERROR_INVALID_ARGS;
1880     }
1881 
1882     vCommand = new WifihalGeneric(wifiHandle, 0,
1883             OUI_QCA,
1884             QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX);
1885     if (vCommand == NULL) {
1886         ALOGE("%s: Error vCommand NULL", __func__);
1887         return WIFI_ERROR_OUT_OF_MEMORY;
1888     }
1889 
1890     /* Create the message */
1891     ret = vCommand->create();
1892     if (ret != WIFI_SUCCESS)
1893         goto cleanup;
1894 
1895     ret = vCommand->set_iface_id(ifaceInfo->name);
1896     if (ret != WIFI_SUCCESS)
1897         goto cleanup;
1898 
1899     /* Add the vendor specific attributes for the NL command. */
1900     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1901     if (!nlData)
1902         goto cleanup;
1903 
1904     ret = vCommand->put_u32(
1905           QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX,
1906           set_size_max);
1907     if (ret != WIFI_SUCCESS)
1908         goto cleanup;
1909 
1910     vCommand->attr_end(nlData);
1911 
1912     /* Populate the input received from caller/framework. */
1913     vCommand->setMaxSetSize(set_size_max);
1914     vCommand->setSizePtr(set_size);
1915     vCommand->setConcurrencySet(set);
1916 
1917     ret = vCommand->requestResponse();
1918     if (ret != WIFI_SUCCESS)
1919         ALOGE("%s: requestResponse() error: %d", __func__, ret);
1920 
1921 cleanup:
1922     delete vCommand;
1923     if (ret)
1924         *set_size = 0;
1925     return ret;
1926 }
1927 
1928 
wifi_set_nodfs_flag(wifi_interface_handle handle,u32 nodfs)1929 wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs)
1930 {
1931     wifi_error ret;
1932     struct nlattr *nlData;
1933     WifiVendorCommand *vCommand = NULL;
1934     interface_info *ifaceInfo = getIfaceInfo(handle);
1935     wifi_handle wifiHandle = getWifiHandle(handle);
1936 
1937     vCommand = new WifiVendorCommand(wifiHandle, 0,
1938             OUI_QCA,
1939             QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG);
1940     if (vCommand == NULL) {
1941         ALOGE("%s: Error vCommand NULL", __func__);
1942         return WIFI_ERROR_OUT_OF_MEMORY;
1943     }
1944 
1945     /* Create the message */
1946     ret = vCommand->create();
1947     if (ret != WIFI_SUCCESS)
1948         goto cleanup;
1949 
1950     ret = vCommand->set_iface_id(ifaceInfo->name);
1951     if (ret != WIFI_SUCCESS)
1952         goto cleanup;
1953 
1954     /* Add the vendor specific attributes for the NL command. */
1955     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1956     if (!nlData)
1957         goto cleanup;
1958 
1959     /* Add the fixed part of the mac_oui to the nl command */
1960     ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG, nodfs);
1961     if (ret != WIFI_SUCCESS)
1962         goto cleanup;
1963 
1964     vCommand->attr_end(nlData);
1965 
1966     ret = vCommand->requestResponse();
1967     /* Don't check response since we aren't expecting one */
1968 
1969 cleanup:
1970     delete vCommand;
1971     return ret;
1972 }
1973 
wifi_start_sending_offloaded_packet(wifi_request_id id,wifi_interface_handle iface,u16 ether_type,u8 * ip_packet,u16 ip_packet_len,u8 * src_mac_addr,u8 * dst_mac_addr,u32 period_msec)1974 wifi_error wifi_start_sending_offloaded_packet(wifi_request_id id,
1975                                                wifi_interface_handle iface,
1976                                                u16 ether_type,
1977                                                u8 *ip_packet,
1978                                                u16 ip_packet_len,
1979                                                u8 *src_mac_addr,
1980                                                u8 *dst_mac_addr,
1981                                                u32 period_msec)
1982 {
1983     wifi_error ret;
1984     struct nlattr *nlData;
1985     WifiVendorCommand *vCommand = NULL;
1986 
1987     ret = initialize_vendor_cmd(iface, id,
1988                                 QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
1989                                 &vCommand);
1990     if (ret != WIFI_SUCCESS) {
1991         ALOGE("%s: Initialization failed", __func__);
1992         return ret;
1993     }
1994 
1995     ALOGV("ether type 0x%04x\n", ether_type);
1996     ALOGV("ip packet length : %u\nIP Packet:", ip_packet_len);
1997     hexdump(ip_packet, ip_packet_len);
1998     ALOGV("Src Mac Address: " MAC_ADDR_STR "\nDst Mac Address: " MAC_ADDR_STR
1999           "\nPeriod in msec : %u", MAC_ADDR_ARRAY(src_mac_addr),
2000           MAC_ADDR_ARRAY(dst_mac_addr), period_msec);
2001 
2002     /* Add the vendor specific attributes for the NL command. */
2003     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2004     if (!nlData)
2005         goto cleanup;
2006 
2007     ret = vCommand->put_u32(
2008             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL,
2009             QCA_WLAN_OFFLOADED_PACKETS_SENDING_START);
2010     if (ret != WIFI_SUCCESS)
2011         goto cleanup;
2012 
2013     ret = vCommand->put_u32(
2014             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID,
2015             id);
2016     if (ret != WIFI_SUCCESS)
2017         goto cleanup;
2018 
2019     ret = vCommand->put_u16(
2020             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_ETHER_PROTO_TYPE,
2021             ether_type);
2022     if (ret != WIFI_SUCCESS)
2023         goto cleanup;
2024 
2025     ret = vCommand->put_bytes(
2026             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA,
2027             (const char *)ip_packet, ip_packet_len);
2028     if (ret != WIFI_SUCCESS)
2029         goto cleanup;
2030 
2031     ret = vCommand->put_addr(
2032             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR,
2033             src_mac_addr);
2034     if (ret != WIFI_SUCCESS)
2035         goto cleanup;
2036 
2037     ret = vCommand->put_addr(
2038             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR,
2039             dst_mac_addr);
2040     if (ret != WIFI_SUCCESS)
2041         goto cleanup;
2042 
2043     ret = vCommand->put_u32(
2044             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD,
2045             period_msec);
2046     if (ret != WIFI_SUCCESS)
2047         goto cleanup;
2048 
2049     vCommand->attr_end(nlData);
2050 
2051     ret = vCommand->requestResponse();
2052     if (ret != WIFI_SUCCESS)
2053         goto cleanup;
2054 
2055 cleanup:
2056     delete vCommand;
2057     return ret;
2058 }
2059 
wifi_stop_sending_offloaded_packet(wifi_request_id id,wifi_interface_handle iface)2060 wifi_error wifi_stop_sending_offloaded_packet(wifi_request_id id,
2061                                               wifi_interface_handle iface)
2062 {
2063     wifi_error ret;
2064     struct nlattr *nlData;
2065     WifiVendorCommand *vCommand = NULL;
2066 
2067     ret = initialize_vendor_cmd(iface, id,
2068                                 QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
2069                                 &vCommand);
2070     if (ret != WIFI_SUCCESS) {
2071         ALOGE("%s: Initialization failed", __func__);
2072         return ret;
2073     }
2074 
2075     /* Add the vendor specific attributes for the NL command. */
2076     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2077     if (!nlData)
2078         goto cleanup;
2079 
2080     ret = vCommand->put_u32(
2081             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL,
2082             QCA_WLAN_OFFLOADED_PACKETS_SENDING_STOP);
2083     if (ret != WIFI_SUCCESS)
2084         goto cleanup;
2085 
2086     ret = vCommand->put_u32(
2087             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID,
2088             id);
2089     if (ret != WIFI_SUCCESS)
2090         goto cleanup;
2091 
2092     vCommand->attr_end(nlData);
2093 
2094     ret = vCommand->requestResponse();
2095     if (ret != WIFI_SUCCESS)
2096         goto cleanup;
2097 
2098 cleanup:
2099     delete vCommand;
2100     return ret;
2101 }
2102 
2103 #define PACKET_FILTER_ID 0
2104 
wifi_set_packet_filter(wifi_interface_handle iface,const u8 * program,u32 len)2105 static wifi_error wifi_set_packet_filter(wifi_interface_handle iface,
2106                                          const u8 *program, u32 len)
2107 {
2108     wifi_error ret;
2109     struct nlattr *nlData;
2110     WifiVendorCommand *vCommand = NULL;
2111     u32 current_offset = 0;
2112     wifi_handle wifiHandle = getWifiHandle(iface);
2113     hal_info *info = getHalInfo(wifiHandle);
2114 
2115     /* len=0 clears the filters in driver/firmware */
2116     if (len != 0 && program == NULL) {
2117         ALOGE("%s: No valid program provided. Exit.",
2118             __func__);
2119         return WIFI_ERROR_INVALID_ARGS;
2120     }
2121 
2122     do {
2123         ret = initialize_vendor_cmd(iface, get_requestid(),
2124                                     QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
2125                                     &vCommand);
2126         if (ret != WIFI_SUCCESS) {
2127             ALOGE("%s: Initialization failed", __FUNCTION__);
2128             return ret;
2129         }
2130 
2131         /* Add the vendor specific attributes for the NL command. */
2132         nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2133         if (!nlData)
2134             goto cleanup;
2135 
2136         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
2137                                 QCA_WLAN_SET_PACKET_FILTER);
2138         if (ret != WIFI_SUCCESS)
2139             goto cleanup;
2140         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID,
2141                                 PACKET_FILTER_ID);
2142         if (ret != WIFI_SUCCESS)
2143             goto cleanup;
2144         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE,
2145                                 len);
2146         if (ret != WIFI_SUCCESS)
2147             goto cleanup;
2148         ret = vCommand->put_u32(
2149                             QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
2150                             current_offset);
2151         if (ret != WIFI_SUCCESS)
2152             goto cleanup;
2153 
2154         if (len) {
2155             ret = vCommand->put_bytes(
2156                                      QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM,
2157                                      (char *)&program[current_offset],
2158                                      min(info->firmware_bus_max_size,
2159                                      len-current_offset));
2160             if (ret!= WIFI_SUCCESS) {
2161                 ALOGE("%s: failed to put program", __FUNCTION__);
2162                 goto cleanup;
2163             }
2164         }
2165 
2166         vCommand->attr_end(nlData);
2167 
2168         ret = vCommand->requestResponse();
2169         if (ret != WIFI_SUCCESS) {
2170             ALOGE("%s: requestResponse Error:%d",__func__, ret);
2171             goto cleanup;
2172         }
2173 
2174         /* destroy the object after sending each fragment to driver */
2175         delete vCommand;
2176         vCommand = NULL;
2177 
2178         current_offset += min(info->firmware_bus_max_size, len);
2179     } while (current_offset < len);
2180 
2181     info->apf_enabled = !!len;
2182 
2183 cleanup:
2184     if (vCommand)
2185         delete vCommand;
2186     return ret;
2187 }
2188 
wifi_get_packet_filter_capabilities(wifi_interface_handle handle,u32 * version,u32 * max_len)2189 static wifi_error wifi_get_packet_filter_capabilities(
2190                 wifi_interface_handle handle, u32 *version, u32 *max_len)
2191 {
2192     wifi_error ret;
2193     struct nlattr *nlData;
2194     WifihalGeneric *vCommand = NULL;
2195     interface_info *ifaceInfo = getIfaceInfo(handle);
2196     wifi_handle wifiHandle = getWifiHandle(handle);
2197 
2198     if (version == NULL || max_len == NULL) {
2199         ALOGE("%s: NULL version/max_len pointer provided. Exit.",
2200             __FUNCTION__);
2201         return WIFI_ERROR_INVALID_ARGS;
2202     }
2203 
2204     vCommand = new WifihalGeneric(wifiHandle, 0,
2205             OUI_QCA,
2206             QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER);
2207     if (vCommand == NULL) {
2208         ALOGE("%s: Error vCommand NULL", __FUNCTION__);
2209         return WIFI_ERROR_OUT_OF_MEMORY;
2210     }
2211 
2212     /* Create the message */
2213     ret = vCommand->create();
2214     if (ret != WIFI_SUCCESS)
2215         goto cleanup;
2216 
2217     ret = vCommand->set_iface_id(ifaceInfo->name);
2218     if (ret != WIFI_SUCCESS)
2219         goto cleanup;
2220 
2221     /* Add the vendor specific attributes for the NL command. */
2222     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2223     if (!nlData)
2224         goto cleanup;
2225 
2226     ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
2227                             QCA_WLAN_GET_PACKET_FILTER);
2228     if (ret != WIFI_SUCCESS)
2229         goto cleanup;
2230 
2231     vCommand->attr_end(nlData);
2232 
2233     ret = vCommand->requestResponse();
2234     if (ret != WIFI_SUCCESS) {
2235         ALOGE("%s: requestResponse() error: %d", __FUNCTION__, ret);
2236         if (ret == WIFI_ERROR_NOT_SUPPORTED) {
2237             /* Packet filtering is not supported currently, so return version
2238              * and length as 0
2239              */
2240             ALOGI("Packet filtering is not supprted");
2241             *version = 0;
2242             *max_len = 0;
2243             ret = WIFI_SUCCESS;
2244         }
2245         goto cleanup;
2246     }
2247 
2248     *version = vCommand->getFilterVersion();
2249     *max_len = vCommand->getFilterLength();
2250 cleanup:
2251     delete vCommand;
2252     return ret;
2253 }
2254 
2255 
wifi_configure_nd_offload(wifi_interface_handle iface,u8 enable)2256 static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface,
2257                                             u8 enable)
2258 {
2259     wifi_error ret;
2260     struct nlattr *nlData;
2261     WifiVendorCommand *vCommand = NULL;
2262 
2263     ret = initialize_vendor_cmd(iface, get_requestid(),
2264                                 QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
2265                                 &vCommand);
2266     if (ret != WIFI_SUCCESS) {
2267         ALOGE("%s: Initialization failed", __func__);
2268         return ret;
2269     }
2270 
2271     ALOGV("ND offload : %s", enable?"Enable":"Disable");
2272 
2273     /* Add the vendor specific attributes for the NL command. */
2274     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2275     if (!nlData)
2276         goto cleanup;
2277 
2278     ret = vCommand->put_u8(QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG, enable);
2279     if (ret != WIFI_SUCCESS)
2280         goto cleanup;
2281 
2282     vCommand->attr_end(nlData);
2283 
2284     ret = vCommand->requestResponse();
2285 
2286 cleanup:
2287     delete vCommand;
2288     return ret;
2289 }
2290 
2291 /**
2292  * Copy 'len' bytes of raw data from host memory at source address 'program'
2293  * to APF (Android Packet Filter) working memory starting at offset 'dst_offset'.
2294  * The size of the program lenght passed to the interpreter is set to
2295  * 'progaram_lenght'
2296  *
2297  * The implementation is allowed to tranlate this wrtie into a series of smaller
2298  * writes,but this function is not allowed to return untill all write operations
2299  * have been completed
2300  * additionally visible memory not targeted by this function must remain
2301  * unchanged
2302 
2303  * @param dst_offset write offset in bytes relative to the beginning of the APF
2304  * working memory with logical address 0X000. Must be a multiple of 4
2305  *
2306  * @param program host memory to copy bytes from. Must be 4B aligned
2307  *
2308  * @param len the number of bytes to copy from the bost into the APF working
2309  * memory
2310  *
2311  * @param program_length new length of the program instructions in bytes to pass
2312  * to the interpreter
2313  */
2314 
wifi_write_packet_filter(wifi_interface_handle iface,u32 dst_offset,const u8 * program,u32 len,u32 program_length)2315 wifi_error wifi_write_packet_filter(wifi_interface_handle iface,
2316                                          u32 dst_offset, const u8 *program,
2317                                          u32 len, u32 program_length)
2318 {
2319     wifi_error ret;
2320     struct nlattr *nlData;
2321     WifiVendorCommand *vCommand = NULL;
2322     u32 current_offset = 0;
2323     wifi_handle wifiHandle = getWifiHandle(iface);
2324     hal_info *info = getHalInfo(wifiHandle);
2325 
2326     /* len=0 clears the filters in driver/firmware */
2327     if (len != 0 && program == NULL) {
2328         ALOGE("%s: No valid program provided. Exit.",
2329             __func__);
2330         return WIFI_ERROR_INVALID_ARGS;
2331     }
2332 
2333     do {
2334         ret = initialize_vendor_cmd(iface, get_requestid(),
2335                                     QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
2336                                     &vCommand);
2337         if (ret != WIFI_SUCCESS) {
2338             ALOGE("%s: Initialization failed", __FUNCTION__);
2339             return ret;
2340         }
2341 
2342         /* Add the vendor specific attributes for the NL command. */
2343         nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2344         if (!nlData)
2345              goto cleanup;
2346 
2347         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
2348                                  QCA_WLAN_WRITE_PACKET_FILTER);
2349         if (ret != WIFI_SUCCESS)
2350             goto cleanup;
2351         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID,
2352                                 PACKET_FILTER_ID);
2353         if (ret != WIFI_SUCCESS)
2354             goto cleanup;
2355         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE,
2356                                 len);
2357         if (ret != WIFI_SUCCESS)
2358             goto cleanup;
2359         ret = vCommand->put_u32(
2360                             QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
2361                             dst_offset + current_offset);
2362         if (ret != WIFI_SUCCESS)
2363             goto cleanup;
2364         ret = vCommand->put_u32(
2365                            QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROG_LENGTH,
2366                             program_length);
2367         if (ret != WIFI_SUCCESS)
2368             goto cleanup;
2369 
2370         ret = vCommand->put_bytes(
2371                                  QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM,
2372                                  (char *)&program[current_offset],
2373                                  min(info->firmware_bus_max_size,
2374                                  len - current_offset));
2375         if (ret!= WIFI_SUCCESS) {
2376             ALOGE("%s: failed to put program", __FUNCTION__);
2377             goto cleanup;
2378         }
2379 
2380         vCommand->attr_end(nlData);
2381 
2382         ret = vCommand->requestResponse();
2383        if (ret != WIFI_SUCCESS) {
2384             ALOGE("%s: requestResponse Error:%d",__func__, ret);
2385             goto cleanup;
2386         }
2387 
2388         /* destroy the object after sending each fragment to driver */
2389         delete vCommand;
2390         vCommand = NULL;
2391 
2392         current_offset += min(info->firmware_bus_max_size,
2393                                          len - current_offset);
2394     } while (current_offset < len);
2395 
2396 cleanup:
2397     if (vCommand)
2398         delete vCommand;
2399     return ret;
2400 }
2401 
wifi_enable_packet_filter(wifi_interface_handle handle,u32 enable)2402 wifi_error wifi_enable_packet_filter(wifi_interface_handle handle,
2403                                         u32 enable)
2404 {
2405     wifi_error ret;
2406     struct nlattr *nlData;
2407     WifiVendorCommand *vCommand = NULL;
2408     u32 subcmd;
2409     wifi_handle wifiHandle = getWifiHandle(handle);
2410     hal_info *info = getHalInfo(wifiHandle);
2411 
2412     ret = initialize_vendor_cmd(handle, get_requestid(),
2413                                 QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
2414                                 &vCommand);
2415 
2416     if (ret != WIFI_SUCCESS) {
2417         ALOGE("%s: Initialization failed", __func__);
2418         return ret;
2419     }
2420     /* Add the vendor specific attributes for the NL command. */
2421     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2422     if (!nlData)
2423         goto cleanup;
2424 
2425     subcmd = enable ? QCA_WLAN_ENABLE_PACKET_FILTER :
2426                       QCA_WLAN_DISABLE_PACKET_FILTER;
2427     ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
2428                             subcmd);
2429     if (ret != WIFI_SUCCESS)
2430             goto cleanup;
2431 
2432     vCommand->attr_end(nlData);
2433     ret = vCommand->requestResponse();
2434 
2435     if (ret != WIFI_SUCCESS) {
2436         ALOGE("%s: requestResponse() error: %d", __FUNCTION__, ret);
2437         goto cleanup;
2438     }
2439 
2440     info->apf_enabled = !!enable;
2441 
2442 cleanup:
2443     if (vCommand)
2444         delete vCommand;
2445     return ret;
2446 
2447 }
2448 
2449 /**
2450  * Copy 'length' bytes of raw data from APF (Android Packet Filter) working
2451  * memory  to host memory starting at offset src_offset into host memory
2452  * pointed to by host_dst.
2453  * Memory can be text, data or some combination of the two. The implementiion is
2454  * allowed to translate this read into a series of smaller reads, but this
2455  * function is not allowed to return untill all the reads operations
2456  * into host_dst have been completed.
2457  *
2458  * @param src_offset offset in bytes of destination memory within APF working
2459  * memory
2460  *
2461  * @param host_dst host memory to copy into. Must be 4B aligned.
2462  *
2463  * @param length the number of bytes to copy from the APF working memory to the
2464  * host.
2465  */
2466 
wifi_read_packet_filter(wifi_interface_handle handle,u32 src_offset,u8 * host_dst,u32 length)2467 static wifi_error wifi_read_packet_filter(wifi_interface_handle handle,
2468                                           u32 src_offset, u8 *host_dst, u32 length)
2469 {
2470     wifi_error ret = WIFI_SUCCESS;
2471     struct nlattr *nlData;
2472     WifihalGeneric *vCommand = NULL;
2473     interface_info *ifaceInfo = getIfaceInfo(handle);
2474     wifi_handle wifiHandle = getWifiHandle(handle);
2475     hal_info *info = getHalInfo(wifiHandle);
2476 
2477     /* Length to be passed to this function should be non-zero
2478      * Return invalid argument if length is passed as zero
2479      */
2480     if (length == 0)
2481         return  WIFI_ERROR_INVALID_ARGS;
2482 
2483     /*Temporary varibles to support the read complete length in chunks */
2484     u8 *temp_host_dst;
2485     u32 remainingLengthToBeRead, currentLength;
2486     u8 apf_locally_disabled = 0;
2487 
2488     /*Initializing the temporary variables*/
2489     temp_host_dst = host_dst;
2490     remainingLengthToBeRead = length;
2491 
2492     if (info->apf_enabled) {
2493         /* Disable APF only when not disabled by framework before calling
2494          * wifi_read_packet_filter()
2495          */
2496         ret = wifi_enable_packet_filter(handle, 0);
2497         if (ret != WIFI_SUCCESS) {
2498             ALOGE("%s: Failed to disable APF", __FUNCTION__);
2499             return ret;
2500         }
2501         apf_locally_disabled = 1;
2502     }
2503     /**
2504      * Read the complete length in chunks of size less or equal to firmware bus
2505      * max size
2506      */
2507     while (remainingLengthToBeRead)
2508     {
2509         vCommand = new WifihalGeneric(wifiHandle, 0, OUI_QCA,
2510                                       QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER);
2511 
2512         if (vCommand == NULL) {
2513             ALOGE("%s: Error vCommand NULL", __FUNCTION__);
2514             ret = WIFI_ERROR_OUT_OF_MEMORY;
2515             break;
2516         }
2517 
2518         /* Create the message */
2519         ret = vCommand->create();
2520         if (ret != WIFI_SUCCESS)
2521             break;
2522         ret = vCommand->set_iface_id(ifaceInfo->name);
2523         if (ret != WIFI_SUCCESS)
2524             break;
2525         /* Add the vendor specific attributes for the NL command. */
2526         nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2527         if (!nlData)
2528             break;
2529         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
2530                                 QCA_WLAN_READ_PACKET_FILTER);
2531         if (ret != WIFI_SUCCESS)
2532             break;
2533 
2534         currentLength = min(remainingLengthToBeRead, info->firmware_bus_max_size);
2535 
2536         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE,
2537                                 currentLength);
2538         if (ret != WIFI_SUCCESS)
2539             break;
2540         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
2541                                 src_offset);
2542         if (ret != WIFI_SUCCESS)
2543             break;
2544 
2545         vCommand->setPacketBufferParams(temp_host_dst, currentLength);
2546         vCommand->attr_end(nlData);
2547         ret = vCommand->requestResponse();
2548 
2549         if (ret != WIFI_SUCCESS) {
2550             ALOGE("%s: requestResponse() error: %d current_len = %u, src_offset = %u",
2551                   __FUNCTION__, ret, currentLength, src_offset);
2552             break;
2553         }
2554 
2555         remainingLengthToBeRead -= currentLength;
2556         temp_host_dst += currentLength;
2557         src_offset += currentLength;
2558         delete vCommand;
2559         vCommand = NULL;
2560     }
2561 
2562     /* Re enable APF only when disabled above within this API */
2563     if (apf_locally_disabled) {
2564         wifi_error status;
2565         status = wifi_enable_packet_filter(handle, 1);
2566         if (status != WIFI_SUCCESS)
2567             ALOGE("%s: Failed to enable APF", __FUNCTION__);
2568         /* Prefer to return read status if read fails */
2569         if (ret == WIFI_SUCCESS)
2570             ret = status;
2571     }
2572 
2573     delete vCommand;
2574     return ret;
2575 }
2576