Using SAS to convert IP addresses into numerical IP values

As citizens of the Internet, we are all familiar with IP addresses — probably more so than our Internet founding fathers had ever intended. These addresses are typically represented in a 4-piece segmented list of numbers separated by dots. Here is an example: “149.173.5.120”.

Each segment is called an octet because it contains 8 (count ’em, eight!) bits. The four-octect IP address is part of the IPv4 standard.

Note: There is a newer IPv6 standard (featuring 16 octets) that many newer networks use and which allows for more addresses. This has become necessary because all new consumer products are required by law to connect to the Internet. (I think that each of my daughter’s “Polly Pocket” pieces can connect to WiFi.) But in this article I’m ignoring IPv6.

The easy-to-read segmented IP address is actually a 32-bit number, and sometimes it is useful to convert the display value into its numeric form. For example, consider the databases that help you to map an IP address to a geographic location in the world. These databases use a numerical range to map an address to a country or city. (For more on range-based geocoding, see this topic in the PROC GEOCODE documentation.)

Here is a SAS program that converts a character-based, 4-segment IP address into its equivalent numeric value. It uses the SCAN function, a DATA step ARRAY, and a little bit of math to do the work:

/* Calculate the numerical IP from "segmented" IP address            */
/* Example: (from Right to Left)                                     */
/* 1.2.3.4 = 4 + (3 * 256) + (2 * 256 * 256) + (1 * 256 * 256 * 256) */
/*   is 4 + 768 + 13,1072 + 16,777,216 = 16,909,060                  */
data ip_numbers (keep=ip_address ip_numeric);
  infile datalines dsd;
  length ip_address $ 20 ip_numeric 8;
  input ip_address;
  array ip_part {4};
  do i = 1 to 4;
    ip_part{i} = scan(ip_address,i,'.');
  end;
  ip_numeric = ip_part{4} +
    (ip_part{3} * 256) +
    (ip_part{2} * 256 * 256) +
    (ip_part{1} * 256 * 256 * 256);
datalines;
115.85.65.148
117.203.114.198
118.96.201.156
119.247.220.11
12.201.116.58
128.2.38.96
128.204.197.27
128.204.207.83
134.102.237.2
141.155.113.98
169.2.124.79
172.16.26.231
172.16.30.229
173.234.211.69
176.63.76.232
178.157.198.132
178.32.145.44
178.32.177.184
178.33.174.213
178.63.199.204
184.82.208.149
188.165.187.71
;
run;

Here’s the output:

With this mapping, I can then combine my collection of IP addresses with one of the IP-to-geolocation databases that are available. (SAS provides a macro to help work with MaxMind, which you can learn about in this topic.) Here’s a sample result:

tags: geocode, IP addresses, IPv4, SAS programming, SAS tips