Exemplo n.º 1
0
 def get_config_update_capwap(self, seq):
     if 'config_update' in self._scapy_cache:
         self._scapy_cache['config_update'][20] = struct.pack('>B', seq)
     else:
         self._scapy_cache['config_update'] = c_buffer(
             bytes(CAPWAP_PKTS.config_update(self, seq)))
     return self._scapy_cache['config_update']
Exemplo n.º 2
0
 def get_echo_capwap(self):
     if 'echo_pkt' in self._scapy_cache:
         self._scapy_cache['echo_pkt'][20] = struct.pack(
             '!B', self.get_capwap_seq())
     else:
         self._scapy_cache['echo_pkt'] = CAPWAP_PKTS.echo(self)
     return self._scapy_cache['echo_pkt']
Exemplo n.º 3
0
 def get_config_update_capwap(self, seq):
     if 'config_update' in self._scapy_cache:
         self._scapy_cache['config_update'][20] = struct.pack('!B', seq)
     else:
         self._scapy_cache['config_update'] = CAPWAP_PKTS.config_update(
             self, seq)
     return self._scapy_cache['config_update']
Exemplo n.º 4
0
    def control_round_trip(self, capw_ctrl_pkt, expected_response_type):
        """Send the packet, wait for the expected answer, and retry until max_retransmit.
        This is a generator for a APService, and returns True if success, and False otherwise.
        To be used in a APService as:
            success = yield self.from control_round_trip(capw_ctrl_pkt, expected_response_type=4) # expecting join response
        For 'expected_response_type', check scapy.contrib.capwap.

        Args:
            capw_ctrl_pkt (bytes): capwap control packet to send
            expected_response_type (int): type of the expected response (usually capw_ctrl_pkt's message type + 1)
        """
        from ...trex_wireless_config import config
        RetransmitInterval = config.capwap.retransmit_interval

        for _ in range(config.capwap.max_retransmit):
            RetransmitInterval *= 2

            encrypted = self.ap.encrypt(capw_ctrl_pkt)
            if encrypted and encrypted != '':
                tx_pkt_wrapped = self.ap.wrap_capwap_pkt(
                    b'\1\0\0\0' + self.ap.encrypt(capw_ctrl_pkt))

                self.ap.logger.debug("sending packet")
                self.send_pkt(tx_pkt_wrapped)
            else:
                continue

            # wait on expected response
            pkts = yield self.async_recv_pkt(time_sec=RetransmitInterval)
            if not pkts:
                continue
            pkt = pkts[0]

            # parsing
            # FIXME assumes specific length of lower layers (no vxlan, etc...)
            capwap_bytes = pkt[42:]

            capwap_hlen = (struct.unpack('!B', capwap_bytes[1:2])[
                0] & 0b11111000) >> 1
            ctrl_header_type = struct.unpack(
                '!B', capwap_bytes[capwap_hlen + 3:capwap_hlen + 4])[0]
            result_code = CAPWAP_PKTS.parse_message_elements(
                capwap_bytes, capwap_hlen, self.ap, self)


            if result_code in (None, 0, 2) and ctrl_header_type == expected_response_type:
                # good
                return True
            elif result_code != -1:
                # non expected response
                self.ap.logger.warn('Service %s control round trip: Not successful result %s - %s for response type %d.' % (self.name, result_code, capwap_result_codes.get(result_code, 'Unknown'), ctrl_header_type))
                return False
            else:
                continue

        # timeout
        self.ap.logger.info(
                "Service {} control round trip: rollback: timeout: too many trials".format(self.name))
        return False
Exemplo n.º 5
0
 def get_echo_capwap(self):
     if 'echo_pkt' in self._scapy_cache:
         self._scapy_cache['echo_pkt'][20] = struct.pack(
             '>B', self.get_capwap_seq())
     else:
         self._scapy_cache['echo_pkt'] = c_buffer(
             bytes(CAPWAP_PKTS.echo(self)))
     return self._scapy_cache['echo_pkt']
Exemplo n.º 6
0
 def get_echo_capwap(self):
     """"Return a Echo Request capwap control packet layer (payload of capwap)."""
     if 'echo_pkt' in self._scapy_cache:
         self._scapy_cache['echo_pkt'][20] = struct.pack(
             '!B', self.get_capwap_seq())
     else:
         self._scapy_cache['echo_pkt'] = CAPWAP_PKTS.echo(self)
     return self._scapy_cache['echo_pkt']
Exemplo n.º 7
0
    def get_config_update_capwap(self, seq):
        """Return a configuration update response (capwap packet, payload of udp) with given sequence number.

        Args:
            seq: the sequence number of the capwap control header
        """
        if 'config_update' in self._scapy_cache:
            self._scapy_cache['config_update'][20] = struct.pack('!B', seq)
        else:
            self._scapy_cache['config_update'] = CAPWAP_PKTS.config_update(
                self, seq)
        return self._scapy_cache['config_update']
