Esempio n. 1
0
    def _handle_ifstate_request(self, req, meta):
        # Only master replies to ifstate requests.
        if not self.zk.have_lock():
            return
        assert isinstance(req, IFStateRequest)
        infos = []
        with self.ifid_state_lock:
            if req.p.ifID == IFStateRequest.ALL_INTERFACES:
                ifid_states = self.ifid_state.items()
            elif req.p.ifID in self.ifid_state:
                ifid_states = [(req.p.ifID, self.ifid_state[req.p.ifID])]
            else:
                logging.error(
                    "Received ifstate request from %s for unknown "
                    "interface %s.", meta, req.p.ifID)
                return

            for (ifid, state) in ifid_states:
                # Don't include inactive interfaces in response.
                if state.is_inactive():
                    continue
                info = IFStateInfo.from_values(ifid, state.is_active(),
                                               self._get_ht_proof(ifid))
                infos.append(info)
        if not infos and not self._quiet_startup():
            logging.warning("No IF state info to put in response. Req: %s" %
                            req.short_desc())
            return
        payload = IFStatePayload.from_values(infos)
        self.send_meta(payload, meta, (meta.host, meta.port))
Esempio n. 2
0
 def _handle_ifstate_request(self, cpld, meta):
     # Only master replies to ifstate requests.
     pmgt = cpld.union
     req = pmgt.union
     assert isinstance(req, IFStateRequest), type(req)
     if not self.zk.have_lock():
         return
     with self.ifid_state_lock:
         infos = []
         for (ifid, state) in self.ifid_state.items():
             # Don't include inactive interfaces in update.
             if state.is_inactive():
                 continue
             srev_info = None
             if state.is_revoked():
                 srev_info = self.if_revocations.get(ifid, None)
                 if not srev_info:
                     logging.warning(
                         "No revocation in cache for revoked IFID: %s",
                         ifid)
                     continue
             infos.append(
                 IFStateInfo.from_values(ifid, state.is_active(),
                                         srev_info))
         if not infos and not self._quiet_startup():
             logging.warning(
                 "No IF state info to put in IFState update for %s.", meta)
             return
     self._send_ifstate_update(infos, [meta])
Esempio n. 3
0
    def handle_ifid_packet(self, pld, meta):
        """
        Update the interface state for the corresponding interface.

        :param pld: The IFIDPayload.
        :type pld: IFIDPayload
        """
        ifid = pld.p.relayIF
        with self.ifid_state_lock:
            if ifid not in self.ifid_state:
                raise SCIONKeyError("Invalid IF %d in IFIDPayload" % ifid)
            br = self.ifid2br[ifid]
            br.interfaces[ifid].to_if_id = pld.p.origIF
            prev_state = self.ifid_state[ifid].update()
            if prev_state == InterfaceState.INACTIVE:
                logging.info("IF %d activated", ifid)
            elif prev_state in [
                    InterfaceState.TIMED_OUT, InterfaceState.REVOKED
            ]:
                logging.info("IF %d came back up.", ifid)
            if not prev_state == InterfaceState.ACTIVE:
                if self.zk.have_lock():
                    # Inform BRs about the interface coming up.
                    state_info = IFStateInfo.from_values(
                        ifid, True, self._get_ht_proof(ifid))
                    pld = IFStatePayload.from_values([state_info])
                    for br in self.topology.border_routers:
                        br_addr, br_port = br.int_addrs[0].public[0]
                        meta = UDPMetadata.from_values(host=br_addr,
                                                       port=br_port)
                        self.send_meta(pld.copy(), meta, (br_addr, br_port))
