mobile: finalize 5G NAS update
This commit is contained in:
parent
0c59985ab6
commit
822bdda332
|
@ -32,6 +32,7 @@ from pycrate_core.utils import *
|
|||
from .TS24501_FGMM import FGMMTypeClasses, FGMMSecProtNASMessage
|
||||
from .TS24501_FGSM import FGSMTypeClasses
|
||||
from .TS24501_UEPOL import FGUEPOLTypeClasses
|
||||
from .TS24519_TSNAF import FGTSNAFEthPortTypeClasses, FGTSNAFBridgeTypeClasses
|
||||
from .TS24011_PPSMS import PPSMSCPTypeClasses
|
||||
|
||||
|
||||
|
@ -111,90 +112,154 @@ def parse_NAS5G(buf, inner=True, sec_hdr=True):
|
|||
# error 96, invalid mandatory info
|
||||
return None, 96
|
||||
#
|
||||
if inner and pd == 126:
|
||||
if typ in (65, 76, 79, 94):
|
||||
nasc = Msg['NASContainer']
|
||||
if not nasc.get_trans():
|
||||
# NAS Container present in Msg
|
||||
cont, err = parse_NAS5G(nasc[-1].get_val(), inner=inner)
|
||||
if err == 0:
|
||||
nasc.replace(nasc[-1], cont)
|
||||
if inner:
|
||||
if pd == 126:
|
||||
if typ in (65, 76, 79, 94):
|
||||
nasc = Msg['NASContainer']
|
||||
if not nasc.get_trans():
|
||||
# NAS Container present in Msg
|
||||
Cont, err = parse_NAS5G(nasc[-1].get_val(), inner=inner)
|
||||
if err == 0:
|
||||
nasc.replace(nasc['V'], Cont)
|
||||
#
|
||||
if typ in (65, 79, 103, 104):
|
||||
payct, payc = Msg['PayloadContainerType'], Msg['PayloadContainer']
|
||||
if not payct.get_trans() and not payc.get_trans():
|
||||
# Payload container present in Msg
|
||||
conttype, contbuf = payct['V'].get_val(), payc['V'].get_val()
|
||||
Cont, err = parse_PayCont(conttype, contbuf)
|
||||
if err == 0:
|
||||
payc.replace(payc['V'], Cont)
|
||||
#
|
||||
if typ in (65, 79, 103, 104):
|
||||
payct, payc = Msg['PayloadContainerType'], Msg['PayloadContainer']
|
||||
if not payct.get_trans() and not payc.get_trans():
|
||||
# Payload container present in Msg
|
||||
conttype, contbuf = payct['V'].get_val(), payc['V'].get_val()
|
||||
cont = parse_NAS5GPayCont(conttype, contbuf)
|
||||
if cont:
|
||||
payc.replace(payc['V'], cont)
|
||||
elif pd == 46:
|
||||
if typ in (193, 201, 203, 204):
|
||||
ethc = Msg['PortMgmtInfoContainer']
|
||||
if not ethc.get_trans():
|
||||
# PortMgmtInfoContainer present in Msg
|
||||
Cont, err = parse_PortMgmtInfoCont(ethc['V'].get_val())
|
||||
if err == 0:
|
||||
ethc.replace(ethc['V'], Cont)
|
||||
#
|
||||
return Msg, 0
|
||||
|
||||
|
||||
def parse_NAS5GPayCont(conttype, buf):
|
||||
def parse_PayCont(conttype, buf):
|
||||
|
||||
if conttype == 1 and len(buf) >= 2:
|
||||
# 5GSM
|
||||
cont, err = parse_NAS5G(buf, inner=True)
|
||||
if err == 0:
|
||||
return cont
|
||||
return parse_NAS5G(buf, inner=True)
|
||||
|
||||
elif conttype == 2 and len(buf) >= 2:
|
||||
# SMS PP
|
||||
pd, typ = unpack('>BB', buf[:2])
|
||||
pd &= 0xF
|
||||
if pd == 9 and typ in (1, 4, 16):
|
||||
cont = PPSMSCPTypeClasses[typ]()
|
||||
Cont = PPSMSCPTypeClasses[typ]()
|
||||
try:
|
||||
cont.from_bytes(buf)
|
||||
Cont.from_bytes(buf)
|
||||
except Exception:
|
||||
pass
|
||||
# error 96, invalid mandatory info
|
||||
return None, 96
|
||||
else:
|
||||
return cont
|
||||
return Cont, 0
|
||||
else:
|
||||
# error 97, Message type non-existent or not implemented
|
||||
return None, 97
|
||||
|
||||
elif conttype == 3:
|
||||
# LPP, TODO
|
||||
pass
|
||||
|
||||
elif conttype == 4 and len(buf) >= 17:
|
||||
# SOR
|
||||
cont = SORTransparentContainer()
|
||||
Cont = SORTransContainer()
|
||||
try:
|
||||
cont.from_bytes(buf)
|
||||
Cont.from_bytes(buf)
|
||||
except Exception:
|
||||
pass
|
||||
# error 96, invalid mandatory info
|
||||
return None, 96
|
||||
else:
|
||||
return cont
|
||||
return Cont, 0
|
||||
|
||||
elif conttype == 5 and len(buf) >= 2:
|
||||
# UE policy
|
||||
_, typ = unpack('>BB', buf[:2])
|
||||
if 1 <= typ <= 4:
|
||||
cont = FGUEPOLTypeClasses[typ]()
|
||||
Cont = FGUEPOLTypeClasses[typ]()
|
||||
try:
|
||||
cont.from_bytes(buf)
|
||||
Cont.from_bytes(buf)
|
||||
except Exception:
|
||||
pass
|
||||
# error 96, invalid mandatory info
|
||||
return None, 96
|
||||
else:
|
||||
return cont
|
||||
elif conttype == 6:
|
||||
# UE params update, TODO
|
||||
pass
|
||||
return Cont, 0
|
||||
else:
|
||||
# error 97, Message type non-existent or not implemented
|
||||
return None, 97
|
||||
|
||||
elif conttype == 6 and len(buf) >= 17:
|
||||
# UPU
|
||||
Cont = UPUTransContainer()
|
||||
try:
|
||||
Cont.from_bytes(buf)
|
||||
except Exception:
|
||||
# error 96, invalid mandatory info
|
||||
return None, 96
|
||||
else:
|
||||
return Cont, 0
|
||||
|
||||
elif conttype == 7:
|
||||
# Loc services, TODO
|
||||
pass
|
||||
elif conttype == 8:
|
||||
# CIoT, TODO
|
||||
# LCS, TODO
|
||||
pass
|
||||
|
||||
elif conttype == 8 and len(buf) >= 1:
|
||||
# CIoT
|
||||
Cont = CIoTSmallDataContainer()
|
||||
try:
|
||||
Cont.from_bytes(buf)
|
||||
except Exception:
|
||||
# error 96, invalid mandatory info
|
||||
return None, 96
|
||||
else:
|
||||
return Cont, 0
|
||||
|
||||
elif conttype == 15 and len(buf) >= 1:
|
||||
# multi
|
||||
cont = PayloadContainerMult()
|
||||
Cont = PayloadContainerMult()
|
||||
try:
|
||||
cont.from_bytes(buf)
|
||||
Cont.from_bytes(buf)
|
||||
except Exception:
|
||||
pass
|
||||
# error 96, invalid mandatory info
|
||||
return None, 96
|
||||
else:
|
||||
# parse each entry
|
||||
for entry in cont['Entries']:
|
||||
econttype, ebuf = cont['Type'].get_val(), cont['Cont'].get_val()
|
||||
econt = parse_NAS5GPayCont(econttype, ebuf)
|
||||
if econt:
|
||||
entry.replace(entr['Cont'], econt)
|
||||
return None
|
||||
|
||||
e_conttype, e_buf = Cont['Type'].get_val(), Cont['Cont'].get_val()
|
||||
e_cont, e_err = parse_NAS5GPayCont(e_conttype, e_buf)
|
||||
if e_err == 0:
|
||||
entry.replace(entry['Cont'], e_cont)
|
||||
|
||||
# error 96, invalid mandatory info
|
||||
return None, 96
|
||||
|
||||
|
||||
def parse_PortMgmtInfoCont(buf):
|
||||
try:
|
||||
# this corresponds actually only to the layout of the 5GMM header
|
||||
typ = unpack('>B', buf[:1])
|
||||
except Exception:
|
||||
# error 96, invalid mandatory info
|
||||
return None, 96
|
||||
if 1 <= typ <= 6:
|
||||
Cont = FGTSNAFEthPortTypeClasses[typ]()
|
||||
try:
|
||||
Cont.from_bytes(buf)
|
||||
except Exception:
|
||||
# error 96, invalid mandatory info
|
||||
return None, 96
|
||||
else:
|
||||
return Cont, 0
|
||||
else:
|
||||
# error 97, Message type non-existent or not implemented
|
||||
return None, 97
|
||||
|
||||
|
|
|
@ -70,9 +70,11 @@ class Layer3(Envelope):
|
|||
ENV_SEL_TRANS = False
|
||||
|
||||
# this is to break the decoding routine when an unknown IE is encountered
|
||||
# this needs to be set to True for 2G RR signaling message (due to rest octets)
|
||||
DEC_BREAK_ON_UNK_IE = False
|
||||
|
||||
|
||||
|
||||
def __init__(self, *args, **kw):
|
||||
if 'val' in kw:
|
||||
val = kw['val']
|
||||
|
@ -102,30 +104,38 @@ class Layer3(Envelope):
|
|||
self._rest = ie
|
||||
else:
|
||||
for ie in self._content:
|
||||
'''
|
||||
if isinstance(ie, (Type1V, Type1TV)):
|
||||
rawtype = integer_types
|
||||
else:
|
||||
rawtype = bytes_types
|
||||
'''
|
||||
if isinstance(ie, (Type1V, Type3V, Type4LV, Type6LVE)) and ie._name in val:
|
||||
# setting value for non-optional IE
|
||||
ie.set_val({'V': val[ie._name]})
|
||||
'''
|
||||
if isinstance(val[ie._name], rawtype):
|
||||
# setting raw value
|
||||
ie['V'].set_val(val[ie._name])
|
||||
else:
|
||||
# setting embedded IE structure
|
||||
ie.set_IE(val=val[ie._name])
|
||||
'''
|
||||
elif isinstance(ie, (Type1TV, Type3TV, Type4TLV, Type6TLVE)):
|
||||
# optional IE
|
||||
T = ie[0]
|
||||
self._opts.append( (T.get_bl(), T(), ie) )
|
||||
if ie._name in val:
|
||||
ie._trans = False
|
||||
ie.set_val({'V': val[ie._name]})
|
||||
'''
|
||||
if isinstance(val[ie._name], rawtype):
|
||||
# setting raw value
|
||||
ie['V'].set_val(val[ie._name])
|
||||
else:
|
||||
# setting embedded IE structure
|
||||
ie.set_IE(val=val[ie._name])
|
||||
'''
|
||||
elif isinstance(ie, Type2):
|
||||
# optional Tag-only IE
|
||||
self._opts.append( (8, ie[0](), ie) )
|
||||
|
@ -269,20 +279,25 @@ class IE(Envelope):
|
|||
elif isinstance(vals, (tuple, list)):
|
||||
for ind, elt in enumerate(self.__iter__()):
|
||||
val = vals[ind]
|
||||
if elt._name == 'V' and not isinstance(val, bytes_types):
|
||||
if elt._name == 'V' and not isinstance(val, elt.TYPES):
|
||||
# keep value for setting the inner IE
|
||||
ie_val = val
|
||||
else:
|
||||
# set raw V value
|
||||
elt.set_val(val)
|
||||
elif isinstance(vals, dict):
|
||||
for key, val in vals.items():
|
||||
if key == 'V' and not isinstance(val, bytes_types):
|
||||
if key == 'V' and not isinstance(val, self['V'].TYPES):
|
||||
# keep value for setting the inner IE
|
||||
ie_val = val
|
||||
else:
|
||||
# set raw V value
|
||||
self.__setitem__(key, val)
|
||||
elif self._SAFE_STAT:
|
||||
raise(EltErr('{0} [set_val]: vals type is {1}, expecting None, tuple, list or dict'\
|
||||
.format(self._name, type(vals).__name__)))
|
||||
if ie_val is not None:
|
||||
# set the value to the inner IE
|
||||
self.set_IE(val=ie_val)
|
||||
|
||||
def _from_char(self, char):
|
||||
|
|
|
@ -186,6 +186,8 @@ class SNSSAI(Envelope):
|
|||
|
||||
|
||||
def _from_char(self, char):
|
||||
if self.get_trans():
|
||||
return
|
||||
l = char.len_bit()
|
||||
if l == 8:
|
||||
self[1].set_trans(True)
|
||||
|
@ -683,6 +685,9 @@ _EMF_dict = {
|
|||
|
||||
|
||||
class FGSNetFeat(Envelope):
|
||||
|
||||
ENV_SEL_TRANS = False
|
||||
|
||||
_name = '5GSNetFeat'
|
||||
_GEN = (
|
||||
Uint('MPSI', bl=1),
|
||||
|
@ -710,9 +715,9 @@ class FGSNetFeat(Envelope):
|
|||
return
|
||||
l = char.len_bit()
|
||||
if l <= 8:
|
||||
self.disable_from(8)
|
||||
self.disable_from('5G-UP-CIoT')
|
||||
elif l <= 16:
|
||||
self.disable_from(13)
|
||||
self.disable_from('spare')
|
||||
elif l > 24:
|
||||
# enables some spare bits at the end
|
||||
self[-1]._bl = l-24
|
||||
|
@ -1883,6 +1888,9 @@ class AddConfigInd(Envelope):
|
|||
#------------------------------------------------------------------------------#
|
||||
|
||||
class FGSMCap(Envelope):
|
||||
|
||||
ENV_SEL_TRANS = False
|
||||
|
||||
_name = '5GSMCap'
|
||||
_GEN = (
|
||||
Uint('TPMIC', bl=1),
|
||||
|
|
|
@ -105,7 +105,7 @@ class EthPortParam(Envelope):
|
|||
_GEN = (
|
||||
Uint16('Name', val=1, dic=EthPortParamName_dict),
|
||||
Uint16('Len'),
|
||||
Buf('Value', val='', rep=REPR_HEX)
|
||||
Buf('Value', val=b'', rep=REPR_HEX)
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
@ -253,7 +253,7 @@ class BridgeParam(Envelope):
|
|||
_GEN = (
|
||||
Uint16('Name', val=1, dic=BridgeParamName_dict),
|
||||
Uint16('Len'),
|
||||
Buf('Value', val='', rep=REPR_HEX)
|
||||
Buf('Value', val=b'', rep=REPR_HEX)
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
@ -291,7 +291,7 @@ class BridgeMgmtList(Sequence):
|
|||
#------------------------------------------------------------------------------#
|
||||
|
||||
class BridgeMgmtCap(Array):
|
||||
_GEN = Uint16('ParamName', val=1, dic=BridgeParamName_dict),
|
||||
_GEN = Uint16('ParamName', val=1, dic=BridgeParamName_dict)
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
|
@ -359,7 +359,7 @@ class BridgeUpdRes(Envelope):
|
|||
class ManageEthPortCommand(Layer3E):
|
||||
_GEN = (
|
||||
Uint8('Type', val=1, dic=TSNAFEthPortMsgType_dict),
|
||||
Type6LVE('EthPortMgmtList', val={'V':b''}, IE=EthPortMgmtList()
|
||||
Type6LVE('EthPortMgmtList', val={'V':b''}, IE=EthPortMgmtList())
|
||||
)
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue