mobile: almost finishing 5G NAS

This commit is contained in:
mich 2019-12-02 18:39:42 +01:00
parent f388afebe8
commit 53b08239fd
6 changed files with 615 additions and 94 deletions

139
pycrate_mobile/NAS5G.py Normal file
View File

@ -0,0 +1,139 @@
# -*- coding: UTF-8 -*-
#/**
# * Software Name : pycrate
# * Version : 0.4
# *
# * Copyright 2019. 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_mobile/NAS5G.py
# * Created : 2019-12-02
# * Authors : Benoit Michau
# *--------------------------------------------------------
#*/
from pycrate_core.utils import *
from .TS24501_FGMM import FGMMTypeClasses, FGMMSecProtNASMessage
from .TS24501_FGSM import FGSMTypeClasses
from .TS24011_PPSMS import PPSMSCPTypeClasses
def parse_NAS5G(buf, inner=True, sec_hdr=True):
"""Parses a 5G NAS message bytes' buffer
Args:
buf: 5G NAS message bytes' buffer
inner: if True, decode NASMessage within security header if possible
decode ?
sec_hdr: if True, handle the 5GMM security header
otherwise, just consider the NAS message is in plain text
Returns:
element, err: 2-tuple
element: Element instance, if err is null (no error)
element: None, if err is not null (standard 5G NAS error code)
"""
try:
# this corresponds actually only to the layout of the 5GMM header
pd, shr, typ = unpack('>BBB', buf)
except Exception:
# error 111, unspecified protocol error
return None, 111
#
if pd == 146:
# 5GMM
if sec_hdr and shdr in (1, 2, 3, 4):
# 5GMM security protected NAS message
Msg = FGMMSecProtNASMessage()
try:
Msg.from_bytes(buf)
except Exception:
# error 96, invalid mandatory info
return None, 96
if inner and shdr in (1, 3):
# parse clear-text NAS message container
cont, err = parse_NAS5G(Msg[3].get_val(), inner=inner)
if cont is not None:
Msg.replace(Msg[3], cont)
return Msg, err
else:
return Msg, 0
else:
# sec hdr == 0 or undefined
# no security, straight 5GMM message
try:
Msg = FGMMTypeClasses[typ]()
except KeyError:
# error 97, message type non-existent or not implemented
return None, 97
#
elif pd == 46:
# 5GSM
try:
if python_version < 3:
typ = ord(buf[3:4])
else:
typ = buf[3]
except:
# error 111, unspecified protocol error
return None, 111
try:
Msg = FGSMTypeClasses[typ]()
except KeyError:
# error 97, message type non-existent or not implemented
return None, 97
#
else:
# error 97: message type non-existent or not implemented
return None, 97
#
if inner and pd == 146:
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:
return Msg, err
else:
nasc.replace(nasc[-1], cont)
#
if typ in (65, 79, 103, 104):
payc = Msg['PayloadContainer']
if not payc.get_trans():
# Payload container present in Msg
# TODO: check if IE decoded properly, then decode each entry into a proper msg
# 5GSM and SMS at 1st
pass
#
return Msg, 0
'''payload container entries:
1 : 'N1 SM information',
2 : 'SMS',
3 : 'LTE Positioning Protocol message container',
4 : 'SOR transparent container',
5 : 'UE policy container',
6 : 'UE parameters update transparent container',
7 : 'Location services message container',
8 : 'CIoT user data container',
'''

View File

@ -148,7 +148,6 @@ def parse_NASLTE_MO(buf, inner=True, sec_hdr=True):
return Msg, err
else:
esmc.replace(esmc[-1], cont)
#esmc[-2].set_valauto(cont.get_len)
elif typ in (98, 99):
# PP-SMS
nasc = Msg['NASContainer']

View File

