31using namespace std::chrono;
32namespace ph = std::placeholders;
42 return (
"bad response");
52 return (
"temporarily unavailable");
54 result << (rc < 0 ?
"error " :
"unknown ") << rc;
55 return (result.str());
69 if (servers.empty()) {
70 isc_throw(BadValue,
"no server");
87 if (servers.empty()) {
88 isc_throw(BadValue,
"no server");
121 :
Exchange(request, maxretries, servers, handler),
126 mutex_(new std::mutex()) {
135 :
Exchange(request, maxretries, servers),
141 mutex_(new std::mutex()) {
159 if (rv.size() !=
sizeof(uint32_t)) {
163 memmove(&ri, &rv[0],
sizeof(uint32_t));
165 rs << hex << setfill(
'0') << setw(8) << ri;
182 .arg(
static_cast<int>(
received_->getIdentifier()))
184 .arg(attr->toString());
248 std::chrono::steady_clock::time_point start_time) {
257 sent_->randomIdentifier();
268 sent_->setSecret(server->getSecret());
274 sent_->setAttributes(attrs);
280 auto delta = steady_clock().now() - start_time;
281 seconds secs = duration_cast<seconds>(delta);
283 static_cast<uint32_t
>(secs.count())));
287 IOAddress local_addr = server->getLocalAddress();
289 if (family == AF_INET) {
293 }
else if (family == AF_INET6) {
304 const vector<uint8_t> zero(AUTH_VECTOR_LEN);
349 if ((
server_->getDeadtime() > 0) &&
354 shared_from_this()));
361 shared_from_this()));
415 .arg(
ep_->getAddress().toText())
416 .arg(
ep_->getPort());
435 shared_from_this()));
444 unsigned deadtime =
server_->getDeadtime();
457 shared_from_this()));
467 shared_from_this()));
473 shared_from_this()));
532 shared_from_this()));
539 const boost::system::error_code ec,
552 if (ex->terminated_) {
559 .arg(ex->identifier_)
563 ex->socket_->close();
572 .arg(ex->identifier_)
576 ex->size_ = ex->buffer_.size();
577 ex->socket_->asyncReceive(&(ex->buffer_)[0], ex->size_, 0, ex->ep_.get(),
601 unsigned got =
received_->getIdentifier();
602 unsigned expected =
sent_->getIdentifier();
603 if (got != expected) {
674 const boost::system::error_code ec,
690 ex->socket_->close();
694 if (ex->terminated_) {
701 .arg(ex->identifier_)
709 (ex->server_->getDeadtime() > 0) &&
710 (ex->server_->getDeadtimeEnd() > ex->start_time_)) {
711 ex->server_->setDeadtimeEnd(ex->start_time_);
716 .arg(ex->identifier_)
718 ex->buffer_.resize(size);
719 ex->received_.reset(
new Message(ex->buffer_, ex->sent_->getAuth(),
720 ex->server_->getSecret()));
722 ex->processResponse();
728 ex->logReplyMessages();
777 handler(shared_from_this());
779 handler(shared_from_this());
804 .arg(ex->identifier_);
808 ex->socket_->cancel();
816 :
Exchange(request, maxretries, servers, handler),
855 .arg(request->size())
856 .arg(
server_->getPeerAddress().toText())
858 .arg(
server_->getTlsContext() ?
" using TLS" :
"");
884 handler(shared_from_this());
896 const boost::system::error_code& ec,
898 const string& error_msg) {
909 if (exchange->handler_) {
910 auto handler = exchange->handler_;
912 exchange->handler_ =
Handler();
920 .arg(ex->identifier_)
922 if (ec == boost::asio::error::timed_out) {
936 .arg(ex->identifier_)
937 .arg(response->size());
940 ex->received_.reset(
new Message(buffer, ex->sent_->getAuth(),
941 ex->server_->getSecret()));
943 ex->processResponse();
946 ex->logReplyMessages();
948 .arg(ex->identifier_)
952 .arg(ex->identifier_)
961 error_msg =
"null response";
965 if (buffer.size() < AUTH_HDR_LEN) {
968 uint16_t length =
static_cast<uint16_t
>(buffer[2]) << 8;
969 length |=
static_cast<uint16_t
>(buffer[3]);
970 if (length > buffer.size()) {
972 }
else if (length == buffer.size()) {
975 error_msg =
"overflow";
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
This is a base class for exceptions thrown from the DNS library module.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown when an unexpected error condition occurs.
The IOAddress class represents an IP addresses (version agnostic)
short getFamily() const
Returns the address family.
The IOService class is a wrapper for the ASIO io_context class.
The IntervalTimer class is a wrapper for the ASIO boost::asio::system_timer class.
The UDPEndpoint class is a concrete derived class of IOEndpoint that represents an endpoint of a UDP ...
static AttributePtr fromInt(const uint8_t type, const uint32_t value)
From integer with type.
static AttributePtr fromIpAddr(const uint8_t type, const asiolink::IOAddress &value)
From IPv4 address with type.
static AttributePtr fromBinary(const uint8_t type, const std::vector< uint8_t > &value)
From binary with type.
static AttributePtr fromIpv6Addr(const uint8_t type, const asiolink::IOAddress &value)
From IPv6 address with type.
Collection of attributes.
asiolink::UDPSocket< const SocketCallback > RadiusSocket
Type of RADIUS UDP sockets.
Servers servers_
Servers (a copy which is what we need).
Handler handler_
Termination handler.
MessagePtr request_
Request message.
Exchange(const MessagePtr &request, unsigned maxretries, const Servers &servers, Handler handler)
Constructor.
std::function< void(const ExchangePtr ex)> Handler
Termination handler.
bool sync_
Sync / async flag.
void processResponse()
Process response.
static constexpr size_t BUF_LEN
Receive buffer size.
void createIdentifier()
Create identifier.
MessagePtr received_
Received message.
int rc_
Error/return code.
std::string identifier_
The identifier (random value in hexadecimal).
std::function< void(const boost::system::error_code ec, const size_t size)> SocketCallback
Type of UDP socket callback functions.
MessagePtr sent_
Sent message.
void buildRequest(const ServerPtr &server, std::chrono::steady_clock::time_point start_time)
Build request.
static ExchangePtr create(const asiolink::IOServicePtr io_service, const MessagePtr &request, unsigned maxretries, const Servers &servers, Handler handler, RadiusProtocol protocol=PW_PROTO_UDP)
Factory.
void logReplyMessages() const
Log reply messages.
unsigned maxretries_
Maximum number of retries for a server.
static std::atomic< bool > shutdown_
Flag which indicates that the instance is shutting down.
isc::tcp::TcpClientPtr tcp_client_
TCP client.
static RadiusImpl & instance()
RadiusImpl is a singleton class.
RADIUS/TCP (or RADIUS/TLS) Exchange.
isc::tcp::WireDataPtr response_
Response wire data.
TcpExchange(const MessagePtr &request, unsigned maxretries, const Servers &servers, Handler handler)
Constructor.
virtual void shutdown()
Shutdown.
void buildRequest()
Build request.
static int CompleteCheck(const isc::tcp::WireDataPtr &response, std::string &error_msg)
Complete check.
std::chrono::steady_clock::time_point start_time_
Start time.
virtual void start()
Start.
ServerPtr server_
Current server.
static void RequestHandler(TcpExchangePtr ex, const boost::system::error_code &ec, const isc::tcp::WireDataPtr &response, const std::string &error_msg)
Request handler.
asiolink::IOServicePtr io_service_
IO service (argument for async or internal for sync).
boost::scoped_ptr< asiolink::UDPEndpoint > ep_
UDP endpoint.
static void receivedHandler(UdpExchangePtr ex, const boost::system::error_code ec, const size_t size)
Received handler.
void cancelTimer()
Cancel timer.
asiolink::IntervalTimerPtr timer_
Interval timer.
size_t size_
Number of transmitted octests;.
void open()
Instance open.
static void timeoutHandler(UdpExchangePtr ex)
Timeout handler.
virtual ~UdpExchange()
Destructor.
bool started_
Started flag.
virtual void shutdown()
Shutdown.
std::chrono::steady_clock::time_point start_time_
Start time.
void setTimer()
Set timer.
std::list< size_t > postponed_
List of postponed server indexes.
void buildRequest()
Build request.
virtual void shutdownInternal()
Shutdown.
size_t idx_
Current server index.
ServerPtr server_
Current server.
virtual void start()
Start.
std::vector< uint8_t > buffer_
Buffer.
static void openNext(UdpExchangePtr ex)
Class open / open next.
boost::scoped_ptr< RadiusSocket > socket_
Socket.
bool terminated_
Terminated flag.
UdpExchange(const asiolink::IOServicePtr io_service, const MessagePtr &request, unsigned maxretries, const Servers &servers, Handler handler)
Constructor.
unsigned retries_
Retry counter.
void terminate()
Terminate.
static void sentHandler(UdpExchangePtr ex, const boost::system::error_code ec, const size_t size)
Sent handler.
boost::scoped_ptr< std::mutex > mutex_
State change mutex.
static MultiThreadingMgr & instance()
Returns a single instance of Multi Threading Manager.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
boost::shared_ptr< IOService > IOServicePtr
Defines a smart pointer to an IOService instance.
std::vector< uint8_t > random(size_t len)
Generate random value.
const isc::log::MessageID RADIUS_UDP_EXCHANGE_OPEN_FAILED
@ PW_ACCT_DELAY_TIME
integer.
@ PW_NAS_IPV6_ADDRESS
ipv6addr.
@ PW_NAS_IP_ADDRESS
ipaddr.
@ PW_REPLY_MESSAGE
string.
@ PW_MESSAGE_AUTHENTICATOR
string.
const isc::log::MessageID RADIUS_EXCHANGE_RECEIVED_MISMATCH
boost::shared_ptr< Attributes > AttributesPtr
Shared pointers to attribute collection.
const isc::log::MessageID RADIUS_UDP_EXCHANGE_SYNC_RETURN
boost::shared_ptr< const Attribute > ConstAttributePtr
const isc::log::MessageID RADIUS_EXCHANGE_RECEIVED_ACCESS_REJECT
const isc::log::MessageID RADIUS_UDP_EXCHANGE_FAILED
boost::shared_ptr< TcpExchange > TcpExchangePtr
Type of shared pointers to RADIUS/TCP exchange object.
string exchangeRCtoText(const int rc)
ExchangeRC value -> name function.
const isc::log::MessageID RADIUS_UDP_EXCHANGE_START
const isc::log::MessageID RADIUS_UDP_EXCHANGE_RECEIVED
const isc::log::MessageID RADIUS_UDP_EXCHANGE_RECEIVE_FAILED
const isc::log::MessageID RADIUS_TCP_EXCHANGE_FAILURE
RadiusProtocol
Transport protocols.
const isc::log::MessageID RADIUS_EXCHANGE_RECEIVED_ACCESS_ACCEPT
std::vector< ServerPtr > Servers
Type of RADIUS server collection.
boost::shared_ptr< Exchange > ExchangePtr
Type of shared pointers to RADIUS exchange object.
const isc::log::MessageID RADIUS_UDP_EXCHANGE_SEND_NEW
boost::shared_ptr< Server > ServerPtr
Type of shared pointers to a RADIUS server object.
string msgCodeToText(const uint8_t code)
MsgCode value -> name function.
const int RADIUS_DBG_TRACE
Radius logging levels.
const isc::log::MessageID RADIUS_EXCHANGE_RECEIVED_ACCOUNTING_RESPONSE
const isc::log::MessageID RADIUS_TCP_EXCHANGE_START_ERROR
const isc::log::MessageID RADIUS_TCP_EXCHANGE_RECEIVED
const isc::log::MessageID RADIUS_TCP_EXCHANGE_SUCCESS
const isc::log::MessageID RADIUS_REPLY_MESSAGE_ATTRIBUTE
const isc::log::MessageID RADIUS_UDP_EXCHANGE_TERMINATE
boost::shared_ptr< UdpExchange > UdpExchangePtr
Type of shared pointers to RADIUS/UDP exchange object.
const isc::log::MessageID RADIUS_TCP_EXCHANGE_SEND
isc::log::Logger radius_logger("radius-hooks")
Radius Logger.
boost::shared_ptr< Message > MessagePtr
Shared pointers to message.
const isc::log::MessageID RADIUS_TCP_EXCHANGE_RECEIVE_FAILED
const isc::log::MessageID RADIUS_EXCHANGE_RECEIVED_UNEXPECTED
const isc::log::MessageID RADIUS_EXCHANGE_RECEIVED_BAD_RESPONSE
const isc::log::MessageID RADIUS_EXCHANGE_RECEIVED_RESPONSE
const isc::log::MessageID RADIUS_TCP_EXCHANGE_START
const isc::log::MessageID RADIUS_UDP_EXCHANGE_TIMEOUT
const isc::log::MessageID RADIUS_UDP_EXCHANGE_SEND_FAILED
const isc::log::MessageID RADIUS_UDP_EXCHANGE_SENT
const isc::log::MessageID RADIUS_UDP_EXCHANGE_SEND_RETRY
std::vector< uint8_t > WireData
Defines a data structure for storing raw bytes of data on the wire.
boost::shared_ptr< WireData > WireDataPtr
Defines the logger used by the top-level component of kea-lfc.
TCP request/response timeout value.
RAII lock object to protect the code in the same scope with a mutex.