From 4f552fe24aaa42f9f3717b8b3fa985a2d7b578fa Mon Sep 17 00:00:00 2001 From: Guillaume Valadon <guillaume@valadon.net> Date: Tue, 23 Dec 2014 09:22:22 +0100 Subject: [PATCH] Refactoring to parse arbitrary Create PDP Context Request --HG-- branch : GTP support --- scapy/contrib/gtp.py | 291 ++++++++++++++++++++++++++++--------------- 1 file changed, 189 insertions(+), 102 deletions(-) diff --git a/scapy/contrib/gtp.py b/scapy/contrib/gtp.py index 515206a2..7cef66cf 100644 --- a/scapy/contrib/gtp.py +++ b/scapy/contrib/gtp.py @@ -1,8 +1,13 @@ -## This file is not now part of Scapy -## Look iniqua.com for more informations -## ffranz <ffranz@iniqua.com> +#! /usr/bin/env python + +## Copyright (C) 2014 Guillaume Valadon <guillaume.valadom@ssi.gouv.fr> +## 2012 ffranz <ffranz@iniqua.com> +## ## This program is published under a GPLv2 license +# scapy.contrib.description = GTP +# scapy.contrib.status = loads + import time import logging @@ -37,7 +42,15 @@ IEType = { 1 : "Cause", 28 : "TraceType", 128: "EndUserAddress", 131: "AccessPointName", - 133: "GSNAddress" } + 132: "ProtocolConfigurationOptions", + 133: "GSNAddress", + 134: "MSInternationalNumber", + 135: "QoS", + 148: "CommonFlags", + 151: "RatType", + 152: "UserLocationInformation", + 153: "MSTimeZone", + 154: "IMEI" } CauseValues = { 0 : "Request IMSI", 1 : "Request IMEI", @@ -143,46 +156,83 @@ class GTPEchoRequest(Packet): ByteField("npdu", 0), ByteField("next_ex", 0),] -class GTPEchoResponse(Packet): - # 3GPP TS 29.060 V9.1.0 (2009-12) - name = "GTP Echo Response" - fields_desc = [ XBitField("seq", 0, 16), - ByteField("npdu", 0), - ByteField("next_ex", 0), - ByteEnumField("IE_Recovery", "Recovery", IEType), - ByteField("res-counter", 24), ] +class IE_Cause(Packet): + name = "Cause" + fields_desc = [ ByteEnumField("ietype", 1, IEType), + BitField("Response", None, 1), + BitField("Rejection", None, 1), + BitEnumField("CauseValue", None, 6, CauseValues), ] + def extract_padding(self, pkt): + return "",pkt -class GTPCreatePDPContextRequest(Packet): - # 3GPP TS 29.060 V9.1.0 (2009-12) - name = "GTP Create PDP Context Request" - fields_desc = [ XBitField("seq", 0, 16), - ByteField("npdu", 0), - ByteField("next_ex", 0), - # IMSI: Conditional - Subscriber identity of de MS - ByteEnumField("IE_IMSI", "IMSI", IEType), - BitField("IMSI", 0, 64), - # RAI: Optional - Routeing Area Identity - ByteEnumField("IE_RAI", "RAI", IEType), + +class IE_IMSI(Packet): + name = "IMSI - Subscriber identity of the MS" + fields_desc = [ ByteEnumField("ietype", 2, IEType), + StrFixedLenField("IMSI", "", 8) ] + def extract_padding(self, pkt): + return "",pkt + +class IE_Routing(Packet): + name = "Routing Area Identity" + fields_desc = [ ByteEnumField("ietype", 3, IEType), BitField("MCC", None, 12), # MNC: If only have 2 digits, then third digit (1byte) is 0xf BitField("MNC", None, 12), BitField("LAC", None, 16), - ByteField("RAC", None), - # Selection Mode: Conditional - Indicates the origin of the APN in the message - ByteEnumField("IE_SelectionMode", "SelectionMode", IEType), - # First 6 bits are "1". Use only first 2 bits. - BitEnumField("SelectionMode", "MSorAPN", 8, Selection_Mode), - # TEIDI: Mandatory - Tunnel Endpoint Identifier Data I - ByteEnumField("IE_TEIDI", "TEIDI", IEType), - XBitField("TEIDI", 0, 32), - # TEICP: Conditional - Tunnel Endpoint Identifier Control Plane - ByteEnumField("IE_TEICP", "TEICP", IEType), - XBitField("TEICP", 0, 32), - # NSAPI: Mandatory - identifying a PDP context in a mobility management context specified by TEICP - ByteEnumField("IE_NASPI", "NSAPI", IEType), + ByteField("RAC", None) ] + def extract_padding(self, pkt): + return "",pkt + +class IE_Recovery(Packet): + name = "Recovery" + fields_desc = [ ByteEnumField("ietype", 14, IEType), + ByteField("res-counter", 24) ] + def extract_padding(self, pkt): + return "",pkt + +class IE_SelectionMode(Packet): + # Indicates the origin of the APN in the message + name = "Selection Mode" + fields_desc = [ ByteEnumField("ietype", 15, IEType), + BitEnumField("SelectionMode", "MSorAPN", 8, Selection_Mode) ] + def extract_padding(self, pkt): + return "",pkt + +class IE_TEIDI(Packet): + name = "Tunnel Endpoint Identifier Data" + fields_desc = [ ByteEnumField("ietype", 16, IEType), + StrFixedLenField("TEIDI", "", 4) ] + def extract_padding(self, pkt): + return "",pkt + +class IE_TEICP(Packet): + name = "Tunnel Endpoint Identifier Control Plane" + fields_desc = [ ByteEnumField("ietype", 17, IEType), + StrFixedLenField("TEICP", "", 4) ] + def extract_padding(self, pkt): + return "",pkt + +class IE_Teardown(Packet): + name = "Teardown Indicator" + fields_desc = [ ByteEnumField("ietype", 19, IEType), + ByteEnumField("indicator", "True", TeardownInd_value) ] + def extract_padding(self, pkt): + return "",pkt + +class IE_NSAPI(Packet): + # Identifies a PDP context in a mobility management context specified by TEICP + name = "NSAPI" + fields_desc = [ ByteEnumField("ietype", 20, IEType), XBitField("SpareNSAPI", 0x0000, 4), - XBitField("NSAPI", 0x0000, 4), - # Charging Characteristics: Conditional - way of informing both the SGSN and GGSN of the rules for + XBitField("NSAPI", 0x0000, 4) ] + def extract_padding(self, pkt): + return "",pkt + +class IE_ChargingCharacteristics(Packet): + # 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. # 0000 .... .... .... : spare # .... 1... .... .... : normal charging @@ -190,21 +240,36 @@ class GTPCreatePDPContextRequest(Packet): # .... ..0. .... .... : flat rate charging # .... ...0 .... .... : hot billing charging # .... .... 0000 0000 : reserved - ByteEnumField("IE_ChargingChrt", "ChargingChrt", IEType), 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), - # Trace Reference: Optional - Identifies a record or a collection of records for a particular trace. - ByteEnumField("IE_TraceReference", "TraceReference", IEType), - XBitField("Trace_reference", None, 16), - # Trace Type: Optional - Indicate the type of the trace - ByteEnumField("IE_TraceType", "TraceType", IEType), - XBitField("Trace_type", None, 16), - # End User Address: Conditional - to supply protocol specific information of the external packet - # data network accessed by the GGPRS suscribers. + XBitField("Ch_ChReserved", 0, 8) ] + def extract_padding(self, pkt): + return "",pkt + +class IE_TraceReference(Packet): + # 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) ] + def extract_padding(self, pkt): + return "",pkt + +class IE_TraceType(Packet): + # Indicates the type of the trace + name = "Trace Type" + fields_desc = [ ByteEnumField("ietype", 28, IEType), + XBitField("Trace_type", None, 16) ] + def extract_padding(self, pkt): + return "",pkt + +class IE_EndUserAddress(Packet): + # Supply protocol specific information of the external packet + name = "End User Addresss" + fields_desc = [ ByteEnumField("ietype", 128, IEType), + # data network accessed by the GGPRS subscribers. # - Request # 1 Type (1byte) # 2-3 Length (2bytes) - value 2 @@ -212,22 +277,73 @@ class GTPCreatePDPContextRequest(Packet): # 5 PDP Type Number # - Response # 6-n PDP Address - ByteEnumField("IE_EndUserAddress", "EndUserAddress", IEType), BitField("EndUserAddressLength", 2, 16), BitField("EndUserAddress", 1111, 4), BitField("PDPTypeOrganization", 1, 4), - XByteField("PDPTypeNumber", None), - # Access Point Name: Conditional - Sent by SGSN or by GGSN as defined in 3GPP TS 23.060 - ByteEnumField("IE_AccessPointName", "AccessPointName", IEType), - ByteField("APNLength", None), - #, length_from=lambda pkt:len(pkt.APNUrl)), - StrField("APNUrl", "apn.es"), - # Protocol Configuration: - # GSN Address: - ByteEnumField("IE_GSNAddress1", "GSNAddress", IEType), - LongField("GSNAddressLength", 4), - IPField("IPGSN1", "0.0.0.0"), ] - # GSN Address: + XByteField("PDPTypeNumber", None) ] + def extract_padding(self, pkt): + return "",pkt + +class IE_AccessPointName(Packet): + # 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), + StrLenField("APN", "apn.es", length_from=lambda x: x.length) ] + def extract_padding(self, pkt): + return "",pkt + +class IE_GSNAddress(Packet): + name = "GSN Address" + fields_desc = [ ByteEnumField("ietype", 133, IEType), + ShortField("length", 4), + IPField("address", "0.0.0.0") ] + def extract_padding(self, pkt): + return "",pkt + +class IE_NotImplemented(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, 15: IE_SelectionMode, 16: IE_TEIDI, + 17: IE_TEICP, 19: IE_Teardown, 20: IE_NSAPI, 26: IE_ChargingCharacteristics, + 27: IE_TraceReference, 28: IE_TraceType, + 128: IE_EndUserAddress, 131: IE_AccessPointName, 132: IE_NotImplemented, + 133: IE_GSNAddress, 134: IE_NotImplemented, 135: IE_NotImplemented, + 148: IE_NotImplemented, 151: IE_NotImplemented, 152: IE_NotImplemented, + 153: IE_NotImplemented, 154: IE_NotImplemented } + +def IE_Dispatcher(s): + if len(s) < 1: + return Raw(s) + ietype = ord(s[0]) + return ietypecls.get(ietype, Raw)(s) + +class GTPEchoResponse(Packet): + # 3GPP TS 29.060 V9.1.0 (2009-12) + name = "GTP Echo Response" + fields_desc = [ XBitField("seq", 0, 16), + ByteField("npdu", 0), + ByteField("next_ex", 0), + PacketListField("IE_list", [], IE_Dispatcher) ] + +class GTPCreatePDPContextRequest(Packet): + # 3GPP TS 29.060 V9.1.0 (2009-12) + name = "GTP Create PDP Context Request" + fields_desc = [ XBitField("seq", 0, 16), + ByteField("npdu", 0), + ByteField("next_ex", 0), + PacketListField("IE_list", [], IE_Dispatcher) ] + +class OLD_GTPCreatePDPContextRequest(Packet): + # 3GPP TS 29.060 V9.1.0 (2009-12) + name = "GTP Create PDP Context Request" + fields_desc = [ XBitField("seq", 0, 16), + PacketListField("IE_list", [], IE_Dispatcher) ] class GTPErrorIndication(Packet): @@ -236,13 +352,7 @@ class GTPErrorIndication(Packet): fields_desc = [ XBitField("seq", 0, 16), ByteField("npdu", 0), ByteField("next_ex",0), - # TEIDI: Mandatory - Tunnel Endpoint Identifier Data I - ByteEnumField("IE_TEIDI", "TEIDI", IEType), - XBitField("TEIDI", 0, 32), - # GSN Address: - ByteEnumField("IE_GSNAddress1", "GSNAddress", IEType), - BitField("GSNAddressLength", 4, 16), - IPField("IPGSN1", "252.253.254.255"), ] + PacketListField("IE_list", [], IE_Dispatcher) ] class GTPDeletePDPContextRequest(Packet): # 3GPP TS 29.060 V9.1.0 (2009-12) @@ -250,17 +360,7 @@ class GTPDeletePDPContextRequest(Packet): fields_desc = [ XBitField("seq", 0, 16), ByteField("npdu", 0), ByteField("next_ex", 0), - # Teardown Ind: conditional - If this element is set to "1", all PDP Contexts that share the same PDP - # address or two IP addresses with the PDP context identified by the - # NSAPI included in the Delete PDP Context Request Message shall be torn down. - ByteEnumField("IE_TeardownInd", "TeardownInd", IEType), - ByteEnumField("TeardownInd", "True", TeardownInd_value), - # NSAPI: Mandatory - identifying a PDP context in a mobility management context specified by TEICP - ByteEnumField("IE_NSAPI", "NSAPI", IEType), - XBitField("SpareNSAPI", 0x0000, 4), - XBitField("NSAPI", 0x0000, 4), ] - # Protocol Configuration Options: Optional - TODO - # Private Extensions: Optional - Contains vendor specific information. TODO + PacketListField("IE_list", [], IE_Dispatcher) ] class GTPDeletePDPContextResponse(Packet): # 3GPP TS 29.060 V9.1.0 (2009-12) @@ -268,15 +368,7 @@ class GTPDeletePDPContextResponse(Packet): fields_desc = [ XBitField("seq", 0, 16), ByteField("npdu", 0), ByteField("next_ex",0), - # Cause: Mandatory - - ByteEnumField("IE_Cause", "Cause", IEType), - BitField("Response", None, 1), - BitField("Rejection", None, 1), - BitEnumField("CauseValue", None, 6, CauseValues), ] - # Protocol Configuration Options: Optional - TODO - # User Location Information: Optional - TODO - # MS Time Zone: Optional - TODO - # Private Extension: Optional - TODO + PacketListField("IE_list", [], IE_Dispatcher) ] class GTP_U_Header(Packet): # 3GPP TS 29.060 V9.1.0 (2009-12) @@ -293,14 +385,9 @@ class GTP_U_Header(Packet): ByteEnumField("type", None, GTPmessageType), BitField("length", None, 16), XBitField("TEID", 0, 32), - # Conditional fields: - # XBitField("seq", 0, 16), - ByteField("npdu", 0), - ByteField("next_ex", 0), - - ConditionalField(XBitField("seq", 0, 16), lambda pkt:pkt.S == 1), - # ConditionalField(ByteField("npdu", 0), lambda pkt:pkt.PT == 1), - # ConditionalField(ByteField("next_ex", 0), lambda pkt:pkt.E == 1), + ConditionalField(XBitField("seq", 0, 16), lambda pkt:pkt.E==1 or pkt.S==1 or pkt.PN==1), + ConditionalField(ByteField("npdu", 0), lambda pkt:pkt.E==1 or pkt.S==1 or pkt.PN==1), + ConditionalField(ByteField("next_ex", 0), lambda pkt:pkt.E==1 or pkt.S==1 or pkt.PN==1), ] def post_build(self, p, pay): @@ -330,12 +417,12 @@ class GTPmorethan1500(Packet): # Bind GTP-C bind_layers(UDP, GTPHeader) -bind_layers( GTPHeader, GTPEchoRequest) -bind_layers(GTPHeader, GTPEchoResponse) -bind_layers(GTPHeader, GTPCreatePDPContextRequest) -bind_layers(GTPHeader, GTPDeletePDPContextRequest) -bind_layers(GTPHeader, GTPDeletePDPContextResponse) -#Bind GTP-U +bind_layers(GTPHeader, GTPEchoRequest, type = 1) +bind_layers(GTPHeader, GTPEchoResponse, type = 2) +bind_layers(GTPHeader, GTPCreatePDPContextRequest, type = 16) +bind_layers(GTPHeader, GTPDeletePDPContextRequest, type = 20) +bind_layers(GTPHeader, GTPDeletePDPContextResponse, type = 21) +# Bind GTP-U bind_layers(UDP, GTP_U_Header) bind_layers(GTP_U_Header, IP) -- GitLab