Пример #1
0
async def send_notification_message(self,
                                    error_code,
                                    error_subcode=0,
                                    data=b""):
    """ Send Notification message """

    if self.tcp_connection_established:
        message = bgp_message.Notification(error_code, error_subcode, data)

        try:
            self.writer.write(message.write())
            await self.writer.drain()

        except OSError:
            self.logger.opt(ansi=True, depth=1).info(
                f"<magenta>[TX-ERR]</> NOTIFICATION - {error_code}, {error_subcode}"
            )
            self.enqueue_event(BgpEvent("Event 18: TcpConnectionFails"))
            self.tcp_connection_established = False
            await asyncio.sleep(1)
            return

        self.logger.opt(ansi=True, depth=1).info(
            f"<magenta>[TX]</> NOTIFICATION {error_code}, {error_subcode}")

    else:
        self.logger.opt(ansi=True, depth=1).info(
            f"<magenta>[TX-ERR]</> NOTIFICATION {error_code}, {error_subcode}")
Пример #2
0
async def open_connection(self):
    """ Open TCP connection to the BGP peer """

    self.logger.opt(depth=0).debug("Opening connection to peer")
    try:
        reader, writer = await asyncio.open_connection(self.peer_ip, 179)
        self.enqueue_event(
            BgpEvent("Event 16: Tcp_CR_Acked",
                     reader=reader,
                     writer=writer,
                     peer_ip=self.peer_ip,
                     peer_port=179))

    except OSError:
        self.tcp_connection_established = False
        self.enqueue_event(BgpEvent("Event 18: TcpConnectionFails"))
Пример #3
0
    async def connection_state_tracking(self):
        """ Restart both connections if both of them are in Idle state """

        await asyncio.sleep(1)

        while True:
            if self.active_mode and self.active_fsm.state == "Idle" and self.passive_fsm.state != "Established":
                self.active_fsm.enqueue_event(
                    BgpEvent("Event 3: AutomaticStart"))

            if self.passive_mode and self.passive_fsm.state == "Idle" and self.active_fsm.state != "Established":
                self.passive_fsm.enqueue_event(
                    BgpEvent(
                        "Event 5: AutomaticStart_with_PassiveTcpEstablishment")
                )
                self.bgp_listeners[self.peer_ip] = self.passive_fsm

            await asyncio.sleep(10)
Пример #4
0
    async def connection_collision_detection(self):
        """ Perform collision detection and shutdown non preferred connection """

        self.logger = loguru.logger.bind(peer="S " + self.peer_ip, state="")

        await asyncio.sleep(1)

        while True:

            if self.active_fsm.state != "Idle" and self.passive_fsm.state != "Idle":

                if self.active_fsm.state == "Established" and self.passive_fsm.state != "Established":
                    self.logger.debug(
                        "Collision detection E/!E - Closing passive connection"
                    )
                    self.passive_fsm.enqueue_event(
                        BgpEvent("Event 8: AutomaticStop"))

                if self.passive_fsm.state == "Established" and self.active_fsm.state != "Established":
                    self.logger.debug(
                        "Collision detection !E/E - Closing active connection")
                    self.active_fsm.enqueue_event(
                        BgpEvent("Event 8: AutomaticStop"))

                if self.active_fsm.state == "OpenConfirm" and self.passive_fsm.state == "OpenConfirm":
                    if struct.unpack("!L", socket.inet_aton(
                            self.local_id))[0] > struct.unpack(
                                "!L", socket.inet_aton(
                                    self.active_fsm.peer_id))[0]:
                        self.logger.debug(
                            "Collision detection OC/OC LID > PID - Closing passive connection"
                        )
                        self.passive_fsm.enqueue_event(
                            BgpEvent("Event 8: AutomaticStop"))
                    else:
                        self.logger.debug(
                            "Collision detection OC/OC LID < PID - Closing active connection"
                        )
                        self.active_fsm.enqueue_event(
                            BgpEvent("Event 8: AutomaticStop"))

            await asyncio.sleep(0.1)
Пример #5
0
async def decrease_hold_timer(self):
    """ Decrease hold_timer every second if its value is greater than zero """

    self.logger.debug("Starting decrease_hold_timer() coroutine")

    if not hasattr(self, "hold_timer"):
        self.hold_timer = 0

    while True:
        await asyncio.sleep(1)
        if self.hold_timer:
            self.logger.debug(f"hold_timer = {self.hold_timer}")
            self.hold_timer -= 1
            if not self.hold_timer:
                self.enqueue_event(BgpEvent("Event 10: HoldTimer_Expires"))
Пример #6
0
async def bgp_broker(reader, writer):
    """ Evaluate incoming connection and send to BGP session if valid peer """

    peer = writer.get_extra_info("peername")
    passive_fsm = BGP_LISTENERS.pop(peer[0], None)

    if passive_fsm:
        passive_fsm.enqueue_event(
            BgpEvent("Event 17: TcpConnectionConfirmed",
                     reader=reader,
                     writer=writer,
                     peer_ip=peer[0],
                     peer_port=peer[1]))

    else:
        writer.close()
        await writer.wait_closed()
