Repository: secdev/scapy

Issue:
ICMPv6 packet could not be parsed with IPSec AH protocol configured 
I am attempting to parse a pcap file by using Scapy as lib, and now I encounter a problem. The ICMPv6 packet, which has been sent via IPSec AH protocol, could not be shown with show()/show2().
Pcap file: 
[AH_IPV6.zip](https://github.com/secdev/scapy/files/805587/AH_IPV6.zip)
My code is easy like this:
    
    from scapy.utils import rdpcap
    from scapy.all import conf

    def main():
        packet_list = rdpcap("/media/sf_ubshare/pcap/AH_IPV6.PCAP")
        pkt2 = packet_list.__getitem__(9)
        pkt2.show2()
    

ICMPv6 packet is missing in show2()
    
###[ IPv6 ]### 
     version   = 6L
     tc        = 0L
     fl        = 0L
     plen      = 128
     nh        = AH Header
     hlim      = 240
     src       = 1::2:1
     dst       = 1::3:2
###[ AH ]### 
        nh        = ipv6
        payloadlen= 4
        reserved  = 0
        spi       = 0x9592d65b
        seq       = 1
        icv       = '\x03\xa77\xc1\xea<\xcf\xb9bO~m`\x00\x00\x00\x00@:@\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x02\x80\x00I\xe2\x00d\x00\x00X\xa6\xa7\x10\x00\x0eJm\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./01234567'
        padding   = None
    
but in wireshark the ICMPv6 packet could be parsed successfully
![image](https://cloud.githubusercontent.com/assets/17735279/23388920/e0690f8a-fd9f-11e6-97c1-540c67faccef.png)

It seems like Scapy considers the ICMPv6 packet as a icv field of last packet.
after some dug I suspect there might be a problem in /scapy/utils.py
    
    def read_packet(self, size=MTU):
        """return a single packet read from the file
        
        returns None when no more packets are available
        """
        hdr = self.f.read(16)
        if len(hdr) < 16:
            return None
        sec,usec,caplen,wirelen = struct.unpack(self.endian+"IIII", hdr)  #<-- this line
        s = self.f.read(caplen)[:size]
        return s,(sec,usec,wirelen) # caplen = len(s)

Test bed info:

- Scapy version: 2.3.3

- OS: Ubuntu 14.04.3 LTS





Discussion:
I have tested Scapy with the correction. It works fine. But the data of icv is not in normal format:
###[ IPv6 ]### 
     version   = 6L
     tc        = 0L
     fl        = 0L
     plen      = 128
     nh        = AH Header
     hlim      = 240
     src       = 1::2:1
     dst       = 1::3:2
###[ AH ]### 
        nh        = ipv6
        payloadlen= 4
        reserved  = 0
        spi       = 0x9592d65b
        seq       = 1
        **icv       = '\x03\xa77\xc1\xea<\xcf\xb9bO~m'   <---This line should be 03 a7 37 c1 ea 3c cf b9 62 4f 7e 6d**
        padding   = ''

*The Pcap file keeps the same as attachment.

Test bed info:

- Scapy version: Scapy (2.3.3.dev372)
- OS: Ubuntu 14.04.3 LTS
Hello!

I am not sure if this is an issue as the ICV is stored as a raw buffer:

```
In [7]: '\x03\xa77\xc1\xea<\xcf\xb9bO~m'.encode('hex')
Out[7]: '03a737c1ea3ccfb9624f7e6d'
```

I don't know if the show method should display StrLenField as hexadecimal or as string...
Any opinion @guedou @p-l-?
hi,

I think from usability point of view, to show icv in "hex" might be much more friendly than "raw". And also wireshark use "hex" too.
![image](https://cloud.githubusercontent.com/assets/17735279/24856503/87572baa-1e17-11e7-9780-a96609800fe3.png)


 
I don't think that it is an issue, but I am willing to merge a PR that will replace the StrField to XStrField =)

Resolving patch:
diff --git a/scapy/layers/ipsec.py b/scapy/layers/ipsec.py
--- a/scapy/layers/ipsec.py
+++ b/scapy/layers/ipsec.py
@@ -47,12 +47,12 @@
 from scapy.config import conf, crypto_validator
 from scapy.data import IP_PROTOS
 from scapy.error import log_loading
-from scapy.fields import (ByteEnumField, ByteField, StrField, StrLenField,
-                          XIntField, IntField, ShortField, PacketField)
+from scapy.fields import ByteEnumField, ByteField, IntField, PacketField, \
+    ShortField, StrField, XIntField, XStrField, XStrLenField
 from scapy.packet import Packet, bind_layers, Raw
 from scapy.layers.inet import IP, UDP
-from scapy.layers.inet6 import (IPv6, IPv6ExtHdrHopByHop, IPv6ExtHdrDestOpt,
-                                IPv6ExtHdrRouting)
+from scapy.layers.inet6 import IPv6, IPv6ExtHdrHopByHop, IPv6ExtHdrDestOpt, \
+    IPv6ExtHdrRouting
 
 
 #------------------------------------------------------------------------------
@@ -82,9 +82,9 @@ def __get_icv_len(self):
         ShortField('reserved', None),
         XIntField('spi', 0x0),
         IntField('seq', 0),
-        StrLenField('icv', None, length_from=__get_icv_len),
+        XStrLenField('icv', None, length_from=__get_icv_len),
         # Padding len can only be known with the SecurityAssociation.auth_algo
-        StrLenField('padding', None, length_from=lambda x: 0),
+        XStrLenField('padding', None, length_from=lambda x: 0),
     ]
 
     overload_fields = {
@@ -112,7 +112,7 @@ class ESP(Packet):
     fields_desc = [
         XIntField('spi', 0x0),
         IntField('seq', 0),
-        StrField('data', None),
+        XStrField('data', None),
     ]
 
     overload_fields = {


Test patch: