28using namespace boost::gregorian;
29using namespace boost::posix_time;
30namespace ph = std::placeholders;
95size_t RadiusAcctHandler::counter_ = 0;
97mutex RadiusAcctHandler::mutex_;
109 file_->addColumn(
"address");
110 file_->addColumn(
"seconds");
111 file_->addColumn(
"milliseconds");
113 if (
file_->exists()) {
122 }
catch (
const std::exception& ex) {
136 string hwaddr = lease->hwaddr_->toText(
false);
140 if (lease->client_id_) {
142 bool extracted =
false;
150 vec =
pop0(lease->client_id_);
152 vec = lease->client_id_->getClientId();
172 bool generate =
false;
179 ostringstream stream;
180 stream << lease->addr_.toText() <<
'@';
181 time_duration rtm(tm -
epoch_);
182 stream << rtm.total_seconds() <<
".";
183 rtm -= seconds(rtm.total_seconds());
184 stream << rtm.total_milliseconds();
201 vector<uint8_t> host_id;
204 host_id = lease->hwaddr_->hwaddr_;
207 if (lease->client_id_) {
208 host_id = lease->client_id_->getClientId();
209 if ((host_id.size() <= 5) ||
210 (host_id[0] != CLIENT_ID_OPTION_TYPE_DUID)) {
213 host_id = vector<uint8_t>(host_id.begin() + 5, host_id.end());
218 if (lease->client_id_) {
219 host_id = lease->client_id_->getClientId();
223 if (lease->client_id_) {
224 host_id = lease->client_id_->getClientId();
225 if ((host_id.size() <= 1) || (host_id[0] != 0)) {
228 host_id = vector<uint8_t>(host_id.begin() + 1, host_id.end());
239 if (!host_id.empty()) {
240 uint32_t subnet_id = lease->subnet_id_;
242 getCfgSubnets4()->getBySubnetId(subnet_id);
243 if (subnet && subnet->getReservationsGlobal()) {
244 subnet_id = SUBNET_ID_GLOBAL;
247 &host_id[0], host_id.size());
251 if (host && host->getContext() &&
262 RadiusAcctEnv env(stream.str(), event, lease->subnet_id_, send);
287 vec =
pop0(lease->duid_);
289 vec = lease->duid_->getDuid();
300 if (lease->hwaddr_) {
301 string hwaddr = lease->hwaddr_->toText(
false);
313 lease->prefixlen_, lease->addr_));
317 bool generate =
false;
324 ostringstream stream;
325 stream << lease->addr_.toText() <<
'@';
326 time_duration rtm(tm -
epoch_);
327 stream << rtm.total_seconds() <<
".";
328 rtm -= seconds(rtm.total_seconds());
329 stream << rtm.total_milliseconds();
346 vector<uint8_t> host_id;
349 host_id = lease->duid_->getDuid();
352 if (lease->hwaddr_) {
353 host_id = lease->hwaddr_->hwaddr_;
357 host_id = lease->duid_->getDuid();
358 if ((host_id.size() <= 2) ||
359 (host_id[0] != 0) || (host_id[1] != 0)) {
362 host_id = vector<uint8_t>(host_id.begin() + 2, host_id.end());
372 if (!host_id.empty()) {
373 uint32_t subnet_id = lease->subnet_id_;
375 getCfgSubnets6()->getBySubnetId(subnet_id);
376 if (subnet && subnet->getReservationsGlobal()) {
377 subnet_id = SUBNET_ID_GLOBAL;
380 &host_id[0], host_id.size());
384 if (host && host->getContext() &&
395 RadiusAcctEnv env(stream.str(), event, lease->subnet_id_, send);
416 uint32_t subnet_id = SUBNET_ID_UNUSED;
427 if (arguments->contains(
"client-id")) {
432 if (arguments->contains(
"force-create")) {
435 }
catch (
const std::exception&) {
446 string mac = hwaddr->toText(
false);
452 bool extracted =
false;
460 vec =
pop0(client_id);
462 vec = client_id->getClientId();
482 bool generate =
false;
489 ostringstream stream;
490 stream << addr <<
'@';
491 time_duration rtm(tm -
epoch_);
492 stream << rtm.total_seconds() <<
".";
493 rtm -= seconds(rtm.total_seconds());
494 stream << rtm.total_milliseconds();
508 vector<uint8_t> host_id;
511 host_id = hwaddr->hwaddr_;
515 host_id = client_id->getClientId();
516 if ((host_id.size() <= 5) ||
517 (host_id[0] != CLIENT_ID_OPTION_TYPE_DUID)) {
520 host_id = vector<uint8_t>(host_id.begin() + 5, host_id.end());
526 host_id = client_id->getClientId();
531 host_id = client_id->getClientId();
532 if ((host_id.size() <= 1) || (host_id[0] != 0)) {
535 host_id = vector<uint8_t>(host_id.begin() + 1, host_id.end());
546 if (!host_id.empty()) {
548 getCfgSubnets4()->getBySubnetId(subnet_id);
549 uint32_t host_subnet_id =
550 ((subnet && subnet->getReservationsGlobal()) ?
551 SUBNET_ID_GLOBAL : subnet_id);
553 &host_id[0], host_id.size());
557 if (host && host->getContext() &&
589 uint32_t subnet_id = SUBNET_ID_UNUSED;
593 uint8_t prefix_len = 128;
602 if (arguments->contains(
"hw-address")) {
607 if (arguments->contains(
"type")) {
609 if (txt ==
"IA_NA") {
611 }
else if (txt ==
"IA_PD") {
616 if ((prefix_len <= 0) || (prefix_len > 128)) {
618 "'prefix-len' value must be in range of [1..128]");
621 if (prefix_len != 128) {
623 if (first_address != addr) {
625 <<
" exceeds prefix/prefix-len pair: " << first_address
626 <<
"/" <<
static_cast<uint32_t
>(prefix_len));
634 if (arguments->contains(
"force-create")) {
637 }
catch (
const std::exception&) {
652 vec = duid->getDuid();
664 string mac = hwaddr->toText(
false);
680 bool generate =
false;
687 ostringstream stream;
688 stream << addr <<
'@';
689 time_duration rtm(tm -
epoch_);
690 stream << rtm.total_seconds() <<
".";
691 rtm -= seconds(rtm.total_seconds());
692 stream << rtm.total_milliseconds();
706 vector<uint8_t> host_id;
709 host_id = duid->getDuid();
713 host_id = hwaddr->hwaddr_;
717 host_id = duid->getDuid();
718 if ((host_id.size() <= 2) ||
719 (host_id[0] != 0) || (host_id[1] != 0)) {
722 host_id = vector<uint8_t>(host_id.begin() + 2, host_id.end());
732 if (!host_id.empty()) {
734 getCfgSubnets6()->getBySubnetId(subnet_id);
735 uint32_t host_subnet_id =
736 ((subnet && subnet->getReservationsGlobal()) ?
737 SUBNET_ID_GLOBAL : subnet_id);
739 &host_id[0], host_id.size());
743 if (host && host->getContext() &&
780 if (result !=
OK_RC) {
794 TMContainerAddressIndex::iterator it = idx.find(addr);
796 if (it == idx.end()) {
801 return (it->timestamp_);
806 while (it != idx.end()) {
811 ptime tm = microsec_clock::universal_time();
824 time_duration rtm(tm -
epoch_);
825 row.
writeAt(
file_->getColumnIndex(
"seconds"), rtm.total_seconds());
826 rtm -= seconds(rtm.total_seconds());
828 rtm.total_milliseconds());
832 }
catch (
const std::exception& ex) {
847 TMContainerAddressIndex::iterator it = idx.find(addr);
848 while (it != idx.end()) {
864 }
catch (
const std::exception& ex) {
884 file_->next(row,
true);
898 string addr_txt = row.
readAt(
file_->getColumnIndex(
"address"));
906 TMContainerAddressIndex::iterator it = idx.find(addr);
907 while (it != idx.end()) {
918 time_duration rtm (seconds(secs) + milliseconds(msecs));
929 }
catch (
const std::exception& ex) {
959 string backfilename =
filename_ +
".new~";
960 rename(newfilename.c_str(), backfilename.c_str());
967 for (
auto const& it : idx) {
971 time_duration rtm(it.timestamp_ -
epoch_);
973 rtm.total_seconds());
974 rtm -= seconds(rtm.total_seconds());
976 rtm.total_milliseconds());
986 string backfilename =
filename_ +
".bak";
988 if (rename(
filename_.c_str(), backfilename.c_str()) != 0) {
991 if (rename(newfilename.c_str(),
filename_.c_str()) != 0) {
994 rename(backfilename.c_str(),
filename_.c_str());
1001 }
catch (
const std::exception& ex) {
1020 if (secs > 24*60*60) {
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.
The IntervalTimer class is a wrapper for the ASIO boost::asio::system_timer class.
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.
void setIdleTimer()
Set idle timer.
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.
static void IdleTimerCallback()
Idle timer callback.
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 communication with accounting servers.
class for asynchronous accounting communication with servers.
dhcp::Host::IdentifierType id_type4_
Identifier type for IPv4.
void registerExchange(ExchangePtr exchange)
Register Exchange.
dhcp::Host::IdentifierType id_type6_
Identifier type for IPv6.
static RadiusImpl & instance()
RadiusImpl is a singleton class.
RadiusService(const std::string &name)
Constructor.
asiolink::IntervalTimerPtr idle_timer_
Idle timer.
long idle_timer_interval_
Idle timer interval in seconds.
void cancelIdleTimer()
Cancel idle timer.
static std::mutex idle_timer_mutex_
Idle timer mutex.
static size_t exchangeListMaxSize
Exchange List Maximum Size (currently the max(200,soft_limit/2)).
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
string exchangeRCtoText(const int rc)
ExchangeRC value -> name function.
Event
Type of accounting events.
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.
const isc::log::MessageID RADIUS_UDP_EXCHANGE_MAX_PENDING
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
boost::shared_ptr< RadiusAcctStatus > RadiusAcctStatusPtr
Pointer to accounting status.
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.
string dumpAsHex(const uint8_t *data, size_t length)
Dumps a buffer of bytes as a string of hexadecimal digits.
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_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.