The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Net::Radius::Server::DBStore - Store Radius packets into a Tied Hash

SYNOPSIS

use MLDBM::Sync;
use MLDBM qw(DB_File Storable);
use Net::Radius::Server::DBStore;
use Net::Radius::Server::Base qw/:set/;

my $obj = Net::Radius::Server::DBStore->new
  ({
    log_level      => 4,
    param          => [ 'MLDBM::Sync', 
                        @Tie_Opts ],
    store          => [qw/packet peer_addr port/],
    pre_store_hook => sub { ... },
    sync           => 1,
    single         => 1,
    internal_tie   => 1,
    frozen         => 0,
    key_attrs      => [ 'Acct-Session-Id', [ Vendor => 'PrivateSession' ] ],
    hashref        => \%external_hash,
    result         => NRS_SET_CONTINUE,
  });

my $sub = $obj->mk();

# or

my $sub = Net::Radius::Server::DBStore->mk
  ({
  # ... same parameters as above ...
  });

DESCRIPTION

Net::Radius::Server::DBStore is a match or set method factory than can be used within Net::Radius::Server::Rule objects.

Note that this factory can produce either match or set methods. The only practical difference is the actual result to be returned, that defaults to NRS_SET_CONTINUE. This is so, as it is anticipated that the most common use for this class would be producing set methods, so that accounting packets can be stored after classification that can be made using corresponding match methods.

You can trivially replace the result to be returning by using the result key, as shown in the SYNOPSIS.

->new($hashref)

Creates a new Net::Radius::Server::DBStore(3) object that acts as aod factory. $hashref referenes a hash with the attributes that will apply to this object, so that multiple methods (that will share the same underlying object) can be created and given to different rules.

->mk($hashref)

Invokes ->new() passing the given $hashref if needed.

At this stage, an object-private hash is tied to the specified class (MLDBM::Sync(3) as in the SYNOPSIS), using the given flags. This hash is stored in the object and will be shared by any methods constructed from it.

This makes more efficient the case where you want to store information coming from various different rules, such as when matching for different types of service, more efficient.

->mk() then returns a method that is suitable to be employed as either a match or set method within a Net::Radius::Server::Rule object.

$self->mk() or __PACKAGE__->mk($hashref)

This method returns a sub suitable for calling as either a match or set method for a Net::Radius::Server::Rule object. The resulting sub will return NRS_SET_CONTINUE by default, unless overriden by the given configuration.

The sub contains a closure where the object attributes -- Actually, the object itself -- are kept.

When invoked as an object method (ie, $self->mk()), no arguments can be given. The object is preserved as is within the closure.

When invoked as a class method (ie, __PACKAGE__->mk($hashref)), a new object is created with the given arguments and then, this object is preserved within the closure. This form is useful for compact filter definitions that require little or no surrounding code or holding variables.

->_do_tie()

You're not supposed to call this method directly. It is called by the sub produced with ->mk(). Within this method, the following takes place:

  • The record key is calculated by using the corresponding configuration entry.

  • The requested information is stored in the tied hash, thus inserted in the underlying storage method.

  • The required return value is passed back to the caller.

Configuration Keys

The following configuration keys are understood by this class, in addition to the ones handled by Net::Radius::Server::Base(3). Note that those are available in the factory object (the one retured by the call to ->new()) as same-name accessors.

param => [ @args ]

The actual parameters to the tie. This parameter is mandatory. The first item in the @args list has to be the name of the class to tie. Tipically you will want to use MLDBM(3), MLDBM::Sync(3), BerkeleyDB::Hash(3) or Tie::DBI(3).

param => [ 'MLDBM::Sync', '/my/db/file.db' ],

Note that concurrency will be an issue. You need to insure that you use modules and settings that consider the fact that multiple instances will be writing at the same time.

key_attrs => [ @keys ]

Specify the Radius attributes to use as the record key for accessing the database. Each element of the list can be one of the following types:

Scalar

This is either an attribute name or a delimiter. Actually, any string is used to look up the corresponding attribute in the request packet. If this fails, the actual string is inserted as the value of the key. Upon success, the value of the corresponding attribute is inserted in the key.

sub or CODE ref

This sub will be called with the following arguments: The Net::Radius::Server::DBStore(3) object, the tied() object as returned by tie, a reference to the tied hash, a reference to the hash with data passed to the method and a Net::Radius::Packet(3) object with the decoded request this rule is responding to.

