Repository: secdev/scapy

Issue:
Bind ARPHRD_NONE to IPv46 protocol layer
Scapy L2Socket uses a 3-step process to determine the layer to be used for decoding the packets captured on a given interface:
* it checks the Ethernet protocol number (`sa_ll[3]`);
* if no L2 layer is bound to the Ethernet protocol number, it uses the ARP hardware address type (`sa_ll[1]`);
* if no L3 layer is bound to the ARP hardware address type, it fallbacks to using the default L2 layer.

https://github.com/secdev/scapy/blob/a1f999fb1721a64415af75d575cabde19625a6f5/scapy/arch/linux.py#L531-L541

Some Linux interfaces operate at layer 3. The packets captured on these interfaces have no link-layer header. For these interfaces, the protocol number (`sa_ll[3]`) is `ARPHRD_NONE`.

In the current implementation of Scapy, the `ARPHRD_NONE` protocol number is not bound to any layer. This can cause packets captured on interfaces with protocol number `ARPHRD_NONE` to be delivered to the wrong layer and decoded incorrectly.

For example, Wireguard interfaces are `ARPHRD_NONE` devices that operate at layer 3. Scapy delivers the IPv4 and IPv6 packets captured on a Wireguard interface to the IPv4 layer.

This PR binds the `ARPHRD_NONE` protocol number to the `IPv46` layer. This way, Scapy can deliver the IP packets to the IPv4 or IPv6 layer depending on the `version` field of the IP header.

Signed-off-by: Carmine Scarpitta <carmine.scarpitta@uniroma2.it>


Discussion:
# [Codecov](https://codecov.io/gh/secdev/scapy/pull/3751?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=secdev) Report
> Merging [#3751](https://codecov.io/gh/secdev/scapy/pull/3751?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=secdev) (38d8075) into [master](https://codecov.io/gh/secdev/scapy/commit/a1f999fb1721a64415af75d575cabde19625a6f5?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=secdev) (a1f999f) will **increase** coverage by `0.00%`.
> The diff coverage is `100.00%`.

```diff
@@           Coverage Diff           @@
##           master    #3751   +/-   ##
=======================================
  Coverage   86.05%   86.05%           
=======================================
  Files         301      301           
  Lines       68341    68342    +1     
=======================================
+ Hits        58814    58815    +1     
  Misses       9527     9527           
```

| [Impacted Files](https://codecov.io/gh/secdev/scapy/pull/3751?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=secdev) | Coverage Δ | |
|---|---|---|
| [scapy/layers/inet6.py](https://codecov.io/gh/secdev/scapy/pull/3751/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=secdev#diff-c2NhcHkvbGF5ZXJzL2luZXQ2LnB5) | `88.02% <100.00%> (+<0.01%)` | :arrow_up: |
| [scapy/arch/windows/\_\_init\_\_.py](https://codecov.io/gh/secdev/scapy/pull/3751/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=secdev#diff-c2NhcHkvYXJjaC93aW5kb3dzL19faW5pdF9fLnB5) | `67.16% <0.00%> (-0.56%)` | :arrow_down: |
| [scapy/automaton.py](https://codecov.io/gh/secdev/scapy/pull/3751/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=secdev#diff-c2NhcHkvYXV0b21hdG9uLnB5) | `74.15% <0.00%> (+0.11%)` | :arrow_up: |
| [scapy/supersocket.py](https://codecov.io/gh/secdev/scapy/pull/3751/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=secdev#diff-c2NhcHkvc3VwZXJzb2NrZXQucHk=) | `58.68% <0.00%> (+0.29%)` | :arrow_up: |
| [scapy/contrib/automotive/ecu.py](https://codecov.io/gh/secdev/scapy/pull/3751/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=secdev#diff-c2NhcHkvY29udHJpYi9hdXRvbW90aXZlL2VjdS5weQ==) | `94.66% <0.00%> (+0.33%)` | :arrow_up: |

I'm not sure to understand, there seems to be what I understand as an inconsistency between `ARPHRD_*` values and `DLT_*` values. Shouldn't we use the `data.ARPHRD_TO_DLT` object?

Resolving patch:
diff --git a/scapy/layers/inet6.py b/scapy/layers/inet6.py
--- a/scapy/layers/inet6.py
+++ b/scapy/layers/inet6.py
@@ -27,8 +27,15 @@
 from scapy.compat import chb, orb, raw, plain_str, bytes_encode
 from scapy.consts import WINDOWS
 from scapy.config import conf
-from scapy.data import DLT_IPV6, DLT_RAW, DLT_RAW_ALT, ETHER_ANY, ETH_P_IPV6, \
-    MTU
+from scapy.data import (
+    DLT_IPV6,
+    DLT_RAW,
+    DLT_RAW_ALT,
+    ETHER_ANY,
+    ETH_P_ALL,
+    ETH_P_IPV6,
+    MTU,
+)
 from scapy.error import log_runtime, warning
 from scapy.fields import BitEnumField, BitField, ByteEnumField, ByteField, \
     DestIP6Field, FieldLenField, FlagsField, IntField, IP6Field, \
@@ -4071,6 +4078,7 @@ def _load_dict(d):
 #############################################################################
 
 conf.l3types.register(ETH_P_IPV6, IPv6)
+conf.l3types.register_num2layer(ETH_P_ALL, IPv46)
 conf.l2types.register(31, IPv6)
 conf.l2types.register(DLT_IPV6, IPv6)
 conf.l2types.register(DLT_RAW, IPv46)


Test patch: