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 #include <string.h>
     24 
     25 #include "shill/arp_packet.h"
     26 #include "shill/logging.h"
     27 #include "shill/net/byte_string.h"
     28 #include "shill/net/sockets.h"
     29 
     30 namespace shill {
     31 
     32 // ARP opcode is the last uint16_t in the ARP header.
     33 const size_t ArpClient::kArpOpOffset = sizeof(arphdr) - sizeof(uint16_t);
     34 
     35 // The largest packet we expect is one with IPv6 addresses in it.
     36 const size_t ArpClient::kMaxArpPacketLength =
     37     sizeof(arphdr) + sizeof(in6_addr) * 2 + ETH_ALEN * 2;
     38 
     39 ArpClient::ArpClient(int interface_index)
     40     : interface_index_(interface_index),
     41       sockets_(new Sockets()),
     42       socket_(-1) {}
     43 
     44 ArpClient::~ArpClient() {}
     45 
     46 bool ArpClient::StartReplyListener() {
     47   return Start(ARPOP_REPLY);
     48 }
     49 
     50 bool ArpClient::StartRequestListener() {
     51   return Start(ARPOP_REQUEST);
     52 }
     53 
     54 bool ArpClient::Start(uint16_t arp_opcode) {
     55   if (!CreateSocket(arp_opcode)) {
     56     LOG(ERROR) << "Could not open ARP socket.";
     57     Stop();
     58     return false;
     59   }
     60   return true;
     61 }
     62 
     63 void ArpClient::Stop() {
     64   socket_closer_.reset();
     65 }
     66 
     67 
     68 bool ArpClient::CreateSocket(uint16_t arp_opcode) {
     69   int socket = sockets_->Socket(PF_PACKET, SOCK_DGRAM, htons(ETHERTYPE_ARP));
     70   if (socket == -1) {
     71     PLOG(ERROR) << "Could not create ARP socket";
     72     return false;
     73   }
     74   socket_ = socket;
     75   socket_closer_.reset(new ScopedSocketCloser(sockets_.get(), socket_));
     76 
     77   // Create a packet filter incoming ARP packets.
     78   const sock_filter arp_filter[] = {
     79     // If a packet contains the ARP opcode we are looking for...
     80     BPF_STMT(BPF_LD | BPF_H | BPF_ABS, kArpOpOffset),
     81     BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, arp_opcode, 0, 1),
     82     // Return the the packet (up to largest expected packet size).
     83     BPF_STMT(BPF_RET | BPF_K, kMaxArpPacketLength),
     84     // Otherwise, drop it.
     85     BPF_STMT(BPF_RET | BPF_K, 0),
     86   };
     87 
     88   sock_fprog pf;
     89   pf.filter = const_cast<sock_filter*>(arp_filter);
     90   pf.len = arraysize(arp_filter);
     91   if (sockets_->AttachFilter(socket_, &pf) != 0) {
     92     PLOG(ERROR) << "Could not attach packet filter";
     93     return false;
     94   }
     95 
     96   if (sockets_->SetNonBlocking(socket_) != 0) {
     97     PLOG(ERROR) << "Could not set socket to be non-blocking";
     98     return false;
     99   }
    100 
    101   sockaddr_ll socket_address;
    102   memset(&socket_address, 0, sizeof(socket_address));
    103   socket_address.sll_family = AF_PACKET;
    104   socket_address.sll_protocol = htons(ETHERTYPE_ARP);
    105   socket_address.sll_ifindex = interface_index_;
    106 
    107   if (sockets_->Bind(socket_,
    108                      reinterpret_cast<struct sockaddr*>(&socket_address),
    109                      sizeof(socket_address)) != 0) {
    110     PLOG(ERROR) << "Could not bind socket to interface";
    111     return false;
    112   }
    113 
    114   return true;
    115 }
    116 
    117 bool ArpClient::ReceivePacket(ArpPacket* packet, ByteString* sender) const {
    118   ByteString payload(kMaxArpPacketLength);
    119   sockaddr_ll socket_address;
    120   memset(&socket_address, 0, sizeof(socket_address));
    121   socklen_t socklen = sizeof(socket_address);
    122   int result = sockets_->RecvFrom(
    123       socket_,
    124       payload.GetData(),
    125       payload.GetLength(),
    126       0,
    127       reinterpret_cast<struct sockaddr*>(&socket_address),
    128       &socklen);
    129   if (result < 0) {
    130     PLOG(ERROR) << "Socket recvfrom failed";
    131     return false;
    132   }
    133 
    134   payload.Resize(result);
    135   if (!packet->Parse(payload)) {
    136     LOG(ERROR) << "Failed to parse ARP packet.";
    137     return false;
    138   }
    139 
    140   // The socket address returned may only be big enough to contain
    141   // the hardware address of the sender.
    142   CHECK(socklen >=
    143         sizeof(socket_address) - sizeof(socket_address.sll_addr) + ETH_ALEN);
    144   CHECK(socket_address.sll_halen == ETH_ALEN);
    145   *sender = ByteString(
    146       reinterpret_cast<const unsigned char*>(&socket_address.sll_addr),
    147       socket_address.sll_halen);
    148   return true;
    149 }
    150 
    151 bool ArpClient::TransmitRequest(const ArpPacket& packet) const {
    152   ByteString payload;
    153   if (!packet.FormatRequest(&payload)) {
    154     return false;
    155   }
    156 
    157   sockaddr_ll socket_address;
    158   memset(&socket_address, 0, sizeof(socket_address));
    159   socket_address.sll_family = AF_PACKET;
    160   socket_address.sll_protocol = htons(ETHERTYPE_ARP);
    161   socket_address.sll_hatype = ARPHRD_ETHER;
    162   socket_address.sll_halen = ETH_ALEN;
    163   socket_address.sll_ifindex = interface_index_;
    164 
    165   ByteString remote_address = packet.remote_mac_address();
    166   CHECK(sizeof(socket_address.sll_addr) >= remote_address.GetLength());
    167   if (remote_address.IsZero()) {
    168     // If the destination MAC address is unspecified, send the packet
    169     // to the broadcast (all-ones) address.
    170     remote_address.BitwiseInvert();
    171   }
    172   memcpy(&socket_address.sll_addr, remote_address.GetConstData(),
    173          remote_address.GetLength());
    174 
    175   int result = sockets_->SendTo(
    176       socket_,
    177       payload.GetConstData(),
    178       payload.GetLength(),
    179       0,
    180       reinterpret_cast<struct sockaddr*>(&socket_address),
    181       sizeof(socket_address));
    182   const int expected_result  = static_cast<int>(payload.GetLength());
    183   if (result != expected_result) {
    184     if (result < 0) {
    185       PLOG(ERROR) << "Socket sendto failed";
    186     } else if (result < static_cast<int>(payload.GetLength())) {
    187       LOG(ERROR) << "Socket sendto returned "
    188                  << result
    189                  << " which is different from expected result "
    190                  << expected_result;
    191     }
    192     return false;
    193   }
    194 
    195   return true;
    196 }
    197 
    198 }  // namespace shill
    199