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