def _handle_probe_request(self, request):
        """Handle an incoming PROBE_REQUEST message.
        Args:
            request, a PROBE_REQUEST message
        Returns:
            None
        """

        wtp_addr = EtherAddress(request.wtp)

        try:
            wtp = RUNTIME.wtps[wtp_addr]
        except KeyError:
            LOG.info("Probe request from unknown WTP (%s)", wtp_addr)
            return

        if not wtp.connection:
            LOG.info("Probe request from disconnected WTP %s", wtp_addr)
            return

        sta = EtherAddress(request.sta)

        if sta in RUNTIME.lvaps:
            return

        if not RUNTIME.is_allowed(sta):
            return

        if RUNTIME.is_denied(sta):
            return

        ssid = SSID(request.ssid)

        if request.ssid == b'':
            LOG.info("Probe request from %s ssid %s", sta, "Broadcast")
        else:
            LOG.info("Probe request from %s ssid %s", sta, ssid)

        # generate list of available SSIDs
        ssids = set()

        for tenant in RUNTIME.tenants.values():
            if tenant.bssid_type == T_TYPE_SHARED:
                continue
            for wtp_in_tenant in tenant.wtps.values():
                if wtp_addr == wtp_in_tenant.addr:
                    ssids.add(tenant.tenant_name)

        if not ssids:
            LOG.info("No SSIDs available at this WTP")
            return

        # spawn new LVAP
        LOG.info("Spawning new LVAP %s on %s", sta, wtp.addr)
        net_bssid = generate_bssid(BASE_MAC, sta)
        lvap = LVAP(sta, net_bssid, net_bssid)
        lvap._ssids = ssids

        RUNTIME.lvaps[sta] = lvap

        # TODO: This should be built starting from the probe request
        lvap.supports.add(ResourceBlock(lvap, sta, 1, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 2, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 3, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 4, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 5, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 6, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 7, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 8, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 9, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 10, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 11, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 36, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 48, BT_L20))

        # This will trigger an LVAP ADD message (and REMOVE if necessary)
        requested = ResourcePool()
        hwaddr = EtherAddress(request.hwaddr)
        channel = request.channel
        band = request.band
        requested.add(ResourceBlock(wtp, hwaddr, channel, band))

        lvap.scheduled_on = wtp.supports & requested

        LOG.info("Sending probe response to %s", lvap.addr)
        self.send_probe_response(lvap)
    def _handle_status_lvap(self, status):
        """Handle an incoming STATUS_LVAP message.
        Args:
            status, a STATUS_LVAP message
        Returns:
            None
        """

        wtp_addr = EtherAddress(status.wtp)

        try:
            wtp = RUNTIME.wtps[wtp_addr]
        except KeyError:
            LOG.info("Status from unknown WTP %s", wtp_addr)
            return

        if not wtp.connection:
            LOG.info("Status from disconnected WTP %s", wtp_addr)
            return

        sta_addr = EtherAddress(status.sta)
        set_mask = bool(status.flags.set_mask)

        lvap = None
        hwaddr = EtherAddress(status.hwaddr)
        block = ResourceBlock(wtp, hwaddr, status.channel, status.band)

        LOG.info("LVAP status update from %s", sta_addr)

        # If the LVAP does not exists, then create a new one
        if sta_addr not in RUNTIME.lvaps:

            net_bssid_addr = EtherAddress(status.net_bssid)
            lvap_bssid_addr = EtherAddress(status.lvap_bssid)
            lvap = LVAP(sta_addr, net_bssid_addr, lvap_bssid_addr)

            # TODO: This should be built starting from the status message
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 1, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 2, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 3, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 4, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 5, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 6, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 7, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 8, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 9, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 10, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 11, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 36, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 48, BT_L20))

            RUNTIME.lvaps[sta_addr] = lvap

        lvap = RUNTIME.lvaps[sta_addr]

        # incoming block
        pool = ResourcePool()
        pool.add(block)

        match = wtp.supports & pool

        if not match:
            LOG.error("Incoming block %s is invalid", block)
            return

        # this will try to updated the lvap object with the resource block
        # coming in this status update message.
        try:

            if set_mask:

                # set downlink+uplink block
                lvap._downlink.setitem(block, RadioPort(lvap, block))

            else:

                # set uplink only blocks
                lvap._uplink.setitem(block, RadioPort(lvap, block))

        except ValueError:
            LOG.error("Error while importing block %s, removing.", block)
            block.radio.connection.send_del_lvap(lvap)
            return

        lvap.authentication_state = bool(status.flags.authenticated)
        lvap.association_state = bool(status.flags.associated)

        lvap._assoc_id = status.assoc_id
        lvap._encap = EtherAddress(status.encap)
        ssids = [SSID(x.ssid) for x in status.ssids]

        if lvap.ssid:

            # Raise LVAP leave event
            LOG.info("LVAP LEAVE %s (%s)", lvap.addr, lvap.ssid)
            for handler in self.server.pt_types_handlers[PT_LVAP_LEAVE]:
                handler(lvap)

            # removing LVAP from tenant, need first to look for right tenant
            if lvap.addr in lvap.tenant.lvaps:
                LOG.info("Removing %s from tenant %s", lvap.addr, lvap.ssid)
                del lvap.tenant.lvaps[lvap.addr]

        lvap._tenant = None

        if ssids[0]:

            # setting tenant without seding out add lvap message
            lvap._tenant = RUNTIME.load_tenant(ssids[0])

            # adding LVAP to tenant
            LOG.info("Adding %s to tenant %s", lvap.addr, ssids[0])
            lvap.tenant.lvaps[lvap.addr] = lvap

            # Raise LVAP join event
            LOG.info("LVAP JOIN %s (%s)", lvap.addr, lvap.ssid)
            for handler in self.server.pt_types_handlers[PT_LVAP_JOIN]:
                handler(lvap)

        # update remaining ssids
        lvap._ssids = ssids[1:]

        # set ports
        lvap.set_ports()

        LOG.info("LVAP status %s", lvap)
    def _handle_probe_request(self, wtp, request):
        """Handle an incoming PROBE_REQUEST message.
        Args:
            request, a PROBE_REQUEST message
        Returns:
            None
        """

        # Check if block is valid
        valid = wtp.get_block(request.hwaddr, request.channel, request.band)

        if not valid:
            self.log.warning("No valid intersection found. Ignoring request.")
            return

        # check is station is in ACL
        sta = EtherAddress(request.sta)

        if not RUNTIME.is_allowed(sta):
            return

        # Requested BSSID
        incoming_ssid = SSID(request.ssid)

        if incoming_ssid == b'':
            self.log.info("Probe request from %s ssid %s", sta, "Broadcast")
        else:
            self.log.info("Probe request from %s ssid %s", sta, incoming_ssid)

        # generate list of available networks
        networks = list()

        for tenant in RUNTIME.tenants.values():
            if tenant.bssid_type == T_TYPE_SHARED:
                continue
            for wtp_in_tenant in tenant.wtps.values():
                if wtp.addr == wtp_in_tenant.addr:
                    bssid = tenant.generate_bssid(sta)
                    ssid = tenant.tenant_name
                    networks.append((bssid, ssid))

        if not networks:
            self.log.info("No Networks available at this WTP")
            return

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

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

            assoc_id = RUNTIME.assoc_id()

            lvap = LVAP(sta, assoc_id=assoc_id)
            lvap.networks = networks
            lvap.supported_band = request.supported_band

            # this will trigger an LVAP ADD message
            lvap.blocks = valid[0]

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

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

            return

        # Update networks
        lvap = RUNTIME.lvaps[sta]
        lvap.networks = networks
        lvap.commit()

        # Send probe response
        if lvap.wtp == wtp:
            self.send_probe_response(lvap, incoming_ssid)
    def _handle_status_lvap(self, wtp, status):
        """Handle an incoming STATUS_LVAP message.
        Args:
            status, a STATUS_LVAP message
        Returns:
            None
        """

        sta = EtherAddress(status.sta)

        # Check if block is valid
        valid = wtp.get_block(status.hwaddr, status.channel, status.band)

        if not valid:
            self.log.warning("No valid intersection found. Removing block.")
            wtp.connection.send_del_lvap(sta)
            return

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

        lvap = RUNTIME.lvaps[sta]

        # update LVAP params
        lvap.supported_band = status.supported_band
        lvap.encap = EtherAddress(status.encap)
        lvap.authentication_state = bool(status.flags.authenticated)
        lvap.association_state = bool(status.flags.associated)

        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

        set_mask = status.flags.set_mask

        # received downlink block but a different downlink block is already
        # present, delete before going any further
        if set_mask and lvap.blocks[0] and lvap.blocks[0] != valid[0]:
            lvap.blocks[0].radio.connection.send_del_lvap(sta)

        if set_mask:
            lvap._downlink = valid[0]
        else:
            lvap._uplink.append(valid[0])

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

        # if an SSID is set and the incoming SSID is different from the
        # current one then raise an LVAP leave event and remove LVAP from the
        # current SSID
        if lvap.ssid and ssid != lvap.ssid:
            self.server.send_lvap_leave_message_to_self(lvap)
            del lvap.tenant.lvaps[lvap.addr]
            lvap.ssid = None

        # if the incoming ssid is not none then raise an lvap join event
        if ssid:
            lvap.ssid = ssid
            lvap.tenant.lvaps[lvap.addr] = lvap
            self.server.send_lvap_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)
