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