Пример #7
0
async def send_keepalive_message(self):
    """ Send Keepalive message """

    if self.tcp_connection_established:
        message = bgp_message.Keepalive()

        try:
            self.writer.write(message.write())
            await self.writer.drain()

        except OSError:
            self.logger.opt(ansi=True,
                            depth=1).error("<magenta>[TX-ERR]</> KEEPALIVE")
            self.enqueue_event(BgpEvent("Event 18: TcpConnectionFails"))
            self.tcp_connection_established = False
            await asyncio.sleep(1)
            return

        self.logger.opt(ansi=True, depth=1).info("<magenta>[TX]</> KEEPALIVE")

    else:
        self.logger.opt(ansi=True,
                        depth=1).error("<magenta>[TX-ERR]</> KEEPALIVE")
Пример #8
0
async def send_open_message(self):
    """ Send Open message """

    if self.tcp_connection_established:
        message = bgp_message.Open(local_id=self.local_id,
                                   local_asn=self.local_asn,
                                   local_hold_time=self.local_hold_time)

        try:
            self.writer.write(message.write())
            await self.writer.drain()

        except OSError:
            self.logger.opt(ansi=True,
                            depth=1).info("<magenta>[TX-ERR]</> OPEN")
            self.enqueue_event(BgpEvent("Event 18: TcpConnectionFails"))
            self.tcp_connection_established = False
            await asyncio.sleep(1)
            return

        self.logger.opt(ansi=True, depth=1).info("<magenta>[TX]</> OPEN")

    else:
        self.logger.opt(ansi=True, depth=1).info("<magenta>[TX-ERR]</> OPEN")
Пример #9
0
async def message_input_loop(self):
    """ Receive messages from the peer and add them to the input queue """

    self.logger.debug("Starting message input loop")

    while True:

        if self.tcp_connection_established is False:
            await asyncio.sleep(1)
            continue

        data = await self.reader.read(4096)
        self.logger.debug(f"Received {len(data)} bytes of data")

        if len(data) == 0:
            self.enqueue_event(BgpEvent("Event 18: TcpConnectionFails"))
            self.tcp_connection_established = False
            await asyncio.sleep(1)
            continue

        while len(data) >= 19:
            message = bgp_message.DecodeMessage(data,
                                                local_id=self.local_id,
                                                peer_asn=self.peer_asn)

            if message.data_len_error:
                self.logger.warning(
                    f"Received {message.data_len_received} bytes of data, expected at least {message.data_len_expected}"
                )
                self.tcp_connection_established = False
                self.enqueue_event(BgpEvent("Event 18: TcpConnectionFails"))
                await asyncio.sleep(1)
                break

            data = data[message.len:]

            if message.message_error_code == bgp_message.MESSAGE_HEADER_ERROR:
                self.enqueue_event(BgpEvent("Event 21: BGPHeaderErr", message))
                break

            if message.message_error_code == bgp_message.OPEN_MESSAGE_ERROR:
                self.enqueue_event(BgpEvent("Event 22: BGPOpenMsgErr",
                                            message))
                break

            if message.type == bgp_message.OPEN:
                self.logger.opt(ansi=True).info(
                    f"<green>[RX]</> OPEN - peer_id: {message.id}")
                self.enqueue_event(BgpEvent("Event 19: BGPOpen", message))

            if message.type == bgp_message.UPDATE:
                self.logger.opt(ansi=True).info(
                    f"<green>[RX]</> UPDATE - add {len(message.prefixes_add)}, del {len(message.prefixes_del)}"
                )
                for attribute in message.attributes:
                    self.logger.opt(
                        ansi=True).info(f"<green>[RX]</> attr: {attribute}")
                for prefix_add in message.prefixes_add:
                    self.logger.opt(ansi=True).info(
                        f"<green>[RX]</> prefix_add: {prefix_add}")
                for prefix_del in message.prefixes_del:
                    self.logger.opt(ansi=True).info(
                        f"<green>[RX]</> prefix_del: {prefix_del}")

            if message.type == bgp_message.NOTIFICATION:
                self.logger.opt(ansi=True).info(
                    f"<green>[RX]</> NOTIFICATION - {message.error_code}, {message.error_subcode}"
                )

                if message.error_code == bgp_message.MESSAGE_HEADER_ERROR:
                    self.enqueue_event(BgpEvent("Event 25: NotifMsg"))

                if message.error_code == bgp_message.OPEN_MESSAGE_ERROR and message.error_subcode == bgp_message.UNSUPPORTED_VERSION_NUMBER:
                    self.enqueue_event(BgpEvent("Event 24: NotifMsgVerErr"))

                if message.error_code == bgp_message.OPEN_MESSAGE_ERROR and message.error_subcode != bgp_message.UNSUPPORTED_VERSION_NUMBER:
                    self.enqueue_event(BgpEvent("Event 25: NotifMsg"))

                if message.error_code == bgp_message.UPDATE_MESSAGE_ERROR:
                    self.enqueue_event(BgpEvent("Event 25: NotifMsg"))

                if message.error_code == bgp_message.HOLD_TIMER_EXPIRED:
                    self.enqueue_event(BgpEvent("Event 25: NotifMsg"))

                if message.error_code == bgp_message.FINITE_STATE_MACHINE_ERROR:
                    self.enqueue_event(BgpEvent("Event 25: NotifMsg"))

                if message.error_code == bgp_message.CEASE:
                    self.enqueue_event(BgpEvent("Event 25: NotifMsg"))

            if message.type == bgp_message.KEEPALIVE:
                self.logger.opt(ansi=True).info("<green>[RX]</> KEEPALIVE")
                self.enqueue_event(BgpEvent("Event 26: KeepAliveMsg"))

            await asyncio.sleep(1)

        else:
            await asyncio.sleep(1)