Exemplo n.º 8
0
    def run_with_buffer(self):
        from ..trex_wireless_config import config

        def rollback(reason=None):
            if reason:
                self.ap.logger.info("Service ApJoinWLC rollback: %s" % reason)
            self.ap.state = APState.DISCOVER
            return ('service',
                    ServiceAPDiscoverWLC(self.worker, self.ap, self.env,
                                         self.topics_to_subs))

        try:

            while True:
                if self.ap.state != APState.JOIN:
                    return

                self.ap.logger.info("Service ApJoinWLC started")

                self.ap.active_service = self

                self.ap.logger.debug('Sending Join Request')
                join_req = CAPWAP_PKTS.join(self.ap)

                ctrl_gen = self.control_round_trip(join_req,
                                                   4,
                                                   debug_msg='Join Request')
                send_data = None
                while True:
                    action = ctrl_gen.send(send_data)
                    if action in ('good_resp', 'time', 'dtls_broke', 'err'):
                        ctrl_gen.close()
                        break
                    else:
                        send_data = yield action
                if action == 'dtls_broke':
                    yield (rollback("dtls session broken"))
                    return
                elif action == 'time':
                    yield rollback("timeout: join request")
                    return
                elif action == 'err':
                    yield rollback("error")
                    return

                self.ap.logger.debug('Got Join Response')

                self.ap.logger.debug('Sending Configuration Status Request')
                ctrl_gen = self.control_round_trip(
                    CAPWAP_PKTS.conf_status_req(self.ap),
                    6,
                    debug_msg='Config status request')
                send_data = None
                while True:
                    action = ctrl_gen.send(send_data)
                    if action in ('good_resp', 'time', 'dtls_broke', 'err'):
                        ctrl_gen.close()
                        break
                    else:
                        send_data = yield action
                if action == 'dtls_broke':
                    yield (rollback("dtls session broken"))
                    return
                elif action == 'time':
                    yield rollback("timeout: join request")
                    return
                elif action == 'err':
                    yield rollback("error")
                    return

                self.ap.logger.debug('Got Configuration Status Response')

                self.ap.logger.debug('Sending Change State Event Request')
                ctrl_gen = self.control_round_trip(
                    CAPWAP_PKTS.change_state(self.ap, radio_id=0),
                    12,
                    debug_msg='Change state event request')
                send_data = None
                while True:
                    action = ctrl_gen.send(send_data)
                    if action in ('good_resp', 'time', 'dtls_broke', 'err'):
                        ctrl_gen.close()
                        break
                    else:
                        send_data = yield action
                        if action == "err":
                            break
                if action == 'dtls_broke':
                    yield (rollback("dtls session broken"))
                    return
                elif action == 'time':
                    yield rollback("timeout: join request")
                    return
                elif action == 'err':
                    yield rollback("error")
                    return

                self.ap.logger.debug('Got Change State Event Response')

                self.ap.logger.debug('Sending Change State Event Request')
                ctrl_gen = self.control_round_trip(
                    CAPWAP_PKTS.change_state(self.ap, radio_id=1),
                    12,
                    debug_msg='Change state event request')
                send_data = None
                while True:
                    action = ctrl_gen.send(send_data)
                    if action in ('good_resp', 'time', 'dtls_broke', 'err'):
                        ctrl_gen.close()
                        break
                    else:
                        send_data = yield action
                        if action == "err":
                            break
                if action == 'dtls_broke':
                    yield (rollback("dtls session broken"))
                    return
                elif action == 'time':
                    yield rollback("timeout: join request")
                    return
                elif action == 'err':
                    yield rollback("error")
                    return

                self.ap.logger.debug('Got Change State Event Response')

                self.ap.logger.debug(
                    'Going to ack all config updates and try to get SSID')

                # ack all config updates in worker_traffic_handler thread
                # while not self.ap.last_recv_ts or self.ap.last_recv_ts + 5 >= time.time():
                #     self.waiting_on = simpy.events.Event(self.env)
                #     yield ("process_with_timeout", self.waiting_on, 5)
                #     del self.waiting_on

                #     if not self.ap.is_dtls_established:
                #         yield rollback("dtls not established")
                #         return
                #     elif self.ap.SSID:
                #         break
                #     if not self.ap.last_recv_ts:
                #         break

                self.waiting_on = simpy.events.Event(self.env)
                yield ("process_with_timeout", self.waiting_on,
                       config.capwap.specific.ssid_timeout)
                del self.waiting_on

                if not self.ap.SSID:
                    yield rollback("no SSID")
                    return

                self.ap.logger.info(
                    "received SSID, proceding with sending data keep_alive")

                RetransmitInterval = config.capwap.retransmit_interval
                for _ in range(config.capwap.max_retransmit):
                    if self.ap.state == APState.RUN:
                        break
                    if not self.ap.is_dtls_established:
                        yield rollback("dtls not established")
                        return
                    RetransmitInterval *= 2
                    tx_pkt = self.ap.wrap_capwap_pkt(CAPWAP_PKTS.keep_alive(
                        self.ap),
                                                     dst_port=5247)

                    self.ap.logger.debug("Sending keep-alive")
                    yield ('put', tx_pkt)

                    self.waiting_on = simpy.events.Event(self.env)
                    yield ("process_with_timeout", self.waiting_on,
                           RetransmitInterval)
                    del self.waiting_on

                    if self.ap.got_keep_alive:
                        self.ap.got_keep_alive = False
                        self.ap.logger.debug('Received Keep-alive response.')
                        self.ap.last_echo_req_ts = time.time()
                        self.ap.join_time = time.time()
                        self.ap.join_duration = self.ap.join_time - self.ap.start_join_time
                        self.ap.state = APState.RUN
                        self.ap.logger.info("Service ApJoinWLC finished")
                        # release spot
                        yield ("done_ap")
                        yield ('service',
                               ServiceAPRun(self.worker, self.ap, self.env,
                                            self.topics_to_subs))
                        return
                    if not self.ap.is_dtls_established:
                        break

                # timeout

                if not self.ap.is_dtls_established:
                    yield rollback("DTLS session broken")
                    return
                # too many trials or failure
                if self.ap.state == APState.JOIN:
                    yield rollback("too many trials")
                    return
        except simpy.events.Interrupt:
            self.ap.logger.debug("Service APJoinWLC interrupted")
            return True