Example #5
0
    def _handle_probe_request(self, request):
        """Handle an incoming PROBE_REQUEST message.
        Args:
            request, a PROBE_REQUEST message
        Returns:
            None
        """

        wtp_addr = EtherAddress(request.wtp)

        try:
            wtp = RUNTIME.wtps[wtp_addr]
        except KeyError:
            LOG.info("Probe request from unknown WTP (%s)", wtp_addr)
            return

        if not wtp.connection:
            LOG.info("Probe request from disconnected WTP %s", wtp_addr)
            return

        sta = EtherAddress(request.sta)

        if sta in RUNTIME.lvaps:
            return

        if not RUNTIME.is_allowed(sta):
            return

        if RUNTIME.is_denied(sta):
            return

        ssid = SSID(request.ssid)

        if request.ssid == b'':
            LOG.info("Probe request from %s ssid %s", sta, "Broadcast")
        else:
            LOG.info("Probe request from %s ssid %s", sta, ssid)

        # generate list of available SSIDs
        ssids = set()

        for tenant in RUNTIME.tenants.values():
            if tenant.bssid_type == T_TYPE_SHARED:
                continue
            for wtp_in_tenant in tenant.wtps.values():
                if wtp_addr == wtp_in_tenant.addr:
                    ssids.add(tenant.tenant_name)

        if not ssids:
            LOG.info("No SSIDs available at this WTP")
            return

        # spawn new LVAP
        LOG.info("Spawning new LVAP %s on %s", sta, wtp.addr)
        net_bssid = generate_bssid(BASE_MAC, sta)
        lvap = LVAP(sta, net_bssid, net_bssid)
        lvap.set_ssids(ssids)

        RUNTIME.lvaps[sta] = lvap

        # TODO: This should be built starting from the probe request
        lvap.supports.add(ResourceBlock(lvap, sta, 1, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 2, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 3, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 4, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 5, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 6, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 7, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 8, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 9, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 10, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 11, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 36, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 48, BT_L20))

        # This will trigger an LVAP ADD message (and REMOVE if necessary)
        requested = ResourcePool()
        hwaddr = EtherAddress(request.hwaddr)
        channel = request.channel
        band = request.band
        requested.add(ResourceBlock(wtp, hwaddr, channel, band))

        lvap.scheduled_on = wtp.supports & requested

        LOG.info("Sending probe response to %s", lvap.addr)
        self.send_probe_response(lvap)
