2
\$\begingroup\$

Identify whether an IP address is internal, global, link-local, or reserved.

Input should be an IPv4 address in decimal octets separated by periods.

Output should be 0 for link-local (RFC 3927), 1 for internal (RFC 1918), 2 for global IPs (Internet), and 3 for otherwise reserved addresses.

All these address types are described in RFC 5735:

  1. Global and Other Specialized Address Blocks

0.0.0.0/8 - Addresses in this block refer to source hosts on "this" network. Address 0.0.0.0/32 may be used as a source address for this host on this network; other addresses within 0.0.0.0/8 may be used to refer to specified hosts on this network ([RFC1122], Section 3.2.1.3).

10.0.0.0/8 - This block is set aside for use in private networks. Its intended use is documented in [RFC1918]. As described in that
RFC, addresses within this block do not legitimately appear on the
public Internet. These addresses can be used without any
coordination with IANA or an Internet registry.

127.0.0.0/8 - This block is assigned for use as the Internet host loopback address. A datagram sent by a higher-level protocol to an
address anywhere within this block loops back inside the host. This
is ordinarily implemented using only 127.0.0.1/32 for loopback. As
described in [RFC1122], Section 3.2.1.3, addresses within the entire 127.0.0.0/8 block do not legitimately appear on any network anywhere.

169.254.0.0/16 - This is the "link local" block. As described in [RFC3927], it is allocated for communication between hosts on a
single link. Hosts obtain these addresses by auto-configuration,
such as when a DHCP server cannot be found.

172.16.0.0/12 - This block is set aside for use in private networks. Its intended use is documented in [RFC1918]. As described in that RFC, addresses within this block do not legitimately appear on the public Internet. These addresses can be used without any coordination with IANA or an Internet registry.

192.0.0.0/24 - This block is reserved for IETF protocol assignments. At the time of writing this document, there are no current assignments. Allocation policy for future assignments is given in [RFC5736].

192.0.2.0/24 - This block is assigned as "TEST-NET-1" for use in documentation and example code. It is often used in conjunction with domain names example.com or example.net in vendor and protocol
documentation. As described in [RFC5737], addresses within this
block do not legitimately appear on the public Internet and can be
used without any coordination with IANA or an Internet registry. See [RFC1166].

192.88.99.0/24 - This block is allocated for use as 6to4 relay anycast addresses, in [RFC3068]. In contrast with previously
described blocks, packets destined to addresses from this block do
appear in the public Internet. [RFC3068], Section 7, describes
operational practices to prevent the malicious use of this block in
routing protocols.

192.168.0.0/16 - This block is set aside for use in private networks. Its intended use is documented in [RFC1918]. As described in that RFC, addresses within this block do not legitimately appear on the public Internet. These addresses can be used without any coordination with IANA or an Internet registry.

198.18.0.0/15 - This block has been allocated for use in benchmark tests of network interconnect devices. [RFC2544] explains that this
range was assigned to minimize the chance of conflict in case a
testing device were to be accidentally connected to part of the
Internet. Packets with source addresses from this range are not
meant to be forwarded across the Internet.

198.51.100.0/24 - This block is assigned as "TEST-NET-2" for use in documentation and example code. It is often used in conjunction with domain names example.com or example.net in vendor and protocol
documentation. As described in [RFC5737], addresses within this
block do not legitimately appear on the public Internet and can be
used without any coordination with IANA or an Internet registry.

203.0.113.0/24 - This block is assigned as "TEST-NET-3" for use in documentation and example code. It is often used in conjunction with domain names example.com or example.net in vendor and protocol
documentation. As described in [RFC5737], addresses within this
block do not legitimately appear on the public Internet and can be
used without any coordination with IANA or an Internet registry.

224.0.0.0/4 - This block, formerly known as the Class D address space, is allocated for use in IPv4 multicast address assignments.
The IANA guidelines for assignments from this space are described in
[RFC3171].

240.0.0.0/4 - This block, formerly known as the Class E address space, is reserved for future use; see [RFC1112], Section 4.

The one exception to this is the "limited broadcast" destination
address 255.255.255.255. As described in [RFC0919] and [RFC0922],
packets with this destination address are not forwarded at the IP
layer.

4. Summary Table

