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
31using testing::_;
32using testing::AnyNumber;
33using testing::HasSubstr;
34using testing::InSequence;
35using testing::Invoke;
36using testing::Mock;
37using testing::Return;
38using testing::StrictMock;
39using testing::Test;
40
41namespace shill {
42
43class ArpClientTest : public Test {
44 public:
45  ArpClientTest() : client_(kInterfaceIndex) {}
46  virtual ~ArpClientTest() {}
47
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
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
74  bool CreateSocket() { return client_.CreateSocket(ARPOP_REPLY); }
75  int GetInterfaceIndex() { return client_.interface_index_; }
76  size_t GetMaxArpPacketLength() { return ArpClient::kMaxArpPacketLength; }
77  int GetSocket() { return client_.socket_; }
78  void SetupValidPacket(ArpPacket* packet);
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
90const int ArpClientTest::kInterfaceIndex = 123;
91const int ArpClientTest::kSocketFD = 456;
92const char ArpClientTest::kLocalIPAddress[] = "10.0.1.1";
93const uint8_t ArpClientTest::kLocalMACAddress[] = { 0, 1, 2, 3, 4, 5 };
94const char ArpClientTest::kRemoteIPAddress[] = "10.0.1.2";
95const uint8_t ArpClientTest::kRemoteMACAddress[] = { 6, 7, 8, 9, 10, 11 };
96const int ArpClientTest::kArpOpOffset = 7;
97
98
99MATCHER_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
111MATCHER_P(IsByteData, byte_data, "") {
112  return ByteString(reinterpret_cast<const unsigned char*>(arg),
113                    byte_data.GetLength()).Equals(byte_data);
114}
115
116void 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
129ssize_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
138void 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
150TEST_F(ArpClientTest, Constructor) {
151  EXPECT_EQ(kInterfaceIndex, GetInterfaceIndex());
152  EXPECT_EQ(-1, GetSocket());
153}
154
155TEST_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
166TEST_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
177TEST_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
189TEST_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
202TEST_F(ArpClientTest, StartSuccess) {
203  StartClient();
204}
205
206TEST_F(ArpClientTest, StartMultipleTimes) {
207  const int kFirstSocketFD = kSocketFD + 1;
208  StartClientWithFD(kFirstSocketFD);
209  EXPECT_CALL(*sockets_, Close(kFirstSocketFD));
210  StartClient();
211}
212
213TEST_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
259TEST_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