Exemplo n.º 9
0
    def run_with_buffer(self):
        from ..trex_wireless_config import config

        # request a slot
        yield ("start_ap")

        self.ap.logger.info("Service DiscoverWLC started")

        self.ap.start_join_time = time.time()

        while True:

            if self.ap.state > APState.DISCOVER:
                return

            yield ("service",
                   ServiceAPShutdownDTLS(self.worker, self.ap, self.env,
                                         self.topics_to_subs))

            self.ap.reset_vars()

            self.ap.state = APState.DISCOVER

            self.ap.active_service = self

            self.ap._create_ssl(config.openssl.buffer_size)

            self.ap.rx_responses[2] = -1

            self.ap.retries += 1

            # First resolve WLC MAC if needed
            if self.ap.wlc_ip_bytes and not self.ap.wlc_mac_bytes:
                self.ap.logger.info("Resolving WLC MAC for IP: %s" %
                                    self.ap.wlc_ip)
                while not self.ap.wlc_mac_bytes:
                    RetransmitInterval = config.capwap.retransmit_interval
                    for _ in range(config.capwap.max_retransmit):
                        if self.ap.wlc_mac_bytes:
                            break
                        RetransmitInterval *= 2
                        self.ap.logger.debug("sending who-as for WLC IP")
                        arp = self.ap.get_arp_pkt(
                            'who-has',
                            src_mac_bytes=self.ap.mac_bytes,
                            src_ip_bytes=self.ap.ip_bytes,
                            dst_ip_bytes=self.ap.wlc_ip_bytes)
                        yield ('put', arp)

                        # waiting for an arp response
                        self.waiting_on = simpy.events.Event(self.env)
                        yield ("process_with_timeout", self.waiting_on,
                               RetransmitInterval)
                        del self.waiting_on

                        if self.ap.wlc_mac_bytes:
                            self.ap.logger.debug("got MAC of WLC")
                            # done
                            break

            if self.ap.wlc_ip_bytes and not self.ap.wlc_mac_bytes:
                self.err(
                    'err', 'Unable to resolve MAC address of WLC for %s' %
                    self.ap.wlc_ip)

            RetransmitInterval = config.capwap.retransmit_interval
            for _ in range(config.capwap.max_retransmit):
                RetransmitInterval *= 2
                discovery_pkt = self.ap.wrap_capwap_pkt(CAPWAP_PKTS.discovery(
                    self.ap),
                                                        is_discovery=True)
                self.ap.logger.debug("sending discovery request to WLC")
                yield ('put', discovery_pkt)

                self.waiting_on = simpy.events.Event(self.env)
                yield ("process_with_timeout", self.waiting_on,
                       RetransmitInterval)
                del self.waiting_on

                try:
                    result_code = self.ap.rx_responses[2]
                except KeyError:
                    result_code = -1
                    yield ("err", 'No response')
                if result_code in (None, 0, 2):
                    self.ap.state = APState.DTLS
                    self.ap.logger.info("Service DiscoverWLC finished")
                    yield ("service",
                           ServiceAPEstablishDTLS(self.worker, self.ap,
                                                  self.env,
                                                  self.topics_to_subs))
                elif result_code != -1:
                    self.ap.wlc_mac_bytes = None
                    self.ap.wlc_mac = None
                    yield ("err", 'Not successful result %s - %s.' %
                           (result_code,
                            capwap_result_codes.get(result_code, 'Unknown')))
                    break

            self.ap.logger.info("DiscoverWLC retries expired")