Example #6
0
    def _handle_status_lvap(self, status):
        """Handle an incoming STATUS_LVAP message.
        Args:
            status, a STATUS_LVAP message
        Returns:
            None
        """

        wtp_addr = EtherAddress(status.wtp)

        try:
            wtp = RUNTIME.wtps[wtp_addr]
        except KeyError:
            LOG.info("Status from unknown WTP %s", wtp_addr)
            return

        if not wtp.connection:
            LOG.info("Status from disconnected WTP %s", wtp_addr)
            return

        sta_addr = EtherAddress(status.sta)
        set_mask = bool(status.flags.set_mask)

        lvap = None
        hwaddr = EtherAddress(status.hwaddr)
        block = ResourceBlock(wtp, hwaddr, status.channel, status.band)

        LOG.info("LVAP status update from %s", sta_addr)

        # If the LVAP does not exists, then create a new one
        if sta_addr not in RUNTIME.lvaps:

            net_bssid_addr = EtherAddress(status.net_bssid)
            lvap_bssid_addr = EtherAddress(status.lvap_bssid)
            lvap = LVAP(sta_addr, net_bssid_addr, lvap_bssid_addr)

            # TODO: This should be built starting from the status message
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 1, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 2, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 3, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 4, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 5, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 6, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 7, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 8, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 9, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 10, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 11, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 36, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 48, BT_L20))

            RUNTIME.lvaps[sta_addr] = lvap

        lvap = RUNTIME.lvaps[sta_addr]

        # incoming block
        pool = ResourcePool()
        pool.add(block)

        match = wtp.supports & pool

        if not match:
            LOG.error("Incoming block %s is invalid", block)
            return

        block = match.pop()

        # this will try to updated the lvap object with the resource block
        # coming in this status update message.
        try:

            if set_mask:

                # set downlink+uplink block
                lvap._downlink.setitem(block, RadioPort(lvap, block))

            else:

                # set uplink only blocks
                lvap._uplink.setitem(block, RadioPort(lvap, block))

        except ValueError:
            LOG.error("Error while importing block %s, removing.", block)
            block.radio.connection.send_del_lvap(lvap)
            return

        lvap.authentication_state = bool(status.flags.authenticated)
        lvap.association_state = bool(status.flags.associated)

        lvap._assoc_id = status.assoc_id
        lvap._encap = EtherAddress(status.encap)
        ssids = [SSID(x.ssid) for x in status.ssids]

        if lvap.ssid:

            # Raise LVAP leave event
            LOG.info("LVAP LEAVE %s (%s)", lvap.addr, lvap.ssid)
            for handler in self.server.pt_types_handlers[PT_LVAP_LEAVE]:
                handler(lvap)

            # removing LVAP from tenant, need first to look for right tenant
            if lvap.addr in lvap.tenant.lvaps:
                LOG.info("Removing %s from tenant %s", lvap.addr, lvap.ssid)
                del lvap.tenant.lvaps[lvap.addr]

        lvap._tenant = None

        if ssids[0]:

            # setting tenant without seding out add lvap message
            lvap._tenant = RUNTIME.load_tenant(ssids[0])

            # adding LVAP to tenant
            LOG.info("Adding %s to tenant %s", lvap.addr, ssids[0])
            lvap.tenant.lvaps[lvap.addr] = lvap

            # Raise LVAP join event
            LOG.info("LVAP JOIN %s (%s)", lvap.addr, lvap.ssid)
            for handler in self.server.pt_types_handlers[PT_LVAP_JOIN]:
                handler(lvap)

        # update remaining ssids
        lvap._ssids = ssids[1:]

        # set ports
        lvap.set_ports()

        LOG.info("LVAP status %s", lvap)
