예제 #1
0
    def ssid(self, ssid):
        """ Set the ssid. """

        if not ssid or ssid == SSID(b'\0'):
            self._ssid = None
        else:
            self._ssid = ssid
예제 #2
0
        def validate_ssid(value):

            try:
                SSID(value)
            except ValueError:
                msg = '%r is not a valid SSID.' % value
                raise ValidationError(msg)
예제 #3
0
    def handle_response(self, response, wtp, _):
        """Handle WSS_RESPONSE message."""

        block_id = response.iface_id

        # init data structures for the incoming block
        self.slice_stats[block_id] = {}

        for entry in response.entries:

            ssid = SSID(entry.ssid)

            if str(ssid) not in self.slice_stats[block_id]:
                self.slice_stats[block_id][str(ssid)] = {}

            self.slice_stats[block_id][str(ssid)][entry.slice_id] = {
                "deficit_used": entry.deficit_used,
                "max_queue_length": entry.max_queue_length,
                "tx_packets": entry.tx_packets,
                "tx_bytes": entry.tx_bytes,
            }

        # update wifi_stats module
        block = wtp.blocks[block_id]
        block.slice_stats = self.slice_stats[block_id]

        # handle callbacks
        self.handle_callbacks("slice_stats")
예제 #4
0
    def to_python(cls, value):
        """Convert value back to Python."""

        try:
            return SSID(value)
        except ValueError:
            msg = '%r is not a valid SSID.' % value
            raise ValidationError(msg)
예제 #5
0
    def _handle_slice_status_response(self, status):
        """Handle an incoming SLICE_STATUS_RESPONSE message."""

        iface_id = status.iface_id
        slice_id = str(status.slice_id)
        ssid = SSID(status.ssid)

        project = self.manager.projects_manager.load_project_by_ssid(ssid)
        block = self.device.blocks[iface_id]

        if not project:
            self.log.warning("Slice status from unknown SSID %s", ssid)
            return

        if slice_id not in project.wifi_slices:
            self.log.warning("Slice %s not found. Removing slice.", slice_id)
            self.send_del_slice(project, int(slice_id), block)
            return

        slc = project.wifi_slices[slice_id]

        if slc.properties['quantum'] != status.quantum:
            if self.device.addr not in slc.devices:
                slc.devices[self.device.addr] = dict()
            slc.devices[self.device.addr]['quantum'] = status.quantum

        amsdu_aggregation = bool(status.flags.amsdu_aggregation)
        if slc.properties['amsdu_aggregation'] != amsdu_aggregation:
            if self.device.addr not in slc.devices:
                slc.devices[self.device.addr] = dict()
            slc.devices[self.device.addr]['amsdu_aggregation'] = \
                amsdu_aggregation

        if slc.properties['sta_scheduler'] != status.sta_scheduler:
            if self.device.addr not in slc.devices:
                slc.devices[self.device.addr] = dict()
            slc.devices[self.device.addr]['sta_scheduler'] = \
                status.sta_scheduler

        project.save()
        project.refresh_from_db()

        self.log.info("Slice status: %s", slc)
예제 #6
0
    def send_add_lvap_request(self, lvap, block, set_mask):
        """Send a ADD_LVAP message."""

        flags = Container(ht_caps=lvap.ht_caps,
                          authenticated=lvap.authentication_state,
                          associated=lvap.association_state,
                          set_mask=set_mask)

        encap = EtherAddress("00:00:00:00:00:00")
        if lvap.encap:
            encap = lvap.encap

        bssid = EtherAddress()
        if lvap.bssid:
            bssid = lvap.bssid

        ssid = SSID()
        if lvap.ssid:
            ssid = lvap.ssid

        msg = Container(length=80,
                        flags=flags,
                        assoc_id=lvap.assoc_id,
                        iface_id=block.block_id,
                        ht_caps_info=Container(**lvap.ht_caps_info),
                        sta=lvap.addr.to_raw(),
                        encap=encap.to_raw(),
                        bssid=bssid.to_raw(),
                        ssid=ssid.to_raw(),
                        networks=[])

        for network in lvap.networks:
            msg.length = msg.length + 6 + WIFI_NWID_MAXSIZE + 1
            msg.networks.append(
                Container(bssid=network[0].to_raw(), ssid=network[1].to_raw()))

        return self.send_message(self.proto.PT_ADD_LVAP_REQUEST, msg,
                                 lvap.handle_add_lvap_response)
예제 #7
0
    def _handle_vap_status_response(self, status):
        """Handle an incoming STATUS_VAP message."""

        bssid = EtherAddress(status.bssid)
        ssid = SSID(status.ssid)

        project = self.manager.projects_manager.load_project_by_ssid(ssid)

        if not project:
            self.log.warning("Unable to find SSID %s", ssid)
            self.send_del_vap(bssid)
            return

        # If the VAP does not exists, then create a new one
        if bssid not in self.manager.vaps:

            incoming = self.device.blocks[status.iface_id]

            self.manager.vaps[bssid] = VAP(bssid, incoming,
                                           project.wifi_props.ssid)

        vap = self.manager.vaps[bssid]

        self.log.info("VAP status %s", vap)
