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 "dhcp_client/dhcp_message.h"
18
19 #include <netinet/in.h>
20
21 #include <cstring>
22
23 #include <gtest/gtest.h>
24 #include <shill/net/byte_string.h>
25
26 #include "dhcp_client/dhcp_options.h"
27
28 #define SERVER_NAME 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
29 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
30 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
31 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
32 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
33 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
34 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
35 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
36
37 #define BOOT_FILE 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
38 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
39 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
40 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
41 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
42 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
43 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
44 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
45 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
46 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
47 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
48 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
49 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
50 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
51 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
52 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
53 #define COOKIE 0x63, 0x82, 0x53, 0x63
54 // The fake client hardware address(the first 6 bytes) contains a zero.
55 #define CLIENT_HARDWARE_ADDRESS 0xbf, 0x78, 0xa2, 0x00, \
56 0x0c, 0xea, 0x00, 0x00, \
57 0x00, 0x00, 0x00, 0x00, \
58 0x00, 0x00, 0x00, 0x00
59
60 #define TRANSACTION_ID 0x0f, 0x22, 0xa3, 0x50
61 #define CLIENT_IP_ADDRESS 0x00, 0x00, 0x00, 0x00
62 #define YOUR_IP_ADDRESS 0xaf, 0x23, 0x11, 0x34
63 #define NEXT_SERVER_IP_ADDRESS 0x00, 0x00, 0x00, 0x00
64 #define AGENT_IP_ADDRESS 0x00, 0x00, 0x00, 0x00
65 #define SECONDS 0x00, 0x00
66 #define FLAGS 0x00, 0x00
67 #define HOPS 0x00
68 #define HARDWARE_ADDRESS_LENGTH 0x06
69 #define HARDWARE_ADDRESS_TYPE 0x01
70 #define REQUEST 0x01
71 #define REPLY 0x02
72 #define END_TAG 0xff
73 #define SERVER_ID 0x01, 0xa2, 0x01, 0x1b
74 #define LEASE_TIME 0x00, 0x00, 0x11, 0x11
75
76 namespace dhcp_client {
77 namespace {
78 const uint8_t kFakeBufferEvenLength[] = {0x08, 0x00, 0x00, 0x00,
79 0x71, 0x50, 0x00, 0x00};
80 const size_t kFakeBufferEvenLengthSize = 8;
81 const uint16_t kFakeBufferEvenLengthChecksum = 0x86af;
82
83 const uint8_t kFakeBufferOddLength[] = {0x08, 0x00, 0x00, 0x00, 0xac, 0x51,
84 0x00, 0x00, 0x00, 0x00, 0x01};
85 const size_t kFakeBufferOddLengthSize = 11;
86 const uint16_t kFakeBufferOddLengthChecksum = 0x4aae;
87
88 const uint8_t kFakeDHCPOfferMessage[] = {
89 REPLY, // op, offer is a reply message
90 HARDWARE_ADDRESS_TYPE, // htype
91 HARDWARE_ADDRESS_LENGTH, // hlen
92 HOPS, // hops
93 TRANSACTION_ID, // xid
94 SECONDS, // secs
95 FLAGS, // flags
96 CLIENT_IP_ADDRESS, // ciaddr
97 YOUR_IP_ADDRESS, // yiaddr
98 NEXT_SERVER_IP_ADDRESS, // siaddr
99 AGENT_IP_ADDRESS, // giaddr
100 CLIENT_HARDWARE_ADDRESS, // chaddr
101 SERVER_NAME, // sname
102 BOOT_FILE, // file
103 COOKIE, // cookie
104 kDHCPOptionMessageType, 0x01, kDHCPMessageTypeOffer, // message type option
105 kDHCPOptionLeaseTime, 0x04, LEASE_TIME, // lease time option
106 kDHCPOptionServerIdentifier, 0x04, SERVER_ID, // server identifier option
107 END_TAG // options end tag
108 };
109
110 const uint8_t kFakeDHCPAckMessage[] = {
111 REPLY, // op, ack is a reply message
112 HARDWARE_ADDRESS_TYPE, // htype
113 HARDWARE_ADDRESS_LENGTH, // hlen
114 HOPS, // hops
115 TRANSACTION_ID, // xid
116 SECONDS, // secs
117 FLAGS, // flags
118 CLIENT_IP_ADDRESS, // ciaddr
119 YOUR_IP_ADDRESS, // yiaddr
120 NEXT_SERVER_IP_ADDRESS, // siaddr
121 AGENT_IP_ADDRESS, // giaddr
122 CLIENT_HARDWARE_ADDRESS, // chaddr
123 SERVER_NAME, // sname
124 BOOT_FILE, // file
125 COOKIE, // cookie
126 kDHCPOptionMessageType, 0x01, kDHCPMessageTypeAck, // message type option
127 kDHCPOptionLeaseTime, 0x04, LEASE_TIME, // lease time option
128 kDHCPOptionServerIdentifier, 0x04, SERVER_ID, // server identifier option
129 END_TAG // options end tag
130 };
131
132 const uint8_t kFakeDHCPNakMessage[] = {
133 REPLY, // op, nak is a reply message
134 HARDWARE_ADDRESS_TYPE, // htype
135 HARDWARE_ADDRESS_LENGTH, // hlen
136 HOPS, // hops
137 TRANSACTION_ID, // xid
138 SECONDS, // secs
139 FLAGS, // flags
140 CLIENT_IP_ADDRESS, // ciaddr
141 YOUR_IP_ADDRESS, // yiaddr
142 NEXT_SERVER_IP_ADDRESS, // siaddr
143 AGENT_IP_ADDRESS, // giaddr
144 CLIENT_HARDWARE_ADDRESS, // chaddr
145 SERVER_NAME, // sname
146 BOOT_FILE, // file
147 COOKIE, // cookie
148 kDHCPOptionMessageType, 0x01, kDHCPMessageTypeNak, // message type option
149 kDHCPOptionServerIdentifier, 0x04, SERVER_ID, // server identifier option
150 END_TAG // options end tag
151 };
152 const uint8_t kFakeTransactionID[] = {TRANSACTION_ID};
153 const uint8_t kFakeServerIdentifier[] = {SERVER_ID};
154 const uint8_t kFakeLeaseTime[] = {LEASE_TIME};
155 const uint8_t kFakeYourIPAddress[] = {YOUR_IP_ADDRESS};
156 const uint8_t kFakeHardwareAddress[] = {CLIENT_HARDWARE_ADDRESS};
157 size_t kFakeDHCPOfferMessageLength = sizeof(kFakeDHCPOfferMessage);
158 size_t kFakeDHCPAckMessageLength = sizeof(kFakeDHCPAckMessage);
159 size_t kFakeDHCPNakMessageLength = sizeof(kFakeDHCPNakMessage);
160 } // namespace
161
162 class DHCPMessageTest : public testing::Test {
163 public:
DHCPMessageTest()164 DHCPMessageTest() {}
165 protected:
166 };
167
TEST_F(DHCPMessageTest,ComputeChecksumEvenLengthTest)168 TEST_F(DHCPMessageTest, ComputeChecksumEvenLengthTest) {
169 uint16_t checksum = DHCPMessage::ComputeChecksum(kFakeBufferEvenLength,
170 kFakeBufferEvenLengthSize);
171 EXPECT_EQ(kFakeBufferEvenLengthChecksum, checksum);
172 }
173
TEST_F(DHCPMessageTest,ComputeChecksumOddLengthTest)174 TEST_F(DHCPMessageTest, ComputeChecksumOddLengthTest) {
175 uint16_t checksum = DHCPMessage::ComputeChecksum(kFakeBufferOddLength,
176 kFakeBufferOddLengthSize);
177 EXPECT_EQ(kFakeBufferOddLengthChecksum, checksum);
178 }
179
TEST_F(DHCPMessageTest,InitFromBufferMessageTypeOffer)180 TEST_F(DHCPMessageTest, InitFromBufferMessageTypeOffer) {
181 DHCPMessage msg;
182 EXPECT_TRUE(DHCPMessage::InitFromBuffer(kFakeDHCPOfferMessage,
183 kFakeDHCPOfferMessageLength,
184 &msg));
185 EXPECT_EQ(kDHCPMessageTypeOffer, msg.message_type());
186 EXPECT_EQ(ntohl(*reinterpret_cast<const uint32_t*>(kFakeTransactionID)),
187 msg.transaction_id());
188 EXPECT_EQ(ntohl(*reinterpret_cast<const uint32_t*>(kFakeServerIdentifier)),
189 msg.server_identifier());
190 EXPECT_EQ(ntohl(*reinterpret_cast<const uint32_t*>(kFakeLeaseTime)),
191 msg.lease_time());
192 EXPECT_EQ(ntohl(*reinterpret_cast<const uint32_t*>(kFakeYourIPAddress)),
193 msg.your_ip_address());
194 EXPECT_EQ(0, std::memcmp(kFakeHardwareAddress,
195 msg.client_hardware_address().GetConstData(),
196 msg.client_hardware_address().GetLength()));
197 }
198
TEST_F(DHCPMessageTest,InitFromBufferMessageTypeAck)199 TEST_F(DHCPMessageTest, InitFromBufferMessageTypeAck) {
200 DHCPMessage msg;
201 EXPECT_TRUE(DHCPMessage::InitFromBuffer(kFakeDHCPAckMessage,
202 kFakeDHCPAckMessageLength,
203 &msg));
204 EXPECT_EQ(kDHCPMessageTypeAck, msg.message_type());
205 EXPECT_EQ(ntohl(*reinterpret_cast<const uint32_t*>(kFakeTransactionID)),
206 msg.transaction_id());
207 EXPECT_EQ(ntohl(*reinterpret_cast<const uint32_t*>(kFakeServerIdentifier)),
208 msg.server_identifier());
209 EXPECT_EQ(ntohl(*reinterpret_cast<const uint32_t*>(kFakeLeaseTime)),
210 msg.lease_time());
211 EXPECT_EQ(ntohl(*reinterpret_cast<const uint32_t*>(kFakeYourIPAddress)),
212 msg.your_ip_address());
213 EXPECT_EQ(0, std::memcmp(kFakeHardwareAddress,
214 msg.client_hardware_address().GetConstData(),
215 msg.client_hardware_address().GetLength()));
216 }
217
TEST_F(DHCPMessageTest,InitFromBufferMessageTypeNak)218 TEST_F(DHCPMessageTest, InitFromBufferMessageTypeNak) {
219 DHCPMessage msg;
220 EXPECT_TRUE(DHCPMessage::InitFromBuffer(kFakeDHCPNakMessage,
221 kFakeDHCPNakMessageLength,
222 &msg));
223 EXPECT_EQ(kDHCPMessageTypeNak, msg.message_type());
224 EXPECT_EQ(ntohl(*reinterpret_cast<const uint32_t*>(kFakeTransactionID)),
225 msg.transaction_id());
226 EXPECT_EQ(ntohl(*reinterpret_cast<const uint32_t*>(kFakeServerIdentifier)),
227 msg.server_identifier());
228 EXPECT_EQ(0, std::memcmp(kFakeHardwareAddress,
229 msg.client_hardware_address().GetConstData(),
230 msg.client_hardware_address().GetLength()));
231 }
232
233 } // namespace dhcp_client
234