26using namespace boost::gregorian;
27using namespace boost::posix_time;
28namespace ph = std::placeholders;
93size_t RadiusAcctHandler::counter_ = 0;
95mutex RadiusAcctHandler::mutex_;
107 file_->addColumn(
"address");
108 file_->addColumn(
"seconds");
109 file_->addColumn(
"milliseconds");
111 if (
file_->exists()) {
120 }
catch (
const std::exception& ex) {
134 string hwaddr = lease->hwaddr_->toText(
false);
138 if (lease->client_id_) {
140 bool extracted =
false;
148 vec =
pop0(lease->client_id_);
150 vec = lease->client_id_->getClientId();
170 bool generate =
false;
177 ostringstream stream;
178 stream << lease->addr_.toText() <<
'@';
179 time_duration rtm(tm -
epoch_);
180 stream << rtm.total_seconds() <<
".";
181 rtm -= seconds(rtm.total_seconds());
182 stream << rtm.total_milliseconds();
199 vector<uint8_t> host_id;
202 host_id = lease->hwaddr_->hwaddr_;
205 if (lease->client_id_) {
206 host_id = lease->client_id_->getClientId();
207 if ((host_id.size() <= 5) ||
208 (host_id[0] != CLIENT_ID_OPTION_TYPE_DUID)) {
211 host_id = vector<uint8_t>(host_id.begin() + 5, host_id.end());
216 if (lease->client_id_) {
217 host_id = lease->client_id_->getClientId();
221 if (lease->client_id_) {
222 host_id = lease->client_id_->getClientId();
223 if ((host_id.size() <= 1) || (host_id[0] != 0)) {
226 host_id = vector<uint8_t>(host_id.begin() + 1, host_id.end());
237 if (!host_id.empty()) {
238 uint32_t subnet_id = lease->subnet_id_;
240 getCfgSubnets4()->getBySubnetId(subnet_id);
241 if (subnet && subnet->getReservationsGlobal()) {
242 subnet_id = SUBNET_ID_GLOBAL;
245 &host_id[0], host_id.size());
249 if (host && host->getContext() &&
260 RadiusAcctEnv env(stream.str(), event, lease->subnet_id_, send);
280 vec =
pop0(lease->duid_);
282 vec = lease->duid_->getDuid();
293 if (lease->hwaddr_) {
294 string hwaddr = lease->hwaddr_->toText(
false);
306 lease->prefixlen_, lease->addr_));
310 bool generate =
false;
317 ostringstream stream;
318 stream << lease->addr_.toText() <<
'@';
319 time_duration rtm(tm -
epoch_);
320 stream << rtm.total_seconds() <<
".";
321 rtm -= seconds(rtm.total_seconds());
322 stream << rtm.total_milliseconds();
339 vector<uint8_t> host_id;
342 host_id = lease->duid_->getDuid();
345 if (lease->hwaddr_) {
346 host_id = lease->hwaddr_->hwaddr_;
350 host_id = lease->duid_->getDuid();
351 if ((host_id.size() <= 2) ||
352 (host_id[0] != 0) || (host_id[1] != 0)) {
355 host_id = vector<uint8_t>(host_id.begin() + 2, host_id.end());
365 if (!host_id.empty()) {
366 uint32_t subnet_id = lease->subnet_id_;
368 getCfgSubnets6()->getBySubnetId(subnet_id);
369 if (subnet && subnet->getReservationsGlobal()) {
370 subnet_id = SUBNET_ID_GLOBAL;
373 &host_id[0], host_id.size());
377 if (host && host->getContext() &&
388 RadiusAcctEnv env(stream.str(), event, lease->subnet_id_, send);
404 uint32_t subnet_id = SUBNET_ID_UNUSED;
415 if (arguments->contains(
"client-id")) {
420 if (arguments->contains(
"force-create")) {
423 }
catch (
const std::exception&) {
434 string mac = hwaddr->toText(
false);
440 bool extracted =
false;
448 vec =
pop0(client_id);
450 vec = client_id->getClientId();
470 bool generate =
false;
477 ostringstream stream;
478 stream << addr <<
'@';
479 time_duration rtm(tm -
epoch_);
480 stream << rtm.total_seconds() <<
".";
481 rtm -= seconds(rtm.total_seconds());
482 stream << rtm.total_milliseconds();
496 vector<uint8_t> host_id;
499 host_id = hwaddr->hwaddr_;
503 host_id = client_id->getClientId();
504 if ((host_id.size() <= 5) ||
505 (host_id[0] != CLIENT_ID_OPTION_TYPE_DUID)) {
508 host_id = vector<uint8_t>(host_id.begin() + 5, host_id.end());
514 host_id = client_id->getClientId();
519 host_id = client_id->getClientId();
520 if ((host_id.size() <= 1) || (host_id[0] != 0)) {
523 host_id = vector<uint8_t>(host_id.begin() + 1, host_id.end());
534 if (!host_id.empty()) {
536 getCfgSubnets4()->getBySubnetId(subnet_id);
537 uint32_t host_subnet_id =
538 ((subnet && subnet->getReservationsGlobal()) ?
539 SUBNET_ID_GLOBAL : subnet_id);
541 &host_id[0], host_id.size());
545 if (host && host->getContext() &&
572 uint32_t subnet_id = SUBNET_ID_UNUSED;
576 uint8_t prefix_len = 128;
585 if (arguments->contains(
"hw-address")) {
590 if (arguments->contains(
"type")) {
592 if (txt ==
"IA_NA") {
594 }
else if (txt ==
"IA_TA") {
596 }
else if (txt ==
"IA_PD") {
601 if ((prefix_len <= 0) || (prefix_len > 128)) {
603 "'prefix-len' value must be in range of [1..128]");
606 if (prefix_len != 128) {
608 if (first_address != addr) {
610 <<
" exceeds prefix/prefix-len pair: " << first_address
611 <<
"/" <<
static_cast<uint32_t
>(prefix_len));
619 if (arguments->contains(
"force-create")) {
622 }
catch (
const std::exception&) {
637 vec = duid->getDuid();
649 string mac = hwaddr->toText(
false);
665 bool generate =
false;
672 ostringstream stream;
673 stream << addr <<
'@';
674 time_duration rtm(tm -
epoch_);
675 stream << rtm.total_seconds() <<
".";
676 rtm -= seconds(rtm.total_seconds());
677 stream << rtm.total_milliseconds();
691 vector<uint8_t> host_id;
694 host_id = duid->getDuid();
698 host_id = hwaddr->hwaddr_;
702 host_id = duid->getDuid();
703 if ((host_id.size() <= 2) ||
704 (host_id[0] != 0) || (host_id[1] != 0)) {
707 host_id = vector<uint8_t>(host_id.begin() + 2, host_id.end());
717 if (!host_id.empty()) {
719 getCfgSubnets6()->getBySubnetId(subnet_id);
720 uint32_t host_subnet_id =
721 ((subnet && subnet->getReservationsGlobal()) ?
722 SUBNET_ID_GLOBAL : subnet_id);
724 &host_id[0], host_id.size());
728 if (host && host->getContext() &&
760 if (result !=
OK_RC) {
774 TMContainerAddressIndex::iterator it = idx.find(addr);
776 if (it == idx.end()) {
781 return (it->timestamp_);
786 while (it != idx.end()) {
791 ptime tm = microsec_clock::universal_time();
804 time_duration rtm(tm -
epoch_);
805 row.
writeAt(
file_->getColumnIndex(
"seconds"), rtm.total_seconds());
806 rtm -= seconds(rtm.total_seconds());
808 rtm.total_milliseconds());
812 }
catch (
const std::exception& ex) {
827 TMContainerAddressIndex::iterator it = idx.find(addr);
828 while (it != idx.end()) {
844 }
catch (
const std::exception& ex) {
864 file_->next(row,
true);
878 string addr_txt = row.
readAt(
file_->getColumnIndex(
"address"));
886 TMContainerAddressIndex::iterator it = idx.find(addr);
887 while (it != idx.end()) {
898 time_duration rtm (seconds(secs) + milliseconds(msecs));
909 }
catch (
const std::exception& ex) {
939 string backfilename =
filename_ +
".new~";
940 rename(newfilename.c_str(), backfilename.c_str());
947 for (
auto const& it : idx) {
951 time_duration rtm(it.timestamp_ -
epoch_);
953 rtm.total_seconds());
954 rtm -= seconds(rtm.total_seconds());
956 rtm.total_milliseconds());
966 string backfilename =
filename_ +
".bak";
968 if (rename(
filename_.c_str(), backfilename.c_str()) != 0) {
971 if (rename(newfilename.c_str(),
filename_.c_str()) != 0) {
974 rename(backfilename.c_str(),
filename_.c_str());
981 }
catch (
const std::exception& ex) {
static DUID fromText(const std::string &text)
Create DUID from the textual format.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
The IOAddress class represents an IP addresses (version agnostic)
std::string toText() const
Convert the address to a string.
bool isV6() const
Convenience function to check for an IPv6 address.
bool isV4() const
Convenience function to check for an IPv4 address.
static isc::asiolink::IOAddress getAddress(const ConstElementPtr &scope, const std::string &name)
Returns a IOAddress parameter from a scope.
static std::string getString(isc::data::ConstElementPtr scope, const std::string &name)
Returns a string parameter from a scope.
static bool getBoolean(isc::data::ConstElementPtr scope, const std::string &name)
Returns a boolean parameter from a scope.
static int64_t getInteger(isc::data::ConstElementPtr scope, const std::string &name)
Returns an integer parameter from a scope.
static CfgMgr & instance()
returns a single instance of Configuration Manager
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
static ClientIdPtr fromText(const std::string &text)
Create client identifier from the textual format.
Holds DUID (DHCPv6 Unique Identifier)
ConstHostPtr get6Any(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len, const HostMgrOperationTarget target) const
Returns any host connected to the IPv6 subnet.
ConstHostPtr get4Any(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len, const HostMgrOperationTarget target) const
Returns any host connected to the IPv4 subnet.
static HostMgr & instance()
Returns a sole instance of the HostMgr.
IdentifierType
Type of the host identifier.
@ IDENT_FLEX
Flexible host identifier.
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 fromString(const uint8_t type, const std::string &value)
From type specific factories.
static AttributePtr fromIpv6Prefix(const uint8_t type, const uint8_t len, const asiolink::IOAddress &value)
From IPv6 prefix with type.
static AttributePtr fromIpv6Addr(const uint8_t type, const asiolink::IOAddress &value)
From IPv6 address with type.
Collection of attributes.
ConstAttributePtr get(const uint8_t type) const
Get instance of the attribute in the collection.
static Attributes fromElement(const data::ConstElementPtr &attr_list)
Parse collection.
RadiusAcctHandlerPtr buildAcct6(const data::ConstElementPtr &arguments, Event event)
Build RadiusAcct handler for Accounting-Request.
TMContainer container_
The Create timestamp container which holds session history.
RadiusAcctHandlerPtr buildAcct4(const data::ConstElementPtr &arguments, Event event)
Build RadiusAcct handler for Accounting-Request.
void eraseCreateTimestamp(const asiolink::IOAddress &addr)
Erase create-timestamp entry to session history.
CSVFilePtr file_
Pointer to the CSVFile.
void init(const std::string &filename)
Initialize.
bool loadFromFile()
Load create-timestamp entries from file.
static void runAsync(RadiusAcctHandlerPtr handler)
Run asynchronously.
std::mutex mutex_
Mutex to protect access to container_ and file_.
RadiusAccounting()
Constructor.
void storeToFile()
Store create-timestamp entries to a file.
size_t record_count_
New record counter.
RadiusAcctHandlerPtr buildAcct(const dhcp::Lease4Ptr &lease, Event event)
Build RadiusAcct handler for Accounting-Request - IPv4.
static void terminate(RadiusAcctEnv env, int result)
Termination callback.
const boost::posix_time::ptime epoch_
Epoch to avoid too long values.
boost::posix_time::ptime getCreateTimestamp(const asiolink::IOAddress &addr, bool generate)
Get lease create-timestamp entry from session history.
std::string filename_
Create timestamps file name.
Class of Radius accounting environments.
RadiusAcctEnv(std::string session_id, Event event, uint32_t subnet_id, AttributesPtr send_attrs)
Constructor.
std::string session_id_
Session Id.
bool finished_
Termination flag.
AttributesPtr send_attrs_
Attributes to send.
uint32_t subnet_id_
Subnet Id (aka client/NAS port).
Class of Radius accounting communication handler.
RadiusAcctHandler(RadiusAcctEnv env, const CallbackAcct &callback)
Constructor.
static size_t getCounter()
Get instance counter.
RadiusAcctEnv env_
Environment.
void start()
Start communication.
virtual ~RadiusAcctHandler()
Destructor.
RadiusAsyncAcctPtr acct_
Pointer to the communication class.
class for asynchronous accounting communication with servers.
dhcp::Host::IdentifierType id_type4_
Identifier type for IPv4.
dhcp::Host::IdentifierType id_type6_
Identifier type for IPv6.
static RadiusImpl & instance()
RadiusImpl is a singleton class.
RadiusService(const std::string &name)
Constructor.
Exception thrown when an error occurs during CSV file processing.
Provides input/output access to CSV files.
void close()
Closes the CSV file.
size_t getColumnCount() const
Returns the number of columns in the file.
bool exists() const
Checks if the CSV file exists and can be opened for reading.
static CSVRow EMPTY_ROW()
Represents empty row.
void append(const CSVRow &row) const
Writes the CSV row into the file.
void addColumn(const std::string &col_name)
Adds new column name.
size_t getColumnIndex(const std::string &col_name) const
Returns the index of the column having specified name.
virtual void open(const bool seek_to_end=false)
Opens existing file or creates a new one.
Represents a single row of the CSV file.
T readAndConvertAt(const size_t at) const
Retrieves a value from the internal container.
void writeAt(const size_t at, const char *value)
Replaces the value at specified index.
std::string readAt(const size_t at) const
Retrieves a value from the internal container.
#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_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
IOAddress firstAddrInPrefix(const IOAddress &prefix, uint8_t len)
This code is based on similar code from the Dibbler project.
boost::shared_ptr< const Element > ConstElementPtr
boost::shared_ptr< const Subnet6 > ConstSubnet6Ptr
A const pointer to a Subnet6 object.
boost::shared_ptr< const Subnet4 > ConstSubnet4Ptr
A const pointer to a Subnet4 object.
boost::shared_ptr< DUID > DuidPtr
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
boost::shared_ptr< ClientId > ClientIdPtr
Shared pointer to a Client ID.
boost::shared_ptr< const Host > ConstHostPtr
Const pointer to the Host object.
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
boost::shared_ptr< RadiusAcctHandler > RadiusAcctHandlerPtr
Type of pointers to Radius accounting communication handler.
@ PW_DELEGATED_IPV6_PREFIX
ipv6prefix.
@ PW_FRAMED_IP_ADDRESS
ipaddr.
@ PW_CALLING_STATION_ID
string.
@ PW_ACCT_STATUS_TYPE
integer.
@ PW_ACCT_SESSION_ID
string.
@ PW_FRAMED_IPV6_ADDRESS
ipv6addr.
vector< uint8_t > extractDuid(const ClientIdPtr &client_id, bool &extracted)
Extract the duid from a RFC 4361 compliant DHCPv4 client ID.
const isc::log::MessageID RADIUS_ACCOUNTING_ERROR
string canonize(const string &hexdump)
Canonize hardware address textual representation.
const isc::log::MessageID RADIUS_SESSION_HISTORY_STORE_FAILED
TMContainer::index< TMAddressIndexTag >::type TMContainerAddressIndex
First index type in the TMContainer.
boost::shared_ptr< Attributes > AttributesPtr
Shared pointers to attribute collection.
const isc::log::MessageID RADIUS_SESSION_HISTORY_OPEN_FAILED
std::function< void(int)> CallbackAcct
Type of callback for accounting termination.
TMContainer::index< TMTimestampIndexTag >::type TMContainerTimestampIndex
Second index type in the TMContainer.
const isc::log::MessageID RADIUS_SESSION_HISTORY_LOADED
Event
Type of accounting events.
string exchangeRCtoText(const int rc)
ExchangeRC value -> name function.
const int RADIUS_DBG_TRACE
Radius logging levels.
const isc::log::MessageID RADIUS_ACCOUNTING_HISTORY_UPDATE_FAILED
const isc::log::MessageID RADIUS_SESSION_HISTORY_APPEND_FAILED
string toPrintable(const vector< uint8_t > &content)
Return printable textual representation of a vector.
string toHex(const vector< uint8_t > &content)
Return hexadecimal textual representation of a vector.
const isc::log::MessageID RADIUS_SESSION_HISTORY_STORED
isc::log::Logger radius_logger("radius-hooks")
Radius Logger.
const isc::log::MessageID RADIUS_SESSION_HISTORY_OPENED
vector< uint8_t > pop0(const ClientIdPtr &client_id)
Pop leading zero in a DHCPv4 client-id.
const isc::log::MessageID RADIUS_SESSION_HISTORY_LOAD_FAILED
const isc::log::MessageID RADIUS_ACCOUNTING_NO_HISTORY
string eventToText(Event event)
Translate an event to text.
Defines the logger used by the top-level component of kea-lfc.
Hardware type that represents information from DHCPv4 packet.
static HWAddr fromText(const std::string &text, const uint16_t htype=HTYPE_ETHER)
Creates instance of the hardware address from textual format.
Type
Type of lease or pool.
@ TYPE_TA
the lease contains temporary IPv6 address
@ TYPE_PD
the lease contains IPv6 prefix (for prefix delegation)
@ TYPE_NA
the lease contains non-temporary IPv6 address
Tag for the index for searching by address.
Tag for the index for searching by timestamp.
RAII lock object to protect the code in the same scope with a mutex.