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