]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
For enslaved devices, get the real MAC address from /proc/net/bonding
authorVincent Bernat <bernat@luffy.cx>
Tue, 9 Dec 2008 18:25:57 +0000 (19:25 +0100)
committerVincent Bernat <bernat@luffy.cx>
Tue, 9 Dec 2008 18:25:57 +0000 (19:25 +0100)
CHANGELOG
src/features.c
src/lldpd.c
src/lldpd.h
src/priv.c

index cb96a1a1fc991cb246887a8c50d89799a0256828..7d407ad618754d75b891753ed8cba99f89df53a9 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,7 +2,8 @@ lldpd (0.3)
 
   * Initial support of LLDP-MED (inventory part)
   * Fix for bridge detection (don't send bridge ioctl on random interfaces)
-  * Don't send anything on inactive slaves (this confuses most switches)
+  * For bonded devices, get the real hardware address. For inactive
+    slaves, transmit using a random MAC address.
 
  -- Vincent Bernat <bernat@luffy.cx>
 
index c3440731d8992c913ca4cbe1366819a76d95dbf6..02c81744dda6e5c25a537b174fa2956afa95778e 100644 (file)
@@ -185,6 +185,95 @@ iface_is_slave_active(struct lldpd *cfg, int master, const char *slave)
        return (active == BOND_STATE_ACTIVE);
 }
 
+void
+iface_get_permanent_mac(struct lldpd *cfg, struct lldpd_hardware *hardware)
+{
+       int master, f, state = 0;
+       FILE *netbond;
+       const char *slaveif = "Slave Interface: ";
+       const char *hwaddr = "Permanent HW addr: ";
+       u_int8_t mac[ETHER_ADDR_LEN];
+       char bond[IFNAMSIZ];
+       char path[SYSFS_PATH_MAX];
+       char line[100];
+       if ((master = iface_is_enslaved(cfg, hardware->h_ifname)) == -1)
+               return;
+       /* We have a bond, we need to query it to get real MAC addresses */
+       if ((if_indextoname(master, bond)) == NULL) {
+               LLOG_WARNX("unable to get bond name");
+               return;
+       }
+
+       if (snprintf(path, SYSFS_PATH_MAX, "/proc/net/bonding/%s",
+               bond) >= SYSFS_PATH_MAX) {
+               LLOG_WARNX("path truncated");
+               return;
+       }
+       if ((f = priv_open(path)) < 0) {
+               if (snprintf(path, SYSFS_PATH_MAX, "/proc/self/net/bonding/%s",
+                       bond) >= SYSFS_PATH_MAX) {
+                       LLOG_WARNX("path truncated");
+                       return;
+               }
+               f = priv_open(path);
+       }
+       if (f < 0) {
+               LLOG_WARNX("unable to find %s in /proc/net/bonding or /proc/self/net/bonding",
+                   bond);
+               return;
+       }
+       if ((netbond = fdopen(f, "r")) == NULL) {
+               LLOG_WARN("unable to read stream from %s", path);
+               close(f);
+               return;
+       }
+       /* State 0:
+            We parse the file to search "Slave Interface: ". If found, go to
+            state 1.
+          State 1:
+            We parse the file to search "Permanent HW addr: ". If found, we get
+            the mac.
+       */
+       while (fgets(line, sizeof(line), netbond)) {
+               switch (state) {
+               case 0:
+                       if (strncmp(line, slaveif, strlen(slaveif)) == 0) {
+                               if (line[strlen(line)-1] == '\n')
+                                       line[strlen(line)-1] = '\0';
+                               if (strncmp(hardware->h_ifname,
+                                       line + strlen(slaveif),
+                                       sizeof(hardware->h_ifname)) == 0)
+                                       state++;
+                       }
+                       break;
+               case 1:
+                       if (strncmp(line, hwaddr, strlen(hwaddr)) == 0) {
+                               if (line[strlen(line)-1] == '\n')
+                                       line[strlen(line)-1] = '\0';
+                               if (sscanf(line + strlen(hwaddr),
+                                       "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
+                                       &mac[0], &mac[1], &mac[2],
+                                       &mac[3], &mac[4], &mac[5]) !=
+                                   ETHER_ADDR_LEN) {
+                                       LLOG_WARN("unable to parse %s",
+                                           line + strlen(hwaddr));
+                                       fclose(netbond);
+                                       return;
+                               }
+                               memcpy(hardware->h_lladdr, mac,
+                                   ETHER_ADDR_LEN);
+                               fclose(netbond);
+                               return;
+                       }
+                       break;
+               }
+       }
+       LLOG_WARNX("unable to find real mac address for %s",
+           bond);
+       fclose(netbond);
+}
+
+
 #ifdef ENABLE_LLDPMED
        /* Fill in inventory stuff:
            - hardware version: /sys/class/dmi/id/product_version
index 661432ff4bc90fb0db8500bfcc5b0cbd7e10f981..0f515a7e0b62b13a4b4409ad2a132563912318a1 100644 (file)
@@ -555,6 +555,7 @@ lldpd_port_add(struct lldpd *cfg, struct ifaddrs *ifa)
        strlcpy(hardware->h_ifname, ifa->ifa_name, sizeof(hardware->h_ifname));
        lladdr = (u_int8_t*)(((struct sockaddr_ll *)ifa->ifa_addr)->sll_addr);
        memcpy(&hardware->h_lladdr, lladdr, sizeof(hardware->h_lladdr));
+       iface_get_permanent_mac(cfg, hardware);
        port->p_id_subtype = LLDP_PORTID_SUBTYPE_LLADDR;
        if ((port->p_id = calloc(1, sizeof(hardware->h_lladdr))) == NULL)
                fatal(NULL);
@@ -1175,7 +1176,7 @@ lldpd_recv_all(struct lldpd *cfg)
        } while ((rc != 0) || (time(NULL) - cfg->g_lastsent < cfg->g_delay));
 }
 
-void static
+static void
 get_random_ether(u_int8_t *lladdr)
 {
        /* We use a simple law to generate random bytes of the MAC address and
index 33fe5f2b2e78f7ecc00d3c673b03358f4417c287..94caebc0f3fbd100c0e124ffaaddcae28b760c57 100644 (file)
@@ -338,6 +338,7 @@ int  iface_is_bond_slave(struct lldpd *,
     const char *, const char *, int *);
 int     iface_is_enslaved(struct lldpd *, const char *);
 int     iface_is_slave_active(struct lldpd *, int, const char *);
+void    iface_get_permanent_mac(struct lldpd *, struct lldpd_hardware *);
 #ifdef ENABLE_LLDPMED
 char   *dmi_hw();
 char   *dmi_fw();
index 9cd99f3ede5ea26ad78f9f1ad41a913b82a953aa..5c5aa2c9edde1b33fa069a2dc8c19b880b5a461b 100644 (file)
@@ -246,6 +246,8 @@ asroot_open()
 {
        const char* authorized[] = {
                "/proc/sys/net/ipv4/ip_forward",
+               "/proc/net/bonding/[^.][^/]*",
+               "/proc/self/net/bonding/[^.][^/]*",
                SYSFS_CLASS_NET "[^.][^/]*/brforward",
                SYSFS_CLASS_NET "[^.][^/]*/brport",
                SYSFS_CLASS_DMI "product_version",