You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
143 lines
4.3 KiB
143 lines
4.3 KiB
/* |
|
* Copyright (c)2019 ZeroTier, Inc. |
|
* |
|
* Use of this software is governed by the Business Source License included |
|
* in the LICENSE.TXT file in the project's root directory. |
|
* |
|
* Change Date: 2025-01-01 |
|
* |
|
* On the date above, in accordance with the Business Source License, use |
|
* of this software will be governed by version 2.0 of the Apache License. |
|
*/ |
|
/****/ |
|
|
|
#ifndef ZT_ARP_HPP |
|
#define ZT_ARP_HPP |
|
|
|
#include <stdint.h> |
|
|
|
#include <utility> |
|
|
|
#include "../node/Constants.hpp" |
|
#include "../node/Hashtable.hpp" |
|
#include "../node/MAC.hpp" |
|
|
|
/** |
|
* Maximum possible ARP length |
|
* |
|
* ARPs are 28 bytes in length, but specify a 128 byte buffer since |
|
* some weird extensions we may support in the future can pad them |
|
* out to as long as 72 bytes. |
|
*/ |
|
#define ZT_ARP_BUF_LENGTH 128 |
|
|
|
/** |
|
* Minimum permitted interval between sending ARP queries for a given IP |
|
*/ |
|
#define ZT_ARP_QUERY_INTERVAL 2000 |
|
|
|
/** |
|
* Maximum time between query and response, otherwise responses are discarded to prevent poisoning |
|
*/ |
|
#define ZT_ARP_QUERY_MAX_TTL 5000 |
|
|
|
/** |
|
* ARP expiration time |
|
*/ |
|
#define ZT_ARP_EXPIRE 600000 |
|
|
|
namespace ZeroTier { |
|
|
|
/** |
|
* ARP cache and resolver |
|
* |
|
* To implement ARP: |
|
* |
|
* (1) Call processIncomingArp() on all ARP packets received and then always |
|
* check responseLen after calling. If it is non-zero, send the contents |
|
* of response to responseDest. |
|
* |
|
* (2) Call query() to look up IP addresses, and then check queryLen. If it |
|
* is non-zero, send the contents of query to queryDest (usually broadcast). |
|
* |
|
* Note that either of these functions can technically generate a response or |
|
* a query at any time, so their result parameters for sending ARPs should |
|
* always be checked. |
|
* |
|
* This class is not thread-safe and must be guarded if used in multi-threaded |
|
* code. |
|
*/ |
|
class Arp |
|
{ |
|
public: |
|
Arp(); |
|
|
|
/** |
|
* Set a local IP entry that we should respond to ARPs for |
|
* |
|
* @param mac Our local MAC address |
|
* @param ip IP in big-endian byte order (sin_addr.s_addr) |
|
*/ |
|
void addLocal(uint32_t ip,const MAC &mac); |
|
|
|
/** |
|
* Delete a local IP entry or a cached ARP entry |
|
* |
|
* @param ip IP in big-endian byte order (sin_addr.s_addr) |
|
*/ |
|
void remove(uint32_t ip); |
|
|
|
/** |
|
* Process ARP packets |
|
* |
|
* For ARP queries, a response is generated and responseLen is set to its |
|
* frame payload length in bytes. |
|
* |
|
* For ARP responses, the cache is populated and the IP address entry that |
|
* was learned is returned. |
|
* |
|
* @param arp ARP frame data |
|
* @param len Length of ARP frame (usually 28) |
|
* @param response Response buffer -- MUST be a minimum of ZT_ARP_BUF_LENGTH in size |
|
* @param responseLen Response length, or set to 0 if no response |
|
* @param responseDest Destination of response, or set to null if no response |
|
* @return IP address learned or 0 if no new IPs in cache |
|
*/ |
|
uint32_t processIncomingArp(const void *arp,unsigned int len,void *response,unsigned int &responseLen,MAC &responseDest); |
|
|
|
/** |
|
* Get the MAC corresponding to an IP, generating a query if needed |
|
* |
|
* This returns a MAC for a remote IP. The local MAC is returned for local |
|
* IPs as well. It may also generate a query if the IP is not known or the |
|
* entry needs to be refreshed. In this case queryLen will be set to a |
|
* non-zero value, so this should always be checked on return even if the |
|
* MAC returned is non-null. |
|
* |
|
* @param localMac Local MAC address of host interface |
|
* @param localIp Local IP address of host interface |
|
* @param targetIp IP to look up |
|
* @param query Buffer for generated query -- MUST be a minimum of ZT_ARP_BUF_LENGTH in size |
|
* @param queryLen Length of generated query, or set to 0 if no query generated |
|
* @param queryDest Destination of query, or set to null if no query generated |
|
* @return MAC or 0 if no cached entry for this IP |
|
*/ |
|
MAC query(const MAC &localMac,uint32_t localIp,uint32_t targetIp,void *query,unsigned int &queryLen,MAC &queryDest); |
|
|
|
private: |
|
struct _ArpEntry |
|
{ |
|
_ArpEntry() : lastQuerySent(0),lastResponseReceived(0),mac(),local(false) {} |
|
uint64_t lastQuerySent; // Time last query was sent or 0 for local IP |
|
uint64_t lastResponseReceived; // Time of last ARP response or 0 for local IP |
|
MAC mac; // MAC address of device responsible for IP or null if not known yet |
|
bool local; // True if this is a local ARP entry |
|
}; |
|
|
|
Hashtable< uint32_t,_ArpEntry > _cache; |
|
uint64_t _lastCleaned; |
|
}; |
|
|
|
} // namespace ZeroTier |
|
|
|
#endif
|
|
|