mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-29 13:07:50 +00:00
[4274] Added a lot of dev DHCP4o6 stuff
This commit is contained in:
parent
85d79e09a2
commit
03e5cc7ea3
@ -52,6 +52,7 @@
|
||||
* - @subpage dhcpv4ConfigBackend
|
||||
* - @subpage dhcpv4SignalBasedReconfiguration
|
||||
* - @subpage dhcpv4Other
|
||||
* - @subpage dhcpv4o6Dhcp4
|
||||
* - @subpage dhcp6
|
||||
* - @subpage dhcpv6ConfigParser
|
||||
* - @subpage dhcpv6ConfigInherit
|
||||
@ -61,6 +62,7 @@
|
||||
* - @subpage dhcpv6ConfigBackend
|
||||
* - @subpage dhcpv6SignalBasedReconfiguration
|
||||
* - @subpage dhcpv6Other
|
||||
* - @subpage dhcpv4o6Dhcp6
|
||||
* - @subpage d2
|
||||
* - @subpage d2CPL
|
||||
* - @subpage d2ProcessDerivation
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2012-2016 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
@ -88,7 +88,7 @@ present, it uses the value from the global context.
|
||||
@endcode
|
||||
|
||||
Note that if the value is neither present in the local storage nor in the global
|
||||
context an error is signalled.
|
||||
context an error is signaled.
|
||||
|
||||
Parameter inheritance is done once, during the reconfiguration phase.
|
||||
Reconfigurations are rare, so extra logic here is not a problem. On the other
|
||||
@ -192,8 +192,8 @@ the DHCPv4 Client FQDN %Option in its responses to a client, with the appropriat
|
||||
flags set.
|
||||
|
||||
@todo Note: the current implementation doesn't allow configuration of the
|
||||
server's behaviour with respect to DNS Updates. This is planned for the future.
|
||||
The default behaviour is constituted by the set of constants defined in the
|
||||
server's behavior with respect to DNS Updates. This is planned for the future.
|
||||
The default behavioris constituted by the set of constants defined in the
|
||||
(upper part of) dhcp4_srv.cc file. Once the configuration is implemented,
|
||||
these constants will be removed.
|
||||
|
||||
@ -272,7 +272,7 @@ isc::dhcp::Dhcpv4Srv::buildCfgOptionList.
|
||||
|
||||
@section dhcpv4ConfigBackend Configuration backend for DHCPv4
|
||||
|
||||
Earlier Kea vesions had a concept of backends, which were implementations of
|
||||
Earlier Kea versions had a concept of backends, which were implementations of
|
||||
different ways how configuration could be delivered to Kea. It seems that the
|
||||
concept of backends didn't get much enthusiasm from users and having multiple
|
||||
backends was cumbersome to maintain, so it was removed in 1.0.
|
||||
@ -308,4 +308,6 @@ specified at server startup. The location of this file is held in the
|
||||
|
||||
For hooks API support in DHCPv4, see @ref dhcpv4Hooks.
|
||||
|
||||
@subpage dhcpv4o6Dhcp4
|
||||
|
||||
*/
|
||||
|
120
src/bin/dhcp4/dhcp4o6_dhcp4.dox
Normal file
120
src/bin/dhcp4/dhcp4o6_dhcp4.dox
Normal file
@ -0,0 +1,120 @@
|
||||
// Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
/**
|
||||
@page dhcpv4o6Dhcp4 DHCPv4-over-DHCPv6 DHCPv4 Server Side
|
||||
|
||||
Kea supports DHCPv4-over-DHCPv6 using cooperating DHCPv6 and DHCPv4
|
||||
servers. This section describes the DHCPv4 server side.
|
||||
|
||||
@section Dhcp4to6Ipc DHCPv6-to-DHCPv4 Inter Process Communication
|
||||
|
||||
The @c Dhcp4to6Ipc class is derived from the base @c Dhcp4o6IpcBase as
|
||||
a singleton class (by the static @ref isc::dhcp::Dhcp4to6Ipc::instance
|
||||
function). @ref isc::dhcp::Dhcp4to6Ipc::open is called to open IPC
|
||||
sockets and to register @ref isc::dhcp::Dhcp4to6Ipc::handler on
|
||||
external sockets on the @c IfaceMgr.
|
||||
|
||||
@section dhcp4to6Receive DHCPv4-over-DHCPv6 Packet Processing
|
||||
|
||||
DHCPv6 DHCPv4-QUERY messages are forwarded by the DHCPv6 server on the IPC.
|
||||
The interface manager (@c IfaceMgr) using the external socket mechanism
|
||||
invokes @ref isc::dhcp::Dhcp4to6Ipc::handler, the packet is received using
|
||||
(inherited) @ref isc::dhcp::Dhcp4o6IpcBase::receive which decodes and strips
|
||||
the ISC Vendor option.
|
||||
|
||||
The handler verifies there is one and only one DHCPv4-Message option
|
||||
and extracts it. @ref isc::dhcp::Dhcpv4Srv::processPacket processes
|
||||
the DHCPv4 query as a @c Pkt4o6 instance and builds the
|
||||
DHCPv4-over-DHCPv6 response.
|
||||
Registered callouts for "buffer4_send" are called (@ref
|
||||
dhcpv4HooksBuffer4Send, note all the other DHCPv4 hook points are
|
||||
served during the standard processing). The response is sent back
|
||||
to the DHCPv6 server on the IPC.
|
||||
|
||||
@section dhcp4to6Specific Modified DHCPv4 Routines
|
||||
|
||||
For a @c Pkt4o6 query the @ref isc::dhcp::Dhcpv4Exchange::initResponse
|
||||
performs some extra steps (@ref isc::dhcp::Dhcpv4Exchange::initResponse4o6):
|
||||
the DHCPv6 response is built and the response member is reset to
|
||||
a @c Pkt4o6 instance with DHCPv4 and DHCPv6 parts.
|
||||
|
||||
The subnet selection (@ref isc::dhcp::Dhcpv4Srv::selectSubnet) is specialized
|
||||
for @c Pkt4o6 queries (@ref isc::dhcp::Dhcpv4Srv::selectSubnet4o6):
|
||||
the subnet selector class (@c SubnetSelector) is filled using DHCPv4 and
|
||||
DHCPv6 information and the @ref isc::dhcp::CfgSubnets4::selectSubnet4o6
|
||||
function is called (instead of @ref isc::dhcp::CfgSubnets4::selectSubnet).
|
||||
|
||||
In @ref isc::dhcp::Dhcpv4Srv::adjustIfaceData for @c Pkt4o6 queries
|
||||
the local address is set to the incoming interface assigned address
|
||||
(same case than for a broadcast local address).
|
||||
|
||||
In @ref isc::dhcp::Dhcpv4Srv::adjustRemoteAddr for @c Pkt4o6 queries the
|
||||
remote address is set to the query one (which is in fact an IPv6 address).
|
||||
|
||||
In @ref isc::dhcp::Dhcpv4Srv::acceptDirectRequest @c Pkt4o6 queries are
|
||||
accepted (they are considered as being relayed).
|
||||
|
||||
@section dhcp4SubnetSelect DHCPv4 Subnet Selection
|
||||
|
||||
@todo Move this to libdhcpsrv
|
||||
|
||||
Selectors (i.e., members of @c SubnetSelector class) are:
|
||||
- incoming interface name
|
||||
- gateway address - giaddr field
|
||||
- client address - ciaddr field
|
||||
- local address
|
||||
- remote address
|
||||
- option select - from the first Relay Agent Link Selection suboption or
|
||||
from a Subnet Selection option
|
||||
- client classes - used to reject a matching rule and try next rules
|
||||
|
||||
First use the option select, next if the message was relayed (not undefined
|
||||
gateway address) use the gateway address as a subnet relay address.
|
||||
|
||||
If a subnet was not already selected choose an address between:
|
||||
|
||||
- if the gateway address is not undefined the gateway address
|
||||
- if the client address is not undefined and the local address not the
|
||||
broadcast address (i.e., renew or rebind) the client address
|
||||
- if the remote address is not undefined and the local address not the
|
||||
broadcast address (i.e., renew or rebind) the remote address
|
||||
- at this point try the interface name as a subnet interface
|
||||
- if the interface name does not select a subnet choose the interface address
|
||||
(last resort)
|
||||
|
||||
Match the chosen address in a subnet address range.
|
||||
|
||||
@section dhcp4o6SubnetSelect DHCPv4-over-DHCPv6 Subnet Selection
|
||||
|
||||
@todo Move this to libdhcpsrv
|
||||
|
||||
Selectors (i.e., members of @c SubnetSelector class) are:
|
||||
- incoming interface name
|
||||
- gateway address - giaddr field (should be always undefined)
|
||||
- client address - ciaddr field
|
||||
- local address - set to the interface address
|
||||
- remote address - IPv6 address
|
||||
- option select - from a Subnet Selection option
|
||||
- first relay link address - (IPv6) undefined or the first relay link
|
||||
address which is not undefined or link local (i.e., usable)
|
||||
- interface ID - (IPv6) when a relay message includes an interface ID
|
||||
relay option
|
||||
- client classes - used to reject a matching rule and try next rules
|
||||
|
||||
Check if DHCPv4-over-DHCPv6 is enabled for the subnet and continue
|
||||
with the next one is when it is not.
|
||||
|
||||
First the remote address is matched in a subnet IPv6 range, second
|
||||
the interface ID if it is set is matched, third the interface name.
|
||||
|
||||
These rules are applied for each subnet configuration so if two
|
||||
subnets match the first one is returned (vs. the first matching rule).
|
||||
|
||||
@todo better DHCPv4-over-DHCPv6 selection, e.g., handle relayed
|
||||
messages and return best (vs first) match.
|
||||
|
||||
*/
|
72
src/bin/dhcp6/dhcp4o6_dhcp6.dox
Normal file
72
src/bin/dhcp6/dhcp4o6_dhcp6.dox
Normal file
@ -0,0 +1,72 @@
|
||||
// Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
/**
|
||||
@page dhcpv4o6Dhcp6 DHCPv4-over-DHCPv6 DHCPv6 Server Side
|
||||
|
||||
Kea supports DHCPv4-over-DHCPv6 using cooperating DHCPv6 and DHCPv4
|
||||
servers. This section describes the DHCPv6 server side.
|
||||
|
||||
@section dhcp6to4Ipc DHCPv6-to-DHCPv4 Inter Process Communication
|
||||
|
||||
The @c Dhcp6to4Ipc class is derived from the base @c Dhcp4o6IpcBase as
|
||||
a singleton class (by the static @ref isc::dhcp::Dhcp6to4Ipc::instance
|
||||
function). @ref isc::dhcp::Dhcp6to4Ipc::open is called to open IPC
|
||||
sockets and to register @ref isc::dhcp::Dhcp6to4Ipc::handler on
|
||||
external sockets on the @c IfaceMgr.
|
||||
|
||||
@section dhcp6to4Process DHCPv6-to-DHCPv4 Packet Processing
|
||||
|
||||
Following the DHCPv4-over-DHCPv6 packet flow:
|
||||
|
||||
- a DHCPv6 DHCPv4-QUERY is received from a DHCPv4-over-DHCPv6 client
|
||||
(standard incoming DHCPv6 message processing is done until
|
||||
the message type specific part)
|
||||
|
||||
- the isc::dhcp::Dhcpv6Srv::processDhcp4Query method which verifies
|
||||
a DHCPv4 message option is present and calls the (inherited) @ref
|
||||
isc::dhcp::Dhcp4o6IpcBase::send method to transmit the DHCPv4-QUERY
|
||||
with the interface name and remote IPv6 address to the DHCPv4 server
|
||||
|
||||
- the DHCPv4 server processes the DHCPv4-QUERY and returns a
|
||||
DHCPv4-RESPONSE using the IPC
|
||||
|
||||
- the interface manager (@c IfaceMgr) using the external socket
|
||||
mechanism invokes @ref isc::dhcp::Dhcp6to4Ipc::handler
|
||||
|
||||
- @ref isc::dhcp::Dhcp6to4Ipc::handler receives the packet by
|
||||
(inherited) @ref isc::dhcp::Dhcp4o6IpcBase::receive which
|
||||
decodes and strips the ISC Vendor option. From this point
|
||||
the code mimics the sending part of standard DHCPv6 packet
|
||||
processing.
|
||||
|
||||
- the callouts registered for "buffer6_send" hook point are called
|
||||
(@ref dhcpv6HooksBuffer6Send). Note the "pkt6_send" hook is not used
|
||||
because the matching query packet is not available
|
||||
|
||||
- the DHCPv6 DHCPv4-RESPONSE packet is sent back to the IPv6 remote address
|
||||
|
||||
@section dhcp6SubnetSelection DHCPv6 Subnet Selection
|
||||
|
||||
@todo Move this to libdhcpsrv
|
||||
|
||||
Selectors (i.e., members of @c SubnetSelector class) are:
|
||||
- incoming interface name
|
||||
- remote address
|
||||
- first relay link address - undefined or the first relay link address which
|
||||
is not undefined or link local (i.e., usable)
|
||||
- interface ID - when a relay message includes an interface ID relay option
|
||||
- client classes - used to reject a matching rule and try next rules
|
||||
|
||||
If the first relay link address is undefined the client is directly connected:
|
||||
the interface name is matched and if it does not select a subnet the remote
|
||||
address is matched in a subnet address range.
|
||||
|
||||
If the first relay link address is not undefined the query was relayed:
|
||||
the interface ID is tried and if it does not select a subnet the first
|
||||
relay address is matched as a subnet relay address.
|
||||
|
||||
*/
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2012-2016 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
@ -88,7 +88,7 @@ SubnetConfigParser::getParam(const std::string& name) {
|
||||
@endcode
|
||||
|
||||
Note that if the value is neither present in the local storage nor in the global
|
||||
context, an error is signalled.
|
||||
context, an error is signaled.
|
||||
|
||||
Parameter inheritance is done once, during the reconfiguration phase.
|
||||
Reconfigurations are rare, so extra logic here is not a problem. On the other
|
||||
@ -276,7 +276,7 @@ isc::dhcp::Dhcpv6Srv::buildCfgOptionList.
|
||||
|
||||
@section dhcpv6ConfigBackend Configuration backend for DHCPv6
|
||||
|
||||
Earlier Kea vesions had a concept of backends, which were implementations of
|
||||
Earlier Kea versions had a concept of backends, which were implementations of
|
||||
different ways how configuration could be delivered to Kea. It seems that the
|
||||
concept of backends didn't get much enthusiasm from users and having multiple
|
||||
backends was cumbersome to maintain, so it was removed in 1.0.
|
||||
@ -312,4 +312,6 @@ specified at server startup. The location of this file is held in the
|
||||
|
||||
For hooks API support in DHCPv6, see @ref dhcpv6Hooks.
|
||||
|
||||
@subpage dhcpv4o6Dhcp6
|
||||
|
||||
*/
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2012-2016 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
@ -22,9 +22,10 @@ The following classes for packet manipulation are implemented:
|
||||
|
||||
- isc::dhcp::Pkt4 - represents a DHCPv4 packet.
|
||||
- isc::dhcp::Pkt6 - represents a DHCPv6 packet.
|
||||
- isc::dhcp::Pkt4o6 - represents a DHCPv4-over-DHCPv6 packet.
|
||||
|
||||
The following pointer types are defined: \c Pkt4Ptr and \c Pkt6Ptr. They are
|
||||
smart pointers using the \c boost::shared_ptr type. There are no const
|
||||
The following pointer types are defined: \c Pkt4Ptr, \c Pkt6Ptr and Pkt4o6Ptr.
|
||||
They are smart pointers using the \c boost::shared_ptr type. There are no const
|
||||
versions of packet types defined, as we assume that hooks can modify any
|
||||
aspect of the packet at almost any stage of processing.
|
||||
|
||||
@ -63,6 +64,19 @@ DHCPv6, but is rarely used in DHCPv4. \ref isc::dhcp::Option::addOption(),
|
||||
\ref isc::dhcp::Option::delOption(), \ref isc::dhcp::Option::getOption() can
|
||||
be used to add, remove and retrieve sub-options from within an option.
|
||||
|
||||
@section libdhcpDhcp4o6 DHCPv4-over-DHCPv6 support
|
||||
|
||||
The DHCPv4-over-DHCPv6 packet class (\c Pkt4o6) is derived from
|
||||
the DHCPv4 packet class (\c Pkt4) with:
|
||||
|
||||
- un extra member pointing to the encapsulating DHCPv6 packet, accessible
|
||||
by \ref isc::dhcp::Pkt4o6::getPkt6()
|
||||
- a specialized isc::dhcp::Pkt::pack() method which builds the wire-format
|
||||
data of the whole DHCPv6-over-DHCPv4 packet.
|
||||
|
||||
To avoid the extra overhead of dynamic casts the isc::dhcp::Pkt4::isDhcp4o6()
|
||||
virtual method returns true for \c Pkt4o6 instances and false for others.
|
||||
|
||||
@section libdhcpRelay Relay v6 support in Pkt6
|
||||
|
||||
DHCPv6 clients that are not connected to the same link as DHCPv6
|
||||
@ -113,7 +127,7 @@ server's response object. See @ref isc::dhcp::Pkt6::RelayInfo for details.
|
||||
@section libdhcpIfaceMgr Interface Manager
|
||||
|
||||
Interface Manager (or IfaceMgr) is an abstraction layer for low-level
|
||||
network operations. In particlar, it provides information about existing
|
||||
network operations. In particular, it provides information about existing
|
||||
network interfaces See @ref isc::dhcp::Iface class and
|
||||
@ref isc::dhcp::IfaceMgr::detectIfaces() and @ref isc::dhcp::IfaceMgr::getIface().
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2012-2016 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
@ -26,6 +26,8 @@ This library contains several crucial elements for the operation of the DHCP ser
|
||||
- isc::dhcp::HostMgr - manager for static reservations (a.k.a. host reservations).
|
||||
- isc::dhcp::D2ClientMgr - DHCP-DDNS (D2) client manager which is responsible for
|
||||
the communication between the DHCP server and the D2 component.
|
||||
- isc::dhcp::Dhcp4o6IpcBase - common part (base class) of DHCPv4-over-DHCPv6
|
||||
inter server communication (aka IPC).
|
||||
|
||||
@section leasemgr Lease Manager
|
||||
|
||||
@ -67,7 +69,7 @@ the \ref isc::dhcp::CfgMgr::getStagingCfg is called again a fresh/default
|
||||
|
||||
The Configuration Manager stores previous configurations, i.e. configurations
|
||||
which occurred prior to the most current configuration. This is currently
|
||||
unused (except for unit tests) by the deamons, but in the future this
|
||||
unused (except for unit tests) by the daemons, but in the future this
|
||||
mechanism can be used to trigger a rollover of the server configuration
|
||||
to a last good configuration that the administrator prefers.
|
||||
|
||||
@ -92,7 +94,7 @@ database. This object must implement the \ref isc::dhcp::BaseHostDataSource
|
||||
interface and its implementation is specific to the type of storage
|
||||
holding the reservations. For example, the host data source managing
|
||||
host reservations in the MySQL database is required to establish
|
||||
connection to the MySQL databse and issue specific queries. Once
|
||||
connection to the MySQL database and issue specific queries. Once
|
||||
implemented, the \ref isc::dhcp::HostMgr::create method must be updated
|
||||
to create an instance of this datasource. Note, that this instance is
|
||||
created as "alternate host data source" as opposed to the primary data
|
||||
@ -113,7 +115,7 @@ documentation.
|
||||
@section optionsConfig Options Configuration Information
|
||||
|
||||
The \ref isc::dhcp::CfgOption object holds a collection of options being
|
||||
sent to the client. Since each subnet comes with a distnict set of
|
||||
sent to the client. Since each subnet comes with a distinct set of
|
||||
options, every \ref isc::dhcp::Subnet object holds its own copy of the
|
||||
\ref isc::dhcp::CfgOption object with specific options.
|
||||
|
||||
@ -137,7 +139,7 @@ that there may be cases when the server administrator doesn't specify
|
||||
any subnet configuration and only wants global options to be used.
|
||||
This is the case, when the DHCP server is used for stateless
|
||||
configuration, i.e. client's are not allocated an address or prefix,
|
||||
and only stateless configruation is handed out.
|
||||
and only stateless configuration is handed out.
|
||||
|
||||
@section allocengine Allocation Engine
|
||||
|
||||
@ -242,7 +244,7 @@ reserved until the client using this address releases or the server
|
||||
assigns a different address for it.
|
||||
|
||||
In order to resolve this conflict the Allocation Engine will refuse to
|
||||
renew the lease for the client using the addres not reserved for it.
|
||||
renew the lease for the client using the address not reserved for it.
|
||||
This client should fall back to the 4-way exchange and the Allocation
|
||||
Engine will assign a different address. As a result, the reserved
|
||||
address will be freed for the use of the client for which the reservation
|
||||
@ -269,7 +271,7 @@ leases.
|
||||
|
||||
The @c isc::dhcp::TimerMgr has been created to address the issue of
|
||||
processing expired leases according to the the dedicated timer.
|
||||
Nevertheless, this concept is univeral and should be used for
|
||||
Nevertheless, this concept is universal and should be used for
|
||||
all timers which need to be triggered asynchronously, i.e. independently
|
||||
from processing the DHCP messages.
|
||||
|
||||
@ -366,4 +368,22 @@ since expiration elapsed. These methods are executed periodically
|
||||
by the DHCP servers using the dedicated timers registered in the
|
||||
@c isc::dhcp::TimerMgr.
|
||||
|
||||
@section dhcp4o6Ipc DHCPv4-over-DHCPv6 Inter Process Communication
|
||||
|
||||
DHCPv4-over-DHCPv6 support is implemented using cooperating
|
||||
DHCPv6 and DHCPv6 servers. Servers communicate over a pair of
|
||||
local UDP sockets using consecutive ports. The common part of
|
||||
the Inter Process Communication (IPC) is provided by the base class
|
||||
@c isc::dhcp::Dhcp4o6IpcBase.
|
||||
|
||||
The receiving interface name and remote IPv6 address meta information
|
||||
are conveyed within a Vendor Specific Information option with the ISC
|
||||
enterprise ID carrying interface and remote address suboptions.
|
||||
\ref isc::dhcp::Dhcp4o6IpcBase::send adds them,
|
||||
\ref isc::dhcp::Dhcp4o6IpcBase::receive decodes and removes them.
|
||||
|
||||
@todo
|
||||
|
||||
DHCPv4-over-DHCPv6 which are relayed by a DHCPv6 relay are not yet supported.
|
||||
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user