Esempio n. 4
0
    def _handle_ifstate_request(self, mgmt_pkt):
        # Only master replies to ifstate requests.
        if not self.zk.have_lock():
            return
        req = mgmt_pkt.get_payload()
        assert isinstance(req, IFStateRequest)
        logging.debug("Received ifstate req:\n%s", mgmt_pkt)
        infos = []
        if req.p.ifID == IFStateRequest.ALL_INTERFACES:
            ifid_states = self.ifid_state.items()
        elif req.p.ifID in self.ifid_state:
            ifid_states = [(req.p.ifID, self.ifid_state[req.p.ifID])]
        else:
            logging.error(
                "Received ifstate request from %s for unknown "
                "interface %s.", mgmt_pkt.addrs.src, req.p.ifID)
            return

        for (ifid, state) in ifid_states:
            # Don't include inactive interfaces in response.
            if state.is_inactive():
                continue
            chain = self._get_if_hash_chain(ifid)
            info = IFStateInfo.from_values(ifid, state.is_active(),
                                           chain.next_element())
            infos.append(info)
        if not infos and not self._quiet_startup():
            logging.warning("No IF state info to put in response.")
            return

        payload = IFStatePayload.from_values(infos)
        state_pkt = self._build_packet(mgmt_pkt.addrs.src.host,
                                       payload=payload)
        self.send(state_pkt, mgmt_pkt.addrs.src.host)
Esempio n. 5
0
    def handle_ifid_packet(self, cpld, meta):
        """
        Update the interface state for the corresponding interface.

        :param pld: The IFIDPayload.
        :type pld: IFIDPayload
        """
        pld = cpld.union
        assert isinstance(pld, IFIDPayload), type(pld)
        ifid = meta.pkt.path.get_hof().ingress_if
        with self.ifid_state_lock:
            if ifid not in self.ifid_state:
                raise SCIONKeyError("Invalid IF %d in IFIDPayload" % ifid)
            br = self.ifid2br[ifid]
            br.interfaces[ifid].to_if_id = pld.p.origIF
            prev_state = self.ifid_state[ifid].update()
            if prev_state == InterfaceState.INACTIVE:
                logging.info("IF %d activated.", ifid)
            elif prev_state in [
                    InterfaceState.TIMED_OUT, InterfaceState.REVOKED
            ]:
                logging.info("IF %d came back up.", ifid)
            if prev_state != InterfaceState.ACTIVE:
                if self.zk.have_lock():
                    # Inform BRs about the interface coming up.
                    metas = []
                    for br in self.topology.border_routers:
                        br_addr, br_port = br.ctrl_addrs.public
                        metas.append(
                            UDPMetadata.from_values(host=br_addr,
                                                    port=br_port))
                    info = IFStateInfo.from_values(ifid, True)
                    self._send_ifstate_update([info], metas)
Esempio n. 6
0
    def handle_ifid_packet(self, pkt):
        """
        Update the interface state for the corresponding interface.

        :param ipkt: The IFIDPayload.
        :type ipkt: IFIDPayload
        """
        payload = pkt.get_payload()
        ifid = payload.p.relayIF
        if ifid not in self.ifid_state:
            raise SCIONKeyError("Invalid IF %d in IFIDPayload" % ifid)
        er = self.ifid2er[ifid]
        er.interface.to_if_id = payload.p.origIF
        prev_state = self.ifid_state[ifid].update()
        if prev_state == InterfaceState.INACTIVE:
            logging.info("IF %d activated", ifid)
        elif prev_state in [InterfaceState.TIMED_OUT, InterfaceState.REVOKED]:
            logging.info("IF %d came back up.", ifid)
        if not prev_state == InterfaceState.ACTIVE:
            if self.zk.have_lock():
                # Inform ERs about the interface coming up.
                chain = self._get_if_hash_chain(ifid)
                if chain is None:
                    return
                state_info = IFStateInfo.from_values(ifid, True,
                                                     chain.current_element())
                pld = IFStatePayload.from_values([state_info])
                mgmt_packet = self._build_packet()
                for er in self.topology.get_all_edge_routers():
                    if er.interface.if_id != ifid:
                        mgmt_packet.addrs.dst.host = er.addr
                        mgmt_packet.set_payload(pld.copy())
                        self.send(mgmt_packet, er.addr)
