Repository: secdev/scapy

Issue:
contrib/cdp.py CDPMsgIPPrefix class has wrong format
#### Things to consider

#### Brief description

[CDPMsgIPPrefix class](https://github.com/secdev/scapy/blob/2be23d9/scapy/contrib/cdp.py#L236) has following fields
```python
class CDPMsgIPPrefix(CDPMsgGeneric):
    name = "IP Prefix"
    type = 0x0007
    fields_desc = [XShortEnumField("type", 0x0007, _cdp_tlv_types),
                   ShortField("len", 8),
                   IPField("defaultgw", "192.168.0.1")]
```
But in real CDP(Cisco Discovery Protocol) packet, IP Prefixes has A.B.C.D/netmask format
```
IP Prefix: 20.0.0.0/24
14 00 00 00 18
```
quoted from [wireshark](https://github.com/wireshark/wireshark/blob/e206eb2/epan/dissectors/packet-cdp.c#L471)

#### Environment

-   Scapy version: `2.4.3`
-   Python version: `2.7.13`
-   Operating System: `Windows 10 64bit Pro`

#### How to reproduce


#### Actual result
![image](https://user-images.githubusercontent.com/47174372/69647196-66014500-10ac-11ea-9439-34171829bf67.png)
![image](https://user-images.githubusercontent.com/47174372/69647289-8df0a880-10ac-11ea-9d29-2b704afe90c7.png)


#### Expected result



#### Related resources

[test.pcap.zip](https://github.com/secdev/scapy/files/3892593/test.pcap.zip)




Discussion:
![image](https://user-images.githubusercontent.com/47174372/69650836-892ef300-10b2-11ea-99e7-033443593e60.png)
I edit it for immediate use.

Resolving patch:
diff --git a/scapy/contrib/cdp.py b/scapy/contrib/cdp.py
--- a/scapy/contrib/cdp.py
+++ b/scapy/contrib/cdp.py
@@ -46,7 +46,6 @@
                 0x0004: "CDPMsgCapabilities",
                 0x0005: "CDPMsgSoftwareVersion",
                 0x0006: "CDPMsgPlatform",
-                0x0007: "CDPMsgIPPrefix",
                 0x0008: "CDPMsgProtoHello",
                 0x0009: "CDPMsgVTPMgmtDomain",  # CDPv2
                 0x000a: "CDPMsgNativeVLAN",    # CDPv2
@@ -99,7 +98,14 @@ def _CDPGuessPayloadClass(p, **kargs):
     cls = conf.raw_layer
     if len(p) >= 2:
         t = struct.unpack("!H", p[:2])[0]
-        clsname = _cdp_tlv_cls.get(t, "CDPMsgGeneric")
+        if t == 0x0007 and len(p) > 4:
+            tmp_len = struct.unpack("!H", p[2:4])[0]
+            if tmp_len == 8:
+                clsname = "CDPMsgIPGateway"
+            else:
+                clsname = "CDPMsgIPPrefix"
+        else:
+            clsname = _cdp_tlv_cls.get(t, "CDPMsgGeneric")
         cls = globals()[clsname]
 
     return cls(p, **kargs)
@@ -184,7 +190,8 @@ class CDPMsgAddr(CDPMsgGeneric):
     fields_desc = [XShortEnumField("type", 0x0002, _cdp_tlv_types),
                    ShortField("len", None),
                    FieldLenField("naddr", None, "addr", "!I"),
-                   PacketListField("addr", [], _CDPGuessAddrRecord, count_from=lambda x:x.naddr)]  # noqa: E501
+                   PacketListField("addr", [], _CDPGuessAddrRecord,
+                                   length_from=lambda x:x.len - 8)]
 
     def post_build(self, pkt, pay):
         if self.len is None:
@@ -233,14 +240,23 @@ class CDPMsgPlatform(CDPMsgGeneric):
 # ODR Routing
 
 
-class CDPMsgIPPrefix(CDPMsgGeneric):
-    name = "IP Prefix"
+class CDPMsgIPGateway(CDPMsgGeneric):
+    name = "IP Gateway"
     type = 0x0007
     fields_desc = [XShortEnumField("type", 0x0007, _cdp_tlv_types),
                    ShortField("len", 8),
                    IPField("defaultgw", "192.168.0.1")]
 
 
+class CDPMsgIPPrefix(CDPMsgGeneric):
+    name = "IP Prefix"
+    type = 0x0007
+    fields_desc = [XShortEnumField("type", 0x0007, _cdp_tlv_types),
+                   ShortField("len", 9),
+                   IPField("prefix", "192.168.0.1"),
+                   ByteField("plen", 24)]
+
+
 class CDPMsgProtoHello(CDPMsgGeneric):
     name = "Protocol Hello"
     type = 0x0008


Test patch:
diff --git a/test/contrib/cdp.uts b/test/contrib/cdp.uts
--- a/test/contrib/cdp.uts
+++ b/test/contrib/cdp.uts
@@ -69,3 +69,9 @@ assert cdpv2[CDPMsgPower].sprintf("%power%") == '6300 mW'
 cdpv2.cksum = None
 s2 = s[:2] + b"\xf3\xf1" + s[4:]
 assert raw(cdpv2) == s2
+
+= CDPv2 - Complex Packet
+
+r = b'\x01\x00\x0c\xcc\xcc\xcc\x11"3DUf\x01\x80\xaa\xaa\x03\x00\x00\x0c \x00\x02\xb4uV\x00\x01\x00\nRouter\x00\x05\x00\x04\x00\x06\x00\x04\x00\x02\x00\x11\x00\x00\x00\x02\x01\x01\xcc\x00\x04\xc0\xa8\x01e\x00\x03\x00\x18GigabitEthernet0/0/1\x00\x04\x00\x08\x00\x00\x00A\x00\x07\x00\t\x14\x00\x00\x00\x18\x00\t\x00\x04\x00\x0b\x00\x05\x01\x00\x16\x00\x11\x00\x00\x00\x01\x01\x01\xcc\x00\x04\xc0\xa8\x01e'
+p = Dot3(r)
+assert CDPMsgPortID in p and CDPMsgIPPrefix in p