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.