From 1bb54991903a2e3a1d8c6f590aa4bb34d708c7d9 Mon Sep 17 00:00:00 2001
From: Guillaume Valadon <guillaume@valadon.net>
Date: Thu, 30 Mar 2017 09:05:13 +0200
Subject: [PATCH] Support Raw IPv6 as PCAP linktype

---
 scapy/data.py         |  5 ++++-
 scapy/layers/inet.py  |  1 +
 scapy/layers/inet6.py | 18 ++++++++++++++++++
 test/regression.uts   |  8 ++++++++
 4 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/scapy/data.py b/scapy/data.py
index 65c829bb..27b3d088 100644
--- a/scapy/data.py
+++ b/scapy/data.py
@@ -30,8 +30,11 @@ ARPHDR_PPP = 512
 ARPHDR_LOOPBACK = 772
 ARPHDR_TUN = 65534
 
-# From net/bpf.h
+# From pcap/dlt.h
 DLT_NULL = 0
+DLT_RAW = 101
+DLT_IPV4 = 228
+DLT_IPV6 = 229
 
 # From net/ipv6.h on Linux (+ Additions)
 IPV6_ADDR_UNICAST     = 0x01
diff --git a/scapy/layers/inet.py b/scapy/layers/inet.py
index 31fc420f..bd51e72e 100644
--- a/scapy/layers/inet.py
+++ b/scapy/layers/inet.py
@@ -804,6 +804,7 @@ bind_layers( IP,            GRE,           frag=0, proto=47)
 
 conf.l2types.register(101, IP)
 conf.l2types.register_num2layer(12, IP)
+conf.l2types.register(DLT_IPV4, IP)
 
 conf.l3types.register(ETH_P_IP, IP)
 conf.l3types.register_num2layer(ETH_P_ALL, IP)
diff --git a/scapy/layers/inet6.py b/scapy/layers/inet6.py
index 1fa08c6c..bba5d308 100644
--- a/scapy/layers/inet6.py
+++ b/scapy/layers/inet6.py
@@ -525,6 +525,21 @@ class IPv6(_IPv6GuessPayload, Packet, IPTools):
             return self.payload.answers(other.payload)
 
 
+class _IPv46(IP):
+    """
+    This class implements a dispatcher that is used to detect the IP version
+    while parsing Raw IP pcap files.
+    """
+    @classmethod
+    def dispatch_hook(cls, _pkt=None, *_, **kargs):
+        if _pkt:
+            if struct.unpack('B', _pkt[0])[0] >> 4 == 6:
+                return IPv6
+        elif kargs.get("version") == 6:
+            return IPv6
+        return IP
+
+
 def inet6_register_l3(l2, l3):
     return getmacbyip6(l3.dst)
 conf.neighbor.register_l3(Ether, IPv6, inet6_register_l3)
@@ -3074,6 +3089,7 @@ _mip6_mhtype2cls = { 0: MIP6MH_BRR,
                      7: MIP6MH_BE }
 
 
+
 #############################################################################
 #############################################################################
 ###                             Traceroute6                               ###
@@ -3858,6 +3874,8 @@ def NDP_Attack_Fake_Router(ra, iface=None, mac_src_filter=None,
 
 conf.l3types.register(ETH_P_IPV6, IPv6)
 conf.l2types.register(31, IPv6)
+conf.l2types.register(DLT_IPV6, IPv6)
+conf.l2types.register(DLT_RAW, _IPv46)
 
 bind_layers(Ether,     IPv6,     type = 0x86dd )
 bind_layers(CookedLinux, IPv6,   proto = 0x86dd )
diff --git a/test/regression.uts b/test/regression.uts
index 80de536c..10794888 100644
--- a/test/regression.uts
+++ b/test/regression.uts
@@ -4964,6 +4964,14 @@ pcapfile = cStringIO.StringIO(b'\xd4\xc3\xb2\xa1\x02\x00\x04\x00\x00\x00\x00\x00
 values = [tuple(int(val) for val in line[:-1].split('\t')) for line in tcpdump(pcapfile, prog=conf.prog.tshark, getfd=True, args=['-T', 'fields', '-e', 'ip.ttl', '-e', 'ip.proto'])]
 assert values == [(64, 6), (64, 17), (64, 1)]
 
+= Check Raw IP pcap files
+
+import tempfile
+filename = tempfile.mktemp(suffix=".pcap")
+wrpcap(filename, [IP()/UDP(), IPv6()/UDP()], linktype=DLT_RAW)
+packets = rdpcap(filename)
+assert(isinstance(packets[0], IP) and isinstance(packets[1], IPv6))
+
 
 ############
 ############
-- 
GitLab