Home | History | Annotate | Download | only in shill
      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:
     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 
     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 
    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 
    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 
    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 
    150 TEST_F(ArpClientTest, Constructor) {
    151   EXPECT_EQ(kInterfaceIndex, GetInterfaceIndex());
    152   EXPECT_EQ(-1, GetSocket());
    153 }
    154 
    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 
    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 
    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 
    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 
    202 TEST_F(ArpClientTest, StartSuccess) {
    203   StartClient();
    204 }
    205 
    206 TEST_F(ArpClientTest, StartMultipleTimes) {
    207   const int kFirstSocketFD = kSocketFD + 1;
    208   StartClientWithFD(kFirstSocketFD);
    209   EXPECT_CALL(*sockets_, Close(kFirstSocketFD));
    210   StartClient();
    211 }
    212 
    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 
    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