@ -36,8 +36,10 @@ from binascii import unhexlify
from time import struct_time
from pycrate_core.utils import *
from pycrate_core.elt import Envelope, Array, Sequence, REPR_RAW, REPR_HEX, \
REPR_BIN, REPR_HD, REPR_HUM
from pycrate_core.elt import (
Envelope, Array, Sequence, Alt,
REPR_RAW, REPR_HEX, REPR_BIN, REPR_HD, REPR_HUM
)
from pycrate_core.base import *
from pycrate_core.repr import *
from pycrate_core.charpy import Charpy
@ -3287,36 +3289,42 @@ class TFTPktFilterId(Envelope):
Uint('Id', bl=4)
)
class _CompIPv4(Envelope):
_GEN = (
Buf('Address', bl=32, rep=REPR_HEX),
Buf('Netmask', bl=32, rep=REPR_HEX)
)
class _CompIPv6(Envelope):
_GEN = (
Buf('Address', bl=128, rep=REPR_HEX),
Buf('Netmask', bl=128, rep=REPR_HEX)
)
class _CompIPv6Pref(Envelope):
_GEN = (
Buf('Address', bl=128, rep=REPR_HEX),
Uint8('PrefixLen')
)
class _CompPortRange(Envelope):
_GEN = (
Uint16('PortLo'),
Uint16('PortHi')
)
class _CompTrafficClass(Envelope):
_GEN = (
Uint8('Class'),
Uint8('Mask')
)
'''
class TFTPktFilterComp(Envelope):
_ValueLUT = {
16 : _CompIPv4('IPv4'),
@ -3356,6 +3364,7 @@ class TFTPktFilterComp(Envelope):
self.replace(self[1], self._ValueLUT[t].clone())
self[1]._from_char(char)
class TFTPktFilter(Envelope):
_Cont = Sequence('Cont', GEN=TFTPktFilterComp())
_GEN = (
@ -3401,18 +3410,72 @@ class TFTPktFilter(Envelope):
else:
char._cur = ccur
char._len_bit = clen
'''
class TFTPktFilterComp(Envelope):
_GEN = (
Uint8('Type', dic=_PktFilterCompType_dict),
Alt('Value', GEN={
16 : _CompIPv4('IPv4'),
17 : _CompIPv4('IPv4'),
32 : _CompIPv6('IPv6'),
33 : _CompIPv6Pref('IPv6Pref'),
35 : _CompIPv6Pref('IPv6Pref'),
48 : Uint8('ProtId'),
64 : Uint16('Port'),
65 : _CompPortRange('PortRange'),
80 : Uint16('Port'),
81 : _CompPortRange('PortRange'),
96 : Uint32('SPI'),
112 : _CompTrafficClass('TrafficClass'),
128 : Uint24('FlowLabel')
},
DEFAULT=Buf('unk', val=b'', rep=REPR_HEX),
sel=lambda self: self.get_env()['Type'].get_val())
)
class TFTPktFilter(Envelope):
_GEN = (
Uint('spare', bl=2),
Uint('Dir', bl=2, dic=_PktFilterDir_dict),
Uint('Id', bl=4),
Uint8('Precedence'),
Uint8('Len'),
Sequence('Cont', GEN=TFTPktFilterComp())
)
def __init__(self, *args, **kwargs):
Envelope.__init__(self, *args, **kwargs)
self['Len'].set_valauto(lambda: self['Cont'].get_len())
def _from_char(self, char):
if self.get_trans():
return
self[0]._from_char(char)
self[1]._from_char(char)
self[2]._from_char(char)
self[3]._from_char(char)
self[4]._from_char(char)
char_lb = char._len_bit
char._len_bit = char._cur + (self[4].get_val()<<3)
self[5]._from_char(char)
char._len_bit = char_lb
class TFTParameter(Envelope):
_GEN = (
Uint8('Id'),
Uint8('Len'),
Buf('Cont', val=b'')
Buf('Cont', val=b'', rep=REPR_HEX)
)
def __init__(self, *args, **kwargs):
Envelope.__init__(self, *args, **kwargs)
self[1].set_valauto(self[2].get_len)
self[2].set_blauto(lambda: 8*self[1]())
class TFT(Envelope):
ENV_SEL_TRANS = False
_GEN = (
@ -3423,6 +3486,7 @@ class TFT(Envelope):
Sequence('PktFilters', GEN=TFTPktFilter()),
Sequence('Parameters', GEN=TFTParameter())
)
def __init__(self, *args, **kwargs):
Envelope.__init__(self, *args, **kwargs)
self[2].set_valauto(lambda: self[3].get_num() if \

View File

@ -158,7 +158,7 @@ class FGMMAuthenticationRequest(Layer3):
Type4LV('ABBA', val={'V':b'\0\0'}),
Type3TV('RAND', val={'T':0x21, 'V':16*b'\0'}, bl={'V':128}),
Type4LV('AUTN', val={'V':16*b'\0'}, IE=AUTN()),
Type6TLVE('EAPMsg', val={'T':0x78, 'V':b'\0\0\0\0'})
Type6TLVE('EAPMsg', val={'T':0x78, 'V':b'\0\0\0\0\0'})
)
@ -172,7 +172,7 @@ class FGMMAuthenticationResponse(Layer3):
_GEN = (
FGMMHeader(val={'Type':87}),
Type4TLV('RES', val={'T':0x2D, 'V':16*b'\0'}),
Type6TLVE('EAPMsg', val={'T':0x78, 'V':b'\0\0\0\0'})
Type6TLVE('EAPMsg', val={'T':0x78, 'V':b'\0\0\0\0\0'})
)
@ -187,7 +187,7 @@ class FGMMAuthenticationResult(Layer3):
FGMMHeader(val={'Type':90}),
Uint('spare', bl=4, rep=REPR_HEX),
Type1V('NAS_KSI', val={'V':7}, IE=NAS_KSI()),
Type6LVE('EAPMsg', val={'V':b'\0\0\0\0'}),
Type6LVE('EAPMsg', val={'V':b'\0\0\0\0\0'}),
Type4TLV('ABBA', val={'T':0x38, 'V':b'\0\0'})
)
@ -215,7 +215,7 @@ class FGMMAuthenticationReject(Layer3):
_name = '5GMMAuthenticationReject'
_GEN = (
FGMMHeader(val={'Type':88}),
Type6LVE('EAPMsg', val={'V':b'\0\0\0\0'})
Type6LVE('EAPMsg', val={'V':b'\0\0\0\0\0'})
)
@ -235,7 +235,7 @@ class FGMMRegistrationRequest(Layer3):
Type4TLV('5GMMCap', val={'T':0x10, 'V':b'\0'}, IE=FGMMCap()),
Type4TLV('UESecCap', val={'T':0x2E, 'V':b'\0\0'}, IE=UESecCap()),
Type4TLV('NSSAI', val={'T':0x2F, 'V':b'\0\0'}, IE=NSSAI()),
Type3TV('TAI', val={'T':0x52, 'V':6*b'\0'}, IE=FGSTAI()),
Type3TV('TAI', val={'T':0x52, 'V':6*b'\0'}, bl={'V':48}, IE=FGSTAI()),
Type4TLV('EPSUENetCap', val={'T':0x17, 'V':b'\0\0'}, IE=EPSUENetCap()),
Type4TLV('ULDataStat', val={'T':0x40, 'V':b'\0\0'}, IE=ULDataStat()),
Type1TV('MICOInd', val={'T':0xB, 'V':0}, IE=MICOInd()),
@ -290,7 +290,7 @@ class FGMMRegistrationAccept(Layer3):
Type4TLV('EmergNumList', val={'T':0x34, 'V':b'\x02\x01\0'}, IE=EmergNumList()),
Type6TLVE('ExtEmergNumList', val={'T':0x7A, 'V':b'\0\0\0\0'}, IE=ExtEmergNumList()),
Type6TLVE('SORTransparentContainer', val={'T':0x73, 'V':17*b'\0'}, IE=SORTransparentContainer()),
Type6TLVE('EAPMsg', val={'T':0x78, 'V':b'\0\0\0\0'}),
Type6TLVE('EAPMsg', val={'T':0x78, 'V':b'\0\0\0\0\0'}),
Type1TV('NSSAIInclMode', val={'T':0xA, 'V':0}, IE=NSSAIInclMode()),
Type6TLVE('OperatorAccessCatDefs', val={'T':0x76, 'V':b''}, IE=OperatorAccessCatDefs()),
Type4TLV('5GSDRXParam', val={'T':0x51, 'V':b'\0'}, IE=FGSDRXParam()),
@ -330,7 +330,7 @@ class FGMMRegistrationReject(Layer3):
Type3V('5GMMCause', val={'V':b'\x16'}, bl={'V':8}, IE=FGMMCause()),
Type4TLV('T3346', val={'T':0x5F, 'V':b'\0'}, IE=GPRSTimer()),
Type4TLV('T3502', val={'T':0x16, 'V':b'\0'}, IE=GPRSTimer()),
Type6TLVE('EAPMsg', val={'T':0x78, 'V':b'\0\0\0\0'}),
Type6TLVE('EAPMsg', val={'T':0x78, 'V':b'\0\0\0\0\0'}),
Type4TLV('RejectedNSSAI', val={'T':0x69, 'V':b'\0\0'}, IE=RejectedNSSAI())
)
@ -462,7 +462,7 @@ class FGMMServiceAccept(Layer3):
Type4TLV('PDUSessStat', val={'T':0x50, 'V':b'\0\0'}, IE=PDUSessStat()),
Type4TLV('PDUSessStatReactResult', val={'T':0x26, 'V':b'\0\0'}, IE=PDUSessStat()),
Type6TLVE('PDUSessReactResultErr', val={'T':0x72, 'V':b'\0\0'}, IE=PDUSessReactResultErr()),
Type6TLVE('EAPMsg', val={'T':0x78, 'V':b'\0\0\0\0'}),
Type6TLVE('EAPMsg', val={'T':0x78, 'V':b'\0\0\0\0\0'}),
Type4TLV('T3448', val={'T':0x6B, 'V':b'\0'}, IE=GPRSTimer())
)
@ -479,7 +479,7 @@ class FGMMServiceReject(Layer3):
Type3V('5GMMCause', val={'V':b'\x16'}, bl={'V':8}, IE=FGMMCause()),
Type4TLV('PDUSessStat', val={'T':0x50, 'V':b'\0\0'}, IE=PDUSessStat()),
Type4TLV('T3346', val={'T':0x5F, 'V':b'\0'}, IE=GPRSTimer()),
Type6TLVE('EAPMsg', val={'T':0x78, 'V':b'\0\0\0\0'}),
Type6TLVE('EAPMsg', val={'T':0x78, 'V':b'\0\0\0\0\0'}),
Type4TLV('T3448', val={'T':0x6B, 'V':b'\0'}, IE=GPRSTimer())
)
@ -599,7 +599,7 @@ class FGMMSecurityModeCommand(Layer3):
Type1TV('IMEISVReq', val={'T':0xC, 'V':0}, IE=IMEISVReq()),
Type3TV('EPSNASSecAlgo', val={'T':0x57, 'V':b'\x11'}, bl={'V':8}, IE=EPSNASSecAlgo()),
Type4TLV('Add5GSecInfo', val={'T':0x36, 'V':b'\0'}, IE=Add5GSecInfo()),
Type6TLVE('EAPMsg', val={'T':0x78, 'V':b'\0\0\0\0'}),
Type6TLVE('EAPMsg', val={'T':0x78, 'V':b'\0\0\0\0\0'}),
Type4TLV('ABBA', val={'T':0x38, 'V':b'\0\0'}),
Type4TLV('EPSUESecCap', val={'T':0x19, 'V':b'\0\0'}, IE=EPSUESecCap())
)

