Generating Layer 3 Interface DNS records for cisco devices

Traceroute looks up the PTR dns records for each hop. A lot of providers create ptr records that describe the layer 3 interface of a given router:

akonkol@use:~$ traceroute 8.8.8.8
traceroute to 8.8.8.8 (8.8.8.8), 30 hops max, 60 byte packets
 1  router1-dal.linode.com (67.18.7.161)  0.451 ms  0.568 ms  0.698 ms
 2  ae2.car01.dllstx2.networklayer.com (67.18.7.89)  0.184 ms  0.215 ms  24.803 ms
 3  po101.dsr01.dllstx2.networklayer.com (70.87.254.73)  0.667 ms  0.726 ms  1.026 ms
 4  po21.dsr01.dllstx3.networklayer.com (70.87.255.65)  0.793 ms  0.860 ms  0.911 ms
 5  ae16.bbr02.eq01.dal03.networklayer.com (173.192.18.228)  0.470 ms  0.451 ms  0.456 ms
 6  ae7.bbr01.eq01.dal03.networklayer.com (173.192.18.208)  0.440 ms  0.437 ms  0.417 ms
 7  50.97.16.37 (50.97.16.37)  0.486 ms  0.512 ms  0.491 ms
 8  72.14.233.85 (72.14.233.85)  0.555 ms 72.14.233.77 (72.14.233.77)  10.054 ms  10.044 ms
 9  64.233.175.148 (64.233.175.148)  7.835 ms 72.14.237.219 (72.14.237.219)  3.690 ms  3.676 ms
10  209.85.249.69 (209.85.249.69)  7.489 ms 72.14.237.123 (72.14.237.123)  7.450 ms 209.85.249.66 (209.85.249.66)  7.409 ms
11  216.239.46.39 (216.239.46.39)  7.366 ms  7.332 ms 216.239.46.63 (216.239.46.63)  7.357 ms
12  * * *
13  google-public-dns-a.google.com (8.8.8.8)  7.410 ms  7.436 ms  7.418 ms

Depending on how much equipment you manage you could have hundreds or even thousands of layer 3 interfaces. This problem intrigued me so I wrote a script that leverages tratto; a framework that I built back in 2012 to ssh/telnet to devices. The script is called l3toptr.py which gets layer 3 interface information and constructs a fqdn.

Connection Code

The following snippet shows a few things: setting up the ssh session, issuing a "show ip interface brief" storing the results in "ip_ints."

#connection setup
import Connectiviy, Systems

device = args['device']
username = args['username']
os_type = Systems.OperatingSystems['IOS']


session = Connectivity.Session(device,port,transport,os_type)
session.login(username, password)
ip_ints = session.sendcommand("sho ip int br")
session.logout()

Parsing Code

We take ip_ints and for each line that contains an ip address, we split the line by "whitespace" which allows us to access the interface name and number separately allowing us to assign these values to int_name and int_ip. Based on the interface name we come up with an abbreviation: GE for gigabit interfaces, FE for fast ethernet interfaces,etc... Since DNS records do now allow for slashes, we replace those with hyphens and assign it to clean_suffix.

#for each line of sho ip int brief

for line in ip_ints.split('\r\n'):
   contains_ip = re.findall( r'[0-9]+(?:\.[0-9]+){3}', line )
   if contains_ip:
        line_chunks = line.split()

        #[0]= gigabitethernet1/2
        int_name = line_chunks[0]

        #[1] = 10.a.b.c
        int_ip = line_chunks[1]

        if "GigabitEthernet" in int_name:
           prefix = "GE"
           suffix = int_name[15:]

        if "FastEthernet" in int_name:
           prefix = "FE"
           suffix = int_name[12:]

        if "Loopback" in int_name:
           prefix ="LO"
           suffix = int_name[8:]

        if "Vlan" in int_name:
           prefix="VL"
           suffix=int_name[4:]

        if "Tunnel" in int_name:
           prefix="TU"
           suffix= int_name[6:]

        #ignore NVIs
        if "NVI" in int_name:
          break

        #replace interface number slash with hyphen
        clean_suffix = re.sub('\/','-',suffix)

Schema and Return Code

The remaining code checks for any user defined schema. There are three variables you can specify in this "schema" (or format string): interface_name, interface_number, hostname, and ip_address. You would specify something like this to use a custom fqdn format: ./l3toPTR.py -u akonkol -d 10.24.2.1 -s "interface_name.hostname.mycompany.com" and interface_name and hostname would be replaced with the dynamically learned information for device living at 10.24.2.1.

if args['schema']:
           schema = args['schema']
           dns_line = schema.replace('interface_name',prefix)
           dns_line = dns_line.replace('interface_number',clean_suffix)
           dns_line = dns_line.replace('hostname',hostname)
           dns_line = dns_line.replace('ip_address',int_ip)
           print dns_line
        else:
           print prefix + clean_suffix  + "." + hostname +  domainname + "," +  int_ip

Some Examples:

akonkol@echo:~/Code$ ./l3toPTR.py -u akonkol -d 10.45.1.2
Password:
GE0-0.chicagorouter02.network.exampleco.com,10.45.1.2
GE0-1.chicagorouter02.network.exampleco.com,24.140.215.81
LO10.chicagorouter02.network.exampleco.com,10.0.45.2
LO99.chicagorouter02.network.exampleco.com,24.140.215.82



akonkol@echo:~/Code$ ./l3toPTR.py -u akonkol -d 10.45.1.2 -dn konkol.com
Password:
GE0-0.chicagorouter02.konkol.com,10.45.1.2
GE0-1.chicagorouter02.konkol.com,24.140.215.81
LO10.chicagorouter02.konkol.com,10.0.45.2
LO99.chicagorouter02.konkol.com,24.140.215.82



akonkol@echo:~/Code$ ./l3toPTR.py -u akonkol -d 10.45.1.2 -s "interface_name-interface_number.mycompany.com,ip_address"
Password:
GE-0-0.mycompany.com,10.45.1.2
GE-0-1.mycompany.com,24.140.215.81
LO-10.mycompany.com,10.0.45.2
LO-99.mycompany.com,24.140.215.82

Wait a second, this isn't actually creating the DNS entries! You would be correct, and I'm willing to bet that if you've read this far that you can figure how to do that... There are a few ways to do this and it all depends on what you are using for your DNS server (bind, windows, etc). The above script generates a CSV output which you could loop through and use to create dns records. Here is a great article on creating ptr records in bulk on a windows dns server DNS Bulk PTR records creation.

Tagged as cisco , dns ios , ptr python , tratto
Written by Andrew Konkol on July 22nd, 2014

0 Comments

Log in with Twitter, Google, Facebook, LinkedIn to leave a comment.