| #! /usr/bin/env python |
| |
| # Copyright (C) 2017 Alessio Deiana <adeiana@gmail.com> |
| # 2017 Alexis Sultan <alexis.sultan@sfr.com> |
| |
| # This file is part of Scapy |
| # Scapy is free software: you can redistribute it and/or modify |
| # it under the terms of the GNU General Public License as published by |
| # the Free Software Foundation, either version 2 of the License, or |
| # any later version. |
| # |
| # Scapy 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 General Public License for more details. |
| # |
| # You should have received a copy of the GNU General Public License |
| # along with Scapy. If not, see <http://www.gnu.org/licenses/>. |
| |
| # scapy.contrib.description = GTPv2 |
| # scapy.contrib.status = loads |
| |
| import time |
| import logging |
| |
| from scapy.packet import * |
| from scapy.fields import * |
| from scapy.layers.inet import IP, UDP |
| from scapy.layers.inet6 import IP6Field |
| from scapy.compat import orb |
| |
| import scapy.contrib.gtp as gtp |
| |
| RATType = { |
| 6: "EUTRAN", |
| } |
| |
| GTPmessageType = {1: "echo_request", |
| 2: "echo_response", |
| 32: "create_session_req", |
| 33: "create_session_res", |
| 34: "modify_bearer_req", |
| 35: "modify_bearer_res", |
| 36: "delete_session_req", |
| 37: "delete_session_res", |
| 70: "downlink_data_notif_failure_indic", |
| 170: "realease_bearers_req", |
| 171: "realease_bearers_res", |
| 176: "downlink_data_notif", |
| 177: "downlink_data_notif_ack", |
| } |
| |
| IEType = {1: "IMSI", |
| 2: "Cause", |
| 3: "Recovery Restart", |
| 71: "APN", |
| 72: "AMBR", |
| 73: "EPS Bearer ID", |
| 74: "IPv4", |
| 75: "MEI", |
| 76: "MSISDN", |
| 77: "Indication", |
| 78: "Protocol Configuration Options", |
| 79: "PAA", |
| 80: "Bearer QoS", |
| 82: "RAT", |
| 83: "Serving Network", |
| 86: "ULI", |
| 87: "F-TEID", |
| 93: "Bearer Context", |
| 94: "Charging ID", |
| 95: "Charging Characteristics", |
| 99: "PDN Type", |
| 114: "UE Time zone", |
| 126: "Port Number", |
| 127: "APN Restriction", |
| 128: "Selection Mode", |
| 161: "Max MBR/APN-AMBR (MMBR)" |
| } |
| |
| CauseValues = { |
| 16: "Request Accepted", |
| } |
| |
| |
| class GTPHeader(Packet): |
| # 3GPP TS 29.060 V9.1.0 (2009-12) |
| # without the version |
| name = "GTP v2 Header" |
| fields_desc = [BitField("version", 2, 3), |
| BitField("P", 1, 1), |
| BitField("T", 1, 1), |
| BitField("SPARE", 0, 1), |
| BitField("SPARE", 0, 1), |
| BitField("SPARE", 0, 1), |
| ByteEnumField("gtp_type", None, GTPmessageType), |
| ShortField("length", None), |
| ConditionalField(IntField("teid", 0), |
| lambda pkt:pkt.T == 1), |
| ThreeBytesField("seq", RandShort()), |
| ByteField("SPARE", 0) |
| ] |
| |
| def post_build(self, p, pay): |
| p += pay |
| if self.length is None: |
| l = len(p)-8 |
| p = p[:2] + struct.pack("!H", l) + 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)) |
| |
| |
| class IE_IPv4(gtp.IE_Base): |
| name = "IE IPv4" |
| fields_desc = [ByteEnumField("ietype", 74, IEType), |
| ShortField("length", 0), |
| BitField("CR_flag", 0, 4), |
| BitField("instance", 0, 4), |
| IPField("address", RandIP())] |
| |
| |
| class IE_MEI(gtp.IE_Base): |
| name = "IE MEI" |
| fields_desc = [ByteEnumField("ietype", 75, IEType), |
| ShortField("length", 0), |
| BitField("CR_flag", 0, 4), |
| BitField("instance", 0, 4), |
| LongField("MEI", 0)] |
| |
| |
| def IE_Dispatcher(s): |
| """Choose the correct Information Element class.""" |
| |
| # Get the IE type |
| ietype = orb(s[0]) |
| cls = ietypecls.get(ietype, Raw) |
| |
| # if ietype greater than 128 are TLVs |
| if cls is Raw and ietype > 128: |
| cls = IE_NotImplementedTLV |
| |
| return cls(s) |
| |
| |
| class IE_EPSBearerID(gtp.IE_Base): |
| name = "IE EPS Bearer ID" |
| fields_desc = [ByteEnumField("ietype", 73, IEType), |
| ShortField("length", 0), |
| BitField("CR_flag", 0, 4), |
| BitField("instance", 0, 4), |
| ByteField("EBI", 0)] |
| |
| |
| class IE_RAT(gtp.IE_Base): |
| name = "IE RAT" |
| fields_desc = [ByteEnumField("ietype", 82, IEType), |
| ShortField("length", 0), |
| BitField("CR_flag", 0, 4), |
| BitField("instance", 0, 4), |
| ByteEnumField("RAT_type", None, RATType)] |
| |
| |
| class IE_ServingNetwork(gtp.IE_Base): |
| name = "IE Serving Network" |
| fields_desc = [ByteEnumField("ietype", 83, IEType), |
| ShortField("length", 0), |
| BitField("CR_flag", 0, 4), |
| BitField("instance", 0, 4), |
| gtp.TBCDByteField("MCC", "", 2), |
| gtp.TBCDByteField("MNC", "", 1)] |
| |
| |
| class ULI_RAI(gtp.IE_Base): |
| name = "IE Tracking Area Identity" |
| fields_desc = [ |
| gtp.TBCDByteField("MCC", "", 2), |
| # MNC: if the third digit of MCC is 0xf, then the length of |
| # MNC is 1 byte |
| gtp.TBCDByteField("MNC", "", 1), |
| ShortField("LAC", 0), |
| ShortField("RAC", 0)] |
| |
| |
| class ULI_SAI(gtp.IE_Base): |
| name = "IE Tracking Area Identity" |
| fields_desc = [ |
| gtp.TBCDByteField("MCC", "", 2), |
| gtp.TBCDByteField("MNC", "", 1), |
| ShortField("LAC", 0), |
| ShortField("SAC", 0)] |
| |
| |
| class ULI_TAI(gtp.IE_Base): |
| name = "IE Tracking Area Identity" |
| fields_desc = [ |
| gtp.TBCDByteField("MCC", "", 2), |
| gtp.TBCDByteField("MNC", "", 1), |
| ShortField("TAC", 0)] |
| |
| |
| class ULI_ECGI(gtp.IE_Base): |
| name = "IE E-UTRAN Cell Identifier" |
| fields_desc = [ |
| gtp.TBCDByteField("MCC", "", 2), |
| gtp.TBCDByteField("MNC", "", 1), |
| BitField("SPARE", 0, 4), |
| BitField("ECI", 0, 28)] |
| |
| |
| class IE_ULI(gtp.IE_Base): |
| name = "IE ULI" |
| fields_desc = [ByteEnumField("ietype", 86, IEType), |
| ShortField("length", 0), |
| BitField("CR_flag", 0, 4), |
| BitField("instance", 0, 4), |
| BitField("SPARE", 0, 2), |
| BitField("LAI_Present", 0, 1), |
| BitField("ECGI_Present", 0, 1), |
| BitField("TAI_Present", 0, 1), |
| BitField("RAI_Present", 0, 1), |
| BitField("SAI_Present", 0, 1), |
| BitField("CGI_Present", 0, 1), |
| ConditionalField( |
| PacketField("SAI", 0, ULI_SAI), lambda pkt: bool(pkt.SAI_Present)), |
| ConditionalField( |
| PacketField("RAI", 0, ULI_RAI), lambda pkt: bool(pkt.RAI_Present)), |
| ConditionalField( |
| PacketField("TAI", 0, ULI_TAI), lambda pkt: bool(pkt.TAI_Present)), |
| ConditionalField(PacketField("ECGI", 0, ULI_ECGI), |
| lambda pkt: bool(pkt.ECGI_Present))] |
| |
| |
| class IE_FTEID(gtp.IE_Base): |
| name = "IE F-TEID" |
| fields_desc = [ByteEnumField("ietype", 87, IEType), |
| ShortField("length", 0), |
| BitField("CR_flag", 0, 4), |
| BitField("instance", 0, 4), |
| BitField("ipv4_present", 0, 1), |
| BitField("ipv6_present", 0, 1), |
| BitField("InterfaceType", 0, 6), |
| XIntField("GRE_Key", 0), |
| ConditionalField( |
| IPField("ipv4", RandIP()), lambda pkt: pkt.ipv4_present), |
| ConditionalField(XBitField("ipv6", "2001::", 128), |
| lambda pkt: pkt.ipv6_present)] |
| |
| |
| class IE_BearerContext(gtp.IE_Base): |
| name = "IE Bearer Context" |
| fields_desc = [ByteEnumField("ietype", 93, IEType), |
| ShortField("length", 0), |
| BitField("CR_flag", 0, 4), |
| BitField("instance", 0, 4), |
| PacketListField("IE_list", None, IE_Dispatcher, |
| length_from=lambda pkt: pkt.length)] |
| |
| |
| class IE_NotImplementedTLV(gtp.IE_Base): |
| name = "IE not implemented" |
| fields_desc = [ByteEnumField("ietype", 0, IEType), |
| ShortField("length", None), |
| StrLenField("data", "", length_from=lambda x: x.length)] |
| |
| |
| class IE_IMSI(gtp.IE_Base): |
| name = "IE IMSI" |
| fields_desc = [ByteEnumField("ietype", 1, IEType), |
| ShortField("length", None), |
| BitField("CR_flag", 0, 4), |
| BitField("instance", 0, 4), |
| gtp.TBCDByteField("IMSI", "33607080910", |
| length_from=lambda x: x.length)] |
| |
| |
| class IE_Cause(gtp.IE_Base): |
| name = "IE Cause" |
| fields_desc = [ByteEnumField("ietype", 2, IEType), |
| ShortField("length", None), |
| BitField("CR_flag", 0, 4), |
| BitField("instance", 0, 4), |
| ByteEnumField("Cause", 1, CauseValues), |
| BitField("SPARE", 0, 5), |
| BitField("PCE", 0, 1), |
| BitField("BCE", 0, 1), |
| BitField("CS", 0, 1)] |
| |
| |
| class IE_RecoveryRestart(gtp.IE_Base): |
| name = "IE Recovery Restart" |
| fields_desc = [ByteEnumField("ietype", 3, IEType), |
| ShortField("length", None), |
| BitField("CR_flag", 0, 4), |
| BitField("instance", 0, 4), |
| ByteField("restart_counter", 0)] |
| |
| |
| class IE_APN(gtp.IE_Base): |
| name = "IE APN" |
| fields_desc = [ByteEnumField("ietype", 71, IEType), |
| ShortField("length", None), |
| BitField("CR_flag", 0, 4), |
| BitField("instance", 0, 4), |
| gtp.APNStrLenField("APN", "internet", |
| length_from=lambda x: x.length)] |
| |
| |
| class IE_AMBR(gtp.IE_Base): |
| name = "IE AMBR" |
| fields_desc = [ByteEnumField("ietype", 72, IEType), |
| ShortField("length", None), |
| BitField("CR_flag", 0, 4), |
| BitField("instance", 0, 4), |
| IntField("AMBR_Uplink", 0), |
| IntField("AMBR_Downlink", 0)] |
| |
| |
| class IE_MSISDN(gtp.IE_Base): |
| name = "IE MSISDN" |
| fields_desc = [ByteEnumField("ietype", 76, IEType), |
| ShortField("length", None), |
| BitField("CR_flag", 0, 4), |
| BitField("instance", 0, 4), |
| gtp.TBCDByteField("digits", "33123456789", |
| length_from=lambda x: x.length)] |
| |
| |
| class IE_Indication(gtp.IE_Base): |
| name = "IE Cause" |
| fields_desc = [ByteEnumField("ietype", 77, IEType), |
| ShortField("length", None), |
| BitField("CR_flag", 0, 4), |
| BitField("instance", 0, 4), |
| BitField("DAF", 0, 1), |
| BitField("DTF", 0, 1), |
| BitField("HI", 0, 1), |
| BitField("DFI", 0, 1), |
| BitField("OI", 0, 1), |
| BitField("ISRSI", 0, 1), |
| BitField("ISRAI", 0, 1), |
| BitField("SGWCI", 0, 1), |
| BitField("SQCI", 0, 1), |
| BitField("UIMSI", 0, 1), |
| BitField("CFSI", 0, 1), |
| BitField("CRSI", 0, 1), |
| BitField("PS", 0, 1), |
| BitField("PT", 0, 1), |
| BitField("SI", 0, 1), |
| BitField("MSV", 0, 1), |
| |
| ConditionalField( |
| BitField("RetLoc", 0, 1), lambda pkt: pkt.length > 2), |
| ConditionalField( |
| BitField("PBIC", 0, 1), lambda pkt: pkt.length > 2), |
| ConditionalField( |
| BitField("SRNI", 0, 1), lambda pkt: pkt.length > 2), |
| ConditionalField( |
| BitField("S6AF", 0, 1), lambda pkt: pkt.length > 2), |
| ConditionalField( |
| BitField("S4AF", 0, 1), lambda pkt: pkt.length > 2), |
| ConditionalField( |
| BitField("MBMDT", 0, 1), lambda pkt: pkt.length > 2), |
| ConditionalField( |
| BitField("ISRAU", 0, 1), lambda pkt: pkt.length > 2), |
| ConditionalField( |
| BitField("CCRSI", 0, 1), lambda pkt: pkt.length > 2), |
| |
| ConditionalField( |
| BitField("CPRAI", 0, 1), lambda pkt: pkt.length > 3), |
| ConditionalField( |
| BitField("ARRL", 0, 1), lambda pkt: pkt.length > 3), |
| ConditionalField( |
| BitField("PPOFF", 0, 1), lambda pkt: pkt.length > 3), |
| ConditionalField( |
| BitField("PPON", 0, 1), lambda pkt: pkt.length > 3), |
| ConditionalField( |
| BitField("PPSI", 0, 1), lambda pkt: pkt.length > 3), |
| ConditionalField( |
| BitField("CSFBI", 0, 1), lambda pkt: pkt.length > 3), |
| ConditionalField( |
| BitField("CLII", 0, 1), lambda pkt: pkt.length > 3), |
| ConditionalField( |
| BitField("CPSR", 0, 1), lambda pkt: pkt.length > 3), |
| |
| ] |
| |
| PDN_TYPES = { |
| 1: "IPv4", |
| 2: "IPv6", |
| 3: "IPv4/IPv6", |
| } |
| |
| PCO_OPTION_TYPES = { |
| 3: "IPv4", |
| 129: "Primary DNS Server IP address", |
| 130: "Primary NBNS Server IP address", |
| 131: "Secondary DNS Server IP address", |
| 132: "Secondary NBNS Server IP address", |
| } |
| |
| |
| class PCO_Option(Packet): |
| def extract_padding(self, pkt): |
| return "", pkt |
| |
| |
| class PCO_IPv4(PCO_Option): |
| name = "IPv4" |
| fields_desc = [ByteEnumField("type", None, PCO_OPTION_TYPES), |
| ByteField("length", 0), |
| IPField("address", RandIP())] |
| |
| |
| class PCO_Primary_DNS(PCO_Option): |
| name = "Primary DNS Server IP Address" |
| fields_desc = [ByteEnumField("type", None, PCO_OPTION_TYPES), |
| ByteField("length", 0), |
| IPField("address", RandIP())] |
| |
| |
| class PCO_Primary_NBNS(PCO_Option): |
| name = "Primary DNS Server IP Address" |
| fields_desc = [ByteEnumField("type", None, PCO_OPTION_TYPES), |
| ByteField("length", 0), |
| IPField("address", RandIP())] |
| |
| |
| class PCO_Secondary_DNS(PCO_Option): |
| name = "Secondary DNS Server IP Address" |
| fields_desc = [ByteEnumField("type", None, PCO_OPTION_TYPES), |
| ByteField("length", 0), |
| IPField("address", RandIP())] |
| |
| |
| class PCO_Secondary_NBNS(PCO_Option): |
| name = "Secondary NBNS Server IP Address" |
| fields_desc = [ByteEnumField("type", None, PCO_OPTION_TYPES), |
| ByteField("length", 0), |
| IPField("address", RandIP())] |
| |
| |
| PCO_PROTOCOL_TYPES = { |
| 0x0001: 'P-CSCF IPv6 Address Request', |
| 0x0003: 'DNS Server IPv6 Address Request', |
| 0x0005: 'MS Support of Network Requested Bearer Control indicator', |
| 0x000a: 'IP Allocation via NAS', |
| 0x000d: 'DNS Server IPv4 Address Request', |
| 0x000c: 'P-CSCF IPv4 Address Request', |
| 0x0010: 'IPv4 Link MTU Request', |
| 0x8021: 'IPCP', |
| 0xc023: 'Password Authentification Protocol', |
| 0xc223: 'Challenge Handshake Authentication Protocol', |
| } |
| |
| PCO_OPTION_CLASSES = { |
| 3: PCO_IPv4, |
| 129: PCO_Primary_DNS, |
| 130: PCO_Primary_NBNS, |
| 131: PCO_Secondary_DNS, |
| 132: PCO_Secondary_NBNS, |
| } |
| |
| |
| def PCO_option_dispatcher(s): |
| """Choose the correct PCO element.""" |
| option = orb(s[0]) |
| |
| cls = PCO_OPTION_CLASSES.get(option, Raw) |
| return cls(s) |
| |
| |
| def len_options(pkt): |
| return pkt.length-4 if pkt.length else 0 |
| |
| |
| class PCO_P_CSCF_IPv6_Address_Request(PCO_Option): |
| name = "PCO PCO-P CSCF IPv6 Address Request" |
| fields_desc = [ShortEnumField("type", None, PCO_PROTOCOL_TYPES), |
| ByteField("length", 0), |
| ConditionalField(XBitField("address", |
| "2001:db8:0:42::", 128), |
| lambda pkt: pkt.length)] |
| |
| |
| class PCO_DNS_Server_IPv6(PCO_Option): |
| name = "PCO DNS Server IPv6 Address Request" |
| fields_desc = [ShortEnumField("type", None, PCO_PROTOCOL_TYPES), |
| ByteField("length", 0), |
| ConditionalField(XBitField("address", |
| "2001:db8:0:42::", 128), |
| lambda pkt: pkt.length)] |
| |
| |
| class PCO_SOF(PCO_Option): |
| name = "PCO MS Support of Network Requested Bearer Control indicator" |
| fields_desc = [ShortEnumField("type", None, PCO_PROTOCOL_TYPES), |
| ByteField("length", 0), |
| ] |
| |
| |
| class PCO_PPP(PCO_Option): |
| name = "PPP IP Control Protocol" |
| fields_desc = [ByteField("Code", 0), |
| ByteField("Identifier", 0), |
| ShortField("length", 0), |
| PacketListField("Options", None, PCO_option_dispatcher, |
| length_from=len_options)] |
| |
| def extract_padding(self, pkt): |
| return "", pkt |
| |
| |
| class PCO_IP_Allocation_via_NAS(PCO_Option): |
| name = "PCO IP Address allocation via NAS Signaling" |
| fields_desc = [ShortEnumField("type", None, PCO_PROTOCOL_TYPES), |
| ByteField("length", 0), |
| PacketListField("Options", None, PCO_option_dispatcher, |
| length_from=len_options)] |
| |
| |
| class PCO_P_CSCF_IPv4_Address_Request(PCO_Option): |
| name = "PCO PCO-P CSCF IPv4 Address Request" |
| fields_desc = [ShortEnumField("type", None, PCO_PROTOCOL_TYPES), |
| ByteField("length", 0), |
| ConditionalField(IPField("address", RandIP()), |
| lambda pkt: pkt.length)] |
| |
| |
| class PCO_DNS_Server_IPv4(PCO_Option): |
| name = "PCO DNS Server IPv4 Address Request" |
| fields_desc = [ShortEnumField("type", None, PCO_PROTOCOL_TYPES), |
| ByteField("length", 0), |
| ConditionalField(IPField("address", RandIP()), |
| lambda pkt: pkt.length)] |
| |
| |
| class PCO_IPv4_Link_MTU_Request(PCO_Option): |
| name = "PCO IPv4 Link MTU Request" |
| fields_desc = [ShortEnumField("type", None, PCO_PROTOCOL_TYPES), |
| ByteField("length", 0), |
| ConditionalField(ShortField("MTU_size", 1500), |
| lambda pkt: pkt.length)] |
| |
| |
| class PCO_IPCP(PCO_Option): |
| name = "PCO Internet Protocol Control Protocol" |
| fields_desc = [ShortEnumField("type", None, PCO_PROTOCOL_TYPES), |
| ByteField("length", 0), |
| PacketField("PPP", None, PCO_PPP)] |
| |
| |
| class PCO_PPP_Auth(PCO_Option): |
| name = "PPP Password Authentification Protocol" |
| fields_desc = [ByteField("Code", 0), |
| ByteField("Identifier", 0), |
| ShortField("length", 0), |
| ByteField("PeerID_length", 0), |
| ConditionalField(StrFixedLenField( |
| "PeerID", |
| "", |
| length_from=lambda pkt: pkt.PeerID_length), |
| lambda pkt: pkt.PeerID_length), |
| ByteField("Password_length", 0), |
| ConditionalField( |
| StrFixedLenField( |
| "Password", |
| "", |
| length_from=lambda pkt: pkt.Password_length), |
| lambda pkt: pkt.Password_length)] |
| |
| |
| class PCO_PasswordAuthentificationProtocol(PCO_Option): |
| name = "PCO Password Authentification Protocol" |
| fields_desc = [ShortEnumField("type", None, PCO_PROTOCOL_TYPES), |
| ByteField("length", 0), |
| PacketField("PPP", None, PCO_PPP_Auth)] |
| |
| |
| class PCO_PPP_Challenge(PCO_Option): |
| name = "PPP Password Authentification Protocol" |
| fields_desc = [ByteField("Code", 0), |
| ByteField("Identifier", 0), |
| ShortField("length", 0), |
| ByteField("value_size", 0), |
| ConditionalField(StrFixedLenField( |
| "value", "", |
| length_from=lambda pkt: pkt.value_size), |
| lambda pkt: pkt.value_size), |
| ConditionalField(StrFixedLenField( |
| "name", "", |
| length_from=lambda pkt: pkt.length-pkt.value_size-5), |
| lambda pkt: pkt.length)] |
| |
| |
| class PCO_ChallengeHandshakeAuthenticationProtocol(PCO_Option): |
| name = "PCO Password Authentification Protocol" |
| fields_desc = [ShortEnumField("type", None, PCO_PROTOCOL_TYPES), |
| ByteField("length", 0), |
| PacketField("PPP", None, PCO_PPP_Challenge)] |
| |
| |
| PCO_PROTOCOL_CLASSES = { |
| 0x0001: PCO_P_CSCF_IPv6_Address_Request, |
| 0x0003: PCO_DNS_Server_IPv6, |
| 0x0005: PCO_SOF, |
| 0x000a: PCO_IP_Allocation_via_NAS, |
| 0x000c: PCO_P_CSCF_IPv4_Address_Request, |
| 0x000d: PCO_DNS_Server_IPv4, |
| 0x0010: PCO_IPv4_Link_MTU_Request, |
| 0x8021: PCO_IPCP, |
| 0xc023: PCO_PasswordAuthentificationProtocol, |
| 0xc223: PCO_ChallengeHandshakeAuthenticationProtocol, |
| } |
| |
| |
| def PCO_protocol_dispatcher(s): |
| """Choose the correct PCO element.""" |
| proto_num = orb(s[0])*256+orb(s[1]) |
| cls = PCO_PROTOCOL_CLASSES.get(proto_num, Raw) |
| return cls(s) |
| |
| |
| class IE_PCO(gtp.IE_Base): |
| name = "IE Protocol Configuration Options" |
| fields_desc = [ByteEnumField("ietype", 78, IEType), |
| ShortField("length", None), |
| BitField("CR_flag", 0, 4), |
| BitField("instance", 0, 4), |
| BitField("Extension", 0, 1), |
| BitField("SPARE", 0, 4), |
| BitField("PPP", 0, 3), |
| PacketListField("Protocols", None, PCO_protocol_dispatcher, |
| length_from=lambda pkt: pkt.length-1)] |
| |
| |
| class IE_PAA(gtp.IE_Base): |
| name = "IE PAA" |
| fields_desc = [ByteEnumField("ietype", 79, IEType), |
| ShortField("length", None), |
| BitField("CR_flag", 0, 4), |
| BitField("instance", 0, 4), |
| BitField("SPARE", 0, 5), |
| BitEnumField("PDN_type", None, 3, PDN_TYPES), |
| ConditionalField( |
| ByteField("ipv6_prefix_length", 8), |
| lambda pkt: pkt.PDN_type in (2, 3)), |
| ConditionalField( |
| XBitField("ipv6", "2001:db8:0:42::", 128), |
| lambda pkt: pkt.PDN_type in (2, 3)), |
| ConditionalField( |
| IPField("ipv4", 0), lambda pkt: pkt.PDN_type in (1, 3)), |
| ] |
| |
| |
| class IE_Bearer_QoS(gtp.IE_Base): |
| name = "IE Bearer Quality of Service" |
| fields_desc = [ByteEnumField("ietype", 80, IEType), |
| ShortField("length", None), |
| BitField("CR_flag", 0, 4), |
| BitField("instance", 0, 4), |
| BitField("SPARE", 0, 1), |
| BitField("PCI", 0, 1), |
| BitField("PriorityLevel", 0, 4), |
| BitField("SPARE", 0, 1), |
| BitField("PVI", 0, 1), |
| ByteField("QCI", 0), |
| BitField("MaxBitRateForUplink", 0, 40), |
| BitField("MaxBitRateForDownlink", 0, 40), |
| BitField("GuaranteedBitRateForUplink", 0, 40), |
| BitField("GuaranteedBitRateForDownlink", 0, 40)] |
| |
| |
| class IE_ChargingID(gtp.IE_Base): |
| name = "IE Charging ID" |
| fields_desc = [ByteEnumField("ietype", 94, IEType), |
| ShortField("length", None), |
| BitField("CR_flag", 0, 4), |
| BitField("instance", 0, 4), |
| IntField("ChargingID", 0)] |
| |
| |
| class IE_ChargingCharacteristics(gtp.IE_Base): |
| name = "IE Charging ID" |
| fields_desc = [ByteEnumField("ietype", 95, IEType), |
| ShortField("length", None), |
| BitField("CR_flag", 0, 4), |
| BitField("instance", 0, 4), |
| XShortField("ChargingCharacteristric", 0)] |
| |
| |
| class IE_PDN_type(gtp.IE_Base): |
| name = "IE PDN Type" |
| fields_desc = [ByteEnumField("ietype", 99, IEType), |
| ShortField("length", None), |
| BitField("CR_flag", 0, 4), |
| BitField("instance", 0, 4), |
| BitField("SPARE", 0, 5), |
| BitEnumField("PDN_type", None, 3, PDN_TYPES)] |
| |
| |
| class IE_UE_Timezone(gtp.IE_Base): |
| name = "IE UE Time zone" |
| fields_desc = [ByteEnumField("ietype", 114, IEType), |
| ShortField("length", None), |
| BitField("CR_flag", 0, 4), |
| BitField("instance", 0, 4), |
| ByteField("Timezone", 0), |
| ByteField("DST", 0)] |
| |
| |
| class IE_Port_Number(gtp.IE_Base): |
| name = "IE Port Number" |
| fields_desc = [ByteEnumField("ietype", 126, IEType), |
| ShortField("length", 2), |
| BitField("CR_flag", 0, 4), |
| BitField("instance", 0, 4), |
| ShortField("PortNumber", RandShort())] |
| |
| |
| class IE_APN_Restriction(gtp.IE_Base): |
| name = "IE APN Restriction" |
| fields_desc = [ByteEnumField("ietype", 127, IEType), |
| ShortField("length", None), |
| BitField("CR_flag", 0, 4), |
| BitField("instance", 0, 4), |
| ByteField("APN_Restriction", 0)] |
| |
| |
| class IE_SelectionMode(gtp.IE_Base): |
| name = "IE Selection Mode" |
| fields_desc = [ByteEnumField("ietype", 128, IEType), |
| ShortField("length", None), |
| BitField("CR_flag", 0, 4), |
| BitField("instance", 0, 4), |
| BitField("SPARE", 0, 6), |
| BitField("SelectionMode", 0, 2)] |
| |
| |
| class IE_MMBR(gtp.IE_Base): |
| name = "IE Max MBR/APN-AMBR (MMBR)" |
| fields_desc = [ByteEnumField("ietype", 72, IEType), |
| ShortField("length", None), |
| BitField("CR_flag", 0, 4), |
| BitField("instance", 0, 4), |
| IntField("uplink_rate", 0), |
| IntField("downlink_rate", 0)] |
| |
| |
| ietypecls = {1: IE_IMSI, |
| 2: IE_Cause, |
| 3: IE_RecoveryRestart, |
| 71: IE_APN, |
| 72: IE_AMBR, |
| 73: IE_EPSBearerID, |
| 74: IE_IPv4, |
| 75: IE_MEI, |
| 76: IE_MSISDN, |
| 77: IE_Indication, |
| 78: IE_PCO, |
| 79: IE_PAA, |
| 80: IE_Bearer_QoS, |
| 82: IE_RAT, |
| 83: IE_ServingNetwork, |
| 86: IE_ULI, |
| 87: IE_FTEID, |
| 93: IE_BearerContext, |
| 94: IE_ChargingID, |
| 95: IE_ChargingCharacteristics, |
| 99: IE_PDN_type, |
| 114: IE_UE_Timezone, |
| 126: IE_Port_Number, |
| 127: IE_APN_Restriction, |
| 128: IE_SelectionMode, |
| 161: IE_MMBR} |
| |
| # |
| # GTPv2 Commands |
| # 3GPP TS 29.060 V9.1.0 (2009-12) |
| # |
| |
| |
| class GTPV2Command(Packet): |
| fields_desc = [PacketListField("IE_list", None, IE_Dispatcher)] |
| |
| |
| class GTPV2EchoRequest(GTPV2Command): |
| name = "GTPv2 Echo Request" |
| |
| |
| class GTPV2EchoResponse(GTPV2Command): |
| name = "GTPv2 Echo Response" |
| |
| |
| class GTPV2CreateSessionRequest(GTPV2Command): |
| name = "GTPv2 Create Session Request" |
| |
| |
| class GTPV2CreateSessionResponse(GTPV2Command): |
| name = "GTPv2 Create Session Response" |
| |
| |
| class GTPV2DeleteSessionRequest(GTPV2Command): |
| name = "GTPv2 Delete Session Request" |
| |
| |
| class GTPV2DeleteSessionResponse(GTPV2Command): |
| name = "GTPv2 Delete Session Request" |
| |
| |
| class GTPV2ModifyBearerCommand(GTPV2Command): |
| name = "GTPv2 Modify Bearer Command" |
| |
| |
| class GTPV2ModifyBearerFailureNotification(GTPV2Command): |
| name = "GTPv2 Modify Bearer Command" |
| |
| |
| class GTPV2DownlinkDataNotifFailureIndication(GTPV2Command): |
| name = "GTPv2 Downlink Data Notification Failure Indication" |
| |
| |
| class GTPV2ModifyBearerRequest(GTPV2Command): |
| name = "GTPv2 Modify Bearer Request" |
| |
| |
| class GTPV2ModifyBearerResponse(GTPV2Command): |
| name = "GTPv2 Modify Bearer Response" |
| |
| |
| class GTPV2UpdateBearerRequest(GTPV2Command): |
| name = "GTPv2 Update Bearer Request" |
| |
| |
| class GTPV2UpdateBearerResponse(GTPV2Command): |
| name = "GTPv2 Update Bearer Response" |
| |
| |
| class GTPV2DeleteBearerRequest(GTPV2Command): |
| name = "GTPv2 Delete Bearer Request" |
| |
| |
| class GTPV2SuspendNotification(GTPV2Command): |
| name = "GTPv2 Suspend Notification" |
| |
| |
| class GTPV2SuspendAcknowledge(GTPV2Command): |
| name = "GTPv2 Suspend Acknowledge" |
| |
| |
| class GTPV2ResumeNotification(GTPV2Command): |
| name = "GTPv2 Resume Notification" |
| |
| |
| class GTPV2ResumeAcknowledge(GTPV2Command): |
| name = "GTPv2 Resume Acknowledge" |
| |
| |
| class GTPV2DeleteBearerResponse(GTPV2Command): |
| name = "GTPv2 Delete Bearer Response" |
| |
| |
| class GTPV2CreateIndirectDataForwardingTunnelRequest(GTPV2Command): |
| name = "GTPv2 Create Indirect Data Forwarding Tunnel Request" |
| |
| |
| class GTPV2CreateIndirectDataForwardingTunnelResponse(GTPV2Command): |
| name = "GTPv2 Create Indirect Data Forwarding Tunnel Response" |
| |
| |
| class GTPV2DeleteIndirectDataForwardingTunnelRequest(GTPV2Command): |
| name = "GTPv2 Delete Indirect Data Forwarding Tunnel Request" |
| |
| |
| class GTPV2DeleteIndirectDataForwardingTunnelResponse(GTPV2Command): |
| name = "GTPv2 Delete Indirect Data Forwarding Tunnel Response" |
| |
| |
| class GTPV2ReleaseBearerRequest(GTPV2Command): |
| name = "GTPv2 Release Bearer Request" |
| |
| |
| class GTPV2ReleaseBearerResponse(GTPV2Command): |
| name = "GTPv2 Release Bearer Response" |
| |
| |
| class GTPV2DownlinkDataNotif(GTPV2Command): |
| name = "GTPv2 Download Data Notification" |
| |
| |
| class GTPV2DownlinkDataNotifAck(GTPV2Command): |
| name = "GTPv2 Download Data Notification Acknowledgment" |
| |
| bind_layers(GTPHeader, GTPV2EchoRequest, gtp_type=1, T=0) |
| bind_layers(GTPHeader, GTPV2EchoResponse, gtp_type=2, T=0) |
| bind_layers(GTPHeader, GTPV2CreateSessionRequest, gtp_type=32) |
| bind_layers(GTPHeader, GTPV2CreateSessionResponse, gtp_type=33) |
| bind_layers(GTPHeader, GTPV2ModifyBearerRequest, gtp_type=34) |
| bind_layers(GTPHeader, GTPV2ModifyBearerResponse, gtp_type=35) |
| bind_layers(GTPHeader, GTPV2DeleteSessionRequest, gtp_type=36) |
| bind_layers(GTPHeader, GTPV2DeleteSessionResponse, gtp_type=37) |
| bind_layers(GTPHeader, GTPV2ModifyBearerCommand, gtp_type=64) |
| bind_layers(GTPHeader, GTPV2ModifyBearerFailureNotification, gtp_type=65) |
| bind_layers(GTPHeader, GTPV2DownlinkDataNotifFailureIndication, gtp_type=70) |
| bind_layers(GTPHeader, GTPV2UpdateBearerRequest, gtp_type=97) |
| bind_layers(GTPHeader, GTPV2UpdateBearerResponse, gtp_type=98) |
| bind_layers(GTPHeader, GTPV2DeleteBearerRequest, gtp_type=99) |
| bind_layers(GTPHeader, GTPV2DeleteBearerResponse, gtp_type=100) |
| bind_layers(GTPHeader, GTPV2SuspendNotification, gtp_type=162) |
| bind_layers(GTPHeader, GTPV2SuspendAcknowledge, gtp_type=163) |
| bind_layers(GTPHeader, GTPV2ResumeNotification, gtp_type=164) |
| bind_layers(GTPHeader, GTPV2ResumeAcknowledge, gtp_type=165) |
| bind_layers( |
| GTPHeader, GTPV2CreateIndirectDataForwardingTunnelRequest, gtp_type=166) |
| bind_layers( |
| GTPHeader, GTPV2CreateIndirectDataForwardingTunnelResponse, gtp_type=167) |
| bind_layers( |
| GTPHeader, GTPV2DeleteIndirectDataForwardingTunnelRequest, gtp_type=168) |
| bind_layers( |
| GTPHeader, GTPV2DeleteIndirectDataForwardingTunnelResponse, gtp_type=169) |
| bind_layers(GTPHeader, GTPV2ReleaseBearerRequest, gtp_type=170) |
| bind_layers(GTPHeader, GTPV2ReleaseBearerResponse, gtp_type=171) |
| bind_layers(GTPHeader, GTPV2DownlinkDataNotif, gtp_type=176) |
| bind_layers(GTPHeader, GTPV2DownlinkDataNotifAck, gtp_type=177) |