From: Vincent Bernat Date: Tue, 9 Dec 2008 18:25:57 +0000 (+0100) Subject: For enslaved devices, get the real MAC address from /proc/net/bonding X-Git-Tag: 0.3~12^2~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1d291522e96d5bbed1b9a6c0955974e7ffe9ca9d;p=thirdparty%2Flldpd.git For enslaved devices, get the real MAC address from /proc/net/bonding --- diff --git a/CHANGELOG b/CHANGELOG index cb96a1a1..7d407ad6 100644 --- 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 diff --git a/src/features.c b/src/features.c index c3440731..02c81744 100644 --- a/src/features.c +++ b/src/features.c @@ -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 diff --git a/src/lldpd.c b/src/lldpd.c index 661432ff..0f515a7e 100644 --- a/src/lldpd.c +++ b/src/lldpd.c @@ -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 diff --git a/src/lldpd.h b/src/lldpd.h index 33fe5f2b..94caebc0 100644 --- a/src/lldpd.h +++ b/src/lldpd.h @@ -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(); diff --git a/src/priv.c b/src/priv.c index 9cd99f3e..5c5aa2c9 100644 --- a/src/priv.c +++ b/src/priv.c @@ -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",