Exemplo n.º 1
0
 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]
Exemplo n.º 2
0
    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()
Exemplo n.º 3
0
    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
            }