title: Python Linux route table lookup
body: <p>I posted <a href="https://stackoverflow.com/questions/4953629/python-find-first-network-hop">Python find first network hop</a> about trying to find the first hop and the more I thought about it, the easier it seemed like it would be a process the routing table in python.  I'm not a programmer, I don't know what I'm doing. :p</p>
  
  <p>This is what I came up with, the first issue I noticed is the loopback interface doesn't show up in the /proc/net/route file- so evaluating 127.0.0.0/8 will give you the default route... for my application, that doesn't matter.</p>
  
  <p>Anything else major I'm overlooking?  Is parsing <code>ip route get &lt;ip&gt;</code> still a better idea? </p>
  
  <pre><code>import re
  import struct
  import socket
  
  '''
     Read all the routes into a list. Most specific first.
     # eth0  000219AC        04001EAC        0003    0       0       0       00FFFFFF ...
  '''
  def _RtTable():
      _rt = []
      rt_m = re.compile('^[a-z0-9]*\W([0-9A-F]{8})\W([0-9A-F]{8})[\W0-9]*([0-9A-F]{8})')
      rt = open('/proc/net/route', 'r')
      for line in rt.read().split('\n'):
          if rt_m.match(line):
              _rt.append(rt_m.findall(line)[0])
  
      rt.close()
      return _rt
  
  '''
     Create a temp ip (tip) that is the entered ip with the host 
     section striped off.  Matching to routers in order, 
     the first match should be the most specific.
  
     If we get 0.0.0.0 as the next hop, the network is likely(?) 
     directly attached- the entered IP is the next (only) hop
  '''
  def FindGw(ip):
      int_ip = struct.unpack("I", socket.inet_aton(ip))[0]
      for entry in _RtTable():
          tip = int_ip &amp; int(entry[2], 16)
          if tip == int(entry[0], 16):
              gw_s = socket.inet_ntoa(struct.pack("I", int(entry[1], 16)))
              if gw_s == '0.0.0.0':
                  return ip
              else:
                  return gw_s
  
  if __name__ == '__main__':
      import sys
      print FindGw(sys.argv[1])
  </code></pre>