Example #7
0
    def _handle_probe_request(self, wtp, request):
        """Handle an incoming PROBE_REQUEST message.
        Args:
            request, a PROBE_REQUEST message
        Returns:
            None
        """

        if not wtp.connection:
            LOG.info("Probe request from disconnected WTP %s", wtp.addr)
            self.stream.close()
            return

        if not wtp.port():
            LOG.info("WTP %s not ready", wtp.addr)
            return

        sta = EtherAddress(request.sta)

        if sta in RUNTIME.lvaps:
            return

        if not RUNTIME.is_allowed(sta):
            return

        if RUNTIME.is_denied(sta):
            return

        ssid = SSID(request.ssid)

        if request.ssid == b'':
            LOG.info("Probe request from %s ssid %s", sta, "Broadcast")
        else:
            LOG.info("Probe request from %s ssid %s", sta, ssid)

        # generate list of available SSIDs
        ssids = set()

        for tenant in RUNTIME.tenants.values():
            if tenant.bssid_type == T_TYPE_SHARED:
                continue
            for wtp_in_tenant in tenant.wtps.values():
                if wtp.addr == wtp_in_tenant.addr:
                    ssids.add(tenant.tenant_name)

        if not ssids:
            LOG.info("No SSIDs available at this WTP")
            return

        # spawn new LVAP
        LOG.info("Spawning new LVAP %s on %s", sta, wtp.addr)
        net_bssid = generate_bssid(BASE_MAC, sta)
        lvap = LVAP(sta, net_bssid, net_bssid)
        lvap.set_ssids(list(ssids))

        # set supported band
        lvap.supported_band = request.supported_band

        # Check if block is valid
        incoming = ResourceBlock(wtp, EtherAddress(request.hwaddr),
                                 request.channel, request.band)

        valid = [block for block in wtp.supports if block == incoming]

        if not valid:
            LOG.warning("No valid intersection found. Ignoring request.")
            return

        # This will trigger an LVAP ADD message (and REMOVE if necessary)
        lvap.blocks = valid[0]

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

        LOG.info("Sending probe response to %s", lvap.addr)
        self.send_probe_response(lvap, ssid)
