From d95249d019778719a59d0124a496c61e8b7830b0 Mon Sep 17 00:00:00 2001
From: Jan Sebechlebsky <sebechlebskyjan@gmail.com>
Date: Thu, 19 Jan 2017 18:40:16 +0100
Subject: [PATCH] Add support for RFC 2637 (PPTP) GRE

---
 scapy/layers/l2.py | 38 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/scapy/layers/l2.py b/scapy/layers/l2.py
index 40f44518..e81c4e7b 100644
--- a/scapy/layers/l2.py
+++ b/scapy/layers/l2.py
@@ -968,6 +968,13 @@ class GRE(Packet):
                     ConditionalField(XIntField("key",None), lambda pkt:pkt.key_present==1),
                     ConditionalField(XIntField("seqence_number",None), lambda pkt:pkt.seqnum_present==1),
                     ]
+
+    @classmethod
+    def dispatch_hook(cls, _pkt=None, *args, **kargs):
+        if _pkt and struct.unpack("!H", _pkt[2:4])[0] == 0x880b:
+            return GRE_PPTP
+        return cls
+
     def post_build(self, p, pay):
         p += pay
         if self.chksum_present and self.chksum is None:
@@ -976,6 +983,37 @@ class GRE(Packet):
         return p
 
 
+class GRE_PPTP(GRE):
+
+    """
+    Enhanced GRE header used with PPTP
+    RFC 2637
+    """
+
+    name = "GRE PPTP"
+    fields_desc = [BitField("chksum_present", 0, 1),
+                   BitField("routing_present", 0, 1),
+                   BitField("key_present", 1, 1),
+                   BitField("seqnum_present", 0, 1),
+                   BitField("strict_route_source", 0, 1),
+                   BitField("recursion_control", 0, 3),
+                   BitField("acknum_present", 0, 1),
+                   BitField("flags", 0, 4),
+                   BitField("version", 1, 3),
+                   XShortEnumField("proto", 0x880b, ETHER_TYPES),
+                   ShortField("payload_len", None),
+                   ShortField("call_id", None),
+                   ConditionalField(XIntField("seqence_number", None), lambda pkt: pkt.seqnum_present == 1),
+                   ConditionalField(XIntField("ack_number", None), lambda pkt: pkt.acknum_present == 1)]
+
+    def post_build(self, p, pay):
+        p += pay
+        if self.payload_len is None:
+            pay_len = len(pay)
+            p = p[:4] + chr((pay_len >> 8) & 0xff) + chr(pay_len & 0xff) + p[6:]
+        return p
+
+
 ### *BSD loopback layer
 
 class LoIntEnumField(EnumField):
-- 
GitLab