예제 #8
0
    def _handle_lvap_status_response(self, status):
        """Handle an incoming LVAP_STATUS_RESPONSE message."""

        sta = EtherAddress(status.sta)

        # If the LVAP does not exists, then create a new one
        if sta not in self.manager.lvaps:
            self.manager.lvaps[sta] = \
                LVAP(sta, assoc_id=status.assoc_id, state=PROCESS_RUNNING)

        lvap = self.manager.lvaps[sta]

        # update LVAP params
        lvap.encap = EtherAddress(status.encap)
        lvap.authentication_state = bool(status.flags.authenticated)
        lvap.association_state = bool(status.flags.associated)
        lvap.ht_caps = bool(status.flags.ht_caps)
        lvap.ht_caps_info = dict(status.ht_caps_info)
        del lvap.ht_caps_info['_io']

        ssid = SSID(status.ssid)
        if ssid == SSID():
            ssid = None

        bssid = EtherAddress(status.bssid)
        if bssid == EtherAddress("00:00:00:00:00:00"):
            bssid = None

        lvap.bssid = bssid

        incoming = self.device.blocks[status.iface_id]

        if status.flags.set_mask:
            lvap.downlink = incoming
        else:
            lvap.uplink.append(incoming)

        # if this is not a DL+UL block then stop here
        if not status.flags.set_mask:
            return

        # if an SSID is set and the incoming SSID is different from the
        # current one then raise an LVAP leave event
        if lvap.ssid and ssid != lvap.ssid:
            self.send_client_leave_message_to_self(lvap)
            lvap.ssid = None

        # if the incoming ssid is not none then raise an lvap join event
        if ssid:
            lvap.ssid = ssid
            self.send_client_join_message_to_self(lvap)

        # udpate networks
        networks = list()

        for network in status.networks:
            incoming = (EtherAddress(network.bssid), SSID(network.ssid))
            networks.append(incoming)

        lvap.networks = networks

        self.log.info("LVAP status: %s", lvap)
예제 #9
0
    def _handle_assoc_request(self, request):
        """Handle an incoming ASSOC_REQUEST message."""

        sta = EtherAddress(request.sta)

        ht_caps = request.flags.ht_caps
        ht_caps_info = dict(request.ht_caps_info)
        del ht_caps_info['_io']

        if sta not in self.manager.lvaps:
            self.log.info("Assoc request from unknown LVAP %s", sta)
            return

        lvap = self.manager.lvaps[sta]

        incoming_bssid = EtherAddress(request.bssid)

        if lvap.bssid != incoming_bssid:
            self.log.info("Assoc request for invalid BSSID %s", incoming_bssid)
            return

        incoming_ssid = SSID(request.ssid)

        # Check if the requested SSID is from a unique project
        for project in self.manager.projects_manager.projects.values():

            if not project.wifi_props:
                continue

            if project.wifi_props.bssid_type == T_BSSID_TYPE_SHARED:
                continue

            bssid = project.generate_bssid(lvap.addr)

            if bssid != incoming_bssid:
                self.log.info("Invalid BSSID %s", incoming_bssid)
                continue

            if project.wifi_props.ssid == incoming_ssid:
                lvap.bssid = incoming_bssid
                lvap.authentication_state = True
                lvap.association_state = True
                lvap.ssid = incoming_ssid
                lvap.ht_caps = ht_caps
                lvap.ht_caps_info = ht_caps_info
                lvap.commit()
                self.send_assoc_response(lvap)
                return

        # Check if the requested SSID is from a unique project
        for project in self.manager.projects_manager.projects.values():

            if not project.wifi_props:
                continue

            if project.wifi_props.bssid_type == T_BSSID_TYPE_UNIQUE:
                continue

            if incoming_bssid not in project.vaps:
                self.log.info("Invalid BSSID %s", incoming_bssid)
                continue

            if project.wifi_props.ssid == incoming_ssid:
                lvap.bssid = incoming_bssid
                lvap.authentication_state = True
                lvap.association_state = True
                lvap.ssid = incoming_ssid
                lvap.ht_caps = ht_caps
                lvap.ht_caps_info = ht_caps_info
                lvap.commit()
                self.send_assoc_response(lvap)
                return

        self.log.info("Unable to find SSID %s", incoming_ssid)
예제 #10
0
    def _handle_probe_request(self, request):
        """Handle an incoming PROBE_REQUEST message."""

        # Get station
        sta = EtherAddress(request.sta)

        # Incoming
        incoming_ssid = SSID(request.ssid)
        iface_id = request.iface_id
        ht_caps = request.flags.ht_caps
        ht_caps_info = dict(request.ht_caps_info)
        del ht_caps_info['_io']

        msg = "Probe request from %s ssid %s iface_id %u ht_caps %u"

        if not incoming_ssid:
            self.log.debug(msg, sta, "Broadcast", iface_id, ht_caps)
        else:
            self.log.debug(msg, sta, incoming_ssid, iface_id, ht_caps)

        # Check is station is in ACL of any networks
        networks = self.manager.projects_manager.get_available_ssids(sta)

        if not networks:
            self.log.debug("No SSID available at this device")
            return

        # If lvap does not exist then create it. Otherwise just refresh the
        # list of available networks
        if sta not in self.manager.lvaps:

            # spawn new LVAP
            self.log.info("Spawning new LVAP %s on %s", sta, self.device.addr)

            assoc_id = randint(1, 2007)

            lvap = LVAP(sta, assoc_id=assoc_id)
            lvap.networks = networks
            lvap.ht_caps = ht_caps
            lvap.ht_caps_info = ht_caps_info

            # this will trigger an LVAP ADD message
            lvap.blocks = self.device.blocks[request.iface_id]

            # save LVAP in the runtime
            self.manager.lvaps[sta] = lvap

            # Send probe response
            self.send_probe_response(lvap, incoming_ssid)

            return

        lvap = self.manager.lvaps[sta]

        # If this probe request is not coming from the same interface on which
        # this LVAP is currenly running then ignore the probe
        if lvap.blocks[0].block_id != iface_id:
            return

        # If LVAP is not running then ignore
        if not lvap.is_running():
            return

        # Update list of available networks
        lvap.networks = networks
        lvap.commit()

        # Send probe response
        self.send_probe_response(lvap, incoming_ssid)