IP pools with rlm_sql_mongo + some general testing with MongoDB

Benjamin Thompson b.thompson at latera.ru
Mon Feb 17 11:39:25 CET 2020

On 14/02/2020, Alan DeKok <aland at deployingradius.com> wrote:
> On Feb 14, 2020, at 10:07 AM, Benjamin Thompson <b.thompson at latera.ru>
> wrote:
>> Firstly, many thanks to all concerned for creatiing a MongoDB module.
>   That would largely be me.  :)

Thanks Alan.

>> 3) In my case I wanted to implement an IP pool with "sticky addresses"
>> based on a unique PPP username. One point to note is that the method
>> findAndModify() does not support sorting by an exact value. So for
>> example it cannot simulate something like "ORDER BY foo <> bar" which
>> is possible with other databases. In my case I decided to work around
>> this using two seperate requests: the first one does a lookup by exact
>> string to see if we can allocate the same IP, then if this does not
>> return anything do a second lookup and sort by expiry_time to find the
>> oldest free IP. Due to this I implemented all the database requests
>> directly in unlang directly in the authorize section instead of using
>> the sqlippool module.
>   Good!  FreeRADIUS can do just about anything. :)

In case it is useful to anyone else, I ended up with something like this:

update reply {
    &Framed-IP-Address := "%{sql: db.radippool.findAndModify({'query':
{'$and': [{'pool_name': '%{control:Pool-Name}'%}, {'pool_key':
'%{User-Name}'%}]%}, 'update': {'$set': {'expiry_time': {'$date':
{'$numberLong': '%{expr: (%l + 3600) * 1000}'%}%}, 'nas_ip':
'%{NAS-IP-Address}', 'calling_station_id':
'%{Calling-Station-Id}'%}%}, 'fields': {'_id': 0, 'value': 1%}%})}"
if (&reply:Framed-IP-Address !~
/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/) {
    update reply {
        &Framed-IP-Address := "%{sql:
db.radippool.findAndModify({'query': {'$and': [{'pool_name':
'%{control:Pool-Name}'%}, {'expiry_time': {'$lt': {'$date':
{'$numberLong': '%{expr: %l * 1000}'%}%}%}%}]%}, 'update': {'$set':
{'expiry_time': {'$date': {'$numberLong': '%{expr: (%l + 3600) *
1000}'%}%}, 'pool_key': '%{User-Name}', 'nas_ip': '%{NAS-IP-Address}',
'calling_station_id': '%{Calling-Station-Id}'%}%}, 'fields': {'_id':
0, 'value': 1%}%})}"

>> 4) I did at one point test the sqlippool module with a variation of
>> the above logic by calling one request in allocate_clear and another
>> in allocate_find. However for some reason I noticed that
>> allocate_clear was not geting called every time and somehow the server
>> was skipping it and calling allocate_find immediately. It could have
>> been a problem with my configuration so I will try to repocude the
>> problem if I get time.
>   Hmm... IIRC allocate_clear isn't called every time?  I think it's once a
> second.

Ahh that would explain it then. Thanks.

>   I think it's time to start pushing DHCP rather more aggressively. :)  We
> are faster than ISC, support more databases, have more configurable
> policies, etc.  The only thing we're missing is the ability to read the ISC
> config file format.

I do recommend FreeRADIUS to others (including for DHCP) and can't see
that anyone would go back to ISC after trying it. One thing though
which our clients are asking for more and more is DHCPv6  so on our
wishlist we are hoping that you will be get this in (v4) at some

Ben Thompson

More information about the Freeradius-Users mailing list