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>
@@ -86,6 +87,44 @@ namespace
8687 */
8788 using MACAddress = std::array<uint8_t , 6 >;
8889
90+ /* *
91+ * Returns the MAC address for the network interface.
92+ */
93+ MACAddress &mac_address ()
94+ {
95+ static MACAddress macAddress = []() {
96+ auto ðernet = lazy_network_interface ();
97+ if constexpr (EthernetDevice::has_unique_mac_address ())
98+ {
99+ return ethernet.mac_address_default ();
100+ }
101+ else
102+ {
103+ std::array<uint8_t , 6 > macAddress;
104+ EntropySource entropy;
105+ for (auto &byte : macAddress)
106+ {
107+ byte = entropy ();
108+ }
109+ // Set the local bit (second bit transmitted from first byte) to
110+ // 1 to indicate a locally administered MAC
111+ macAddress[0 ] |= 0b01 ;
112+ // Make sure that the broadcast bit is 0
113+ macAddress[0 ] &= ~0b1 ;
114+ Debug::log (
115+ " MAC address: {}:{}:{}:{}:{}:{}" ,
116+ macAddress[0 ],
117+ macAddress[1 ],
118+ macAddress[2 ],
119+ macAddress[3 ],
120+ macAddress[4 ],
121+ macAddress[5 ]);
122+ return macAddress;
123+ }
124+ }();
125+ return macAddress;
126+ }
127+
89128 /* *
90129 * Ethernet header.
91130 */
@@ -499,6 +538,7 @@ namespace
499538
500539 bool packet_filter_ingress (const uint8_t *data, size_t length)
501540 {
541+ static constinit MACAddress broadcastMAC = {0xff , 0xff , 0xff , 0xff , 0xff , 0xff };
502542 // Not a valid Ethernet frame (64 bytes including four-byte FCS, which
503543 // is stripped by this point).
504544 if (length < 60 )
@@ -508,6 +548,19 @@ namespace
508548 }
509549 EthernetHeader *ethernetHeader =
510550 reinterpret_cast <EthernetHeader *>(const_cast <uint8_t *>(data));
551+ if ((ethernetHeader->destination != mac_address ()) &&
552+ (ethernetHeader->destination != broadcastMAC))
553+ {
554+ Debug::log (
555+ " Dropping frame with destination MAC address {}:{}:{}:{}:{}:{}" ,
556+ ethernetHeader->destination [0 ],
557+ ethernetHeader->destination [1 ],
558+ ethernetHeader->destination [2 ],
559+ ethernetHeader->destination [3 ],
560+ ethernetHeader->destination [4 ],
561+ ethernetHeader->destination [5 ]);
562+ return false ;
563+ }
511564 switch (ethernetHeader->etherType )
512565 {
513566#ifdef ENABLE_IPV6
@@ -550,7 +603,9 @@ bool ethernet_driver_start()
550603 }
551604 Debug::log (" Initialising network interface" );
552605 auto ðernet = lazy_network_interface ();
553- ethernet.mac_address_set ();
606+ // If the device has a unique MAC address, use it. Otherwise, generate a
607+ // random locally administered one.
608+ ethernet.mac_address_set (mac_address ());
554609 // Poke the barrier and make the driver thread start.
555610 barrier = 2 ;
556611 barrier.notify_one ();
@@ -761,3 +816,11 @@ void firewall_remove_udpipv6_remote_endpoint(uint8_t *remoteAddress,
761816}
762817
763818#endif
819+
820+ uint8_t *firewall_mac_address_get ()
821+ {
822+ CHERI::Capability ret{mac_address ().data ()};
823+ ret.permissions () &= {CHERI::Permission::Load, CHERI::Permission::Global};
824+ ret.bounds () = 6 ;
825+ return ret;
826+ }
0 commit comments