From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 08420A04DD; Tue, 31 Dec 2019 13:06:56 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id CF7D81C020; Tue, 31 Dec 2019 13:06:55 +0100 (CET) Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by dpdk.org (Postfix) with ESMTP id E54641C012 for ; Tue, 31 Dec 2019 13:06:53 +0100 (CET) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga105.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 31 Dec 2019 04:06:52 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.69,379,1571727600"; d="scan'208";a="244129700" Received: from unknown (HELO dpdktestzhiwei.sh.intel.com) ([10.67.119.33]) by fmsmga004.fm.intel.com with ESMTP; 31 Dec 2019 04:06:50 -0800 From: "zhiwei.he" To: dts@dpdk.org Cc: "zhiwei.he" Date: Tue, 31 Dec 2019 20:07:08 +0800 Message-Id: <1577794029-82969-1-git-send-email-zhiwei.he@intel.com> X-Mailer: git-send-email 1.8.3.1 Subject: [dts] [PATCH V1 1/2] dep/add gtp for the advanced rss feature support gtp packets in CVL X-BeenThere: dts@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: test suite reviews and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dts-bounces@dpdk.org Sender: "dts" From: "zhiwei.he" Signed-off-by: zhiwei.he --- dep/gtp.py | 909 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 909 insertions(+) create mode 100644 dep/gtp.py diff --git a/dep/gtp.py b/dep/gtp.py new file mode 100644 index 0000000..7d57789 --- /dev/null +++ b/dep/gtp.py @@ -0,0 +1,909 @@ +#! /usr/bin/env python + +# 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 +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 IP6Field +from scapy.modules.six.moves import range +from scapy.packet import bind_layers, 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", + 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]] # noqa: E501 + return b"".join(ret) + + def i2m(self, pkt, val): + val = str(val) + ret_string = "" + for i in range(0, len(val), 2): + tmp = val[i:i + 2] + if len(tmp) == 2: + ret_string += chr(int(tmp[1] + tmp[0], 16)) + else: + ret_string += chr(int("F" + tmp[0], 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 + + +# 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 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): + s = b"".join(chb(len(x)) + x for x in s.split(".")) + 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", 4), + IPField("address", RandIP())] + + +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 pkt: pkt.length > 1), + ConditionalField(XBitField("delay_class", 0x000, 3), + lambda pkt: pkt.length > 1), + ConditionalField(XBitField("reliability_class", 0x000, 3), + lambda pkt: pkt.length > 1), + + ConditionalField(XBitField("peak_troughput", 0x0000, 4), + lambda pkt: pkt.length > 2), + ConditionalField(BitField("spare", 0, 1), + lambda pkt: pkt.length > 2), + ConditionalField(XBitField("precedence_class", 0x000, 3), + lambda pkt: pkt.length > 2), + + ConditionalField(XBitField("spare", 0x000, 3), + lambda pkt: pkt.length > 3), + ConditionalField(XBitField("mean_troughput", 0x00000, 5), + lambda pkt: pkt.length > 3), + + ConditionalField(XBitField("traffic_class", 0x000, 3), + lambda pkt: pkt.length > 4), + ConditionalField(XBitField("delivery_order", 0x00, 2), + lambda pkt: pkt.length > 4), + ConditionalField(XBitField("delivery_of_err_sdu", 0x000, 3), + lambda pkt: pkt.length > 4), + + ConditionalField(ByteField("max_sdu_size", None), + lambda pkt: pkt.length > 5), + ConditionalField(ByteField("max_bitrate_up", None), + lambda pkt: pkt.length > 6), + ConditionalField(ByteField("max_bitrate_down", None), + lambda pkt: pkt.length > 7), + + ConditionalField(XBitField("redidual_ber", 0x0000, 4), + lambda pkt: pkt.length > 8), + ConditionalField(XBitField("sdu_err_ratio", 0x0000, 4), + lambda pkt: pkt.length > 8), + ConditionalField(XBitField("transfer_delay", 0x00000, 6), + lambda pkt: pkt.length > 9), + ConditionalField(XBitField("traffic_handling_prio", + 0x000, + 2), + lambda pkt: pkt.length > 9), + + ConditionalField(ByteField("guaranteed_bit_rate_up", None), + lambda pkt: pkt.length > 10), + ConditionalField(ByteField("guaranteed_bit_rate_down", + None), + lambda pkt: pkt.length > 11), + + ConditionalField(XBitField("spare", 0x000, 3), + lambda pkt: pkt.length > 12), + ConditionalField(BitField("signaling_indication", 0, 1), + lambda pkt: pkt.length > 12), + ConditionalField(XBitField("source_stats_desc", 0x0000, 4), + lambda pkt: pkt.length > 12), + + ConditionalField(ByteField("max_bitrate_down_ext", None), + lambda pkt: pkt.length > 13), + ConditionalField(ByteField("guaranteed_bitrate_down_ext", + None), + lambda pkt: pkt.length > 14), + ConditionalField(ByteField("max_bitrate_up_ext", None), + lambda pkt: pkt.length > 15), + ConditionalField(ByteField("guaranteed_bitrate_up_ext", + None), + lambda pkt: pkt.length > 16), + ConditionalField(ByteField("max_bitrate_down_ext2", None), + lambda pkt: pkt.length > 17), + ConditionalField(ByteField("guaranteed_bitrate_down_ext2", + None), + lambda pkt: pkt.length > 18), + ConditionalField(ByteField("max_bitrate_up_ext2", None), + lambda pkt: pkt.length > 19), + ConditionalField(ByteField("guaranteed_bitrate_up_ext2", + None), + lambda pkt: pkt.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(), # noqa: E501 + IE_GSNAddress(), + 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(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_layers(UDP, GTPHeader, dport=2123) +bind_layers(UDP, GTPHeader, 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_layers(UDP, GTP_U_Header, dport=2152) +bind_layers(UDP, GTP_U_Header, sport=2152) +bind_layers(GTP_U_Header, GTPErrorIndication, gtp_type=26, S=1) +bind_layers(GTP_U_Header, IP, gtp_type=255) -- 1.8.3.1