Repository: secdev/scapy

Issue:
Can't get correct length with BitField
This is the code.
```python
from scapy.all import *


class Test(Packet):
    name = "Test"
    fields_desc = [
        FieldLenField("BitCount", None, fmt="H", count_of="Values"),
        FieldLenField("ByteCount", None, fmt="B", length_of="Values"),
        FieldListField("Values", [], BitField("data", 0x0, size=1), count_from=lambda pkt: pkt.BitCount)
    ]

>>>packet = Test(Values=[0, 0, 0, 0, 1, 1, 1, 1])
>>>packet.show2()
###[ Test ]###
  BitCount  = 8
  ByteCount = 16
  Values    = [0L, 0L, 0L, 0L, 1L, 1L, 1L, 1L]
```

I think `ByteCount` should not be 16. So i try to direct get size from `BitField`. But the size of `BitField` is always return 2.

```python
from scapy.all import *

>>>packet = BitField("data", 0x0, size=0x8)
>>>packet.sz
2
>>>packet.i2len(packet,0x0)
2
>>>
>>>packet = BitField("data", 0x01020304, size=0x32)
>>>packet.sz
2
>>>packet.i2len(packet,0x01020304)
2
```

This is the source code of `Field` object.
```python
class Field(object):
    """For more informations on how this work, please refer to
       http://www.secdev.org/projects/scapy/files/scapydoc.pdf
       chapter ``Adding a New Field''"""
    __slots__ = ["name", "fmt", "default", "sz", "owners"]
    __metaclass__ = Field_metaclass
    islist = 0
    ismutable = False
    holds_packets = 0
    def __init__(self, name, default, fmt="H"):
        self.name = name
        if fmt[0] in "@=<>!":
            self.fmt = fmt
        else:
            self.fmt = "!"+fmt
        self.default = self.any2i(None,default)
        self.sz = struct.calcsize(self.fmt)
        self.owners = []
       ...
       ...
       ...
    def i2len(self, pkt, x):
        """Convert internal value to a length usable by a FieldLenField"""
        return self.sz
```
Since `BitField` didn't overwrite `i2len` method and "fmt", so it's will always return `struct.calcsize("!H")`

So how can i get the correct length with BitField in bit or byte? 


Discussion:

Resolving patch:
diff --git a/scapy/fields.py b/scapy/fields.py
--- a/scapy/fields.py
+++ b/scapy/fields.py
@@ -783,6 +783,8 @@ def getfield(self, pkt, s):
             return s,b
     def randval(self):
         return RandNum(0,2**self.size-1)
+    def i2len(self, pkt, x):
+        return float(self.size)/8
 
 
 class BitFieldLenField(BitField):


Test patch:
diff --git a/test/regression.uts b/test/regression.uts
--- a/test/regression.uts
+++ b/test/regression.uts
@@ -7969,6 +7969,7 @@ r1 == b'@\x04\x08\x08\x08\x08'
 r2 = b.dec(r1)[0]
 r2.val == '8.8.8.8'
 
+
 ############
 ############
 + inet.py
@@ -8113,3 +8114,22 @@ def test_IPID_count():
     assert(lines[0].endswith("Probably 3 classes: [4613, 53881, 58437]"))
 
 test_IPID_count()
+
+
+############
+############
++ Fields
+
+= FieldLenField with BitField
+class Test(Packet):
+    name = "Test"
+    fields_desc = [
+        FieldLenField("BitCount", None, fmt="H", count_of="Values"),
+        FieldLenField("ByteCount", None, fmt="B", length_of="Values"),
+        FieldListField("Values", [], BitField("data", 0x0, size=1),
+                       count_from=lambda pkt: pkt.BitCount),
+    ]
+
+pkt = Test(str(Test(Values=[0, 0, 0, 0, 1, 1, 1, 1])))
+assert(pkt.BitCount == 8)
+assert(pkt.ByteCount == 1)