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

        if ssid == SSID(b'\0'):
            self._ssid = None
        else:
            self._ssid = ssid
예제 #2
0
    def _handle_status_vap(self, wtp, status):
        """Handle an incoming STATUS_VAP message.
        Args:
            status, a STATUS_VAP message
        Returns:
            None
        """

        bssid = EtherAddress(status.bssid)
        ssid = SSID(status.ssid)
        tenant = RUNTIME.load_tenant(ssid)

        if not tenant:
            self.log.info("VAP %s from unknown tenant %s", bssid, ssid)
            return

        # 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 VAP.")
            wtp.connection.send_del_vap(bssid)
            return

        # If the VAP does not exists, then create a new one
        if bssid not in tenant.vaps:
            vap = VAP(bssid, valid, tenant)
            tenant.vaps[bssid] = vap

        vap = tenant.vaps[bssid]

        self.log.info("VAP status %s", vap)
예제 #3
0
    def _handle_status_vap(cls, wtp, status):
        """Handle an incoming STATUS_VAP message.
        Args:
            status, a STATUS_VAP message
        Returns:
            None
        """

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

        net_bssid_addr = EtherAddress(status.net_bssid)
        ssid = SSID(status.ssid)
        tenant = RUNTIME.load_tenant(ssid)

        if not tenant:
            LOG.info("VAP %s from unknown tenant %s", net_bssid_addr, ssid)
            return

        incoming = ResourceBlock(wtp, EtherAddress(status.hwaddr),
                                 status.channel, status.band)

        LOG.info("VAP status update from %s", net_bssid_addr)

        # If the VAP does not exists, then create a new one
        if net_bssid_addr not in tenant.vaps:
            vap = VAP(net_bssid_addr, incoming, wtp, tenant)
            tenant.vaps[net_bssid_addr] = vap

        vap = tenant.vaps[net_bssid_addr]

        LOG.info("VAP status %s", vap)
예제 #4
0
    def _handle_status_slice(self, wtp, status):
        """Handle an incoming STATUS_SLICE message.
        Args:
            status, a STATUS_SLICE message
        Returns:
            None
        """

        dscp = DSCP(status.dscp)
        ssid = SSID(status.ssid)

        tenant = RUNTIME.load_tenant(ssid)

        if not tenant:
            self.log.info("Slice status from unknown tenant %s", ssid)
            return

        # 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.")
            return

        # check if slice is valid
        if dscp not in tenant.slices:
            self.log.warning("DSCP %s not found. Removing slice.", dscp)
            self.send_del_slice(valid[0], ssid, dscp)
            return

        slc = tenant.slices[dscp]

        if slc.wifi['static-properties']['quantum'] != status.quantum:

            if wtp.addr not in slc.wifi['wtps']:
                slc.wifi['wtps'][wtp.addr] = {'static-properties': {}}

                slc.wifi['wtps'][wtp.addr]['static-properties']['quantum'] = \
                status.quantum

        if slc.wifi['static-properties']['amsdu_aggregation'] != \
            bool(status.flags.amsdu_aggregation):

            if wtp.addr not in slc.wifi['wtps']:
                slc.wifi['wtps'][wtp.addr] = {'static-properties': {}}

            slc.wifi['wtps'][wtp.addr]['static-properties'] \
                ['amsdu_aggregation'] = bool(status.flags.amsdu_aggregation)

        if slc.wifi['static-properties']['scheduler'] != status.scheduler:

            if wtp.addr not in slc.wifi['wtps']:
                slc.wifi['wtps'][wtp.addr] = {'static-properties': {}}

                slc.wifi['wtps'][wtp.addr]['static-properties']['scheduler'] = \
                status.scheduler

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

        flags = Container(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=78,
                        flags=flags,
                        assoc_id=lvap.assoc_id,
                        module_id=get_xid(),
                        hwaddr=block.hwaddr.to_raw(),
                        channel=block.channel,
                        band=block.band,
                        supported_band=lvap.supported_band,
                        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()))

        xid = self.send_message(PT_ADD_LVAP, msg)

        lvap.pending.append(xid)
