config: parse default mac address from board.json
authorFelix Fietkau <nbd@nbd.name>
Mon, 30 Nov 2020 11:34:13 +0000 (12:34 +0100)
committerFelix Fietkau <nbd@nbd.name>
Mon, 30 Nov 2020 11:39:25 +0000 (12:39 +0100)
Example:
{
"network-device": {
"eth0": {
"macaddr": "bc:a5:11:16:76:d7"
}
}
}

Signed-off-by: Felix Fietkau <nbd@nbd.name>
config.c
config.h
config/board.json [new file with mode: 0644]
device.c
device.h
interface-ip.c
macvlan.c
netifd.h
system-dummy.c
system-linux.c
veth.c

index d91830c8a931917239a3502a4f256674cfad2627..fa7cbe42052d28b37ffd797fb263e35537da3d2c 100644 (file)
--- a/config.c
+++ b/config.c
@@ -18,6 +18,8 @@
 
 #include <uci.h>
 
+#include <libubox/blobmsg_json.h>
+
 #include "netifd.h"
 #include "interface.h"
 #include "interface-ip.h"
@@ -31,6 +33,7 @@ bool config_init = false;
 static struct uci_context *uci_ctx;
 static struct uci_package *uci_network;
 static struct uci_package *uci_wireless;
+static struct blob_attr *board_netdevs;
 static struct blob_buf b;
 
 static int
@@ -654,6 +657,57 @@ config_init_wireless(void)
        }
 }
 
+
+static struct blob_attr *
+config_find_blobmsg_attr(struct blob_attr *attr, const char *name, int type)
+{
+       struct blobmsg_policy policy = { .name = name, .type = type };
+       struct blob_attr *cur;
+
+       blobmsg_parse(&policy, 1, &cur, blobmsg_data(attr), blobmsg_len(attr));
+
+       return cur;
+}
+
+struct ether_addr *config_get_default_macaddr(const char *ifname)
+{
+       struct blob_attr *cur;
+
+       if (!board_netdevs)
+               return NULL;
+
+       cur = config_find_blobmsg_attr(board_netdevs, ifname, BLOBMSG_TYPE_TABLE);
+       if (!cur)
+               return NULL;
+
+       cur = config_find_blobmsg_attr(cur, "macaddr", BLOBMSG_TYPE_STRING);
+       if (!cur)
+               return NULL;
+
+       return ether_aton(blobmsg_get_string(cur));
+}
+
+static void
+config_init_board(void)
+{
+       struct blob_attr *cur;
+
+       blob_buf_init(&b, 0);
+
+       if (!blobmsg_add_json_from_file(&b, DEFAULT_BOARD_JSON))
+               return;
+
+       free(board_netdevs);
+       board_netdevs = NULL;
+
+       cur = config_find_blobmsg_attr(b.head, "network-device",
+                                      BLOBMSG_TYPE_TABLE);
+       if (!cur)
+               return;
+
+       board_netdevs = blob_memdup(cur);
+}
+
 int
 config_init_all(void)
 {
@@ -676,6 +730,8 @@ config_init_all(void)
                ret = -1;
        }
 
+       config_init_board();
+
        vlist_update(&interfaces);
        config_init = true;
        device_lock();
index fae7cd8046474f8af2bcc7fb64b7078a1574d7f2..ae77ed11e11c2e67bf2660ec87810f8f51ff636f 100644 (file)
--- a/config.h
+++ b/config.h
@@ -20,5 +20,6 @@
 extern bool config_init;
 
 int config_init_all(void);
+struct ether_addr *config_get_default_macaddr(const char *ifname);
 
 #endif
