29using namespace boost::gregorian;
30using namespace boost::posix_time;
31namespace ph = std::placeholders;
96size_t RadiusAcctHandler::counter_ = 0;
98mutex RadiusAcctHandler::mutex_;
110 file_->addColumn(
"address");
111 file_->addColumn(
"seconds");
112 file_->addColumn(
"milliseconds");
114 if (
file_->exists()) {
123 }
catch (
const std::exception& ex) {
137 string hwaddr = lease->hwaddr_->toText(
false);
141 if (lease->client_id_) {
143 bool extracted =
false;
151 vec =
pop0(lease->client_id_);
153 vec = lease->client_id_->getClientId();
173 bool generate =
false;
180 ostringstream stream;
181 stream << lease->addr_.toText() <<
'@';
182 time_duration rtm(tm -
epoch_);
183 stream << rtm.total_seconds() <<
".";
184 rtm -= seconds(rtm.total_seconds());
185 stream << rtm.total_milliseconds();
202 vector<uint8_t> host_id;
205 host_id = lease->hwaddr_->hwaddr_;
208 if (lease->client_id_) {
209 host_id = lease->client_id_->getClientId();
210 if ((host_id.size() <= 5) ||
211 (host_id[0] != CLIENT_ID_OPTION_TYPE_DUID)) {
214 host_id = vector<uint8_t>(host_id.begin() + 5, host_id.end());
219 if (lease->client_id_) {
220 host_id = lease->client_id_->getClientId();
224 if (lease->client_id_) {
225 host_id = lease->client_id_->getClientId();
226 if ((host_id.size() <= 1) || (host_id[0] != 0)) {
229 host_id = vector<uint8_t>(host_id.begin() + 1, host_id.end());
240 if (!host_id.empty()) {
241 uint32_t subnet_id = lease->subnet_id_;
243 getCfgSubnets4()->getBySubnetId(subnet_id);
244 if (subnet && subnet->getReservationsGlobal()) {
245 subnet_id = SUBNET_ID_GLOBAL;
248 &host_id[0], host_id.size());
252 if (host && host->getContext() &&
263 RadiusAcctEnv env(stream.str(), event, lease->subnet_id_, send);
288 vec =
pop0(lease->duid_);
290 vec = lease->duid_->getDuid();
301 if (lease->hwaddr_) {
302 string hwaddr = lease->hwaddr_->toText(
false);
314 lease->prefixlen_, lease->addr_));
318 bool generate =
false;
325 ostringstream stream;
326 stream << lease->addr_.toText() <<
'@';
327 time_duration rtm(tm -
epoch_);
328 stream << rtm.total_seconds() <<
".";
329 rtm -= seconds(rtm.total_seconds());
330 stream << rtm.total_milliseconds();
347 vector<uint8_t> host_id;
350 host_id = lease->duid_->getDuid();
353 if (lease->hwaddr_) {
354 host_id = lease->hwaddr_->hwaddr_;
358 host_id = lease->duid_->getDuid();
359 if ((host_id.size() <= 2) ||
360 (host_id[0] != 0) || (host_id[1] != 0)) {
363 host_id = vector<uint8_t>(host_id.begin() + 2, host_id.end());
373 if (!host_id.empty()) {
374 uint32_t subnet_id = lease->subnet_id_;
376 getCfgSubnets6()->getBySubnetId(subnet_id);
377 if (subnet && subnet->getReservationsGlobal()) {
378 subnet_id = SUBNET_ID_GLOBAL;
381 &host_id[0], host_id.size());
385 if (host && host->getContext() &&
396 RadiusAcctEnv env(stream.str(), event, lease->subnet_id_, send);
417 uint32_t subnet_id = SUBNET_ID_UNUSED;
428 if (arguments->contains(
"client-id")) {
433 if (arguments->contains(
"force-create")) {
436 }
catch (
const std::exception&) {
447 string mac = hwaddr->toText(
false);
453 bool extracted =
false;
461 vec =
pop0(client_id);
463 vec = client_id->getClientId();
483 bool generate =
false;
490 ostringstream stream;
491 stream << addr <<
'@';
492 time_duration rtm(tm -
epoch_);
493 stream << rtm.total_seconds() <<
".";
494 rtm -= seconds(rtm.total_seconds());
495 stream << rtm.total_milliseconds();
509 vector<uint8_t> host_id;
512 host_id = hwaddr->hwaddr_;
516 host_id = client_id->getClientId();
517 if ((host_id.size() <= 5) ||
518 (host_id[0] != CLIENT_ID_OPTION_TYPE_DUID)) {
521 host_id = vector<uint8_t>(host_id.begin() + 5, host_id.end());
527 host_id = client_id->getClientId();
532 host_id = client_id->getClientId();
533 if ((host_id.size() <= 1) || (host_id[0] != 0)) {
536 host_id = vector<uint8_t>(host_id.begin() + 1, host_id.end());
547 if (!host_id.empty()) {
549 getCfgSubnets4()->getBySubnetId(subnet_id);
550 uint32_t host_subnet_id =
551 ((subnet && subnet->getReservationsGlobal()) ?
552 SUBNET_ID_GLOBAL : subnet_id);
554 &host_id[0], host_id.size());
558 if (host && host->getContext() &&
590 uint32_t subnet_id = SUBNET_ID_UNUSED;
594 uint8_t prefix_len = 128;
603 if (arguments->contains(
"hw-address")) {
608 if (arguments->contains(
"type")) {
610 if (txt ==
"IA_NA") {
612 }
else if (txt ==
"IA_PD") {
617 if ((prefix_len <= 0) || (prefix_len > 128)) {
619 "'prefix-len' value must be in range of [1..128]");
622 if (prefix_len != 128) {
624 if (first_address != addr) {
626 <<
" exceeds prefix/prefix-len pair: " << first_address
627 <<
"/" <<
static_cast<uint32_t
>(prefix_len));
635 if (arguments->contains(
"force-create")) {
638 }
catch (
const std::exception&) {
653 vec = duid->getDuid();
665 string mac = hwaddr->toText(
false);
681 bool generate =
false;
688 ostringstream stream;
689 stream << addr <<
'@';
690 time_duration rtm(tm -
epoch_);
691 stream << rtm.total_seconds() <<
".";
692 rtm -= seconds(rtm.total_seconds());
693 stream << rtm.total_milliseconds();
707 vector<uint8_t> host_id;
710 host_id = duid->getDuid();
714 host_id = hwaddr->hwaddr_;
718 host_id = duid->getDuid();
719 if ((host_id.size() <= 2) ||
720 (host_id[0] != 0) || (host_id[1] != 0)) {
723 host_id = vector<uint8_t>(host_id.begin() + 2, host_id.end());
733 if (!host_id.empty()) {
735 getCfgSubnets6()->getBySubnetId(subnet_id);
736 uint32_t host_subnet_id =
737 ((subnet && subnet->getReservationsGlobal()) ?
738 SUBNET_ID_GLOBAL : subnet_id);
740 &host_id[0], host_id.size());
744 if (host && host->getContext() &&
781 if (result !=
OK_RC) {
795 TMContainerAddressIndex::iterator it = idx.find(addr);
797 if (it == idx.end()) {
802 return (it->timestamp_);
807 while (it != idx.end()) {
812 ptime tm = microsec_clock::universal_time();
825 time_duration rtm(tm -
epoch_);
826 row.
writeAt(
file_->getColumnIndex(
"seconds"), rtm.total_seconds());
827 rtm -= seconds(rtm.total_seconds());
829 rtm.total_milliseconds());
833 }
catch (
const std::exception& ex) {
848 TMContainerAddressIndex::iterator it = idx.find(addr);
849 while (it != idx.end()) {
865 }
catch (
const std::exception& ex) {
885 file_->next(row,
true);
899 string addr_txt = row.
readAt(
file_->getColumnIndex(
"address"));
907 TMContainerAddressIndex::iterator it = idx.find(addr);
908 while (it != idx.end()) {
919 time_duration rtm (seconds(secs) + milliseconds(msecs));
930 }
catch (
const std::exception& ex) {
960 string backfilename =
filename_ +
".new~";
961 rename(newfilename.c_str(), backfilename.c_str());
968 for (
auto const& it : idx) {
972 time_duration rtm(it.timestamp_ -
epoch_);
974 rtm.total_seconds());
975 rtm -= seconds(rtm.total_seconds());
977 rtm.total_milliseconds());
987 string backfilename =
filename_ +
".bak";
989 if (rename(
filename_.c_str(), backfilename.c_str()) != 0) {
992 if (rename(newfilename.c_str(),
filename_.c_str()) != 0) {
995 rename(backfilename.c_str(),
filename_.c_str());
1002 }
catch (
const std::exception& ex) {
1021 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.