View File

@ -44,7 +44,7 @@ from .TS24008_IE import (
ProtConfig, GPRSTimer,
)
from .TS24301_IE import (
HdrCompConfig,
HdrCompConfig, ServingPLMNRateCtrl,
)
from .TS24501_IE import *
@ -96,8 +96,8 @@ class FGSMHeader(Envelope):
class FGSMPDUSessionEstabRequest(Layer3):
_name = '5GSMPDUSessionEstabRequest'
_GEN = (
FGSMHeader(val={'Type':193})
Type3V('IntegrityProtMaxDataRate', val={'V':b'\0\0'}, IE=IntegrityProtMaxDataRate()),
FGSMHeader(val={'Type':193}),
Type3V('IntegrityProtMaxDataRate', val={'V':b'\0\0'}, bl={'V':16}, IE=IntegrityProtMaxDataRate()),
Type1TV('PDUSessType', val={'T':0x9, 'V':1}, IE=PDUSessType()),
Type1TV('SSCMode', val={'T':0xA, 'V':1}, IE=SSCMode()),
Type4TLV('5GSMCap', val={'T':0x28, 'V':b'\0'}, IE=FGSMCap()),
@ -119,18 +119,27 @@ class FGSMPDUSessionEstabRequest(Layer3):
class FGSMPDUSessionEstabAccept(Layer3):
_name = '5GSMPDUSessionEstabAccept'
_GEN = (
FGSMHeader(val={'Type':194})
FGSMHeader(val={'Type':194}),
Type1V('SSCMode', val={'V':1}, IE=SSCMode()),
Type1V('PDUSessType', val={'V':1}, IE=PDUSessType()),
Type6LVE('QoSRules', val={'V':b'\0\0\0\0'}, IE=QoSRules()),
Type4LV('SessAMBR', val={'V':b'\x06\0\x01\x06\0\x01'}, IE=SessAMBR()),
Type3TV('FGSMCause', val={'T':0x59, 'V':b'\x1a'}, IE=FGSMCause()),
Type3TV('5GSMCause', val={'T':0x59, 'V':b'\x1a'}, bl={'V':8}, IE=FGSMCause()),
Type4TLV('PDUAddress', val={'T':0x29, 'V':b'\x01\x7f\0\0\x01'}, IE=PDUAddress()),
Type3TV('RQTimer', val={'T':0x56, 'V':b'\0'}, IE=GPRSTimer()),
Type3TV('RQTimer', val={'T':0x56, 'V':b'\0'}, bl={'V':8}, IE=GPRSTimer()),
Type4TLV('SNSSAI', val={'T':0x22, 'V':b'\0'}, IE=SNSSAI()),
Type1TV('AlwaysOnPDUSessInd', val={'T':0x8, 'V':0}, IE=AlwaysOnPDUSessInd()),
# TODO
Type6TLVE('MappedEPSBearerCtxt', val={'T':0x75, 'V':b'\0\0\0\0'}, IE=MappedEPSBearerCtxt()),
Type6TLVE('EAPMsg', val={'T':0x78, 'V':b'\0\0\0\0\0'}),
Type6TLVE('QoSFlowDesc', val={'T':0x79, 'V':b'\0\0\0'}, IE=QoSFlowDesc()),
Type6TLVE('ExtProtConfig', val={'T':0x7B, 'V':b'\0'}, IE=ProtConfig()),
Type4TLV('DNN', val={'T':0x25, 'V':b'\0'}, IE=APN('DNN')),
#Type4TLV('5GSMNetFeat', val={'T':0x00, 'V':b'\0'}, IE=FGSMNetFeat()), # WNG: tag is undefined in current TS
#Type4TLV('SessTMBR', val={'T':0x00, 'V':6*b'\0'}, IE=SessTMBR()), # WNG: tag is undefined in current TS
#Type4TLV('ServingPLMNRateCtrl', val={'T':0x00, 'V':b'\0\0'}, IE=ServingPLMNRateCtrl()), # WNG: tag is undefined in current TS
#Type6TLVE('ATSSSContainer', val={'T':0x00, 'B':b''}), # WNG: tag is undefined in current TS
#Type1TV('CtrlPlaneOnlyInd', val={'T':0x0, 'V':1}, IE=CtrlPlaneOnlyInd()), # WNG: tag is undefined in current TS
Type4TLV('HdrCompConfig', val={'T':0x66, 'V':b'\0\0\0'}, IE=HdrCompConfig())
)
@ -142,8 +151,14 @@ class FGSMPDUSessionEstabAccept(Layer3):
class FGSMPDUSessionEstabReject(Layer3):
_name = '5GSMPDUSessionEstabReject'
_GEN = (
FGSMHeader(val={'Type':195})
FGSMHeader(val={'Type':195}),
Type3V('5GSMCause', val={'V':b'\x1a'}, bl={'V':8}, IE=FGSMCause()),
Type4TLV('BackOffTimer', val={'T':0x37, 'V':b'\0'}, IE=GRPSTimer3()),
Type1TV('AllowedSSCMode', val={'T':0xF, 'V':0}, IE=AllowedSSCMode()),
Type6TLVE('EAPMsg', val={'T':0x78, 'V':b'\0\0\0\0\0'}),
Type6TLVE('ExtProtConfig', val={'T':0x7B, 'V':b'\0'}, IE=ProtConfig()),
#Type4TLV('ReattemptInd', val={'V':0x00, 'V':b'\0'}, IE=ReattemptInd()), # WNG: tag is undefined in current TS
Type4TLV('CongestReattemptInd', val={'T':0x61, 'V':b'\0'}, IE=CongestReattemptInd())
)
@ -155,8 +170,9 @@ class FGSMPDUSessionEstabReject(Layer3):
class FGSMPDUSessionAuthentCommand(Layer3):
_name = '5GSMPDUSessionAuthentCommand'
_GEN = (
FGSMHeader(val={'Type':197})
FGSMHeader(val={'Type':197}),
Type6LVE('EAPMsg', val={'V':b'\0\0\0\0\0'}),
Type6TLVE('ExtProtConfig', val={'T':0x7B, 'V':b'\0'}, IE=ProtConfig())
)
@ -168,8 +184,9 @@ class FGSMPDUSessionAuthentCommand(Layer3):
class FGSMPDUSessionAuthentComplete(Layer3):
_name = '5GSMPDUSessionAuthentComplete'
_GEN = (
FGSMHeader(val={'Type':198})
FGSMHeader(val={'Type':198}),
Type6LVE('EAPMsg', val={'V':b'\0\0\0\0\0'}),
Type6TLVE('ExtProtConfig', val={'T':0x7B, 'V':b'\0'}, IE=ProtConfig())
)
@ -181,8 +198,9 @@ class FGSMPDUSessionAuthentComplete(Layer3):
class FGSMPDUSessionAuthentResult(Layer3):
_name = '5GSMPDUSessionAuthentResult'
_GEN = (
FGSMHeader(val={'Type':199})
FGSMHeader(val={'Type':199}),
Type6TLVE('EAPMsg', val={'T':0x78, 'V':b'\0\0\0\0\0'}),
Type6TLVE('ExtProtConfig', val={'T':0x7B, 'V':b'\0'}, IE=ProtConfig()),
)
@ -194,8 +212,17 @@ class FGSMPDUSessionAuthentResult(Layer3):
class FGSMPDUSessionModifRequest(Layer3):
_name = '5GSMPDUSessionModifRequest'
_GEN = (
FGSMHeader(val={'Type':201})
FGSMHeader(val={'Type':201}),
Type4TLV('5GSMCap', val={'T':0x28, 'V':b'\0'}, IE=FGSMCap()),
Type3TV('5GSMCause', val={'T':0x59, 'V':b'\x1a'}, bl={'V':8}, IE=FGSMCause()),
Type3TV('MaxPktFilters', val={'T':0x55, 'V':b'\x02\x20'}, bl={'V':16}, IE=MaxPktFilters()),
Type1TV('AlwaysOnPDUSessReq', val={'T':0xB, 'V':0}, IE=AlwaysOnPDUSessReq()),
Type3TV('IntegrityProtMaxDataRate', val={'V':b'\0\0'}, bl={'V':16}, IE=IntegrityProtMaxDataRate()),
Type6TLVE('QoSRules', val={'T':0x7A, 'V':b'\0\0\0\0'}, IE=QoSRules()),
Type6TLVE('QoSFlowDesc', val={'T':0x79, 'V':b'\0\0\0'}, IE=QoSFlowDesc()),
Type6TLVE('MappedEPSBearerCtxt', val={'T':0x75, 'V':b'\0\0\0\0'}, IE=MappedEPSBearerCtxt()),
Type6TLVE('ExtProtConfig', val={'T':0x7B, 'V':b'\0'}, IE=ProtConfig()),
#Type6TLVE('PortMgmtInfoContainer', val={'T':0x00, 'V':b'\0'}), # WNG: tag is undefined in current TS
)
@ -207,8 +234,12 @@ class FGSMPDUSessionModifRequest(Layer3):
class FGSMPDUSessionModifReject(Layer3):
_name = '5GSMPDUSessionModifReject'
_GEN = (
FGSMHeader(val={'Type':202})
FGSMHeader(val={'Type':202}),
Type3V('5GSMCause', val={'V':b'\x1a'}, bl={'V':8}, IE=FGSMCause()),
Type4TLV('BackOffTimer', val={'T':0x37, 'V':b'\0'}, IE=GRPSTimer3()),
Type6TLVE('ExtProtConfig', val={'T':0x7B, 'V':b'\0'}, IE=ProtConfig()),
#Type4TLV('ReattemptInd', val={'V':0x00, 'V':b'\0'}, IE=ReattemptInd()), # WNG: tag is undefined in current TS
Type4TLV('CongestReattemptInd', val={'T':0x61, 'V':b'\0'}, IE=CongestReattemptInd())
)
@ -220,8 +251,19 @@ class FGSMPDUSessionModifReject(Layer3):
class FGSMPDUSessionModifCommand(Layer3):
_name = '5GSMPDUSessionModifCommand'
_GEN = (
FGSMHeader(val={'Type':203})
FGSMHeader(val={'Type':203}),
Type3TV('5GSMCause', val={'T':0x59, 'V':b'\x1a'}, bl={'V':8}, IE=FGSMCause()),
Type4TLV('SessAMBR', val={'T':0x2A, 'V':b'\x06\0\x01\x06\0\x01'}, IE=SessAMBR()),
Type3TV('RQTimer', val={'T':0x56, 'V':b'\0'}, bl={'V':8}, IE=GPRSTimer()),
Type1TV('AlwaysOnPDUSessInd', val={'T':0x8, 'V':0}, IE=AlwaysOnPDUSessInd()),
Type6TLVE('QoSRules', val={'T':0x7A, 'V':b'\0\0\0\0'}, IE=QoSRules()),
Type6TLVE('MappedEPSBearerCtxt', val={'T':0x75, 'V':b'\0\0\0\0'}, IE=MappedEPSBearerCtxt()),
Type6TLVE('QoSFlowDesc', val={'T':0x79, 'V':b'\0\0\0'}, IE=QoSFlowDesc()),
Type6TLVE('ExtProtConfig', val={'T':0x7B, 'V':b'\0'}, IE=ProtConfig()),
#Type4TLV('SessTMBR', val={'T':0x00, 'V':6*b'\0'}, IE=SessTMBR()), # WNG: tag is undefined in current TS
#Type6TLVE('ATSSSContainer', val={'T':0x00, 'B':b''}), # WNG: tag is undefined in current TS
Type4TLV('HdrCompConfig', val={'T':0x66, 'V':b'\0\0\0'}, IE=HdrCompConfig()),
#Type6TLVE('PortMgmtInfoContainer', val={'T':0x00, 'V':b'\0'}), # WNG: tag is undefined in current TS
)
@ -233,8 +275,9 @@ class FGSMPDUSessionModifCommand(Layer3):
class FGSMPDUSessionModifComplete(Layer3):
_name = '5GSMPDUSessionModifComplete'
_GEN = (
FGSMHeader(val={'Type':204})
FGSMHeader(val={'Type':204}),
Type6TLVE('ExtProtConfig', val={'T':0x7B, 'V':b'\0'}, IE=ProtConfig()),
#Type6TLVE('PortMgmtInfoContainer', val={'T':0x00, 'V':b'\0'}), # WNG: tag is undefined in current TS
)
@ -246,8 +289,9 @@ class FGSMPDUSessionModifComplete(Layer3):
class FGSMPDUSessionModifCommandReject(Layer3):
_name = '5GSMPDUSessionModifCommandReject'
_GEN = (
FGSMHeader(val={'Type':205})
FGSMHeader(val={'Type':205}),
Type3V('5GSMCause', val={'V':b'\x1a'}, bl={'V':8}, IE=FGSMCause()),
Type6TLVE('ExtProtConfig', val={'T':0x7B, 'V':b'\0'}, IE=ProtConfig())
)
@ -259,8 +303,9 @@ class FGSMPDUSessionModifCommandReject(Layer3):
class FGSMPDUSessionReleaseRequest(Layer3):
_name = '5GSMPDUSessionReleaseRequest'
_GEN = (
FGSMHeader(val={'Type':209})
FGSMHeader(val={'Type':209}),
Type3TV('5GSMCause', val={'T':0x59, 'V':b'\x1a'}, bl={'V':8}, IE=FGSMCause()),
Type6TLVE('ExtProtConfig', val={'T':0x7B, 'V':b'\0'}, IE=ProtConfig())
)
@ -272,8 +317,9 @@ class FGSMPDUSessionReleaseRequest(Layer3):
class FGSMPDUSessionReleaseReject(Layer3):
_name = '5GSMPDUSessionReleaseReject'
_GEN = (
FGSMHeader(val={'Type':210})
FGSMHeader(val={'Type':210}),
Type3V('5GSMCause', val={'V':b'\x1a'}, bl={'V':8}, IE=FGSMCause()),
Type6TLVE('ExtProtConfig', val={'T':0x7B, 'V':b'\0'}, IE=ProtConfig())
)
@ -285,8 +331,12 @@ class FGSMPDUSessionReleaseReject(Layer3):
class FGSMPDUSessionReleaseCommand(Layer3):
_name = '5GSMPDUSessionReleaseCommand'
_GEN = (
FGSMHeader(val={'Type':211})
FGSMHeader(val={'Type':211}),
Type3V('5GSMCause', val={'V':b'\x1a'}, bl={'V':8}, IE=FGSMCause()),
Type4TLV('BackOffTimer', val={'T':0x37, 'V':b'\0'}, IE=GRPSTimer3()),
Type6TLVE('EAPMsg', val={'T':0x78, 'V':b'\0\0\0\0\0'}),
Type4TLV('CongestReattemptInd', val={'T':0x61, 'V':b'\0'}, IE=CongestReattemptInd()),
Type6TLVE('ExtProtConfig', val={'T':0x7B, 'V':b'\0'}, IE=ProtConfig())
)
@ -298,8 +348,9 @@ class FGSMPDUSessionReleaseCommand(Layer3):
class FGSMPDUSessionReleaseComplete(Layer3):
_name = '5GSMPDUSessionReleaseComplete'
_GEN = (
FGSMHeader(val={'Type':212})
FGSMHeader(val={'Type':212}),
Type3TV('5GSMCause', val={'T':0x59, 'V':b'\x1a'}, bl={'V':8}, IE=FGSMCause()),
Type6TLVE('ExtProtConfig', val={'T':0x7B, 'V':b'\0'}, IE=ProtConfig())
)
@ -311,8 +362,8 @@ class FGSMPDUSessionReleaseComplete(Layer3):
class FGSMStatus(Layer3):
_name = '5GSMStatus'
_GEN = (
FGSMHeader(val={'Type':214})
FGSMHeader(val={'Type':214}),
Type3V('5GSMCause', val={'V':b'\x1a'}, bl={'V':8}, IE=FGSMCause())
)

View File

@ -44,10 +44,11 @@ from pycrate_core.charpy import Charpy
from pycrate_ether.Ethernet import EtherType_dict
from pycrate_ether.IP import IPProt_dict
from pycrate_mobile.TS24008_IE import (
BufBCD, PLMN, GPRSTimer3, APN,
BufBCD, PLMN, GPRSTimer3, APN, TFT,
)
from pycrate_mobile.TS24301_IE import (
EPSQoS, ExtEPSQoS, APN_AMBR, ExtAPN_AMBR,
)
#from pycrate_mobile.TS24301_IE import (
# )
_str_reserved = 'reserved'
_str_mnospec = 'operator-specific'
@ -1805,6 +1806,20 @@ class AlwaysOnPDUSessReq(Envelope):
)
#------------------------------------------------------------------------------#
# Allowed SSC mode
# TS 24.501, 9.11.4.5
#------------------------------------------------------------------------------#
class AllowedSSCMode(Envelope):
_GEN = (
Uint('spare', bl=1),
Uint('SSC3', bl=1),
Uint('SSC2', bl=1),
Uint('SSC1', bl=1)
)
#------------------------------------------------------------------------------#
# Integrity protection maximum data rate
# TS 24.501, 9.11.4.7
@ -1822,6 +1837,92 @@ class IntegrityProtMaxDataRate(Envelope):
)
#------------------------------------------------------------------------------#
# Mapped EPS bearer contexts
# TS 24.501, 9.11.4.8
#------------------------------------------------------------------------------#
_EPSBearerCtxtOC_dict = {
0 : _str_reserved,
1 : 'Create new EPS bearer',
2 : 'Delete new EPS bearer',
3 : 'Modify new EPS bearer'
}
_EPSBearerCtxtEDict_sel = {
1 : {
0 : 'parameters not included',
1 : 'parameters included'
},
2 : {
0 : 'previously provided parameters extension',
1 : 'previously provided parameters replacement'
},
3 : { # TS unclear there !
}
}
_EPSParamType_dict = {
1 : 'Mapped EPS QoS parameters',
2 : 'Mapped extended EPS QoS parameters',
3 : 'Traffic flow template',
4 : 'APN-AMBR',
5 : 'extended APN-AMBR',
}
class EPSParam(Envelope):
_GEN = (
Uint8('Type', dic=_EPSParamType_dict),
Uint8('Len'),
Alt('Content', GEN={
1 : EPSQoS(),
2 : ExtEPSQoS(),
3 : TFT(),
4 : APN_AMBR(),
5 : ExtAPN_AMBR()
},
DEFAULT=Buf('unk', val=b'', rep=REPR_HEX),
sel=lambda self: self.get_env()['Type'].get_val())
)
def __init__(self, *args, **kwargs):
Envelope.__init__(self, *args, **kwargs)
self['Len'].set_valauto(lambda: self['Content'].get_len())
def _from_char(self, char):
self[0]._from_char(char)
self[1]._from_char(char)
char_lb = char._len_bit
char._len_bit = char._cur + (self[1].get_val()<<3)
self[2]._from_char(char)
char._len_bit = char_lb
class EPSBearerCtxt(Envelope):
_GEN = (
Uint('spare', bl=4),
Uint('EBI', bl=4),
Uint16('Len'),
Uint('OpCode', bl=2, dic=_EPSBearerCtxtOC_dict),
Uint('spare', bl=2),
Uint('E', bl=1),
Uint('Num', bl=3),
Sequence('EPSParams', GEN=EPSParam())
)
def __init__(self, *args, **kwargs):
Envelope.__init__(self, *args, **kwargs)
self['Len'].set_valauto(lambda: 1 + self['EPSParams'].get_len()) # TS does not define which length it is...
self['E'].set_dicauto(lambda: _EPSBearerCtxtEDict_sel[self['OpCode'].get_val()])
self['Num'].set_valauto(lambda: self['EPSParams'].get_num())
self['EPSParams'].set_numauto(lambda: self['Num'].get_val())
class MappedEPSBearerCtxt(Sequence):
_GEN = EPSBearerCtxt()
#------------------------------------------------------------------------------#
# Maximum number of supported packet filters
# TS 24.501, 9.11.4.9
@ -1877,10 +1978,131 @@ class PDUSessType(Envelope):
)
#------------------------------------------------------------------------------#
# QoS flow descriptions
# TS 24.501, 9.11.4.12
#------------------------------------------------------------------------------#
_UnitBitrate_dict = {
1 : '1 Kbps',
2 : '4 Kbps',
3 : '16 Kbps',
4 : '64 Kbps',
5 : '256 kbps',
6 : '1 Mbps',
7 : '4 Mbps',
8 : '16 Mbps',
9 : '64 Mbps',
10 : '256 Mbps',
11 : '1 Gbps',
12 : '4 Gbps',
13 : '16 Gbps',
14 : '64 Gbps',
15 : '256 Gbps',
16 : '1 Tbps',
17 : '4 Tbps',
18 : '16 Tbps',
19 : '64 Tbps',
20 : '256 Tbps',
21 : '1 Pbps',
22 : '4 Pbps',
23 : '16 Pbps',
24 : '64 Pbps',
25 : '256 Pbps'
}
_QoSFlowOC_dict = {
1 : 'Create new QoS flow description',
2 : 'Delete existing QoS flow description',
3 : 'Modify existing QoS flow description'
}
_QoSFlowE_dict = {
1 : {
0 : _str_reserved,
1 : 'parameters list is included'
},
2 : {
0 : 'parameters list is not included',
1 : _str_reserved
},
3 : {
0 : 'extension of previously provided parameters',
1 : 'replacement of all previously provided parameters'
}
}
_QoSFlowParamType_dict = {
1 : '5QI',
2 : 'GFBR uplink',
3 : 'GFBR downlink',
4 : 'MFBR uplink',
5 : 'MFBR downlink',
6 : 'Averaging window',
7 : 'EPS bearer identity'
}
class _QoSFlowParamFBR(Envelope):
_GEN = (
Uint8('Unit', dic=_UnitBitrate_dict),
Uint16('Value')
)
class _QoSFlowParamEBI(Envelope):
_GEN = (
Uint('spare', bl=4),
Uint('EBI', bl=4),
)
class QoSFlowParam(Envelope):
_GEN = (
Uint8('Type', dic=_QoSFlowParamType_dict),
Uint8('Len'),
Alt('Content', GEN={
1 : Uint8('5GQI'),
2 : _QoSFlowParamFBR('GFBR'),
3 : _QoSFlowParamFBR('GFBR'),
4 : _QoSFlowParamFBR('MFBR'),
5 : _QoSFlowParamFBR('MFBR'),
6 : Uint16('Win', desc='millisecond'),
7 : _QoSFlowParamEBI('EBI')
},
DEFAULT=Buf('unk', val=b'', rep=REPR_HEX),
sel=lambda self: self.get_env()['Type'].get_val())
)
class QoSFlow(Envelope):
_GEN = (
Uint('spare', bl=2),
Uint('QFI', bl=6),
Uint('OpCode', bl=3, dic=_QoSFlowOC_dict),
Uint('spare', bl=6), # last 5 bit of 2nd octet and 1st bit of 3rd octet
Uint('E', bl=1),
Uint('Num', bl=6),
Sequence('Params', GEN=QoSFlowParam('Param'))
)
def __init__(self, *args, **kwargs):
Envelope.__init__(self, *args, **kwargs)
self['E'].set_dicauto(lambda: _QoSFlowE_dict[self['OpCode'].get_val()])
self['Num'].set_valauto(lambda: self['Params'].get_num())
self['Params'].set_numauto(lambda: self['Num'].get_val())
class QoSFlowDesc(Sequence):
_GEN = QoSFlow()
#------------------------------------------------------------------------------#
# QoS rules
# TS 24.501, 9.11.4.13
#------------------------------------------------------------------------------#
# similar to Traffic Flow Template for PS and EPS domains
# TS 24.008, 10.5.6.12
_QoSRuleOpCode_dict = {
0 : _str_reserved,
@ -1985,17 +2207,16 @@ class PktFilterComp(Envelope):
_GEN = (
Uint8('Type', dic=_PktFilterCompType_dict),
Alt('Value', GEN={
# TODO
1 : Buf('none', bl=0),
16 : _PktFilterCompIPv4('IPv4RemoteAddr'),
17 : _PktFilterCompIPv4('IPv4LocalAddr'),
33 : _PktFilterCompIPv6('IPv6RemoteAddr'),
35 : _PktFilterCompIPv6('IPv6LocalAddr'),
48 : Uint8('ProtID', dic=IPProt_dict),
64 : Uint16('PortLocal'),
65 : _PktFilterCompPortRange('PortRangeLocal'),
80 : Uint16('PortRemote'),
81 : _PktFilterCompPortRange('PortRangeRemote'),
16 : _PktFilterCompIPv4('IPv4'),
17 : _PktFilterCompIPv4('IPv4'),
33 : _PktFilterCompIPv6('IPv6Pref'),
35 : _PktFilterCompIPv6('IPv6Pref'),
48 : Uint8('ProtId', dic=IPProt_dict),
64 : Uint16('Port'),
65 : _PktFilterCompPortRange('PortRange'),
80 : Uint16('Port'),
81 : _PktFilterCompPortRange('PortRange'),
96 : Uint32('SPI', rep=REPR_HEX),
112 : _PktFilterTrafficClass('TrafficClass'),
128 : _PktFilterFlowLabel('FlowLabel'),
@ -2007,7 +2228,7 @@ class PktFilterComp(Envelope):
134 : _PktFilterPCPDEI('STagPCPDEI'),
135 : Uint16('EtherType', dic=EtherType_dict)
},
DEFAULT=Buf('unk', rep=REPR_HEX),
DEFAULT=Buf('unk', val=b'', rep=REPR_HEX),
sel=lambda self: self.get_env()['Type'].get_val())
)
@ -2015,8 +2236,8 @@ class PktFilterComp(Envelope):
class PktFilterAdd(Envelope):
_GEN = (
Uint('spare', bl=2),
Uint('Direction', bl=2, dict=_PktFilterDir_dict),
Uint('ID', bl=4),
Uint('Dir', bl=2, dict=_PktFilterDir_dict),
Uint('Id', bl=4),
Uint8('Len'),
Sequence('PktFilter', GEN=PktFilterComp())
)
@ -2080,34 +2301,6 @@ class QoSRules(Sequence):
# TS 24.501, 9.11.4.14
#------------------------------------------------------------------------------#
_UnitBitrate_dict = {
1 : '1 Kbps',
2 : '4 Kbps',
3 : '16 Kbps',
4 : '64 Kbps',
5 : '256 kbps',
6 : '1 Mbps',
7 : '4 Mbps',
8 : '16 Mbps',
9 : '64 Mbps',
10 : '256 Mbps',
11 : '1 Gbps',
12 : '4 Gbps',
13 : '16 Gbps',
14 : '64 Gbps',
15 : '256 Gbps',
16 : '1 Tbps',
17 : '4 Tbps',
18 : '16 Tbps',
19 : '64 Tbps',
20 : '256 Tbps',
21 : '1 Pbps',
22 : '4 Pbps',
23 : '16 Pbps',
24 : '64 Pbps',
25 : '256 Pbps'
}
class SessAMBR(Envelope):
_GEN = (
Uint8('DLUnit', dic=_UnitBitrate_dict),
@ -2149,5 +2342,80 @@ class SSCMode(Envelope):
)
#------------------------------------------------------------------------------#
# Re-attempt indicator
# TS 24.501, 9.11.4.17
#------------------------------------------------------------------------------#
class ReattemptInd(Envelope):
_GEN = (
Uint('spare', bl=6, rep=REPR_HEX),
Uint('EPLMNC', bl=1),
Uint('RATC', bl=1)
)
#------------------------------------------------------------------------------#
# 5GSM network feature support
# TS 24.501, 9.11.4.18
#------------------------------------------------------------------------------#
class FGSNetFeat(Envelope):
_name = '5GSMNetFeat'
_GEN = (
Uint('spare', bl=7),
Uint('EPT-S1', bl=1),
Buf('spare', val=b'', rep=REPR_HEX)
)
def disable_from(self, ind):
"""disables all elements from index `ind' excluded (element offset or name)
"""
if isinstance(ind, str_types) and ind in self._by_name:
ind = self._by_name.index(ind)
[e.set_trans(True) for e in self._content[ind:]]
def enable_upto(self, ind):
"""enables all elements up to index `ind' included (element offset or name)
"""
if isinstance(ind, str_types) and ind in self._by_name:
ind = 1 + self._by_name.index(ind)
[e.set_trans(False) for e in self._content[:ind]]
#------------------------------------------------------------------------------#
# Session-TMBR
# TS 24.501, 9.11.4.19
#------------------------------------------------------------------------------#
class SessTMBR(SessAMBR):
pass
#------------------------------------------------------------------------------#
# Re-attempt indicator
# TS 24.501, 9.11.4.17
#------------------------------------------------------------------------------#
class CongestReattemptInd(Envelope):
_GEN = (
Uint('spare', bl=7, rep=REPR_HEX),
Uint('ABO', bl=1)
)
#------------------------------------------------------------------------------#
# Control plane only indication
# TS 24.501, 9.11.4.23
#------------------------------------------------------------------------------#
class CtrlPlaneOnlyInd(Envelope):
_GEN = (
Uint('spare', bl=3),
Uint('Value', val=1, bl=1,
dic={1:'PDU session can be used for control plane CIoT 5GS optimization only'})
)