diff --git a/config/board.json b/config/board.json
new file mode 100644 (file)
index 0000000..112a511
--- /dev/null
@@ -0,0 +1,52 @@
+{
+    "model": {
+        "id": "netgear,gs110tpp-v1",
+        "name": "Netgear GS110TPP"
+    },
+    "bridge": {
+        "name": "switch",
+        "macaddr": "bc:a5:11:16:76:d7"
+    },
+    "network": {
+        "wan": {
+            "ifname": " lan1 lan2 lan3 lan4 lan5 lan6 lan7 lan8",
+            "protocol": "dhcp",
+            "macaddr": "bc:a5:11:16:76:d7"
+        },
+        "lan": {
+            "ifname": "lan1",
+            "protocol": "static",
+            "vlan": "100",
+            "macaddr": "be:a5:11:16:76:d7"
+        }
+    },
+    "network-device": {
+        "eth0": {
+            "macaddr": "bc:a5:11:16:76:d7"
+        },
+        "lan1": {
+            "macaddr": "be:a5:11:16:76:d7"
+        },
+        "lan2": {
+            "macaddr": "be:a5:11:16:76:d8"
+        },
+        "lan3": {
+            "macaddr": "be:a5:11:16:76:d9"
+        },
+        "lan4": {
+            "macaddr": "be:a5:11:16:76:da"
+        },
+        "lan5": {
+            "macaddr": "be:a5:11:16:76:db"
+        },
+        "lan6": {
+            "macaddr": "be:a5:11:16:76:dc"
+        },
+        "lan7": {
+            "macaddr": "be:a5:11:16:76:dd"
+        },
+        "lan8": {
+            "macaddr": "be:a5:11:16:76:de"
+        }
+    }
+}
index 627f1a244649e380aaf1d8acae91a8aab13a036a..73cc4bfebd17253dced948a1b985f9d8928878e1 100644 (file)
--- a/device.c
+++ b/device.c
 
 #include <sys/types.h>
 #include <sys/socket.h>
-#include <net/ethernet.h>
-
-#ifdef linux
-#include <netinet/ether.h>
-#endif
 
 #include <libubox/list.h>
 
@@ -232,7 +227,7 @@ device_merge_settings(struct device *dev, struct device_settings *n)
        n->txqueuelen = s->flags & DEV_OPT_TXQUEUELEN ?
                s->txqueuelen : os->txqueuelen;
        memcpy(n->macaddr,
-               (s->flags & DEV_OPT_MACADDR ? s->macaddr : os->macaddr),
+               (s->flags & (DEV_OPT_MACADDR|DEV_OPT_DEFAULT_MACADDR) ? s->macaddr : os->macaddr),
                sizeof(n->macaddr));
        n->ipv6 = s->flags & DEV_OPT_IPV6 ? s->ipv6 : os->ipv6;
        n->promisc = s->flags & DEV_OPT_PROMISC ? s->promisc : os->promisc;
@@ -430,6 +425,21 @@ void device_broadcast_event(struct device *dev, enum device_event ev)
        safe_list_for_each(&dev->users, device_broadcast_cb, &dev_ev);
 }
 
