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

[Enhancement] Split multiple SOME/IP messages from a single TCP/UDP packet. #4608

Open
sfaiss opened this issue Dec 11, 2024 · 0 comments
Open

Comments

@sfaiss
Copy link

sfaiss commented Dec 11, 2024

Brief description

As discussed in #4144, the SOME/IP specification allows to transmit multiple SOME/IP messages in a single TCP/UDP packet:

[PRS_SOMEIP_00535]
All Transport Protocol Bindings shall support transporting more than one SOME/IP
message in a Transport Layer PDU (i.e. UDP packet or TCP segment).

[PRS_SOMEIP_00140]
The header format allows transporting more than one SOME/IP message in a single
packet. The SOME/IP implementation shall identify the end of a SOME/IP message by
means of the SOME/IP length field. Based on the packet length field, SOME/IP shall
determine if there are additional SOME/IP messages in the packet. This shall apply for
UDP and TCP transport.

The end of each message is based on its Length field:

image

[PRS_SOMEIP_00042]
Length field shall contain the length in Byte starting from Request ID/Client ID until
the end of the SOME/IP message.

The current implementation of Scapy only interprets the first SOME/IP message, putting all additional messages in the payload of the first one. Please consider splitting them up according to the specification.

Scapy version

2.6.1

Python version

3.11.2

Operating system

Windows 11

Additional environment information

No response

How to reproduce

The following snippet constructs a full ethernet frame with dummy data. Its UDP payload contains three individual SOME/IP messages. They are nested in a way that the current Scapy implementation sees them as a single message. This matches the structure of real data.

payload_3 = bytes.fromhex("deadbeef")
someip_3 = SOMEIP(srv_id=0xabcd, sub_id=0x8001, len=8 + len(payload_3))
someip_3.payload = Raw(load=payload_3)

payload_2 = bytes.fromhex("ff")
someip_23 = SOMEIP(srv_id=0x5678, sub_id=0x8002, len=8 + len(payload_2))
someip_23.payload = Raw(load=payload_2 + bytes(someip_3))

payload_1 = bytes.fromhex("0000")
someip_123 = SOMEIP(srv_id=0x1234, sub_id=0x8001, len=8 + len(payload_1))
someip_123.payload = Raw(load=payload_1 + bytes(someip_23))

eth_frame = (
    Ether(src="00:11:22:33:44:55", dst="AA:BB:CC:DD:EE:FF")
    / IP(src="192.168.0.10", dst="192.168.0.20")
    / UDP(sport=30501, dport=30491)
    / someip_123
)

Actual result

eth_frame.show() shows only a single SOME/IP message:

###[ Ethernet ]###
  dst       = AA:BB:CC:DD:EE:FF
  src       = 00:11:22:33:44:55
  type      = IPv4
###[ IP ]###
     version   = 4
     ihl       = None
     tos       = 0x0
     len       = None
     id        = 1
     flags     = 
     frag      = 0
     ttl       = 64
     proto     = udp
     chksum    = None
     src       = 192.168.0.10
     dst       = 192.168.0.20
     \options   \
###[ UDP ]###
        sport     = 30501
        dport     = 30491
        len       = None
        chksum    = None
###[ SOME/IP ]###
           srv_id    = 0x1234
           sub_id    = 0x8001 (event_id)
           len       = 10
           client_id = 0x0
           session_id= 0x0
           proto_ver = 0x1
           iface_ver = 0x1
           msg_type  = REQUEST
           retcode   = E_OK
###[ Raw ]###
              load      = b'\x00\x00Vx\x80\x02\x00\x00\x00\t\x00\x00\x00\x00\x01\x01\x00\x00\xff\xab\xcd\x80\x01\x00\x00\x00\x0c\x00\x00\x00\x00\x01\x01\x00\x00\xde\xad\xbe\xef'

The other two messages are hidden inside the payload of the first message:

image

Expected result

All three SOME/IP messages should be shown individually:

###[ Ethernet ]###
  dst       = AA:BB:CC:DD:EE:FF
  src       = 00:11:22:33:44:55
  type      = IPv4
###[ IP ]###
     version   = 4
     ihl       = None
     tos       = 0x0
     len       = None
     id        = 1
     flags     =
     frag      = 0
     ttl       = 64
     proto     = udp
     chksum    = None
     src       = 192.168.0.10
     dst       = 192.168.0.20
     \options   \
###[ UDP ]###
        sport     = 30501
        dport     = 30491
        len       = None
        chksum    = None
###[ SOME/IP #1 ]###
            srv_id    = 0x1234
            sub_id    = 0x8001 (event_id)
            len       = 10
            client_id = 0x0
            session_id= 0x0
            proto_ver = 0x1
            iface_ver = 0x1
            msg_type  = REQUEST
            retcode   = E_OK
###[ Raw ]###
                load      = b'\x00\x00'
###[ SOME/IP #2 ]###
            srv_id    = 0x4567
            sub_id    = 0x8002 (event_id)
            len       = 9
            client_id = 0x0
            session_id= 0x0
            proto_ver = 0x1
            iface_ver = 0x1
            msg_type  = REQUEST
            retcode   = E_OK
###[ Raw ]###
                load      = b'\xff'
###[ SOME/IP #3 ]###
            srv_id    = 0xabcd
            sub_id    = 0x8001 (event_id)
            len       = 12
            client_id = 0x0
            session_id= 0x0
            proto_ver = 0x1
            iface_ver = 0x1
            msg_type  = REQUEST
            retcode   = E_OK
###[ Raw ]###
                load      = b'\xde\xad\xbe\xef'

Related resources

Protocol Specification: https://www.autosar.org/fileadmin/standards/R24-11/FO/AUTOSAR_FO_PRS_SOMEIPProtocol.pdf

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