# Copyright (C) 2018 Leonardo Monteiro # 2017 Alexis Sultan # 2017 Alessio Deiana # 2014 Guillaume Valadon # 2012 ffranz ## # This program is published under a GPLv2 license # scapy.contrib.description = GPRS Tunneling Protocol (GTP) # scapy.contrib.status = loads from __future__ import absolute_import import struct from scapy.compat import chb, orb, bytes_encode from scapy.error import warning from scapy.fields import BitEnumField, BitField, ByteEnumField, ByteField, \ ConditionalField, FieldLenField, FieldListField, FlagsField, IntField, \ IPField, PacketListField, ShortField, StrFixedLenField, StrLenField, \ XBitField, XByteField, XIntField from scapy.layers.inet import IP, UDP from scapy.layers.inet6 import IPv6, IP6Field from scapy.layers.ppp import PPP from scapy.modules.six.moves import range from scapy.packet import bind_layers, bind_bottom_up, bind_top_down, \ Packet, Raw from scapy.volatile import RandInt, RandIP, RandNum, RandString # GTP Data types RATType = { 1: "UTRAN", 2: "GETRAN", 3: "WLAN", 4: "GAN", 5: "HSPA" } GTPmessageType = {1: "echo_request", 2: "echo_response", 16: "create_pdp_context_req", 17: "create_pdp_context_res", 18: "update_pdp_context_req", 19: "update_pdp_context_resp", 20: "delete_pdp_context_req", 21: "delete_pdp_context_res", 26: "error_indication", 27: "pdu_notification_req", 31: "supported_extension_headers_notification", 254: "end_marker", 255: "g_pdu"} IEType = {1: "Cause", 2: "IMSI", 3: "RAI", 4: "TLLI", 5: "P_TMSI", 8: "IE_ReorderingRequired", 14: "Recovery", 15: "SelectionMode", 16: "TEIDI", 17: "TEICP", 19: "TeardownInd", 20: "NSAPI", 26: "ChargingChrt", 27: "TraceReference", 28: "TraceType", 127: "ChargingId", 128: "EndUserAddress", 131: "AccessPointName", 132: "ProtocolConfigurationOptions", 133: "GSNAddress", 134: "MSInternationalNumber", 135: "QoS", 148: "CommonFlags", 149: "APNRestriction", 151: "RatType", 152: "UserLocationInformation", 153: "MSTimeZone", 154: "IMEI", 181: "MSInfoChangeReportingAction", 184: "BearerControlMode", 191: "EvolvedAllocationRetentionPriority", 255: "PrivateExtention"} CauseValues = {0: "Request IMSI", 1: "Request IMEI", 2: "Request IMSI and IMEI", 3: "No identity needed", 4: "MS Refuses", 5: "MS is not GPRS Responding", 128: "Request accepted", 129: "New PDP type due to network preference", 130: "New PDP type due to single address bearer only", 192: "Non-existent", 193: "Invalid message format", 194: "IMSI not known", 195: "MS is GPRS Detached", 196: "MS is not GPRS Responding", 197: "MS Refuses", 198: "Version not supported", 199: "No resources available", 200: "Service not supported", 201: "Mandatory IE incorrect", 202: "Mandatory IE missing", 203: "Optional IE incorrect", 204: "System failure", 205: "Roaming restriction", 206: "P-TMSI Signature mismatch", 207: "GPRS connection suspended", 208: "Authentication failure", 209: "User authentication failed", 210: "Context not found", 211: "All dynamic PDP addresses are occupied", 212: "No memory is available", 213: "Reallocation failure", 214: "Unknown mandatory extension header", 215: "Semantic error in the TFT operation", 216: "Syntactic error in TFT operation", 217: "Semantic errors in packet filter(s)", 218: "Syntactic errors in packet filter(s)", 219: "Missing or unknown APN", 220: "Unknown PDP address or PDP type", 221: "PDP context without TFT already activated", 222: "APN access denied : no subscription", 223: "APN Restriction type incompatibility with currently active PDP Contexts", # noqa: E501 224: "MS MBMS Capabilities Insufficient", 225: "Invalid Correlation : ID", 226: "MBMS Bearer Context Superseded", 227: "Bearer Control Mode violation", 228: "Collision with network initiated request"} Selection_Mode = {11111100: "MS or APN", 11111101: "MS", 11111110: "NET", 11111111: "FutureUse"} TrueFalse_value = {254: "False", 255: "True"} # http://www.arib.or.jp/IMT-2000/V720Mar09/5_Appendix/Rel8/29/29281-800.pdf ExtensionHeadersTypes = { 0: "No more extension headers", 1: "Reserved", 2: "Reserved", 64: "UDP Port", 133: "PDU Session Container", 192: "PDCP PDU Number", 193: "Reserved", 194: "Reserved" } class TBCDByteField(StrFixedLenField): def i2h(self, pkt, val): return val def m2i(self, pkt, val): ret = [] for v in val: byte = orb(v) left = byte >> 4 right = byte & 0xf if left == 0xf: ret.append(TBCD_TO_ASCII[right:right + 1]) else: ret += [ TBCD_TO_ASCII[right:right + 1], TBCD_TO_ASCII[left:left + 1] ] return b"".join(ret) def i2m(self, pkt, val): if not isinstance(val, bytes): val = bytes_encode(val) ret_string = b"" for i in range(0, len(val), 2): tmp = val[i:i + 2] if len(tmp) == 2: ret_string += chb(int(tmp[::-1], 16)) else: ret_string += chb(int(b"F" + tmp[:1], 16)) return ret_string TBCD_TO_ASCII = b"0123456789*#abc" class GTP_ExtensionHeader(Packet): @classmethod def dispatch_hook(cls, _pkt=None, *args, **kargs): if _pkt is None: return GTP_UDPPort_ExtensionHeader return cls class GTP_UDPPort_ExtensionHeader(GTP_ExtensionHeader): fields_desc = [ByteField("length", 0x40), ShortField("udp_port", None), ByteEnumField("next_ex", 0, ExtensionHeadersTypes), ] class GTP_PDCP_PDU_ExtensionHeader(GTP_ExtensionHeader): fields_desc = [ByteField("length", 0x01), ShortField("pdcp_pdu", None), ByteEnumField("next_ex", 0, ExtensionHeadersTypes), ] class GTPHeader(Packet): # 3GPP TS 29.060 V9.1.0 (2009-12) name = "GTP-C Header" fields_desc = [BitField("version", 1, 3), BitField("PT", 1, 1), BitField("reserved", 0, 1), BitField("E", 0, 1), BitField("S", 0, 1), BitField("PN", 0, 1), ByteEnumField("gtp_type", None, GTPmessageType), ShortField("length", None), IntField("teid", 0), ConditionalField(XBitField("seq", 0, 16), lambda pkt:pkt.E == 1 or pkt.S == 1 or pkt.PN == 1), # noqa: E501 ConditionalField(ByteField("npdu", 0), lambda pkt:pkt.E == 1 or pkt.S == 1 or pkt.PN == 1), # noqa: E501 ConditionalField(ByteEnumField("next_ex", 0, ExtensionHeadersTypes), lambda pkt:pkt.E == 1 or pkt.S == 1 or pkt.PN == 1), ] # noqa: E501 def post_build(self, p, pay): p += pay if self.length is None: tmp_len = len(p) - 8 p = p[:2] + struct.pack("!H", tmp_len) + p[4:] return p def hashret(self): return struct.pack("B", self.version) + self.payload.hashret() def answers(self, other): return (isinstance(other, GTPHeader) and self.version == other.version and self.payload.answers(other.payload)) @classmethod def dispatch_hook(cls, _pkt=None, *args, **kargs): if _pkt and len(_pkt) >= 1: if (orb(_pkt[0]) >> 5) & 0x7 == 2: from . import gtp_v2 return gtp_v2.GTPHeader if _pkt and len(_pkt) >= 8: _gtp_type = orb(_pkt[1:2]) return GTPforcedTypes.get(_gtp_type, GTPHeader) return cls class GTP_U_Header(GTPHeader): # 3GPP TS 29.060 V9.1.0 (2009-12) name = "GTP-U Header" # GTP-U protocol is used to transmit T-PDUs between GSN pairs (or between an SGSN and an RNC in UMTS), # noqa: E501 # encapsulated in G-PDUs. A G-PDU is a packet including a GTP-U header and a T-PDU. The Path Protocol # noqa: E501 # defines the path and the GTP-U header defines the tunnel. Several tunnels may be multiplexed on a single path. # noqa: E501 def guess_payload_class(self, payload): # Snooped from Wireshark # https://github.com/boundary/wireshark/blob/07eade8124fd1d5386161591b52e177ee6ea849f/epan/dissectors/packet-gtp.c#L8195 # noqa: E501 if self.E == 1: if self.next_ex == 0x85: return GTPPDUSessionContainer return GTPHeader.guess_payload_class(self, payload) if self.gtp_type == 255: sub_proto = orb(payload[0]) if sub_proto >= 0x45 and sub_proto <= 0x4e: return IP elif (sub_proto & 0xf0) == 0x60: return IPv6 else: return PPP return GTPHeader.guess_payload_class(self, payload) # Some gtp_types have to be associated with a certain type of header GTPforcedTypes = { 16: GTPHeader, 17: GTPHeader, 18: GTPHeader, 19: GTPHeader, 20: GTPHeader, 21: GTPHeader, 26: GTP_U_Header, 27: GTPHeader, 254: GTP_U_Header, 255: GTP_U_Header } class GTPPDUSessionContainer(Packet): name = "GTP PDU Session Container" fields_desc = [ByteField("ExtHdrLen", None), BitField("type", 0, 4), BitField("spare1", 0, 4), BitField("P", 0, 1), BitField("R", 0, 1), BitField("QFI", 0, 6), ConditionalField(XBitField("PPI", 0, 3), lambda pkt: pkt.P == 1), ConditionalField(XBitField("spare2", 0, 5), lambda pkt: pkt.P == 1), ConditionalField(ByteField("pad1", 0), lambda pkt: pkt.P == 1), ConditionalField(ByteField("pad2", 0), lambda pkt: pkt.P == 1), ConditionalField(ByteField("pad3", 0), lambda pkt: pkt.P == 1), ByteEnumField("NextExtHdr", 0, ExtensionHeadersTypes), ] def guess_payload_class(self, payload): if self.NextExtHdr == 0: sub_proto = orb(payload[0]) if sub_proto >= 0x45 and sub_proto <= 0x4e: return IP elif (sub_proto & 0xf0) == 0x60: return IPv6 else: return PPP return GTPHeader.guess_payload_class(self, payload) def post_build(self, p, pay): p += pay if self.ExtHdrLen is None: if self.P == 1: hdr_len = 2 else: hdr_len = 1 p = struct.pack("!B", hdr_len) + p[1:] return p def hashret(self): return struct.pack("H", self.seq) class GTPEchoRequest(Packet): # 3GPP TS 29.060 V9.1.0 (2009-12) name = "GTP Echo Request" def hashret(self): return struct.pack("H", self.seq) class IE_Base(Packet): def extract_padding(self, pkt): return "", pkt class IE_Cause(IE_Base): name = "Cause" fields_desc = [ByteEnumField("ietype", 1, IEType), ByteEnumField("CauseValue", None, CauseValues)] class IE_IMSI(IE_Base): name = "IMSI - Subscriber identity of the MS" fields_desc = [ByteEnumField("ietype", 2, IEType), TBCDByteField("imsi", str(RandNum(0, 999999999999999)), 8)] class IE_Routing(IE_Base): name = "Routing Area Identity" fields_desc = [ByteEnumField("ietype", 3, IEType), TBCDByteField("MCC", "", 2), # MNC: if the third digit of MCC is 0xf, # then the length of MNC is 1 byte TBCDByteField("MNC", "", 1), ShortField("LAC", None), ByteField("RAC", None)] class IE_ReorderingRequired(IE_Base): name = "Recovery" fields_desc = [ByteEnumField("ietype", 8, IEType), ByteEnumField("reordering_required", 254, TrueFalse_value)] class IE_Recovery(IE_Base): name = "Recovery" fields_desc = [ByteEnumField("ietype", 14, IEType), ByteField("restart_counter", 24)] class IE_SelectionMode(IE_Base): # Indicates the origin of the APN in the message name = "Selection Mode" fields_desc = [ByteEnumField("ietype", 15, IEType), BitEnumField("SelectionMode", "MS or APN", 8, Selection_Mode)] class IE_TEIDI(IE_Base): name = "Tunnel Endpoint Identifier Data" fields_desc = [ByteEnumField("ietype", 16, IEType), XIntField("TEIDI", RandInt())] class IE_TEICP(IE_Base): name = "Tunnel Endpoint Identifier Control Plane" fields_desc = [ByteEnumField("ietype", 17, IEType), XIntField("TEICI", RandInt())] class IE_Teardown(IE_Base): name = "Teardown Indicator" fields_desc = [ByteEnumField("ietype", 19, IEType), ByteEnumField("indicator", "True", TrueFalse_value)] class IE_NSAPI(IE_Base): # Identifies a PDP context in a mobility management context specified by TEICP # noqa: E501 name = "NSAPI" fields_desc = [ByteEnumField("ietype", 20, IEType), XBitField("sparebits", 0x0000, 4), XBitField("NSAPI", RandNum(0, 15), 4)] class IE_ChargingCharacteristics(IE_Base): # Way of informing both the SGSN and GGSN of the rules for name = "Charging Characteristics" fields_desc = [ByteEnumField("ietype", 26, IEType), # producing charging information based on operator configured triggers. # noqa: E501 # 0000 .... .... .... : spare # .... 1... .... .... : normal charging # .... .0.. .... .... : prepaid charging # .... ..0. .... .... : flat rate charging # .... ...0 .... .... : hot billing charging # .... .... 0000 0000 : reserved XBitField("Ch_ChSpare", None, 4), XBitField("normal_charging", None, 1), XBitField("prepaid_charging", None, 1), XBitField("flat_rate_charging", None, 1), XBitField("hot_billing_charging", None, 1), XBitField("Ch_ChReserved", 0, 8)] class IE_TraceReference(IE_Base): # Identifies a record or a collection of records for a particular trace. name = "Trace Reference" fields_desc = [ByteEnumField("ietype", 27, IEType), XBitField("Trace_reference", None, 16)] class IE_TraceType(IE_Base): # Indicates the type of the trace name = "Trace Type" fields_desc = [ByteEnumField("ietype", 28, IEType), XBitField("Trace_type", None, 16)] class IE_ChargingId(IE_Base): name = "Charging ID" fields_desc = [ByteEnumField("ietype", 127, IEType), XIntField("Charging_id", RandInt())] class IE_EndUserAddress(IE_Base): # Supply protocol specific information of the external packet name = "End User Address" fields_desc = [ByteEnumField("ietype", 128, IEType), # data network accessed by the GGPRS subscribers. # - Request # 1 Type (1byte) # 2-3 Length (2bytes) - value 2 # 4 Spare + PDP Type Organization # 5 PDP Type Number # - Response # 6-n PDP Address ShortField("length", 2), BitField("SPARE", 15, 4), BitField("PDPTypeOrganization", 1, 4), XByteField("PDPTypeNumber", None), ConditionalField(IPField("PDPAddress", RandIP()), lambda pkt: pkt.length == 6 or pkt.length == 22), # noqa: E501 ConditionalField(IP6Field("IPv6_PDPAddress", '::1'), lambda pkt: pkt.length == 18 or pkt.length == 22)] # noqa: E501 class APNStrLenField(StrLenField): # Inspired by DNSStrField def m2i(self, pkt, s): ret_s = b"" tmp_s = s while tmp_s: tmp_len = orb(tmp_s[0]) + 1 if tmp_len > len(tmp_s): warning("APN prematured end of character-string (size=%i, remaining bytes=%i)" % (tmp_len, len(tmp_s))) # noqa: E501 ret_s += tmp_s[1:tmp_len] tmp_s = tmp_s[tmp_len:] if len(tmp_s): ret_s += b"." s = ret_s return s def i2m(self, pkt, s): if not isinstance(s, bytes): s = bytes_encode(s) s = b"".join(chb(len(x)) + x for x in s.split(b".")) return s class IE_AccessPointName(IE_Base): # Sent by SGSN or by GGSN as defined in 3GPP TS 23.060 name = "Access Point Name" fields_desc = [ByteEnumField("ietype", 131, IEType), ShortField("length", None), APNStrLenField("APN", "nternet", length_from=lambda x: x.length)] # noqa: E501 def post_build(self, p, pay): if self.length is None: tmp_len = len(p) - 3 p = p[:2] + struct.pack("!B", tmp_len) + p[3:] return p class IE_ProtocolConfigurationOptions(IE_Base): name = "Protocol Configuration Options" fields_desc = [ByteEnumField("ietype", 132, IEType), ShortField("length", 4), StrLenField("Protocol_Configuration", "", length_from=lambda x: x.length)] class IE_GSNAddress(IE_Base): name = "GSN Address" fields_desc = [ByteEnumField("ietype", 133, IEType), ShortField("length", None), ConditionalField(IPField("ipv4_address", RandIP()), lambda pkt: pkt.length == 4), ConditionalField(IP6Field("ipv6_address", '::1'), lambda pkt: pkt.length == 16)] def post_build(self, p, pay): if self.length is None: tmp_len = len(p) - 3 p = p[:2] + struct.pack("!B", tmp_len) + p[3:] return p class IE_MSInternationalNumber(IE_Base): name = "MS International Number" fields_desc = [ByteEnumField("ietype", 134, IEType), ShortField("length", None), FlagsField("flags", 0x91, 8, ["Extension", "", "", "International Number", "", "", "", "ISDN numbering"]), # noqa: E501 TBCDByteField("digits", "33607080910", length_from=lambda x: x.length - 1)] # noqa: E501 class QoS_Profile(IE_Base): name = "QoS profile" fields_desc = [ByteField("qos_ei", 0), ByteField("length", None), XBitField("spare", 0x00, 2), XBitField("delay_class", 0x000, 3), XBitField("reliability_class", 0x000, 3), XBitField("peak_troughput", 0x0000, 4), BitField("spare", 0, 1), XBitField("precedence_class", 0x000, 3), XBitField("spare", 0x000, 3), XBitField("mean_troughput", 0x00000, 5), XBitField("traffic_class", 0x000, 3), XBitField("delivery_order", 0x00, 2), XBitField("delivery_of_err_sdu", 0x000, 3), ByteField("max_sdu_size", None), ByteField("max_bitrate_up", None), ByteField("max_bitrate_down", None), XBitField("redidual_ber", 0x0000, 4), XBitField("sdu_err_ratio", 0x0000, 4), XBitField("transfer_delay", 0x00000, 5), XBitField("traffic_handling_prio", 0x000, 3), ByteField("guaranteed_bit_rate_up", None), ByteField("guaranteed_bit_rate_down", None)] class IE_QoS(IE_Base): name = "QoS" fields_desc = [ByteEnumField("ietype", 135, IEType), ShortField("length", None), ByteField("allocation_retention_prioiry", 1), ConditionalField(XBitField("spare", 0x00, 2), lambda p: p.length and p.length > 1), ConditionalField(XBitField("delay_class", 0x000, 3), lambda p: p.length and p.length > 1), ConditionalField(XBitField("reliability_class", 0x000, 3), lambda p: p.length and p.length > 1), ConditionalField(XBitField("peak_troughput", 0x0000, 4), lambda p: p.length and p.length > 2), ConditionalField(BitField("spare", 0, 1), lambda p: p.length and p.length > 2), ConditionalField(XBitField("precedence_class", 0x000, 3), lambda p: p.length and p.length > 2), ConditionalField(XBitField("spare", 0x000, 3), lambda p: p.length and p.length > 3), ConditionalField(XBitField("mean_troughput", 0x00000, 5), lambda p: p.length and p.length > 3), ConditionalField(XBitField("traffic_class", 0x000, 3), lambda p: p.length and p.length > 4), ConditionalField(XBitField("delivery_order", 0x00, 2), lambda p: p.length and p.length > 4), ConditionalField(XBitField("delivery_of_err_sdu", 0x000, 3), lambda p: p.length and p.length > 4), ConditionalField(ByteField("max_sdu_size", None), lambda p: p.length and p.length > 5), ConditionalField(ByteField("max_bitrate_up", None), lambda p: p.length and p.length > 6), ConditionalField(ByteField("max_bitrate_down", None), lambda p: p.length and p.length > 7), ConditionalField(XBitField("redidual_ber", 0x0000, 4), lambda p: p.length and p.length > 8), ConditionalField(XBitField("sdu_err_ratio", 0x0000, 4), lambda p: p.length and p.length > 8), ConditionalField(XBitField("transfer_delay", 0x00000, 6), lambda p: p.length and p.length > 9), ConditionalField(XBitField("traffic_handling_prio", 0x000, 2), lambda p: p.length and p.length > 9), ConditionalField(ByteField("guaranteed_bit_rate_up", None), lambda p: p.length and p.length > 10), ConditionalField(ByteField("guaranteed_bit_rate_down", None), lambda p: p.length and p.length > 11), ConditionalField(XBitField("spare", 0x000, 3), lambda p: p.length and p.length > 12), ConditionalField(BitField("signaling_indication", 0, 1), lambda p: p.length and p.length > 12), ConditionalField(XBitField("source_stats_desc", 0x0000, 4), lambda p: p.length and p.length > 12), ConditionalField(ByteField("max_bitrate_down_ext", None), lambda p: p.length and p.length > 13), ConditionalField(ByteField("guaranteed_bitrate_down_ext", None), lambda p: p.length and p.length > 14), ConditionalField(ByteField("max_bitrate_up_ext", None), lambda p: p.length and p.length > 15), ConditionalField(ByteField("guaranteed_bitrate_up_ext", None), lambda p: p.length and p.length > 16), ConditionalField(ByteField("max_bitrate_down_ext2", None), lambda p: p.length and p.length > 17), ConditionalField(ByteField("guaranteed_bitrate_down_ext2", None), lambda p: p.length and p.length > 18), ConditionalField(ByteField("max_bitrate_up_ext2", None), lambda p: p.length and p.length > 19), ConditionalField(ByteField("guaranteed_bitrate_up_ext2", None), lambda p: p.length and p.length > 20)] class IE_CommonFlags(IE_Base): name = "Common Flags" fields_desc = [ByteEnumField("ietype", 148, IEType), ShortField("length", None), BitField("dual_addr_bearer_fl", 0, 1), BitField("upgrade_qos_supported", 0, 1), BitField("nrsn", 0, 1), BitField("no_qos_nego", 0, 1), BitField("mbms_cnting_info", 0, 1), BitField("ran_procedure_ready", 0, 1), BitField("mbms_service_type", 0, 1), BitField("prohibit_payload_compression", 0, 1)] class IE_APNRestriction(IE_Base): name = "APN Restriction" fields_desc = [ByteEnumField("ietype", 149, IEType), ShortField("length", 1), ByteField("restriction_type_value", 0)] class IE_RATType(IE_Base): name = "Rat Type" fields_desc = [ByteEnumField("ietype", 151, IEType), ShortField("length", 1), ByteEnumField("RAT_Type", None, RATType)] class IE_UserLocationInformation(IE_Base): name = "User Location Information" fields_desc = [ByteEnumField("ietype", 152, IEType), ShortField("length", None), ByteField("type", 1), # Only type 1 is currently supported TBCDByteField("MCC", "", 2), # MNC: if the third digit of MCC is 0xf, then the length of MNC is 1 byte # noqa: E501 TBCDByteField("MNC", "", 1), ShortField("LAC", None), ShortField("SAC", None)] class IE_MSTimeZone(IE_Base): name = "MS Time Zone" fields_desc = [ByteEnumField("ietype", 153, IEType), ShortField("length", None), ByteField("timezone", 0), BitField("Spare", 0, 1), BitField("Spare", 0, 1), BitField("Spare", 0, 1), BitField("Spare", 0, 1), BitField("Spare", 0, 1), BitField("Spare", 0, 1), XBitField("daylight_saving_time", 0x00, 2)] class IE_IMEI(IE_Base): name = "IMEI" fields_desc = [ByteEnumField("ietype", 154, IEType), ShortField("length", None), TBCDByteField("IMEI", "", length_from=lambda x: x.length)] class IE_MSInfoChangeReportingAction(IE_Base): name = "MS Info Change Reporting Action" fields_desc = [ByteEnumField("ietype", 181, IEType), ShortField("length", 1), ByteField("Action", 0)] class IE_DirectTunnelFlags(IE_Base): name = "Direct Tunnel Flags" fields_desc = [ByteEnumField("ietype", 182, IEType), ShortField("length", 1), BitField("Spare", 0, 1), BitField("Spare", 0, 1), BitField("Spare", 0, 1), BitField("Spare", 0, 1), BitField("Spare", 0, 1), BitField("EI", 0, 1), BitField("GCSI", 0, 1), BitField("DTI", 0, 1)] class IE_BearerControlMode(IE_Base): name = "Bearer Control Mode" fields_desc = [ByteEnumField("ietype", 184, IEType), ShortField("length", 1), ByteField("bearer_control_mode", 0)] class IE_EvolvedAllocationRetentionPriority(IE_Base): name = "Evolved Allocation/Retention Priority" fields_desc = [ByteEnumField("ietype", 191, IEType), ShortField("length", 1), BitField("Spare", 0, 1), BitField("PCI", 0, 1), XBitField("PL", 0x0000, 4), BitField("Spare", 0, 1), BitField("PVI", 0, 1)] class IE_CharginGatewayAddress(IE_Base): name = "Chargin Gateway Address" fields_desc = [ByteEnumField("ietype", 251, IEType), ShortField("length", 4), ConditionalField(IPField("ipv4_address", "127.0.0.1"), lambda pkt: pkt.length == 4), ConditionalField(IP6Field("ipv6_address", "::1"), lambda pkt: pkt.length == 16)] class IE_PrivateExtension(IE_Base): name = "Private Extension" fields_desc = [ByteEnumField("ietype", 255, IEType), ShortField("length", 1), ByteField("extension identifier", 0), StrLenField("extention_value", "", length_from=lambda x: x.length)] class IE_ExtensionHeaderList(IE_Base): name = "Extension Header List" fields_desc = [ByteEnumField("ietype", 141, IEType), FieldLenField("length", None, length_of="extension_headers"), # noqa: E501 FieldListField("extension_headers", [64, 192], ByteField("", 0))] # noqa: E501 class IE_NotImplementedTLV(Packet): name = "IE not implemented" fields_desc = [ByteEnumField("ietype", 0, IEType), ShortField("length", None), StrLenField("data", "", length_from=lambda x: x.length)] def extract_padding(self, pkt): return "", pkt ietypecls = {1: IE_Cause, 2: IE_IMSI, 3: IE_Routing, 8: IE_ReorderingRequired, 14: IE_Recovery, 15: IE_SelectionMode, 16: IE_TEIDI, 17: IE_TEICP, 19: IE_Teardown, 20: IE_NSAPI, 26: IE_ChargingCharacteristics, 27: IE_TraceReference, 28: IE_TraceType, 127: IE_ChargingId, 128: IE_EndUserAddress, 131: IE_AccessPointName, 132: IE_ProtocolConfigurationOptions, 133: IE_GSNAddress, 134: IE_MSInternationalNumber, 135: IE_QoS, 141: IE_ExtensionHeaderList, 148: IE_CommonFlags, 149: IE_APNRestriction, 151: IE_RATType, 152: IE_UserLocationInformation, 153: IE_MSTimeZone, 154: IE_IMEI, 181: IE_MSInfoChangeReportingAction, 182: IE_DirectTunnelFlags, 184: IE_BearerControlMode, 191: IE_EvolvedAllocationRetentionPriority, 251: IE_CharginGatewayAddress, 255: IE_PrivateExtension} def IE_Dispatcher(s): """Choose the correct Information Element class.""" if len(s) < 1: return Raw(s) # Get the IE type ietype = orb(s[0]) cls = ietypecls.get(ietype, Raw) # if ietype greater than 128 are TLVs if cls == Raw and ietype & 128 == 128: cls = IE_NotImplementedTLV return cls(s) class GTPEchoResponse(Packet): # 3GPP TS 29.060 V9.1.0 (2009-12) name = "GTP Echo Response" fields_desc = [PacketListField("IE_list", [], IE_Dispatcher)] def hashret(self): return struct.pack("H", self.seq) def answers(self, other): return self.seq == other.seq class GTPCreatePDPContextRequest(Packet): # 3GPP TS 29.060 V9.1.0 (2009-12) name = "GTP Create PDP Context Request" fields_desc = [PacketListField("IE_list", [IE_TEIDI(), IE_NSAPI(), IE_GSNAddress(length=4, ipv4_address=RandIP()), # noqa: E501 IE_GSNAddress(length=4, ipv4_address=RandIP()), # noqa: E501 IE_NotImplementedTLV(ietype=135, length=15, data=RandString(15))], # noqa: E501 IE_Dispatcher)] def hashret(self): return struct.pack("H", self.seq) class GTPCreatePDPContextResponse(Packet): # 3GPP TS 29.060 V9.1.0 (2009-12) name = "GTP Create PDP Context Response" fields_desc = [PacketListField("IE_list", [], IE_Dispatcher)] def hashret(self): return struct.pack("H", self.seq) def answers(self, other): return self.seq == other.seq class GTPUpdatePDPContextRequest(Packet): # 3GPP TS 29.060 V9.1.0 (2009-12) name = "GTP Update PDP Context Request" fields_desc = [PacketListField("IE_list", [ IE_Cause(), IE_Recovery(), IE_TEIDI(), IE_TEICP(), IE_ChargingId(), IE_ProtocolConfigurationOptions(), IE_GSNAddress(), IE_GSNAddress(), IE_GSNAddress(), IE_GSNAddress(), IE_QoS(), IE_CharginGatewayAddress(), IE_CharginGatewayAddress(), IE_CommonFlags(), IE_APNRestriction(), IE_BearerControlMode(), IE_MSInfoChangeReportingAction(), IE_EvolvedAllocationRetentionPriority(), IE_PrivateExtension()], IE_Dispatcher)] def hashret(self): return struct.pack("H", self.seq) class GTPUpdatePDPContextResponse(Packet): # 3GPP TS 29.060 V9.1.0 (2009-12) name = "GTP Update PDP Context Response" fields_desc = [PacketListField("IE_list", None, IE_Dispatcher)] def hashret(self): return struct.pack("H", self.seq) class GTPErrorIndication(Packet): # 3GPP TS 29.060 V9.1.0 (2009-12) name = "GTP Error Indication" fields_desc = [PacketListField("IE_list", [], IE_Dispatcher)] class GTPDeletePDPContextRequest(Packet): # 3GPP TS 29.060 V9.1.0 (2009-12) name = "GTP Delete PDP Context Request" fields_desc = [PacketListField("IE_list", [], IE_Dispatcher)] class GTPDeletePDPContextResponse(Packet): # 3GPP TS 29.060 V9.1.0 (2009-12) name = "GTP Delete PDP Context Response" fields_desc = [PacketListField("IE_list", [], IE_Dispatcher)] class GTPPDUNotificationRequest(Packet): # 3GPP TS 29.060 V9.1.0 (2009-12) name = "GTP PDU Notification Request" fields_desc = [PacketListField("IE_list", [IE_IMSI(), IE_TEICP(TEICI=RandInt()), IE_EndUserAddress(PDPTypeNumber=0x21), # noqa: E501 IE_AccessPointName(), IE_GSNAddress(ipv4_address="127.0.0.1"), # noqa: E501 ], IE_Dispatcher)] class GTPSupportedExtensionHeadersNotification(Packet): name = "GTP Supported Extension Headers Notification" fields_desc = [PacketListField("IE_list", [IE_ExtensionHeaderList(), ], IE_Dispatcher)] class GTPmorethan1500(Packet): # 3GPP TS 29.060 V9.1.0 (2009-12) name = "GTP More than 1500" fields_desc = [ByteEnumField("IE_Cause", "Cause", IEType), BitField("IE", 1, 12000), ] # Bind GTP-C bind_bottom_up(UDP, GTPHeader, dport=2123) bind_bottom_up(UDP, GTPHeader, sport=2123) bind_layers(UDP, GTPHeader, dport=2123, sport=2123) bind_layers(GTPHeader, GTPEchoRequest, gtp_type=1, S=1) bind_layers(GTPHeader, GTPEchoResponse, gtp_type=2, S=1) bind_layers(GTPHeader, GTPCreatePDPContextRequest, gtp_type=16) bind_layers(GTPHeader, GTPCreatePDPContextResponse, gtp_type=17) bind_layers(GTPHeader, GTPUpdatePDPContextRequest, gtp_type=18) bind_layers(GTPHeader, GTPUpdatePDPContextResponse, gtp_type=19) bind_layers(GTPHeader, GTPDeletePDPContextRequest, gtp_type=20) bind_layers(GTPHeader, GTPDeletePDPContextResponse, gtp_type=21) bind_layers(GTPHeader, GTPPDUNotificationRequest, gtp_type=27) bind_layers(GTPHeader, GTPSupportedExtensionHeadersNotification, gtp_type=31, S=1) # noqa: E501 bind_layers(GTPHeader, GTP_UDPPort_ExtensionHeader, next_ex=64, E=1) bind_layers(GTPHeader, GTP_PDCP_PDU_ExtensionHeader, next_ex=192, E=1) # Bind GTP-U bind_bottom_up(UDP, GTP_U_Header, dport=2152) bind_bottom_up(UDP, GTP_U_Header, sport=2152) bind_layers(UDP, GTP_U_Header, dport=2152, sport=2152) bind_layers(GTP_U_Header, GTPErrorIndication, gtp_type=26, S=1) bind_layers(GTP_U_Header, GTPPDUSessionContainer, gtp_type=255, E=1, next_ex=0x85) bind_top_down(GTP_U_Header, IP, gtp_type=255) bind_top_down(GTP_U_Header, IPv6, gtp_type=255) bind_top_down(GTP_U_Header, PPP, gtp_type=255)