add some 5G MM structures and routines

This commit is contained in:
p1-bmu 2021-04-27 17:30:12 +02:00
parent 013b3fccbb
commit c4333e4b59
9 changed files with 1132 additions and 79 deletions

View File

@ -366,7 +366,7 @@ class GNBd(object):
return None, ran_ue_id return None, ran_ue_id
elif FgsIdType == FGSIDTYPE_GUTI: elif FgsIdType == FGSIDTYPE_GUTI:
# TODO: should ensure PLMN and AMF identifiers correspond # TODO: should ensure PLMN and AMF identifiers correspond
return self.Server.get_ued(mtmsi=FgsId['5GTMSI'].get_val()), ran_ue_id return self.Server.get_ued(fgtmsi=FgsId['5GTMSI'].get_val()), ran_ue_id
else: else:
self._log('WNG', 'Unable to get UE id from NAS message, 5GSID of '\ self._log('WNG', 'Unable to get UE id from NAS message, 5GSID of '\
'unexpected type %i' % FgsIdType) 'unexpected type %i' % FgsIdType)

View File

@ -28,11 +28,11 @@
# *-------------------------------------------------------- # *--------------------------------------------------------
#*/ #*/
from .utils import *
from .HdlrUEIuCS import * from .HdlrUEIuCS import *
from .HdlrUEIuPS import * from .HdlrUEIuPS import *
from .HdlrUES1 import * from .HdlrUES1 import *
from .HdlrUENG import * from .HdlrUENG import *
from .utils import *
class UEd(SigStack): class UEd(SigStack):
@ -75,10 +75,11 @@ class UEd(SigStack):
IMSI = None IMSI = None
IMEI = None IMEI = None
IMEISV = None IMEISV = None
# temporary identities (TMSI / PTMSI / MTMSI are uint32) # temporary identities (TMSI / PTMSI / MTMSI / FGTMSI are uint32)
TMSI = None # CS domain TMSI = None # CS domain
PTMSI = None # PS domain PTMSI = None # PS domain
MTMSI = None # EPS / 5GS domains MTMSI = None # EPS domain
FGTMSI = None # 5GS domain
#--------------------------------------------------------------------------# #--------------------------------------------------------------------------#
# CorenetServer reference # CorenetServer reference
@ -118,11 +119,17 @@ class UEd(SigStack):
if imsi: if imsi:
self.IMSI = imsi self.IMSI = imsi
elif 'tmsi' in kw: elif 'tmsi' in kw:
# CS domain, 3G
self.TMSI = kw['tmsi'] self.TMSI = kw['tmsi']
elif 'ptmsi' in kw: elif 'ptmsi' in kw:
# PS domain, 3G
self.PTMSI = kw['ptmsi'] self.PTMSI = kw['ptmsi']
elif 'mtmsi' in kw: elif 'mtmsi' in kw:
# EPS domain, 4G
self.MTMSI = kw['mtmsi'] self.MTMSI = kw['mtmsi']
elif 'fgtmsi' in kw:
# 5GS domain, 5G
self.FGTMSI = kw['fgtmsi']
# #
# init capabilities # init capabilities
self.Cap = {} self.Cap = {}
@ -405,6 +412,8 @@ class UEd(SigStack):
def get_new_tmsi(self): def get_new_tmsi(self):
# use the Python random generator # use the Python random generator
# WARNING: not good for randomness, but good enough for corenet
# and at least with some good uniqueness
return random.getrandbits(32) return random.getrandbits(32)
def set_tmsi(self, tmsi): def set_tmsi(self, tmsi):
@ -438,12 +447,23 @@ class UEd(SigStack):
del self.Server.MTMSI[self.MTMSI] del self.Server.MTMSI[self.MTMSI]
except Exception: except Exception:
pass pass
# set the new PTMSI # set the new MTMSI
self.MTMSI = mtmsi self.MTMSI = mtmsi
# update the Server LUT # update the Server LUT
self.Server.MTMSI[mtmsi] = self.IMSI self.Server.MTMSI[mtmsi] = self.IMSI
# TODO: handle 5G NAS identities def set_fgtmsi(self, fgtmsi):
# delete current 5GTMSI from the Server LUT
if self.FGTMSI is not None:
try:
del self.Server.FGTMSI[self.FGTMSI]
except Exception:
pass
# set the new 5G TMSI
self.FGTMSI = fgtmsi
# update the Server LUT
self.Server.FGTMSI[fgtmsi] = self.FGTMSI
#--------------------------------------------------------------------------# #--------------------------------------------------------------------------#
# UE location # UE location
@ -771,3 +791,4 @@ class UEd(SigStack):
return '\n\n'.join(txt) return '\n\n'.join(txt)
else: else:
return '' return ''

View File

