19#include <util/threadinterrupt.h>
93 {1,
"UNSUPP_VERSION"},
94 {2,
"NOT_AUTHORIZED"},
95 {3,
"NETWORK_FAILURE"},
158 {1,
"UNSUPP_VERSION"},
159 {2,
"NOT_AUTHORIZED"},
160 {3,
"MALFORMED_REQUEST"},
161 {4,
"UNSUPP_OPCODE"},
162 {5,
"UNSUPP_OPTION"},
163 {6,
"MALFORMED_OPTION"},
164 {7,
"NETWORK_FAILURE"},
166 {9,
"UNSUPP_PROTOCOL"},
167 {10,
"USER_EX_QUOTA"},
168 {11,
"CANNOT_PROVIDE_EXTERNAL"},
169 {12,
"ADDRESS_MISMATCH"},
170 {13,
"EXCESSIVE_REMOTE_PEER"},
198 }
else if (addr.
IsIPv6()) {
226 std::function<
bool(std::span<const uint8_t>)>
check_packet,
229 using namespace std::chrono;
239 if (sock.
Send(request.data(), request.size(), 0) !=
static_cast<ssize_t>(request.size())) {
248 if (interrupt)
return std::nullopt;
320 [&](
const std::span<const uint8_t>
response) ->
bool {
322 LogWarning(
"natpmp: Response too small\n");
326 LogWarning(
"natpmp: Response to wrong command\n");
358 [&](
const std::span<const uint8_t>
response) ->
bool {
360 LogWarning(
"natpmp: Response too small\n");
364 LogWarning(
"natpmp: Response to wrong command\n");
369 LogWarning(
"natpmp: Response port doesn't match request\n");
383 static std::atomic<bool>
warned{
false};
384 if (!
warned.exchange(
true)) {
479 [&](
const std::span<const uint8_t>
response) ->
bool {
486 LogWarning(
"pcp: Response too small\n");
490 LogWarning(
"pcp: Response to wrong command\n");
502 LogWarning(
"pcp: Response protocol or port doesn't match request\n");
526 static std::atomic<bool>
warned{
false};
527 if (!
warned.exchange(
true)) {
547 return strprintf(
"%s:%s -> %s (for %ds)",
#define Assume(val)
Assume is the identity function.
std::string ToStringAddr() const
bool GetIn6Addr(struct in6_addr *pipv6Addr) const
Try to get our IPv6 (or CJDNS) address.
bool GetInAddr(struct in_addr *pipv4Addr) const
Try to get our IPv4 address.
A combination of a network address (CNetAddr) and a (TCP) port.
bool SetSockAddr(const struct sockaddr *paddr, socklen_t addrlen)
Set CService from a network sockaddr.
std::string ToStringAddrPort() const
A helper class for interruptible sleeps.
RAII helper class that manages a socket and closes it automatically when it goes out of scope.
virtual ssize_t Send(const void *data, size_t len, int flags) const
send(2) wrapper.
virtual int Bind(const sockaddr *addr, socklen_t addr_len) const
bind(2) wrapper.
virtual bool Wait(std::chrono::milliseconds timeout, Event requested, Event *occurred=nullptr) const
Wait for readiness for input (recv) or output (send).
virtual int GetSockName(sockaddr *name, socklen_t *name_len) const
getsockname(2) wrapper.
static constexpr Event RECV
If passed to Wait(), then it will wait for readiness to read from the socket.
virtual int Connect(const sockaddr *addr, socklen_t addr_len) const
connect(2) wrapper.
virtual ssize_t Recv(void *buf, size_t len, int flags) const
recv(2) wrapper.
std::variant< MappingResult, MappingError > NATPMPRequestPortMap(const CNetAddr &gateway, uint16_t port, uint32_t lifetime, CThreadInterrupt &interrupt, int num_tries, std::chrono::milliseconds timeout_per_try)
Try to open a port using RFC 6886 NAT-PMP.
std::variant< MappingResult, MappingError > PCPRequestPortMap(const PCPMappingNonce &nonce, const CNetAddr &gateway, const CNetAddr &bind, uint16_t port, uint32_t lifetime, CThreadInterrupt &interrupt, int num_tries, std::chrono::milliseconds timeout_per_try)
Try to open a port using RFC 6887 Port Control Protocol (PCP).
#define WSAGetLastError()
void WriteBE32(B *ptr, uint32_t x)
void WriteBE16(B *ptr, uint16_t x)
uint16_t ReadBE16(const B *ptr)
uint32_t ReadBE32(const B *ptr)
std::string HexStr(const std::span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
#define LogDebug(category,...)
bool HasPrefix(const T1 &obj, const std::array< uint8_t, PREFIX_LEN > &prefix)
Check whether a container begins with the given prefix.
static constexpr size_t ADDR_IPV4_SIZE
Size of IPv4 address (in bytes).
static const std::array< uint8_t, 12 > IPV4_IN_IPV6_PREFIX
Prefix of an IPv6 address when it contains an embedded IPv4 address.
static constexpr size_t ADDR_IPV6_SIZE
Size of IPv6 address (in bytes).
std::function< std::unique_ptr< Sock >(int, int, int)> CreateSock
Socket factory.
std::array< uint8_t, PCP_MAP_NONCE_SIZE > PCPMappingNonce
PCP mapping nonce. Arbitrary data chosen by the client to identify a mapping.
constexpr size_t PCP_MAP_NONCE_SIZE
Mapping nonce size in bytes (see RFC6887 section 11.1).
@ PROTOCOL_ERROR
Any kind of protocol-level error, except unsupported version or no resources.
@ NO_RESOURCES
No resources available (port probably already mapped).
@ UNSUPP_VERSION
Unsupported protocol version.
@ NETWORK_ERROR
Any kind of network-level error.
std::string NetworkErrorString(int err)
Return readable error string for a network error code.
Successful response to a port mapping.
CService external
External host:port.
uint32_t lifetime
Granted lifetime of binding (seconds).
CService internal
Internal host:port.
std::string ToString() const
Format mapping as string for logging.
uint8_t version
Protocol version, one of NATPMP_VERSION or PCP_VERSION.
static time_point now() noexcept
Return current system time or mocked time, if set.
constexpr auto Ticks(Dur2 d)
Helper to count the seconds of a duration/time_point.