Address Block       Present Use                Reference
0.0.0.0/8           "This" Network             RFC 1122, Section 3.2.1.3
10.0.0.0/8          Private-Use Networks       RFC 1918
127.0.0.0/8         Loopback                   RFC 1122, Section 3.2.1.3
169.254.0.0/16      Link Local                 RFC 3927
172.16.0.0/12       Private-Use Networks       RFC 1918
192.0.0.0/24        IETF Protocol Assignments  RFC 5736
192.0.2.0/24        TEST-NET-1                 RFC 5737
192.88.99.0/24      6to4 Relay Anycast         RFC 3068
192.168.0.0/16      Private-Use Networks       RFC 1918
198.18.0.0/15       Network Interconnect
                    Device Benchmark Testing   RFC 2544
198.51.100.0/24     TEST-NET-2                 RFC 5737
203.0.113.0/24      TEST-NET-3                 RFC 5737
224.0.0.0/4         Multicast                  RFC 3171
240.0.0.0/4         Reserved for Future Use    RFC 1112, Section 4
255.255.255.255/32  Limited Broadcast          RFC 919, Section 7
                                               RFC 922, Section 7

Rules

  • Standard loopholes apply.
  • This is , shortest answer wins.
\$\endgroup\$
10
  • 1
    \$\begingroup\$ For those of us who do not know this stuff, how do the single values here identify "blocks" and what values are "in" said blocks? Also which blocks are (2) and which are (3) (or are all non RFC3927/1918 (3) and everything else (2))? \$\endgroup\$ Nov 12, 2016 at 2:38
  • \$\begingroup\$ @JonathanAllan The number after the slash in the IP address is the bitmask. networkengineering.stackexchange.com/questions/3697/… \$\endgroup\$
    – anna328p
    Nov 12, 2016 at 2:41
  • 1
    \$\begingroup\$ That does not help me - I did not even think we would have that part in the input - "decimal octets separated by periods". \$\endgroup\$ Nov 12, 2016 at 2:44
  • 2
    \$\begingroup\$ Could you please reformat the summary table so that it exactly shows what should return 0, what should return 1, etc. \$\endgroup\$
    – orlp
    Nov 12, 2016 at 6:52
  • 2
    \$\begingroup\$ This question should have some example inputs and outputs. \$\endgroup\$ May 12, 2017 at 17:07

3 Answers 3

3
\$\begingroup\$

JavaScript, 261 207 bytes

v=>["169.254","10.|172.1[6789].|172.2\\d.|172.3[01]|192.168","x","0.|127|192.0.[02].|192.88.99|198.1[89].|198.51.100|203.0.113|2[345]\\d|22[^0123]"].reduce((a,x,i)=>v.search(x.replace(/\./g,"\\."))==0?i:a,2)

Readable version

v=>[
    "169.254",
    "10.|172.1[6789].|172.2\\d.|172.3[01]|192.168",
    "x",
    "0.|127|192.0.[02].|192.88.99|198.1[89].|198.51.100|203.0.113|2[345]\\d|22[^0123]"]
    .reduce((a,x,i)=>v.search(x.replace(/\./g,"\\."))==0?i:a,2)

Create an array with matching patterns, loop through the patterns and compare to input. Return 0,1,2,3 as appropriate.

Edit: Fix bugs and streamline

\$\endgroup\$
7
  • \$\begingroup\$ I think you can save 18 bytes using (a,x,i)=>x.every(t=>v.search("^"+t.replace(".","\.")))?a:i. \$\endgroup\$
    – Neil
    Nov 12, 2016 at 11:29
  • \$\begingroup\$ V('172.16.0.1') => 2 (INVALID),V('172.17.1.1')=> 2 (INVALID), basically the whole "172.16" block does not work correctly. Have you tested this ? There is a syntax error - "\d" not escaped properly, resulting in a literal "d" match, and the patterns for this block are simply not correct too. \$\endgroup\$
    – zeppelin
    Nov 12, 2016 at 21:53
  • \$\begingroup\$ 172.16.0.1 returns 1 if you use the short version. I made an error when copying and pasting the "readable" version. As for the patterns being wrong, I made a mistake when calculating that subnet. \$\endgroup\$
    – Grax32
    Nov 14, 2016 at 11:55
  • \$\begingroup\$ The mask for 172.16.0.0 is 12 bits, which means that the address range is: 172.16.0.0-172.31.255.255 (i.e. 172.16.X, 172.17 (!) e.t.c.)). Test: I("172.17.0.1") => 2 (should be 1 instead) \$\endgroup\$
    – zeppelin
    Nov 14, 2016 at 12:17
  • \$\begingroup\$ (you can compute the address ranges at iplocation.net/subnet-calculator, to avoid doing that by hand) \$\endgroup\$
    – zeppelin
    Nov 14, 2016 at 12:18
