root/scapy/route.py

Revision 862:52d055e522bd, 5.1 kB (checked in by Phil <phil@secdev.org>, 5 months ago)

Merged with one-file scapy

Line 
1 ## This file is part of Scapy
2 ## See http://www.secdev.org/projects/scapy for more informations
3 ## Copyright (C) Philippe Biondi <phil@secdev.org>
4 ## This program is published under a GPLv2 license
5
6 import socket
7 from arch import read_routes,get_if_addr,LOOPBACK_NAME
8 from utils import atol,ltoa,itom
9 from config import conf
10 from error import Scapy_Exception,warning
11
12 ##############################
13 ## Routing/Interfaces stuff ##
14 ##############################
15
16 class Route:
17     def __init__(self):
18         self.resync()
19         self.s=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
20         self.cache = {}
21
22     def invalidate_cache(self):
23         self.cache = {}
24
25     def resync(self):
26         self.invalidate_cache()
27         self.routes = read_routes()
28
29     def __repr__(self):
30         rt = "Network         Netmask         Gateway         Iface           Output IP\n"
31         for net,msk,gw,iface,addr in self.routes:
32             rt += "%-15s %-15s %-15s %-15s %-15s\n" % (ltoa(net),
33                                               ltoa(msk),
34                                               gw,
35                                               iface,
36                                               addr)
37         return rt
38
39     def make_route(self, host=None, net=None, gw=None, dev=None):
40         if host is not None:
41             thenet,msk = host,32
42         elif net is not None:
43             thenet,msk = net.split("/")
44             msk = int(msk)
45         else:
46             raise Scapy_Exception("make_route: Incorrect parameters. You should specify a host or a net")
47         if gw is None:
48             gw="0.0.0.0"
49         if dev is None:
50             if gw:
51                 nhop = gw
52             else:
53                 nhop = thenet
54             dev,ifaddr,x = self.route(nhop)
55         else:
56             ifaddr = get_if_addr(dev)
57         return (atol(thenet), itom(msk), gw, dev, ifaddr)
58
59     def add(self, *args, **kargs):
60         """Ex:
61         add(net="192.168.1.0/24",gw="1.2.3.4")
62         """
63         self.invalidate_cache()
64         self.routes.append(self.make_route(*args,**kargs))
65
66        
67     def delt(self,  *args, **kargs):
68         """delt(host|net, gw|dev)"""
69         self.invalidate_cache()
70         route = self.make_route(*args,**kargs)
71         try:
72             i=self.routes.index(route)
73             del(self.routes[i])
74         except ValueError:
75             warning("no matching route found")
76              
77     def ifchange(self, iff, addr):
78         self.invalidate_cache()
79         the_addr,the_msk = (addr.split("/")+["32"])[:2]
80         the_msk = itom(int(the_msk))
81         the_rawaddr = atol(the_addr)
82         the_net = the_rawaddr & the_msk
83        
84        
85         for i in range(len(self.routes)):
86             net,msk,gw,iface,addr = self.routes[i]
87             if iface != iff:
88                 continue
89             if gw == '0.0.0.0':
90                 self.routes[i] = (the_net,the_msk,gw,iface,the_addr)
91             else:
92                 self.routes[i] = (net,msk,gw,iface,the_addr)
93         conf.netcache.flush()
94        
95                
96
97     def ifdel(self, iff):
98         self.invalidate_cache()
99         new_routes=[]
100         for rt in self.routes:
101             if rt[3] != iff:
102                 new_routes.append(rt)
103         self.routes=new_routes
104        
105     def ifadd(self, iff, addr):
106         self.invalidate_cache()
107         the_addr,the_msk = (addr.split("/")+["32"])[:2]
108         the_msk = itom(int(the_msk))
109         the_rawaddr = atol(the_addr)
110         the_net = the_rawaddr & the_msk
111         self.routes.append((the_net,the_msk,'0.0.0.0',iff,the_addr))
112
113
114     def route(self,dest,verbose=None):
115         if dest in self.cache:
116             return self.cache[dest]
117         if verbose is None:
118             verbose=conf.verb
119         # Transform "192.168.*.1-5" to one IP of the set
120         dst = dest.split("/")[0]
121         dst = dst.replace("*","0")
122         while 1:
123             l = dst.find("-")
124             if l < 0:
125                 break
126             m = (dst[l:]+".").find(".")
127             dst = dst[:l]+dst[l+m:]
128
129            
130         dst = atol(dst)
131         pathes=[]
132         for d,m,gw,i,a in self.routes:
133             aa = atol(a)
134             if aa == dst:
135                 pathes.append((0xffffffffL,(LOOPBACK_NAME,a,"0.0.0.0")))
136             if (dst & m) == (d & m):
137                 pathes.append((m,(i,a,gw)))
138         if not pathes:
139             if verbose:
140                 warning("No route found (no default route?)")
141             return LOOPBACK_NAME,"0.0.0.0","0.0.0.0" #XXX linux specific!
142         # Choose the more specific route (greatest netmask).
143         # XXX: we don't care about metrics
144         pathes.sort()
145         ret = pathes[-1][1]
146         self.cache[dest] = ret
147         return ret
148            
149     def get_if_bcast(self, iff):
150         for net, msk, gw, iface, addr in self.routes:
151             if (iff == iface and net != 0L):
152                 bcast = atol(addr)|(~msk&0xffffffffL); # FIXME: check error in atol()
153                 return ltoa(bcast);
154         warning("No broadcast address found for iface %s\n" % iff);
155
156 conf.route=Route()
157
158 #XXX use "with"
159 _betteriface = conf.route.route("0.0.0.0", verbose=0)[0]
160 if _betteriface != LOOPBACK_NAME:
161     conf.iface = _betteriface
162 del(_betteriface)
Note: See TracBrowser for help on using the browser.