1c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 2c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Copyright (C) 2012 The Android Open Source Project 3c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 4c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Licensed under the Apache License, Version 2.0 (the "License"); 5c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// you may not use this file except in compliance with the License. 6c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// You may obtain a copy of the License at 7c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 8c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// http://www.apache.org/licenses/LICENSE-2.0 9c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 10c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Unless required by applicable law or agreed to in writing, software 11c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// distributed under the License is distributed on an "AS IS" BASIS, 12c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// See the License for the specific language governing permissions and 14c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// limitations under the License. 15c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 16ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart 17ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart#include "shill/arp_client.h" 18ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart 19ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart#include <linux/if_packet.h> 20ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart#include <net/ethernet.h> 21ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart#include <net/if_arp.h> 22ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart#include <netinet/in.h> 23ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart#include <string.h> 24ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart 25ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart#include "shill/arp_packet.h" 26b691efd71561246065eae3cdd73a96ca1b8a528dChristopher Wiley#include "shill/logging.h" 278d6b59704591ba9fad57751858835dc332dbdd37Peter Qiu#include "shill/net/byte_string.h" 288d6b59704591ba9fad57751858835dc332dbdd37Peter Qiu#include "shill/net/sockets.h" 29ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart 30ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewartnamespace shill { 31ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart 327fab89734d88724a288e96a9996b15548c5294c7Ben Chan// ARP opcode is the last uint16_t in the ARP header. 337fab89734d88724a288e96a9996b15548c5294c7Ben Chanconst size_t ArpClient::kArpOpOffset = sizeof(arphdr) - sizeof(uint16_t); 34ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart 35ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart// The largest packet we expect is one with IPv6 addresses in it. 36ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewartconst size_t ArpClient::kMaxArpPacketLength = 37ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart sizeof(arphdr) + sizeof(in6_addr) * 2 + ETH_ALEN * 2; 38ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart 39ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul StewartArpClient::ArpClient(int interface_index) 40ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart : interface_index_(interface_index), 41ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart sockets_(new Sockets()), 42ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart socket_(-1) {} 43ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart 44ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul StewartArpClient::~ArpClient() {} 45ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart 46417e5f079a1ccbc068c67f9cbf34f13c40330abcPaul Stewartbool ArpClient::StartReplyListener() { 47417e5f079a1ccbc068c67f9cbf34f13c40330abcPaul Stewart return Start(ARPOP_REPLY); 48417e5f079a1ccbc068c67f9cbf34f13c40330abcPaul Stewart} 49417e5f079a1ccbc068c67f9cbf34f13c40330abcPaul Stewart 50417e5f079a1ccbc068c67f9cbf34f13c40330abcPaul Stewartbool ArpClient::StartRequestListener() { 51417e5f079a1ccbc068c67f9cbf34f13c40330abcPaul Stewart return Start(ARPOP_REQUEST); 52417e5f079a1ccbc068c67f9cbf34f13c40330abcPaul Stewart} 53417e5f079a1ccbc068c67f9cbf34f13c40330abcPaul Stewart 54417e5f079a1ccbc068c67f9cbf34f13c40330abcPaul Stewartbool ArpClient::Start(uint16_t arp_opcode) { 55417e5f079a1ccbc068c67f9cbf34f13c40330abcPaul Stewart if (!CreateSocket(arp_opcode)) { 56ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart LOG(ERROR) << "Could not open ARP socket."; 57ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart Stop(); 58ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart return false; 59ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart } 60ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart return true; 61ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart} 62ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart 63ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewartvoid ArpClient::Stop() { 64ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart socket_closer_.reset(); 65ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart} 66ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart 67ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart 68417e5f079a1ccbc068c67f9cbf34f13c40330abcPaul Stewartbool ArpClient::CreateSocket(uint16_t arp_opcode) { 69ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart int socket = sockets_->Socket(PF_PACKET, SOCK_DGRAM, htons(ETHERTYPE_ARP)); 70ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart if (socket == -1) { 71ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart PLOG(ERROR) << "Could not create ARP socket"; 72ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart return false; 73ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart } 74ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart socket_ = socket; 75ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart socket_closer_.reset(new ScopedSocketCloser(sockets_.get(), socket_)); 76ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart 77417e5f079a1ccbc068c67f9cbf34f13c40330abcPaul Stewart // Create a packet filter incoming ARP packets. 78c528bf60a127b82a841c9d349a7f549d61679dfePeter Qiu const sock_filter arp_filter[] = { 79417e5f079a1ccbc068c67f9cbf34f13c40330abcPaul Stewart // If a packet contains the ARP opcode we are looking for... 80ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart BPF_STMT(BPF_LD | BPF_H | BPF_ABS, kArpOpOffset), 81417e5f079a1ccbc068c67f9cbf34f13c40330abcPaul Stewart BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, arp_opcode, 0, 1), 82ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart // Return the the packet (up to largest expected packet size). 83ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart BPF_STMT(BPF_RET | BPF_K, kMaxArpPacketLength), 84ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart // Otherwise, drop it. 85ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart BPF_STMT(BPF_RET | BPF_K, 0), 86ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart }; 87ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart 88ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart sock_fprog pf; 89a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart pf.filter = const_cast<sock_filter*>(arp_filter); 90c528bf60a127b82a841c9d349a7f549d61679dfePeter Qiu pf.len = arraysize(arp_filter); 91ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart if (sockets_->AttachFilter(socket_, &pf) != 0) { 92ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart PLOG(ERROR) << "Could not attach packet filter"; 93ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart return false; 94ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart } 95ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart 96ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart if (sockets_->SetNonBlocking(socket_) != 0) { 97ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart PLOG(ERROR) << "Could not set socket to be non-blocking"; 98ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart return false; 99ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart } 100ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart 101ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart sockaddr_ll socket_address; 102ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart memset(&socket_address, 0, sizeof(socket_address)); 103ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart socket_address.sll_family = AF_PACKET; 104ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart socket_address.sll_protocol = htons(ETHERTYPE_ARP); 105ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart socket_address.sll_ifindex = interface_index_; 106ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart 107ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart if (sockets_->Bind(socket_, 108a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart reinterpret_cast<struct sockaddr*>(&socket_address), 109ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart sizeof(socket_address)) != 0) { 110ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart PLOG(ERROR) << "Could not bind socket to interface"; 111ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart return false; 112ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart } 113ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart 114ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart return true; 115ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart} 116ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart 117a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartbool ArpClient::ReceivePacket(ArpPacket* packet, ByteString* sender) const { 118ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart ByteString payload(kMaxArpPacketLength); 119ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart sockaddr_ll socket_address; 120ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart memset(&socket_address, 0, sizeof(socket_address)); 121ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart socklen_t socklen = sizeof(socket_address); 122ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart int result = sockets_->RecvFrom( 123ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart socket_, 124ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart payload.GetData(), 125ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart payload.GetLength(), 126ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart 0, 127a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart reinterpret_cast<struct sockaddr*>(&socket_address), 128ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart &socklen); 129ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart if (result < 0) { 130ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart PLOG(ERROR) << "Socket recvfrom failed"; 131ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart return false; 132ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart } 133ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart 134ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart payload.Resize(result); 135417e5f079a1ccbc068c67f9cbf34f13c40330abcPaul Stewart if (!packet->Parse(payload)) { 136417e5f079a1ccbc068c67f9cbf34f13c40330abcPaul Stewart LOG(ERROR) << "Failed to parse ARP packet."; 137ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart return false; 138ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart } 139ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart 140ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart // The socket address returned may only be big enough to contain 141ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart // the hardware address of the sender. 142ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart CHECK(socklen >= 143ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart sizeof(socket_address) - sizeof(socket_address.sll_addr) + ETH_ALEN); 144ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart CHECK(socket_address.sll_halen == ETH_ALEN); 145ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart *sender = ByteString( 146a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart reinterpret_cast<const unsigned char*>(&socket_address.sll_addr), 147ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart socket_address.sll_halen); 148ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart return true; 149ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart} 150ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart 151a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewartbool ArpClient::TransmitRequest(const ArpPacket& packet) const { 152ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart ByteString payload; 153ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart if (!packet.FormatRequest(&payload)) { 154ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart return false; 155ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart } 156ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart 157ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart sockaddr_ll socket_address; 158ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart memset(&socket_address, 0, sizeof(socket_address)); 159ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart socket_address.sll_family = AF_PACKET; 160ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart socket_address.sll_protocol = htons(ETHERTYPE_ARP); 161ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart socket_address.sll_hatype = ARPHRD_ETHER; 162ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart socket_address.sll_halen = ETH_ALEN; 163ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart socket_address.sll_ifindex = interface_index_; 164ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart 165ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart ByteString remote_address = packet.remote_mac_address(); 166ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart CHECK(sizeof(socket_address.sll_addr) >= remote_address.GetLength()); 167ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart if (remote_address.IsZero()) { 168ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart // If the destination MAC address is unspecified, send the packet 169ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart // to the broadcast (all-ones) address. 170ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart remote_address.BitwiseInvert(); 171ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart } 172ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart memcpy(&socket_address.sll_addr, remote_address.GetConstData(), 173ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart remote_address.GetLength()); 174ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart 175ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart int result = sockets_->SendTo( 176ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart socket_, 177ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart payload.GetConstData(), 178ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart payload.GetLength(), 179ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart 0, 180a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart reinterpret_cast<struct sockaddr*>(&socket_address), 181ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart sizeof(socket_address)); 182ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart const int expected_result = static_cast<int>(payload.GetLength()); 183ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart if (result != expected_result) { 184ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart if (result < 0) { 185ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart PLOG(ERROR) << "Socket sendto failed"; 186ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart } else if (result < static_cast<int>(payload.GetLength())) { 187ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart LOG(ERROR) << "Socket sendto returned " 188ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart << result 189ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart << " which is different from expected result " 190ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart << expected_result; 191ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart } 192ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart return false; 193ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart } 194ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart 195ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart return true; 196ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart} 197ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart 198ac1328e5143f6ee0054d5cb2f7d17754c16a3814Paul Stewart} // namespace shill 199