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