From b714108ae43ad650553c15f5d29398980a1c0231 Mon Sep 17 00:00:00 2001 From: gpotter2 Date: Wed, 1 May 2019 13:18:43 +0200 Subject: [PATCH] Fix GTP_U_Header binds --- scapy/contrib/gtp.py | 33 ++++++++++++++++++++++++++------- scapy/contrib/gtp.uts | 15 +++++++++++++++ 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/scapy/contrib/gtp.py b/scapy/contrib/gtp.py index 7d577890e9b..aed80a3e6cd 100644 --- a/scapy/contrib/gtp.py +++ b/scapy/contrib/gtp.py @@ -22,9 +22,11 @@ IPField, PacketListField, ShortField, StrFixedLenField, StrLenField, \ XBitField, XByteField, XIntField from scapy.layers.inet import IP, UDP -from scapy.layers.inet6 import IP6Field +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, Packet, Raw +from scapy.packet import bind_layers, bind_bottom_up, bind_top_down, \ + Packet, Raw from scapy.volatile import RandInt, RandIP, RandNum, RandString @@ -254,6 +256,19 @@ class GTP_U_Header(GTPHeader): # 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.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 = { @@ -887,8 +902,9 @@ class GTPmorethan1500(Packet): # Bind GTP-C -bind_layers(UDP, GTPHeader, dport=2123) -bind_layers(UDP, GTPHeader, sport=2123) +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) @@ -903,7 +919,10 @@ class GTPmorethan1500(Packet): 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_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, IP, gtp_type=255) +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) diff --git a/scapy/contrib/gtp.uts b/scapy/contrib/gtp.uts index 53efb87f882..23393f7b9c1 100644 --- a/scapy/contrib/gtp.uts +++ b/scapy/contrib/gtp.uts @@ -16,6 +16,21 @@ assert a.E == a.S == a.PN == 0 a = GTPHeader(raw(GTP_U_Header()/GTPErrorIndication())) assert isinstance(a, GTP_U_Header) += GTP_U_Header sub layers + +a = IPv6(raw(IPv6()/UDP()/GTP_U_Header()/IPv6())) +b = IPv6(raw(IPv6()/UDP()/GTP_U_Header()/IP())) +c = IP(raw(IP()/UDP()/GTP_U_Header()/IPv6())) +d = IP(raw(IP()/UDP()/GTP_U_Header()/IP())) + +assert isinstance(a[GTP_U_Header].payload, IPv6) +assert isinstance(b[GTP_U_Header].payload, IP) +assert isinstance(c[GTP_U_Header].payload, IPv6) +assert isinstance(d[GTP_U_Header].payload, IP) + +a = IP(raw(IP()/UDP()/GTP_U_Header()/PPP())) +assert isinstance(a[GTP_U_Header].payload, PPP) + = GTPCreatePDPContextRequest(), basic instantiation gtp = IP(src="127.0.0.1")/UDP(dport=2123)/GTPHeader(teid=2807)/GTPCreatePDPContextRequest() gtp.dport == 2123 and gtp.teid == 2807 and len(gtp.IE_list) == 5