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