Home | History | Annotate | Download | only in wifi_hal
      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 <fcntl.h>
     19 #include <sys/socket.h>
     20 #include <netlink/genl/genl.h>
     21 #include <netlink/genl/family.h>
     22 #include <netlink/genl/ctrl.h>
     23 #include <linux/rtnetlink.h>
     24 #include <netpacket/packet.h>
     25 #include <linux/filter.h>
     26 #include <linux/errqueue.h>
     27 
     28 #include <linux/pkt_sched.h>
     29 #include <netlink/object-api.h>
     30 #include <netlink/netlink.h>
     31 #include <netlink/socket.h>
     32 #include <netlink-types.h>
     33 
     34 #include "nl80211_copy.h"
     35 
     36 #include <dirent.h>
     37 #include <net/if.h>
     38 
     39 #include "sync.h"
     40 
     41 #define LOG_TAG  "WifiHAL"
     42 
     43 #include <utils/Log.h>
     44 
     45 #include "wifi_hal.h"
     46 #include "common.h"
     47 #include "cpp_bindings.h"
     48 
     49 /*
     50  BUGBUG: normally, libnl allocates ports for all connections it makes; but
     51  being a static library, it doesn't really know how many other netlink connections
     52  are made by the same process, if connections come from different shared libraries.
     53  These port assignments exist to solve that problem - temporarily. We need to fix
     54  libnl to try and allocate ports across the entire process.
     55  */
     56 
     57 #define WIFI_HAL_CMD_SOCK_PORT       644
     58 #define WIFI_HAL_EVENT_SOCK_PORT     645
     59 
     60 static void internal_event_handler(wifi_handle handle, int events);
     61 static int internal_valid_message_handler(nl_msg *msg, void *arg);
     62 static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group);
     63 static int wifi_add_membership(wifi_handle handle, const char *group);
     64 static wifi_error wifi_init_interfaces(wifi_handle handle);
     65 
     66 /* Initialize/Cleanup */
     67 
     68 void wifi_socket_set_local_port(struct nl_sock *sock, uint32_t port)
     69 {
     70     uint32_t pid = getpid() & 0x3FFFFF;
     71 
     72     if (port == 0) {
     73         sock->s_flags &= ~NL_OWN_PORT;
     74     } else {
     75         sock->s_flags |= NL_OWN_PORT;
     76     }
     77 
     78     sock->s_local.nl_pid = pid + (port << 22);
     79 }
     80 
     81 static nl_sock * wifi_create_nl_socket(int port)
     82 {
     83     // ALOGI("Creating socket");
     84     struct nl_sock *sock = nl_socket_alloc();
     85     if (sock == NULL) {
     86         ALOGE("Could not create handle");
     87         return NULL;
     88     }
     89 
     90     wifi_socket_set_local_port(sock, port);
     91 
     92     struct sockaddr_nl *addr_nl = &(sock->s_local);
     93     /* ALOGI("socket address is %d:%d:%d:%d",
     94         addr_nl->nl_family, addr_nl->nl_pad, addr_nl->nl_pid, addr_nl->nl_groups); */
     95 
     96     struct sockaddr *addr = NULL;
     97     // ALOGI("sizeof(sockaddr) = %d, sizeof(sockaddr_nl) = %d", sizeof(*addr), sizeof(*addr_nl));
     98 
     99     // ALOGI("Connecting socket");
    100     if (nl_connect(sock, NETLINK_GENERIC)) {
    101         ALOGE("Could not connect handle");
    102         nl_socket_free(sock);
    103         return NULL;
    104     }
    105 
    106     ALOGI("Socket Value:%p", sock);
    107     return sock;
    108 }
    109 
    110 int ack_handler(struct nl_msg *msg, void *arg)
    111 {
    112     int *err = (int *)arg;
    113     *err = 0;
    114     ALOGD("%s invoked",__func__);
    115     return NL_STOP;
    116 }
    117 
    118 int finish_handler(struct nl_msg *msg, void *arg)
    119 {
    120     int *ret = (int *)arg;
    121     *ret = 0;
    122     ALOGD("%s called",__func__);
    123     return NL_SKIP;
    124 }
    125 
    126 int error_handler(struct sockaddr_nl *nla,
    127                   struct nlmsgerr *err, void *arg)
    128 {
    129     int *ret = (int *)arg;
    130     *ret = err->error;
    131 
    132     ALOGD("%s invoked with error: %d", __func__, err->error);
    133     return NL_SKIP;
    134 }
    135 static int no_seq_check(struct nl_msg *msg, void *arg)
    136 {
    137     ALOGD("no_seq_check received");
    138     return NL_OK;
    139 }
    140 
    141 wifi_error wifi_initialize(wifi_handle *handle)
    142 {
    143     int err = 0;
    144     srand(getpid());
    145 
    146     ALOGI("Initializing wifi");
    147     hal_info *info = (hal_info *)malloc(sizeof(hal_info));
    148     if (info == NULL) {
    149         ALOGE("Could not allocate hal_info");
    150         return WIFI_ERROR_UNKNOWN;
    151     }
    152 
    153     memset(info, 0, sizeof(*info));
    154 
    155     ALOGI("Creating socket");
    156     struct nl_sock *cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT);
    157     if (cmd_sock == NULL) {
    158         ALOGE("Could not create handle");
    159         return WIFI_ERROR_UNKNOWN;
    160     }
    161 
    162     struct nl_sock *event_sock = wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT);
    163     if (event_sock == NULL) {
    164         ALOGE("Could not create handle");
    165         nl_socket_free(cmd_sock);
    166         return WIFI_ERROR_UNKNOWN;
    167     }
    168 
    169     struct nl_cb *cb = nl_socket_get_cb(event_sock);
    170     if (cb == NULL) {
    171         ALOGE("Could not create handle");
    172         return WIFI_ERROR_UNKNOWN;
    173     }
    174 
    175     err = 1;
    176     nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
    177     nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
    178     nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
    179     nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
    180 
    181     nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler, info);
    182     nl_cb_put(cb);
    183 
    184     info->cmd_sock = cmd_sock;
    185     info->event_sock = event_sock;
    186     info->clean_up = false;
    187     info->in_event_loop = false;
    188 
    189     info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE);
    190     info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE;
    191     info->num_event_cb = 0;
    192 
    193     info->cmd = (cmd_info *)malloc(sizeof(cmd_info) * DEFAULT_CMD_SIZE);
    194     info->alloc_cmd = DEFAULT_CMD_SIZE;
    195     info->num_cmd = 0;
    196 
    197     info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211");
    198     if (info->nl80211_family_id < 0) {
    199         ALOGE("Could not resolve nl80211 familty id");
    200         nl_socket_free(cmd_sock);
    201         nl_socket_free(event_sock);
    202         free(info);
    203         return WIFI_ERROR_UNKNOWN;
    204     }
    205     ALOGI("%s: family_id:%d", __func__, info->nl80211_family_id);
    206 
    207     *handle = (wifi_handle) info;
    208 
    209     wifi_add_membership(*handle, "scan");
    210     wifi_add_membership(*handle, "mlme");
    211     wifi_add_membership(*handle, "regulatory");
    212     wifi_add_membership(*handle, "vendor");
    213 
    214     wifi_init_interfaces(*handle);
    215     // ALOGI("Found %d interfaces", info->num_interfaces);
    216 
    217     ALOGI("Initialized Wifi HAL Successfully; vendor cmd = %d handle %p", NL80211_CMD_VENDOR ,
    218                        *handle);
    219     return WIFI_SUCCESS;
    220 }
    221 
    222 static int wifi_add_membership(wifi_handle handle, const char *group)
    223 {
    224     hal_info *info = getHalInfo(handle);
    225 
    226     int id = wifi_get_multicast_id(handle, "nl80211", group);
    227     if (id < 0) {
    228         ALOGE("Could not find group %s", group);
    229         return id;
    230     }
    231 
    232     int ret = nl_socket_add_membership(info->event_sock, id);
    233     if (ret < 0) {
    234         ALOGE("Could not add membership to group %s", group);
    235     }
    236 
    237     // ALOGI("Successfully added membership for group %s", group);
    238     return ret;
    239 }
    240 
    241 static void internal_cleaned_up_handler(wifi_handle handle)
    242 {
    243     hal_info *info = getHalInfo(handle);
    244     wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler;
    245 
    246     if (info->cmd_sock != 0) {
    247         nl_socket_free(info->cmd_sock);
    248         nl_socket_free(info->event_sock);
    249         info->cmd_sock = NULL;
    250         info->event_sock = NULL;
    251     }
    252 
    253     (*cleaned_up_handler)(handle);
    254     free(info);
    255 
    256     ALOGI("Internal cleanup completed");
    257 }
    258 
    259 void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
    260 {
    261     hal_info *info = getHalInfo(handle);
    262     info->cleaned_up_handler = handler;
    263     info->clean_up = true;
    264 
    265     ALOGI("Wifi cleanup completed");
    266 }
    267 
    268 static int internal_pollin_handler(wifi_handle handle)
    269 {
    270     hal_info *info = getHalInfo(handle);
    271     struct nl_cb *cb = nl_socket_get_cb(info->event_sock);
    272     int res = nl_recvmsgs(info->event_sock, cb);
    273     nl_cb_put(cb);
    274     return res;
    275 }
    276 
    277 static void internal_event_handler(wifi_handle handle, int events)
    278 {
    279     if (events & POLLERR) {
    280         ALOGE("Error reading from socket");
    281     } else if (events & POLLHUP) {
    282         ALOGE("Remote side hung up");
    283     } else if (events & POLLIN) {
    284         ALOGI("Found some events!!!");
    285         internal_pollin_handler(handle);
    286     } else {
    287         ALOGE("Unknown event - %0x", events);
    288     }
    289 }
    290 
    291 /* Run event handler */
    292 void wifi_event_loop(wifi_handle handle)
    293 {
    294     hal_info *info = getHalInfo(handle);
    295     if (info->in_event_loop) {
    296         return;
    297     } else {
    298         info->in_event_loop = true;
    299     }
    300 
    301     pollfd pfd;
    302     memset(&pfd, 0, sizeof(pfd));
    303 
    304     pfd.fd = nl_socket_get_fd(info->event_sock);
    305     pfd.events = POLLIN;
    306 
    307     /* TODO: Add support for timeouts */
    308 
    309     do {
    310         int timeout = -1;                   /* Infinite timeout */
    311         pfd.revents = 0;
    312         //ALOGI("Polling socket");
    313         int result = poll(&pfd, 1, -1);
    314         ALOGI("Poll result = %0x", result);
    315         if (result < 0) {
    316             ALOGE("Error polling socket");
    317         } else if (pfd.revents & (POLLIN | POLLHUP | POLLERR)) {
    318             internal_event_handler(handle, pfd.revents);
    319         }
    320     } while (!info->clean_up);
    321 
    322 
    323     ALOGI("Cleaning up");
    324     internal_cleaned_up_handler(handle);
    325 }
    326 
    327 ///////////////////////////////////////////////////////////////////////////////////////
    328 
    329 static int internal_valid_message_handler(nl_msg *msg, void *arg)
    330 {
    331     wifi_handle handle = (wifi_handle)arg;
    332     hal_info *info = getHalInfo(handle);
    333 
    334     WifiEvent event(msg);
    335     int res = event.parse();
    336     if (res < 0) {
    337         ALOGE("Failed to parse event: %d", res);
    338         return NL_SKIP;
    339     }
    340 
    341     int cmd = event.get_cmd();
    342     uint32_t vendor_id = 0;
    343     int subcmd = 0;
    344 
    345     if (cmd == NL80211_CMD_VENDOR) {
    346         vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID);
    347         subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD);
    348         ALOGI("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x",
    349                 event.get_cmdString(), vendor_id, subcmd);
    350     } else {
    351         ALOGI("event received %s", event.get_cmdString());
    352     }
    353 
    354     ALOGI("event received %s, vendor_id = 0x%0x", event.get_cmdString(), vendor_id);
    355     // event.log();
    356 
    357     bool dispatched = false;
    358     for (int i = 0; i < info->num_event_cb; i++) {
    359         if (cmd == info->event_cb[i].nl_cmd) {
    360             if (cmd == NL80211_CMD_VENDOR
    361                 && ((vendor_id != info->event_cb[i].vendor_id)
    362                 || (subcmd != info->event_cb[i].vendor_subcmd)))
    363             {
    364                 /* event for a different vendor, ignore it */
    365                 continue;
    366             }
    367 
    368             cb_info *cbi = &(info->event_cb[i]);
    369             (*(cbi->cb_func))(msg, cbi->cb_arg);
    370             dispatched = true;
    371         }
    372     }
    373 
    374     if (!dispatched) {
    375         ALOGI("event ignored!!");
    376     }
    377 
    378     return NL_OK;
    379 }
    380 
    381 ///////////////////////////////////////////////////////////////////////////////////////
    382 
    383 class GetMulticastIdCommand : public WifiCommand
    384 {
    385 private:
    386     const char *mName;
    387     const char *mGroup;
    388     int   mId;
    389 public:
    390     GetMulticastIdCommand(wifi_handle handle, const char *name, const char *group)
    391         : WifiCommand(handle, 0)
    392     {
    393         mName = name;
    394         mGroup = group;
    395         mId = -1;
    396     }
    397 
    398     int getId() {
    399         return mId;
    400     }
    401 
    402     virtual int create() {
    403         int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl");
    404         // ALOGI("ctrl family = %d", nlctrlFamily);
    405         int ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0);
    406         if (ret < 0) {
    407             return ret;
    408         }
    409         ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName);
    410         return ret;
    411     }
    412 
    413     virtual int handleResponse(WifiEvent& reply) {
    414 
    415         // ALOGI("handling reponse in %s", __func__);
    416 
    417         struct nlattr **tb = reply.attributes();
    418         struct genlmsghdr *gnlh = reply.header();
    419         struct nlattr *mcgrp = NULL;
    420         int i;
    421 
    422         if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
    423             ALOGI("No multicast groups found");
    424             return NL_SKIP;
    425         } else {
    426             // ALOGI("Multicast groups attr size = %d", nla_len(tb[CTRL_ATTR_MCAST_GROUPS]));
    427         }
    428 
    429         for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
    430 
    431             // ALOGI("Processing group");
    432             struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
    433             nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp),
    434                 nla_len(mcgrp), NULL);
    435             if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID]) {
    436                 continue;
    437             }
    438 
    439             char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
    440             int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
    441 
    442             // ALOGI("Found group name %s", grpName);
    443 
    444             if (strncmp(grpName, mGroup, grpNameLen) != 0)
    445                 continue;
    446 
    447             mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
    448             break;
    449         }
    450 
    451         return NL_SKIP;
    452     }
    453 
    454 };
    455 
    456 static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group)
    457 {
    458     GetMulticastIdCommand cmd(handle, name, group);
    459     int res = cmd.requestResponse();
    460     if (res < 0)
    461         return res;
    462     else
    463         return cmd.getId();
    464 }
    465 
    466 /////////////////////////////////////////////////////////////////////////
    467 
    468 static bool is_wifi_interface(const char *name)
    469 {
    470     if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0) {
    471         /* not a wifi interface; ignore it */
    472         return false;
    473     } else {
    474         return true;
    475     }
    476 }
    477 
    478 static int get_interface(const char *name, interface_info *info)
    479 {
    480     strcpy(info->name, name);
    481     info->id = if_nametoindex(name);
    482     // ALOGI("found an interface : %s, id = %d", name, info->id);
    483     return WIFI_SUCCESS;
    484 }
    485 
    486 wifi_error wifi_init_interfaces(wifi_handle handle)
    487 {
    488     hal_info *info = (hal_info *)handle;
    489 
    490     struct dirent *de;
    491 
    492     DIR *d = opendir("/sys/class/net");
    493     if (d == 0)
    494         return WIFI_ERROR_UNKNOWN;
    495 
    496     int n = 0;
    497     while ((de = readdir(d))) {
    498         if (de->d_name[0] == '.')
    499             continue;
    500         if (is_wifi_interface(de->d_name) ) {
    501             n++;
    502         }
    503     }
    504 
    505     closedir(d);
    506 
    507     d = opendir("/sys/class/net");
    508     if (d == 0)
    509         return WIFI_ERROR_UNKNOWN;
    510 
    511     info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n);
    512 
    513     int i = 0;
    514     while ((de = readdir(d))) {
    515         if (de->d_name[0] == '.')
    516             continue;
    517         if (is_wifi_interface(de->d_name)) {
    518             interface_info *ifinfo = (interface_info *)malloc(sizeof(interface_info));
    519             if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {
    520                 free(ifinfo);
    521                 continue;
    522             }
    523             ifinfo->handle = handle;
    524             info->interfaces[i] = ifinfo;
    525             i++;
    526         }
    527     }
    528 
    529     closedir(d);
    530 
    531     info->num_interfaces = n;
    532     return WIFI_SUCCESS;
    533 }
    534 
    535 wifi_error wifi_get_ifaces(wifi_handle handle, int *num, wifi_interface_handle **interfaces)
    536 {
    537     hal_info *info = (hal_info *)handle;
    538 
    539     *interfaces = (wifi_interface_handle *)info->interfaces;
    540     *num = info->num_interfaces;
    541 
    542     return WIFI_SUCCESS;
    543 }
    544 
    545 wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name, size_t size)
    546 {
    547     interface_info *info = (interface_info *)handle;
    548     strcpy(name, info->name);
    549     return WIFI_SUCCESS;
    550 }
    551 
    552 wifi_interface_handle wifi_get_iface_handle(wifi_handle handle, char *name)
    553 {
    554     hal_info *info = (hal_info *)handle;
    555     for (int i=0;i<info->num_interfaces;i++)
    556     {
    557         if (!strcmp(info->interfaces[i]->name, name))
    558         {
    559             return ((wifi_interface_handle )(info->interfaces)[i]);
    560         }
    561     }
    562     return NULL;
    563 }
    564 
    565 /////////////////////////////////////////////////////////////////////////////
    566 
    567 wifi_error wifi_get_supported_feature_set(wifi_interface_handle handle, feature_set *set) {
    568     return WIFI_ERROR_NOT_SUPPORTED;
    569 }
    570 
    571 wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle, int max_size,
    572         feature_set *matrix, int *size) {
    573     return WIFI_ERROR_NOT_SUPPORTED;
    574 }
    575 
    576