def ReceiveSLI(self, pkt): """Receive a SLI packet, handle the AVP. :param pkt: :return: """ if L2tpv3GlobalSettings.L2tpv3GlobalSettings.MustAvpsCheck is True: ret = self.connection.checkMustAvps( L2tpv3ControlPacket.L2tpv3ControlPacket.SLIMandatoryAVPs, pkt.avps) if ret is not True: return L2tpv3ControlPacket.L2tpv3CDN( self, 2, 4, "Cannot handle AVP in SLI message") self.logger.debug("L2Tp Session[%d, %d] receive a SLI message", self.localSessionId, self.remoteSessionId) if len(pkt.avps) > 1: for i in xrange(1, len(pkt.avps)): avp = pkt.avps[i] if not avp.handleAvp(pkt, None): return L2tpv3ControlPacket.L2tpv3CDN( self, 2, 4, "Cannot handle AVP in SLI message") return None
def ReceiveICCN(self, pkt): """Receive a ICCN packet from the connection. Will process the AVPs. :param pkt: THe decoded l2tp control packet. :return: a ICCN response packet or None """ if L2tpv3GlobalSettings.L2tpv3GlobalSettings.MustAvpsCheck is True: ret = self.connection.checkMustAvps( L2tpv3ControlPacket.L2tpv3ControlPacket.ICCNMandatoryAVPs, pkt.avps) if ret is not True: self.fsm.recvBadICCN() return L2tpv3ControlPacket.L2tpv3CDN( self, 2, 4, "Avp cannot be handled correctly") self.logger.debug("L2Tp session[%d, %d] receive a ICCN message", self.localSessionId, self.remoteSessionId) if len(pkt.avps) > 1: for i in xrange(1, len(pkt.avps)): avp = pkt.avps[i] # We got a bad ICCN, we should send a CDN if not avp.handleAvp(pkt, None): self.fsm.recvBadICCN() return L2tpv3ControlPacket.L2tpv3CDN( self, 2, 4, "Avp cannot be handled correctly") self.logger.debug("Session[%d, %d] got a good ICCN, send it to fsm.", self.localSessionId, self.remoteSessionId) self.fsm.recvGoodICCN() # We need to send the ZLB. ackpkt = L2tpv3ControlPacket.L2tpv3ACK( connID=self.connection.remoteConnID) return ackpkt
def _findSession(self, pkt): # Find the remote Session remoteSessid = 0 localSessId = 0 for avp in pkt.avps: if isinstance(avp, L2tpv3RFC3931AVPs.LocalSessionID): remoteSessid = avp.sessionID elif isinstance(avp, L2tpv3RFC3931AVPs.RemoteSessionID): localSessId = avp.sessionID if not remoteSessid and not localSessId: self.logger.warn( "Got a packet but no local/remote session ID is set, we cannot send " "rsp since we don't know the session ID") return None # Try to find the session, this is the case sender or some error packet # happens session1 = self.findSessionByRemoteSessionID(remoteSessid) session2 = self.findSessionByLocalSessionID(localSessId) if session1 is None and session2 is None: # generate a fake session for it, for send the CDN session = L2tpv3Session.L2tpv3Session(randint(1, 0xFFFFFFFF), remoteSessid, 'receive', self) cdn = L2tpv3ControlPacket.L2tpv3CDN( session, 2, 5, "Cannot find the session in local runtime DB") self.transport.SendPacket(cdn) return None return session1 if session1 else session2
def fsmStateRecipientIdle(self, event): """Callback function will called when fsm changed to this state. CDN is to be sent to remote and remove the session. :param event: The event that triggers the fsm to idle state. :return: """ self.logger.debug( "Session [%d, %d] state is transferred to idle, event:" + event.src + " " + event.dst + " " + event.event, self.localSessionId, self.remoteSessionId) self.lastchangetime = time.time() if event.event == "startup": # for startup, ignore it. return if event.event == L2tpv3Fsm.L2tpv3SessionRecipientFsm.EventRecvCDN and self.connection is not None: self.logger.debug( "We reach to this state since we receive a CDN, don't need to send the CDN again" ) self.connection.transport.needSendZlb = True self.connection.removeSession(self) return # we should send the CDN to remote if event.event == L2tpv3Fsm.L2tpv3SessionRecipientFsm.EventCloseRequest: retcode = 3 errorcode = 0 msg = "Admin closes the session" else: # fixme we should figure that retcode = 3 errorcode = 0 msg = "Admin closes the session" if self.connection is not None: self.logger.debug( "Send a CDN to remote since the session is terminated") if not self.silentlyCleared: transport = self.connection.transport cdn = L2tpv3ControlPacket.L2tpv3CDN(self, retcode, errorcode, msg) transport.SendPacket(cdn, None) # Clean up the session self.connection.removeSession(self)
def ReceiveICRQ(self, pkt): """Receive a ICRQ from remote, if it is a good ICRQ, will send a ICRP. :param pkt: The ICRQ control packet, has been decoded. :return: ICRP packet or None """ if L2tpv3GlobalSettings.L2tpv3GlobalSettings.MustAvpsCheck is True: ret = self.connection.checkMustAvps( L2tpv3ControlPacket.L2tpv3ControlPacket.ICRQMandatoryAVPs, pkt.avps) if ret is not True: self.fsm.recvBadICRQ() return L2tpv3ControlPacket.L2tpv3CDN( self, 2, 4, "Avp cannot be handled correctly") self.logger.debug("L2tp session[%d, %d] receives a ICRQ message.", self.localSessionId, self.remoteSessionId) avps = list() avps.append( L2tpv3RFC3931AVPs.ControlMessageAVP( L2tpv3RFC3931AVPs.ControlMessageAVP.ICRP)) avps.append( L2tpv3RFC3931AVPs.DataSequencing( L2tpv3RFC3931AVPs.DataSequencing.AllSeq)) # TODO add sbfd support for ipv6 if Convert.is_valid_ipv4_address(self.connection.localAddr): avps.append( L2tpv3RFC3931AVPs.SbfdDiscriminator( int( socket.inet_aton( self.connection.localAddr).encode('hex'), 16))) avps.append( L2tpv3RFC3931AVPs.SbfdVccv( L2tpv3RFC3931AVPs.SbfdVccv.VccvValue)) # Need add some Cable labs avp self.logger.debug( "Session [%d, %d]sends a ICRP packet to remote, connection:%d", self.localSessionId, self.remoteSessionId, pkt.Connection.remoteConnID) icrp = L2tpv3ControlPacket.L2tpv3ControlPacket( pkt.Connection.remoteConnID, 0, 0, avps) del self.avps_icrq[:] del self.mcast[:] if len(pkt.avps) > 1: for i in xrange(1, len(pkt.avps)): avp = pkt.avps[i] if isinstance( avp, L2tpv3CableLabsAvps.DepiL2SpecificSublayerSubtype): self.session_l2Sublayer = avp.pw_type self.avps_icrq.append(avp) # We got a bad ICRQ, we should send a CDN if not avp.handleAvp(pkt, icrp): self.fsm.recvBadICRQ() return L2tpv3ControlPacket.L2tpv3CDN( self, 2, 4, "Avp cannot be handled correctly") self.logger.debug("We got a good ICRQ, send to fsm") self.fsm.recvGoodICRQ() return icrp
def ReceiveICRP(self, pkt): """Receive a ICRP from remote, if it is a good ICRP, will send a ICCN. this function will be used for simulator purpose. :param pkt: The ICRP control packet, has been decoded. :return: """ if L2tpv3GlobalSettings.L2tpv3GlobalSettings.MustAvpsCheck is True: ret = self.connection.checkMustAvps( L2tpv3ControlPacket.L2tpv3ControlPacket.ICRPMandatoryAVPs, pkt.avps) if ret is not True: if isinstance(self.fsm, L2tpv3Fsm.L2tpv3SessionSenderFsm): self.fsm.recvBadICRP() return L2tpv3ControlPacket.L2tpv3CDN( self, 2, 4, "Avp cannot be handled correctly") self.logger.debug("Session [%d, %d] gets a l2tp ICRP message.", self.localSessionId, self.remoteSessionId) if isinstance(self.fsm, L2tpv3Fsm.L2tpv3SessionRecipientFsm): self.logger.debug( "Recipient session [%d, %d] gets a l2tp ICRP message.", self.localSessionId, self.remoteSessionId) self.fsm.recvICRP() # this event will trigger the recipient state # machine transferring to idle state. return # Find the local session ID for avp in pkt.avps: if isinstance(avp, L2tpv3RFC3931AVPs.LocalSessionID): self.remoteSessionId = avp.sessionID self.connection.addSession(self) # If the incoming l2TP ICRP does not contain a local session ID if not self.remoteSessionId: self.logger.warn( "Session[%d, %d] is terminated due to not find the local session ID in ICRP message.", self.localSessionId, self.remoteSessionId) self.fsm.recvBadICRP() return L2tpv3ControlPacket.L2tpv3CDN(self, 2, 5, "") # send a ICCN msgAvp = L2tpv3RFC3931AVPs.ControlMessageAVP( L2tpv3RFC3931AVPs.ControlMessageAVP.ICCN) iccn = L2tpv3ControlPacket.L2tpv3ControlPacket( self.connection.remoteConnID, avps=(msgAvp, )) if len(pkt.avps) > 1: for i in xrange(1, len(pkt.avps)): avp = pkt.avps[i] # We got a bad ICRP, we should send a CDN if not avp.handleAvp(pkt, iccn): self.fsm.recvBadICRP() return L2tpv3ControlPacket.L2tpv3CDN( self, 2, 4, "Avp cannot be handled correctly") self.logger.debug( "Sender session [%d, %d] gets a good l2tp ICRP message.", self.localSessionId, self.remoteSessionId) self.fsm.recvGoodICRP() return iccn