$search
00001 #! /usr/bin/env python 00002 00003 import system 00004 from twisted.internet.defer import inlineCallbacks, DeferredLock 00005 from twisted.internet import reactor 00006 from state_publisher import CompositeStatePublisher 00007 from netlink_monitor import netlink_monitor, IFSTATE 00008 import ip_rule 00009 00010 # FIXME Allow anybody to call shutdown. 00011 00012 class _DhcpSetterCommon: 00013 # Provides support common code for shutting down on shutdown, and 00014 # handles locking. 00015 def __init__(self): 00016 self._lock = DeferredLock() 00017 self.is_shutdown = False 00018 reactor.addSystemEventTrigger('before', 'shutdown', self._shutdown) 00019 00020 @inlineCallbacks 00021 def _cb(self, old_state, new_state): 00022 if self.is_shutdown: 00023 return 00024 yield self._lock.acquire() 00025 try: 00026 yield self._locked_cb(old_state, new_state) 00027 finally: 00028 self._lock.release() 00029 00030 @inlineCallbacks 00031 def _shutdown(self): 00032 #print "Shutdown", self 00033 yield self._cb(None, None) 00034 self.is_shutdown = True 00035 00036 class DhcpAddressSetter(_DhcpSetterCommon): 00037 def __init__(self, iface, state_pub): 00038 _DhcpSetterCommon.__init__(self) 00039 self.iface = iface 00040 self._iface_status_pub = netlink_monitor.get_status_publisher(iface) 00041 state_pub.subscribe(self._cb) 00042 00043 @inlineCallbacks 00044 def _locked_cb(self, old_state, new_state): 00045 #print "Address", self.iface, new_state 00046 if new_state is None or old_state is not None: 00047 if self._iface_status_pub.get() >= IFSTATE.PLUGGED: 00048 yield system.system('ifconfig', self.iface, '0.0.0.0') 00049 00050 if new_state is not None: 00051 ip = new_state['ip'] 00052 ip_slashed = new_state['ip_slashed'] 00053 yield system.system('ip', 'addr', 'add', ip_slashed, 'dev', self.iface) 00054 # Send both request and response gratuitous arp. 00055 yield system.system('arping', '-q', '-c', '1', '-A', '-I', self.iface, ip) 00056 yield system.system('arping', '-q', '-c', '1', '-U', '-I', self.iface, ip) 00057 00058 class DhcpRouteSetter(_DhcpSetterCommon): 00059 def __init__(self, iface, table, state_pub): 00060 _DhcpSetterCommon.__init__(self) 00061 self.iface = iface 00062 self.table = str(table) 00063 self._iface_status_pub = netlink_monitor.get_status_publisher(iface) 00064 CompositeStatePublisher(lambda (addr, dhcp): None if not addr else dhcp, [ 00065 netlink_monitor.get_state_publisher(iface, IFSTATE.ADDR), 00066 state_pub 00067 ]).subscribe(self._cb) 00068 00069 @inlineCallbacks 00070 def _locked_cb(self, old_state, new_state): 00071 if self._iface_status_pub.get() >= IFSTATE.PLUGGED: 00072 yield system.system('ip', 'route', 'flush', 'table', self.table, 'dev', self.iface) 00073 00074 if new_state: 00075 gateway = new_state['gateway'] 00076 ip = new_state['ip'] 00077 network_slashed = new_state['network_slashed'] 00078 yield system.system('ip', 'route', 'add', 'table', self.table, 'default', 'dev', self.iface, 'via', gateway, 'src', ip, 'onlink') 00079 yield system.system('ip', 'route', 'add', 'table', self.table, network_slashed, 'dev', self.iface, 'src', ip) 00080 00081 class DhcpSourceRuleSetter: 00082 def __init__(self, iface, table, priority): 00083 self._ip_rule = ip_rule.IpRule(priority) 00084 self.table = str(table) 00085 self.state_pub = self._ip_rule.state_pub 00086 netlink_monitor.get_state_publisher(iface, IFSTATE.ADDR).subscribe(self._cb) 00087 00088 def _cb(self, old_state, new_state): 00089 if new_state: 00090 ip = new_state[0] 00091 self._ip_rule.set('table', self.table, 'from', ip+"/32") 00092 else: 00093 self._ip_rule.set()