<s> from six . moves import queue <EOL> import time <EOL> from networking_cisco . _i18n import _LE , _LI <EOL> from networking_cisco . apps . saf . common import dfa_logger as logging <EOL> from networking_cisco . apps . saf . common import dfa_sys_lib as dsl <EOL> from networking_cisco . apps . saf . common import utils <EOL> LOG = logging . getLogger ( __name__ ) <EOL> class IpMacPort ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , ip , mac , port ) : <EOL> self . ip = ip <EOL> self . mac = mac and mac . lower ( ) <EOL> self . port = port <EOL> self . chain = '<STR_LIT>' + port [ : <NUM_LIT:10> ] <EOL> class IptablesDriver ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , cfg ) : <EOL> self . _root_helper = cfg . sys . root_helper <EOL> self . rule_info = [ ] <EOL> self . _iptq = queue . Queue ( ) <EOL> def update_rule_entry ( self , rule_info ) : <EOL> """<STR_LIT>""" <EOL> if rule_info . get ( '<STR_LIT:status>' ) == '<STR_LIT>' : <EOL> self . add_rule_entry ( rule_info ) <EOL> if rule_info . get ( '<STR_LIT:status>' ) == '<STR_LIT>' : <EOL> self . remove_rule_entry ( rule_info ) <EOL> def add_rule_entry ( self , rule_info ) : <EOL> """<STR_LIT>""" <EOL> new_rule = IpMacPort ( rule_info . get ( '<STR_LIT>' ) , rule_info . get ( '<STR_LIT>' ) , <EOL> rule_info . get ( '<STR_LIT:port>' ) ) <EOL> LOG . debug ( '<STR_LIT>' , rule_info ) <EOL> self . rule_info . append ( new_rule ) <EOL> def remove_rule_entry ( self , rule_info ) : <EOL> """<STR_LIT>""" <EOL> temp_list = list ( self . rule_info ) <EOL> for rule in temp_list : <EOL> if ( rule . ip == rule_info . get ( '<STR_LIT>' ) and <EOL> rule . mac == rule_info . get ( '<STR_LIT>' ) and <EOL> rule . port == rule_info . get ( '<STR_LIT:port>' ) ) : <EOL> LOG . debug ( '<STR_LIT>' , rule_info ) <EOL> self . rule_info . remove ( rule ) <EOL> def _find_chain_name ( self , mac ) : <EOL> """<STR_LIT>""" <EOL> ipt_cmd = [ '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ] <EOL> cmdo = dsl . execute ( ipt_cmd , root_helper = self . _root_helper , <EOL> log_output = False ) <EOL> for o in cmdo . split ( '<STR_LIT:\n>' ) : <EOL> if mac in o . lower ( ) : <EOL> chain = o . split ( ) [ <NUM_LIT:1> ] <EOL> LOG . info ( _LI ( '<STR_LIT>' ) , <EOL> { '<STR_LIT>' : chain , '<STR_LIT>' : mac } ) <EOL> return chain <EOL> def _find_rule_no ( self , mac ) : <EOL> """<STR_LIT>""" <EOL> ipt_cmd = [ '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ] <EOL> cmdo = dsl . execute ( ipt_cmd , self . _root_helper , log_output = False ) <EOL> for o in cmdo . split ( '<STR_LIT:\n>' ) : <EOL> if mac in o . lower ( ) : <EOL> rule_no = o . split ( ) [ <NUM_LIT:0> ] <EOL> LOG . info ( _LI ( '<STR_LIT>' ) , <EOL> { '<STR_LIT>' : rule_no , '<STR_LIT>' : mac } ) <EOL> return rule_no <EOL> def update_ip_rule ( self , ip , mac ) : <EOL> """<STR_LIT>""" <EOL> rule_no = self . _find_rule_no ( mac ) <EOL> chain = self . _find_chain_name ( mac ) <EOL> if not rule_no or not chain : <EOL> LOG . error ( _LE ( '<STR_LIT>' ) , <EOL> { '<STR_LIT>' : ip , '<STR_LIT>' : mac } ) <EOL> return <EOL> update_cmd = [ '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT:%s>' % chain , '<STR_LIT:%s>' % rule_no , <EOL> '<STR_LIT>' , '<STR_LIT>' % ip , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT:%s>' % mac , '<STR_LIT>' , '<STR_LIT>' ] <EOL> LOG . debug ( '<STR_LIT>' , update_cmd ) <EOL> dsl . execute ( update_cmd , self . _root_helper , log_output = False ) <EOL> def enqueue_event ( self , event ) : <EOL> """<STR_LIT>""" <EOL> LOG . debug ( '<STR_LIT>' , event ) <EOL> if event . get ( '<STR_LIT:status>' ) == '<STR_LIT>' : <EOL> for rule in self . rule_info : <EOL> if ( rule . mac == event . get ( '<STR_LIT>' ) . lower ( ) and <EOL> rule . port == event . get ( '<STR_LIT:port>' ) ) : <EOL> if rule . ip != event . get ( '<STR_LIT>' ) : <EOL> LOG . debug ( '<STR_LIT>' <EOL> '<STR_LIT>' % ( rule . ip , event . get ( '<STR_LIT>' ) ) ) <EOL> rule . ip = event . get ( '<STR_LIT>' ) <EOL> return <EOL> self . _iptq . put ( event ) <EOL> def create_thread ( self ) : <EOL> """<STR_LIT>""" <EOL> ipt_thrd = utils . EventProcessingThread ( '<STR_LIT>' , self , <EOL> '<STR_LIT>' ) <EOL> return ipt_thrd <EOL> def _is_ip_in_rule ( self , ip , rule ) : <EOL> try : <EOL> ip_loc = rule . index ( '<STR_LIT>' ) + <NUM_LIT:1> <EOL> rule_ip = rule [ ip_loc ] . split ( '<STR_LIT:/>' ) [ <NUM_LIT:0> ] <EOL> return ip == rule_ip <EOL> except Exception : <EOL> return False <EOL> def update_iptables ( self ) : <EOL> """<STR_LIT>""" <EOL> iptables_cmds = [ '<STR_LIT>' , '<STR_LIT:-c>' ] <EOL> all_rules = dsl . execute ( iptables_cmds , root_helper = self . _root_helper , <EOL> log_output = False ) <EOL> new_rules = [ ] <EOL> is_modified = False <EOL> for line in all_rules . split ( '<STR_LIT:\n>' ) : <EOL> new_line = line <EOL> line_content = line . split ( ) <EOL> if '<STR_LIT>' in line_content : <EOL> tmp_rule_info = list ( self . rule_info ) <EOL> for rule in tmp_rule_info : <EOL> if ( rule . mac in line . lower ( ) and <EOL> rule . chain . lower ( ) in line . lower ( ) and <EOL> not self . _is_ip_in_rule ( rule . ip , line_content ) ) : <EOL> ip_loc = line_content . index ( '<STR_LIT>' ) + <NUM_LIT:1> <EOL> line_content [ ip_loc ] = rule . ip + '<STR_LIT>' <EOL> new_line = '<STR_LIT:U+0020>' . join ( line_content ) <EOL> LOG . debug ( '<STR_LIT>' <EOL> '<STR_LIT>' % ( <EOL> { '<STR_LIT>' : line , <EOL> '<STR_LIT>' : new_line } ) ) <EOL> is_modified = True <EOL> new_rules . append ( new_line ) <EOL> if is_modified and new_rules : <EOL> iptables_cmds = [ '<STR_LIT>' , '<STR_LIT:-c>' ] <EOL> dsl . execute ( iptables_cmds , process_input = '<STR_LIT:\n>' . join ( new_rules ) , <EOL> root_helper = self . _root_helper , log_output = False ) <EOL> def process_rule_info ( self ) : <EOL> """<STR_LIT>""" <EOL> while True : <EOL> try : <EOL> event = self . _iptq . get ( block = False ) <EOL> LOG . debug ( '<STR_LIT>' , event ) <EOL> self . update_rule_entry ( event ) <EOL> except queue . Empty : <EOL> self . update_iptables ( ) <EOL> time . sleep ( <NUM_LIT:1> ) <EOL> except Exception : <EOL> LOG . exception ( _LE ( '<STR_LIT>' ) ) </s>