Esempio n. 7
0
    def _issue_revocation(self, if_id, chain):
        """
        Store a RevocationObject in ZK and send a revocation to all ERs.

        :param if_id: The interface that needs to be revoked.
        :type if_id: int
        :param chain: The hash chain corresponding to if_id.
        :type chain: :class:`lib.crypto.hash_chain.HashChain`
        """
        # Only the master BS issues revocations.
        if not self.zk.have_lock():
            return
        rev_info = RevocationInfo.from_values(chain.next_element())
        logging.info("Storing revocation in ZK.")
        rev_obj = RevocationObject.from_values(if_id, chain.current_index(),
                                               chain.next_element())
        entry_name = "%s:%s" % (chain.start_element(hex_=True),
                                chain.next_element(hex_=True))
        self.revobjs_cache.store(entry_name, rev_obj.pack())
        logging.info("Issuing revocation for IF %d.", if_id)
        # Issue revocation to all ERs.
        info = IFStateInfo.from_values(if_id, False, chain.next_element())
        pld = IFStatePayload.from_values([info])
        state_pkt = self._build_packet()
        for er in self.topology.get_all_edge_routers():
            state_pkt.addrs.dst.host = er.addr
            state_pkt.set_payload(pld.copy())
            self.send(state_pkt, er.addr)
        self._process_revocation(rev_info, if_id)
Esempio n. 8
0
    def _issue_revocations(self, revoked_ifs):
        """
        Store a RevocationInfo in ZK and send a revocation to all BRs.

        :param list revoked_ifs: A list of interfaces that needs to be revoked.
        """
        # Only the master BS issues revocations.
        if not self.zk.have_lock():
            return
        # Process revoked interfaces.
        infos = []
        for if_id in revoked_ifs:
            rev_info = self._get_ht_proof(if_id)
            logging.info("Issuing revocation: %s", rev_info.short_desc())
            if self._labels:
                REVOCATIONS_ISSUED.labels(**self._labels).inc()
            self._process_revocation(rev_info)
            infos.append(IFStateInfo.from_values(if_id, False, rev_info))
        border_metas = []
        # Add all BRs.
        for br in self.topology.border_routers:
            br_addr, br_port = br.int_addrs[0].public[0]
            border_metas.append(
                UDPMetadata.from_values(host=br_addr, port=br_port))
        # Add local path server.
        ps_meta = []
        if self.topology.path_servers:
            try:
                addr, port = self.dns_query_topo(PATH_SERVICE)[0]
            except SCIONServiceLookupError:
                addr, port = None, None
            # Create a meta if there is a local path service
            if addr:
                ps_meta.append(UDPMetadata.from_values(host=addr, port=port))
        self._send_ifstate_update(infos, border_metas, ps_meta)
