0

I've got an issue but don't really have sufficient Python knowledge to solve it. I found some similar cases so for someone who is really good at Python this is probably a really small task to solve, if you would like!


Problem: Write a list of failed IP's within a monitored range from two input sources

  1. I've got a CSV file with two columns, "FailedIPs.csv":

    State, FailedIP,
    1, 178.203.178.159,
    
  2. Then I've got another file with ISP name and CIDR, "IPranges.csv":

    ISPname, IPrange,
    Vodafone, 88.128.64.0/18,
    
  3. I want to produce a CSV which contains all the failed IP addresses that are in one of the supplied ranges:

    State, FailedIP, ISPname, IPrange,
    1, 178.203.178.159, Vodafone, 168.00.64.0/32,
    

I found some similar questions here on StackOverflow:

Looking forward to any Python "pro" (from my point of view) that would like to help! :)

Community
  • 1
  • 1
  • How many lines in the `File2 CSV IPranges.csv` file? – Aya Apr 26 '13 at 16:24
  • For the sake of the question it really doesn't matter what the values are and mean to a large degree. It would be very beneficial to simplify the problem to its components. – UpAndAdam Apr 26 '13 at 16:36
  • Can you further express where you are stuck? If not this post is likely to get closed off as trivially specific and not having done sufficient research first. – UpAndAdam Apr 26 '13 at 16:40
  • 1
    It looks like Python 3.3+ includes an [`ipaddress`](http://docs.python.org/3.3/library/ipaddress) module which might be of use here. – Aya Apr 26 '13 at 16:51

2 Answers2

0
#!/usr/bin/env python2
import csv
from IPy import IP

def get_IP_ranges(filename):
    with open(filename, 'rb') as csv_file:
        csv_reader = csv.reader(csv_file)
        next(csv_reader) # skip header
        for ISP, IP_range in csv_reader:
            yield IP(IP_range, make_net=True), ISP

def get_failed_IPs(filename):
    with open(filename, 'rb') as csv_file:
        csv_reader = csv.reader(csv_file)
        next(csv_reader) # skip header
        for state, failed_IP in csv_reader:
            yield state, IP(failed_IP)

IP_ranges = tuple(get_IP_ranges('IPranges.csv'))
with open('join.csv', 'wb') as join_csvfile:
    join_writer = csv.writer(join_csvfile)
    join_writer.writerow(('State', 'FailedIP', 'ISPname', 'IPrange'))
    for state, failed_IP in get_failed_IPs('FailedIPs.csv'):
        for IP_range, ISP in IP_ranges:
            if failed_IP in IP_range:
                break
        else:
            continue
        join_writer.writerow((state, failed_IP, ISP, IP_range))

It uses the IPy library.

Cristian Ciupitu
  • 20,270
  • 7
  • 50
  • 76
  • Thanks for all the responses! – user2324240 May 01 '13 at 12:46
  • 5 min EDIT: Thanks a lot for the responses! [at]Aya: Hi, around 200 for this particular task (194). [at]UpAndAdam: Hi, honestly I'm stuck with just learning Python itself. I'm not a dev (at all). Took one course in Java at the university on a managerial programme within IT to understand the basics. @Cristian Ciupitu The answer you have given is of great help, I will try to see if I can put it into a fully working script :)! Any further comments or help is greatly appreciated by you guys – user2324240 May 01 '13 at 12:54
  • If you have any questions leave a comment. – Cristian Ciupitu May 02 '13 at 02:36
  • @user2324240: if you found my answer useful, please give it +1 – Cristian Ciupitu May 03 '13 at 20:39
0

Below is an example of how you might load the files with the csv module, and use a function to test whether the IP address from the first file falls within an IP range for the other. I'm not familiar with using IP addresses, but as suggested above, the ipaddress module would probably be useful here.

import csv

#Modify this function to check if an IP address falls within a range
def ismatch(ipadress, iprange):
    return ipadress == iprange

#Load CSVs
failed = csv.DictReader(open('File1 CSV IPfailed.csv'))
ranges = csv.DictReader(open('File2 CSV IPrange.csv'))
#list for ranges, since will iterate multiple times
rangelist = [row for row in ranges]

#Add cases where FailedIP entry == IPrange entry
matches = []
for ii in failed:
    for jj in rangelist:
        if ismatch(ii[' FailedIP'], jj[' IPrange']):
            ii.update(jj)                       #merge jj dict entries into ii
            matches.append(ii)                  #add to matches

#Output
fieldnames = ranges.fieldnames + failed.fieldnames      #list of all field names
with open('IPmatches.csv', 'w') as f_out:
    writer = csv.DictWriter(f_out, fieldnames)
    writer.writeheader()
    writer.writerows(matches)

One thing to note is that the fieldnames begin with spaces, since there is a space between each field in the header of your CSV files. If your fieldnames are within quotes in the header of your CSV files, then the DictReader won't append those spaces in front.

As this script iterates through the IP ranges for each failed IP address, it may not scale to your problem. Like UpAndAdam mentioned above, simplifying the components of the problem you're trying to solve (matching IPs, using csv), would be helpful for offering more detailed advice.

machow
  • 1,034
  • 1
  • 10
  • 16