예제 #6
0
    def _handle_status_vap(cls, status):
        """Handle an incoming STATUS_VAP message.
        Args:
            status, a STATUS_VAP message
        Returns:
            None
        """

        wtp_addr = EtherAddress(status.wtp)

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

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

        net_bssid_addr = EtherAddress(status.net_bssid)
        ssid = SSID(status.ssid)
        tenant_id = None

        for tenant in RUNTIME.tenants.values():
            if tenant.tenant_name == ssid:
                tenant_id = tenant.tenant_id
                break

        if not tenant_id:
            LOG.info("VAP %s from unknown tenant %s", net_bssid_addr, ssid)
            return

        tenant = RUNTIME.tenants[tenant_id]

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

        LOG.info("VAP %s status update block %s", net_bssid_addr, block)

        # If the VAP does not exists, then create a new one
        if net_bssid_addr not in tenant.vaps:
            tenant.vaps[net_bssid_addr] = \
                VAP(net_bssid_addr, block, wtp, tenant)

        vap = tenant.vaps[net_bssid_addr]
        LOG.info("VAP status %s", vap)
예제 #7
0
    def _handle_status_traffic_rule(self, wtp, status):
        """Handle an incoming STATUS_TRAFFIC_RULE message.
        Args:
            status, a STATUS_TRAFFIC_RULE message
        Returns:
            None
        """

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

        quantum = status.quantum
        amsdu_aggregation = bool(status.flags.amsdu_aggregation)
        dscp = "{0:#0{1}x}".format(status.dscp, 4)
        ssid = SSID(status.ssid)

        tenant = RUNTIME.load_tenant(ssid)

        if not tenant:
            LOG.info("Traffic rule status from unknown tenant %s", ssid)
            return

        incoming = ResourceBlock(wtp, EtherAddress(status.hwaddr),
                                 status.channel, status.band)

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

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

        block = valid[0]

        trq = block.traffic_rule_queues[(ssid, dscp)]

        trq._quantum = quantum
        trq._amsdu_aggregation = amsdu_aggregation

        LOG.info("Transmission rule status %s", trq)
예제 #8
0
    def post(self, *args, **kwargs):
        """ Create a new tenant.

        Args:
            None

        Request:
            version: protocol version (1.0)
            owner: the username of the requester
            tenant_id: the network name
            desc: a description for the new tenant
            bssid_type: shared or unique

        Example URLs:

            POST /api/v1/tenants

        """

        try:

            if len(args) > 1:
                raise ValueError("Invalid url")

            request = tornado.escape.json_decode(self.request.body)

            if "version" not in request:
                raise ValueError("missing version element")

            if "owner" not in request:
                raise ValueError("missing owner element")

            if "desc" not in request:
                raise ValueError("missing desc element")

            if "tenant_name" not in request:
                raise ValueError("missing tenant_name element")

            if "bssid_type" not in request:
                bssid_type = T_TYPE_UNIQUE
            else:
                bssid_type = request['bssid_type']

            if bssid_type not in T_TYPES:
                raise ValueError("invalid bssid_type %s" % bssid_type)

            if len(args) == 1:
                tenant_id = UUID(args[0])
            else:
                tenant_id = None

            tenant_name = SSID(request['tenant_name'])

            RUNTIME.add_tenant(request['owner'], request['desc'], tenant_name,
                               bssid_type, tenant_id)

            self.set_header("Location", "/api/v1/tenants/%s" % tenant_id)

        except ValueError as ex:
            self.send_error(400, message=ex)
        except KeyError as ex:
            self.send_error(404, message=ex)

        self.set_status(201, None)
예제 #9
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)
예제 #10
0
    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)
예제 #11
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)
예제 #12
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)
예제 #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_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)
예제 #14
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))

        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)
