Repository: secdev/scapy

Issue:
VXLAN Binding to IPv6 or IPv4 doesn't work
#### Brief description
When doing a VXLAN()/IP or VXLAN()/IPv6 the binding does not work properly. Both IP layers are interpreted as Ethernet Layers.

#### Environment

-   Scapy version: `2.4.0`
-   Python version: `3.5.2`
-   Operating System: `Ubuntu 16.04`

#### How to reproduce
```python
>>> issue = Ether()/IP()/UDP()/VXLAN(flags=4, NextProtocol=1)/IP()
>>> issue.show2()
###[ Ethernet ]### 
  dst= ff:ff:ff:ff:ff:ff
  src= 00:00:00:00:00:00
  type= 0x800
###[ IP ]### 
     version= 4
     ihl= 5
     tos= 0x0
     len= 56
     id= 1
     flags= 
     frag= 0
     ttl= 64
     proto= udp
     chksum= 0x7cb2
     src= 127.0.0.1
     dst= 127.0.0.1
     \options\
###[ UDP ]### 
        sport= 4789
        dport= 4789
        len= 36
        chksum= 0xd838
###[ VXLAN ]### 
           flags= NextProtocol
           reserved0= 0
           NextProtocol= IPv4
           vni= 0x0
           reserved2= 0x0
###[ Ethernet ]### 
              dst= 45:00:00:14:00:01
              src= 00:00:40:00:7c:e7
              type= 0x7f00
###[ Raw ]### 
                 load= '\x00\x01\x7f\x00\x00\x01'
```

#### Actual result
```python
###[ Ethernet ]### 
  dst= ff:ff:ff:ff:ff:ff
  src= 00:00:00:00:00:00
  type= 0x800
###[ IP ]### 
     version= 4
     ihl= 5
     tos= 0x0
     len= 56
     id= 1
     flags= 
     frag= 0
     ttl= 64
     proto= udp
     chksum= 0x7cb2
     src= 127.0.0.1
     dst= 127.0.0.1
     \options\
###[ UDP ]### 
        sport= 4789
        dport= 4789
        len= 36
        chksum= 0xd838
###[ VXLAN ]### 
           flags= NextProtocol
           reserved0= 0
           NextProtocol= IPv4
           vni= 0x0
           reserved2= 0x0
###[ Ethernet ]### 
              dst= 45:00:00:14:00:01
              src= 00:00:40:00:7c:e7
              type= 0x7f00
###[ Raw ]### 
                 load= '\x00\x01\x7f\x00\x00\x01'
```

#### Expected result
```python
###[ Ethernet ]### 
  dst= ff:ff:ff:ff:ff:ff
  src= 00:00:00:00:00:00
  type= 0x800
###[ IP ]### 
     version= 4
     ihl= 5
     tos= 0x0
     len= 56
     id= 1
     flags= 
     frag= 0
     ttl= 64
     proto= udp
     chksum= 0x7cb2
     src= 127.0.0.1
     dst= 127.0.0.1
     \options\
###[ UDP ]### 
        sport= 4789
        dport= 4789
        len= 36
        chksum= 0xd838
###[ VXLAN ]### 
           flags= NextProtocol
           reserved0= 0
           NextProtocol= IPv4
           vni= 0x0
           reserved2= 0x0
###[ IP ]### 
              version= 4
              ihl= 5
              tos= 0x0
              len= 20
              id= 1
              flags= 
              frag= 0
              ttl= 64
              proto= hopopt
              chksum= 0x7ce7
              src= 127.0.0.1
              dst= 127.0.0.1
              \options\
```



Discussion:

Resolving patch:
diff --git a/scapy/layers/vxlan.py b/scapy/layers/vxlan.py
--- a/scapy/layers/vxlan.py
+++ b/scapy/layers/vxlan.py
@@ -85,9 +85,10 @@ def mysummary(self):
 # By default, set both ports to the RFC standard
 bind_layers(UDP, VXLAN, sport=4789, dport=4789)
 
-bind_layers(VXLAN, Ether)
+bind_layers(VXLAN, Ether, NextProtocol=0)
 bind_layers(VXLAN, IP, NextProtocol=1)
 bind_layers(VXLAN, IPv6, NextProtocol=2)