Example #8
0
    def _handle_status_lvap(self, wtp, status):
        """Handle an incoming STATUS_LVAP message.
        Args:
            status, a STATUS_LVAP message
        Returns:
            None
        """

        if not wtp.connection:
            LOG.info("Status from disconnected WTP %s", wtp.addr)
            return

        sta = EtherAddress(status.sta)
        set_mask = bool(status.flags.set_mask)

        lvap = None

        accum = []
        incoming_ssids = [SSID(x.ssid) for x in status.ssids]

        accum.append("addr ")
        accum.append(EtherAddress(status.sta).to_str())
        accum.append(" net_bssid ")
        accum.append(EtherAddress(status.net_bssid).to_str())
        accum.append(" lvap_bssid ")
        accum.append(EtherAddress(status.lvap_bssid).to_str())

        accum.append(" ssid ")

        if incoming_ssids[0]:
            accum.append(incoming_ssids[0].to_str())
        else:
            accum.append("None")

        accum.append(" ssids [")

        for ssid in incoming_ssids[1:]:
            accum.append(" ")
            accum.append(ssid.to_str())

        accum.append(" ]")

        accum.append(" assoc_id ")
        accum.append(str(status.assoc_id))

        if bool(status.flags.authenticated):
            accum.append(" AUTH")

        if bool(status.flags.associated):
            accum.append(" ASSOC")

        LOG.info("LVAP status %s", ''.join(accum))

        # If the LVAP does not exists, then create a new one
        if sta not in RUNTIME.lvaps:

            net_bssid_addr = EtherAddress(status.net_bssid)
            lvap_bssid_addr = EtherAddress(status.lvap_bssid)
            lvap = LVAP(sta, net_bssid_addr, lvap_bssid_addr)

            RUNTIME.lvaps[sta] = lvap

        lvap = RUNTIME.lvaps[sta]

        # Check if block is valid
        incoming = ResourceBlock(wtp, EtherAddress(status.hwaddr),
                                 status.channel, status.band)

        valid = [block for block in wtp.supports if block == incoming]

        if not valid:
            LOG.warning("No valid intersection found. Removing block.")
            wtp.connection.send_del_lvap(lvap)
            return

        # this will try to updated the lvap object with the resource block
        # coming in this status update message.
        try:
            if set_mask:
                # set downlink+uplink block
                lvap._downlink.setitem(valid[0], RadioPort(lvap, valid[0]))
            else:
                # set uplink only blocks
                lvap._uplink.setitem(valid[0], RadioPort(lvap, valid[0]))
        except Exception as e:
            LOG.exception(e)
            LOG.error("Error while importing block %s, removing.", valid[0])
            wtp.connection.send_del_lvap(lvap)
            return

        # update LVAP ports
        lvap.ports[0] = VirtualPortLvap(phy_port=wtp.port(),
                                        virtual_port_id=0,
                                        lvap=lvap)

        # set supported band
        lvap.supported_band = status.supported_band

        # update LVAP params
        lvap.authentication_state = bool(status.flags.authenticated)
        lvap.association_state = bool(status.flags.associated)

        lvap._assoc_id = status.assoc_id
        lvap._encap = EtherAddress(status.encap)
        ssids = [SSID(x.ssid) for x in status.ssids]

        # update ssid
        if lvap.ssid:

            # Raise LVAP leave event
            self.server.send_lvap_leave_message_to_self(lvap)

            # removing LVAP from tenant, need first to look for right tenant
            if lvap.addr in lvap.tenant.lvaps:
                LOG.info("Removing %s from tenant %s", lvap.addr, lvap.ssid)
                del lvap.tenant.lvaps[lvap.addr]

            lvap._tenant = None

        # update remaining ssids
        lvap._ssids = ssids[1:]

        if ssids[0]:

            tenant = RUNTIME.load_tenant(ssids[0])

            if not tenant:
                LOG.info("LVAP %s from unknown tenant %s", lvap.addr, ssids[0])
                RUNTIME.remove_lvap(lvap.addr)
                return

            # setting tenant without seding out add lvap message
            lvap._tenant = tenant

            # adding LVAP to tenant
            LOG.info("Adding %s to tenant %s", lvap.addr, ssids[0])
            lvap.tenant.lvaps[lvap.addr] = lvap

            # Raise LVAP join event
            self.server.send_lvap_join_message_to_self(lvap)
    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)
    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)
    def _handle_status_lvap(self, wtp, status):
        """Handle an incoming STATUS_LVAP message.
        Args:
            status, a STATUS_LVAP message
        Returns:
            None
        """

        if not wtp.connection:
            LOG.info("Status from disconnected WTP %s", wtp.addr)
            return

        sta_addr = EtherAddress(status.sta)
        set_mask = bool(status.flags.set_mask)

        lvap = None

        LOG.info("LVAP status update from %s", sta_addr)

        # If the LVAP does not exists, then create a new one
        if sta_addr not in RUNTIME.lvaps:

            net_bssid_addr = EtherAddress(status.net_bssid)
            lvap_bssid_addr = EtherAddress(status.lvap_bssid)
            lvap = LVAP(sta_addr, net_bssid_addr, lvap_bssid_addr)

            RUNTIME.lvaps[sta_addr] = lvap

        lvap = RUNTIME.lvaps[sta_addr]

        # incoming block
        lvap.supported = ResourcePool()
        hwaddr = EtherAddress(status.hwaddr)
        channel = status.channel
        band = status.band
        lvap.supported.add(ResourceBlock(lvap, hwaddr, channel, band))

        match = wtp.supports & lvap.supported

        if not match:
            LOG.error("Incoming block %s is invalid", block)
            return

        block = match.pop()

        # this will try to updated the lvap object with the resource block
        # coming in this status update message.
        try:

            if set_mask:

                # set downlink+uplink block
                lvap._downlink.setitem(block, RadioPort(lvap, block))

            else:

                # set uplink only blocks
                lvap._uplink.setitem(block, RadioPort(lvap, block))

        except ValueError:
            LOG.error("Error while importing block %s, removing.", block)
            block.radio.connection.send_del_lvap(lvap)
            return

        lvap.authentication_state = bool(status.flags.authenticated)
        lvap.association_state = bool(status.flags.associated)

        lvap._assoc_id = status.assoc_id
        lvap._encap = EtherAddress(status.encap)
        ssids = [SSID(x.ssid) for x in status.ssids]

        if lvap.ssid:

            # Raise LVAP leave event
            self.server.send_lvap_leave_message_to_self(lvap)

            # removing LVAP from tenant, need first to look for right tenant
            if lvap.addr in lvap.tenant.lvaps:
                LOG.info("Removing %s from tenant %s", lvap.addr, lvap.ssid)
                del lvap.tenant.lvaps[lvap.addr]

        lvap._tenant = None

        if ssids[0]:

            tenant = RUNTIME.load_tenant(ssids[0])

            if not tenant:
                LOG.info("LVAP %s from unknown tenant %s", lvap.addr, ssids[0])
                RUNTIME.remove_lvap(lvap.addr)
                return

            # setting tenant without seding out add lvap message
            lvap._tenant = tenant

            # adding LVAP to tenant
            LOG.info("Adding %s to tenant %s", lvap.addr, ssids[0])
            lvap.tenant.lvaps[lvap.addr] = lvap

            # Raise LVAP join event
            self.server.send_lvap_join_message_to_self(lvap)

        # update remaining ssids
        lvap._ssids = ssids[1:]

        # set ports
        lvap.set_ports()

        LOG.info("LVAP status %s", lvap)
    def _handle_probe_request(self, wtp, request):
        """Handle an incoming PROBE_REQUEST message.
        Args:
            request, a PROBE_REQUEST message
        Returns:
            None
        """

        if not wtp.connection:
            LOG.info("Probe request from disconnected WTP %s", wtp.addr)
            self.stream.close()
            return

        if not wtp.port():
            LOG.info("WTP %s not ready", wtp.addr)
            return

        sta = EtherAddress(request.sta)

        if sta in RUNTIME.lvaps:
            return

        if not RUNTIME.is_allowed(sta):
            return

        if RUNTIME.is_denied(sta):
            return

        ssid = SSID(request.ssid)

        if request.ssid == b'':
            LOG.info("Probe request from %s ssid %s", sta, "Broadcast")
        else:
            LOG.info("Probe request from %s ssid %s", sta, ssid)

        # generate list of available SSIDs
        ssids = set()

        for tenant in RUNTIME.tenants.values():
            if tenant.bssid_type == T_TYPE_SHARED:
                continue
            for wtp_in_tenant in tenant.wtps.values():
                if wtp.addr == wtp_in_tenant.addr:
                    ssids.add(tenant.tenant_name)

        if not ssids:
            LOG.info("No SSIDs available at this WTP")
            return

        # spawn new LVAP
        LOG.info("Spawning new LVAP %s on %s", sta, wtp.addr)
        net_bssid = generate_bssid(BASE_MAC, sta)
        lvap = LVAP(sta, net_bssid, net_bssid)
        lvap.set_ssids(list(ssids))

        RUNTIME.lvaps[sta] = lvap

        # This will trigger an LVAP ADD message (and REMOVE if necessary)
        lvap.supported = ResourcePool()
        hwaddr = EtherAddress(request.hwaddr)
        channel = request.channel
        band = request.band
        lvap.supported.add(ResourceBlock(lvap, hwaddr, channel, band))

        lvap.scheduled_on = wtp.supports & lvap.supported

        LOG.info("Sending probe response to %s", lvap.addr)
        self.send_probe_response(lvap)
