blob: c7a296b476c95a487f95be59f7e6acdf2ae280a0 [file] [log] [blame]
#!/usr/bin/env python
# Copyright (c) 2009 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Return information about routing table entries
Read and parse the system routing table. There are
two classes defined here: NetworkRoutes, which contains
information about all routes, and Route, which describes
a single routing table entry.
"""
ROUTES_FILE = "/proc/net/route"
# The following constants are from <net/route.h>
RTF_UP = 0x0001
RTF_GATEWAY = 0x0002
RTF_HOST = 0x0004
import socket
import struct
def intToDottedQuad(addr):
return socket.inet_ntoa(struct.pack('@I', addr))
def convertIpToInt(i):
"""Convert the supplied argument to an int representing an IP address."""
if isinstance(i, int):
return i;
return struct.unpack('I', socket.inet_aton(i))[0]
class Route(object):
def __init__(self, iface, dest, gway, flags, mask):
self.interface = iface
self.destination = int(dest, 16)
self.gateway = int(gway, 16)
self.flagbits = int(flags, 16)
self.netmask = int(mask, 16)
def __str__(self):
flags = ""
if self.flagbits & RTF_UP:
flags += "U"
if self.flagbits & RTF_GATEWAY:
flags += "G"
if self.flagbits & RTF_HOST:
flags += "H"
return "<%s dest: %s gway: %s mask: %s flags: %s>" % (
self.interface,
intToDottedQuad(self.destination),
intToDottedQuad(self.gateway),
intToDottedQuad(self.netmask),
flags)
def isUsable(self):
return self.flagbits & RTF_UP
def isHostRoute(self):
return self.flagbits & RTF_HOST
def isGatewayRoute(self):
return self.flagbits & RTF_GATEWAY
def isInterfaceRoute(self):
return (self.flagbits & RTF_GATEWAY) == 0
def isDefaultRoute(self):
return (self.flagbits & RTF_GATEWAY) and self.destination == 0
def matches(self, ip):
return (ip & self.netmask) == self.destination
class NetworkRoutes(object):
def __init__(self, routelist=None):
if not routelist:
routef = open(ROUTES_FILE)
routelist = routef.readlines()
routef.close()
# The first line is headers that will allow us
# to correctly interpret the values in the following
# lines
colMap = {}
headers = routelist[0].split()
for (pos, token) in enumerate(headers):
colMap[token] = pos
self.routes = []
for routeline in routelist[1:]:
route = routeline.split()
interface = route[colMap["Iface"]]
destination = route[colMap["Destination"]]
gateway = route[colMap["Gateway"]]
flags = route[colMap["Flags"]]
mask = route[colMap["Mask"]]
self.routes.append(Route(interface, destination, gateway, flags, mask))
def hasDefaultRoute(self, interface):
for rr in self.routes:
if rr.isUsable() and rr.interface == interface and rr.isDefaultRoute():
return True
return False
def getDefaultRoutes(self):
defroutes = []
for rr in self.routes:
if rr.isUsable() and rr.isDefaultRoute():
defroutes.append(rr)
return defroutes
def hasInterfaceRoute(self, interface):
for rr in self.routes:
if rr.isUsable() and rr.interface == interface and rr.isInterfaceRoute():
return True
return False
def getRouteFor(self, ip_as_int_or_string):
ip = convertIpToInt(ip_as_int_or_string)
for rr in self.routes:
if rr.isUsable() and rr.matches(ip):
return rr
return None
if __name__ == "__main__":
routes = NetworkRoutes()
if routes == None:
print "Failed to read routing table"
else:
for rr in routes.routes:
print rr
print "hasDefaultRoute(\"eth0\"):", routes.hasDefaultRoute("eth0")
dflts = routes.getDefaultRoutes()
if dflts == None:
print "There are no default routes"
else:
print "There are %d default routes" % (len(dflts))
print "hasInterfaceRoute(\"eth0\"):", routes.hasInterfaceRoute("eth0")
routes = NetworkRoutes([
"Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT",
"ones 00010203 FE010203 0007 0 0 0 00FFFFFF 0 0 0\n",
"default 00000000 09080706 0007 0 0 0 00000000 0 0 0\n",
])
print routes.getRouteFor(0x01010203)
print routes.getRouteFor("3.2.1.1")
print routes.getRouteFor(0x08010209)