@ -3,7 +3,7 @@
# * Software Name : pycrate # * Software Name : pycrate
# * Version : 0.4 # * Version : 0.4
# * # *
# * Copyright 2020. Benoit Michau. ANSSI. # * Copyright 2020. Benoit Michau. P1Sec.
# * # *
# * This library is free software; you can redistribute it and/or # * This library is free software; you can redistribute it and/or
# * modify it under the terms of the GNU Lesser General Public # * modify it under the terms of the GNU Lesser General Public
@ -29,9 +29,9 @@
from .utils import * from .utils import *
from .ProcCNNgap import * from .ProcCNNgap import *
# load all required 5GS NAS protocol handlers and SMS handler from .ProcCNFGMM import *
#from .ProcCNFGMM import * from .ProcCNFGSM import *
#from .HdlrUESMS import * from .HdlrUESMS import *
class UEFGMMd(SigStack): class UEFGMMd(SigStack):
@ -55,17 +55,27 @@ class UEFGMMd(SigStack):
# additional time for letting background task happen in priority # additional time for letting background task happen in priority
_WAIT_ADD = 0.005 _WAIT_ADD = 0.005
# list of 5GMM message types that do not require NAS security to be
# activated to be processed #--------------------------------------------------------------------------#
SEC_NOTNEED = {} # FGMM timers
# to disable completely the check for secured NAS message #--------------------------------------------------------------------------#
SEC_DISABLED = False
# MT Deregistration
T3522 = 1
# Registration
T3550 = 1
# UE Config Update
T3555 = 2
# AKA, SMC
T3560 = 2
# Identification
T3570 = 1
# NSSAI Auth
T3575 = 2
def _log(self, logtype, msg): def _log(self, logtype, msg):
self.NG._log(logtype, '[5GMM] %s' % msg) self.NG._log(logtype, '[5GMM] %s' % msg)
@ -89,13 +99,11 @@ class UEFGMMd(SigStack):
"""process a NAS 5GMM message (NasRx) sent by the UE, """process a NAS 5GMM message (NasRx) sent by the UE,
and return a list (possibly empty) of NGAP procedure(s) to be sent back and return a list (possibly empty) of NGAP procedure(s) to be sent back
to the gNB to the gNB
NasRx has 2 additional attributes (_sec [bool], _ulcnt [uint])
""" """
# TODO # TODO
return [] return []
def init_proc(self, ProcClass, encod=None, fgmm_preempt=False, sec=True): def init_proc(self, ProcClass, encod=None, fgmm_preempt=False):
"""initialize a CN-initiated 5GMM procedure of class `ProcClass' and """initialize a CN-initiated 5GMM procedure of class `ProcClass' and
given encoder(s), and return the procedure given encoder(s), and return the procedure
""" """
@ -133,7 +141,7 @@ class UEFGMMd(SigStack):
else: else:
return True return True
def run_proc(self, ProcClass, sec=True, **IEs): def run_proc(self, ProcClass, **IEs):
"""run a network-initiated procedure ProcClass in the context of the 5GMM stack, """run a network-initiated procedure ProcClass in the context of the 5GMM stack,
after setting the given IEs in the NAS message to be sent to the UE after setting the given IEs in the NAS message to be sent to the UE
@ -147,7 +155,7 @@ class UEFGMMd(SigStack):
if not self._net_init_con(): if not self._net_init_con():
return False, None return False, None
# #
Proc = self.init_proc(ProcClass, encod={ProcClass.Init: IEs}, fgmm_preempt=True, sec=sec) Proc = self.init_proc(ProcClass, encod={ProcClass.Init: IEs}, fgmm_preempt=True)
try: try:
NgapTxProc = Proc.output() NgapTxProc = Proc.output()
except Exception: except Exception:
@ -190,15 +198,6 @@ class UEFGSMd(SigStack):
# to bypass the process() server loop with a custom NAS PDU handler # to bypass the process() server loop with a custom NAS PDU handler
RX_HOOK = None RX_HOOK = None
# list of ESM message types that do not require NAS security to be
# activated to be processed
SEC_NOTNEED = {
}
# to disable completely the check for secured NAS message
SEC_DISABLED = False
def _log(self, logtype, msg): def _log(self, logtype, msg):
self.NG._log(logtype, '[5GSM] %s' % msg) self.NG._log(logtype, '[5GSM] %s' % msg)
@ -224,8 +223,6 @@ class UEFGSMd(SigStack):
and return a list (possibly empty) of NGAP procedure(s) to be sent back and return a list (possibly empty) of NGAP procedure(s) to be sent back
to the gNB to the gNB
NasRx has 2 additional attributes (_sec [bool], _ulcnt [uint])
FGMMProc [FMMSigProc or None], indicates if the NAS FGSM message is handled in FGMMProc [FMMSigProc or None], indicates if the NAS FGSM message is handled in
the context of an FGMM procedure the context of an FGMM procedure
""" """
@ -361,6 +358,7 @@ class UENGd(SigStack):
self.reset_sec_ctx() self.reset_sec_ctx()
# #
self.connected = Event() self.connected = Event()
self.nasinit = Event() # state for initial NAS message
if gnbd is not None: if gnbd is not None:
self.set_ran(gnbd) self.set_ran(gnbd)
else: else:
@ -369,12 +367,13 @@ class UENGd(SigStack):
# init 5GMM and 5GSM sig stacks # init 5GMM and 5GSM sig stacks
self.FGMM = UEFGMMd(ued, self) self.FGMM = UEFGMMd(ued, self)
self.FGSM = UEFGSMd(ued, self) self.FGSM = UEFGSMd(ued, self)
#self.SMS = UESMSd(ued, self) self.SMS = UESMSd(ued, self)
def set_ran(self, gnbd): def set_ran(self, gnbd):
self.SEC['KSI'] = None self.SEC['KSI'] = None
self.GNB = gnbd self.GNB = gnbd
self.connected.set() self.connected.set()
self.nasinit.set()
def unset_ran(self): def unset_ran(self):
self.GNB.unset_ue_ng(self.CtxId) self.GNB.unset_ue_ng(self.CtxId)
@ -382,6 +381,7 @@ class UENGd(SigStack):
self.SEC['KSI'] = None self.SEC['KSI'] = None
self.clear() self.clear()
self.connected.clear() self.connected.clear()
self.nasinit.clear()
def set_ran_unconnected(self, gnbd): def set_ran_unconnected(self, gnbd):
# required for paging # required for paging
@ -575,13 +575,15 @@ class UENGd(SigStack):
return self.ret_ngap_dnt(NAS.FGMMStatus(val={'5GMMCause':err}, sec=False)) return self.ret_ngap_dnt(NAS.FGMMStatus(val={'5GMMCause':err}, sec=False))
# #
# 5GS NAS security handling # 5GS NAS security handling
sh, pd = NasRxSec[0]['SecHdr'].get_val(), NasRxSec[0]['EPD'].get_val() sh, pd = NasRxSec[0]['SecHdr'].get_val(), NasRxSec[0]['EPD'].get_val()
if sh == 0: if sh == 0:
# clear-text NAS message # clear-text NAS message
NasRxSec._sec = False NasRxSec._sec = False
NasRxSec._ulcnt = 0 NasRxSec._ulcnt = 0
if self.UE.TRACE_NAS_EPS: if self.UE.TRACE_NAS_5GS:
self._log('TRACE_NAS_5G_UL', '\n' + NasRxSec.show()) self._log('TRACE_NAS_5GS_UL', '\n' + NasRxSec.show())
if pd == 126: if pd == 126:
NgapTxProc = self.FGMM.process(NasRxSec) NgapTxProc = self.FGMM.process(NasRxSec)
else: else:
@ -707,7 +709,6 @@ class UENGd(SigStack):
else: else:
return [] return []
def _ngap_nas_sec_err(self): def _ngap_nas_sec_err(self):
# TODO: maybe release the NG-UE link ? # TODO: maybe release the NG-UE link ?
return [] return []
@ -716,6 +717,7 @@ class UENGd(SigStack):
# clears all NAS EPS procedures # clears all NAS EPS procedures
self.FGMM.clear() self.FGMM.clear()
self.FGSM.clear() self.FGSM.clear()
self.SMS.clear()
#--------------------------------------------------------------------------# #--------------------------------------------------------------------------#
# network-initiated method (fg task, to be used from the interpreter) # network-initiated method (fg task, to be used from the interpreter)

View File

@ -68,17 +68,18 @@ class UEEMMd(SigStack):
# list of EMM message types that do not require NAS security to be # list of EMM message types that do not require NAS security to be
# activated to be processed # activated to be processed
SEC_NOTNEED = {'EMMAttachRequest', SEC_NOTNEED = {
'EMMIdentityResponse', # only for IMSI 'EMMAttachRequest',
'EMMAuthenticationResponse', 'EMMIdentityResponse', # only for IMSI
'EMMAuthenticationFailure', 'EMMAuthenticationResponse',
'EMMSecurityModeReject', 'EMMAuthenticationFailure',
'EMMDetachRequestMO', # if sent before security activation 'EMMSecurityModeReject',
'EMMDetachAccept', 'EMMDetachRequestMO', # if sent before security activation
'EMMTrackingAreaUpdateRequest', 'EMMDetachAccept',
'EMMServiceRequest', 'EMMTrackingAreaUpdateRequest',
'EMMExtServiceRequest' 'EMMServiceRequest',
} 'EMMExtServiceRequest'
}
# to disable completely the check for secured NAS message # to disable completely the check for secured NAS message
SEC_DISABLED = False SEC_DISABLED = False

View File

@ -0,0 +1,794 @@
# -*- coding: UTF-8 -*-
#/**
# * Software Name : pycrate
# * Version : 0.4
# *
# * Copyright 2021. Benoit Michau. P1Sec.
# *
# * This library is free software; you can redistribute it and/or
# * modify it under the terms of the GNU Lesser General Public
# * License as published by the Free Software Foundation; either
# * version 2.1 of the License, or (at your option) any later version.
# *
# * This library is distributed in the hope that it will be useful,
# * but WITHOUT ANY WARRANTY; without even the implied warranty of
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# * Lesser General Public License for more details.
# *
# * You should have received a copy of the GNU Lesser General Public
# * License along with this library; if not, write to the Free Software
# * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# * MA 02110-1301 USA
# *
# *--------------------------------------------------------
# * File Name : pycrate_corenet/ProcCNFGMM.py
# * Created : 2021-04-27
# * Authors : Benoit Michau
# *--------------------------------------------------------
#*/
__all__ = [
'FGMMSigProc',
#
'FGMMPrimAKA',
'FGMMSecurityModeControl',
'FGMMIdentification',
'FGMMGenericUEConfigUpdate',
'FGMMMONASTransport',
'FGMMMTNASTransport',
'FGMMNSSAA',
#
'FGMMRegistration',
'FGMMMODeregistration',
'FGMMMTDeregistration',
'FGMMServiceRequest',
'FGMMCtrlPlaneServiceRequest',
#
'FGMMProcUeDispatcher',
'FGMMProcUeDispatcherStr',
'FGMMProcCnDispatcher',
'FGMMProcCnDispatcherStr'
]
from .utils import *
from .ProcProto import *
from .ProcCNNgap import *
TESTING = False
#------------------------------------------------------------------------------#
# NAS 5GS Mobility Management signalling procedure
# TS 24.501, version h21
# Core Network side
#------------------------------------------------------------------------------#
class FGMMSigProc(NASSigProc):
"""5GS Mobility Management signalling procedure handler
instance attributes:
- Name : procedure name
- FGMM : reference to the UEFGMMd instance running this procedure
- NG : reference to the UENGd instance connecting the UE
- Cont : 2-tuple of CN-initiated NAS message(s) and UE-initiated NAS
message(s)
- Timer: timer in sec. for this procedure
- Encod: custom NAS message encoders with fixed values
- Decod: custom NAS message decoders with transform functions
"""
# tacking all exchanged NAS message within the procedure
TRACK_PDU = True
# potential timer
Timer = None
TimerDefault = 4
# network initiator message id
Init = None
if TESTING:
def __init__(self, encod=None):
self._prepare(encod)
self._log('DBG', 'instantiating procedure')
def _log(self, logtype, msg):
log('[TESTING] [%s] [FGMMSigProc] [%s] %s' % (logtype, self.Name, msg))
else:
def __init__(self, fgmmd, encod=None, fgmm_preempt=False, sec=True):
self._prepare(encod)
self.FGMM = fgmmd
self.NG = fgmmd.NG
self.UE = fgmmd.UE
self._fgmm_preempt = fgmm_preempt
if fgmm_preempt:
self.FGMM.ready.clear()
self._log('DBG', 'instantiating procedure')
def _log(self, logtype, msg):
self.FGMM._log(logtype, '[%s] %s' % (self.Name, msg))
def output(self):
self._log('ERR', 'output() not implemented')
return []
def process(self, pdu):
if self.TRACK_PDU:
self._pdu.append( (time(), 'UL', pdu) )
self.UEInfo = {}
self.decode_msg(pdu, self.UEInfo)
#
self._log('ERR', 'process() not implemented')
return []
def postprocess(self, Proc=None):
self._log('ERR', 'postprocess() not implemented')
self.rm_from_fgmm_stack()
return []
def abort(self):
# abort this procedure, and all procedures started within this one
ind = self.FGMM.Proc.index(self)
if ind >= 0:
for p in self.FGMM.Proc[ind+1:]:
p.abort()
del self.FGMM.Proc[ind:]
if self._fgmm_preempt:
# release the FGMM stack
self.FGMM.ready.set()
self._log('INF', 'aborting')
def rm_from_fgmm_stack(self):
# remove the procedure from the FGMM stack of procedures
try:
if self.FGMM.Proc[-1] == self:
del self.FGMM.Proc[-1]
except Exception:
self._log('WNG', 'FGMM stack corrupted')
else:
if self._fgmm_preempt:
# release the FGMM stack
self.FGMM.ready.set()
def init_timer(self):
if self.Timer is not None:
self.TimerValue = getattr(self.FGMM, self.Timer, self.TimerDefault)
self.TimerStart = time()
self.TimerStop = self.TimerStart + self.TimerValue
def get_timer(self):
if self.Timer is None:
return None
else:
return getattr(self.FGMM, self.Timer)
def fgmm_preempt(self):
self._fgmm_preempt = True
self.FGMM.ready.clear()
#--------------------------------------------------------------------------#
# common helpers
#--------------------------------------------------------------------------#
# None yet
#------------------------------------------------------------------------------#
# 5GMM common procedures: TS 24.501, section 5.4
#------------------------------------------------------------------------------#
class FGMMPrimAKA(FGMMSigProc):
"""Primary authentication and key agreement procedure: TS 24.501, section 5.4.1
CN-initiated
CN message:
5GMMAuthenticationRequest (PD 126, Type 86), IEs:
- Type1V : spare
- Type1V : NAS_KSI
- Type4LV : ABBA
- Type3TV : RAND (T: 33)
- Type4TLV : AUTN (T: 32)
- Type6TLVE : EAPMsg (T: 120)
5GMMAuthenticationReject (PD 126, Type 88), IEs:
- Type6TLVE : EAPMsg (T: 120)
5GMMAuthenticationResult (PD 126, Type 90), IEs:
- Type1V : spare
- Type1V : NAS_KSI
- Type6LVE : EAPMsg
- Type4TLV : ABBA (T: 56)
UE message:
5GMMAuthenticationResponse (PD 126, Type 87), IEs:
- Type4TLV : RES (T: 45)
- Type6TLVE : EAPMsg (T: 120)
5GMMAuthenticationFailure (PD 126, Type 89), IEs:
- Type3V : 5GMMCause
- Type4TLV : AUTS (T: 48)
"""
Cont = (
(TS24501_FGMM.FGMMAuthenticationRequest, TS24501_FGMM.FGMMAuthenticationReject),
(TS24501_FGMM.FGMMAuthenticationResponse, TS24501_FGMM.FGMMAuthenticationFailure)
)
Init = (126, 86)
Timer = 'T3560'
'''TODO
def output(self):
return []
def process(self, pdu):
return []
'''
class FGMMSecurityModeControl(FGMMSigProc):
"""Security mode control procedure: TS 24.501, section 5.4.2
CN-initiated
CM message:
5GMMSecurityModeCommand (PD 126, Type 93), IEs:
- Type3V : NASSecAlgo
- Type1V : spare
- Type1V : NAS_KSI
- Type4LV : UESecCap
- Type1TV : IMEISVReq (T: 14)
- Type3TV : EPSNASSecAlgo (T: 87)
- Type4TLV : Add5GSecInfo (T: 54)
- Type6TLVE : EAPMsg (T: 120)
- Type4TLV : ABBA (T: 56)
- Type4TLV : S1UESecCap (T: 25)
UE message:
5GMMSecurityModeComplete (PD 126, Type 94), IEs:
- Type6TLVE : IMEISV (T: 119)
- Type6TLVE : NASContainer (T: 113)
- Type6TLVE : PEI (T: 120)
5GMMSecurityModeReject (PD 126, Type 95), IEs:
- Type3V : 5GMMCause
"""
Cont = (
(TS24501_FGMM.FGMMSecurityModeCommand, ),
(TS24501_FGMM.FGMMSecurityModeComplete, TS24501_FGMM.FGMMSecurityModeReject)
)
Init = (126, 93)
Timer = 'T3560'
'''TODO
def output(self):
return []
def process(self, pdu):
return []
'''
class FGMMIdentification(FGMMSigProc):
"""Identification procedure: TS 24.501, section 5.4.3
CN-initiated
CN message:
5GMMIdentityRequest (PD 126, Type 91), IEs:
- Type1V : spare
- Type1V : 5GSIDType
UE message:
5GMMIdentityResponse (PD 126, Type 92), IEs:
- Type6LVE : 5GSID
"""
Cont = (
(NAS.FGMMIdentityRequest, ),
(NAS.FGMMIdentityResponse, )
)
Init = (126, 91)
Timer = 'T3570'
'''TODO
def output(self):
return []
def process(self, pdu):
return []
'''
class FGMMGenericUEConfigUpdate(FGMMSigProc):
"""Generic UE configuration update procedure: TS 24.501, section 5.4.4
CN-initiated
CN message:
5GMMConfigurationUpdateCommand (PD 126, Type 84), IEs:
- Type1TV : ConfigUpdateInd (T: 13)
- Type6TLVE : GUTI (T: 119)
- Type4TLV : 5GSTAIList (T: 84)
- Type4TLV : AllowedNSSAI (T: 21)
- Type4TLV : SAList (T: 39)
- Type4TLV : NetFullName (T: 67)
- Type4TLV : NetShortName (T: 69)
- Type3TV : LocalTimeZone (T: 70)
- Type3TV : UnivTimeAndTimeZone (T: 71)
- Type4TLV : DLSavingTime (T: 73)
- Type6TLVE : LADNInfo (T: 121)
- Type1TV : MICOInd (T: 11)
- Type1TV : NetSlicingInd (T: 9)
- Type4TLV : ConfiguredNSSAI (T: 49)
- Type4TLV : RejectedNSSAI (T: 17)
- Type6TLVE : OperatorAccessCatDefs (T: 118)
- Type1TV : SMSInd (T: 15)
- Type4TLV : T3447 (T: 108)
- Type6TLVE : CAGInfoList (T: 117)
- Type4TLV : UERadioCapID (T: 103)
- Type1TV : UERadioCapIDDelInd (T: 10)
- Type4TLV : 5GSRegResult (T: 68)
- Type4TLV : Trunc5GSTMSIConfig (T: 27)
- Type1TV : AddConfigInd (T: 12)
UE message:
5GMMConfigurationUpdateComplete (PD 126, Type 85), IEs:
None
"""
Cont = (
(NAS.FGMMConfigurationUpdateCommand, ),
(NAS.FGMMConfigurationUpdateComplete, )
)
Init = (126, 84)
Timer = 'T3555'
'''TODO
def output(self):
return []
def process(self, pdu):
return []
'''
class FGMMMONASTransport(FGMMSigProc):
"""UE-initiated NAS transport procedure: TS 24.501, section 5.4.5.2
UE-initiated
CN message:
None
UE message:
5GMMULNASTransport (PD 126, Type 103), IEs:
- Type1V : spare
- Type1V : PayloadContainerType
- Type6LVE : PayloadContainer
- Type3TV : PDUSessID (T: 18)
- Type3TV : OldPDUSessID (T: 89)
- Type1TV : RequestType (T: 8)
- Type4TLV : SNSSAI (T: 34)
- Type4TLV : DNN (T: 37)
- Type4TLV : AddInfo (T: 36)
- Type1TV : MAPDUSessInfo (T: 10)
- Type1TV : ReleaseAssistInd (T: 15)
"""
Cont = (
None,
(NAS.FGMMULNASTransport,)
)
Init = (126, 103)
'''TODO
def process(self, pdu):
return []
'''
class FGMMMTNASTransport(FGMMSigProc):
"""Network-initiated NAS transport procedure: TS 24.501, section 5.4.5.3
CN-initiated
CN message:
5GMMDLNASTransport (PD 126, Type 104), IEs:
- Type1V : spare
- Type1V : PayloadContainerType
- Type6LVE : PayloadContainer
- Type3TV : PDUSessID (T: 18)
- Type4TLV : AddInfo (T: 36)
- Type3TV : 5GMMCause (T: 88)
- Type4TLV : BackOffTimer (T: 55)
UE message:
None
"""
Cont = (
(NAS.FGMMDLNASTransport, ),
None
)
Init = (126, 104)
'''TODO
def output(self):
return []
'''
class FGMMNSSAA(FGMMSigProc):
"""Network slice-specific authentication and authorization procedure: TS 24.501, section 5.4.7
CN-initiated
CN message:
5GMMNetworkSliceSpecAuthCommand (PD 126, Type 80), IEs:
- Type4LV : SNSSAI
- Type6LVE : EAPMsg
5GMMNetworkSliceSpecAuthResult (PD 126, Type 82), IEs:
- Type4LV : SNSSAI
- Type6LVE : EAPMsg
UE message:
5GMMNetworkSliceSpecAuthComplete (PD 126, Type 81), IEs:
- Type4LV : SNSSAI
- Type6LVE : EAPMsg
"""
Cont = (
(NAS.FGMMNetworkSliceSpecAuthCommand, NAS.FGMMNetworkSliceSpecAuthResult),
(NAS.FGMMNetworkSliceSpecAuthComplete, )
)
Init = (126, 80)
Timer = 'T3575'
'''TODO
def output(self):
return []
def process(self, pdu):
return []
'''
#------------------------------------------------------------------------------#
# 5GMM specific procedures: TS 24.501, section 5.5
#------------------------------------------------------------------------------#
class FGMMRegistration(FGMMSigProc):
"""Registration procedure: TS 24.501, section 5.5.1
UE-initiated
CN message:
5GMMRegistrationAccept (PD 126, Type 66), IEs:
- Type4LV : 5GSRegResult
- Type6TLVE : GUTI (T: 119)
- Type4TLV : EquivPLMNList (T: 74)
- Type4TLV : 5GSTAIList (T: 84)
- Type4TLV : AllowedNSSAI (T: 21)
- Type4TLV : RejectedNSSAI (T: 17)
- Type4TLV : ConfiguredNSSAI (T: 49)
- Type4TLV : 5GSNetFeat (T: 33)
- Type4TLV : PDUSessStat (T: 80)
- Type4TLV : PDUSessReactResult (T: 38)
- Type6TLVE : PDUSessReactResultErr (T: 114)
- Type6TLVE : LADNInfo (T: 121)
- Type1TV : MICOInd (T: 11)
- Type1TV : NetSlicingInd (T: 9)
- Type4TLV : SAList (T: 39)
- Type4TLV : T3512 (T: 94)
- Type4TLV : Non3GPPDeregTimer (T: 93)
- Type4TLV : T3502 (T: 22)
- Type4TLV : EmergNumList (T: 52)
- Type6TLVE : ExtEmergNumList (T: 122)
- Type6TLVE : SORTransContainer (T: 115)
- Type6TLVE : EAPMsg (T: 120)
- Type1TV : NSSAIInclMode (T: 10)
- Type6TLVE : OperatorAccessCatDefs (T: 118)
- Type4TLV : 5GSDRXParam (T: 81)
- Type1TV : Non3GPPNWProvPol (T: 13)
- Type4TLV : EPSBearerCtxtStat (T: 96)
- Type4TLV : ExtDRXParam (T: 110)
- Type4TLV : T3447 (T: 108)
- Type4TLV : T3448 (T: 107)
- Type4TLV : T3324 (T: 106)
- Type4TLV : UERadioCapID (T: 103)
- Type4TLV : PendingNSSAI (T: 57)
- Type6TLVE : CipheringKeyData (T: 116)
- Type6TLVE : CAGInfoList (T: 117)
- Type4TLV : Trunc5GSTMSIConfig (T: 27)
- Type4TLV : WUSAssistInfo (T: 26)
- Type4TLV : NBN1ModeDRXParam (T: 41)
5GMMRegistrationReject (PD 126, Type 68), IEs:
- Type3V : 5GMMCause
- Type4TLV : T3346 (T: 95)
- Type4TLV : T3502 (T: 22)
- Type6TLVE : EAPMsg (T: 120)
- Type4TLV : RejectedNSSAI (T: 105)
- Type6TLVE : CAGInfoList (T: 117)
UE message:
5GMMRegistrationRequest (PD 126, Type 65), IEs:
- Type1V : NAS_KSI
- Type1V : 5GSRegType
- Type6LVE : 5GSID
- Type1TV : NonCurrentNativeNAS_KSI (T: 12)
- Type4TLV : 5GMMCap (T: 16)
- Type4TLV : UESecCap (T: 46)
- Type4TLV : NSSAI (T: 47)
- Type3TV : TAI (T: 82)
- Type4TLV : EPSUENetCap (T: 23)
- Type4TLV : ULDataStat (T: 64)
- Type4TLV : PDUSessStat (T: 80)
- Type1TV : MICOInd (T: 11)
- Type4TLV : UEStatus (T: 43)
- Type6TLVE : AddGUTI (T: 119)
- Type4TLV : AllowedPDUSessStat (T: 37)
- Type4TLV : UEUsage (T: 24)
- Type4TLV : 5GSDRXParam (T: 81)
- Type6TLVE : EPSNASContainer (T: 112)
- Type6TLVE : LADNInd (T: 116)
- Type1TV : PayloadContainerType (T: 8)
- Type6TLVE : PayloadContainer (T: 123)
- Type1TV : NetSlicingInd (T: 9)
- Type4TLV : 5GSUpdateType (T: 83)
- Type4TLV : MSCm2 (T: 65)
- Type4TLV : SuppCodecs (T: 66)
- Type6TLVE : NASContainer (T: 113)
- Type4TLV : EPSBearerCtxtStat (T: 96)
- Type4TLV : ExtDRXParam (T: 110)
- Type4TLV : T3324 (T: 106)
- Type4TLV : UERadioCapID (T: 103)
- Type4TLV : MappedNSSAI (T: 53)
- Type4TLV : AddInfoReq (T: 72)
- Type4TLV : WUSAssistInfo (T: 26)
- Type2 : N5GCInd (T: 10)
- Type4TLV : NBN1ModeDRXParam (T: 48)
5GMMRegistrationComplete (PD 126, Type 67), IEs:
- Type6TLVE : SORTransContainer (T: 115)
"""
Cont = (
(NAS.FGMMRegistrationAccept, NAS.FGMMRegistrationReject),
(NAS.FGMMRegistrationRequest, NAS.FGMMRegistrationComplete)
)
Init = (126, 65)
Timer = 'T3550'
'''TODO
def process(self, pdu):
return []
def output(self):
return []
'''
class FGMMMODeregistration(FGMMSigProc):
"""UE-initiated de-registration procedure: TS 24.501, section 5.5.2.2
UE-initiated
CN message:
5GMMMODeregistrationAccept (PD 126, Type 70), IEs:
None
UE message:
5GMMMODeregistrationRequest (PD 126, Type 69), IEs:
- Type1V : NAS_KSI
- Type1V : DeregistrationType
- Type6LVE : 5GSID
"""
Cont = (
(NAS.FGMMMODeregistrationAccept, ),
(NAS.FGMMMODeregistrationRequest, )
)
Init = (126, 69)
'''TODO
def process(self, pdu):
return []
def output(self):
return []
'''
class FGMMMTDeregistration(FGMMSigProc):
"""Network-initiated de-registration procedure: TS 24.501, section 5.5.2.3
CN-initiated
CN message:
5GMMMTDeregistrationRequest (PD 126, Type 71), IEs:
- Type1V : spare
- Type1V : DeregistrationType
- Type3TV : 5GMMCause (T: 88)
- Type4TLV : T3346 (T: 95)
- Type4TLV : RejectedNSSAI (T: 109)
UE message:
5GMMMTDeregistrationAccept (PD 126, Type 71), IEs:
None
"""
Cont = (
(NAS.FGMMMTDeregistrationRequest, ),
(NAS.FGMMMTDeregistrationAccept, )
)
Init = (126, 71)
Timer = 'T3522'
'''TODO
def output(self):
return []
def process(self, pdu):
return []
'''
#------------------------------------------------------------------------------#
# 5GMM connection management procedures: TS 24.501, section 5.6
#------------------------------------------------------------------------------#
class FGMMServiceRequest(FGMMSigProc):
"""Service request procedure: TS 24.501, section 5.6.1
UE-initiated
CN message:
5GMMServiceAccept (PD 126, Type 78), IEs:
- Type4TLV : PDUSessStat (T: 80)
- Type4TLV : PDUSessReactResult (T: 38)
- Type6TLVE : PDUSessReactResultErr (T: 114)
- Type6TLVE : EAPMsg (T: 120)
- Type4TLV : T3448 (T: 107)
5GMMServiceAccept (PD 126, Type 77), IEs:
- Type3V : 5GMMCause
- Type4TLV : PDUSessStat (T: 80)
- Type4TLV : T3346 (T: 95)
- Type6TLVE : EAPMsg (T: 120)
- Type4TLV : T3448 (T: 107)
- Type6TLVE : CAGInfoList (T: 117)
UE message:
5GMMServiceRequest (PD 126, Type 76), IEs:
- Type1V : ServiceType
- Type1V : NAS_KSI
- Type6LVE : 5GSID
- Type4TLV : ULDataStat (T: 64)
- Type4TLV : PDUSessStat (T: 80)
- Type4TLV : AllowedPDUSessStat (T: 37)
- Type6TLVE : NASContainer (T: 113)
"""
Cont = (
(NAS.FGMMServiceAccept, NAS.FGMMServiceReject),
(NAS.FGMMServiceRequest, )
)
Init = (126, 76)
'''TODO
def process(self, pdu):
return []
def output(self):
return []
'''
class FGMMCtrlPlaneServiceRequest(FGMMSigProc):
"""Service request procedure: TS 24.501, section 5.6.1
UE-initiated
CN message:
5GMMServiceAccept (PD 126, Type 78), IEs:
- Type4TLV : PDUSessStat (T: 80)
- Type4TLV : PDUSessReactResult (T: 38)
- Type6TLVE : PDUSessReactResultErr (T: 114)
- Type6TLVE : EAPMsg (T: 120)
- Type4TLV : T3448 (T: 107)
5GMMServiceAccept (PD 126, Type 77), IEs:
- Type3V : 5GMMCause
- Type4TLV : PDUSessStat (T: 80)
- Type4TLV : T3346 (T: 95)
- Type6TLVE : EAPMsg (T: 120)
- Type4TLV : T3448 (T: 107)
- Type6TLVE : CAGInfoList (T: 117)
UE message:
5GMMControlPlaneServiceRequest (PD 126, Type 79), IEs:
- Type1V : NAS_KSI
- Type1V : CtrlPlaneServiceType
- Type4TLV : CIoTSmallDataContainer (T: 111)
- Type1TV : PayloadContainerType (T: 8)
- Type6TLVE : PayloadContainer (T: 123)
- Type3TV : PDUSessID (T: 18)
- Type4TLV : PDUSessStat (T: 80)
- Type1TV : ReleaseAssistInd (T: 15)
- Type4TLV : ULDataStat (T: 64)
- Type6TLVE : NASContainer (T: 113)
- Type4TLV : AddInfo (T: 36)
"""
Cont = (
(NAS.FGMMServiceAccept, NAS.FGMMServiceReject),
(NAS.FGMMControlPlaneServiceRequest, )
)
Init = (126, 79)
'''TODO
def process(self, pdu):
return []
def output(self):
return []
'''
FGMMPrimAKA.init(filter_init=1)
FGMMSecurityModeControl.init(filter_init=1)
FGMMIdentification.init(filter_init=1)
FGMMGenericUEConfigUpdate.init(filter_init=1)
FGMMMONASTransport.init(filter_init=1)
FGMMMTNASTransport.init(filter_init=1)
FGMMNSSAA.init(filter_init=1)
FGMMRegistration.init(filter_init=1)
FGMMMODeregistration.init(filter_init=1)
FGMMMTDeregistration.init(filter_init=1)
FGMMServiceRequest.init(filter_init=1)
FGMMCtrlPlaneServiceRequest.init(filter_init=1)
# 5G MM UE-initiated procedures dispatcher
FGMMProcUeDispatcher = {
103 : FGMMMONASTransport,
65 : FGMMRegistration,
69 : FGMMMODeregistration,
76 : FGMMServiceRequest,
79 : FGMMCtrlPlaneServiceRequest,
}
FGMMProcUeDispatcherStr = {ProcClass.Cont[1][0]()._name: ProcClass \
for ProcClass in FGMMProcUeDispatcher.values()}
# 5G MM CN-initiated procedures dispatcher
FGMMProcCnDispatcher = {
86 : FGMMPrimAKA,
93 : FGMMSecurityModeControl,
91 : FGMMIdentification,
84 : FGMMGenericUEConfigUpdate,
104 : FGMMMTNASTransport,
80 : FGMMNSSAA,
71 : FGMMMTDeregistration,
}
FGMMProcCnDispatcherStr = {ProcClass.Cont[0][0]()._name: ProcClass \
for ProcClass in FGMMProcCnDispatcher.values()}

View File

@ -0,0 +1,179 @@
# -*- coding: UTF-8 -*-
#/**
# * Software Name : pycrate
# * Version : 0.4
# *
# * Copyright 2021. Benoit Michau. P1Sec.
# *
# * This library is free software; you can redistribute it and/or
# * modify it under the terms of the GNU Lesser General Public
# * License as published by the Free Software Foundation; either
# * version 2.1 of the License, or (at your option) any later version.
# *
# * This library is distributed in the hope that it will be useful,
# * but WITHOUT ANY WARRANTY; without even the implied warranty of
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# * Lesser General Public License for more details.
# *
# * You should have received a copy of the GNU Lesser General Public
# * License along with this library; if not, write to the Free Software
# * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# * MA 02110-1301 USA
# *
# *--------------------------------------------------------
# * File Name : pycrate_corenet/ProcCNFGSM.py
# * Created : 2021-04-27
# * Authors : Benoit Michau
# *--------------------------------------------------------
#*/
__all__ = [
'FGSMSigProc',
]
from .utils import *
from .ProcProto import *
from .ProcCNNgap import *
TESTING = False
#------------------------------------------------------------------------------#
# NAS 5GS Session Management signalling procedure
# TS 24.501, version h21
# Core Network side
#------------------------------------------------------------------------------#
class FGSMSigProc(NASSigProc):
"""5GS Session Management signalling procedure handler
instance attributes:
- Name : procedure name
- FGSM : reference to the UEFGSMd instance running this procedure
- NG : reference to the UENGd instance connecting the UE
- Cont : 2-tuple of CN-initiated NAS message(s) and UE-initiated NAS
message(s)
- Timer: timer in sec. for this procedure
- Encod: custom NAS message encoders with fixed values
- Decod: custom NAS message decoders with transform functions
"""
# tacking all exchanged NAS message within the procedure
TRACK_PDU = True
# potential timer
Timer = None
TimerDefault = 2
if TESTING:
def __init__(self, encod=None):
self._prepare(encod)
self._log('DBG', 'instantiating procedure')
def _log(self, logtype, msg):
log('[TESTING] [%s] [FGSMSigProc] [%s] %s' % (logtype, self.Name, msg))
else:
def __init__(self, fgsmd, encod=None, sec=True, ebi=0, FGMMProc=None):
self._prepare(encod)
self.FGSM = fgsmd
self.NG = fgsmd.NG
self.UE = fgsmd.UE
self._ebi = ebi
self._FGMMProc = FGMMProc
self._log('DBG', 'instantiating procedure')
def _log(self, logtype, msg):
self.FGSM._log(logtype, '[%s [%i]] %s' % (self.Name, self._ebi, msg))
def decode_msg(self, msg, ret):
NASSigProc.decode_msg(self, msg, ret)
# add PDUSessionID and PTI into ret
ret['PDUSessID'] = msg[0][1].get_val()
ret['PTI'] = msg[0][2].get_val()
def set_msg(self, pd, typ, **kw):
"""prepare a specific encoder dict for a given NAS message
"""
# select the encoder and duplicate it
try:
Encod = self.Encod[(pd, typ)]
except Exception:
return
FGSMHeader = {}
if 'PDUSessID' in kw:
FGSMHeader['PDUSessID'] = kw['PDUSessID']
del kw['PDUSessID']
if 'PTI' in kw:
FGSMHeader['PTI'] = kw['PTI']
del kw['PTI']
if FGSMHeader:
kw['FGSMHeader'] = FGSMHeader
Encod.update(kw)
def output(self):
self._log('ERR', 'output() not implemented')
return None
def process(self, pdu):
if self.TRACK_PDU:
self._pdu.append( (time(), 'UL', pdu) )
self.UEInfo = {}
self.decode_msg(pdu, self.UEInfo)
#
self._log('ERR', 'process() not implemented')
return None
def postprocess(self, Proc=None):
self._log('ERR', 'postprocess() not implemented')
self.rm_from_fgsm_stack()
return None
def abort(self):
# abort this procedure, and all procedures started within this one
ProcStack = self.FGSM.Proc[self._ebi]
ind = ProcStack.index(self)
if ind >= 0:
for p in ProcStack[ind+1:]:
p.abort()
del ProcStack[ind:]
self._log('INF', 'aborting')
def rm_from_fgsm_stack(self):
# remove the procedure from the FGSM stack of procedures
try:
ProcStack = self.FGSM.Proc[self._ebi]
if ProcStack[-1] == self:
del ProcStack[-1]
except Exception:
self._log('WNG', 'FGSM stack corrupted')
def init_timer(self):
if self.Timer is not None:
self.TimerValue = getattr(self.FGSM, self.Timer, self.TimerDefault)
self.TimerStart = time()
self.TimerStop = self.TimerStart + self.TimerValue
def get_timer(self):
if self.Timer is None:
return None
else:
return getattr(self.FGSM, self.Timer)
#--------------------------------------------------------------------------#
# common helpers
#--------------------------------------------------------------------------#
# None yet
#------------------------------------------------------------------------------#
# Network-requested 5G SM procedures: TS 24.501, section 6.3
#------------------------------------------------------------------------------#
#------------------------------------------------------------------------------#
# UE-requested 5G SM procedures: TS 24.501, section 6.4
#------------------------------------------------------------------------------#

View File

@ -489,8 +489,10 @@ class NASSigProc(SigProc):
mhdr = msg[0] mhdr = msg[0]
if mhdr[0]._name == 'TIPD': if mhdr[0]._name == 'TIPD':
mid = (mhdr[0]['ProtDisc'].get_val(), mhdr['Type'].get_val()) mid = (mhdr[0]['ProtDisc'].get_val(), mhdr['Type'].get_val())
else: elif 'ProtDisc' in mhdr._by_name:
mid = (mhdr['ProtDisc'].get_val(), mhdr['Type'].get_val()) mid = (mhdr['ProtDisc'].get_val(), mhdr['Type'].get_val())
else:
mid = (mhdr['EPD'].get_val(), mhdr['Type'].get_val())
mies = msg[1:] mies = msg[1:]
ContLUT[mid] = (0, i) ContLUT[mid] = (0, i)
if mid not in cls.Encod: if mid not in cls.Encod:
@ -520,8 +522,10 @@ class NASSigProc(SigProc):
mhdr = msg[0] mhdr = msg[0]
if mhdr[0]._name == 'TIPD': if mhdr[0]._name == 'TIPD':
mid = (mhdr[0]['ProtDisc'].get_val(), mhdr['Type'].get_val()) mid = (mhdr[0]['ProtDisc'].get_val(), mhdr['Type'].get_val())
else: elif 'ProtDisc' in mhdr._by_name:
mid = (mhdr['ProtDisc'].get_val(), mhdr['Type'].get_val()) mid = (mhdr['ProtDisc'].get_val(), mhdr['Type'].get_val())
else:
mid = (mhdr['EPD'].get_val(), mhdr['Type'].get_val())
mies = msg[1:] mies = msg[1:]
ContLUT[mid] = (1, i) ContLUT[mid] = (1, i)
if mid not in cls.Encod: if mid not in cls.Encod:
@ -553,8 +557,10 @@ class NASSigProc(SigProc):
mhdr = msg[0] mhdr = msg[0]
if mhdr[0]._name == 'TIPD': if mhdr[0]._name == 'TIPD':
mid = (mhdr[0]['ProtDisc'].get_val(), mhdr['Type'].get_val()) mid = (mhdr[0]['ProtDisc'].get_val(), mhdr['Type'].get_val())
else: elif 'ProtDisc' in mhdr._by_name:
mid = (mhdr['ProtDisc'].get_val(), mhdr['Type'].get_val()) mid = (mhdr['ProtDisc'].get_val(), mhdr['Type'].get_val())
else:
mid = (mhdr['EPD'].get_val(), mhdr['Type'].get_val())
Filter.add(mid) Filter.add(mid)
FilterStr.add(msg._name) FilterStr.add(msg._name)
if Filter: if Filter:

View File

@ -342,10 +342,11 @@ class CorenetServer(object):
# UE, indexed by TMSI when the IMSI is unknown (at attachment), # UE, indexed by TMSI when the IMSI is unknown (at attachment),
# and their UEd handler instance are set in ._UEpre, created at init # and their UEd handler instance are set in ._UEpre, created at init
# #
# TMSI / P-TMSI / M-TMSI to IMSI conversion # TMSI / P-TMSI / M-TMSI / 5G-TMSI to IMSI conversion
TMSI = {} TMSI = {}
PTMSI = {} PTMSI = {}
MTMSI = {} MTMSI = {}
FGTMSI = {}
# #
# This is a filter which enables the potential attachment of non-preconfigured # This is a filter which enables the potential attachment of non-preconfigured
# UE to the CorenetServer # UE to the CorenetServer
@ -1315,7 +1316,7 @@ class CorenetServer(object):
def get_ued(self, **kw): def get_ued(self, **kw):
"""return a UEd instance or None, according to the UE identity provided """return a UEd instance or None, according to the UE identity provided
kw: imsi (digit-str), tmsi (uint32), ptmsi (uint32) or mtmsi (uint32) kw: imsi (digit-str), tmsi (uint32), ptmsi (uint32), mtmsi (uint32) or fgtmsi (uint32)
If an imsi is provided, returns the UEd instance in case the IMSI is allowed If an imsi is provided, returns the UEd instance in case the IMSI is allowed
If a tmsi or ptmsi is provided, returns If a tmsi or ptmsi is provided, returns
@ -1333,7 +1334,7 @@ class CorenetServer(object):
return self.UE[imsi] return self.UE[imsi]
elif self.UE_ATTACH_FILTER and re.match(self.UE_ATTACH_FILTER, imsi) and \ elif self.UE_ATTACH_FILTER and re.match(self.UE_ATTACH_FILTER, imsi) and \
'*' in self.ConfigUE: '*' in self.ConfigUE:
self._log('WNG', 'attaching an UE without dedicated configuration, IMSI %s' % imsi) self._log('WNG', 'attaching a UE without dedicated configuration, IMSI %s' % imsi)
self.UE[imsi] = UEd(self, imsi, config=self.ConfigUE['*']) self.UE[imsi] = UEd(self, imsi, config=self.ConfigUE['*'])
return self.UE[imsi] return self.UE[imsi]
else: else:
@ -1359,6 +1360,13 @@ class CorenetServer(object):
else: else:
# creating a UEd instance which will request IMSI # creating a UEd instance which will request IMSI
return self.create_dummy_ue(mtmsi=mtmsi) return self.create_dummy_ue(mtmsi=mtmsi)
elif 'fgtmsi' in kw:
fgtmsi = kw['fgtmsi']
if fgtmsi in self.FGTMSI:
return self.UE[self.FGTMSI[fgtmsi]]
else:
# creating a UEd instance which will request SUPI
return self.create_dummy_ue(fgtmsi=fgtmsi)
return None return None
def create_dummy_ue(self, **kw): def create_dummy_ue(self, **kw):
@ -1390,18 +1398,20 @@ class CorenetServer(object):
# go over all UE and abort() NAS signalling procedures in timeout # go over all UE and abort() NAS signalling procedures in timeout
T = time() T = time()
for ue in self.UE.values(): for ue in self.UE.values():
if ue.IuCS is not None: if ue.IuCS is not None:
if ue.IuCS.MM.Proc: if ue.IuCS.MM.Proc:
for P in ue.IuCS.MM.Proc: for P in ue.IuCS.MM.Proc:
if hasattr(P, 'TimerStop') and T > P.TimerStop: if hasattr(P, 'TimerStop') and T > P.TimerStop:
P._log('WNG', 'timeout: aborting') P._log('WNG', 'timeout: aborting')
P.abort() P.abort()
#if ue.IuCS.CC.Proc: if ue.IuCS.CC.Proc:
# for P in ue.IuCS.CC.Proc.values(): for P in ue.IuCS.CC.Proc.values():
# if hasattr(P, 'TimerStop') and T > P.TimerStop: if hasattr(P, 'TimerStop') and T > P.TimerStop:
# P._log('WNG', 'timeout: aborting') P._log('WNG', 'timeout: aborting')
# P.abort() P.abort()
if ue.IuCS.SMS.Proc: if ue.IuCS.SMS.Proc:
for P in tuple(ue.IuCS.SMS.Proc.values()): for P in tuple(ue.IuCS.SMS.Proc.values()):
@ -1409,11 +1419,11 @@ class CorenetServer(object):
P._log('WNG', 'timeout: aborting') P._log('WNG', 'timeout: aborting')
P.abort() P.abort()
#if ue.IuCS.SS.Proc: if ue.IuCS.SS.Proc:
# for P in ue.IuCS.SS.Proc.values(): for P in ue.IuCS.SS.Proc.values():
# if hasattr(P, 'TimerStop') and T > P.TimerStop: if hasattr(P, 'TimerStop') and T > P.TimerStop:
# P._log('WNG', 'timeout: aborting') P._log('WNG', 'timeout: aborting')
# P.abort() P.abort()
if ue.IuPS is not None: if ue.IuPS is not None:
@ -1424,11 +1434,11 @@ class CorenetServer(object):
P._log('WNG', 'timeout: aborting') P._log('WNG', 'timeout: aborting')
P.abort() P.abort()
#if ue.IuPS.SM.Proc: if ue.IuPS.SM.Proc:
# for P in tuple(ue.IuPS.SM.Proc.values()): for P in tuple(ue.IuPS.SM.Proc.values()):
# if hasattr(P, 'TimerStop') and T > P.TimerStop: if hasattr(P, 'TimerStop') and T > P.TimerStop:
# P._log('WNG', 'timeout: aborting') P._log('WNG', 'timeout: aborting')
# P.abort() P.abort()
if ue.S1 is not None: if ue.S1 is not None:
@ -1449,6 +1459,26 @@ class CorenetServer(object):
if hasattr(P, 'TimerStop') and T > P.TimerStop: if hasattr(P, 'TimerStop') and T > P.TimerStop:
P._log('WNG', 'timeout: aborting') P._log('WNG', 'timeout: aborting')
P.abort() P.abort()
if ue.NG is not None:
if ue.NG.FGMM.Proc:
for P in ue.NG.FGMM.Proc:
if hasattr(P, 'TimerStop') and T > P.TimerStop:
P._log('WNG', 'timeout: aborting')
P.abort()
if ue.NG.FGSM.Proc:
for P in tuple(ue.NG.FGSM.Proc.values()):
if hasattr(P, 'TimerStop') and T > P.TimerStop:
P._log('WNG', 'timeout: aborting')
P.abort()
if ue.NG.SMS.Proc:
for P in tuple(ue.NG.SMS.Proc.values()):
if hasattr(P, 'TimerStop') and T > P.TimerStop:
P._log('WNG', 'timeout: aborting')
P.abort()
def get_gtp_teid(self): def get_gtp_teid(self):
if self._GTP_TEID_UL > 4294967294: if self._GTP_TEID_UL > 4294967294:

View File

@ -475,32 +475,52 @@ def print_pduies(desc):
print(' None') print(' None')
def print_nasies(nasmsg): def print_nasies(nasmsg, indent=''):
# go after the header (last field: Type), and print IE type, tag if defined, # go after the header (last field: Type), and print IE type, tag if defined,
# and name # and name
# WNG: Type1V (Uint4), Type2 (Uint8), Type3V(Buf) are not wrapped # WNG: Type1V (Uint4), Type2 (Uint8), Type3V(Buf) are not wrapped
hdr = nasmsg[0] hdr = nasmsg[0]
if 'ProtDisc' in hdr._by_name: if 'ProtDisc' in hdr._by_name:
pd = hdr['ProtDisc'].get_val() pd = hdr['ProtDisc'].get_val()
elif 'EPD' in hdr._by_name:
pd = hdr['EPD'].get_val()
else: else:
pd = hdr[0]['ProtDisc'].get_val() pd = hdr[0]['ProtDisc'].get_val()
typ = hdr['Type'].get_val() typ = hdr['Type'].get_val()
print('%s (PD %i, Type %i), IEs:' % (nasmsg._name, pd, typ)) print('%s%s (PD %i, Type %i), IEs:' % (indent, nasmsg._name, pd, typ))
# #
if len(nasmsg._content) == 1: if len(nasmsg._content) == 1:
print(' None') print('%s None' % indent)
else: else:
for ie in nasmsg._content[1:]: for ie in nasmsg._content[1:]:
if ie.get_trans(): if ie.get_trans():
# optional IE # optional IE
print('- %-9s : %s (T: %i)'\ print('%s- %-9s : %s (T: %i)'\
% (ie.__class__.__name__, ie._name, ie[0].get_val())) % (indent, ie.__class__.__name__, ie._name, ie[0].get_val()))
elif isinstance(ie, TS24007.IE): elif isinstance(ie, TS24007.IE):
# mandatory IE # mandatory IE
print('- %-9s : %s' % (ie.__class__.__name__, ie._name)) print('%s- %-9s : %s' % (indent, ie.__class__.__name__, ie._name))
elif ie.get_bl() == 4: elif ie.get_bl() == 4:
# uint / spare bits # uint / spare bits
print('- %-9s : %s' % ('Type1V', 'spare')) print('%s- %-9s : %s' % (indent, 'Type1V', 'spare'))
else: else:
assert() assert()
def print_nasproc_docs(nasproc):
msgcn, msgue = nasproc.Cont
print('CN message:')
if msgcn is None:
print(' None')
else:
for m in msgcn:
print_nasies(m(), indent=' ')
print(' ')
print('UE message:')
if msgue is None:
print(' None')
else:
for m in msgue:
print_nasies(m(), indent=' ')
print(' ')