Example #13
0
    def _handle_status_lvap(self, wtp, status):
        """Handle an incoming STATUS_LVAP message.
        Args:
            status, a STATUS_LVAP message
        Returns:
            None
        """

        if not wtp.connection:
            LOG.info("Status from disconnected WTP %s", wtp.addr)
            return

        sta = EtherAddress(status.sta)
        set_mask = bool(status.flags.set_mask)

        lvap = None

        accum = []
        incoming_ssids = [SSID(x.ssid) for x in status.ssids]

        accum.append("addr ")
        accum.append(EtherAddress(status.sta).to_str())
        accum.append(" net_bssid ")
        accum.append(EtherAddress(status.net_bssid).to_str())
        accum.append(" lvap_bssid ")
        accum.append(EtherAddress(status.lvap_bssid).to_str())

        accum.append(" ssid ")

        if incoming_ssids[0]:
            accum.append(incoming_ssids[0].to_str())
        else:
            accum.append("None")

        accum.append(" ssids [")

        for ssid in incoming_ssids[1:]:
            accum.append(" ")
            accum.append(ssid.to_str())

        accum.append(" ]")

        accum.append(" assoc_id ")
        accum.append(str(status.assoc_id))

        if bool(status.flags.authenticated):
            accum.append(" AUTH")

        if bool(status.flags.associated):
            accum.append(" ASSOC")

        LOG.info("LVAP status %s", ''.join(accum))

        # If the LVAP does not exists, then create a new one
        if sta not in RUNTIME.lvaps:

            net_bssid_addr = EtherAddress(status.net_bssid)
            lvap_bssid_addr = EtherAddress(status.lvap_bssid)
            lvap = LVAP(sta, net_bssid_addr, lvap_bssid_addr)

            RUNTIME.lvaps[sta] = lvap

        lvap = RUNTIME.lvaps[sta]

        # Check if block is valid
        incoming = ResourceBlock(wtp, EtherAddress(status.hwaddr),
                                 status.channel, status.band)

        valid = [block for block in wtp.supports if block == incoming]

        if not valid:
            LOG.warning("No valid intersection found. Removing block.")
            wtp.connection.send_del_lvap(lvap)
            return

        # received downlink block but a different downlink block is already
        # present, delete before going any further
        if set_mask and lvap._downlink and lvap._downlink != valid[0]:
            lvap._downlink.radio.connection.send_del_lvap(lvap)

        if set_mask:
            lvap._downlink = valid[0]
        else:
            lvap._uplink.append(valid[0])

        # update ports
        if not lvap.ports:
            lvap.ports[0] = VirtualPort(virtual_port_id=0)

        lvap.ports[0].poas.append(wtp.port())

        # set supported band
        lvap._supported_band = status.supported_band

        # update LVAP params
        lvap.authentication_state = bool(status.flags.authenticated)
        lvap.association_state = bool(status.flags.associated)

        lvap._assoc_id = status.assoc_id
        lvap._encap = EtherAddress(status.encap)
        ssids = [SSID(x.ssid) for x in status.ssids]

        # update ssid
        if lvap.ssid:

            # Raise LVAP leave event
            self.server.send_lvap_leave_message_to_self(lvap)

            # removing LVAP from tenant, need first to look for right tenant
            if lvap.addr in lvap.tenant.lvaps:
                LOG.info("Removing %s from tenant %s", lvap.addr, lvap.ssid)
                del lvap.tenant.lvaps[lvap.addr]

            lvap._tenant = None

        # update remaining ssids
        lvap._ssids = ssids[1:]

        if ssids[0]:

            tenant = RUNTIME.load_tenant(ssids[0])

            if not tenant:
                LOG.info("LVAP %s from unknown tenant %s", lvap.addr, ssids[0])
                RUNTIME.remove_lvap(lvap.addr)
                return

            # setting tenant without seding out add lvap message
            lvap._tenant = tenant

            # adding LVAP to tenant
            LOG.info("Adding %s to tenant %s", lvap.addr, ssids[0])
            lvap.tenant.lvaps[lvap.addr] = lvap

            # Raise LVAP join event
            self.server.send_lvap_join_message_to_self(lvap)