Use list=blocks to return all single IP blocks in a CIDR
Open, Needs TriagePublic

Description

Problem
To find all the single IP blocks in a given CIDR using query&list=blocks you need to pass all possible IP addresses.

Feature request
Extending on the functionality of blocks&bkip= (which returns a result only if the queried CIDR falls within an existing blocked range), we should also return all single IP blocks in a provided CIDR.

Example
https://en.wikipedia.org/w/api.php?action=query&format=json&list=blocks&bkip=170.24.138.0/24 would return all single IP blocks in the CIDR 170.24.138.0/24 as;

{
	"batchcomplete": "",
	"query": {
		"blocks": [{
			"id": 8067923,
			"user": "170.24.138.57",
			"by": "Gilliam",
			"timestamp": "2017-12-13T06:28:59Z",
			"expiry": "2017-12-20T06:28:59Z",
			"reason": "{{school block}}",
			"anononly": "",
			"nocreate": "",
			"allowusertalk": ""
		}, {
			"id": 8083937,
			"user": "170.24.138.53",
			"by": "Oshwah",
			"timestamp": "2017-12-19T19:37:20Z",
			"expiry": "2018-01-19T19:37:20Z",
			"reason": "{{school block}}",
			"anononly": "",
			"nocreate": "",
			"allowusertalk": ""
		}]
	}
}
Samtar created this task.Dec 19 2017, 9:58 PM
Restricted Application added a subscriber: Aklapper. · View Herald TranscriptDec 19 2017, 9:58 PM
Samtar updated the task description. (Show Details)Dec 19 2017, 10:00 PM
Anomie added a subscriber: Anomie.Dec 20 2017, 2:54 PM

Extending on the functionality of blocks&bkip= (which returns a result only if the queried CIDR falls within an existing blocked range), we should also return all single IP blocks in a provided CIDR.

That would be confusing. bkip should either return all blocks that apply to the passed IP or range, or all blocks contained in the passed IP or range. Since it already does the former, we shouldn't add the latter behavior.

Instead a new parameter should be added for the new functionality of requesting all blocks contained within a CIDR range.

Anomie moved this task from Unsorted to Needs Code on the MediaWiki-API board.Dec 20 2017, 2:55 PM

Hmm. If T51504: ipb_range_start and ipb_range_end should be blank for single-IP blocks is done, I think I'll have to decline this task since the necessary database query would become nontrivial.

TK-999 added a subscriber: TK-999.Mar 20 2018, 1:40 PM

I was thinking that it might help with this task, if we separated concerns between the ipblocks.ipb_user and ipblocks.ipb_address fields:

-- Blocked IP address in dotted-quad form or user name.
ipb_address tinyblob NOT NULL,

-- Blocked user ID or 0 for IP blocks.
ipb_user int unsigned NOT NULL default 0,

Currently when we are checking the blocked status of a logged in user, we query based on the user name, not the user ID. This behavior could be adjusted to use the user ID and the ipb_user field instead (clients such as ApiQueryBlocks will have to be changed to use a JOIN or some other user name lookup). ipb_address could then be replaced by a field better suited towards storing IP data, such as a VARBINARY(16) column storing the raw bytes of the address.

However this sounds like a significantly more complex project.

It may be helpful to note a while back I found that this query returned the information I needed:

SET @IPBase='107.77.207.0';
SET @IPCIDR='24';
select ipb_address from ipblocks where (inet_aton(ipb_address) & power(2, 32) - power(2, (32 - @IPCIDR))) = inet_aton(@IPBase);

I think that's MySQL specific and won't work on other supported RDBMSes. AFAIK Postgres for instance has designated data types like cidr instead of this helper.