+static void
+device_fill_default_settings(struct device *dev)
+{
+       struct device_settings *s = &dev->settings;
+       struct ether_addr *ea;
+
+       if (!(s->flags & DEV_OPT_MACADDR)) {
+               ea = config_get_default_macaddr(dev->ifname);
+               if (ea) {
+                       memcpy(s->macaddr, ea, 6);
+                       s->flags |= DEV_OPT_DEFAULT_MACADDR;
+               }
+       }
+}
+
 int device_claim(struct device_user *dep)
 {
        struct device *dev = dep->dev;
@@ -447,6 +457,7 @@ int device_claim(struct device_user *dep)
                return 0;
 
        device_broadcast_event(dev, DEV_EVENT_SETUP);
+       device_fill_default_settings(dev);
        if (dev->external) {
                /* Get ifindex for external claimed devices so a valid   */
                /* ifindex is in place avoiding possible race conditions */
index b2b18ab0cfa63c4069c4b495d33a29f5169e8bfb..ab5a162a964ce0d3be4cdcc98de18b2ddf86213c 100644 (file)
--- a/device.h
+++ b/device.h
@@ -93,7 +93,8 @@ enum {
        DEV_OPT_IGMPVERSION             = (1 << 7),
        DEV_OPT_MLDVERSION              = (1 << 8),
        DEV_OPT_NEIGHREACHABLETIME      = (1 << 9),
-       /* 2 bit hole */
+       DEV_OPT_DEFAULT_MACADDR         = (1 << 10),
+       /* 1 bit hole */
        DEV_OPT_MTU6                    = (1 << 12),
        DEV_OPT_DADTRANSMITS            = (1 << 13),
        DEV_OPT_MULTICAST_TO_UNICAST    = (1 << 14),
index 6efc3c503aac85e1005bc4394f83c4c86cb1d1e6..024c5b8e360ef0a0cde792b4911f7f2e4a5dc168 100644 (file)
 #include <arpa/inet.h>
 #include <netinet/in.h>
 
-#ifdef linux
-#include <netinet/ether.h>
-#else
-#include <net/ethernet.h>
-#endif
-
 #include "netifd.h"
 #include "device.h"
 #include "interface.h"
index 092f1dd36c1d574a2e5fa110ae2b7a8d33de4838..c4ebdd0d9249df55d8a5c31461d71578275bb3ac 100644 (file)
--- a/macvlan.c
+++ b/macvlan.c
 #include <stdio.h>
 #include <assert.h>
 #include <errno.h>
-#include <net/ethernet.h>
-
-#ifdef linux
-#include <netinet/ether.h>
-#endif
 
 #include "netifd.h"
 #include "device.h"
index a4a146cabd6f0218dfb4663ee42198a38c6a0538..9645a0a33769148f80b469fe610e17ce637f5da6 100644 (file)
--- a/netifd.h
+++ b/netifd.h
 
 #include <libubus.h>
 
+#ifdef linux
+#include <netinet/ether.h>
+#else
+#include <net/ethernet.h>
+#endif
+
 #include "utils.h"
 
 #ifdef DUMMY_MODE
 #define DEFAULT_CONFIG_PATH    "./config"
 #define DEFAULT_HOTPLUG_PATH   "./examples/hotplug-cmd"
 #define DEFAULT_RESOLV_CONF    "./tmp/resolv.conf"
+#define DEFAULT_BOARD_JSON     "./config/board.json"
 #else
 #define DEFAULT_MAIN_PATH      "/lib/netifd"
 #define DEFAULT_CONFIG_PATH    NULL /* use the default set in libuci */
 #define DEFAULT_HOTPLUG_PATH   "/sbin/hotplug-call"
 #define DEFAULT_RESOLV_CONF    "/tmp/resolv.conf.d/resolv.conf.auto"
+#define DEFAULT_BOARD_JSON     "/etc/board.json"
 #endif
 
 extern const char *resolv_conf;
index 4ad9db521126302ece6b68ca300449d8092c79b9..6bf0f8b31fdd25c1a6ed9f273f4afb52cdf0c573 100644 (file)
@@ -159,7 +159,9 @@ system_if_dump_stats(struct device *dev, struct blob_buf *b)
 void
 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
 {
-       if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
+       apply_mask &= s->flags;
+
+       if ((apply_mask & (DEV_OPT_MACADDR | DEV_OPT_DEFAULT_MACADDR)) && !dev->external) {
                D(SYSTEM, "ifconfig %s hw ether %s\n",
                  dev->ifname, format_macaddr(s->macaddr));
        }
index 880cd232b8043136a325997a325083fa8d1f146e..bf746f9fd68b4709f932e30e2bc630d75472e482 100644 (file)
@@ -28,8 +28,8 @@
 
 #include <limits.h>
 #include <arpa/inet.h>
-#include <netinet/ether.h>
 #include <netinet/in.h>
+#include <netinet/ether.h>
 
 #include <linux/rtnetlink.h>
 #include <linux/neighbour.h>
@@ -1659,7 +1659,7 @@ system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned
                if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
                        s->flags &= ~DEV_OPT_TXQUEUELEN;
        }
-       if ((apply_mask & DEV_OPT_MACADDR) && !dev->external) {
+       if ((apply_mask & (DEV_OPT_MACADDR | DEV_OPT_DEFAULT_MACADDR)) && !dev->external) {
                ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
                memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
                if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
diff --git a/veth.c b/veth.c
index eafa4cf97bbbf5523e574a72e53ddc37f7c35d11..fdab38a4b70b310ad434e034f8a68c8cb71fb2f2 100644 (file)
--- a/veth.c
+++ b/veth.c
 #include <stdio.h>
 #include <assert.h>
 #include <errno.h>
-#include <net/ethernet.h>
-
-#ifdef linux
-#include <netinet/ether.h>
-#endif
 
 #include "netifd.h"
 #include "device.h"