Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect Unpacking of Ethernet Frames with VLAN ETH_TYPE_8021Q Tag #658

Open
perjah20 opened this issue Nov 12, 2023 · 0 comments
Open

Comments

@perjah20
Copy link

perjah20 commented Nov 12, 2023

It is my first time creating an issue on Github so if I've done anything incorrectly I apologize in advance.

Describe the bug
I have encountered an issue with the dpkt package related to handling VLAN tagged frames in Ethernet packets. Specifically, the issue arises when packing and then unpacking an Ethernet frame with VLAN ETH_TYPE_8021Q tags. The unpacked frame does not maintain the same structure and data as it had before being packed, indicating a potential bug in the handling of VLAN tags during these processes.

To Reproduce
I've written 3 test cases in python that can be used to look and see where the discrepancies are.
The first two sets the "type" of the ethernet frame to ETH_TYPE_8021Q .
The third test sets the "type" to ETH_TYPE_IP. This result in the unpacking I would like to see in the first two experiments.

Expected behavior
The byte string should be the same, and it should not create two VLAN tags.

Screenshots
Here is a screenshot of the output in the console. I've highlighted the inconsistencies in yellow.
First and second experiment:
image
Third experiment:
image

Details(please complete the following information):

  • OS: Windows10
  • Python Version: 3.8.10

Code to reproduce
`

import unittest
import dpkt

class EthernetExperiment(unittest.TestCase):
    def test_experiment_1(self):
        # Create an Ethernet object
        eth = dpkt.ethernet.Ethernet(
        src = b'\x01\x02\x03\x04\x05\x06',
        dst = b'\x01\x02\x03\x04\x05\x06',
        type = dpkt.ethernet.ETH_TYPE_8021Q,
    )

    # Create a VLAN tagged frame (802.1Q)
    vlan = dpkt.ethernet.VLANtag8021Q()
    vlan.pri = 7  # Priority
    vlan.id = 10  # VLAN ID
    vlan.type = dpkt.ethernet.ETH_TYPE_8021Q  # Encapsulated protocol type

    data = b'\x01\x02\x03\x04\x05\x06'
    eth.vlan_tags = [vlan]
    eth.data = data

    print(f"Ethernet frame (before packing):\n"
          f"Bytes: {str(eth)}\n"
          f"Object: {repr(eth)}\n")

    # Get the packed Ethernet frame bytes
    eth_bytes = eth.pack()
    print(f"Ethernet frame (after packing):\n {eth_bytes}\n")

    # Unpack the Ethernet frame
    eth_unpacked = dpkt.ethernet.Ethernet(eth_bytes)
    print(f"Ethernet frame (after unpacking):\n"
          f"Bytes: {str(eth_unpacked)}\n"
          f"Object: {repr(eth_unpacked)}\n")

    self.assertEqual(str(eth_unpacked), str(eth))

def test_experiment_2(self):
    # Create an Ethernet object
    eth = dpkt.ethernet.Ethernet(
        src = b'\x01\x02\x03\x04\x05\x06',
        dst = b'\x01\x02\x03\x04\x05\x06',
        type = dpkt.ethernet.ETH_TYPE_8021Q,
    )

    # Create a VLAN tagged frame (802.1Q)
    vlan = dpkt.ethernet.VLANtag8021Q()
    vlan.pri = 7
    vlan.id = 10
    vlan.type = dpkt.ethernet.ETH_TYPE_8021Q

    data = b'\x01\x02\x03\x04\x05\x06'
    eth.data = vlan.pack() + data

    print(f"Ethernet frame (before packing):\n"
          f"Bytes: {str(eth)}\n"
          f"Object: {repr(eth)}\n")

    # Get the packed Ethernet frame bytes
    eth_bytes = eth.pack()
    print(f"Ethernet frame (after packing):\n {eth_bytes}\n")

    # Unpack the Ethernet frame
    eth_unpacked = dpkt.ethernet.Ethernet(eth_bytes)
    print(f"Ethernet frame (after unpacking):\n"
          f"Bytes: {str(eth_unpacked)}\n"
          f"Object: {repr(eth_unpacked)}\n")

    self.assertEqual(str(eth_unpacked), str(eth))

def test_experiment_3(self):
    # Create an Ethernet object
    eth = dpkt.ethernet.Ethernet(
        src=b'\x01\x02\x03\x04\x05\x06',
        dst=b'\x01\x02\x03\x04\x05\x06',
        type=dpkt.ethernet.ETH_TYPE_IP,
    )

    # Create a VLAN tagged frame (802.1Q)
    vlan = dpkt.ethernet.VLANtag8021Q()
    vlan.pri = 7
    vlan.id = 10
    vlan.type = dpkt.ethernet.ETH_TYPE_8021Q

    data = b'\x01\x02\x03\x04\x05\x06'
    eth.vlan_tags = [vlan]
    eth.data = data

    print(f"Ethernet frame (before packing):\n"
          f"Bytes: {str(eth)}\n"
          f"Object: {repr(eth)}\n")

    # Get the packed Ethernet frame bytes
    eth_bytes = eth.pack()
    print(f"Ethernet frame (after packing):\n {eth_bytes}\n")

    # Unpack the Ethernet frame
    eth_unpacked = dpkt.ethernet.Ethernet(eth_bytes)
    print(f"Ethernet frame (after unpacking):\n"
          f"Bytes: {str(eth_unpacked)}\n"
          f"Object: {repr(eth_unpacked)}\n")

    self.assertEqual(str(eth_unpacked), str(eth))

`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant