]> git.ipfire.org Git - network.git/commitdiff
networkd: Generate a random Ethernet address for ports
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 11 Feb 2023 12:01:42 +0000 (12:01 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 11 Feb 2023 12:01:42 +0000 (12:01 +0000)
This happens when either no address was set, or it cannot be parsed.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/networkd/address.h
src/networkd/port.c

index 1d9fbfc955436f27aac01f51140e0fdbe81d256e..f875b26102edc0d0afa8826dba9ee6ae742fd6cd 100644 (file)
@@ -23,6 +23,9 @@
 
 #include <netinet/ether.h>
 #include <string.h>
+#include <sys/random.h>
+
+#include "logging.h"
 
 typedef struct ether_addr nw_address_t;
 
@@ -44,4 +47,26 @@ static inline char* nw_address_to_string(const nw_address_t* addr) {
        return strdup(buffer);
 }
 
+static inline int nw_address_generate(nw_address_t* addr) {
+       ssize_t bytes = getrandom(addr, sizeof(*addr), 0);
+       if (bytes < 0) {
+               ERROR("getrandom() failed: %m\n");
+               return 1;
+       }
+
+       // Check if we filled the entire buffer
+       if (bytes < (ssize_t)sizeof(*addr)) {
+               ERROR("Could not gather enough randomness\n");
+               return 1;
+       }
+
+       // Clear the multicast bit
+       addr->ether_addr_octet[0] &= 0xfe;
+
+       // Set the software-generated bit
+       addr->ether_addr_octet[1] |= 0x02;
+
+       return 0;
+}
+
 #endif /* NETWORKD_ADDRESS_H */
index aff79a532a46bd35cdfdf16200298797539343ae..4c325924c0806fc3a012cdca68b39f101f51fdba 100644 (file)
@@ -75,18 +75,28 @@ static int nw_port_setup_address(struct nw_port* port) {
        const char* s = nw_config_get(port->config, "ADDRESS");
        if (!s) {
                ERROR("Port %s: Address isn't set\n", port->name);
-               return 1;
+               goto ERROR;
        }
 
        // Parse the address
        r = nw_address_from_string(&port->address, s);
        if (r) {
                ERROR("Port %s: Could not parse address: %m\n", port->name);
-               return r;
+               goto ERROR;
        }
 
        // XXX Do we need to check for multicast here?
 
+       return 0;
+
+ERROR:
+       // Generate a random Ethernet address
+       r = nw_address_generate(&port->address);
+       if (r) {
+               ERROR("Could not generate a random Ethernet address: %m\n");
+               return r;
+       }
+
        return 0;
 }