From 7f6c35ba7a55503495c6b70cbd77dc0fc8a321c5 Mon Sep 17 00:00:00 2001 From: Dimitri Staessens Date: Thu, 27 Aug 2026 20:12:10 +0200 Subject: ipcpd: Assign random MAC on ETH poa with loopback The loopback has an all-zero MAC, so two PoAs on a loopback receive their own frames and a PoA refuses its own FLOW_REQ, failing the flow with ECONNREFUSED. The shim IPCP didn't have this problem because it ignored requests for names not registered locally (shim-data). The PoA has no "local" name registry, it uses the unicast IPCP's directory (DHT) via IRMd query requests. This fixes the issue by generating a random locally administered MAC on the loopback device. Signed-off-by: Dimitri Staessens Signed-off-by: Sander Vrijders --- src/lib/poa/eth.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'src/lib') diff --git a/src/lib/poa/eth.c b/src/lib/poa/eth.c index 5e959ef6..93ccbdfe 100644 --- a/src/lib/poa/eth.c +++ b/src/lib/poa/eth.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -316,6 +317,20 @@ static bool mac_is_zero(const uint8_t * mac) return memcmp(mac, zero, POA_MAC_SIZE) == 0; } +/* Assign a random MAC on loopback interfaces (zero MAC). */ +static int eth_dev_mac(uint8_t * mac) +{ + if (!mac_is_zero(mac)) + return 0; + + if (random_buffer(mac, POA_MAC_SIZE) < 0) + return -1; + + mac[0] = (mac[0] | 0x02) & 0xFE; + + return 0; +} + static bool eth_query_is_match(const struct eth_query * q, const struct poa * poa) { @@ -805,6 +820,9 @@ static int eth_dev_info(const char * dev, close(fd); + if (eth_dev_mac(mac) < 0) + return -EIO; + *mtu = MIN(MIN(ETH_MAX_MTU, POA_ETH_RD_BUF), (uint32_t) ifr.ifr_mtu); if (memcmp(dev, "lo", 2) == 0 && *mtu > POA_ETH_LO_MTU) *mtu = POA_ETH_LO_MTU; @@ -1405,6 +1423,9 @@ static int eth_dev_info(const char * dev, close(fd); + if (eth_dev_mac(mac) < 0) + return -1; + *mtu = MIN(MIN(ETH_MAX_MTU, POA_ETH_RD_BUF), (uint32_t) ifr.ifr_mtu); if (memcmp(dev, "lo", 2) == 0 && *mtu > POA_ETH_LO_MTU) *mtu = POA_ETH_LO_MTU; @@ -1771,6 +1792,9 @@ static int eth_dev_info(const char * dev, close(fd); + if (eth_dev_mac(mac) < 0) + return -1; + *mtu = MIN(MIN(ETH_MAX_MTU, POA_ETH_RD_BUF), (uint32_t) ifr.ifr_mtu); if (memcmp(dev, "lo", 2) == 0 && *mtu > POA_ETH_LO_MTU) *mtu = POA_ETH_LO_MTU; -- cgit v1.2.3