[Answers Posted] Relevance Challenge - IP Address is in which Subnet - February 2020

Ah, I think I see. I could take this problem in two different ways. Depending on how you look at it, the ‘cidr’ properties will either give your own IP address in CIDR format, or your subnet in CIDR format. ‘cidr strings’ returns it in subnet format:

q: addresses of adapters of network
A: 192.168.1.151
T: 12.696 ms

q: cidr addresses whose (it != "127.0.0.0/8") of adapters of network
A: 192.168.1.151/24
T: 8.530 ms

q: cidr strings whose (it != "127.0.0.0/8") of adapters of network
A: 192.168.1.0/24
T: 4.444 ms

If you have a defined list of every CIDR subnet, that’s great, you should be able to compare it directly to ‘cidr strings’. So if I had a list of subnets that included 192.168.1.0/24 that’s a pretty easy comparison.

But if we haven’t split out every subnet, but we want to compare to a superblock like 192.168.0.0/16, I think we go back into the use-case for this challenge and “how do I apply the relevance above”.

We can make a couple of small modifications to a large piece of relevance to get “only the subnets that match one of my IP addresses” like so

(
	    item 0 of it  /* Subnet CIDR Address */
	           /* IP address bitset string elements matching this subnet */
	           /* IP Address AND Subnet Mask = Subnet Address bitset */

           /* Previously I was counting "number of" these, now we only want the ones that match */
	  ,  (
	         item 1 of it  /* subnet address bitset string */
	       , item 2 of it  /* subnet mask bitset string */
	       , elements of item 3 of it  /* ip address bitset strings */
	       ) whose (bit set (item 2 of it) * item 1 of it = item 0 of it)
) of

	(
	  /* Derive bitsets for subnets */
	  item 0 of it  /* subnet CIDR address */
	  ,  bit set (concatenation of ((last 8 of padded string of (it as integer as bit set)) as string) of substrings separated by "." of preceding text of first "/" of item 0 of it) 
	  ,  bit set ((concatenation of  "1" of integers in (1,(it)) & concatenation of "0" of integers in (31, it)) of (following text of first "/" of item 0 of it as integer))
	  , item 1 of it /* preserve IP address set of bitset strings */
	) of
	
	(
	   /* unwind subnet CIDR strings */
	   elements of item 0 of it
	   , item 1 of it
	) of
	
	(
	  item 0 of it   /* preserve subnet CIDR strings */
	         /* Convert set of IP addresses into a set of IP Address Bitsets */
	  ,  set of (it as string) of 
	       (concatenation of ((last 8 of padded string of (it as integer as bit set)) as string) of substrings separated by "." of it)  of elements of item 1 of it
	)
	of 
	
	(
	  set of (   /* Subnet CIDR Addresses */
	          "192.168.1.0/24"
	        ; "192.168.2.0/25"
	        ; "192.168.0.0/16"
	        ; "192.168.2.128/25"
	        ; "192.168.3.0/25"
	        ; "192.168.3.128/26"
	        ; "192.168.3.192/26"
	        ; "0.1.0.0/27"
	      )
	     /* Previously I was giving a static list of IP addresses, now let's retrieve addresses from the client */
	 , set of (  /* IP Addresses */
	       addresses of adapters of network as string
	      )
)

For me this gives result

192.168.0.0/16, ( 11000000101010000000000000000000, 11111111111111110000000000000000, 11000000101010000000000110010111 )
192.168.1.0/24, ( 11000000101010000000000100000000, 11111111111111111111111100000000, 11000000101010000000000110010111 )

(My IP address matches against both 192.168.0.0/16, and against 192.168.1.0/24, but not the other subnets).

We can turn that into a true/false by just putting ‘exists’ in front of it…

exists
(
	    item 0 of it  /* Subnet CIDR Address */
	           /* IP address bitset string elements matching this subnet */
	           /* IP Address AND Subnet Mask = Subnet Address bitset */
	  ,  (
	         item 1 of it  /* subnet address bitset string */
	       , item 2 of it  /* subnet mask bitset string */
	       , elements of item 3 of it  /* ip address bitset strings */
	       ) whose (bit set (item 2 of it) * item 1 of it = item 0 of it)
) of

	(
	  /* Derive bitsets for subnets */
	  item 0 of it  /* subnet CIDR address */
	  ,  bit set (concatenation of ((last 8 of padded string of (it as integer as bit set)) as string) of substrings separated by "." of preceding text of first "/" of item 0 of it) 
	  ,  bit set ((concatenation of  "1" of integers in (1,(it)) & concatenation of "0" of integers in (31, it)) of (following text of first "/" of item 0 of it as integer))
	  , item 1 of it /* preserve IP address set of bitset strings */
	) of
	
	(
	   /* unwind subnet CIDR strings */
	   elements of item 0 of it
	   , item 1 of it
	) of
	
	(
	  item 0 of it   /* preserve subnet CIDR strings */
	         /* Convert set of IP addresses into a set of IP Address Bitsets */
	  ,  set of (it as string) of 
	       (concatenation of ((last 8 of padded string of (it as integer as bit set)) as string) of substrings separated by "." of it)  of elements of item 1 of it
	)
	of 
	
	(
	  set of (   /* Subnet CIDR Addresses */
	          "192.168.1.0/24"
	        ; "192.168.2.0/25"
	        ; "192.168.0.0/16"
	        ; "192.168.2.128/25"
	        ; "192.168.3.0/25"
	        ; "192.168.3.128/26"
	        ; "192.168.3.192/26"
	        ; "0.1.0.0/27"
	      )
	
	 , set of (  /* IP Addresses */
	       addresses of adapters of network as string
	      )
)

:True

It gets the job done, but it’s definitely difficult to read and a good argument for adding operators like cidr subnet contains ip address and ip address is contained by cidr subnet

4 Likes