1 //
2 // Copyright (C) 2015 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 "shill/net/netlink_packet.h"
18
19 #include <linux/netlink.h>
20
21 #include <gmock/gmock.h>
22 #include <gtest/gtest.h>
23
24 using testing::Test;
25
26 namespace shill {
27
28 class NetlinkPacketTest : public Test {
29 };
30
TEST_F(NetlinkPacketTest,Constructor)31 TEST_F(NetlinkPacketTest, Constructor) {
32 // A null pointer should not crash the constructor, but should yield
33 // an invalid packet.
34 NetlinkPacket null_packet(nullptr, 100);
35 EXPECT_FALSE(null_packet.IsValid());
36
37 unsigned char data[sizeof(nlmsghdr) + 1];
38 memset(&data, 0, sizeof(data));
39
40 // A packet that is too short to contain an nlmsghdr should be invalid.
41 NetlinkPacket short_packet(data, sizeof(nlmsghdr) - 1);
42 EXPECT_FALSE(short_packet.IsValid());
43
44 // A packet that contains an invalid nlmsg_len (should be at least
45 // as large as sizeof(nlmgsghdr)) should be invalid.
46 NetlinkPacket invalid_packet(data, sizeof(nlmsghdr));
47 EXPECT_FALSE(invalid_packet.IsValid());
48
49 // Successfully parse a well-formed packet that has no payload.
50 nlmsghdr hdr;
51 memset(&hdr, 0, sizeof(hdr));
52 hdr.nlmsg_len = sizeof(hdr);
53 hdr.nlmsg_type = 1;
54 memcpy(&data, &hdr, sizeof(hdr));
55 NetlinkPacket empty_packet(data, sizeof(nlmsghdr));
56 EXPECT_TRUE(empty_packet.IsValid());
57 EXPECT_EQ(sizeof(nlmsghdr), empty_packet.GetLength());
58 EXPECT_EQ(1, empty_packet.GetMessageType());
59 char payload_byte = 0;
60 EXPECT_FALSE(empty_packet.ConsumeData(1, &payload_byte));
61
62 // A packet that contains an nlmsg_len that is larger than the
63 // data provided should be invalid.
64 hdr.nlmsg_len = sizeof(hdr) + 1;
65 hdr.nlmsg_type = 2;
66 memcpy(&data, &hdr, sizeof(hdr));
67 NetlinkPacket incomplete_packet(data, sizeof(nlmsghdr));
68 EXPECT_FALSE(incomplete_packet.IsValid());
69
70 // Retrieve a byte from a well-formed packet. After that byte is
71 // retrieved, no more data can be consumed.
72 data[sizeof(nlmsghdr)] = 10;
73 NetlinkPacket complete_packet(data, sizeof(nlmsghdr) + 1);
74 EXPECT_TRUE(complete_packet.IsValid());
75 EXPECT_EQ(sizeof(nlmsghdr) + 1, complete_packet.GetLength());
76 EXPECT_EQ(2, complete_packet.GetMessageType());
77 EXPECT_EQ(1, complete_packet.GetRemainingLength());
78 EXPECT_TRUE(complete_packet.ConsumeData(1, &payload_byte));
79 EXPECT_EQ(10, payload_byte);
80 EXPECT_FALSE(complete_packet.ConsumeData(1, &payload_byte));
81 }
82
TEST_F(NetlinkPacketTest,ConsumeData)83 TEST_F(NetlinkPacketTest, ConsumeData) {
84 // This code assumes that the value of NLMSG_ALIGNTO is 4, and that nlmsghdr
85 // is aligned to a 4-byte boundary.
86 static_assert(NLMSG_ALIGNTO == 4, "NLMSG_ALIGNTO sized has changed");
87 static_assert((sizeof(nlmsghdr) % NLMSG_ALIGNTO) == 0,
88 "nlmsghdr is not aligned with NLMSG_ALIGNTO");
89
90 const char kString1[] = "A";
91 const char kString2[] = "pattern";
92 const char kString3[] = "so";
93 const char kString4[] = "grand";
94
95 // Assert string sizes (with null terminator).
96 ASSERT_EQ(2, sizeof(kString1));
97 ASSERT_EQ(8, sizeof(kString2));
98 ASSERT_EQ(3, sizeof(kString3));
99 ASSERT_EQ(6, sizeof(kString4));
100
101 unsigned char data[sizeof(nlmsghdr) + 22];
102 memset(data, 0, sizeof(data));
103 nlmsghdr hdr;
104 memset(&hdr, 0, sizeof(hdr));
105 hdr.nlmsg_len = sizeof(data);
106 memcpy(data, &hdr, sizeof(hdr));
107 memcpy(data + sizeof(nlmsghdr), kString1, sizeof(kString1));
108 memcpy(data + sizeof(nlmsghdr) + 4, kString2, sizeof(kString2));
109 memcpy(data + sizeof(nlmsghdr) + 12, kString3, sizeof(kString3));
110 memcpy(data + sizeof(nlmsghdr) + 16, kString4, sizeof(kString4));
111
112 NetlinkPacket packet(data, sizeof(data));
113 EXPECT_EQ(22, packet.GetRemainingLength());
114
115 // Consuming 2 bytes of data also consumed 2 bytes of padding.
116 char string_piece[8];
117 EXPECT_TRUE(packet.ConsumeData(2, &string_piece));
118 EXPECT_STREQ(kString1, string_piece);
119 EXPECT_EQ(18, packet.GetRemainingLength());
120
121 // An aligned read (8 bytes) should read no more than this number.
122 EXPECT_TRUE(packet.ConsumeData(8, &string_piece));
123 EXPECT_STREQ(kString2, string_piece);
124 EXPECT_EQ(10, packet.GetRemainingLength());
125
126 // Try an odd-numbered unaligned read.
127 EXPECT_TRUE(packet.ConsumeData(3, &string_piece));
128 EXPECT_STREQ(kString3, string_piece);
129 EXPECT_EQ(6, packet.GetRemainingLength());
130
131 // Reading more than is left should fail, and should not consume anything.
132 EXPECT_FALSE(packet.ConsumeData(7, &string_piece));
133 EXPECT_EQ(6, packet.GetRemainingLength());
134
135 // Reading a correctly-sized unalinged value which consumes the rest of
136 // the buffer should succeed.
137 EXPECT_TRUE(packet.ConsumeData(6, &string_piece));
138 EXPECT_STREQ(kString4, string_piece);
139 EXPECT_EQ(0, packet.GetRemainingLength());
140 }
141
142 } // namespace shill
143