While it may be feasible to store on disk a record for each IPv4 address,
doing so for IPv6 addresses is definitely out of the question.  A single
/64 pool of addresses has 4 billions times the number of addresses of
the whole IPv4 space.  For that reason, doing ranges is a must.

Ranges are represented by setting a prefix length in the record data. 
They can be set either manually using ibd-ban, or automatically on 
storing a single IPv6 address among nearby ones.  The heuristic to do 
so provides for looking for neighbors.  To limit such search, the 
algorithm considers the number of times an IP or range was caught and 
the probability of it being blocked to determine an index.  The index 
points to an array of decreasing prefix sizes, for example /128, /64, 
/56, /48, /36, /32, /28, /24, /20, /12.  Recall that the larger the
prefix length the smaller the range.  The prefix length determined that
way is the allowed length.

If a neighbor is found such that a range that includes it and the ip or
range to be inserted has a prefix length not smaller than the allowed
length, a new range is created and the records for IP or ranges inside
it are deleted.

A range is also deleted when an IP or range to be set falls inside it,
but the allowed length of the range is smaller than the allowed length,
due to rehabilitation.  The existing range is considered stale and
deleted before inserting the new one.

The formula to calculate the index which leads to the allowed length
uses a logarithm in order to grow slowly:

    ndx = log2(factor * min(count, 5) * probability/RAND_MAX)

where the probability/RAND_MAX is the actual probability (taking 
decay into account), note that it is always less or equal to 1; factor
is a parameter and count is the number of times the IP or range was
caught, already incremented; that is, 1 for a new record.

Both the factor and the array of decreasing prefix sizes can be set at
compile time.  The variables are IPQBDB_INDEX_FACTOR and
IPQBDB_IPV6_RANGES respectively.  In addition, factor can be
overridden using options -f or --index-factor of ibd-ban and ibd-parse.

That heuristic is experimental.  The distribution includes a
logarithmic-growth.png which shows that ndx will hardly reach the value
of 6, corresponding to /28.  To visualize possible growths of ranges,
there is a TESTipv6 program, which produces .png files named after the
parameters passed.  Use its --help option to list them.

On disk, IPv6 records stay in different files, whose names are derived
from the IPv4 filename by appending a "6" to the basename.  The record
format is the same, and is the same as it was in version 1 of this
software.  That means version 2 can be installed over version 1
following the command sequence given in INSTALL.

The key field is the address, 4-byte for IPv4, 16-byte for IPv6. There 
is a 1-byte field in the record that stores the prefix length of a 
range expressed in CIDR notation.  This field is always 0 for IPv4 
record and for IPv6 sigle-address records.  On disk, the key field of a 
range is set to the last address (unlike CIDR notation).  This is done 
to take advantage of the DB_SET_RANGE flag of the DBcursor->get() 
function of the Berkeley DB.  This hack is invisible to normal users, 
as the key is converted to first address when displayed.

IPv4 mapped addresses, like ::ffff:192.0.2.3 and ::192.0.2.3, are stored
in the IPv4 database.


libmnl
https://netfilter.org/projects/libmnl/doxygen/html/
https://git.netfilter.org/libmnl/


Oracle Berkeley DB 1.81
https://docs.oracle.com/database/bdb181/books.htm
https://docs.oracle.com/database/bdb181/html/api_reference/C/index.html
https://docs.oracle.com/database/bdb181/html/programmer_reference/env.html
