1#!/usr/bin/env python 2# 3# Copyright (C) 2009 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17 18"""Return information about routing table entries 19 20Read and parse the system routing table. There are 21two classes defined here: NetworkRoutes, which contains 22information about all routes, and Route, which describes 23a single routing table entry. 24""" 25 26ROUTES_FILE = "/proc/net/route" 27# The following constants are from <net/route.h> 28RTF_UP = 0x0001 29RTF_GATEWAY = 0x0002 30RTF_HOST = 0x0004 31 32import socket 33import struct 34 35def intToDottedQuad(addr): 36 return socket.inet_ntoa(struct.pack('@I', addr)) 37 38def convertIpToInt(i): 39 """Convert the supplied argument to an int representing an IP address.""" 40 if isinstance(i, int): 41 return i 42 return struct.unpack('I', socket.inet_aton(i))[0] 43 44class Route(object): 45 def __init__(self, iface, dest, gway, flags, mask): 46 self.interface = iface 47 self.destination = int(dest, 16) 48 self.gateway = int(gway, 16) 49 self.flagbits = int(flags, 16) 50 self.netmask = int(mask, 16) 51 52 def __str__(self): 53 flags = "" 54 if self.flagbits & RTF_UP: 55 flags += "U" 56 if self.flagbits & RTF_GATEWAY: 57 flags += "G" 58 if self.flagbits & RTF_HOST: 59 flags += "H" 60 return "<%s dest: %s gway: %s mask: %s flags: %s>" % ( 61 self.interface, 62 intToDottedQuad(self.destination), 63 intToDottedQuad(self.gateway), 64 intToDottedQuad(self.netmask), 65 flags) 66 67 def isUsable(self): 68 return self.flagbits & RTF_UP 69 70 def isHostRoute(self): 71 return self.flagbits & RTF_HOST 72 73 def isGatewayRoute(self): 74 return self.flagbits & RTF_GATEWAY 75 76 def isInterfaceRoute(self): 77 return (self.flagbits & RTF_GATEWAY) == 0 78 79 def isDefaultRoute(self): 80 return (self.flagbits & RTF_GATEWAY) and self.destination == 0 81 82 def matches(self, ip): 83 return (ip & self.netmask) == self.destination 84 85class NetworkRoutes(object): 86 def __init__(self, routelist=None): 87 if not routelist: 88 routef = open(ROUTES_FILE) 89 routelist = routef.readlines() 90 routef.close() 91 92 # The first line is headers that will allow us 93 # to correctly interpret the values in the following 94 # lines 95 colMap = {} 96 headers = routelist[0].split() 97 for (pos, token) in enumerate(headers): 98 colMap[token] = pos 99 100 self.routes = [] 101 for routeline in routelist[1:]: 102 route = routeline.split() 103 interface = route[colMap["Iface"]] 104 destination = route[colMap["Destination"]] 105 gateway = route[colMap["Gateway"]] 106 flags = route[colMap["Flags"]] 107 mask = route[colMap["Mask"]] 108 self.routes.append( 109 Route(interface, destination, gateway, flags, mask)) 110 111 def hasDefaultRoute(self, interface): 112 for rr in self.routes: 113 if (rr.isUsable() and 114 rr.interface == interface and 115 rr.isDefaultRoute()): 116 return True 117 return False 118 119 def getDefaultRoutes(self): 120 defroutes = [] 121 for rr in self.routes: 122 if rr.isUsable() and rr.isDefaultRoute(): 123 defroutes.append(rr) 124 return defroutes 125 126 def hasInterfaceRoute(self, interface): 127 for rr in self.routes: 128 if (rr.isUsable() and 129 rr.interface == interface and 130 rr.isInterfaceRoute()): 131 return True 132 return False 133 134 def getRouteFor(self, ip_as_int_or_string): 135 ip = convertIpToInt(ip_as_int_or_string) 136 for rr in self.routes: 137 if rr.isUsable() and rr.matches(ip): 138 return rr 139 return None 140 141 142if __name__ == "__main__": 143 routes = NetworkRoutes() 144 if routes == None: 145 print "Failed to read routing table" 146 else: 147 for each_route in routes.routes: 148 print each_route 149 150 print "hasDefaultRoute(\"eth0\"):", routes.hasDefaultRoute("eth0") 151 152 dflts = routes.getDefaultRoutes() 153 if dflts == None: 154 print "There are no default routes" 155 else: 156 print "There are %d default routes" % (len(dflts)) 157 158 159 print "hasInterfaceRoute(\"eth0\"):", routes.hasInterfaceRoute("eth0") 160 161 routes = NetworkRoutes([ 162 "Iface Destination Gateway Flags RefCnt " 163 "Use Metric Mask MTU Window IRTT", 164 "ones 00010203 FE010203 0007 0 0 0 00FFFFFF 0 0 0\n", 165 "default 00000000 09080706 0007 0 0 0 00000000 0 0 0\n", 166 ]) 167 168 print routes.getRouteFor(0x01010203) 169 print routes.getRouteFor("3.2.1.1") 170 print routes.getRouteFor(0x08010209) 171