I already coded a very similar thing before you posted this, however, as an integrated extension to SQLite3 so without the necessity to load an external lib (this is discouraged even by the SQLite3 developers themselves as it can open up security holes quite easily).
Just mentioning here that I already had some progress and, in fact, have an IPv4 version of this already working. The issue I was having yesterday is, however, that SQLIte3 does at maximum support 64 bit integers. While this is obviously sufficient to implement IPv4 subnetting (32 bit), it does result in an issue with IPv6 addresses (128 bit) as we cannot perform standard math such as BETWEEN on this kind of numbers.
I verified that the same issue exists as well when we prepare and store the 128 bit numbers themselves in the database. So what you proposed above is no alternative, either. Now we know this for sure.
This isn't a real show stopper, the comparison for IPv6 just gets a bit trickier. I'm re-implementing my function to do the entire checking internally so it only needs to return a boolean. We'd use my new sqlite3-internal subroutine like:
SELECT COUNT(*) FROM client WHERE check_subnet(ip, '127.0.0.1') = TRUE;
where ip automatically expands to the ip column data (may or may not contain a trailing /24, etc.) and '127.0.0.1' is some textual IP address provided by FTL. I'm coding this all in highly performance C code, so there should be no performance impact.
I pushed what I have so far. I'm running out of time now (already way beyond midnight over here), but you may want to do some initial testing on it. To ease possibly needed debugging, I added some very verbose logging (see /var/log/pihole-FTL.log) in the style of:
[2020-03-03 23:27:18.695 21965] Comparing database 127.0.0.0/8 (extracted CIDR: /8) to 192.168.2.223 - NO MATCH
[2020-03-03 23:27:18.695 21965] Comparing database 127.0.0.102 (extracted CIDR: /32) to 192.168.2.223 - NO MATCH
[2020-03-03 23:27:18.695 21965] Comparing database 127.0.0.103 (extracted CIDR: /32) to 192.168.2.223 - NO MATCH
[2020-03-03 23:27:18.695 21965] Comparing database 192.168.2.100 (extracted CIDR: /32) to 192.168.2.223 - NO MATCH
[2020-03-03 23:27:18.695 21965] Comparing database 192.168.2.2/24 (extracted CIDR: /24) to 192.168.2.223 - !!! MATCH !!!
or from localhost:
[2020-03-03 23:27:18.692 21965] Comparing database 127.0.0.0/8 (extracted CIDR: /8) to 127.0.0.1 - !!! MATCH !!!
[2020-03-03 23:27:18.692 21965] Comparing database 127.0.0.102 (extracted CIDR: /32) to 127.0.0.1 - NO MATCH
[2020-03-03 23:27:18.692 21965] Comparing database 127.0.0.103 (extracted CIDR: /32) to 127.0.0.1 - NO MATCH
[2020-03-03 23:27:18.692 21965] Comparing database 192.168.2.100 (extracted CIDR: /32) to 127.0.0.1 - NO MATCH
[2020-03-03 23:27:18.692 21965] Comparing database 192.168.2.2/24 (extracted CIDR: /24) to 127.0.0.1 - NO MATCH
[2020-03-03 23:27:18.692 21965] Comparing database 192.168.2.210 (extracted CIDR: /32) to 127.0.0.1 - NO MATCH
@troykelly As you can see, it seems to work for the few IPv4 clients I have configured in my network. However, I did not do any real testing. Any comments you may have, especially with IPv6 clients, would be appreciated!
Database client IPs are now allowed to be either in the "usual" format:
192.168.2.123
or in CIDR notation:
192.168.2.0/24
I wrote the code entirely general so every possible mask should be available, not only multiples of eight or something like that. Also, users should not be able to break anything as any invalid input should simply be skipped without consequences.
Subnetting support has now been merged into the beta and will be released with Pi-hole v5.0. Meanwhile, we added a client IP validation accepting a possible CIDR.
Please go back on the main beta testing using:
pihole checkout web release/v5.0
pihole checkout ftl release/v5.0
Thanks for using the Pi-hole and helping us make Pi-hole a better software for us all!
Well, let's rephrase this to: "[...] unable to add these IPv6 addresses."
Not unable in general.
For the validation algorithm I invented was for IPv6 addresses, I forgot about addresses with trailing :: without anything behind them.
We discussed this before in here, but missed this kind of valid address type.
I already modified our validator, would you mind doing some more testing to see if we prevent any further valid addresses?