• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2012 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/arp_client.h"
18 
19 #include <linux/if_packet.h>
20 #include <net/ethernet.h>
21 #include <net/if_arp.h>
22 #include <netinet/in.h>
23 
24 #include <gtest/gtest.h>
25 
26 #include "shill/arp_packet.h"
27 #include "shill/mock_log.h"
28 #include "shill/net/ip_address.h"
29 #include "shill/net/mock_sockets.h"
30 
31 using testing::_;
32 using testing::AnyNumber;
33 using testing::HasSubstr;
34 using testing::InSequence;
35 using testing::Invoke;
36 using testing::Mock;
37 using testing::Return;
38 using testing::StrictMock;
39 using testing::Test;
40 
41 namespace shill {
42 
43 class ArpClientTest : public Test {
44  public:
ArpClientTest()45   ArpClientTest() : client_(kInterfaceIndex) {}
~ArpClientTest()46   virtual ~ArpClientTest() {}
47 
SetUp()48   virtual void SetUp() {
49     sockets_ = new StrictMock<MockSockets>();
50     // Passes ownership.
51     client_.sockets_.reset(sockets_);
52     memset(&recvfrom_sender_, 0, sizeof(recvfrom_sender_));
53   }
54 
TearDown()55   virtual void TearDown() {
56     if (GetSocket() == kSocketFD) {
57       EXPECT_CALL(*sockets_, Close(kSocketFD));
58       client_.Stop();
59     }
60   }
61 
62   ssize_t SimulateRecvFrom(int sockfd, void* buf, size_t len, int flags,
63                            struct sockaddr* src_addr, socklen_t* addrlen);
64 
65  protected:
66   static const int kInterfaceIndex;
67   static const int kSocketFD;
68   static const char kLocalIPAddress[];
69   static const uint8_t kLocalMACAddress[];
70   static const char kRemoteIPAddress[];
71   static const uint8_t kRemoteMACAddress[];
72   static const int kArpOpOffset;
73 
CreateSocket()74   bool CreateSocket() { return client_.CreateSocket(ARPOP_REPLY); }
GetInterfaceIndex()75   int GetInterfaceIndex() { return client_.interface_index_; }
GetMaxArpPacketLength()76   size_t GetMaxArpPacketLength() { return ArpClient::kMaxArpPacketLength; }
GetSocket()77   int GetSocket() { return client_.socket_; }
78   void SetupValidPacket(ArpPacket* packet);
StartClient()79   void StartClient() { StartClientWithFD(kSocketFD); }
80   void StartClientWithFD(int fd);
81 
82   // Owned by ArpClient, and tracked here only for mocks.
83   MockSockets* sockets_;
84   ArpClient client_;
85   ByteString recvfrom_reply_data_;
86   sockaddr_ll recvfrom_sender_;
87 };
88 
89 
90 const int ArpClientTest::kInterfaceIndex = 123;
91 const int ArpClientTest::kSocketFD = 456;
92 const char ArpClientTest::kLocalIPAddress[] = "10.0.1.1";
93 const uint8_t ArpClientTest::kLocalMACAddress[] = { 0, 1, 2, 3, 4, 5 };
94 const char ArpClientTest::kRemoteIPAddress[] = "10.0.1.2";
95 const uint8_t ArpClientTest::kRemoteMACAddress[] = { 6, 7, 8, 9, 10, 11 };
96 const int ArpClientTest::kArpOpOffset = 7;
97 
98 
99 MATCHER_P2(IsLinkAddress, interface_index, destination_mac, "") {
100   const struct sockaddr_ll* socket_address =
101       reinterpret_cast<const struct sockaddr_ll*>(arg);
102   ByteString socket_mac(
103       reinterpret_cast<const unsigned char*>(&socket_address->sll_addr),
104       destination_mac.GetLength());
105   return socket_address->sll_family == AF_PACKET &&
106       socket_address->sll_protocol == htons(ETHERTYPE_ARP) &&
107       socket_address->sll_ifindex == interface_index &&
108       destination_mac.Equals(socket_mac);
109 }
110 
111 MATCHER_P(IsByteData, byte_data, "") {
112   return ByteString(reinterpret_cast<const unsigned char*>(arg),
113                     byte_data.GetLength()).Equals(byte_data);
114 }
115 
SetupValidPacket(ArpPacket * packet)116 void ArpClientTest::SetupValidPacket(ArpPacket* packet) {
117   IPAddress local_ip(IPAddress::kFamilyIPv4);
118   EXPECT_TRUE(local_ip.SetAddressFromString(kLocalIPAddress));
119   packet->set_local_ip_address(local_ip);
120   IPAddress remote_ip(IPAddress::kFamilyIPv4);
121   EXPECT_TRUE(remote_ip.SetAddressFromString(kRemoteIPAddress));
122   packet->set_remote_ip_address(remote_ip);
123   ByteString local_mac(kLocalMACAddress, arraysize(kLocalMACAddress));
124   packet->set_local_mac_address(local_mac);
125   ByteString remote_mac(kRemoteMACAddress, arraysize(kRemoteMACAddress));
126   packet->set_remote_mac_address(remote_mac);
127 }
128 
SimulateRecvFrom(int sockfd,void * buf,size_t len,int flags,struct sockaddr * src_addr,socklen_t * addrlen)129 ssize_t ArpClientTest::SimulateRecvFrom(int sockfd, void* buf, size_t len,
130                                         int flags, struct sockaddr* src_addr,
131                                         socklen_t* addrlen) {
132   memcpy(buf, recvfrom_reply_data_.GetConstData(),
133          recvfrom_reply_data_.GetLength());
134   memcpy(src_addr, &recvfrom_sender_, sizeof(recvfrom_sender_));
135   return recvfrom_reply_data_.GetLength();
136 }
137 
StartClientWithFD(int fd)138 void ArpClientTest::StartClientWithFD(int fd) {
139   EXPECT_CALL(*sockets_, Socket(PF_PACKET, SOCK_DGRAM, htons(ETHERTYPE_ARP)))
140       .WillOnce(Return(fd));
141   EXPECT_CALL(*sockets_, AttachFilter(fd, _)).WillOnce(Return(0));
142   EXPECT_CALL(*sockets_, SetNonBlocking(fd)).WillOnce(Return(0));
143   EXPECT_CALL(*sockets_, Bind(fd,
144                               IsLinkAddress(kInterfaceIndex, ByteString()),
145                               sizeof(sockaddr_ll))).WillOnce(Return(0));
146   EXPECT_TRUE(CreateSocket());
147   EXPECT_EQ(fd, client_.socket_);
148 }
149 
TEST_F(ArpClientTest,Constructor)150 TEST_F(ArpClientTest, Constructor) {
151   EXPECT_EQ(kInterfaceIndex, GetInterfaceIndex());
152   EXPECT_EQ(-1, GetSocket());
153 }
154 
TEST_F(ArpClientTest,SocketOpenFail)155 TEST_F(ArpClientTest, SocketOpenFail) {
156   ScopedMockLog log;
157   EXPECT_CALL(log,
158       Log(logging::LOG_ERROR, _,
159           HasSubstr("Could not create ARP socket"))).Times(1);
160 
161   EXPECT_CALL(*sockets_, Socket(PF_PACKET, SOCK_DGRAM, htons(ETHERTYPE_ARP)))
162       .WillOnce(Return(-1));
163   EXPECT_FALSE(CreateSocket());
164 }
165 
TEST_F(ArpClientTest,SocketFilterFail)166 TEST_F(ArpClientTest, SocketFilterFail) {
167   ScopedMockLog log;
168   EXPECT_CALL(log,
169       Log(logging::LOG_ERROR, _,
170           HasSubstr("Could not attach packet filter"))).Times(1);
171 
172   EXPECT_CALL(*sockets_, Socket(_, _, _)).WillOnce(Return(kSocketFD));
173   EXPECT_CALL(*sockets_, AttachFilter(kSocketFD, _)).WillOnce(Return(-1));
174   EXPECT_FALSE(CreateSocket());
175 }
176 
TEST_F(ArpClientTest,SocketNonBlockingFail)177 TEST_F(ArpClientTest, SocketNonBlockingFail) {
178   ScopedMockLog log;
179   EXPECT_CALL(log,
180       Log(logging::LOG_ERROR, _,
181           HasSubstr("Could not set socket to be non-blocking"))).Times(1);
182 
183   EXPECT_CALL(*sockets_, Socket(_, _, _)).WillOnce(Return(kSocketFD));
184   EXPECT_CALL(*sockets_, AttachFilter(kSocketFD, _)).WillOnce(Return(0));
185   EXPECT_CALL(*sockets_, SetNonBlocking(kSocketFD)).WillOnce(Return(-1));
186   EXPECT_FALSE(CreateSocket());
187 }
188 
TEST_F(ArpClientTest,SocketBindFail)189 TEST_F(ArpClientTest, SocketBindFail) {
190   ScopedMockLog log;
191   EXPECT_CALL(log,
192       Log(logging::LOG_ERROR, _,
193           HasSubstr("Could not bind socket to interface"))).Times(1);
194 
195   EXPECT_CALL(*sockets_, Socket(_, _, _)).WillOnce(Return(kSocketFD));
196   EXPECT_CALL(*sockets_, AttachFilter(kSocketFD, _)).WillOnce(Return(0));
197   EXPECT_CALL(*sockets_, SetNonBlocking(kSocketFD)).WillOnce(Return(0));
198   EXPECT_CALL(*sockets_, Bind(kSocketFD, _, _)).WillOnce(Return(-1));
199   EXPECT_FALSE(CreateSocket());
200 }
201 
TEST_F(ArpClientTest,StartSuccess)202 TEST_F(ArpClientTest, StartSuccess) {
203   StartClient();
204 }
205 
TEST_F(ArpClientTest,StartMultipleTimes)206 TEST_F(ArpClientTest, StartMultipleTimes) {
207   const int kFirstSocketFD = kSocketFD + 1;
208   StartClientWithFD(kFirstSocketFD);
209   EXPECT_CALL(*sockets_, Close(kFirstSocketFD));
210   StartClient();
211 }
212 
TEST_F(ArpClientTest,Receive)213 TEST_F(ArpClientTest, Receive) {
214   StartClient();
215   EXPECT_CALL(*sockets_,
216               RecvFrom(kSocketFD, _, GetMaxArpPacketLength(), 0, _, _))
217       .WillOnce(Return(-1))
218       .WillRepeatedly(Invoke(this, &ArpClientTest::SimulateRecvFrom));
219   ArpPacket reply;
220   ByteString sender;
221 
222   ScopedMockLog log;
223   EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
224   {
225     InSequence seq;
226 
227     // RecvFrom returns an error.
228     EXPECT_CALL(log,
229         Log(logging::LOG_ERROR, _,
230             HasSubstr("Socket recvfrom failed"))).Times(1);
231     EXPECT_FALSE(client_.ReceivePacket(&reply, &sender));
232 
233     // RecvFrom returns an empty response which fails to parse.
234     EXPECT_CALL(log,
235         Log(logging::LOG_ERROR, _,
236             HasSubstr("Failed to parse ARP packet"))).Times(1);
237     EXPECT_FALSE(client_.ReceivePacket(&reply, &sender));
238 
239     ArpPacket packet;
240     SetupValidPacket(&packet);
241     packet.FormatRequest(&recvfrom_reply_data_);
242 
243     // Hack: Force this packet to be an ARP repsonse instead of an ARP request.
244     recvfrom_reply_data_.GetData()[kArpOpOffset] = ARPOP_REPLY;
245 
246     static const uint8_t kSenderBytes[] = { 0xa, 0xb, 0xc, 0xd, 0xe, 0xf };
247     memcpy(&recvfrom_sender_.sll_addr, kSenderBytes, sizeof(kSenderBytes));
248     recvfrom_sender_.sll_halen = sizeof(kSenderBytes);
249     EXPECT_TRUE(client_.ReceivePacket(&reply, &sender));
250     EXPECT_TRUE(reply.local_ip_address().Equals(packet.local_ip_address()));
251     EXPECT_TRUE(reply.local_mac_address().Equals(packet.local_mac_address()));
252     EXPECT_TRUE(reply.remote_ip_address().Equals(packet.remote_ip_address()));
253     EXPECT_TRUE(reply.remote_mac_address().Equals(packet.remote_mac_address()));
254     EXPECT_TRUE(
255         sender.Equals(ByteString(kSenderBytes, arraysize(kSenderBytes))));
256   }
257 }
258 
TEST_F(ArpClientTest,Transmit)259 TEST_F(ArpClientTest, Transmit) {
260   ArpPacket packet;
261   StartClient();
262   // Packet isn't valid.
263   EXPECT_FALSE(client_.TransmitRequest(packet));
264 
265   SetupValidPacket(&packet);
266   const ByteString& remote_mac = packet.remote_mac_address();
267   ByteString packet_bytes;
268   ASSERT_TRUE(packet.FormatRequest(&packet_bytes));
269   EXPECT_CALL(*sockets_, SendTo(kSocketFD,
270                                 IsByteData(packet_bytes),
271                                 packet_bytes.GetLength(),
272                                 0,
273                                 IsLinkAddress(kInterfaceIndex, remote_mac),
274                                 sizeof(sockaddr_ll)))
275       .WillOnce(Return(-1))
276       .WillOnce(Return(0))
277       .WillOnce(Return(packet_bytes.GetLength() - 1))
278       .WillOnce(Return(packet_bytes.GetLength()));
279   {
280     InSequence seq;
281     ScopedMockLog log;
282     EXPECT_CALL(log,
283         Log(logging::LOG_ERROR, _,
284             HasSubstr("Socket sendto failed"))).Times(1);
285     EXPECT_CALL(log,
286         Log(logging::LOG_ERROR, _,
287             HasSubstr("different from expected result"))).Times(2);
288 
289     EXPECT_FALSE(client_.TransmitRequest(packet));
290     EXPECT_FALSE(client_.TransmitRequest(packet));
291     EXPECT_FALSE(client_.TransmitRequest(packet));
292     EXPECT_TRUE(client_.TransmitRequest(packet));
293   }
294 
295   // If the destination MAC address is unset, it should be sent to the
296   // broadcast MAC address.
297   static const uint8_t kZeroBytes[] = { 0, 0, 0, 0, 0, 0 };
298   packet.set_remote_mac_address(ByteString(kZeroBytes, arraysize(kZeroBytes)));
299   ASSERT_TRUE(packet.FormatRequest(&packet_bytes));
300   static const uint8_t kBroadcastBytes[] =
301       { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
302   ByteString broadcast_mac(kBroadcastBytes, arraysize(kBroadcastBytes));
303   EXPECT_CALL(*sockets_, SendTo(kSocketFD,
304                                 IsByteData(packet_bytes),
305                                 packet_bytes.GetLength(),
306                                 0,
307                                 IsLinkAddress(kInterfaceIndex, broadcast_mac),
308                                 sizeof(sockaddr_ll)))
309       .WillOnce(Return(packet_bytes.GetLength()));
310   EXPECT_TRUE(client_.TransmitRequest(packet));
311 }
312 
313 }  // namespace shill
314