27using namespace boost::gregorian;
28using namespace boost::posix_time;
29namespace ph = std::placeholders;
94size_t RadiusAcctHandler::counter_ = 0;
96mutex RadiusAcctHandler::mutex_;
108 file_->addColumn(
"address");
109 file_->addColumn(
"seconds");
110 file_->addColumn(
"milliseconds");
112 if (
file_->exists()) {
121 }
catch (
const std::exception& ex) {
135 string hwaddr = lease->hwaddr_->toText(
false);
139 if (lease->client_id_) {
141 bool extracted =
false;
149 vec =
pop0(lease->client_id_);
151 vec = lease->client_id_->getClientId();
171 bool generate =
false;
178 ostringstream stream;
179 stream << lease->addr_.toText() <<
'@';
180 time_duration rtm(tm -
epoch_);
181 stream << rtm.total_seconds() <<
".";
182 rtm -= seconds(rtm.total_seconds());
183 stream << rtm.total_milliseconds();
200 vector<uint8_t> host_id;
203 host_id = lease->hwaddr_->hwaddr_;
206 if (lease->client_id_) {
207 host_id = lease->client_id_->getClientId();
208 if ((host_id.size() <= 5) ||
209 (host_id[0] != CLIENT_ID_OPTION_TYPE_DUID)) {
212 host_id = vector<uint8_t>(host_id.begin() + 5, host_id.end());
217 if (lease->client_id_) {
218 host_id = lease->client_id_->getClientId();
222 if (lease->client_id_) {
223 host_id = lease->client_id_->getClientId();
224 if ((host_id.size() <= 1) || (host_id[0] != 0)) {
227 host_id = vector<uint8_t>(host_id.begin() + 1, host_id.end());
238 if (!host_id.empty()) {
239 uint32_t subnet_id = lease->subnet_id_;
241 getCfgSubnets4()->getBySubnetId(subnet_id);
242 if (subnet && subnet->getReservationsGlobal()) {
243 subnet_id = SUBNET_ID_GLOBAL;
246 &host_id[0], host_id.size());
250 if (host && host->getContext() &&
261 RadiusAcctEnv env(stream.str(), event, lease->subnet_id_, send);
281 vec =
pop0(lease->duid_);
283 vec = lease->duid_->getDuid();
294 if (lease->hwaddr_) {
295 string hwaddr = lease->hwaddr_->toText(
false);
307 lease->prefixlen_, lease->addr_));
311 bool generate =
false;
318 ostringstream stream;
319 stream << lease->addr_.toText() <<
'@';
320 time_duration rtm(tm -
epoch_);
321 stream << rtm.total_seconds() <<
".";
322 rtm -= seconds(rtm.total_seconds());
323 stream << rtm.total_milliseconds();
340 vector<uint8_t> host_id;
343 host_id = lease->duid_->getDuid();
346 if (lease->hwaddr_) {
347 host_id = lease->hwaddr_->hwaddr_;
351 host_id = lease->duid_->getDuid();
352 if ((host_id.size() <= 2) ||
353 (host_id[0] != 0) || (host_id[1] != 0)) {
356 host_id = vector<uint8_t>(host_id.begin() + 2, host_id.end());
366 if (!host_id.empty()) {
367 uint32_t subnet_id = lease->subnet_id_;
369 getCfgSubnets6()->getBySubnetId(subnet_id);
370 if (subnet && subnet->getReservationsGlobal()) {
371 subnet_id = SUBNET_ID_GLOBAL;
374 &host_id[0], host_id.size());
378 if (host && host->getContext() &&
389 RadiusAcctEnv env(stream.str(), event, lease->subnet_id_, send);
405 uint32_t subnet_id = SUBNET_ID_UNUSED;
416 if (arguments->contains(
"client-id")) {
421 if (arguments->contains(
"force-create")) {
424 }
catch (
const std::exception&) {
435 string mac = hwaddr->toText(
false);
441 bool extracted =
false;
449 vec =
pop0(client_id);
451 vec = client_id->getClientId();
471 bool generate =
false;
478 ostringstream stream;
479 stream << addr <<
'@';
480 time_duration rtm(tm -
epoch_);
481 stream << rtm.total_seconds() <<
".";
482 rtm -= seconds(rtm.total_seconds());
483 stream << rtm.total_milliseconds();
497 vector<uint8_t> host_id;
500 host_id = hwaddr->hwaddr_;
504 host_id = client_id->getClientId();
505 if ((host_id.size() <= 5) ||
506 (host_id[0] != CLIENT_ID_OPTION_TYPE_DUID)) {
509 host_id = vector<uint8_t>(host_id.begin() + 5, host_id.end());
515 host_id = client_id->getClientId();
520 host_id = client_id->getClientId();
521 if ((host_id.size() <= 1) || (host_id[0] != 0)) {
524 host_id = vector<uint8_t>(host_id.begin() + 1, host_id.end());
535 if (!host_id.empty()) {
537 getCfgSubnets4()->getBySubnetId(subnet_id);
538 uint32_t host_subnet_id =
539 ((subnet && subnet->getReservationsGlobal()) ?
540 SUBNET_ID_GLOBAL : subnet_id);
542 &host_id[0], host_id.size());
546 if (host && host->getContext() &&
573 uint32_t subnet_id = SUBNET_ID_UNUSED;
577 uint8_t prefix_len = 128;
586 if (arguments->contains(
"hw-address")) {
591 if (arguments->contains(
"type")) {
593 if (txt ==
"IA_NA") {
595 }
else if (txt ==
"IA_TA") {
597 }
else if (txt ==
"IA_PD") {
602 if ((prefix_len <= 0) || (prefix_len > 128)) {
604 "'prefix-len' value must be in range of [1..128]");
607 if (prefix_len != 128) {
609 if (first_address != addr) {
611 <<
" exceeds prefix/prefix-len pair: " << first_address
612 <<
"/" <<
static_cast<uint32_t
>(prefix_len));
620 if (arguments->contains(
"force-create")) {
623 }
catch (
const std::exception&) {
638 vec = duid->getDuid();
650 string mac = hwaddr->toText(
false);
666 bool generate =
false;
673 ostringstream stream;
674 stream << addr <<
'@';
675 time_duration rtm(tm -
epoch_);
676 stream << rtm.total_seconds() <<
".";
677 rtm -= seconds(rtm.total_seconds());
678 stream << rtm.total_milliseconds();
692 vector<uint8_t> host_id;
695 host_id = duid->getDuid();
699 host_id = hwaddr->hwaddr_;
703 host_id = duid->getDuid();
704 if ((host_id.size() <= 2) ||
705 (host_id[0] != 0) || (host_id[1] != 0)) {
708 host_id = vector<uint8_t>(host_id.begin() + 2, host_id.end());
718 if (!host_id.empty()) {
720 getCfgSubnets6()->getBySubnetId(subnet_id);
721 uint32_t host_subnet_id =
722 ((subnet && subnet->getReservationsGlobal()) ?
723 SUBNET_ID_GLOBAL : subnet_id);
725 &host_id[0], host_id.size());
729 if (host && host->getContext() &&
761 if (result !=
OK_RC) {
775 TMContainerAddressIndex::iterator it = idx.find(addr);
777 if (it == idx.end()) {
782 return (it->timestamp_);
787 while (it != idx.end()) {
792 ptime tm = microsec_clock::universal_time();
805 time_duration rtm(tm -
epoch_);
806 row.
writeAt(
file_->getColumnIndex(
"seconds"), rtm.total_seconds());
807 rtm -= seconds(rtm.total_seconds());
809 rtm.total_milliseconds());
813 }
catch (
const std::exception& ex) {
828 TMContainerAddressIndex::iterator it = idx.find(addr);
829 while (it != idx.end()) {
845 }
catch (
const std::exception& ex) {
865 file_->next(row,
true);
879 string addr_txt = row.
readAt(
file_->getColumnIndex(
"address"));
887 TMContainerAddressIndex::iterator it = idx.find(addr);
888 while (it != idx.end()) {
899 time_duration rtm (seconds(secs) + milliseconds(msecs));
910 }
catch (
const std::exception& ex) {
940 string backfilename =
filename_ +
".new~";
941 rename(newfilename.c_str(), backfilename.c_str());
948 for (
auto const& it : idx) {
952 time_duration rtm(it.timestamp_ -
epoch_);
954 rtm.total_seconds());
955 rtm -= seconds(rtm.total_seconds());
957 rtm.total_milliseconds());
967 string backfilename =
filename_ +
".bak";
969 if (rename(
filename_.c_str(), backfilename.c_str()) != 0) {
972 if (rename(newfilename.c_str(),
filename_.c_str()) != 0) {
975 rename(backfilename.c_str(),
filename_.c_str());
982 }
catch (
const std::exception& ex) {
1001 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.
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.
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
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.
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.