join 1.0
lightweight network framework library
Loading...
Searching...
No Matches
arp.hpp
Go to the documentation of this file.
1
25#ifndef JOIN_FABRIC_ARP_HPP
26#define JOIN_FABRIC_ARP_HPP
27
28// libjoin.
30#include <join/mac_address.hpp>
31#include <join/raw_socket.hpp>
32#include <join/condition.hpp>
33
34// C++.
35#include <unordered_map>
36#include <string>
37
38// C.
39#include <linux/filter.h>
40#include <net/if_arp.h>
41#include <net/if.h>
42
43namespace join
44{
48 class Arp : public EventHandler
49 {
50 public:
54 Arp () = delete;
55
62 Arp (const std::string& interface, NeighborManager& neighbors = NeighborManager::instance ());
63
68 Arp (const Arp& other) = delete;
69
74 Arp (Arp&& other) = delete;
75
81 Arp& operator= (const Arp& other) = delete;
82
88 Arp& operator= (Arp&& other) = delete;
89
93 ~Arp ();
94
101 template <typename Rep, typename Period>
102 MacAddress get (const IpAddress& ip, std::chrono::duration<Rep, Period> timeout)
103 {
104 if (ip.family () != AF_INET)
105 {
107 return {};
108 }
109
110 if (ip == IpAddress::ipv4Address (_interface))
111 {
112 return MacAddress::address (_interface);
113 }
114
115 MacAddress mac = cache (ip);
116
117 return mac.isWildcard () ? request (ip, timeout) : mac;
118 }
119
126 {
127 return get (ip, std::chrono::seconds (5));
128 }
129
137 template <typename Rep, typename Period>
138 static MacAddress get (const std::string& interface, const IpAddress& ip,
139 std::chrono::duration<Rep, Period> timeout)
140 {
141 return Arp (interface).get (ip, timeout);
142 }
143
150 static MacAddress get (const std::string& interface, const IpAddress& ip)
151 {
152 return get (interface, ip, std::chrono::seconds (5));
153 }
154
161 template <typename Rep, typename Period>
162 MacAddress request (const IpAddress& ip, std::chrono::duration<Rep, Period> timeout)
163 {
164 if (_reactor.isReactorThread ())
165 {
166 lastError = std::make_error_code (std::errc::resource_deadlock_would_occur);
167 return {};
168 }
169
170 if (ip.family () != AF_INET)
171 {
173 return {};
174 }
175
176 Packet out = {};
177 const MacAddress srcMac = MacAddress::address (_interface);
178 const IpAddress srcIp = IpAddress::ipv4Address (_interface);
179
180 ::memcpy (out.eth.h_dest, MacAddress::broadcast.addr (), ETH_ALEN);
181 ::memcpy (out.eth.h_source, srcMac.addr (), ETH_ALEN);
182 out.eth.h_proto = ::htons (ETH_P_ARP);
183
184 out.arp.ar_hrd = ::htons (ARPHRD_ETHER);
185 out.arp.ar_pro = ::htons (ETH_P_IP);
186 out.arp.ar_hln = ETH_ALEN;
187 out.arp.ar_pln = 4;
188 out.arp.ar_op = ::htons (ARPOP_REQUEST);
189 ::memcpy (out.arp.ar_sha, srcMac.addr (), ETH_ALEN);
190 ::memcpy (&out.arp.ar_sip, srcIp.addr (), sizeof (uint32_t));
191 ::memcpy (out.arp.ar_tha, MacAddress::wildcard.addr (), ETH_ALEN);
192 ::memcpy (&out.arp.ar_tip, ip.addr (), sizeof (uint32_t));
193
194 ScopedLock<Mutex> lock (_syncMutex);
195
196 uint32_t tip;
197 ::memcpy (&tip, &out.arp.ar_tip, sizeof (tip));
198 auto inserted = _pending.emplace (tip, std::make_unique<PendingRequest> ());
199 if (!inserted.second)
200 {
201 // LCOV_EXCL_START
203 return {};
204 // LCOV_EXCL_STOP
205 }
206
207 if (_socket.write (reinterpret_cast<const char*> (&out), sizeof (Packet)) == -1)
208 {
209 // LCOV_EXCL_START
210 _pending.erase (inserted.first);
211 return {};
212 // LCOV_EXCL_STOP
213 }
214
215 if (!inserted.first->second->cond.timedWait (lock, timeout))
216 {
217 _pending.erase (inserted.first);
218 lastError = std::make_error_code (std::errc::no_such_device_or_address);
219 return {};
220 }
221
222 MacAddress mac = inserted.first->second->mac;
223 _pending.erase (inserted.first);
224
225 return mac;
226 }
227
234 {
235 return request (ip, std::chrono::seconds (5));
236 }
237
245 template <typename Rep, typename Period>
246 static MacAddress request (const std::string& interface, const IpAddress& ip,
247 std::chrono::duration<Rep, Period> timeout)
248 {
249 return Arp (interface).request (ip, timeout);
250 }
251
258 static MacAddress request (const std::string& interface, const IpAddress& ip)
259 {
260 return request (interface, ip, std::chrono::seconds (5));
261 }
262
269 int add (const MacAddress& mac, const IpAddress& ip);
270
278 static int add (const std::string& interface, const MacAddress& mac, const IpAddress& ip);
279
285 int remove (const IpAddress& ip);
286
293 static int remove (const std::string& interface, const IpAddress& ip);
294
300 MacAddress cache (const IpAddress& ip);
301
308 static MacAddress cache (const std::string& interface, const IpAddress& ip);
309
310 private:
314 struct __attribute__ ((packed)) ArpPacket
315 {
316 uint16_t ar_hrd;
317 uint16_t ar_pro;
318 uint8_t ar_hln;
319 uint8_t ar_pln;
320 uint16_t ar_op;
321 uint8_t ar_sha[ETH_ALEN];
322 uint32_t ar_sip;
323 uint8_t ar_tha[ETH_ALEN];
324 uint32_t ar_tip;
325 };
326
330 struct __attribute__ ((packed)) Packet
331 {
332 struct ethhdr eth;
333 ArpPacket arp;
334 };
335
340 void onReadable (int fd) noexcept override final;
341
343 static constexpr size_t _bufferSize = 4096;
344
348 struct PendingRequest
349 {
350 Condition cond;
351 MacAddress mac;
352 };
353
355 std::unordered_map<uint32_t, std::unique_ptr<PendingRequest>> _pending;
356
358 Mutex _syncMutex;
359
361 Raw::Socket _socket;
362
364 const std::string _interface;
365
367 uint32_t _index = 0;
368
370 NeighborManager& _neighbors;
371
373 Reactor& _reactor;
374 };
375}
376
377#endif
ARP protocol class.
Definition arp.hpp:49
static MacAddress request(const std::string &interface, const IpAddress &ip)
get the MAC address for the given IP address using ARP request.
Definition arp.hpp:258
int add(const MacAddress &mac, const IpAddress &ip)
add entry the MAC address of the given IP address to ARP cache.
Definition arp.cpp:90
~Arp()
destroy the Arp instance.
Definition arp.cpp:81
MacAddress request(const IpAddress &ip, std::chrono::duration< Rep, Period > timeout)
get the MAC address for the given IP address using ARP request.
Definition arp.hpp:162
Arp(const Arp &other)=delete
create instance by copy.
static MacAddress request(const std::string &interface, const IpAddress &ip, std::chrono::duration< Rep, Period > timeout)
get the MAC address for the given IP address using ARP request.
Definition arp.hpp:246
static MacAddress get(const std::string &interface, const IpAddress &ip)
discover the MAC address for the given internet layer address.
Definition arp.hpp:150
static MacAddress get(const std::string &interface, const IpAddress &ip, std::chrono::duration< Rep, Period > timeout)
discover the MAC address for the given internet layer address.
Definition arp.hpp:138
Arp()=delete
create the Arp instance.
MacAddress get(const IpAddress &ip, std::chrono::duration< Rep, Period > timeout)
get the MAC address for the given IP address using netlink neighbor cache or ARP request.
Definition arp.hpp:102
int remove(const IpAddress &ip)
remove the MAC address of the given IP address from ARP cache.
Definition arp.cpp:114
MacAddress cache(const IpAddress &ip)
get the MAC address for the given IP address using ARP cache.
Definition arp.cpp:138
Arp & operator=(const Arp &other)=delete
assign instance by copy.
MacAddress request(const IpAddress &ip)
get the MAC address for the given IP address using ARP request.
Definition arp.hpp:233
MacAddress get(const IpAddress &ip)
get the MAC address for the given IP address using ARP cache or ARP request.
Definition arp.hpp:125
Arp(Arp &&other)=delete
create instance by move.
ssize_t write(const char *data, size_t maxSize) noexcept
write data.
Definition raw_socket.hpp:247
Event handler interface class.
Definition reactor.hpp:51
friend class Reactor
friendship with reactor.
Definition reactor.hpp:152
IPv6, IPv4 address class.
Definition ip_address.hpp:52
int family() const
get address family.
Definition ip_address.cpp:1250
static IpAddress ipv4Address(const std::string &interface)
get the specified interface IPv4 address.
Definition ip_address.cpp:1526
const void * addr() const
get the internal address structure.
Definition ip_address.cpp:1259
MAC address class.
Definition mac_address.hpp:47
static const MacAddress broadcast
broadcast MAC address.
Definition mac_address.hpp:310
bool isWildcard() const
check if MAC address is a wildcard address.
Definition mac_address.cpp:182
static const MacAddress wildcard
wildcard MAC address.
Definition mac_address.hpp:307
static MacAddress address(const std::string &interface)
get the specified interface MAC address.
Definition mac_address.cpp:355
const uint8_t * addr() const
get the internal MAC address array address.
Definition mac_address.cpp:164
ARP / NDP neighbor manager class.
Definition neighbor_manager.hpp:138
static NeighborManager & instance()
get the a singleton instance.
Definition neighbor_manager.cpp:62
bool isReactorThread() const noexcept
check if the calling thread is the reactor thread.
Definition reactor.cpp:337
class owning a mutex for the duration of a scoped block.
Definition mutex.hpp:249
Definition acceptor.hpp:32
std::error_code make_error_code(join::Errc code) noexcept
Create an std::error_code object.
Definition error.cpp:195