1
\$\begingroup\$

ES6 (Javascript), 204, 200, 182, 178 bytes

EDIT: Rewritten hex padding code, removed extra parenthesis, -4 bytes

EDIT: RegExp cleanup, streamline the result extraction, shorten the hex conversion code

EDIT: Refactored result extraction to bring it down to 200 bytes

Note, this should be pretty easy to shorten even further, by compressing the RegExp (as I never really bothered to do this)

Golfed

a=>/(^(?:00|7f|c0(?:5863|0{3}[02])|c6(?:1[23]|3364)|cb0071|e|f))|(^a9fe)|(^0a|^ac1|^c0a8)|./.exec(a.replace(/\d+./g,o=>(o|256).toString(16).slice(1))).reverse().findIndex(a=>a)^1

Explanation

IP addresses are shorter to write and easier to match, when converted to hexadecimal form, as CIDR masks tend to end on the 4 bit boundaries (with an exception of 198.18.0.0/15).

E.g.

0A000000-0AFFFFFF //10.0.0.0/8 
AC100000-AC1FFFFF //172.16.0.0/12
C0A80000-C0A8FFFF //192.168.0.0/16

can be matched as

/^0a|^ac1|^c0a8/

Test

I=a=>/(^(?:00|7f|c0(?:5863|0{3}[02])|c6(?:1[23]|3364)|cb0071|e|f))|(^a9fe)|(^0a|^ac1|^c0a8)|./.exec(a.replace(/\d+./g,o=>(o|256).toString(16).slice(1))).reverse().findIndex(a=>a)^1;

T=(i,o)=>{
  block=I(i);
  console.log(i,(block==o)?"OK":"NOT OK");
}

T("0.0.0.0",3)
T("10.0.0.0",1)
T("11.0.0.0",2)
T("127.0.0.0",3)
T("169.254.0.0",0)
T("169.253.0.0",2)
T("172.16.0.0",1)
T("172.31.0.0",1)
T("172.32.0.0",2)
T("192.0.0.0",3)
T("192.0.2.0",3)
T("192.88.99.0",3)
T("192.168.0.0",1)
T("192.167.0.0",2)
T("198.18.0.0",3)
T("198.51.100.0",3)
T("203.0.113.0",3)
T("224.0.0.0",3)
T("239.255.255.255",3)
T("240.0.0.0",3)
T("255.255.255.255",3)
T("241.0.0.1",3)
T("151.101.192.71",2)
\$\endgroup\$
0
\$\begingroup\$

Batch, 356 bytes

@echo off
set s=%1
if not %s==%s:.=% %0 %s:.= %
if %1.%2==169.254 exit/b0
if %1==10 exit/b1
if %1.%2==172.16 if %3 lss 32 exit/b1
if %1.%2==192.168 exit/b1
if %1==0 exit/b3
if %1==127 exit/b3
if %1 geq 224 exit/b3
for %%a in (18 19)do if %1.%2==192.%a exit/b3
for %%a in (192.0.0 192.0.2 198.51.100 203.0.113)do if %1.%2.%3==%%a exit/b3
exit/b2

Takes input as a command-line parameter and returns the result by setting the errorlevel.

\$\endgroup\$
3
  • \$\begingroup\$ The "224.0.0.0/4 Multicast" range has a 4 bit mask, which means that it covers the addresses from 224.0.0.0 – 239.255.255.255 (and you only match 224). The same for "240" block. \$\endgroup\$
    – zeppelin
    Nov 12, 2016 at 22:02
  • \$\begingroup\$ @zeppelin Ah, so in fact anything >= 224 counts? \$\endgroup\$
    – Neil
    Nov 13, 2016 at 1:05
  • \$\begingroup\$ Yep, correct, everything > 224 is either multicast, reserved or broadcast, all of which map to the same output value. \$\endgroup\$
    – zeppelin
    Nov 13, 2016 at 17:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.