blob: 2bf2c00e2ac252bfbcf5ffb96e17b8e48f7fdd8b [file] [log] [blame]
//
// 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 "dhcp_client/dhcp_message.h"
#include <netinet/in.h>
#include <cstring>
#include <gtest/gtest.h>
#include <shill/net/byte_string.h>
#include "dhcp_client/dhcp_options.h"
#define SERVER_NAME 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
#define BOOT_FILE 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
#define COOKIE 0x63, 0x82, 0x53, 0x63
// The fake client hardware address(the first 6 bytes) contains a zero.
#define CLIENT_HARDWARE_ADDRESS 0xbf, 0x78, 0xa2, 0x00, \
0x0c, 0xea, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00
#define TRANSACTION_ID 0x0f, 0x22, 0xa3, 0x50
#define SECONDS 0x00, 0x00
#define FLAGS 0x00, 0x00
#define HOPS 0x00
#define HARDWARE_ADDRESS_LENGTH 0x06
#define HARDWARE_ADDRESS_TYPE 0x01
#define REQUEST 0x01
#define REPLY 0x02
#define END_TAG 0xff
#define SERVER_ID 0x01, 0xa2, 0x01, 0x1b
#define LEASE_TIME 0x00, 0x00, 0x11, 0x11
#define ZERO_IP_ADDRESS 0x00, 0x00, 0x00, 0x00
#define FAKE_IP_ADDRESS1 0xae, 0x23, 0x15, 0x03
#define FAKE_IP_ADDRESS2 0x9f, 0x01, 0xfb0, 0x00
using shill::ByteString;
namespace dhcp_client {
namespace {
const uint8_t kFakeBufferEvenLength[] = {0x08, 0x00, 0x00, 0x00,
0x71, 0x50, 0x00, 0x00};
const size_t kFakeBufferEvenLengthSize = 8;
const uint16_t kFakeBufferEvenLengthChecksum = 0x86af;
const uint8_t kFakeBufferOddLength[] = {0x08, 0x00, 0x00, 0x00, 0xac, 0x51,
0x00, 0x00, 0x00, 0x00, 0x01};
const size_t kFakeBufferOddLengthSize = 11;
const uint16_t kFakeBufferOddLengthChecksum = 0x4aae;
const uint8_t kFakeDHCPOfferMessage[] = {
REPLY, // op, offer is a reply message
HARDWARE_ADDRESS_TYPE, // htype
HARDWARE_ADDRESS_LENGTH, // hlen
HOPS, // hops
TRANSACTION_ID, // xid
SECONDS, // secs
FLAGS, // flags
ZERO_IP_ADDRESS, // ciaddr
FAKE_IP_ADDRESS1, // yiaddr
ZERO_IP_ADDRESS, // siaddr
ZERO_IP_ADDRESS, // giaddr
CLIENT_HARDWARE_ADDRESS, // chaddr
SERVER_NAME, // sname
BOOT_FILE, // file
COOKIE, // cookie
kDHCPOptionLeaseTime, 0x04, LEASE_TIME, // lease time option
kDHCPOptionMessageType, 0x01, kDHCPMessageTypeOffer, // message type option
kDHCPOptionServerIdentifier, 0x04, SERVER_ID, // server identifier option
END_TAG // options end tag
};
const uint8_t kFakeDHCPAckMessage[] = {
REPLY, // op, ack is a reply message
HARDWARE_ADDRESS_TYPE, // htype
HARDWARE_ADDRESS_LENGTH, // hlen
HOPS, // hops
TRANSACTION_ID, // xid
SECONDS, // secs
FLAGS, // flags
ZERO_IP_ADDRESS, // ciaddr
FAKE_IP_ADDRESS1, // yiaddr
ZERO_IP_ADDRESS, // siaddr
ZERO_IP_ADDRESS, // giaddr
CLIENT_HARDWARE_ADDRESS, // chaddr
SERVER_NAME, // sname
BOOT_FILE, // file
COOKIE, // cookie
kDHCPOptionLeaseTime, 0x04, LEASE_TIME, // lease time option
kDHCPOptionMessageType, 0x01, kDHCPMessageTypeAck, // message type option
kDHCPOptionServerIdentifier, 0x04, SERVER_ID, // server identifier option
END_TAG // options end tag
};
const uint8_t kFakeDHCPNakMessage[] = {
REPLY, // op, nak is a reply message
HARDWARE_ADDRESS_TYPE, // htype
HARDWARE_ADDRESS_LENGTH, // hlen
HOPS, // hops
TRANSACTION_ID, // xid
SECONDS, // secs
FLAGS, // flags
ZERO_IP_ADDRESS, // ciaddr
ZERO_IP_ADDRESS, // yiaddr
ZERO_IP_ADDRESS, // siaddr
ZERO_IP_ADDRESS, // giaddr
CLIENT_HARDWARE_ADDRESS, // chaddr
SERVER_NAME, // sname
BOOT_FILE, // file
COOKIE, // cookie
kDHCPOptionMessageType, 0x01, kDHCPMessageTypeNak, // message type option
kDHCPOptionServerIdentifier, 0x04, SERVER_ID, // server identifier option
END_TAG // options end tag
};
const uint8_t kFakeDHCPDiscoverMessage[] = {
REQUEST, // op, nak is a reply message
HARDWARE_ADDRESS_TYPE, // htype
HARDWARE_ADDRESS_LENGTH, // hlen
HOPS, // hops
TRANSACTION_ID, // xid
SECONDS, // secs
FLAGS, // flags
ZERO_IP_ADDRESS, // ciaddr
ZERO_IP_ADDRESS, // yiaddr
ZERO_IP_ADDRESS, // siaddr
ZERO_IP_ADDRESS, // giaddr
CLIENT_HARDWARE_ADDRESS, // chaddr
SERVER_NAME, // sname
BOOT_FILE, // file
COOKIE, // cookie
// message type option
kDHCPOptionMessageType, 0x01, kDHCPMessageTypeDiscover,
kDHCPOptionServerIdentifier, 0x04, SERVER_ID, // server identifier option
END_TAG // options end tag
};
const uint8_t kFakeDHCPRequestMessage[] = {
REQUEST, // op, nak is a reply message
HARDWARE_ADDRESS_TYPE, // htype
HARDWARE_ADDRESS_LENGTH, // hlen
HOPS, // hops
TRANSACTION_ID, // xid
SECONDS, // secs
FLAGS, // flags
ZERO_IP_ADDRESS, // ciaddr
ZERO_IP_ADDRESS, // yiaddr
ZERO_IP_ADDRESS, // siaddr
ZERO_IP_ADDRESS, // giaddr
CLIENT_HARDWARE_ADDRESS, // chaddr
SERVER_NAME, // sname
BOOT_FILE, // file
COOKIE, // cookie
// message type option
kDHCPOptionMessageType, 0x01, kDHCPMessageTypeRequest,
END_TAG // options end tag
};
const uint8_t kFakeDHCPDeclineMessage[] = {
REQUEST, // op, nak is a reply message
HARDWARE_ADDRESS_TYPE, // htype
HARDWARE_ADDRESS_LENGTH, // hlen
HOPS, // hops
TRANSACTION_ID, // xid
SECONDS, // secs
FLAGS, // flags
ZERO_IP_ADDRESS, // ciaddr
ZERO_IP_ADDRESS, // yiaddr
ZERO_IP_ADDRESS, // siaddr
ZERO_IP_ADDRESS, // giaddr
CLIENT_HARDWARE_ADDRESS, // chaddr
SERVER_NAME, // sname
BOOT_FILE, // file
COOKIE, // cookie
// message type option
kDHCPOptionMessageType, 0x01, kDHCPMessageTypeDecline,
END_TAG // options end tag
};
const uint8_t kFakeDHCPReleaseMessage[] = {
REQUEST, // op, nak is a reply message
HARDWARE_ADDRESS_TYPE, // htype
HARDWARE_ADDRESS_LENGTH, // hlen
HOPS, // hops
TRANSACTION_ID, // xid
SECONDS, // secs
FLAGS, // flags
ZERO_IP_ADDRESS, // ciaddr
ZERO_IP_ADDRESS, // yiaddr
ZERO_IP_ADDRESS, // siaddr
ZERO_IP_ADDRESS, // giaddr
CLIENT_HARDWARE_ADDRESS, // chaddr
SERVER_NAME, // sname
BOOT_FILE, // file
COOKIE, // cookie
// message type option
kDHCPOptionMessageType, 0x01, kDHCPMessageTypeRelease,
END_TAG // options end tag
};
const uint8_t kFakeTransactionID[] = {TRANSACTION_ID};
const uint8_t kFakeServerIdentifier[] = {SERVER_ID};
const uint8_t kFakeLeaseTime[] = {LEASE_TIME};
const uint8_t kFakeIPAddress1[] = {FAKE_IP_ADDRESS1};
const uint8_t kZeroIPAddress[] = {ZERO_IP_ADDRESS};
const uint8_t kFakeHardwareAddress[] = {CLIENT_HARDWARE_ADDRESS};
const uint8_t kHardwareAddressLength = HARDWARE_ADDRESS_LENGTH;
size_t kFakeDHCPOfferMessageLength = sizeof(kFakeDHCPOfferMessage);
size_t kFakeDHCPAckMessageLength = sizeof(kFakeDHCPAckMessage);
size_t kFakeDHCPNakMessageLength = sizeof(kFakeDHCPNakMessage);
} // namespace
class DHCPMessageTest : public testing::Test {
public:
DHCPMessageTest() {}
protected:
};
TEST_F(DHCPMessageTest, ComputeChecksumEvenLengthTest) {
uint16_t checksum = DHCPMessage::ComputeChecksum(kFakeBufferEvenLength,
kFakeBufferEvenLengthSize);
EXPECT_EQ(kFakeBufferEvenLengthChecksum, checksum);
}
TEST_F(DHCPMessageTest, ComputeChecksumOddLengthTest) {
uint16_t checksum = DHCPMessage::ComputeChecksum(kFakeBufferOddLength,
kFakeBufferOddLengthSize);
EXPECT_EQ(kFakeBufferOddLengthChecksum, checksum);
}
TEST_F(DHCPMessageTest, InitFromBufferMessageTypeOffer) {
DHCPMessage msg;
EXPECT_TRUE(DHCPMessage::InitFromBuffer(kFakeDHCPOfferMessage,
kFakeDHCPOfferMessageLength,
&msg));
EXPECT_EQ(kDHCPMessageTypeOffer, msg.message_type());
EXPECT_EQ(ntohl(*reinterpret_cast<const uint32_t*>(kFakeTransactionID)),
msg.transaction_id());
EXPECT_EQ(ntohl(*reinterpret_cast<const uint32_t*>(kFakeServerIdentifier)),
msg.server_identifier());
EXPECT_EQ(ntohl(*reinterpret_cast<const uint32_t*>(kFakeLeaseTime)),
msg.lease_time());
EXPECT_EQ(ntohl(*reinterpret_cast<const uint32_t*>(kFakeIPAddress1)),
msg.your_ip_address());
EXPECT_EQ(0, std::memcmp(kFakeHardwareAddress,
msg.client_hardware_address().GetConstData(),
msg.client_hardware_address().GetLength()));
}
TEST_F(DHCPMessageTest, InitFromBufferMessageTypeAck) {
DHCPMessage msg;
EXPECT_TRUE(DHCPMessage::InitFromBuffer(kFakeDHCPAckMessage,
kFakeDHCPAckMessageLength,
&msg));
EXPECT_EQ(kDHCPMessageTypeAck, msg.message_type());
EXPECT_EQ(ntohl(*reinterpret_cast<const uint32_t*>(kFakeTransactionID)),
msg.transaction_id());
EXPECT_EQ(ntohl(*reinterpret_cast<const uint32_t*>(kFakeServerIdentifier)),
msg.server_identifier());
EXPECT_EQ(ntohl(*reinterpret_cast<const uint32_t*>(kFakeLeaseTime)),
msg.lease_time());
EXPECT_EQ(ntohl(*reinterpret_cast<const uint32_t*>(kFakeIPAddress1)),
msg.your_ip_address());
EXPECT_EQ(0, std::memcmp(kFakeHardwareAddress,
msg.client_hardware_address().GetConstData(),
msg.client_hardware_address().GetLength()));
}
TEST_F(DHCPMessageTest, InitFromBufferMessageTypeNak) {
DHCPMessage msg;
EXPECT_TRUE(DHCPMessage::InitFromBuffer(kFakeDHCPNakMessage,
kFakeDHCPNakMessageLength,
&msg));
EXPECT_EQ(kDHCPMessageTypeNak, msg.message_type());
EXPECT_EQ(ntohl(*reinterpret_cast<const uint32_t*>(kFakeTransactionID)),
msg.transaction_id());
EXPECT_EQ(ntohl(*reinterpret_cast<const uint32_t*>(kFakeServerIdentifier)),
msg.server_identifier());
EXPECT_EQ(0, std::memcmp(kFakeHardwareAddress,
msg.client_hardware_address().GetConstData(),
msg.client_hardware_address().GetLength()));
}
TEST_F(DHCPMessageTest, SerialzeDHCPDiscoverMessage) {
DHCPMessage msg;
DHCPMessage::InitRequest(&msg);
msg.SetMessageType(kDHCPMessageTypeDiscover);
msg.SetClientHardwareAddress(ByteString(kFakeHardwareAddress,
kHardwareAddressLength));
msg.SetServerIdentifier(
ntohl(*reinterpret_cast<const uint32_t*>(kFakeServerIdentifier)));
msg.SetClientIPAddress(
ntohl(*reinterpret_cast<const uint32_t*>(kZeroIPAddress)));
msg.SetTransactionID(
ntohl(*reinterpret_cast<const uint32_t*>(kFakeTransactionID)));
ByteString buffer;
EXPECT_TRUE(msg.Serialize(&buffer));
EXPECT_EQ(0, std::memcmp(kFakeDHCPDiscoverMessage,
buffer.GetConstData(),
buffer.GetLength()));
}
TEST_F(DHCPMessageTest, SerialzeDHCPRequestMessage) {
DHCPMessage msg;
DHCPMessage::InitRequest(&msg);
msg.SetMessageType(kDHCPMessageTypeRequest);
msg.SetClientHardwareAddress(ByteString(kFakeHardwareAddress,
kHardwareAddressLength));
msg.SetClientIPAddress(
ntohl(*reinterpret_cast<const uint32_t*>(kZeroIPAddress)));
msg.SetTransactionID(
ntohl(*reinterpret_cast<const uint32_t*>(kFakeTransactionID)));
ByteString buffer;
EXPECT_TRUE(msg.Serialize(&buffer));
EXPECT_EQ(0, std::memcmp(kFakeDHCPRequestMessage,
buffer.GetConstData(),
buffer.GetLength()));
}
TEST_F(DHCPMessageTest, SerialzeDHCPDeclineMessage) {
DHCPMessage msg;
DHCPMessage::InitRequest(&msg);
msg.SetMessageType(kDHCPMessageTypeDecline);
msg.SetClientHardwareAddress(ByteString(kFakeHardwareAddress,
kHardwareAddressLength));
msg.SetClientIPAddress(
ntohl(*reinterpret_cast<const uint32_t*>(kZeroIPAddress)));
msg.SetTransactionID(
ntohl(*reinterpret_cast<const uint32_t*>(kFakeTransactionID)));
ByteString buffer;
EXPECT_TRUE(msg.Serialize(&buffer));
EXPECT_EQ(0, std::memcmp(kFakeDHCPDeclineMessage,
buffer.GetConstData(),
buffer.GetLength()));
}
TEST_F(DHCPMessageTest, SerialzeDHCPReleaseMessage) {
DHCPMessage msg;
DHCPMessage::InitRequest(&msg);
msg.SetMessageType(kDHCPMessageTypeRelease);
msg.SetClientHardwareAddress(ByteString(kFakeHardwareAddress,
kHardwareAddressLength));
msg.SetClientIPAddress(
ntohl(*reinterpret_cast<const uint32_t*>(kZeroIPAddress)));
msg.SetTransactionID(
ntohl(*reinterpret_cast<const uint32_t*>(kFakeTransactionID)));
ByteString buffer;
EXPECT_TRUE(msg.Serialize(&buffer));
EXPECT_EQ(0, std::memcmp(kFakeDHCPReleaseMessage,
buffer.GetConstData(),
buffer.GetLength()));
}
} // namespace dhcp_client