1 /*
2 * Copyright (C) 2016, 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 <memory>
18
19 #include <gtest/gtest.h>
20
21 #include <linux/nl80211.h>
22
23 #include "wificond/net/nl80211_attribute.h"
24 #include "wificond/net/nl80211_packet.h"
25
26 using std::string;
27
28 namespace android {
29 namespace wificond {
30
31 namespace {
32
33 const uint8_t kU8Value1 = 150;
34 const uint16_t kU16Value1 = 5000;
35 const uint32_t kU32Value1 = 500000;
36 const uint32_t kU32Value2 = 800000;
37 const uint32_t kPortId = 123;
38
39 const uint8_t kGenNLCommand = 102;
40 const uint16_t kNLMsgType = 4000;
41 const uint32_t kNLMsgSequenceNumber = 70000;
42
43 // NL80211 family id is dynamically allocated by kernel.
44 const uint16_t kNL80211FamilyId = 0x13;
45 const uint32_t kWiPhy = 0;
46 const uint32_t kExpectedIfIndex = 4;
47 const uint8_t kMacAddressBytes[] = {
48 0xc0, 0x3f, 0x0e, 0x77, 0xe8, 0x7f
49 };
50
51 const unsigned char kNL80211_CMD_ASSOCIATE[] = {
52 0x58, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
53 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
54 0x26, 0x01, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00,
55 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0x00,
56 0x04, 0x00, 0x00, 0x00, 0x32, 0x00, 0x33, 0x00,
57 0x10, 0x00, 0x3a, 0x01, 0x48, 0x5d, 0x60, 0x77,
58 0x2d, 0xcf, 0xc0, 0x3f, 0x0e, 0x77, 0xe8, 0x7f,
59 0xc0, 0x3f, 0x0e, 0x77, 0xe8, 0x7f, 0x40, 0x07,
60 0x01, 0x04, 0x00, 0x00, 0x01, 0xc0, 0x01, 0x08,
61 0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24,
62 0x32, 0x04, 0x30, 0x48, 0x60, 0x6c, 0x00, 0x00,
63 };
64
65 const uint32_t kExpectedCqmNotAcked = 50;
66
67 const unsigned char kNL80211_CMD_NOTIFY_CQM[] = {
68 0x3c, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
69 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70 0x40, 0x01, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00,
71 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0x00,
72 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x06, 0x00,
73 0xc0, 0x3f, 0x0e, 0x77, 0xe8, 0x7f, 0x00, 0x00,
74 0x0c, 0x00, 0x5e, 0x00, 0x08, 0x00, 0x04, 0x00,
75 0x32, 0x00, 0x00, 0x00,
76 };
77
78 const uint32_t kNewStationExpectedGeneration = 275;
79
80 const unsigned char kNL80211_CMD_NEW_STATION[] = {
81 0x34, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83 0x13, 0x01, 0x00, 0x00, 0x08, 0x00, 0x03, 0x00,
84 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x06, 0x00,
85 0xc0, 0x3f, 0x0e, 0x77, 0xe8, 0x7f, 0x00, 0x00,
86 0x08, 0x00, 0x2e, 0x00, 0x13, 0x01, 0x00, 0x00,
87 0x04, 0x00, 0x15, 0x00,
88 };
89
90 } // namespace
91
TEST(NL80211PacketTest,CanConstructValidNL80211Packet)92 TEST(NL80211PacketTest, CanConstructValidNL80211Packet) {
93 NL80211Packet netlink_packet(kNLMsgType,
94 kGenNLCommand,
95 kNLMsgSequenceNumber,
96 kPortId);
97 EXPECT_TRUE(netlink_packet.IsValid());
98 }
99
TEST(NL80211PacketTest,SetAndGetNL80211PacketHeaderFields)100 TEST(NL80211PacketTest, SetAndGetNL80211PacketHeaderFields) {
101 NL80211Packet netlink_packet(kNLMsgType,
102 kGenNLCommand,
103 kNLMsgSequenceNumber,
104 kPortId);
105 netlink_packet.SetFlags(NLM_F_MULTI);
106 EXPECT_EQ(kGenNLCommand, netlink_packet.GetCommand());
107 EXPECT_EQ(kNLMsgType, netlink_packet.GetMessageType());
108 EXPECT_EQ(kNLMsgSequenceNumber, netlink_packet.GetMessageSequence());
109 EXPECT_TRUE(netlink_packet.IsMulti());
110 EXPECT_EQ(kPortId, netlink_packet.GetPortId());
111 }
112
TEST(NL80211PacketTest,AddAttributeToNL80211Packet)113 TEST(NL80211PacketTest, AddAttributeToNL80211Packet) {
114 NL80211Packet netlink_packet(kNLMsgType,
115 kGenNLCommand,
116 kNLMsgSequenceNumber,
117 kPortId);
118 NL80211Attr<uint8_t> u8_attr(1, kU8Value1);
119 netlink_packet.AddAttribute(u8_attr);
120 EXPECT_TRUE(netlink_packet.IsValid());
121 EXPECT_TRUE(netlink_packet.HasAttribute(1));
122 uint8_t attr_value;
123 EXPECT_TRUE(netlink_packet.GetAttributeValue(1, &attr_value));
124 EXPECT_EQ(attr_value, kU8Value1);
125 }
126
TEST(NL80211PacketTest,AddMultipleAttributesToNL80211Packet)127 TEST(NL80211PacketTest, AddMultipleAttributesToNL80211Packet) {
128 NL80211Packet netlink_packet(kNLMsgType,
129 kGenNLCommand,
130 kNLMsgSequenceNumber,
131 kPortId);
132 NL80211Attr<uint8_t> u8_attr(1, kU8Value1);
133 NL80211Attr<uint32_t> u32_attr(2, kU32Value1);
134 NL80211Attr<uint16_t> u16_attr(3, kU16Value1);
135 netlink_packet.AddAttribute(u8_attr);
136 netlink_packet.AddAttribute(u32_attr);
137 netlink_packet.AddAttribute(u16_attr);
138 EXPECT_TRUE(netlink_packet.IsValid());
139 EXPECT_TRUE(netlink_packet.HasAttribute(1));
140 EXPECT_TRUE(netlink_packet.HasAttribute(2));
141 EXPECT_TRUE(netlink_packet.HasAttribute(3));
142 uint8_t u8_attr_value;
143 uint32_t u32_attr_value;
144 uint16_t u16_attr_value;
145 EXPECT_TRUE(netlink_packet.GetAttributeValue(1, &u8_attr_value));
146 EXPECT_TRUE(netlink_packet.GetAttributeValue(2, &u32_attr_value));
147 EXPECT_TRUE(netlink_packet.GetAttributeValue(3, &u16_attr_value));
148 EXPECT_EQ(u8_attr_value, kU8Value1);
149 EXPECT_EQ(u32_attr_value, kU32Value1);
150 EXPECT_EQ(u16_attr_value, kU16Value1);
151 }
152
TEST(NL80211PacketTest,AddNestedAttributesToNL80211Packet)153 TEST(NL80211PacketTest, AddNestedAttributesToNL80211Packet) {
154 NL80211Packet netlink_packet(kNLMsgType,
155 kGenNLCommand,
156 kNLMsgSequenceNumber,
157 kPortId);
158 NL80211NestedAttr nested_attr(1);
159 NL80211Attr<uint16_t> u16_attr(2, kU16Value1);
160 NL80211Attr<uint32_t> u32_attr_1(3, kU32Value1);
161 NL80211Attr<uint32_t> u32_attr_2(4, kU32Value2);
162 nested_attr.AddAttribute(u16_attr);
163 nested_attr.AddAttribute(u32_attr_1);
164 netlink_packet.AddAttribute(nested_attr);
165 netlink_packet.AddAttribute(u32_attr_2);
166 EXPECT_TRUE(netlink_packet.HasAttribute(1));
167 EXPECT_TRUE(netlink_packet.HasAttribute(4));
168 // Attribute 2 and 3 are deeper nested.
169 // They should not be found from packet level.
170 EXPECT_FALSE(netlink_packet.HasAttribute(2));
171 EXPECT_FALSE(netlink_packet.HasAttribute(3));
172 }
173
TEST(NL80211PacketTest,CanbotGetMissingAttributeFromNL80211Packet)174 TEST(NL80211PacketTest, CanbotGetMissingAttributeFromNL80211Packet) {
175 NL80211Packet netlink_packet(kNLMsgType,
176 kGenNLCommand,
177 kNLMsgSequenceNumber,
178 kPortId);
179 NL80211Attr<uint8_t> u8_attr(1, kU8Value1);
180 netlink_packet.AddAttribute(u8_attr);
181 EXPECT_TRUE(netlink_packet.IsValid());
182 EXPECT_FALSE(netlink_packet.HasAttribute(2));
183 uint8_t attr_value;
184 EXPECT_FALSE(netlink_packet.GetAttributeValue(2, &attr_value));
185 }
186
TEST(NL80211PacketTest,ParseCMDAssociateTest)187 TEST(NL80211PacketTest, ParseCMDAssociateTest) {
188 NL80211Packet netlink_packet(std::vector<uint8_t>(
189 kNL80211_CMD_ASSOCIATE,
190 kNL80211_CMD_ASSOCIATE + sizeof(kNL80211_CMD_ASSOCIATE)));
191 EXPECT_TRUE(netlink_packet.IsValid());
192 EXPECT_EQ(kNL80211FamilyId, netlink_packet.GetMessageType());
193 EXPECT_EQ(NL80211_CMD_ASSOCIATE, netlink_packet.GetCommand());
194 uint32_t value;
195 EXPECT_TRUE(netlink_packet.GetAttributeValue(NL80211_ATTR_WIPHY, &value));
196 EXPECT_EQ(kWiPhy, value);
197 EXPECT_TRUE(netlink_packet.GetAttributeValue(NL80211_ATTR_IFINDEX, &value));
198 EXPECT_EQ(kExpectedIfIndex, value);
199 std::vector<uint8_t> rawdata;
200 EXPECT_TRUE(netlink_packet.GetAttributeValue(NL80211_ATTR_FRAME, &rawdata));
201 EXPECT_FALSE(rawdata.empty());
202
203 }
204
TEST(NL80211PacketTest,ParseCMDNotifyCQMTest)205 TEST(NL80211PacketTest, ParseCMDNotifyCQMTest) {
206 NL80211Packet netlink_packet(std::vector<uint8_t>(
207 kNL80211_CMD_NOTIFY_CQM,
208 kNL80211_CMD_NOTIFY_CQM + sizeof(kNL80211_CMD_NOTIFY_CQM)));
209 EXPECT_TRUE(netlink_packet.IsValid());
210 EXPECT_EQ(kNL80211FamilyId, netlink_packet.GetMessageType());
211 EXPECT_EQ(NL80211_CMD_NOTIFY_CQM, netlink_packet.GetCommand());
212 uint32_t value;
213 EXPECT_TRUE(netlink_packet.GetAttributeValue(NL80211_ATTR_WIPHY, &value));
214 EXPECT_EQ(kWiPhy, value);
215 EXPECT_TRUE(netlink_packet.GetAttributeValue(NL80211_ATTR_IFINDEX, &value));
216 EXPECT_EQ(kExpectedIfIndex, value);
217 std::vector<uint8_t> mac;
218 EXPECT_TRUE(netlink_packet.GetAttributeValue(NL80211_ATTR_MAC, &mac));
219 std::vector<uint8_t> expected_mac(
220 kMacAddressBytes,
221 kMacAddressBytes + sizeof(kMacAddressBytes));
222 EXPECT_EQ(expected_mac, mac);
223 NL80211NestedAttr nested(0);
224 EXPECT_TRUE(netlink_packet.GetAttribute(NL80211_ATTR_CQM, &nested));
225 EXPECT_TRUE(nested.GetAttributeValue(NL80211_ATTR_CQM_PKT_LOSS_EVENT, &value));
226 EXPECT_EQ(kExpectedCqmNotAcked, value);
227 }
228
TEST(NL80211PacketTest,ParseCMDNewStation)229 TEST(NL80211PacketTest, ParseCMDNewStation) {
230 NL80211Packet netlink_packet(std::vector<uint8_t>(
231 kNL80211_CMD_NEW_STATION,
232 kNL80211_CMD_NEW_STATION + sizeof(kNL80211_CMD_NEW_STATION)));
233 EXPECT_TRUE(netlink_packet.IsValid());
234 EXPECT_EQ(kNL80211FamilyId, netlink_packet.GetMessageType());
235 EXPECT_EQ(NL80211_CMD_NEW_STATION, netlink_packet.GetCommand());
236 uint32_t value;
237 EXPECT_TRUE(netlink_packet.GetAttributeValue(NL80211_ATTR_IFINDEX, &value));
238 EXPECT_EQ(kExpectedIfIndex, value);
239 std::vector<uint8_t> mac;
240 EXPECT_TRUE(netlink_packet.GetAttributeValue(NL80211_ATTR_MAC, &mac));
241 std::vector<uint8_t> expected_mac(
242 kMacAddressBytes,
243 kMacAddressBytes + sizeof(kMacAddressBytes));
244 EXPECT_EQ(expected_mac, mac);
245 NL80211NestedAttr nested(0);
246 EXPECT_TRUE(netlink_packet.GetAttribute(NL80211_ATTR_STA_INFO, &nested));
247 EXPECT_TRUE(netlink_packet.GetAttributeValue(NL80211_ATTR_GENERATION,
248 &value));
249 EXPECT_EQ(kNewStationExpectedGeneration, value);
250 }
251
252 } // namespace wificond
253 } // namespace android
254