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