77#include < debug.hh>
88// #include <fail-simulator-on-error.h>
99#include < locks.hh>
10+ #include < platform-entropy.hh>
1011#include < platform-ethernet.hh>
1112#include < timeout.h>
1213#include < timeout.hh>
@@ -93,6 +94,44 @@ namespace
9394 */
9495 using MACAddress = std::array<uint8_t , 6 >;
9596
97+ /* *
98+ * Returns the MAC address for the network interface.
99+ */
100+ MACAddress &mac_address ()
101+ {
102+ static MACAddress macAddress = []() {
103+ auto ðernet = lazy_network_interface ();
104+ if constexpr (EthernetDevice::has_unique_mac_address ())
105+ {
106+ return ethernet.mac_address_default ();
107+ }
108+ else
109+ {
110+ std::array<uint8_t , 6 > macAddress;
111+ EntropySource entropy;
112+ for (auto &byte : macAddress)
113+ {
114+ byte = entropy ();
115+ }
116+ // Set the local bit (second bit transmitted from first byte) to
117+ // 1 to indicate a locally administered MAC
118+ macAddress[0 ] |= 0b01 ;
119+ // Make sure that the broadcast bit is 0
120+ macAddress[0 ] &= ~0b1 ;
121+ ConditionalDebug<true , " Firewall" >::log (
122+ " MAC address: {}:{}:{}:{}:{}:{}" ,
123+ macAddress[0 ],
124+ macAddress[1 ],
125+ macAddress[2 ],
126+ macAddress[3 ],
127+ macAddress[4 ],
128+ macAddress[5 ]);
129+ return macAddress;
130+ }
131+ }();
132+ return macAddress;
133+ }
134+
96135 /* *
97136 * Ethernet header.
98137 */
@@ -506,6 +545,7 @@ namespace
506545
507546 bool packet_filter_ingress (const uint8_t *data, size_t length)
508547 {
548+ static constinit MACAddress broadcastMAC = {0xff , 0xff , 0xff , 0xff , 0xff , 0xff };
509549 // Not a valid Ethernet frame (64 bytes including four-byte FCS, which
510550 // is stripped by this point).
511551 if (length < 60 )
@@ -515,6 +555,19 @@ namespace
515555 }
516556 EthernetHeader *ethernetHeader =
517557 reinterpret_cast <EthernetHeader *>(const_cast <uint8_t *>(data));
558+ if ((ethernetHeader->destination != mac_address ()) &&
559+ (ethernetHeader->destination != broadcastMAC))
560+ {
561+ ConditionalDebug<true , " Firewall" >::log (
562+ " Dropping frame with destination MAC address {}:{}:{}:{}:{}:{}" ,
563+ ethernetHeader->destination [0 ],
564+ ethernetHeader->destination [1 ],
565+ ethernetHeader->destination [2 ],
566+ ethernetHeader->destination [3 ],
567+ ethernetHeader->destination [4 ],
568+ ethernetHeader->destination [5 ]);
569+ return false ;
570+ }
518571 switch (ethernetHeader->etherType )
519572 {
520573#ifdef ENABLE_IPV6
@@ -557,7 +610,9 @@ bool ethernet_driver_start()
557610 }
558611 Debug::log (" Initialising network interface" );
559612 auto ðernet = lazy_network_interface ();
560- ethernet.mac_address_set ();
613+ // If the device has a unique MAC address, use it. Otherwise, generate a
614+ // random locally administered one.
615+ ethernet.mac_address_set (mac_address ());
561616 // Poke the barrier and make the driver thread start.
562617 barrier = 2 ;
563618 barrier.notify_one ();
@@ -768,3 +823,11 @@ void firewall_remove_udpipv6_remote_endpoint(uint8_t *remoteAddress,
768823}
769824
770825#endif
826+
827+ uint8_t *firewall_mac_address_get ()
828+ {
829+ CHERI::Capability ret{mac_address ().data ()};
830+ ret.permissions () &= {CHERI::Permission::Load, CHERI::Permission::Global};
831+ ret.bounds () = 6 ;
832+ return ret;
833+ }
0 commit comments