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_virtual_interface_create = wifi_virtual_interface_create;
575     fn->wifi_virtual_interface_delete = wifi_virtual_interface_delete;
576     fn->wifi_set_latency_mode = wifi_set_latency_mode;
577     fn->wifi_set_thermal_mitigation_mode = wifi_set_thermal_mitigation_mode;
578 
579     return WIFI_SUCCESS;
580 }
581 
cld80211lib_cleanup(hal_info * info)582 static void cld80211lib_cleanup(hal_info *info)
583 {
584     if (!info->cldctx)
585         return;
586     cld80211_remove_mcast_group(info->cldctx, "host_logs");
587     cld80211_remove_mcast_group(info->cldctx, "fw_logs");
588     cld80211_remove_mcast_group(info->cldctx, "per_pkt_stats");
589     cld80211_remove_mcast_group(info->cldctx, "diag_events");
590     cld80211_remove_mcast_group(info->cldctx, "fatal_events");
591     cld80211_remove_mcast_group(info->cldctx, "oem_msgs");
592     exit_cld80211_recv(info->cldctx);
593     cld80211_deinit(info->cldctx);
594     info->cldctx = NULL;
595 }
596 
wifi_get_iface_id(hal_info * info,const char * iface)597 static int wifi_get_iface_id(hal_info *info, const char *iface)
598 {
599     int i;
600     for (i = 0; i < info->num_interfaces; i++)
601         if (!strcmp(info->interfaces[i]->name, iface))
602             return i;
603     return -1;
604 }
605 
wifi_initialize(wifi_handle * handle)606 wifi_error wifi_initialize(wifi_handle *handle)
607 {
608     wifi_error ret = WIFI_SUCCESS;
609     wifi_interface_handle iface_handle;
610     struct nl_sock *cmd_sock = NULL;
611     struct nl_sock *event_sock = NULL;
612     struct nl_cb *cb = NULL;
613     int status = 0;
614     int index;
615     char hw_ver_type[MAX_HW_VER_LENGTH];
616     char *hw_name = NULL;
617 
618     ALOGI("Initializing wifi");
619     hal_info *info = (hal_info *)malloc(sizeof(hal_info));
620     if (info == NULL) {
621         ALOGE("Could not allocate hal_info");
622         return WIFI_ERROR_OUT_OF_MEMORY;
623     }
624 
625     memset(info, 0, sizeof(*info));
626 
627     cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT,
628                                                      NETLINK_GENERIC);
629     if (cmd_sock == NULL) {
630         ALOGE("Failed to create command socket port");
631         ret = WIFI_ERROR_UNKNOWN;
632         goto unload;
633     }
634 
635     /* Set the socket buffer size */
636     if (nl_socket_set_buffer_size(cmd_sock, (256*1024), 0) < 0) {
637         ALOGE("Could not set nl_socket RX buffer size for cmd_sock: %s",
638                    strerror(errno));
639         /* continue anyway with the default (smaller) buffer */
640     }
641 
642     event_sock =
643         wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT, NETLINK_GENERIC);
644     if (event_sock == NULL) {
645         ALOGE("Failed to create event socket port");
646         ret = WIFI_ERROR_UNKNOWN;
647         goto unload;
648     }
649 
650     /* Set the socket buffer size */
651     if (nl_socket_set_buffer_size(event_sock, (256*1024), 0) < 0) {
652         ALOGE("Could not set nl_socket RX buffer size for event_sock: %s",
653                    strerror(errno));
654         /* continue anyway with the default (smaller) buffer */
655     }
656 
657     cb = nl_socket_get_cb(event_sock);
658     if (cb == NULL) {
659         ALOGE("Failed to get NL control block for event socket port");
660         ret = WIFI_ERROR_UNKNOWN;
661         goto unload;
662     }
663 
664     info->event_sock_arg = 1;
665     nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
666     nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &info->event_sock_arg);
667     nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &info->event_sock_arg);
668     nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &info->event_sock_arg);
669 
670     nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler,
671             info);
672     nl_cb_put(cb);
673 
674     info->cmd_sock = cmd_sock;
675     info->event_sock = event_sock;
676     info->clean_up = false;
677     info->in_event_loop = false;
678 
679     info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE);
680     if (info->event_cb == NULL) {
681         ALOGE("Could not allocate event_cb");
682         ret = WIFI_ERROR_OUT_OF_MEMORY;
683         goto unload;
684     }
685     info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE;
686     info->num_event_cb = 0;
687 
688     info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211");
689     if (info->nl80211_family_id < 0) {
690         ALOGE("Could not resolve nl80211 familty id");
691         ret = WIFI_ERROR_UNKNOWN;
692         goto unload;
693     }
694 
695     pthread_mutex_init(&info->cb_lock, NULL);
696     pthread_mutex_init(&info->pkt_fate_stats_lock, NULL);
697 
698     *handle = (wifi_handle) info;
699 
700     wifi_add_membership(*handle, "scan");
701     wifi_add_membership(*handle, "mlme");
702     wifi_add_membership(*handle, "regulatory");
703     wifi_add_membership(*handle, "vendor");
704 
705     info->wifihal_ctrl_sock.s = 0;
706 
707     wifi_create_ctrl_socket(info);
708 
709     //! Initailise the monitoring clients list
710     INITIALISE_LIST(&info->monitor_sockets);
711 
712     info->cldctx = cld80211_init();
713     if (info->cldctx != NULL) {
714         info->user_sock = info->cldctx->sock;
715         ret = wifi_init_cld80211_sock_cb(info);
716         if (ret != WIFI_SUCCESS) {
717             ALOGE("Could not set cb for CLD80211 family");
718             goto cld80211_cleanup;
719         }
720 
721         status = cld80211_add_mcast_group(info->cldctx, "host_logs");
722         if (status) {
723             ALOGE("Failed to add mcast group host_logs :%d", status);
724             goto cld80211_cleanup;
725         }
726         status = cld80211_add_mcast_group(info->cldctx, "fw_logs");
727         if (status) {
728             ALOGE("Failed to add mcast group fw_logs :%d", status);
729             goto cld80211_cleanup;
730         }
731         status = cld80211_add_mcast_group(info->cldctx, "per_pkt_stats");
732         if (status) {
733             ALOGE("Failed to add mcast group per_pkt_stats :%d", status);
734             goto cld80211_cleanup;
735         }
736         status = cld80211_add_mcast_group(info->cldctx, "diag_events");
737         if (status) {
738             ALOGE("Failed to add mcast group diag_events :%d", status);
739             goto cld80211_cleanup;
740         }
741         status = cld80211_add_mcast_group(info->cldctx, "fatal_events");
742         if (status) {
743             ALOGE("Failed to add mcast group fatal_events :%d", status);
744             goto cld80211_cleanup;
745         }
746 
747         if(info->wifihal_ctrl_sock.s > 0)
748         {
749           status = cld80211_add_mcast_group(info->cldctx, "oem_msgs");
750           if (status) {
751              ALOGE("Failed to add mcast group oem_msgs :%d", status);
752              goto cld80211_cleanup;
753           }
754         }
755     } else {
756         ret = wifi_init_user_sock(info);
757         if (ret != WIFI_SUCCESS) {
758             ALOGE("Failed to alloc user socket");
759             goto unload;
760         }
761     }
762 
763     ret = wifi_init_interfaces(*handle);
764     if (ret != WIFI_SUCCESS) {
765         ALOGE("Failed to init interfaces");
766         goto unload;
767     }
768 
769     if (info->num_interfaces == 0) {
770         ALOGE("No interfaces found");
771         ret = WIFI_ERROR_UNINITIALIZED;
772         goto unload;
773     }
774 
775     index = wifi_get_iface_id(info, "wlan0");
776     if (index == -1) {
777         int i;
778         for (i = 0; i < info->num_interfaces; i++)
779         {
780             free(info->interfaces[i]);
781         }
782         ALOGE("%s no iface with wlan0", __func__);
783         goto unload;
784     }
785     iface_handle = (wifi_interface_handle)info->interfaces[index];
786 
787     ret = acquire_supported_features(iface_handle,
788             &info->supported_feature_set);
789     if (ret != WIFI_SUCCESS) {
790         ALOGI("Failed to get supported feature set : %d", ret);
791         //acquire_supported_features failure is acceptable condition as legacy
792         //drivers might not support the required vendor command. So, do not
793         //consider it as failure of wifi_initialize
794         ret = WIFI_SUCCESS;
795     }
796 
797     ret = acquire_driver_supported_features(iface_handle,
798                                   &info->driver_supported_features);
799     if (ret != WIFI_SUCCESS) {
800         ALOGI("Failed to get vendor feature set : %d", ret);
801         ret = WIFI_SUCCESS;
802     }
803 
804     ret =  wifi_get_logger_supported_feature_set(iface_handle,
805                          &info->supported_logger_feature_set);
806     if (ret != WIFI_SUCCESS)
807         ALOGE("Failed to get supported logger feature set: %d", ret);
808 
809     ret =  wifi_get_firmware_version(iface_handle, hw_ver_type,
810                                      MAX_HW_VER_LENGTH);
811     if (ret == WIFI_SUCCESS) {
812         hw_name = strstr(hw_ver_type, "HW:");
813         if (hw_name) {
814             hw_name += strlen("HW:");
815             if (strncmp(hw_name, "QCA6174", 7) == 0)
816                info->pkt_log_ver = PKT_LOG_V1;
817             else
818                info->pkt_log_ver = PKT_LOG_V2;
819         } else {
820            info->pkt_log_ver = PKT_LOG_V0;
821         }
822         ALOGV("%s: hardware version type %d", __func__, info->pkt_log_ver);
823     } else {
824         ALOGE("Failed to get firmware version: %d", ret);
825     }
826 
827     ret = get_firmware_bus_max_size_supported(iface_handle);
828     if (ret != WIFI_SUCCESS) {
829         ALOGE("Failed to get supported bus size, error : %d", ret);
830         info->firmware_bus_max_size = 1520;
831     }
832 
833     ret = wifi_logger_ring_buffers_init(info);
834     if (ret != WIFI_SUCCESS)
835         ALOGE("Wifi Logger Ring Initialization Failed");
836 
837     ret = wifi_get_capabilities(iface_handle);
838     if (ret != WIFI_SUCCESS)
839         ALOGE("Failed to get wifi Capabilities, error: %d", ret);
840 
841     info->pkt_stats = (struct pkt_stats_s *)malloc(sizeof(struct pkt_stats_s));
842     if (!info->pkt_stats) {
843         ALOGE("%s: malloc Failed for size: %zu",
844                 __FUNCTION__, sizeof(struct pkt_stats_s));
845         ret = WIFI_ERROR_OUT_OF_MEMORY;
846         goto unload;
847     }
848 
849     info->rx_buf_size_allocated = MAX_RXMPDUS_PER_AMPDU * MAX_MSDUS_PER_MPDU
850                                   * PKT_STATS_BUF_SIZE;
851 
852     info->rx_aggr_pkts =
853         (wifi_ring_buffer_entry  *)malloc(info->rx_buf_size_allocated);
854     if (!info->rx_aggr_pkts) {
855         ALOGE("%s: malloc Failed for size: %d",
856                 __FUNCTION__, info->rx_buf_size_allocated);
857         ret = WIFI_ERROR_OUT_OF_MEMORY;
858         info->rx_buf_size_allocated = 0;
859         goto unload;
860     }
861     memset(info->rx_aggr_pkts, 0, info->rx_buf_size_allocated);
862 
863     info->exit_sockets[0] = -1;
864     info->exit_sockets[1] = -1;
865 
866     if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->exit_sockets) == -1) {
867         ALOGE("Failed to create exit socket pair");
868         ret = WIFI_ERROR_UNKNOWN;
869         goto unload;
870     }
871 
872     ALOGV("Initializing Gscan Event Handlers");
873     ret = initializeGscanHandlers(info);
874     if (ret != WIFI_SUCCESS) {
875         ALOGE("Initializing Gscan Event Handlers Failed");
876         goto unload;
877     }
878 
879     ret = initializeRSSIMonitorHandler(info);
880     if (ret != WIFI_SUCCESS) {
881         ALOGE("Initializing RSSI Event Handler Failed");
882         goto unload;
883     }
884 
885     ALOGV("Initialized Wifi HAL Successfully; vendor cmd = %d Supported"
886             " features : 0x%" PRIx64, NL80211_CMD_VENDOR, info->supported_feature_set);
887 
888 cld80211_cleanup:
889     if (status != 0 || ret != WIFI_SUCCESS) {
890         ret = WIFI_ERROR_UNKNOWN;
891         cld80211lib_cleanup(info);
892     }
893 unload:
894     if (ret != WIFI_SUCCESS) {
895         if (cmd_sock)
896             nl_socket_free(cmd_sock);
897         if (event_sock)
898             nl_socket_free(event_sock);
899         if (info) {
900             if (info->cldctx) {
901                 cld80211lib_cleanup(info);
902             } else if (info->user_sock) {
903                 nl_socket_free(info->user_sock);
904             }
905             if (info->pkt_stats) free(info->pkt_stats);
906             if (info->rx_aggr_pkts) free(info->rx_aggr_pkts);
907             wifi_logger_ring_buffers_deinit(info);
908             cleanupGscanHandlers(info);
909             cleanupRSSIMonitorHandler(info);
910             free(info->event_cb);
911             if (info->driver_supported_features.flags) {
912                 free(info->driver_supported_features.flags);
913                 info->driver_supported_features.flags = NULL;
914             }
915             free(info);
916         }
917     }
918 
919     return ret;
920 }
921 
922 #ifdef WIFI_DRIVER_STATE_CTRL_PARAM
wifi_update_driver_state(const char * state)923 static int wifi_update_driver_state(const char *state) {
924     struct timespec ts;
925     int len, fd, ret = 0, count = 5;
926     ts.tv_sec = 0;
927     ts.tv_nsec = 200 * 1000000L;
928 
929     do {
930         if (access(WIFI_DRIVER_STATE_CTRL_PARAM, W_OK) == 0)
931             break;
932         nanosleep(&ts, (struct timespec *)NULL);
933     } while (--count > 0); /* wait at most 1 second for completion. */
934     if (count == 0) {
935         ALOGE("Failed to access driver state control param %s, %d at %s",
936               strerror(errno), errno, WIFI_DRIVER_STATE_CTRL_PARAM);
937         return -1;
938     }
939 
940     fd = TEMP_FAILURE_RETRY(open(WIFI_DRIVER_STATE_CTRL_PARAM, O_WRONLY));
941     if (fd < 0) {
942         ALOGE("Failed to open driver state control param at %s",
943               WIFI_DRIVER_STATE_CTRL_PARAM);
944         return -1;
945     }
946 
947     len = strlen(state) + 1;
948     if (TEMP_FAILURE_RETRY(write(fd, state, len)) != len) {
949         ALOGE("Failed to write driver state control param at %s",
950               WIFI_DRIVER_STATE_CTRL_PARAM);
951         ret = -1;
952     }
953 
954     close(fd);
955     return ret;
956 }
957 #endif
958 
wifi_wait_for_driver_ready(void)959 wifi_error wifi_wait_for_driver_ready(void)
960 {
961     // This function will wait to make sure basic client netdev is created
962     // Function times out after 10 seconds
963     int count = (POLL_DRIVER_MAX_TIME_MS * 1000) / POLL_DRIVER_DURATION_US;
964     FILE *fd;
965 
966 #if defined(WIFI_DRIVER_STATE_CTRL_PARAM) && defined(WIFI_DRIVER_STATE_ON)
967     if (wifi_update_driver_state(WIFI_DRIVER_STATE_ON) < 0) {
968         return WIFI_ERROR_UNKNOWN;
969     }
970 #endif
971 
972     do {
973         if ((fd = fopen("/sys/class/net/wlan0", "r")) != NULL) {
974             fclose(fd);
975             return WIFI_SUCCESS;
976         }
977         usleep(POLL_DRIVER_DURATION_US);
978     } while(--count > 0);
979 
980     ALOGE("Timed out wating on Driver ready ... ");
981     return WIFI_ERROR_TIMED_OUT;
982 }
983 
wifi_add_membership(wifi_handle handle,const char * group)984 static int wifi_add_membership(wifi_handle handle, const char *group)
985 {
986     hal_info *info = getHalInfo(handle);
987 
988     int id = wifi_get_multicast_id(handle, "nl80211", group);
989     if (id < 0) {
990         ALOGE("Could not find group %s", group);
991         return id;
992     }
993 
994     int ret = nl_socket_add_membership(info->event_sock, id);
995     if (ret < 0) {
996         ALOGE("Could not add membership to group %s", group);
997     }
998 
999     return ret;
1000 }
1001 
internal_cleaned_up_handler(wifi_handle handle)1002 static void internal_cleaned_up_handler(wifi_handle handle)
1003 {
1004     hal_info *info = getHalInfo(handle);
1005     wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler;
1006     wifihal_mon_sock_t *reg, *tmp;
1007 
1008     if (info->cmd_sock != 0) {
1009         nl_socket_free(info->cmd_sock);
1010         nl_socket_free(info->event_sock);
1011         info->cmd_sock = NULL;
1012         info->event_sock = NULL;
1013     }
1014 
1015     if (info->wifihal_ctrl_sock.s != 0) {
1016         close(info->wifihal_ctrl_sock.s);
1017         unlink(info->wifihal_ctrl_sock.local.sun_path);
1018         info->wifihal_ctrl_sock.s = 0;
1019     }
1020 
1021    list_for_each_entry_safe(reg, tmp, &info->monitor_sockets, list) {
1022         del_from_list(&reg->list);
1023         if(reg) {
1024            free(reg);
1025         }
1026     }
1027 
1028     if (info->interfaces) {
1029         for (int i = 0; i < info->num_interfaces; i++)
1030             free(info->interfaces[i]);
1031         free(info->interfaces);
1032     }
1033 
1034     if (info->cldctx != NULL) {
1035         cld80211lib_cleanup(info);
1036     } else if (info->user_sock != 0) {
1037         nl_socket_free(info->user_sock);
1038         info->user_sock = NULL;
1039     }
1040 
1041     if (info->pkt_stats)
1042         free(info->pkt_stats);
1043     if (info->rx_aggr_pkts)
1044         free(info->rx_aggr_pkts);
1045     wifi_logger_ring_buffers_deinit(info);
1046     cleanupGscanHandlers(info);
1047     cleanupRSSIMonitorHandler(info);
1048 
1049     if (info->num_event_cb)
1050         ALOGE("%d events were leftover without being freed",
1051               info->num_event_cb);
1052     free(info->event_cb);
1053 
1054     if (info->exit_sockets[0] >= 0) {
1055         close(info->exit_sockets[0]);
1056         info->exit_sockets[0] = -1;
1057     }
1058 
1059     if (info->exit_sockets[1] >= 0) {
1060         close(info->exit_sockets[1]);
1061         info->exit_sockets[1] = -1;
1062     }
1063 
1064     if (info->pkt_fate_stats) {
1065         free(info->pkt_fate_stats);
1066         info->pkt_fate_stats = NULL;
1067     }
1068 
1069     if (info->driver_supported_features.flags) {
1070         free(info->driver_supported_features.flags);
1071         info->driver_supported_features.flags = NULL;
1072     }
1073 
1074     (*cleaned_up_handler)(handle);
1075     pthread_mutex_destroy(&info->cb_lock);
1076     pthread_mutex_destroy(&info->pkt_fate_stats_lock);
1077     free(info);
1078 }
1079 
wifi_cleanup(wifi_handle handle,wifi_cleaned_up_handler handler)1080 void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
1081 {
1082     if (!handle) {
1083         ALOGE("Handle is null");
1084         return;
1085     }
1086 
1087     hal_info *info = getHalInfo(handle);
1088     info->cleaned_up_handler = handler;
1089     info->clean_up = true;
1090     // Remove the dynamically created interface during wifi cleanup.
1091     wifi_cleanup_dynamic_ifaces(handle);
1092 
1093 
1094     TEMP_FAILURE_RETRY(write(info->exit_sockets[0], "E", 1));
1095     ALOGI("Sent msg on exit sock to unblock poll()");
1096 }
1097 
1098 
1099 
validate_cld80211_msg(nlmsghdr * nlh,int family,int cmd)1100 static int validate_cld80211_msg(nlmsghdr *nlh, int family, int cmd)
1101 {
1102     //! Enhance this API
1103     struct genlmsghdr *hdr;
1104     hdr = (genlmsghdr *)nlmsg_data(nlh);
1105 
1106     if (nlh->nlmsg_len > DEFAULT_PAGE_SIZE - sizeof(wifihal_ctrl_req_t))
1107     {
1108       ALOGE("%s: Invalid nlmsg length", __FUNCTION__);
1109       return -1;
1110     }
1111     if(hdr->cmd == WLAN_NL_MSG_OEM)
1112     {
1113       ALOGV("%s: FAMILY ID : %d ,NL CMD : %d received", __FUNCTION__,
1114              nlh->nlmsg_type, hdr->cmd);
1115 
1116       //! Update pid with the wifihal pid
1117       nlh->nlmsg_pid = getpid();
1118       return 0;
1119     }
1120     else
1121     {
1122       ALOGE("%s: NL CMD : %d received is not allowed", __FUNCTION__, hdr->cmd);
1123       return -1;
1124     }
1125 }
1126 
1127 
validate_genl_msg(nlmsghdr * nlh,int family,int cmd)1128 static int validate_genl_msg(nlmsghdr *nlh, int family, int cmd)
1129 {
1130     //! Enhance this API
1131     struct genlmsghdr *hdr;
1132     hdr = (genlmsghdr *)nlmsg_data(nlh);
1133 
1134     if (nlh->nlmsg_len > DEFAULT_PAGE_SIZE - sizeof(wifihal_ctrl_req_t))
1135     {
1136       ALOGE("%s: Invalid nlmsg length", __FUNCTION__);
1137       return -1;
1138     }
1139     if(hdr->cmd == NL80211_CMD_FRAME ||
1140        hdr->cmd == NL80211_CMD_REGISTER_ACTION)
1141     {
1142       ALOGV("%s: FAMILY ID : %d ,NL CMD : %d received", __FUNCTION__,
1143              nlh->nlmsg_type, hdr->cmd);
1144       return 0;
1145     }
1146     else
1147     {
1148       ALOGE("%s: NL CMD : %d received is not allowed", __FUNCTION__, hdr->cmd);
1149       return -1;
1150     }
1151 }
1152 
send_nl_data(wifi_handle handle,wifihal_ctrl_req_t * ctrl_msg)1153 static int send_nl_data(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg)
1154 {
1155     hal_info *info = getHalInfo(handle);
1156     struct nl_msg *msg = NULL;
1157     int retval = -1;
1158 
1159     //! attach monitor socket if it was not it the list
1160     if(ctrl_msg->monsock_len)
1161     {
1162       retval = attach_monitor_sock(handle, ctrl_msg);
1163       if(retval)
1164         goto nl_out;
1165     }
1166 
1167     msg = nlmsg_alloc();
1168     if (!msg)
1169     {
1170        ALOGE("%s: Memory allocation failed \n", __FUNCTION__);
1171        goto nl_out;
1172     }
1173 
1174     if (ctrl_msg->data_len > nlmsg_get_max_size(msg))
1175     {
1176         ALOGE("%s: Invalid ctrl msg length \n", __FUNCTION__);
1177         retval = -1;
1178         goto nl_out;
1179     }
1180     memcpy((char *)msg->nm_nlh, (char *)ctrl_msg->data, ctrl_msg->data_len);
1181 
1182    if(ctrl_msg->family_name == GENERIC_NL_FAMILY)
1183    {
1184      //! Before sending the received gennlmsg to kernel,
1185      //! better to have checks for allowed commands
1186      retval = validate_genl_msg(msg->nm_nlh, ctrl_msg->family_name, ctrl_msg->cmd_id);
1187      if (retval < 0)
1188          goto nl_out;
1189 
1190      retval = nl_send_auto_complete(info->event_sock, msg);    /* send message */
1191      if (retval < 0)
1192      {
1193        ALOGE("%s: nl_send_auto_complete - failed : %d \n", __FUNCTION__, retval);
1194        goto nl_out;
1195      }
1196 
1197      retval = internal_pollin_handler(handle, info->event_sock);
1198   }
1199   else if (ctrl_msg->family_name == CLD80211_FAMILY)
1200   {
1201     if (info->cldctx != NULL)
1202     {
1203       //! Before sending the received cld80211 msg to kernel,
1204       //! better to have checks for allowed commands
1205       retval = validate_cld80211_msg(msg->nm_nlh, ctrl_msg->family_name, ctrl_msg->cmd_id);
1206       if (retval < 0)
1207          goto nl_out;
1208 
1209       retval = cld80211_send_msg(info->cldctx, msg);
1210       if (retval != 0)
1211       {
1212         ALOGE("%s: send cld80211 message - failed\n", __FUNCTION__);
1213         goto nl_out;
1214       }
1215       ALOGD("%s: sent cld80211 message for pid %d\n", __FUNCTION__, getpid());
1216     }
1217     else
1218     {
1219       ALOGE("%s: cld80211 ctx not present \n", __FUNCTION__);
1220     }
1221   }
1222   else
1223   {
1224     ALOGE("%s: Unknown family name : %d \n", __FUNCTION__, ctrl_msg->family_name);
1225     retval = -1;
1226   }
1227 nl_out:
1228   if (msg)
1229   {
1230     nlmsg_free(msg);
1231   }
1232   return retval;
1233 }
1234 
register_monitor_sock(wifi_handle handle,wifihal_ctrl_req_t * ctrl_msg,int attach)1235 static int register_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg, int attach)
1236 {
1237     hal_info *info = getHalInfo(handle);
1238 
1239     wifihal_mon_sock_t *reg, *nreg;
1240     char *match = NULL;
1241     unsigned int match_len = 0;
1242     unsigned int type;
1243 
1244     //! For Register Action frames, compare the match length and match buffer.
1245     //! For other registrations such as oem messages,
1246     //! diag messages check for respective commands
1247 
1248     if((ctrl_msg->family_name == GENERIC_NL_FAMILY) &&
1249        (ctrl_msg->cmd_id == NL80211_CMD_REGISTER_ACTION))
1250     {
1251        struct genlmsghdr *genlh;
1252        struct  nlmsghdr *nlh = (struct  nlmsghdr *)ctrl_msg->data;
1253        genlh = (struct genlmsghdr *)nlmsg_data(nlh);
1254        struct nlattr *nlattrs[NL80211_ATTR_MAX + 1];
1255 
1256        if (nlh->nlmsg_len > DEFAULT_PAGE_SIZE - sizeof(*ctrl_msg))
1257        {
1258          ALOGE("%s: Invalid nlmsg length", __FUNCTION__);
1259          return -1;
1260        }
1261        if (nla_parse(nlattrs, NL80211_ATTR_MAX, genlmsg_attrdata(genlh, 0),
1262                  genlmsg_attrlen(genlh, 0), NULL))
1263        {
1264          ALOGE("unable to parse nl attributes");
1265          return -1;
1266        }
1267        if (!nlattrs[NL80211_ATTR_FRAME_TYPE])
1268        {
1269          ALOGD("No Valid frame type");
1270        }
1271        else
1272        {
1273          type = nla_get_u16(nlattrs[NL80211_ATTR_FRAME_TYPE]);
1274        }
1275        if (!nlattrs[NL80211_ATTR_FRAME_MATCH])
1276        {
1277          ALOGE("No Frame Match");
1278          return -1;
1279        }
1280        else
1281        {
1282          match_len = nla_len(nlattrs[NL80211_ATTR_FRAME_MATCH]);
1283          match = (char *)nla_data(nlattrs[NL80211_ATTR_FRAME_MATCH]);
1284 
1285          list_for_each_entry(reg, &info->monitor_sockets, list) {
1286 
1287            if(reg == NULL)
1288               break;
1289 
1290            int mlen = min(match_len, reg->match_len);
1291 
1292            if (reg->match_len == 0)
1293                continue;
1294 
1295            if (memcmp(reg->match, match, mlen) == 0) {
1296 
1297               if((ctrl_msg->monsock_len == reg->monsock_len) &&
1298                  (memcmp((char *)&reg->monsock, (char *)&ctrl_msg->monsock, ctrl_msg->monsock_len) == 0))
1299               {
1300                 if(attach)
1301                 {
1302                   ALOGE(" %s :Action frame already registered for this client ", __FUNCTION__);
1303                   return -2;
1304                 }
1305                 else
1306                 {
1307                   del_from_list(&reg->list);
1308                   free(reg);
1309                   return 0;
1310                 }
1311               }
1312               else
1313               {
1314                 //! when action frame registered for other client,
1315                 //! you can't attach or dettach for new client
1316                 ALOGE(" %s :Action frame registered for other client ", __FUNCTION__);
1317                 return -2;
1318               }
1319            }
1320          }
1321        }
1322     }
1323     else
1324     {
1325       list_for_each_entry(reg, &info->monitor_sockets, list) {
1326 
1327          //! Checking for monitor sock in the list :
1328 
1329          //! For attach request :
1330          //! if sock is not present, then it is a new entry , so add to list.
1331          //! if sock is present,  and cmd_id does not match, add another entry to list.
1332          //! if sock is present, and cmd_id matches, return 0.
1333 
1334          //! For dettach req :
1335          //! if sock is not present, return error -2.
1336          //! if sock is present,  and cmd_id does not match, return error -2.
1337          //! if sock is present, and cmd_id matches, delete entry and return 0.
1338          if(reg == NULL)
1339             break;
1340 
1341          if (ctrl_msg->monsock_len != reg->monsock_len)
1342              continue;
1343 
1344          if (memcmp((char *)&reg->monsock, (char *)&ctrl_msg->monsock, ctrl_msg->monsock_len) == 0) {
1345 
1346             if((reg->family_name == ctrl_msg->family_name) && (reg->cmd_id == ctrl_msg->cmd_id))
1347             {
1348                if(!attach)
1349                {
1350                  del_from_list(&reg->list);
1351                  free(reg);
1352                }
1353                return 0;
1354             }
1355          }
1356       }
1357     }
1358 
1359     if(attach)
1360     {
1361        if (ctrl_msg->monsock_len > sizeof(struct sockaddr_un))
1362        {
1363          ALOGE("%s: Invalid monitor socket length \n", __FUNCTION__);
1364          return -3;
1365        }
1366 
1367        nreg = (wifihal_mon_sock_t *)malloc(sizeof(*reg) + match_len);
1368         if (!nreg)
1369            return -1;
1370 
1371        memset((char *)nreg, 0, sizeof(*reg) + match_len);
1372        nreg->family_name = ctrl_msg->family_name;
1373        nreg->cmd_id = ctrl_msg->cmd_id;
1374        nreg->monsock_len = ctrl_msg->monsock_len;
1375        memcpy((char *)&nreg->monsock, (char *)&ctrl_msg->monsock, ctrl_msg->monsock_len);
1376 
1377        if(match_len && match)
1378        {
1379          nreg->match_len = match_len;
1380          memcpy(nreg->match, match, match_len);
1381        }
1382        add_to_list(&nreg->list, &info->monitor_sockets);
1383     }
1384     else
1385     {
1386        //! Not attached, so cant be dettached
1387        ALOGE("%s: Dettaching the unregistered socket \n", __FUNCTION__);
1388        return -2;
1389     }
1390 
1391    return 0;
1392 }
1393 
attach_monitor_sock(wifi_handle handle,wifihal_ctrl_req_t * ctrl_msg)1394 static int attach_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg)
1395 {
1396    return register_monitor_sock(handle, ctrl_msg, 1);
1397 }
1398 
dettach_monitor_sock(wifi_handle handle,wifihal_ctrl_req_t * ctrl_msg)1399 static int dettach_monitor_sock(wifi_handle handle, wifihal_ctrl_req_t *ctrl_msg)
1400 {
1401    return register_monitor_sock(handle, ctrl_msg, 0);
1402 }
1403 
internal_pollin_handler_app(wifi_handle handle,struct ctrl_sock * sock)1404 static int internal_pollin_handler_app(wifi_handle handle,  struct ctrl_sock *sock)
1405 {
1406     int retval = -1;
1407     int res;
1408     struct sockaddr_un from;
1409     socklen_t fromlen = sizeof(from);
1410     wifihal_ctrl_req_t *ctrl_msg;
1411     wifihal_ctrl_sync_rsp_t ctrl_reply;
1412 
1413     ctrl_msg = (wifihal_ctrl_req_t *)malloc(DEFAULT_PAGE_SIZE);
1414     if(ctrl_msg == NULL)
1415     {
1416       ALOGE ("Memory allocation failure");
1417       return -1;
1418     }
1419 
1420     memset((char *)ctrl_msg, 0, DEFAULT_PAGE_SIZE);
1421 
1422     res = recvfrom(sock->s, (char *)ctrl_msg, DEFAULT_PAGE_SIZE, 0,
1423                    (struct sockaddr *)&from, &fromlen);
1424     if (res < 0) {
1425         ALOGE("recvfrom(ctrl_iface): %s",
1426                strerror(errno));
1427         if(ctrl_msg)
1428            free(ctrl_msg);
1429 
1430         return 0;
1431     }
1432     switch(ctrl_msg->ctrl_cmd)
1433     {
1434        case WIFIHAL_CTRL_MONITOR_ATTACH:
1435          retval = attach_monitor_sock(handle, ctrl_msg);
1436        break;
1437        case WIFIHAL_CTRL_MONITOR_DETTACH:
1438          retval = dettach_monitor_sock(handle, ctrl_msg);
1439        break;
1440        case WIFIHAL_CTRL_SEND_NL_DATA:
1441          retval = send_nl_data(handle, ctrl_msg);
1442        break;
1443        default:
1444        break;
1445     }
1446 
1447     ctrl_reply.ctrl_cmd = ctrl_msg->ctrl_cmd;
1448     ctrl_reply.family_name = ctrl_msg->family_name;
1449     ctrl_reply.cmd_id = ctrl_msg->cmd_id;
1450     ctrl_reply.status = retval;
1451 
1452     if(ctrl_msg)
1453        free(ctrl_msg);
1454 
1455     if (sendto(sock->s, (char *)&ctrl_reply, sizeof(ctrl_reply), 0, (struct sockaddr *)&from,
1456                fromlen) < 0) {
1457                   int _errno = errno;
1458                   ALOGE("socket send failed : %d",_errno);
1459 
1460        if (_errno == ENOBUFS || _errno == EAGAIN) {
1461            /*
1462             * The socket send buffer could be full. This
1463             * may happen if client programs are not
1464             * receiving their pending messages. Close and
1465             * reopen the socket as a workaround to avoid
1466             * getting stuck being unable to send any new
1467             * responses.
1468             */
1469           }
1470         }
1471       return res;
1472 }
1473 
internal_pollin_handler(wifi_handle handle,struct nl_sock * sock)1474 static int internal_pollin_handler(wifi_handle handle, struct nl_sock *sock)
1475 {
1476     struct nl_cb *cb = nl_socket_get_cb(sock);
1477 
1478     int res = nl_recvmsgs(sock, cb);
1479     if(res)
1480         ALOGE("Error :%d while reading nl msg", res);
1481     nl_cb_put(cb);
1482     return res;
1483 }
1484 
internal_event_handler_app(wifi_handle handle,int events,struct ctrl_sock * sock)1485 static void internal_event_handler_app(wifi_handle handle, int events,
1486                                     struct ctrl_sock *sock)
1487 {
1488     if (events & POLLERR) {
1489         ALOGE("Error reading from wifi_hal ctrl socket");
1490         internal_pollin_handler_app(handle, sock);
1491     } else if (events & POLLHUP) {
1492         ALOGE("Remote side hung up");
1493     } else if (events & POLLIN) {
1494         //ALOGI("Found some events!!!");
1495         internal_pollin_handler_app(handle, sock);
1496     } else {
1497         ALOGE("Unknown event - %0x", events);
1498     }
1499 }
1500 
internal_event_handler(wifi_handle handle,int events,struct nl_sock * sock)1501 static void internal_event_handler(wifi_handle handle, int events,
1502                                    struct nl_sock *sock)
1503 {
1504     if (events & POLLERR) {
1505         ALOGE("Error reading from socket");
1506         internal_pollin_handler(handle, sock);
1507     } else if (events & POLLHUP) {
1508         ALOGE("Remote side hung up");
1509     } else if (events & POLLIN) {
1510         //ALOGI("Found some events!!!");
1511         internal_pollin_handler(handle, sock);
1512     } else {
1513         ALOGE("Unknown event - %0x", events);
1514     }
1515 }
1516 
1517 /* Run event handler */
wifi_event_loop(wifi_handle handle)1518 void wifi_event_loop(wifi_handle handle)
1519 {
1520     hal_info *info = getHalInfo(handle);
1521     if (info->in_event_loop) {
1522         return;
1523     } else {
1524         info->in_event_loop = true;
1525     }
1526 
1527     pollfd pfd[4];
1528     memset(&pfd, 0, 4*sizeof(pfd[0]));
1529 
1530     pfd[0].fd = nl_socket_get_fd(info->event_sock);
1531     pfd[0].events = POLLIN;
1532 
1533     pfd[1].fd = nl_socket_get_fd(info->user_sock);
1534     pfd[1].events = POLLIN;
1535 
1536     pfd[2].fd = info->exit_sockets[1];
1537     pfd[2].events = POLLIN;
1538 
1539     if(info->wifihal_ctrl_sock.s > 0) {
1540       pfd[3].fd = info->wifihal_ctrl_sock.s ;
1541       pfd[3].events = POLLIN;
1542     }
1543     /* TODO: Add support for timeouts */
1544 
1545     do {
1546         pfd[0].revents = 0;
1547         pfd[1].revents = 0;
1548         pfd[2].revents = 0;
1549         pfd[3].revents = 0;
1550         //ALOGI("Polling sockets");
1551         int result = poll(pfd, 4, -1);
1552         if (result < 0) {
1553             ALOGE("Error polling socket");
1554         } else {
1555             if (pfd[0].revents & (POLLIN | POLLHUP | POLLERR)) {
1556                 internal_event_handler(handle, pfd[0].revents, info->event_sock);
1557             }
1558             if (pfd[1].revents & (POLLIN | POLLHUP | POLLERR)) {
1559                 internal_event_handler(handle, pfd[1].revents, info->user_sock);
1560             }
1561             if ((info->wifihal_ctrl_sock.s > 0) && (pfd[3].revents & (POLLIN | POLLHUP | POLLERR))) {
1562                 internal_event_handler_app(handle, pfd[3].revents, &info->wifihal_ctrl_sock);
1563             }
1564         }
1565         rb_timerhandler(info);
1566     } while (!info->clean_up);
1567     internal_cleaned_up_handler(handle);
1568 }
1569 
user_sock_message_handler(nl_msg * msg,void * arg)1570 static int user_sock_message_handler(nl_msg *msg, void *arg)
1571 {
1572     wifi_handle handle = (wifi_handle)arg;
1573     hal_info *info = getHalInfo(handle);
1574 
1575     diag_message_handler(info, msg);
1576 
1577     return NL_OK;
1578 }
1579 
internal_valid_message_handler(nl_msg * msg,void * arg)1580 static int internal_valid_message_handler(nl_msg *msg, void *arg)
1581 {
1582     wifi_handle handle = (wifi_handle)arg;
1583     hal_info *info = getHalInfo(handle);
1584 
1585     WifiEvent event(msg);
1586     int res = event.parse();
1587     if (res < 0) {
1588         ALOGE("Failed to parse event: %d", res);
1589         return NL_SKIP;
1590     }
1591 
1592     int cmd = event.get_cmd();
1593     uint32_t vendor_id = 0;
1594     int subcmd = 0;
1595 
1596     if (cmd == NL80211_CMD_VENDOR) {
1597         vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID);
1598         subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD);
1599         /* Restrict printing GSCAN_FULL_RESULT which is causing lot
1600            of logs in bug report */
1601         if (subcmd != QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT) {
1602             ALOGI("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x",
1603                   event.get_cmdString(), vendor_id, subcmd);
1604         }
1605     }
1606     else if((info->wifihal_ctrl_sock.s > 0) && (cmd == NL80211_CMD_FRAME))
1607     {
1608        struct genlmsghdr *genlh;
1609        struct  nlmsghdr *nlh = nlmsg_hdr(msg);
1610        genlh = (struct genlmsghdr *)nlmsg_data(nlh);
1611        struct nlattr *nlattrs[NL80211_ATTR_MAX + 1];
1612 
1613        wifihal_ctrl_event_t *ctrl_evt;
1614        char *buff;
1615        wifihal_mon_sock_t *reg;
1616 
1617        nla_parse(nlattrs, NL80211_ATTR_MAX, genlmsg_attrdata(genlh, 0),
1618                  genlmsg_attrlen(genlh, 0), NULL);
1619 
1620        if (!nlattrs[NL80211_ATTR_FRAME])
1621        {
1622          ALOGD("No Frame body");
1623          return WIFI_SUCCESS;
1624        }
1625        ctrl_evt = (wifihal_ctrl_event_t *)malloc(sizeof(*ctrl_evt) + nlh->nlmsg_len);
1626        if(ctrl_evt == NULL)
1627        {
1628          ALOGE("Memory allocation failure");
1629          return -1;
1630        }
1631        memset((char *)ctrl_evt, 0, sizeof(*ctrl_evt) + nlh->nlmsg_len);
1632        ctrl_evt->family_name = GENERIC_NL_FAMILY;
1633        ctrl_evt->cmd_id = cmd;
1634        ctrl_evt->data_len = nlh->nlmsg_len;
1635        memcpy(ctrl_evt->data, (char *)nlh, ctrl_evt->data_len);
1636 
1637 
1638        buff = (char *)nla_data(nlattrs[NL80211_ATTR_FRAME]) + 24; //! Size of Wlan80211FrameHeader
1639 
1640        list_for_each_entry(reg, &info->monitor_sockets, list) {
1641 
1642                  if(reg == NULL)
1643                     break;
1644 
1645                  if (memcmp(reg->match, buff, reg->match_len))
1646                      continue;
1647 
1648                  /* found match! */
1649                  /* Indicate the received Action frame to respective client */
1650                  if (sendto(info->wifihal_ctrl_sock.s, (char *)ctrl_evt,
1651                             sizeof(*ctrl_evt) + ctrl_evt->data_len,
1652                             0, (struct sockaddr *)&reg->monsock, reg->monsock_len) < 0)
1653                  {
1654                    int _errno = errno;
1655                    ALOGE("socket send failed : %d",_errno);
1656 
1657                    if (_errno == ENOBUFS || _errno == EAGAIN) {
1658                    }
1659                  }
1660 
1661         }
1662         free(ctrl_evt);
1663     }
1664 
1665     else {
1666         ALOGV("event received %s", event.get_cmdString());
1667     }
1668 
1669     // event.log();
1670 
1671     bool dispatched = false;
1672 
1673     pthread_mutex_lock(&info->cb_lock);
1674 
1675     for (int i = 0; i < info->num_event_cb; i++) {
1676         if (cmd == info->event_cb[i].nl_cmd) {
1677             if (cmd == NL80211_CMD_VENDOR
1678                 && ((vendor_id != info->event_cb[i].vendor_id)
1679                 || (subcmd != info->event_cb[i].vendor_subcmd)))
1680             {
1681                 /* event for a different vendor, ignore it */
1682                 continue;
1683             }
1684 
1685             cb_info *cbi = &(info->event_cb[i]);
1686             pthread_mutex_unlock(&info->cb_lock);
1687             if (cbi->cb_func) {
1688                 (*(cbi->cb_func))(msg, cbi->cb_arg);
1689                 dispatched = true;
1690             }
1691             return NL_OK;
1692         }
1693     }
1694 
1695 #ifdef QC_HAL_DEBUG
1696     if (!dispatched) {
1697         ALOGI("event ignored!!");
1698     }
1699 #endif
1700 
1701     pthread_mutex_unlock(&info->cb_lock);
1702     return NL_OK;
1703 }
1704 
1705 ////////////////////////////////////////////////////////////////////////////////
1706 
1707 class GetMulticastIdCommand : public WifiCommand
1708 {
1709 private:
1710     const char *mName;
1711     const char *mGroup;
1712     int   mId;
1713 public:
GetMulticastIdCommand(wifi_handle handle,const char * name,const char * group)1714     GetMulticastIdCommand(wifi_handle handle, const char *name,
1715             const char *group) : WifiCommand(handle, 0)
1716     {
1717         mName = name;
1718         mGroup = group;
1719         mId = -1;
1720     }
1721 
getId()1722     int getId() {
1723         return mId;
1724     }
1725 
create()1726     virtual wifi_error create() {
1727         int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl");
1728         // ALOGI("ctrl family = %d", nlctrlFamily);
1729         wifi_error ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0);
1730         if (ret != WIFI_SUCCESS)
1731             return ret;
1732 
1733         ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName);
1734         return ret;
1735     }
1736 
handleResponse(WifiEvent & reply)1737     virtual int handleResponse(WifiEvent& reply) {
1738 
1739         // ALOGI("handling reponse in %s", __func__);
1740 
1741         struct nlattr **tb = reply.attributes();
1742         struct nlattr *mcgrp = NULL;
1743         int i;
1744 
1745         if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
1746             ALOGI("No multicast groups found");
1747             return NL_SKIP;
1748         } else {
1749             // ALOGI("Multicast groups attr size = %d",
1750             // nla_len(tb[CTRL_ATTR_MCAST_GROUPS]));
1751         }
1752 
1753         for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
1754 
1755             // ALOGI("Processing group");
1756             struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
1757             nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp),
1758                 nla_len(mcgrp), NULL);
1759             if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID])
1760             {
1761                 continue;
1762             }
1763 
1764             char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
1765             int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
1766 
1767             // ALOGI("Found group name %s", grpName);
1768 
1769             if (strncmp(grpName, mGroup, grpNameLen) != 0)
1770                 continue;
1771 
1772             mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
1773             break;
1774         }
1775 
1776         return NL_SKIP;
1777     }
1778 
1779 };
1780 
wifi_get_multicast_id(wifi_handle handle,const char * name,const char * group)1781 static int wifi_get_multicast_id(wifi_handle handle, const char *name,
1782         const char *group)
1783 {
1784     GetMulticastIdCommand cmd(handle, name, group);
1785     int res = cmd.requestResponse();
1786     if (res < 0)
1787         return res;
1788     else
1789         return cmd.getId();
1790 }
1791 
1792 /////////////////////////////////////////////////////////////////////////
1793 
is_wifi_interface(const char * name)1794 static bool is_wifi_interface(const char *name)
1795 {
1796     if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0
1797         && strncmp(name, "wifi", 4) != 0) {
1798         /* not a wifi interface; ignore it */
1799         return false;
1800     } else {
1801         return true;
1802     }
1803 }
1804 
get_interface(const char * name,interface_info * info)1805 static int get_interface(const char *name, interface_info *info)
1806 {
1807     strlcpy(info->name, name, (IFNAMSIZ + 1));
1808     info->id = if_nametoindex(name);
1809     // ALOGI("found an interface : %s, id = %d", name, info->id);
1810     return WIFI_SUCCESS;
1811 }
1812 
wifi_init_interfaces(wifi_handle handle)1813 wifi_error wifi_init_interfaces(wifi_handle handle)
1814 {
1815     hal_info *info = (hal_info *)handle;
1816 
1817     struct dirent *de;
1818 
1819     DIR *d = opendir("/sys/class/net");
1820     if (d == 0)
1821         return WIFI_ERROR_UNKNOWN;
1822 
1823     int n = 0;
1824     while ((de = readdir(d))) {
1825         if (de->d_name[0] == '.')
1826             continue;
1827         if (is_wifi_interface(de->d_name) ) {
1828             n++;
1829         }
1830     }
1831 
1832     closedir(d);
1833 
1834     d = opendir("/sys/class/net");
1835     if (d == 0)
1836         return WIFI_ERROR_UNKNOWN;
1837 
1838     info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n);
1839     if (info->interfaces == NULL) {
1840         ALOGE("%s: Error info->interfaces NULL", __func__);
1841         return WIFI_ERROR_OUT_OF_MEMORY;
1842     }
1843 
1844     int i = 0;
1845     while ((de = readdir(d))) {
1846         if (de->d_name[0] == '.')
1847             continue;
1848         if (is_wifi_interface(de->d_name)) {
1849             interface_info *ifinfo
1850                 = (interface_info *)malloc(sizeof(interface_info));
1851             if (ifinfo == NULL) {
1852                 ALOGE("%s: Error ifinfo NULL", __func__);
1853                 while (i > 0) {
1854                     free(info->interfaces[i-1]);
1855                     i--;
1856                 }
1857                 free(info->interfaces);
1858                 return WIFI_ERROR_OUT_OF_MEMORY;
1859             }
1860             if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {
1861                 free(ifinfo);
1862                 continue;
1863             }
1864             ifinfo->handle = handle;
1865             info->interfaces[i] = ifinfo;
1866             i++;
1867         }
1868     }
1869 
1870     closedir(d);
1871 
1872     info->num_interfaces = n;
1873 
1874     return WIFI_SUCCESS;
1875 }
1876 
wifi_get_ifaces(wifi_handle handle,int * num,wifi_interface_handle ** interfaces)1877 wifi_error wifi_get_ifaces(wifi_handle handle, int *num,
1878         wifi_interface_handle **interfaces)
1879 {
1880     hal_info *info = (hal_info *)handle;
1881 
1882     /* In case of dynamic interface add/remove, interface handles need to be
1883      * updated so that, interface specific APIs could be instantiated.
1884      * Reload here to get interfaces which are dynamically added. */
1885 
1886     if (info->num_interfaces > 0) {
1887         for (int i = 0; i < info->num_interfaces; i++)
1888             free(info->interfaces[i]);
1889         free(info->interfaces);
1890         info->interfaces = NULL;
1891         info->num_interfaces = 0;
1892     }
1893 
1894     wifi_error ret = wifi_init_interfaces(handle);
1895     if (ret != WIFI_SUCCESS) {
1896         ALOGE("Failed to init interfaces while wifi_get_ifaces");
1897         return ret;
1898     }
1899 
1900     *interfaces = (wifi_interface_handle *)info->interfaces;
1901     *num = info->num_interfaces;
1902 
1903     return WIFI_SUCCESS;
1904 }
1905 
wifi_get_iface_name(wifi_interface_handle handle,char * name,size_t size)1906 wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name,
1907         size_t size)
1908 {
1909     interface_info *info = (interface_info *)handle;
1910     strlcpy(name, info->name, size);
1911     return WIFI_SUCCESS;
1912 }
1913 
1914 /* Get the supported Feature set */
wifi_get_supported_feature_set(wifi_interface_handle iface,feature_set * set)1915 wifi_error wifi_get_supported_feature_set(wifi_interface_handle iface,
1916         feature_set *set)
1917 {
1918     int ret = 0;
1919     wifi_handle handle = getWifiHandle(iface);
1920     *set = 0;
1921     hal_info *info = getHalInfo(handle);
1922 
1923     ret = acquire_supported_features(iface, set);
1924     if (ret != WIFI_SUCCESS) {
1925         *set = info->supported_feature_set;
1926         ALOGV("Supported feature set acquired at initialization : 0x%" PRIx64, *set);
1927     } else {
1928         info->supported_feature_set = *set;
1929         ALOGV("Supported feature set acquired : 0x%" PRIx64, *set);
1930     }
1931     return WIFI_SUCCESS;
1932 }
1933 
wifi_get_concurrency_matrix(wifi_interface_handle handle,int set_size_max,feature_set set[],int * set_size)1934 wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle,
1935                                        int set_size_max,
1936                                        feature_set set[], int *set_size)
1937 {
1938     wifi_error ret;
1939     struct nlattr *nlData;
1940     WifihalGeneric *vCommand = NULL;
1941     interface_info *ifaceInfo = getIfaceInfo(handle);
1942     wifi_handle wifiHandle = getWifiHandle(handle);
1943 
1944     if (set == NULL) {
1945         ALOGE("%s: NULL set pointer provided. Exit.",
1946             __func__);
1947         return WIFI_ERROR_INVALID_ARGS;
1948     }
1949 
1950     vCommand = new WifihalGeneric(wifiHandle, 0,
1951             OUI_QCA,
1952             QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX);
1953     if (vCommand == NULL) {
1954         ALOGE("%s: Error vCommand NULL", __func__);
1955         return WIFI_ERROR_OUT_OF_MEMORY;
1956     }
1957 
1958     /* Create the message */
1959     ret = vCommand->create();
1960     if (ret != WIFI_SUCCESS)
1961         goto cleanup;
1962 
1963     ret = vCommand->set_iface_id(ifaceInfo->name);
1964     if (ret != WIFI_SUCCESS)
1965         goto cleanup;
1966 
1967     /* Add the vendor specific attributes for the NL command. */
1968     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1969     if (!nlData)
1970         goto cleanup;
1971 
1972     ret = vCommand->put_u32(
1973           QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX,
1974           set_size_max);
1975     if (ret != WIFI_SUCCESS)
1976         goto cleanup;
1977 
1978     vCommand->attr_end(nlData);
1979 
1980     /* Populate the input received from caller/framework. */
1981     vCommand->setMaxSetSize(set_size_max);
1982     vCommand->setSizePtr(set_size);
1983     vCommand->setConcurrencySet(set);
1984 
1985     ret = vCommand->requestResponse();
1986     if (ret != WIFI_SUCCESS)
1987         ALOGE("%s: requestResponse() error: %d", __func__, ret);
1988 
1989 cleanup:
1990     delete vCommand;
1991     if (ret)
1992         *set_size = 0;
1993     return ret;
1994 }
1995 
1996 
wifi_set_nodfs_flag(wifi_interface_handle handle,u32 nodfs)1997 wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs)
1998 {
1999     wifi_error ret;
2000     struct nlattr *nlData;
2001     WifiVendorCommand *vCommand = NULL;
2002     interface_info *ifaceInfo = getIfaceInfo(handle);
2003     wifi_handle wifiHandle = getWifiHandle(handle);
2004 
2005     vCommand = new WifiVendorCommand(wifiHandle, 0,
2006             OUI_QCA,
2007             QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG);
2008     if (vCommand == NULL) {
2009         ALOGE("%s: Error vCommand NULL", __func__);
2010         return WIFI_ERROR_OUT_OF_MEMORY;
2011     }
2012 
2013     /* Create the message */
2014     ret = vCommand->create();
2015     if (ret != WIFI_SUCCESS)
2016         goto cleanup;
2017 
2018     ret = vCommand->set_iface_id(ifaceInfo->name);
2019     if (ret != WIFI_SUCCESS)
2020         goto cleanup;
2021 
2022     /* Add the vendor specific attributes for the NL command. */
2023     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2024     if (!nlData)
2025         goto cleanup;
2026 
2027     /* Add the fixed part of the mac_oui to the nl command */
2028     ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG, nodfs);
2029     if (ret != WIFI_SUCCESS)
2030         goto cleanup;
2031 
2032     vCommand->attr_end(nlData);
2033 
2034     ret = vCommand->requestResponse();
2035     /* Don't check response since we aren't expecting one */
2036 
2037 cleanup:
2038     delete vCommand;
2039     return ret;
2040 }
2041 
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)2042 wifi_error wifi_start_sending_offloaded_packet(wifi_request_id id,
2043                                                wifi_interface_handle iface,
2044                                                u16 ether_type,
2045                                                u8 *ip_packet,
2046                                                u16 ip_packet_len,
2047                                                u8 *src_mac_addr,
2048                                                u8 *dst_mac_addr,
2049                                                u32 period_msec)
2050 {
2051     wifi_error ret;
2052     struct nlattr *nlData;
2053     WifiVendorCommand *vCommand = NULL;
2054 
2055     ret = initialize_vendor_cmd(iface, id,
2056                                 QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
2057                                 &vCommand);
2058     if (ret != WIFI_SUCCESS) {
2059         ALOGE("%s: Initialization failed", __func__);
2060         return ret;
2061     }
2062 
2063     ALOGV("ether type 0x%04x\n", ether_type);
2064     ALOGV("ip packet length : %u\nIP Packet:", ip_packet_len);
2065     hexdump(ip_packet, ip_packet_len);
2066     ALOGV("Src Mac Address: " MAC_ADDR_STR "\nDst Mac Address: " MAC_ADDR_STR
2067           "\nPeriod in msec : %u", MAC_ADDR_ARRAY(src_mac_addr),
2068           MAC_ADDR_ARRAY(dst_mac_addr), period_msec);
2069 
2070     /* Add the vendor specific attributes for the NL command. */
2071     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2072     if (!nlData)
2073         goto cleanup;
2074 
2075     ret = vCommand->put_u32(
2076             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL,
2077             QCA_WLAN_OFFLOADED_PACKETS_SENDING_START);
2078     if (ret != WIFI_SUCCESS)
2079         goto cleanup;
2080 
2081     ret = vCommand->put_u32(
2082             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID,
2083             id);
2084     if (ret != WIFI_SUCCESS)
2085         goto cleanup;
2086 
2087     ret = vCommand->put_u16(
2088             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_ETHER_PROTO_TYPE,
2089             ether_type);
2090     if (ret != WIFI_SUCCESS)
2091         goto cleanup;
2092 
2093     ret = vCommand->put_bytes(
2094             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA,
2095             (const char *)ip_packet, ip_packet_len);
2096     if (ret != WIFI_SUCCESS)
2097         goto cleanup;
2098 
2099     ret = vCommand->put_addr(
2100             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR,
2101             src_mac_addr);
2102     if (ret != WIFI_SUCCESS)
2103         goto cleanup;
2104 
2105     ret = vCommand->put_addr(
2106             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR,
2107             dst_mac_addr);
2108     if (ret != WIFI_SUCCESS)
2109         goto cleanup;
2110 
2111     ret = vCommand->put_u32(
2112             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD,
2113             period_msec);
2114     if (ret != WIFI_SUCCESS)
2115         goto cleanup;
2116 
2117     vCommand->attr_end(nlData);
2118 
2119     ret = vCommand->requestResponse();
2120     if (ret != WIFI_SUCCESS)
2121         goto cleanup;
2122 
2123 cleanup:
2124     delete vCommand;
2125     return ret;
2126 }
2127 
wifi_stop_sending_offloaded_packet(wifi_request_id id,wifi_interface_handle iface)2128 wifi_error wifi_stop_sending_offloaded_packet(wifi_request_id id,
2129                                               wifi_interface_handle iface)
2130 {
2131     wifi_error ret;
2132     struct nlattr *nlData;
2133     WifiVendorCommand *vCommand = NULL;
2134 
2135     ret = initialize_vendor_cmd(iface, id,
2136                                 QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
2137                                 &vCommand);
2138     if (ret != WIFI_SUCCESS) {
2139         ALOGE("%s: Initialization failed", __func__);
2140         return ret;
2141     }
2142 
2143     /* Add the vendor specific attributes for the NL command. */
2144     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2145     if (!nlData)
2146         goto cleanup;
2147 
2148     ret = vCommand->put_u32(
2149             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL,
2150             QCA_WLAN_OFFLOADED_PACKETS_SENDING_STOP);
2151     if (ret != WIFI_SUCCESS)
2152         goto cleanup;
2153 
2154     ret = vCommand->put_u32(
2155             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID,
2156             id);
2157     if (ret != WIFI_SUCCESS)
2158         goto cleanup;
2159 
2160     vCommand->attr_end(nlData);
2161 
2162     ret = vCommand->requestResponse();
2163     if (ret != WIFI_SUCCESS)
2164         goto cleanup;
2165 
2166 cleanup:
2167     delete vCommand;
2168     return ret;
2169 }
2170 
2171 #define PACKET_FILTER_ID 0
2172 
wifi_set_packet_filter(wifi_interface_handle iface,const u8 * program,u32 len)2173 static wifi_error wifi_set_packet_filter(wifi_interface_handle iface,
2174                                          const u8 *program, u32 len)
2175 {
2176     wifi_error ret;
2177     struct nlattr *nlData;
2178     WifiVendorCommand *vCommand = NULL;
2179     u32 current_offset = 0;
2180     wifi_handle wifiHandle = getWifiHandle(iface);
2181     hal_info *info = getHalInfo(wifiHandle);
2182 
2183     /* len=0 clears the filters in driver/firmware */
2184     if (len != 0 && program == NULL) {
2185         ALOGE("%s: No valid program provided. Exit.",
2186             __func__);
2187         return WIFI_ERROR_INVALID_ARGS;
2188     }
2189 
2190     do {
2191         ret = initialize_vendor_cmd(iface, get_requestid(),
2192                                     QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
2193                                     &vCommand);
2194         if (ret != WIFI_SUCCESS) {
2195             ALOGE("%s: Initialization failed", __FUNCTION__);
2196             return ret;
2197         }
2198 
2199         /* Add the vendor specific attributes for the NL command. */
2200         nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2201         if (!nlData)
2202             goto cleanup;
2203 
2204         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
2205                                 QCA_WLAN_SET_PACKET_FILTER);
2206         if (ret != WIFI_SUCCESS)
2207             goto cleanup;
2208         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID,
2209                                 PACKET_FILTER_ID);
2210         if (ret != WIFI_SUCCESS)
2211             goto cleanup;
2212         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE,
2213                                 len);
2214         if (ret != WIFI_SUCCESS)
2215             goto cleanup;
2216         ret = vCommand->put_u32(
2217                             QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
2218                             current_offset);
2219         if (ret != WIFI_SUCCESS)
2220             goto cleanup;
2221 
2222         if (len) {
2223             ret = vCommand->put_bytes(
2224                                      QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM,
2225                                      (char *)&program[current_offset],
2226                                      min(info->firmware_bus_max_size,
2227                                      len-current_offset));
2228             if (ret!= WIFI_SUCCESS) {
2229                 ALOGE("%s: failed to put program", __FUNCTION__);
2230                 goto cleanup;
2231             }
2232         }
2233 
2234         vCommand->attr_end(nlData);
2235 
2236         ret = vCommand->requestResponse();
2237         if (ret != WIFI_SUCCESS) {
2238             ALOGE("%s: requestResponse Error:%d",__func__, ret);
2239             goto cleanup;
2240         }
2241 
2242         /* destroy the object after sending each fragment to driver */
2243         delete vCommand;
2244         vCommand = NULL;
2245 
2246         current_offset += min(info->firmware_bus_max_size, len);
2247     } while (current_offset < len);
2248 
2249     info->apf_enabled = !!len;
2250 
2251 cleanup:
2252     if (vCommand)
2253         delete vCommand;
2254     return ret;
2255 }
2256 
wifi_get_packet_filter_capabilities(wifi_interface_handle handle,u32 * version,u32 * max_len)2257 static wifi_error wifi_get_packet_filter_capabilities(
2258                 wifi_interface_handle handle, u32 *version, u32 *max_len)
2259 {
2260     wifi_error ret;
2261     struct nlattr *nlData;
2262     WifihalGeneric *vCommand = NULL;
2263     interface_info *ifaceInfo = getIfaceInfo(handle);
2264     wifi_handle wifiHandle = getWifiHandle(handle);
2265 
2266     if (version == NULL || max_len == NULL) {
2267         ALOGE("%s: NULL version/max_len pointer provided. Exit.",
2268             __FUNCTION__);
2269         return WIFI_ERROR_INVALID_ARGS;
2270     }
2271 
2272     vCommand = new WifihalGeneric(wifiHandle, 0,
2273             OUI_QCA,
2274             QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER);
2275     if (vCommand == NULL) {
2276         ALOGE("%s: Error vCommand NULL", __FUNCTION__);
2277         return WIFI_ERROR_OUT_OF_MEMORY;
2278     }
2279 
2280     /* Create the message */
2281     ret = vCommand->create();
2282     if (ret != WIFI_SUCCESS)
2283         goto cleanup;
2284 
2285     ret = vCommand->set_iface_id(ifaceInfo->name);
2286     if (ret != WIFI_SUCCESS)
2287         goto cleanup;
2288 
2289     /* Add the vendor specific attributes for the NL command. */
2290     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2291     if (!nlData)
2292         goto cleanup;
2293 
2294     ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
2295                             QCA_WLAN_GET_PACKET_FILTER);
2296     if (ret != WIFI_SUCCESS)
2297         goto cleanup;
2298 
2299     vCommand->attr_end(nlData);
2300 
2301     ret = vCommand->requestResponse();
2302     if (ret != WIFI_SUCCESS) {
2303         ALOGE("%s: requestResponse() error: %d", __FUNCTION__, ret);
2304         if (ret == WIFI_ERROR_NOT_SUPPORTED) {
2305             /* Packet filtering is not supported currently, so return version
2306              * and length as 0
2307              */
2308             ALOGI("Packet filtering is not supprted");
2309             *version = 0;
2310             *max_len = 0;
2311             ret = WIFI_SUCCESS;
2312         }
2313         goto cleanup;
2314     }
2315 
2316     *version = vCommand->getFilterVersion();
2317     *max_len = vCommand->getFilterLength();
2318 cleanup:
2319     delete vCommand;
2320     return ret;
2321 }
2322 
2323 
wifi_configure_nd_offload(wifi_interface_handle iface,u8 enable)2324 static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface,
2325                                             u8 enable)
2326 {
2327     wifi_error ret;
2328     struct nlattr *nlData;
2329     WifiVendorCommand *vCommand = NULL;
2330 
2331     ret = initialize_vendor_cmd(iface, get_requestid(),
2332                                 QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
2333                                 &vCommand);
2334     if (ret != WIFI_SUCCESS) {
2335         ALOGE("%s: Initialization failed", __func__);
2336         return ret;
2337     }
2338 
2339     ALOGV("ND offload : %s", enable?"Enable":"Disable");
2340 
2341     /* Add the vendor specific attributes for the NL command. */
2342     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2343     if (!nlData)
2344         goto cleanup;
2345 
2346     ret = vCommand->put_u8(QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG, enable);
2347     if (ret != WIFI_SUCCESS)
2348         goto cleanup;
2349 
2350     vCommand->attr_end(nlData);
2351 
2352     ret = vCommand->requestResponse();
2353 
2354 cleanup:
2355     delete vCommand;
2356     return ret;
2357 }
2358 
2359 /**
2360  * Copy 'len' bytes of raw data from host memory at source address 'program'
2361  * to APF (Android Packet Filter) working memory starting at offset 'dst_offset'.
2362  * The size of the program lenght passed to the interpreter is set to
2363  * 'progaram_lenght'
2364  *
2365  * The implementation is allowed to tranlate this wrtie into a series of smaller
2366  * writes,but this function is not allowed to return untill all write operations
2367  * have been completed
2368  * additionally visible memory not targeted by this function must remain
2369  * unchanged
2370 
2371  * @param dst_offset write offset in bytes relative to the beginning of the APF
2372  * working memory with logical address 0X000. Must be a multiple of 4
2373  *
2374  * @param program host memory to copy bytes from. Must be 4B aligned
2375  *
2376  * @param len the number of bytes to copy from the bost into the APF working
2377  * memory
2378  *
2379  * @param program_length new length of the program instructions in bytes to pass
2380  * to the interpreter
2381  */
2382 
wifi_write_packet_filter(wifi_interface_handle iface,u32 dst_offset,const u8 * program,u32 len,u32 program_length)2383 wifi_error wifi_write_packet_filter(wifi_interface_handle iface,
2384                                          u32 dst_offset, const u8 *program,
2385                                          u32 len, u32 program_length)
2386 {
2387     wifi_error ret;
2388     struct nlattr *nlData;
2389     WifiVendorCommand *vCommand = NULL;
2390     u32 current_offset = 0;
2391     wifi_handle wifiHandle = getWifiHandle(iface);
2392     hal_info *info = getHalInfo(wifiHandle);
2393 
2394     /* len=0 clears the filters in driver/firmware */
2395     if (len != 0 && program == NULL) {
2396         ALOGE("%s: No valid program provided. Exit.",
2397             __func__);
2398         return WIFI_ERROR_INVALID_ARGS;
2399     }
2400 
2401     do {
2402         ret = initialize_vendor_cmd(iface, get_requestid(),
2403                                     QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
2404                                     &vCommand);
2405         if (ret != WIFI_SUCCESS) {
2406             ALOGE("%s: Initialization failed", __FUNCTION__);
2407             return ret;
2408         }
2409 
2410         /* Add the vendor specific attributes for the NL command. */
2411         nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2412         if (!nlData)
2413              goto cleanup;
2414 
2415         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
2416                                  QCA_WLAN_WRITE_PACKET_FILTER);
2417         if (ret != WIFI_SUCCESS)
2418             goto cleanup;
2419         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID,
2420                                 PACKET_FILTER_ID);
2421         if (ret != WIFI_SUCCESS)
2422             goto cleanup;
2423         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE,
2424                                 len);
2425         if (ret != WIFI_SUCCESS)
2426             goto cleanup;
2427         ret = vCommand->put_u32(
2428                             QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
2429                             dst_offset + current_offset);
2430         if (ret != WIFI_SUCCESS)
2431             goto cleanup;
2432         ret = vCommand->put_u32(
2433                            QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROG_LENGTH,
2434                             program_length);
2435         if (ret != WIFI_SUCCESS)
2436             goto cleanup;
2437 
2438         ret = vCommand->put_bytes(
2439                                  QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM,
2440                                  (char *)&program[current_offset],
2441                                  min(info->firmware_bus_max_size,
2442                                  len - current_offset));
2443         if (ret!= WIFI_SUCCESS) {
2444             ALOGE("%s: failed to put program", __FUNCTION__);
2445             goto cleanup;
2446         }
2447 
2448         vCommand->attr_end(nlData);
2449 
2450         ret = vCommand->requestResponse();
2451        if (ret != WIFI_SUCCESS) {
2452             ALOGE("%s: requestResponse Error:%d",__func__, ret);
2453             goto cleanup;
2454         }
2455 
2456         /* destroy the object after sending each fragment to driver */
2457         delete vCommand;
2458         vCommand = NULL;
2459 
2460         current_offset += min(info->firmware_bus_max_size,
2461                                          len - current_offset);
2462     } while (current_offset < len);
2463 
2464 cleanup:
2465     if (vCommand)
2466         delete vCommand;
2467     return ret;
2468 }
2469 
wifi_enable_packet_filter(wifi_interface_handle handle,u32 enable)2470 wifi_error wifi_enable_packet_filter(wifi_interface_handle handle,
2471                                         u32 enable)
2472 {
2473     wifi_error ret;
2474     struct nlattr *nlData;
2475     WifiVendorCommand *vCommand = NULL;
2476     u32 subcmd;
2477     wifi_handle wifiHandle = getWifiHandle(handle);
2478     hal_info *info = getHalInfo(wifiHandle);
2479 
2480     ret = initialize_vendor_cmd(handle, get_requestid(),
2481                                 QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
2482                                 &vCommand);
2483 
2484     if (ret != WIFI_SUCCESS) {
2485         ALOGE("%s: Initialization failed", __func__);
2486         return ret;
2487     }
2488     /* Add the vendor specific attributes for the NL command. */
2489     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2490     if (!nlData)
2491         goto cleanup;
2492 
2493     subcmd = enable ? QCA_WLAN_ENABLE_PACKET_FILTER :
2494                       QCA_WLAN_DISABLE_PACKET_FILTER;
2495     ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
2496                             subcmd);
2497     if (ret != WIFI_SUCCESS)
2498             goto cleanup;
2499 
2500     vCommand->attr_end(nlData);
2501     ret = vCommand->requestResponse();
2502 
2503     if (ret != WIFI_SUCCESS) {
2504         ALOGE("%s: requestResponse() error: %d", __FUNCTION__, ret);
2505         goto cleanup;
2506     }
2507 
2508     info->apf_enabled = !!enable;
2509 
2510 cleanup:
2511     if (vCommand)
2512         delete vCommand;
2513     return ret;
2514 
2515 }
2516 
2517 /**
2518  * Copy 'length' bytes of raw data from APF (Android Packet Filter) working
2519  * memory  to host memory starting at offset src_offset into host memory
2520  * pointed to by host_dst.
2521  * Memory can be text, data or some combination of the two. The implementiion is
2522  * allowed to translate this read into a series of smaller reads, but this
2523  * function is not allowed to return untill all the reads operations
2524  * into host_dst have been completed.
2525  *
2526  * @param src_offset offset in bytes of destination memory within APF working
2527  * memory
2528  *
2529  * @param host_dst host memory to copy into. Must be 4B aligned.
2530  *
2531  * @param length the number of bytes to copy from the APF working memory to the
2532  * host.
2533  */
2534 
wifi_read_packet_filter(wifi_interface_handle handle,u32 src_offset,u8 * host_dst,u32 length)2535 static wifi_error wifi_read_packet_filter(wifi_interface_handle handle,
2536                                           u32 src_offset, u8 *host_dst, u32 length)
2537 {
2538     wifi_error ret = WIFI_SUCCESS;
2539     struct nlattr *nlData;
2540     WifihalGeneric *vCommand = NULL;
2541     interface_info *ifaceInfo = getIfaceInfo(handle);
2542     wifi_handle wifiHandle = getWifiHandle(handle);
2543     hal_info *info = getHalInfo(wifiHandle);
2544 
2545     /* Length to be passed to this function should be non-zero
2546      * Return invalid argument if length is passed as zero
2547      */
2548     if (length == 0)
2549         return  WIFI_ERROR_INVALID_ARGS;
2550 
2551     /*Temporary varibles to support the read complete length in chunks */
2552     u8 *temp_host_dst;
2553     u32 remainingLengthToBeRead, currentLength;
2554     u8 apf_locally_disabled = 0;
2555 
2556     /*Initializing the temporary variables*/
2557     temp_host_dst = host_dst;
2558     remainingLengthToBeRead = length;
2559 
2560     if (info->apf_enabled) {
2561         /* Disable APF only when not disabled by framework before calling
2562          * wifi_read_packet_filter()
2563          */
2564         ret = wifi_enable_packet_filter(handle, 0);
2565         if (ret != WIFI_SUCCESS) {
2566             ALOGE("%s: Failed to disable APF", __FUNCTION__);
2567             return ret;
2568         }
2569         apf_locally_disabled = 1;
2570     }
2571     /**
2572      * Read the complete length in chunks of size less or equal to firmware bus
2573      * max size
2574      */
2575     while (remainingLengthToBeRead)
2576     {
2577         vCommand = new WifihalGeneric(wifiHandle, 0, OUI_QCA,
2578                                       QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER);
2579 
2580         if (vCommand == NULL) {
2581             ALOGE("%s: Error vCommand NULL", __FUNCTION__);
2582             ret = WIFI_ERROR_OUT_OF_MEMORY;
2583             break;
2584         }
2585 
2586         /* Create the message */
2587         ret = vCommand->create();
2588         if (ret != WIFI_SUCCESS)
2589             break;
2590         ret = vCommand->set_iface_id(ifaceInfo->name);
2591         if (ret != WIFI_SUCCESS)
2592             break;
2593         /* Add the vendor specific attributes for the NL command. */
2594         nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
2595         if (!nlData)
2596             break;
2597         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
2598                                 QCA_WLAN_READ_PACKET_FILTER);
2599         if (ret != WIFI_SUCCESS)
2600             break;
2601 
2602         currentLength = min(remainingLengthToBeRead, info->firmware_bus_max_size);
2603 
2604         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE,
2605                                 currentLength);
2606         if (ret != WIFI_SUCCESS)
2607             break;
2608         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
2609                                 src_offset);
2610         if (ret != WIFI_SUCCESS)
2611             break;
2612 
2613         vCommand->setPacketBufferParams(temp_host_dst, currentLength);
2614         vCommand->attr_end(nlData);
2615         ret = vCommand->requestResponse();
2616 
2617         if (ret != WIFI_SUCCESS) {
2618             ALOGE("%s: requestResponse() error: %d current_len = %u, src_offset = %u",
2619                   __FUNCTION__, ret, currentLength, src_offset);
2620             break;
2621         }
2622 
2623         remainingLengthToBeRead -= currentLength;
2624         temp_host_dst += currentLength;
2625         src_offset += currentLength;
2626         delete vCommand;
2627         vCommand = NULL;
2628     }
2629 
2630     /* Re enable APF only when disabled above within this API */
2631     if (apf_locally_disabled) {
2632         wifi_error status;
2633         status = wifi_enable_packet_filter(handle, 1);
2634         if (status != WIFI_SUCCESS)
2635             ALOGE("%s: Failed to enable APF", __FUNCTION__);
2636         /* Prefer to return read status if read fails */
2637         if (ret == WIFI_SUCCESS)
2638             ret = status;
2639     }
2640 
2641     delete vCommand;
2642     return ret;
2643 }
2644