142 lines
5 KiB
C++
142 lines
5 KiB
C++
//
|
|
// Copyright (C) 2015 The Android Open Source Project
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
|
|
#include "shill/net/netlink_packet.h"
|
|
|
|
#include <linux/netlink.h>
|
|
|
|
#include <gmock/gmock.h>
|
|
#include <gtest/gtest.h>
|
|
|
|
using testing::Test;
|
|
|
|
namespace shill {
|
|
|
|
class NetlinkPacketTest : public Test {
|
|
};
|
|
|
|
TEST_F(NetlinkPacketTest, Constructor) {
|
|
// A null pointer should not crash the constructor, but should yield
|
|
// an invalid packet.
|
|
NetlinkPacket null_packet(nullptr, 100);
|
|
EXPECT_FALSE(null_packet.IsValid());
|
|
|
|
unsigned char data[sizeof(nlmsghdr) + 1];
|
|
memset(&data, 0, sizeof(data));
|
|
|
|
// A packet that is too short to contain an nlmsghdr should be invalid.
|
|
NetlinkPacket short_packet(data, sizeof(nlmsghdr) - 1);
|
|
EXPECT_FALSE(short_packet.IsValid());
|
|
|
|
// A packet that contains an invalid nlmsg_len (should be at least
|
|
// as large as sizeof(nlmgsghdr)) should be invalid.
|
|
NetlinkPacket invalid_packet(data, sizeof(nlmsghdr));
|
|
EXPECT_FALSE(invalid_packet.IsValid());
|
|
|
|
// Successfully parse a well-formed packet that has no payload.
|
|
nlmsghdr hdr;
|
|
memset(&hdr, 0, sizeof(hdr));
|
|
hdr.nlmsg_len = sizeof(hdr);
|
|
hdr.nlmsg_type = 1;
|
|
memcpy(&data, &hdr, sizeof(hdr));
|
|
NetlinkPacket empty_packet(data, sizeof(nlmsghdr));
|
|
EXPECT_TRUE(empty_packet.IsValid());
|
|
EXPECT_EQ(sizeof(nlmsghdr), empty_packet.GetLength());
|
|
EXPECT_EQ(1, empty_packet.GetMessageType());
|
|
char payload_byte = 0;
|
|
EXPECT_FALSE(empty_packet.ConsumeData(1, &payload_byte));
|
|
|
|
// A packet that contains an nlmsg_len that is larger than the
|
|
// data provided should be invalid.
|
|
hdr.nlmsg_len = sizeof(hdr) + 1;
|
|
hdr.nlmsg_type = 2;
|
|
memcpy(&data, &hdr, sizeof(hdr));
|
|
NetlinkPacket incomplete_packet(data, sizeof(nlmsghdr));
|
|
EXPECT_FALSE(incomplete_packet.IsValid());
|
|
|
|
// Retrieve a byte from a well-formed packet. After that byte is
|
|
// retrieved, no more data can be consumed.
|
|
data[sizeof(nlmsghdr)] = 10;
|
|
NetlinkPacket complete_packet(data, sizeof(nlmsghdr) + 1);
|
|
EXPECT_TRUE(complete_packet.IsValid());
|
|
EXPECT_EQ(sizeof(nlmsghdr) + 1, complete_packet.GetLength());
|
|
EXPECT_EQ(2, complete_packet.GetMessageType());
|
|
EXPECT_EQ(1, complete_packet.GetRemainingLength());
|
|
EXPECT_TRUE(complete_packet.ConsumeData(1, &payload_byte));
|
|
EXPECT_EQ(10, payload_byte);
|
|
EXPECT_FALSE(complete_packet.ConsumeData(1, &payload_byte));
|
|
}
|
|
|
|
TEST_F(NetlinkPacketTest, ConsumeData) {
|
|
// This code assumes that the value of NLMSG_ALIGNTO is 4, and that nlmsghdr
|
|
// is aligned to a 4-byte boundary.
|
|
static_assert(NLMSG_ALIGNTO == 4, "NLMSG_ALIGNTO sized has changed");
|
|
static_assert((sizeof(nlmsghdr) % NLMSG_ALIGNTO) == 0,
|
|
"nlmsghdr is not aligned with NLMSG_ALIGNTO");
|
|
|
|
const char kString1[] = "A";
|
|
const char kString2[] = "pattern";
|
|
const char kString3[] = "so";
|
|
const char kString4[] = "grand";
|
|
|
|
// Assert string sizes (with null terminator).
|
|
ASSERT_EQ(2, sizeof(kString1));
|
|
ASSERT_EQ(8, sizeof(kString2));
|
|
ASSERT_EQ(3, sizeof(kString3));
|
|
ASSERT_EQ(6, sizeof(kString4));
|
|
|
|
unsigned char data[sizeof(nlmsghdr) + 22];
|
|
memset(data, 0, sizeof(data));
|
|
nlmsghdr hdr;
|
|
memset(&hdr, 0, sizeof(hdr));
|
|
hdr.nlmsg_len = sizeof(data);
|
|
memcpy(data, &hdr, sizeof(hdr));
|
|
memcpy(data + sizeof(nlmsghdr), kString1, sizeof(kString1));
|
|
memcpy(data + sizeof(nlmsghdr) + 4, kString2, sizeof(kString2));
|
|
memcpy(data + sizeof(nlmsghdr) + 12, kString3, sizeof(kString3));
|
|
memcpy(data + sizeof(nlmsghdr) + 16, kString4, sizeof(kString4));
|
|
|
|
NetlinkPacket packet(data, sizeof(data));
|
|
EXPECT_EQ(22, packet.GetRemainingLength());
|
|
|
|
// Consuming 2 bytes of data also consumed 2 bytes of padding.
|
|
char string_piece[8];
|
|
EXPECT_TRUE(packet.ConsumeData(2, &string_piece));
|
|
EXPECT_STREQ(kString1, string_piece);
|
|
EXPECT_EQ(18, packet.GetRemainingLength());
|
|
|
|
// An aligned read (8 bytes) should read no more than this number.
|
|
EXPECT_TRUE(packet.ConsumeData(8, &string_piece));
|
|
EXPECT_STREQ(kString2, string_piece);
|
|
EXPECT_EQ(10, packet.GetRemainingLength());
|
|
|
|
// Try an odd-numbered unaligned read.
|
|
EXPECT_TRUE(packet.ConsumeData(3, &string_piece));
|
|
EXPECT_STREQ(kString3, string_piece);
|
|
EXPECT_EQ(6, packet.GetRemainingLength());
|
|
|
|
// Reading more than is left should fail, and should not consume anything.
|
|
EXPECT_FALSE(packet.ConsumeData(7, &string_piece));
|
|
EXPECT_EQ(6, packet.GetRemainingLength());
|
|
|
|
// Reading a correctly-sized unalinged value which consumes the rest of
|
|
// the buffer should succeed.
|
|
EXPECT_TRUE(packet.ConsumeData(6, &string_piece));
|
|
EXPECT_STREQ(kString4, string_piece);
|
|
EXPECT_EQ(0, packet.GetRemainingLength());
|
|
}
|
|
|
|
} // namespace shill
|