#5078·scapy

`rt_msghdr`s are misprased on FreeBSD (32-bit)

Author: evverxCreated Aug 8, 2026Updated Sep 1, 2026
Labelsplatform-specific

Brief description

read_routes() and read_routes6() return the automatically added multicast routes (224/4 and ff00::/8) only.

Scapy version

d8f7b272b1eb3e989920ba2a84bbae1a847660bd

Python version

3.12.13

Operating system

FreeBSD 14.4-RELEASE i386

Additional environment information

I went with the following quick fix for now

diff
--- a/scapy/arch/bpf/pfroute.py
+++ b/scapy/arch/bpf/pfroute.py
@@ -779,18 +779,18 @@ else:
 
     class rt_metrics(Packet):
         fields_desc = [
-            Field("rmx_locks", 0, fmt="=Q"),
-            Field("rmx_mtu", 0, fmt="=Q"),
-            Field("rmx_hopcount", 0, fmt="=Q"),
-            Field("rmx_expire", 0, fmt="=Q"),
-            Field("rmx_recvpipe", 0, fmt="=Q"),
-            Field("rmx_sendpipe", 0, fmt="=Q"),
-            Field("rmx_sshthresh", 0, fmt="=Q"),
-            Field("rmx_rtt", 0, fmt="=Q"),
-            Field("rmx_rttvar", 0, fmt="=Q"),
-            Field("rmx_pksent", 0, fmt="=Q"),
-            Field("rmx_weight", 0, fmt="=Q"),
-            Field("rmx_nhidx", 0, fmt="=Q"),
+            Field("rmx_locks", 0, fmt="@L"),
+            Field("rmx_mtu", 0, fmt="@L"),
+            Field("rmx_hopcount", 0, fmt="@L"),
+            Field("rmx_expire", 0, fmt="@L"),
+            Field("rmx_recvpipe", 0, fmt="@L"),
+            Field("rmx_sendpipe", 0, fmt="@L"),
+            Field("rmx_sshthresh", 0, fmt="@L"),
+            Field("rmx_rtt", 0, fmt="@L"),
+            Field("rmx_rttvar", 0, fmt="@L"),
+            Field("rmx_pksent", 0, fmt="@L"),
+            Field("rmx_weight", 0, fmt="@L"),
+            Field("rmx_nhidx", 0, fmt="@L"),
             StrFixedLenField("rmx_filler", 0, length=16 if IS_64BITS else 8),
         ]
 
@@ -921,7 +921,7 @@ else:
             Field("rtm_seq", 0, fmt="=I"),
             Field("rtm_errno", 0, fmt="=I"),
             Field("rtm_fmask", 0, fmt="=I"),
-            Field("rtm_inits", 0, fmt="=Q"),
+            Field("rtm_inits", 0, fmt="@L"),
             PadField(
                 PacketField("rtm_rmx", rt_metrics(), rt_metrics),
                 8,

but since it uses the native size it isn't compatible with the regression tests.

bytes.hex(zlib.compress(...)) with AF_INET for the read_routes test:

bash
789cbbc2c0cac2c8c0c0c0ccc1c060ce801bdc61c523090520735890f8024ca8f2203e170313132e790b21460636663686d45c030e06f59e951f095b896c2e3f8c7f05ea27460601aaf809d99950bb107c909bd1e4ffffff0fe753cb4f47807e02d9caca21c0608c4fa30361b3c1f18dc72e743f59083131480035e4e41b10e97a84b9f510ebc000ee0706eaf88111898f6e9700c8cd48f2d4f20300c7d3174f

bytes.hex(zlib.compress(...)) with AF_INET6 for the read_routes6 test:

bash
789ce5953f0e823014c6bf963fa21371d181ddd5c401460ee264e2a6f10a1ec08b780b0fe221747311e405d0526a4b2212894d9a40dfd7fefafabeb436736c0e60e80121342dd605f3c6b23e10fe83e0bdf64d8c89b15468a5201a734c2d60b39b9b37d490676767401fd9b2da33383b660eade39ab99558b2af0c736698178d195ccbc57a3bf7303b1cafe66d297923ccd2249b4ebc33721f389e8f856e91d8cc614597b90a197caaa730f8adfa76e7f197577fc9e337e41e67f05bf1b8282bb9f7c96a7909c145ad4f5e5568e59ca9f5c1d7b6825be65d72694ccebbafbe96ee26e39e9ef53dd5057df5b57c06a4fb075fabb85df8fa56e466aa69d3dc2c0557ae29f1e4b7485fd3cff296f88cf86dd754bc8875dcb6df6015a38bbb2ae5756db337b82ef886af1f8e4c93c2

The output of _get_if_list()

bash
{1: {'flags': <Flag 34883 (UP+BROADCAST+DRV_RUNNING+SIMPLEX+MULTICAST)>,
     'index': 1,
     'ips': [{'address': 'fe80::a00:27ff:fe8c:a9f1',
              'af_family': 28,
              'index': 1,
              'scope': 32},
             {'address': 'fd17:625c:f037:2:a00:27ff:fe8c:a9f1',
              'af_family': 28,
              'index': 1,
              'scope': 0},
             {'address': '10.0.2.15', 'af_family': 2, 'index': 1}],
     'mac': '08:00:27:8c:a9:f1',
     'name': 'em0',
     'type': 6},
 2: {'flags': <Flag 32841 (UP+LOOPBACK+DRV_RUNNING+MULTICAST)>,
     'index': 2,
     'ips': [{'address': '::1', 'af_family': 28, 'index': 2, 'scope': 16},
             {'address': 'fe80::1', 'af_family': 28, 'index': 2, 'scope': 32},
             {'address': '127.0.0.1', 'af_family': 2, 'index': 2}],
     'mac': '00:00:00:00:00:00',
     'name': 'lo0',
     'type': 24}}

How to reproduce

It can be reproduced by running scapy on a 32-bit FreeBSD machine and printing conf.route.

Actual result

python
>>> conf.route
Network    Netmask    Gateway  Iface  Output IP      Metric
224.0.0.0  240.0.0.0  0.0.0.0  em0    10.0.2.15      250   
224.0.0.0  240.0.0.0  0.0.0.0  em1    192.168.56.20  250   
224.0.0.0  240.0.0.0  0.0.0.0  lo0    127.0.0.1      250

Expected result

python
>>> conf.route
Network        Netmask          Gateway   Iface  Output IP      Metric
0.0.0.0        0.0.0.0          10.0.2.2  em0    10.0.2.15      1     
10.0.2.0       255.255.255.0    0.0.0.0   em0    10.0.2.15      1     
10.0.2.15      255.255.255.255  0.0.0.0   lo0    127.0.0.1      1     
127.0.0.1      255.255.255.255  0.0.0.0   lo0    127.0.0.1      1     
192.168.56.0   255.255.255.0    0.0.0.0   em1    192.168.56.20  1     
192.168.56.20  255.255.255.255  0.0.0.0   lo0    127.0.0.1      1     
224.0.0.0      240.0.0.0        0.0.0.0   em0    10.0.2.15      250   
224.0.0.0      240.0.0.0        0.0.0.0   em1    192.168.56.20  250   
224.0.0.0      240.0.0.0        0.0.0.0   lo0    127.0.0.1      250 

Related resources

No response