def parse(self, message): """ Partition Capabilities message one by one """ try: self.capa_code, self.capa_length = struct.unpack( '!BB', message[:2]) except: raise excp.OpenMessageError( sub_error=bgp_cons.ERR_MSG_HDR_BAD_MSG_LEN, data=message[:2]) self.capa_value = message[2:self.capa_length + 2]
def open_received(self, timestamp, msg): """ porcess open message :param timestamp: timestamp that received this message :param msg: binary raw message data :return: """ self.msg_recv_stat['Opens'] += 1 open_msg = Open() parse_result = open_msg.parse(msg) if self.fsm.bgp_peering.peer_asn != open_msg.asn: raise excep.OpenMessageError( sub_error=bgp_cons.ERR_MSG_OPEN_BAD_PEER_AS) # Open message Capabilities negotiation cfg.CONF.bgp.running_config[self.factory.peer_addr]['capability'][ 'remote'] = open_msg.capa_dict LOG.info("[%s]A BGP Open message was received", self.factory.peer_addr) LOG.info('--version = %s', open_msg.version) LOG.info('--ASN = %s', open_msg.asn) LOG.info('--hold time = %s', open_msg.hold_time) LOG.info('--id = %s', open_msg.bgp_id) LOG.info("[%s]Neighbor's Capabilities:", self.factory.peer_addr) for key in cfg.CONF.bgp.running_config[ self.factory.peer_addr]['capability']['remote']: if key == 'four_bytes_as': self.fourbytesas = True elif key == 'add_path': if cfg.CONF.bgp.running_config[self.factory.peer_addr]['capability']['remote']['add_path'] in \ ['ipv4_send', 'ipv4_both']: if cfg.CONF.bgp.running_config[self.factory.peer_addr]['capability']['local']['add_path'] in \ ['ipv4_receive', 'ipv4_both']: self.add_path_ipv4_receive = True LOG.info( "--%s = %s", key, cfg.CONF.bgp.running_config[ self.factory.peer_addr]['capability']['remote'][key]) # write bgp message self.factory.write_msg(timestamp=timestamp, msg_type=1, msg=parse_result, flush=True) self.peer_id = open_msg.bgp_id self.bgp_peering.set_peer_id(open_msg.bgp_id) self.negotiate_hold_time(open_msg.hold_time) self.fsm.open_received()
def parse(self, message): """Parses a BGP Open message""" try: self.version, self.asn, self.hold_time, \ self.bgp_id, self.opt_para_len = struct.unpack('!BHHIB', message[:10]) except: raise excp.MessageHeaderError( sub_error=bgp_cons.ERR_MSG_HDR_BAD_MSG_LEN, data=message[:10]) self.bgp_id = str(netaddr.IPAddress(self.bgp_id)) if self.version != 4: # Here we just support BGP-4 raise excp.OpenMessageError( sub_error=bgp_cons.ERR_MSG_OPEN_UNSUP_VERSION, data=self.version) if isinstance(self.asn, float): self.asn = str(self.asn).split('.') self.asn = 65536 * (int(self.asn[0])) + int(self.asn[1]) if self.asn in (0, 2**16 - 1): # bad peer asn raise excp.OpenMessageError( sub_error=bgp_cons.ERR_MSG_OPEN_BAD_PEER_AS, data=self.asn) # Hold Time negotiation is out of this scope if self.bgp_id in (0, 2**32 - 1): raise excp.OpenMessageError( sub_error=bgp_cons.ERR_MSG_OPEN_BAD_BGP_ID, data=self.bgp_id) # Optional Parameters if self.opt_para_len: self.opt_paras = message[10:] # While Loop: Parse one Optional Parameter(Capability) each time while self.opt_paras: # 1 octet 1 octet variable # --------------------------------------+ # para_type | para_length | para_value | # --------------------------------------+ opt_para_type, opt_para_length = struct.unpack( '!BB', self.opt_paras[:2]) # Parameter Type 1: Authentication (deprecated) [RFC4271] [RFC5492] # Parameter Type 2: Capabilities [RFC5492] # Here we only support Type 2 if opt_para_type != 2: # if type is not type 2, return an suberror used to Notification raise excp.OpenMessageError( sub_error=bgp_cons.ERR_MSG_OPEN_UNSUP_OPT_PARAM, data=message[10:]) # ---------------------- Parse Capabilities ------------------# # capabilities belongs to one Optional Parameter Capability capabilities = self.opt_paras[2:opt_para_length + 2] while capabilities: # ---- Parse every capability in this Optional Parameter capability = Capability() capability.parse(capabilities) # (1) for 4 bytes ASN if capability.capa_code == capability.FOUR_BYTES_ASN: asn = struct.unpack('!I', capability.capa_value)[0] self.asn = asn self.capa_dict['four_bytes_as'] = True # (2) Multiprotocol Extensions for BGP-4 elif capability.capa_code == capability.MULTIPROTOCOL_EXTENSIONS: if 'afi_safi' not in self.capa_dict: self.capa_dict['afi_safi'] = [] afi, res, safi = struct.unpack('!HBB', capability.capa_value) self.capa_dict['afi_safi'].append((afi, safi)) # (3) Route Refresh elif capability.capa_code == capability.ROUTE_REFRESH: self.capa_dict['route_refresh'] = True # (4) Cisco Route Refresh elif capability.capa_code == capability.CISCO_ROUTE_REFRESH: self.capa_dict['cisco_route_refresh'] = True # (5) Graceful Restart elif capability.capa_code == capability.GRACEFUL_RESTART: self.capa_dict['graceful_restart'] = True # (6) Cisco MultiSession elif capability.capa_code == capability.CISCO_MULTISESSION_BGP: self.capa_dict['cisco_multi_session'] = True # (7) enhanced route refresh elif capability.capa_code == capability.ENHANCED_ROUTE_REFRESH: self.capa_dict['enhanced_route_refresh'] = True # (8) add path elif capability.capa_code == capability.ADD_PATH: self.capa_dict['add_path'] = True else: self.capa_dict[str( capability.capa_code)] = capability.capa_value capabilities = capabilities[2 + capability.capa_length:] # Go to next Optional Parameter self.opt_paras = self.opt_paras[opt_para_length + 2:] return { 'Version': self.version, 'ASN': self.asn, 'holdTime': self.hold_time, 'bgpID': self.bgp_id, 'Capabilities': self.capa_dict }