GooDoo
GooDoo

Reputation: 153

Shell script to check and insert IP addresses

I have a text file containing a long list of IP addresses that are sorted. A sample of the file looks like this:

103.21.244.0/22     1;  #Cloudflare
103.22.200.0/22     1;  #Cloudflare
103.31.4.0/22       1;  #Cloudflare
104.16.0.0/12       1;  #Cloudflare
108.162.192.0/18    1;  #Cloudflare
141.101.64.0/18     1;  #Cloudflare
162.158.0.0/15      1;  #Cloudflare
173.245.48.0/20     1;  #Cloudflare
188.114.96.0/20     1;  #Cloudflare
190.93.240.0/20     1;  #Cloudflare
197.234.240.0/22    1;  #Cloudflare
198.41.128.0/17     1;  #Cloudflare
199.27.128.0/21     1;  #Cloudflare

I'm trying to write a shell script that does the following:

  1. For a given IP address (e.g. 1.2.3.4) or an IP range (e.g. 1.2.3.0/24), find out whether it is already in the file.

  2. If it is, do nothing. If it is not, then insert it into the file in the right place.

Problems:

A. I'm stuck at checking whether an IP address or IP range is already in the file because a simple grep won't do. For example, grep will return negative for the IP 188.114.98.200, which in fact is already represented by 188.114.96.0/20. Likewise for 188.114.98.0/24.

B. I am also clueless about how to insert an IP address/range entry in the right place without messing the sorted order.

Can someone help? Thank you very much.

Edit:

Okay, after looking at the suggestions, I guess I don't have to needlessly limit myself to Bash, especially if there are already existing libraries in other languages that can get the job done easily.

Upvotes: 1

Views: 925

Answers (2)

Juan Diego Godoy Robles
Juan Diego Godoy Robles

Reputation: 14945

Not bash, but this task is quite simple using Python:

>>> print ips
103.21.244.0/22     1;  #Cloudflare
103.22.200.0/22     1;  #Cloudflare
103.31.4.0/22       1;  #Cloudflare
104.16.0.0/12       1;  #Cloudflare
108.162.192.0/18    1;  #Cloudflare
141.101.64.0/18     1;  #Cloudflare
162.158.0.0/15      1;  #Cloudflare
173.245.48.0/20     1;  #Cloudflare
188.114.96.0/20     1;  #Cloudflare
190.93.240.0/20     1;  #Cloudflare
197.234.240.0/22    1;  #Cloudflare
198.41.128.0/17     1;  #Cloudflare
199.27.128.0/21     1;  #Cloudflare

>>> import iptools
>>> [raw_range for raw_range in ips.splitlines()                     
... if '188.114.98.200' in iptools.IpRangeList(raw_range.split()[0])]
['188.114.96.0/20     1;  #Cloudflare']                              
>>>                                                                  
>>> [raw_range for raw_range in ips.splitlines()                     
... if '188.112.98.200' in iptools.IpRangeList(raw_range.split()[0])]
[]

Upvotes: 0

Alexandre Halm
Alexandre Halm

Reputation: 989

Seems to me that comparing/matching IP-format strings will be quite annoying.

This page (Listing 4) has a good and simple trick to convert an IP string into an array of integers, only using bash parameter substitution (documented here, look for ${var#Pattern}, ${var##Pattern}).

If you want to catch the mask, add something like IP[5]=${tmp##*/} (with the notations of the linux mag pdf).

For simple IP comparison, you can simply compare/match arrays of integers with bash's arithmetic evaluation ((...)) (documented here for instance).

For more complex CIDR matching, either you are willing to implement quite a bit of logic yourself, or try tools like ipcalc (check this) which is available on most Linux distros.

Upvotes: 1

Related Questions