예제 #15
0
    def post(self, *args, **kwargs):
        """ Create a new tenant request.

        Args:
            None

        Request:
            version: protocol version (1.0)
            owner: the username of the requester
            tenant_id: the network name
            desc: a description for the new tenant
            bssid_type: shared or unique

        Example URLs:

            POST /api/v1/pending

        """

        try:

            if len(args) > 1:
                raise ValueError("Invalid url")

            request = tornado.escape.json_decode(self.request.body)

            if "version" not in request:
                raise ValueError("missing version element")

            if "desc" not in request:
                raise ValueError("missing desc element")

            if "tenant_name" not in request:
                raise ValueError("missing tenant_name element")

            bssid_type = T_TYPE_UNIQUE
            if "bssid_type" in request:
                bssid_type = request['bssid_type']

            # If PLMN ID is not given, default it to 000000 value
            plmn_id = 000000

            if "plmn_id" in request and request['plmn_id'] != None and \
                (len(request['plmn_id']) == 5 or len(request['plmn_id']) == 6):
                plmn_id = int(request['plmn_id'])

            if len(args) == 1:
                tenant_id = UUID(args[0])
            else:
                tenant_id = None

            tenant_name = SSID(request['tenant_name'])

            RUNTIME.request_tenant(self.account.username, request['desc'],
                                   tenant_name, bssid_type, tenant_id, plmn_id)

            self.set_header("Location", "/api/v1/pendig/%s" % tenant_id)

        except KeyError as ex:
            self.send_error(404, message=ex)
        except ValueError as ex:
            self.send_error(400, message=ex)

        self.set_status(201, None)
예제 #16
0
    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)
예제 #17
0
    def _handle_assoc_request(self, wtp, request):
        """Handle an incoming ASSOC_REQUEST message.
        Args:
            request, a ASSOC_REQUEST message
        Returns:
            None
        """

        sta = EtherAddress(request.sta)

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

        lvap = RUNTIME.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 tenant
        for tenant in RUNTIME.tenants.values():

            if tenant.bssid_type == T_TYPE_SHARED:
                continue

            bssid = tenant.generate_bssid(lvap.addr)

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

            if tenant.tenant_name == incoming_ssid:
                lvap.bssid = incoming_bssid
                lvap.authentication_state = True
                lvap.association_state = True
                lvap.ssid = incoming_ssid
                lvap.supported_band = request.supported_band
                lvap.commit()
                self.send_assoc_response(lvap)
                return

        # Check if the requested SSID is from a unique tenant
        for tenant in RUNTIME.tenants.values():

            if tenant.bssid_type == T_TYPE_UNIQUE:
                continue

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

            ssid = tenant.vaps[incoming_bssid].ssid

            if ssid == incoming_ssid:
                lvap.bssid = incoming_bssid
                lvap.authentication_state = True
                lvap.association_state = True
                lvap.ssid = incoming_ssid
                lvap.supported_band = request.supported_band
                lvap.commit()
                self.send_assoc_response(lvap)
                return

        self.log.info("Unable to find SSID %s", incoming_ssid)
예제 #18
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)
예제 #19
0
    def _handle_assoc_request(self, request):
        """Handle an incoming ASSOC_REQUEST message.
        Args:
            request, a ASSOC_REQUEST message
        Returns:
            None
        """

        wtp_addr = EtherAddress(request.wtp)

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

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

        sta = EtherAddress(request.sta)

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

        lvap = RUNTIME.lvaps[sta]

        if not RUNTIME.is_allowed(sta):
            LOG.info("Assoc request from %s ignored (white list)", sta)
            return

        if RUNTIME.is_denied(sta):
            LOG.info("Assoc request from %s ignored (black list)", sta)
            return

        ssid = SSID(request.ssid.decode('UTF-8'))
        bssid = EtherAddress(request.bssid)

        tenant_name = None

        # look for ssid in shared tenants
        for tenant_id in RUNTIME.tenants:

            tenant = RUNTIME.tenants[tenant_id]

            if tenant.bssid_type == T_TYPE_UNIQUE:
                continue

            if bssid in tenant.vaps and ssid == tenant.tenant_name:
                tenant_name = tenant.tenant_name

        # otherwise this must be the lvap unique bssid
        if lvap.net_bssid == bssid and ssid in lvap.ssids:
            tenant_name = ssid

        if not tenant_name:
            LOG.info("Assoc request sta %s for ssid %s bssid %s, ignoring",
                     lvap.addr, lvap.ssid, lvap.lvap_bssid)
            return

        # this will trigger an add lvap message to update the ssid
        lvap.tenant = RUNTIME.load_tenant(tenant_name)

        # this will trigger an add lvap message to update the assoc id
        lvap.assoc_id = self.server.assoc_id

        LOG.info("Assoc request sta %s ssid %s bssid %s assoc id %u, replying",
                 lvap.addr, lvap.ssid, lvap.lvap_bssid, lvap.assoc_id)

        self.send_assoc_response(lvap)
예제 #20
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)