Home | History | Annotate | Download | only in wifi_hal
      1 #include <stdint.h>
      2 #include <fcntl.h>
      3 #include <sys/socket.h>
      4 #include <netlink/genl/genl.h>
      5 #include <netlink/genl/family.h>
      6 #include <netlink/genl/ctrl.h>
      7 #include <linux/rtnetlink.h>
      8 #include <netpacket/packet.h>
      9 #include <linux/filter.h>
     10 #include <linux/errqueue.h>
     11 
     12 #include <linux/pkt_sched.h>
     13 #include <netlink/object-api.h>
     14 #include <netlink/netlink.h>
     15 #include <netlink/socket.h>
     16 #include <netlink-private/object-api.h>
     17 #include <netlink-private/types.h>
     18 
     19 
     20 #include "nl80211_copy.h"
     21 #include "sync.h"
     22 
     23 #define LOG_TAG  "WifiHAL"
     24 
     25 #include <log/log.h>
     26 
     27 #include "wifi_hal.h"
     28 #include "common.h"
     29 #include "cpp_bindings.h"
     30 
     31 typedef enum {
     32     WIFI_OFFLOAD_START_MKEEP_ALIVE = ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START,
     33     WIFI_OFFLOAD_STOP_MKEEP_ALIVE,
     34 } WIFI_OFFLOAD_SUB_COMMAND;
     35 
     36 typedef enum {
     37     MKEEP_ALIVE_ATTRIBUTE_ID,
     38     MKEEP_ALIVE_ATTRIBUTE_IP_PKT,
     39     MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN,
     40     MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR,
     41     MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR,
     42     MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC
     43 } WIFI_MKEEP_ALIVE_ATTRIBUTE;
     44 
     45 typedef enum {
     46     START_MKEEP_ALIVE,
     47     STOP_MKEEP_ALIVE,
     48 } GetCmdType;
     49 
     50 ///////////////////////////////////////////////////////////////////////////////
     51 class MKeepAliveCommand : public WifiCommand
     52 {
     53     u8 mIndex;
     54     u8 *mIpPkt;
     55     u16 mIpPktLen;
     56     u8 *mSrcMacAddr;
     57     u8 *mDstMacAddr;
     58     u32 mPeriodMsec;
     59     GetCmdType mType;
     60 
     61 public:
     62 
     63     // constructor for start sending
     64     MKeepAliveCommand(wifi_interface_handle iface, u8 index, u8 *ip_packet, u16 ip_packet_len,
     65             u8 *src_mac_addr, u8 *dst_mac_addr, u32 period_msec, GetCmdType cmdType)
     66         : WifiCommand("MKeepAliveCommand", iface, 0), mIndex(index), mIpPkt(ip_packet),
     67         mIpPktLen(ip_packet_len), mSrcMacAddr(src_mac_addr), mDstMacAddr(dst_mac_addr),
     68         mPeriodMsec(period_msec), mType(cmdType)
     69     { }
     70 
     71     // constructor for stop sending
     72     MKeepAliveCommand(wifi_interface_handle iface, u8 index, GetCmdType cmdType)
     73         : WifiCommand("MKeepAliveCommand", iface, 0), mIndex(index), mType(cmdType)
     74     { }
     75 
     76     int createRequest(WifiRequest &request) {
     77         int result;
     78 
     79         switch (mType) {
     80             case START_MKEEP_ALIVE:
     81             {
     82                 result = request.create(GOOGLE_OUI, WIFI_OFFLOAD_START_MKEEP_ALIVE);
     83                 if (result != WIFI_SUCCESS) {
     84                     ALOGE("Failed to create start keep alive request; result = %d", result);
     85                     return result;
     86                 }
     87 
     88                 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
     89 
     90                 result = request.put_u8(MKEEP_ALIVE_ATTRIBUTE_ID, mIndex);
     91                 if (result < 0) {
     92                     ALOGE("Failed to put id request; result = %d", result);
     93                     return result;
     94                 }
     95 
     96                 result = request.put_u16(MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN, mIpPktLen);
     97                 if (result < 0) {
     98                     ALOGE("Failed to put ip pkt len request; result = %d", result);
     99                     return result;
    100                 }
    101 
    102                 result = request.put(MKEEP_ALIVE_ATTRIBUTE_IP_PKT, (u8*)mIpPkt, mIpPktLen);
    103                 if (result < 0) {
    104                     ALOGE("Failed to put ip pkt request; result = %d", result);
    105                     return result;
    106                 }
    107 
    108                 result = request.put_addr(MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR, mSrcMacAddr);
    109                 if (result < 0) {
    110                     ALOGE("Failed to put src mac address request; result = %d", result);
    111                     return result;
    112                 }
    113 
    114                 result = request.put_addr(MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR, mDstMacAddr);
    115                 if (result < 0) {
    116                     ALOGE("Failed to put dst mac address request; result = %d", result);
    117                     return result;
    118                 }
    119 
    120                 result = request.put_u32(MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC, mPeriodMsec);
    121                 if (result < 0) {
    122                     ALOGE("Failed to put period request; result = %d", result);
    123                     return result;
    124                 }
    125 
    126                 request.attr_end(data);
    127                 break;
    128             }
    129 
    130             case STOP_MKEEP_ALIVE:
    131             {
    132                 result = request.create(GOOGLE_OUI, WIFI_OFFLOAD_STOP_MKEEP_ALIVE);
    133                 if (result != WIFI_SUCCESS) {
    134                     ALOGE("Failed to create stop keep alive request; result = %d", result);
    135                     return result;
    136                 }
    137 
    138                 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
    139 
    140                 result = request.put_u8(MKEEP_ALIVE_ATTRIBUTE_ID, mIndex);
    141                 if (result < 0) {
    142                     ALOGE("Failed to put id request; result = %d", result);
    143                     return result;
    144                 }
    145 
    146                 request.attr_end(data);
    147                 break;
    148             }
    149 
    150             default:
    151                 ALOGE("Unknown wifi keep alive command");
    152                 result = WIFI_ERROR_UNKNOWN;
    153         }
    154         return result;
    155     }
    156 
    157     int start() {
    158         ALOGD("Start mkeep_alive command");
    159         WifiRequest request(familyId(), ifaceId());
    160         int result = createRequest(request);
    161         if (result != WIFI_SUCCESS) {
    162             ALOGE("Failed to create keep alive request; result = %d", result);
    163             return result;
    164         }
    165 
    166         result = requestResponse(request);
    167         if (result != WIFI_SUCCESS) {
    168             ALOGE("Failed to register keep alive response; result = %d", result);
    169         }
    170         return result;
    171     }
    172 
    173     virtual int handleResponse(WifiEvent& reply) {
    174         ALOGD("In MKeepAliveCommand::handleResponse");
    175 
    176         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
    177             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
    178             return NL_SKIP;
    179         }
    180 
    181         switch (mType) {
    182             case START_MKEEP_ALIVE:
    183             case STOP_MKEEP_ALIVE:
    184                 break;
    185 
    186             default:
    187                 ALOGW("Unknown mkeep_alive command");
    188         }
    189         return NL_OK;
    190     }
    191 
    192     virtual int handleEvent(WifiEvent& event) {
    193         /* NO events! */
    194         return NL_SKIP;
    195     }
    196 };
    197 
    198 
    199 /* API to send specified mkeep_alive packet periodically. */
    200 wifi_error wifi_start_sending_offloaded_packet(wifi_request_id index, wifi_interface_handle iface,
    201         u8 *ip_packet, u16 ip_packet_len, u8 *src_mac_addr, u8 *dst_mac_addr, u32 period_msec)
    202 {
    203     if ((index > 0 && index <= N_AVAIL_ID) && (ip_packet != NULL) && (src_mac_addr != NULL)
    204             && (dst_mac_addr != NULL) && (period_msec > 0)
    205             && (ip_packet_len <= MKEEP_ALIVE_IP_PKT_MAX)) {
    206         MKeepAliveCommand *cmd = new MKeepAliveCommand(iface, index, ip_packet, ip_packet_len,
    207                 src_mac_addr, dst_mac_addr, period_msec, START_MKEEP_ALIVE);
    208         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
    209         wifi_error result = (wifi_error)cmd->start();
    210         cmd->releaseRef();
    211         return result;
    212     } else {
    213         ALOGE("Invalid mkeep_alive parameters");
    214         return  WIFI_ERROR_INVALID_ARGS;
    215     }
    216 }
    217 
    218 /* API to stop sending mkeep_alive packet. */
    219 wifi_error wifi_stop_sending_offloaded_packet(wifi_request_id index, wifi_interface_handle iface)
    220 {
    221     if (index > 0 && index <= N_AVAIL_ID) {
    222         MKeepAliveCommand *cmd = new MKeepAliveCommand(iface, index, STOP_MKEEP_ALIVE);
    223         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
    224         wifi_error result = (wifi_error)cmd->start();
    225         cmd->releaseRef();
    226         return result;
    227     } else {
    228         ALOGE("Invalid mkeep_alive parameters");
    229         return  WIFI_ERROR_INVALID_ARGS;
    230     }
    231 }
    232