Repository: secdev/scapy

Issue:
[Bug] GENEVE.post_build() compute 'optionlen' incorrect
### Brief description

GENEVE.post_build() compute 'optionlen' incorrect.

I found that 'optionlen' always incorrect, when I implement class `GeneveOptINT` for (In-band Network Telemetry (INT)),.

Finally I found that `BitField("optionlen", None, 6)` the 'optionlen' is a 6bits field,
The tmp_len mask should be 0x3f instead of 0x2f.

1.Current Implement:
```Python
class GENEVE(Packet):
    def post_build(self, p, pay):
        if self.optionlen is None:
            tmp_len = (len(p) - 8) // 4
            p = chb(tmp_len & 0x2f | orb(p[0]) & 0xc0) + p[1:]
        return p + pay
```

2.Fixed method:
```Python
class GENEVE(Packet):
    def post_build(self, p, pay):
        if self.optionlen is None:
            tmp_len = (len(p) - 8) // 4
            p = chb(tmp_len & 0x3f | orb(p[0]) & 0xc0) + p[1:]
        return p + pay
```


### Scapy version

2.5.0

### Python version

3.7

### Operating system

Linux 5.10.27-051027-generic

### Additional environment information

_No response_

### How to reproduce

```
hujf@4c4c2fcab3ca:/usr/lib/python3/dist-packages$ sudo scapy
>>> from scapy.contrib.geneve import *
>>> data_str='1111222233334444555566667777888899990000aaaabbbbccccddddeeeeffff'
>>> GENEVE(raw(GENEVE(options=GeneveOptions(data=data_str))))[GENEVE].optionlen
1
```

### Actual result

```
hujf@4c4c2fcab3ca:/usr/lib/python3/dist-packages$ sudo scapy
>>> from scapy.contrib.geneve import *
>>> data_str='1111222233334444555566667777888899990000aaaabbbbccccddddeeeeffff'
>>> GENEVE(raw(GENEVE(options=GeneveOptions(data=data_str))))[GENEVE].optionlen
1
```

### Expected result

```
hujf@a7a04dccbbb8:/localdata/hujf/asic-cosim$ sudo scapy
>>> from scapy.contrib.geneve import *
>>> data_str='1111222233334444555566667777888899990000aaaabbbbccccddddeeeeffff'
>>> GENEVE(raw(GENEVE(options=GeneveOptions(data=data_str))))[GENEVE].optionlen
17
>>> 
```

### Related resources

_No response_


Discussion:
Hi there,
Two questions:
- do you have a link to a documentation and/or (reference) implementation that supports your report?
- if so, would you like to create a pull request (since you already did all the work)?


Resolving patch:
diff --git a/scapy/contrib/geneve.py b/scapy/contrib/geneve.py
--- a/scapy/contrib/geneve.py
+++ b/scapy/contrib/geneve.py
@@ -66,7 +66,7 @@ class GENEVE(Packet):
     def post_build(self, p, pay):
         if self.optionlen is None:
             tmp_len = (len(p) - 8) // 4
-            p = chb(tmp_len & 0x2f | orb(p[0]) & 0xc0) + p[1:]
+            p = chb(tmp_len & 0x3f | orb(p[0]) & 0xc0) + p[1:]
         return p + pay
 
     def answers(self, other):


Test patch:
diff --git a/test/contrib/geneve.uts b/test/contrib/geneve.uts
--- a/test/contrib/geneve.uts
+++ b/test/contrib/geneve.uts
@@ -66,3 +66,9 @@ a = GENEVE(proto=0x0800)/b'E\x00\x00\x1c\x00\x01\x00\x00@\x01\xfa$\xc0\xa8\x00w\
 a = GENEVE(raw(a))
 assert a.summary() == 'GENEVE / IP / ICMP 192.168.0.119 > 172.217.18.195 echo-request 0'
 assert a.mysummary() in ['GENEVE (vni=0x0,optionlen=0,proto=0x800)', 'GENEVE (vni=0x0,optionlen=0,proto=IPv4)']
+
+= GENEVE - Optionlen
+
+data = raw(RandString(size=random.randint(0, pow(2, 6)) * 4))
+p = GENEVE(raw(GENEVE(options=GeneveOptions(data=data))))
+assert p[GENEVE].optionlen == (len(data) // 4 + 1)