The return value of the sub will be inserted in the key.

This is useful to create hash keys that depend on information not within the actual Radius request.

ArrayRef

This is interpreted as a VSA. The first element of the given list encodes the vendor name. The second attribute encodes the vendor attribute name.

If the attribute is found within the request packet, its value is substituted at the current location of the key. Otherwise, an empty string will be substituted in its place.

The following example:

key_attrs => [ 'Acct-Session-Id', '|', [ Cisco => 'Foo' ] ]

Would produce a key like this:

DEADBEEF872374628742|

Or if the ficticious VSA was defined, something like

DEADBEEF872374628742|The_Value

The default attribute list is [ 'NAS-IP-Address', '|', 'Acct-Session-Id' ] which is likely to be suitable for Radius accounting packets. Note that RFC-2866 states that the Acct-Session-Id attribute is unique, but this is generally so within a single device. When multiple devices are served, there may be a chance of collision. Including the IP Address of the NAS helps solve the problem. You must review your own environment and insure that the given key will produce unique values for each session.

store => [ @items ]

Tells the method which pieces of information to store within the tied hash. This corresponds to the attributes that are passed to the actual method. You might want to take a look at Net::Radius::Server::NS(3) and Net::Radius::Server::Rule(3) for more information.

You should be conservative with this config entry, to store only as much information as needed. Note that you might be storing potentially sensitive information, such as user passwords, so appropiate care should be taken.

The dafault value for @items is packet, peer_addr, peer_host, peer_port, port. This default should avoid storing huge objects alongside the useful data.

Be aware that storing decoded packets (ie, including either request or response on the list of @items) will lead to storing the NAS shared secret and the dictionaries using to encode and decode the packets. This will be large.

pre_store_hook => $sub

This $sub will be called before actually calculating and storing in the BerkeleyDB(3) database. The following arguments are passed, in this order: The Net::Radius::Server::DBStore(3) object, the tied() object as returned, a reference to the tied hash, a reference to the hash with data passed to the method, a Net::Radius::Packet(3) object with the decoded request this rule is responding to and the calculated key for this entry.

The return value of the sub is currently ignored.

sync => $value

Causes a call to ->db_sync() after each insertion when $value evaluates to true, which is the default. When set to a false value, no calls will be made.

The call to ->db_sync() probably causes a performance hit.

single => $value

When set to true (the default), stores all the required elements as a single hash. When set to false, each tuple is stored individually within a hashref associated to the key.

frozen => $value

When set to true (the default), uses freeze() from Storable(3) to serialize the values prior to storing.

internal_tie => $value

When true, the default, tie() will be performed on the hash. In certain cases, you might want to "share" a hash. In these cases, the actual tying can be done elsewhere.

hashref => $hashref

Tells the factory to work with an external hash. This is useful to have external code modifying the underlying hash outside of a RADIUS transaction.

If not provided, each call to ->mk() ties a private hash. Note that you can use hashref in a call to ->new(), and then all the functions generated with ->mk() will share the same hash.

EXPORT

None by default.

BUGS

This code uses die() currently, however it is likely that croak() would be better. The problem with this, is that using croak() as intended, results in Perl returning errors like this one...

Bizarre copy of HASH in sassign 
    at /usr/share/perl/5.10/Carp/Heavy.pm line 96.

while running make test in my test machine. Since I don't want to run any risks, I'll stick to the die() calls which do not manipulate the stack so much.

SEE ALSO

Perl(1), BerkeleyDB(3), Class::Accessor(3), MLDBM(3), MLDBM::Sync(3), Net::Radius::Packet(3), Net::Radius::Server(3), Net::Radius::Server::Base(3), Net::Radius::Server::NS(3), Net::Radius::Server::Rule(3), Storable(3), Tie::DBI(3).

AUTHOR

Luis E. Muñoz, <luismunoz@cpan.org>

COPYRIGHT AND LICENSE

Copyright (C) 2006-2009 by Luis E. Muñoz

This library is free software; you can redistribute it and/or modify it under the terms of the GPL version 2.

1 POD Error

The following errors were encountered while parsing the POD:

Around line 480:

Non-ASCII character seen before =encoding in 'Muñoz,'. Assuming UTF-8