mobile: finalize 5G NAS update

This commit is contained in:
mich 2020-08-21 12:50:32 +02:00
parent 0c59985ab6
commit 822bdda332
4 changed files with 144 additions and 56 deletions

View File

@ -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

View File

@ -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):

View File

@ -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),

View File

@ -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())
)