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-types.h>
17
18 #include "nl80211_copy.h"
19 #include "sync.h"
20
21 #define LOG_TAG "WifiHAL"
22
23 #include <utils/Log.h>
24
25 #include "wifi_hal.h"
26 #include "common.h"
27 #include "cpp_bindings.h"
28
29 using namespace android;
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
MKeepAliveCommand(wifi_interface_handle iface,u8 index,u8 * ip_packet,u16 ip_packet_len,u8 * src_mac_addr,u8 * dst_mac_addr,u32 period_msec,GetCmdType cmdType)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
MKeepAliveCommand(wifi_interface_handle iface,u8 index,GetCmdType cmdType)72 MKeepAliveCommand(wifi_interface_handle iface, u8 index, GetCmdType cmdType)
73 : WifiCommand("MKeepAliveCommand", iface, 0), mIndex(index), mType(cmdType)
74 { }
75
createRequest(WifiRequest & request)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
start()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
handleResponse(WifiEvent & reply)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
handleEvent(WifiEvent & event)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. */
wifi_start_sending_offloaded_packet(wifi_request_id index,wifi_interface_handle iface,u8 * ip_packet,u16 ip_packet_len,u8 * src_mac_addr,u8 * dst_mac_addr,u32 period_msec)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. */
wifi_stop_sending_offloaded_packet(wifi_request_id index,wifi_interface_handle iface)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