Esempio n. 9
0
    def _issue_revocations(self, revoked_ifs):
        """
        Store a RevocationInfo in ZK and send a revocation to all BRs.

        :param list revoked_ifs: A list of interfaces that needs to be revoked.
        """
        # Only the master BS issues revocations.
        if not self.zk.have_lock():
            return
        # Process revoked interfaces.
        infos = []
        for if_id in revoked_ifs:
            br = self.ifid2br[if_id]
            rev_info = RevocationInfo.from_values(
                self.addr.isd_as, if_id, br.interfaces[if_id].link_type,
                int(time.time()), self.REVOCATION_TTL)
            logging.info("Issuing revocation: %s", rev_info.short_desc())
            if self._labels:
                REVOCATIONS_ISSUED.labels(**self._labels).inc()
            chain = self._get_my_cert()
            _, cert_ver = chain.get_leaf_isd_as_ver()
            src = DefaultSignSrc.from_values(
                rev_info.isd_as(), cert_ver,
                self._get_my_trc().version).pack()
            srev_info = SignedRevInfo.from_values(rev_info.copy().pack(),
                                                  ProtoSignType.ED25519, src)
            srev_info.sign(self.signing_key)
            # Add to revocation cache
            self.if_revocations[if_id] = srev_info
            self._process_revocation(srev_info)
            infos.append(IFStateInfo.from_values(if_id, False, srev_info))
        border_metas = []
        # Add all BRs.
        for br in self.topology.border_routers:
            br_addr, br_port = br.int_addrs.public[0]
            border_metas.append(
                UDPMetadata.from_values(host=br_addr, port=br_port))
        # Add local path server.
        ps_meta = []
        if self.topology.path_servers:
            try:
                addr, port = self.dns_query_topo(ServiceType.PS)[0]
            except SCIONServiceLookupError:
                addr, port = None, None
            # Create a meta if there is a local path service
            if addr:
                ps_meta.append(UDPMetadata.from_values(host=addr, port=port))
        self._send_ifstate_update(infos, border_metas, ps_meta)
Esempio n. 10
0
File: base.py Progetto: fjacky/scion
 def _send_ifstate_update(self, border_metas, server_metas=None):
     server_metas = server_metas or []
     with self.ifid_state_lock:
         infos = []
         for (ifid, state) in self.ifid_state.items():
             # Don't include inactive interfaces in update.
             if state.is_inactive():
                 continue
             rev_info = self._get_ht_proof(ifid) if state.is_revoked() else None
             info = IFStateInfo.from_values(ifid, state.is_active(), rev_info)
             infos.append(info)
         if not infos and not self._quiet_startup():
             logging.warning("No IF state info to put in IFState update for %s.",
                             ", ".join([str(m) for m in border_metas + server_metas]))
             return
         payload = IFStatePayload.from_values(infos)
     for meta in border_metas:
         self.send_meta(payload.copy(), meta, (meta.host, meta.port))
     for meta in server_metas:
         self.send_meta(payload.copy(), meta)
Esempio n. 11
0
    def _issue_revocation(self, if_id):
        """
        Store a RevocationInfo in ZK and send a revocation to all BRs.

        :param if_id: The interface that needs to be revoked.
        :type if_id: int
        """
        # Only the master BS issues revocations.
        if not self.zk.have_lock():
            return
        rev_info = self._get_ht_proof(if_id)
        logging.error("Issuing revocation for IF %d.", if_id)
        # Issue revocation to all BRs.
        info = IFStateInfo.from_values(if_id, False, rev_info)
        pld = IFStatePayload.from_values([info])
        for br in self.topology.get_all_border_routers():
            meta = UDPMetadata.from_values(host=br.addr, port=br.port)
            self.send_meta(pld.copy(), meta, (br.addr, br.port))
        self._process_revocation(rev_info)
        self._send_rev_to_local_ps(rev_info)
Esempio n. 12
0
    def _issue_revocation(self, if_id):
        """
        Store a RevocationInfo in ZK and send a revocation to all BRs.

        :param if_id: The interface that needs to be revoked.
        :type if_id: int
        """
        # Only the master BS issues revocations.
        if not self.zk.have_lock():
            return
        rev_info = self._get_ht_proof(if_id)
        logging.info("Issuing revocation: %s", rev_info.short_desc())
        if self._labels:
            REVOCATIONS_ISSUED.labels(**self._labels).inc()
        # Issue revocation to all BRs.
        info = IFStateInfo.from_values(if_id, False, rev_info)
        pld = IFStatePayload.from_values([info])
        for br in self.topology.border_routers:
            br_addr, br_port = br.int_addrs[0].public[0]
            meta = UDPMetadata.from_values(host=br_addr, port=br_port)
            self.send_meta(pld.copy(), meta, (br_addr, br_port))
        self._process_revocation(rev_info)
        self._send_rev_to_local_ps(rev_info)