3GPP
The threegpp.l3msg module
3GPP Layer 3 Message Processing Library
This module provides classes and utilities for processing 3GPP Layer 3 messages, particularly for 5G Session Management (5GSM) and 5G Mobility Management (5GMM) protocols. It builds upon the encoding module to provide high-level message parsing and generation.
- class threegpp.l3msg.FGMMMessageType
5G Mobility Management (5GMM) message type identifiers.
RegistrationRequest = 0x41
RegistrationAccept = 0x42
RegistrationComplete = 0x43
RegistrationReject = 0x44
DeregistrationRequestUEOriginating = 0x45
DeregistrationAcceptUEOriginating = 0x46
DeregistrationRequestNetworkOriginating = 0x47
DeregistrationAcceptNetworkOriginating = 0x48
ServiceRequest = 0x4C
ServiceReject = 0x4D
ServiceAccept = 0x4E
ControlPlaneServiceRequest = 0x4F
NetworkSliceSpecificAuthenticationCommand = 0x50
NetworkSliceSpecificAuthenticationComplete = 0x51
NetworkSliceSpecificAuthenticationResult = 0x52
ConfigurationUpdateCommand = 0x54
ConfigurationUpdateComplete = 0x55
AuthenticationRequest = 0x56
AuthenticationResponse = 0x57
AuthenticationReject = 0x58
AuthenticationFailure = 0x59
AuthenticationResult = 0x5A
IdentityRequest = 0x5B
IdentityResponse = 0x5C
SecurityModeCommand = 0x5D
SecurityModeComplete = 0x5E
SecurityModeReject = 0x5F
FiveGMMStatus = 0x64
Notification = 0x65
NotificationResponse = 0x66
UplinkNasTransport = 0x67
DownlinkNasTransport = 0x68
RelayKeyRequest = 0x69
RelayKeyAccept = 0x6A
RelayKeyReject = 0x6B
RelayAuthenticationRequest = 0x6C
RelayAuthenticationResponse = 0x6D
- class threegpp.l3msg.FGSMMessageType
5G Session Management (5GSM) message type identifiers.
PDUSessionEstablishmentRequest = 0xC1
PDUSessionEstablishmentAccept = 0xC2
PDUSessionEstablishmentReject = 0xC3
PDUSessionAuthenticationCommand = 0xC5
PDUSessionAuthenticationComplete = 0xC6
PDUSessionAuthenticationResult = 0xC7
PDUSessionModificationRequest = 0xC9
PDUSessionModificationReject = 0xCA
PDUSessionModificationCommand = 0xCB
PDUSessionModificationComplete = 0xCC
PDUSessionModificationCompleteReject = 0xCD
PDUSessionReleaseRequest = 0xD1
PDUSessionReleaseReject = 0xD2
PDUSessionReleaseCommand = 0xD3
PDUSessionReleaseComplete = 0xD4
FiveGSMStatus = 0xD6
ServiceLevelAuthenticationCommand = 0xD8
ServiceLevelAuthenticationComplete = 0xD9
RemoteUEReport = 0xDA
RemoteUEReportResponse = 0xDB
- class threegpp.l3msg.IE(desc, value)
Information Element within a message.
Represents a single Information Element (IE) in a 3GPP message. It contains a value property which can be either an integer for single-octet IEs or a bytes object for multi-octet IEs. Upon setting this property the value is validated against the format defined in the IE descriptor.
Objects of this class know how to encode themselves into binary format using their descriptor attribute desc.
- Parameters
desc (IEDesc) – IE descriptor defining the structure.
value (any) – Value of the IE.
- encode(buffer)
Encode the IE into a buffer.
- Parameters
buffer (bytearray) – Buffer to encode into.
- property value
Get the IE value.
- Returns
Current value of the IE.
- Return type
any
- class threegpp.l3msg.IEDesc(iei, name, fmt)
Information Element Descriptor.
Describes a single Information Element (IE) within a 3GPP message, including its identifier, name, and encoding format.
- Parameters
iei (int or None) – Information Element Identifier (IEI). None for mandatory IEs.
name (str) – Descriptive name of the IE.
fmt (encoding format object) – Encoding format specification for this IE.
- property mandatory
Check if this IE is mandatory.
- Returns
True if the IE is mandatory (iei is None).
- Return type
bool
- class threegpp.l3msg.Message(desc, ies)
Represents a 3GPP Layer 3 message.
A Message consists of an ordered list of IEs. This list is accessible via the ies parameter and can be modified by inserting, deleting, or reordering the elements.
However, this is not the preferred method of interacting with a Message. Instead, Nokia advises to use the provided methods and operators to get, set, or delete Information Elements. This ensures that the message remains valid according to its descriptor:
mandatory IEs cannot be deleted,
optional IEs are inserted at the correct position,
values are validated according to their format, but without further semantic checks.
By default these methods act on the assumption that only a single IE of each type will be present. This is the most common case. However, if multiple IEs of the same type are expected, the all parameter can be set to True to modify the behavior accordingly; that is, the values being passed and returned are lists instead of single values.
- Parameters
desc (MessageDescriptor) – Message descriptor defining the structure.
ies (list of IE) – List of Information Elements in this message.
- static decode(data)
Decode a Layer 3 message from binary data.
Automatically determines the protocol type from the protocol discriminator and uses the appropriate decoder.
- Parameters
data (bytes or bytearray) – Binary message data to decode.
- Returns
Decoded Message object.
- Return type
- Raises
ValueError – If data is too short.
RuntimeError – If protocol is not supported.
- delIE(key, all=False)
Delete Information Element(s) by key.
- Parameters
key (int or str) – IEI (as int) or name (as str) of the IE.
all (bool) – If True, delete all occurrences; if False, delete first only.
- Raises
RuntimeError – If attempting to delete mandatory IEs.
- encode()
Encode the message to binary format.
- Returns
Binary representation of the message.
- Return type
bytes
- getIE(key, all=False)
Get the value(s) of an Information Element by key.
- Parameters
key (int or str) – IEI (as int) or name (as str) of the IE.
all (bool) – If True, return all occurrences; if False, return first only.
- Returns
IE value(s) - single value if all=False, list if all=True.
- Return type
any or list
- property protocol
Get the protocol discriminator value.
- Returns
Extended or regular protocol discriminator value.
- Return type
int or None
- setIE(key, value, all=False)
Set the value(s) of an Information Element by key.
- Parameters
key (int or str) – IEI (as int) or name (as str) of the IE.
value (any or list or tuple) – Value to set. Must be list/tuple if all=True.
all (bool) – If True, set multiple occurrences; if False, set first only.
- Raises
TypeError –
ValueError – If value format is incorrect or IE is unknown.
- class threegpp.l3msg.MessageDescriptor(ies)
Message Descriptor for 3GPP Layer 3 messages.
Defines the structure of a message including its mandatory and optional Information Elements, and provides methods for decoding messages.
- Parameters
ies (list of IEDesc) – List of Information Element descriptors for this message.
- class threegpp.l3msg.ProtocolDiscriminator
Protocol Discriminator values for 3GPP Layer 3 messages.
GroupCallControl = 0x00
BroadcastCallControl = 0x01
EPSSessionManagement = 0x02
CallControl = 0x03
GTTP = 0x04
MobilityManagement = 0x05
RadioResourceManagement = 0x06
EPSMobilityManagement = 0x07
GPRSMobilityManagement = 0x08
SMSMessages = 0x09
GRPSSessionManagement = 0x0A
NonCallRelatedSS = 0x0B
LocationServices = 0x0C
FiveGSessionManagement = 0x2E
FiveGMobilityManagement = 0x7E
- SPEC_VERSION = 'V17.9.0'
3GPP specification version used for message definitions. This constant indicates the version of 3GPP TS 24.501 specification that was used to define the message structures and IEs in this module.
- threegpp.l3msg.fgmm_ie_descriptors
5G Mobility Management (5GMM) Information Element descriptors.
- threegpp.l3msg.fgmm_security_protected_encrypted_msg
5GMM security protected and encrypted message descriptor. MessageDescriptor for 5GMM messages with both integrity protection and encryption. Used when the security header type indicates both integrity and ciphering (security header types 2 and 4). The payload contains encrypted NAS message data.
- threegpp.l3msg.fgmm_security_protected_msg
5GMM security protected message descriptor. MessageDescriptor for 5GMM messages with integrity protection (no encryption). Used when the security header type indicates integrity protection only (security header types 1 and 3).
- threegpp.l3msg.fgsm_ie_descriptors
5G Session Management (5GSM) Information Element descriptors.
The threegpp.encoding module
3GPP Message Encoding Library
This module provides encoding and decoding functionality for 3GPP Layer 3 message Information Elements (IEs) according to the format specifications in TS 24.007.
The module implements all standard IE encoding formats:
Type 1: V format and TV format
Type 2: T format
Type 3: V format and TV format
Type 4: LV format and TLV format
Type 6: LVE format and TLVE format
Each format class adheres to the interface defined by the abstract base class Formatter.
- class threegpp.encoding.Formatter
Abstract base class for 3GPP message format encoders/decoders.
Note
This class is abstract and documents the interface implemented by objects returned by factory functions such as
LV(). It should not be used directly.Defines the interface that all format classes must implement for encoding and decoding Information Elements in 3GPP messages.
- check_value(value)
Validate the value to be encoded.
- Parameters
value (any) – Value to validate.
- Raises
ValueError – If value is invalid for this format.
- decode(data)
Decode an Information Element from binary data.
- Parameters
data (bytes or bytearray) – Binary data to decode.
- Returns
Tuple of (iei, value, remaining_data).
- Raises
ValueError – If data cannot be decoded.
- encode(iei, value, buffer)
Encode an Information Element into a buffer.
- Parameters
iei (int or None) – Information Element Identifier.
value (any) – Value to encode.
buffer (bytearray) – Buffer to append encoded data to.
- Raises
ValueError – If IEI or value is invalid.
- threegpp.encoding.LV(min_len=None, max_len=None)
Create a formatter for Type 4 Format LV.
- Parameters
min_len (int or None) – Minimum total length in bytes (including length field).
max_len (int or None) – Maximum total length in bytes (including length field).
- Return type
Formatter instance
- threegpp.encoding.LVE(min_len=None, max_len=None)
Create a formatter for Type 6 Format LVE.
- Parameters
min_len (int or None) – Minimum total length in bytes (including length field).
max_len (int or None) – Maximum total length in bytes (including length field).
- Return type
Formatter instance
- threegpp.encoding.T
Formatter for Type 2 Format T IE.
- threegpp.encoding.TLV(min_len=None, max_len=None)
Create a formatter for Type 4 Format TLV.
- Parameters
min_len (int or None) – Minimum total length in bytes (including IEI and length field).
max_len (int or None) – Maximum total length in bytes (including IEI and length field).
- Return type
Formatter instance
- threegpp.encoding.TLVE(min_len=None, max_len=None)
Create a formatter for Type 6 Format TLVE.
- Parameters
min_len (int or None) – Minimum total length in bytes (including IEI and length field).
max_len (int or None) – Maximum total length in bytes (including IEI and length field).
- Return type
Formatter instance
- threegpp.encoding.TV(length)
Create a Formatter for Type 3 Format TV.
- Parameters
length (int) – Total length including IEI (minimum 1 byte).
- Return type
Formatter instance
- threegpp.encoding.TV1
Formatter for Type 1 Format TV IE.
- threegpp.encoding.V(length, remainder=None)
Create a Formatter for Type 3 Format V.
- Parameters
length (int) – Fixed length of the value field in bytes.
remainder ('n' or None) – If
'n', allows variable length from length to max. If None, fixed length.
- Return type
Formatter instance
- threegpp.encoding.Vlower
Formatter for Type 1 Format V lower half-octet IE.
- threegpp.encoding.Vupper
Formatter for Type 1 Format V upper half-octet IE.
Examples
1. Basic modification
1from binascii import unhexlify
2from threegpp.l3msg import Message
3
4data = unhexlify(b"2e0101c1ffff91a12801017b001380000100001000000c00000e00000300000d00")
5
6# Decode a message from a byte string
7msg = Message.decode(data)
8
9# Access the protocol discriminator value
10protocol = msg.protocol # Returns 0x2E for 5GSM
11
12# Get the value of an IE
13capability = msg["5GSMCapability"]
14
15# Check if an IE is present in the message
16if "SuggestedInterfaceIdentifier" in msg:
17 # Delete the IE from the message
18 del msg["SuggestedInterfaceIdentifier"]
19
20# Set a new value for an existing IE
21msg["5GSMCapability"] = 2
22
23# Setting a value for a non-existing IE adds it to the message
24msg["MaximumNumberOfSupportedPacketFilters"] = b"\x01\x02"
25
26# The IE-indexing functions also work with IEIs
27msg[0x55] = b"\x03\x04"
28
29# Encode the modified message back to a byte string
30modified_data = msg.encode()
2. Messages with multi-valued IEs
1from binascii import unhexlify
2from threegpp.l3msg import Message
3
4# Example message with multiple optional IEs
5data = unhexlify(b"2e0101c1ffff91a12801017b001380000100001000000c00000e00000300000d00")
6
7# Decode a message from a byte string
8msg = Message.decode(data)
9
10# getIE() - Get a single IE value (first occurrence by default)
11capability = msg.getIE("5GSMCapability")
12
13# getIE(all=True) - Get all occurrences of an IE
14all_capabilities = msg.getIE("5GSMCapability", all=True)
15
16# setIE(all=True) - Replace all occurrences with new values
17# This replaces all occurrences with the values in the list
18msg.setIE("5GSMCapability", [0xAA, 0xBB, 0xCC], all=True)
19
20# delIE() - Delete first occurrence of an IE
21msg.delIE("5GSMCapability")
22
23# delIE(all=True) - Delete all remaining occurrences of an IE
24msg.delIE("5GSMCapability", all=True)
25
26# Check if IE exists after deletion
27exists = "5GSMCapability" in msg
28
29# Using IEI (0x28) instead of name
30msg.setIE(0x28, [0x12, 0x34], all=True)
31capabilities_by_iei = msg.getIE(0x28, all=True)
32
33# Difference between [] and getIE()
34first_only = msg["5GSMCapability"] # Returns first value only
35first_getie = msg.getIE("5GSMCapability") # Also returns first value only
36all_getie = msg.getIE("5GSMCapability", all=True) # Returns list of all values
3. Working with custom IEs and the IE list
1from binascii import unhexlify
2from threegpp.l3msg import Message, IE, IEDesc
3from threegpp.encoding import TLV
4
5# Example message
6data = unhexlify(b"2e0101c1ffff91a12801017b001380000100001000000c00000e00000300000d00")
7
8msg = Message.decode(data)
9
10# Direct access to the IEs list
11# Message.ies is a list of IE objects
12ies_list = msg.ies
13
14# Iterate over all IEs in the message
15for ie in msg.ies:
16 # Each IE has a descriptor (desc) and a value
17 ie_name = ie.desc.name
18 ie_value = ie.value
19 ie_iei = ie.desc.iei
20
21# Find a specific IE by examining the list
22capability_ie = next((ie for ie in msg.ies if ie.desc.name == "5GSMCapability"), None)
23
24# Modify an IE's value directly
25if capability_ie:
26 capability_ie.value = 0xAB
27
28# Add a new IE by creating an IE object and appending to the list
29# Note: No ordering checks are performed when manipulating the list directly
30new_ie_desc = IEDesc(0x99, "CustomIE", TLV(3, 255))
31new_ie = IE(new_ie_desc, b"\x01\x02")
32msg.ies.append(new_ie)
33
34# Insert an IE at a specific position
35another_ie_desc = IEDesc(0xAA, "AnotherCustomIE", TV(2))
36another_ie = IE(another_ie_desc, 1)
37msg.ies.insert(5, another_ie) # Insert at position 5
38
39# Remove an IE from the list by index
40del msg.ies[5]
41
42# Remove an IE by finding it first
43ie_to_remove = next((ie for ie in msg.ies if ie.desc.name == "5GSMCapability"), None)
44if ie_to_remove:
45 msg.ies.remove(ie_to_remove)
46
47# Add multiple IEs of the same type
48for value in [0x11, 0x22, 0x33]:
49 ie_desc = msg.desc["5GSMCapability"]
50 msg.ies.append(IE(ie_desc, value))
51
52# Encode the modified message
53modified_data = msg.encode()
4. Custom messages
1from threegpp.l3msg import Message, MessageDescriptor, IEDesc, fgsm_ie_descriptors
2from threegpp.encoding import V, TV, TLV, LV
3
4# Define a custom message type code (use a reserved/unassigned value)
5CUSTOM_MESSAGE_TYPE = 0xFF
6
7# Create a MessageDescriptor for the custom message
8# This defines the structure of IEs for this new message type
9custom_message_descriptor = MessageDescriptor(
10 [
11 # Mandatory IEs
12 IEDesc(None, "ExtendedProtocolDiscriminator", V(1)),
13 IEDesc(None, "PDUSessionID", V(1)),
14 IEDesc(None, "PTI", V(1)),
15 IEDesc(None, "MessageType", V(1)),
16 IEDesc(None, "CustomMandatoryField", V(2)),
17
18 # Optional IEs (with IEI values)
19 IEDesc(0x10, "CustomOptionalField1", TV(2)),
20 IEDesc(0x20, "CustomOptionalField2", TLV(3, 255)),
21 IEDesc(0x30, "CustomOptionalField3", TLV(3, 255)),
22 ]
23)
24
25# Add the custom message descriptor to the 5GSM descriptor table
26fgsm_ie_descriptors[CUSTOM_MESSAGE_TYPE] = custom_message_descriptor
27
28# Now we can decode a message of this custom type
29# Construct a raw message with the custom message type
30custom_message_data = bytes([
31 0x2E, # Extended Protocol Discriminator (5GSM)
32 0x05, # PDU Session ID
33 0x01, # PTI
34 0xFF, # Message Type (our custom type)
35 0x12, 0x34, # CustomMandatoryField (2 bytes)
36 0x10, 0xAB, # CustomOptionalField1 (TV format, IEI=0x10, value=0xAB)
37 0x20, 0x03, 0x01, 0x02, 0x03, # CustomOptionalField2 (TLV format)
38])
39
40# Decode the custom message
41msg = Message.decode(custom_message_data)
42
43# Access the custom IEs
44protocol_disc = msg["ExtendedProtocolDiscriminator"]
45session_id = msg["PDUSessionID"]
46mandatory_field = msg["CustomMandatoryField"]
47optional_field1 = msg["CustomOptionalField1"]
48optional_field2 = msg["CustomOptionalField2"]
49
50# Modify custom IE values
51# For V format fields, value must match the exact length
52msg["CustomMandatoryField"] = b"\x56\x78"
53msg["CustomOptionalField1"] = 0xCD
54
55# Add another optional IE
56msg["CustomOptionalField3"] = b"\x01\x02\x03\x04"
57
58# Encode the modified message back
59encoded_data = msg.encode()
5. Error handling
1from threegpp.l3msg import Message
2
3# Example 1: Handling unknown message types
4# Attempting to decode a message with an unknown message type
5try:
6 unknown_msg_data = bytes([
7 0x2E, # Extended Protocol Discriminator (5GSM)
8 0x05, # PDU Session ID
9 0x01, # PTI
10 0xEE, # Unknown Message Type
11 ])
12 msg = Message.decode(unknown_msg_data)
13except RuntimeError as e:
14 # Will raise: "Unknown 5GSM message type: 0xee"
15 print(e)
16
17# Example 2: Data too short for message header
18try:
19 short_data = bytes([0x2E, 0x01]) # Only 2 bytes, needs at least 4 for 5GSM
20 msg = Message.decode(short_data)
21except ValueError as e:
22 # Will raise: "Data too short to contain 5GSM header"
23 print(e)
24
25# Example 3: Invalid protocol discriminator
26try:
27 invalid_protocol = bytes([0xFF, 0x01, 0x02, 0x03])
28 msg = Message.decode(invalid_protocol)
29except RuntimeError as e:
30 # Protocol discriminator not in decoder table
31 print(e)
32
33# Example 4: Attempting to delete a mandatory IE
34# Create a RegistrationComplete message (5GMM message type 0x43)
35msg = Message.decode(bytes([
36 0x7E, # Extended Protocol Discriminator (5GMM)
37 0x00, # Security Header Type (0) | Spare Half Octet (0)
38 0x43, # Message Type (RegistrationComplete)
39]))
40
41try:
42 del msg["MessageType"] # MessageType is mandatory
43except RuntimeError as e:
44 # Will raise: "Cannot delete mandatory IEs"
45 print(e)
46
47# Example 5: Setting invalid value for IE
48try:
49 # SORTransparentContainer expects TLVE format (min 20 bytes)
50 # The format validates the value length
51 msg["SORTransparentContainer"] = b"\x01" # Too short
52except ValueError as e:
53 # Format validation error
54 print(e)
55
56# Example 6: Attempting to set unknown IE when not allowed
57# This is caught when trying to insert an IE that doesn't exist in the descriptor
58try:
59 msg["NonExistentIE"] = b"\x01\x02\x03"
60except RuntimeError as e:
61 # Will raise: "Cannot insert unknown IE"
62 print(e)
63
64# Example 7: Value validation - out of range for nibble fields
65try:
66 # SecurityHeaderType is a nibble field (upper 4 bits), values 0x0-0xF only
67 msg["SecurityHeaderType"] = 0x20 # Too large for a nibble
68except ValueError as e:
69 # Will raise: "Value out of range"
70 print(e)
71
72# Example 8: Encoding with invalid data
73try:
74 # Create a message with invalid mandatory field value
75 msg["ExtendedProtocolDiscriminator"] = 0x1234 # Too large for 1 byte
76except ValueError as e:
77 # Value validation fails
78 print(e)