+bind_layers(VXLAN, Ether, NextProtocol=3)
 bind_layers(VXLAN, Ether, flags=4, NextProtocol=0)
 bind_layers(VXLAN, IP, flags=4, NextProtocol=1)
 bind_layers(VXLAN, IPv6, flags=4, NextProtocol=2)


Test patch:
diff --git a/test/regression.uts b/test/regression.uts
--- a/test/regression.uts
+++ b/test/regression.uts
@@ -8721,7 +8721,7 @@ pkt.flags.NextProtocol and pkt.NextProtocol == 3
 = Verify UDP dport overloading
 p = Ether(dst="11:11:11:11:11:11", src="22:22:22:22:22:22")
 p /= IP(src="1.1.1.1", dst="2.2.2.2") / UDP(sport=1111)
-p /= VXLAN(flags=0x8, vni=42) / Ether() / IP()
+p /= VXLAN(flags=0xC, vni=42, NextProtocol=0) / Ether() / IP()
 p = Ether(raw(p))
 assert(p[UDP].dport == 4789)
 assert(p[Ether:2].type == 0x800)
@@ -8739,21 +8739,51 @@ assert(p[Ether:2].type == 0x800)
 = Build a VXLAN packet with no group policy ID
 p = Ether(dst="11:11:11:11:11:11", src="22:22:22:22:22:22")
 p /= IP(src="1.1.1.1", dst="2.2.2.2") / UDP(sport=1111)
-p /= VXLAN(flags=0x8, vni=42) / Ether() / IP()
+p /= VXLAN(flags=0xC, vni=42) / Ether() / IP()
 p = Ether(raw(p))
-assert(p[VXLAN].reserved1 == 0x0)
+assert(p[VXLAN].reserved2 == 0x0)
 assert(p[VXLAN].gpid is None)
 assert(p[Ether:2].type == 0x800)
 
 = Build a VXLAN packet with group policy ID = 42
 p = Ether(dst="11:11:11:11:11:11", src="22:22:22:22:22:22")
 p /= IP(src="1.1.1.1", dst="2.2.2.2") / UDP(sport=1111)
-p /= VXLAN(flags=0x88, gpid=42, vni=42) / Ether() / IP()
+p /= VXLAN(flags=0x8C, gpid=42, vni=42) / Ether() / IP()
 p = Ether(raw(p))
 assert(p[VXLAN].gpid == 42)
 assert(p[VXLAN].reserved1 is None)
 assert(p[Ether:2].type == 0x800)
 
+= Build a VXLAN packet followed by and IP or IPv6 layer
+etherproto = 0x0
+ipproto = 0x1
+ipv6proto = 0x2
+iptest = "192.168.20.20"
+ipv6test = "659f:2c23:565:3fab:32d5:bb95:a0ed:2e3b"
+
+expkt = UDP() / VXLAN() / IP(dst=iptest) / "testing"
+expkt = UDP(bytes(expkt))
+assert(expkt[VXLAN].NextProtocol == ipproto)
+assert(IP in expkt)
+assert(expkt[IP].dst == iptest)
+
+expkt = UDP() / VXLAN() / IPv6(dst=ipv6test) / "testing"
+expkt = UDP(bytes(expkt))
+assert(expkt[VXLAN].NextProtocol == ipv6proto)
+assert(IPv6 in expkt)
+assert(expkt[IPv6].dst == ipv6test)
+
+expkt = UDP() / VXLAN(flags=0x4, NextProtocol=ipproto) / "0xfffffffffffffffffffffffffffffffffffffffffffff"
+expkt = UDP(bytes(expkt))
+assert(IP in expkt)
+
+expkt = UDP() / VXLAN(flags=0x4, NextProtocol=ipv6proto) / "0xfffffffffffffffffffffffffffffffffffffffffffff"
+expkt = UDP(bytes(expkt))
+assert(IPv6 in expkt)
+
+expkt = UDP() / VXLAN(flags=0x4, NextProtocol=etherproto) / "0xfffffffffffffffffffffffffffffffffffffffffffff"
+expkt = UDP(bytes(expkt))
+assert(Ether in expkt)
 
 ############
 ############