+ Change the numeric value for LLDP-MED policy L2 priority value
for "Best effort" to 0 to match 802.1D-2004.
* Change:
+ + Retrieve the permanent MAC address of an interface through
+ ethtool for Linux. This is is possible since 2.6.14, so no
+ compatibility layer is kept.
+ Running lldpd with "-d" will keep the process in foreground but
logs will still go to syslog. To log to the console, add at
least one "-d".
struct interfaces_device *iface)
{
struct interfaces_device *master;
- int f, state = 0;
- FILE *netbond;
- const char *slaveif = "Slave Interface: ";
- const char *hwaddr = "Permanent HW addr: ";
u_int8_t mac[ETHER_ADDR_LEN];
- char path[SYSFS_PATH_MAX];
- char line[100];
+ /* We could do that for any interface, but let's do that only for
+ * aggregates. */
if ((master = iface->upper) == NULL || master->type != IFACE_BOND_T)
return;
log_debug("interfaces", "get MAC address for %s",
iface->name);
- /* We have a bond, we need to query it to get real MAC addresses */
- if (snprintf(path, SYSFS_PATH_MAX, "/proc/net/bonding/%s",
- master->name) >= SYSFS_PATH_MAX) {
- log_warnx("interfaces", "path truncated");
- return;
- }
- if ((f = priv_open(path)) < 0) {
- if (snprintf(path, SYSFS_PATH_MAX, "/proc/self/net/bonding/%s",
- master->name) >= SYSFS_PATH_MAX) {
- log_warnx("interfaces", "path truncated");
- return;
- }
- f = priv_open(path);
- }
- if (f < 0) {
- log_warnx("interfaces",
- "unable to find %s in /proc/net/bonding or /proc/self/net/bonding",
- master->name);
- return;
- }
- if ((netbond = fdopen(f, "r")) == NULL) {
- log_warn("interfaces", "unable to read stream from %s", path);
- close(f);
+ if (priv_iface_mac(iface->name, mac, ETHER_ADDR_LEN) != 0) {
+ log_warnx("interfaces", "unable to get permanent MAC address for %s",
+ iface->name);
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 (strcmp(iface->name,
- line + strlen(slaveif)) == 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) {
- log_warn("interfaces", "unable to parse %s",
- line + strlen(hwaddr));
- fclose(netbond);
- return;
- }
- memcpy(iface->address, mac,
- ETHER_ADDR_LEN);
- fclose(netbond);
- return;
- }
- break;
- }
- }
- log_warnx("interfaces", "unable to find real mac address for %s",
- iface->name);
- fclose(netbond);
+ memcpy(iface->address, mac,
+ ETHER_ADDR_LEN);
}
/* Fill up MAC/PHY for a given hardware port */
void asroot_open(void);
int priv_ethtool(char*, void*, size_t);
void asroot_ethtool(void);
+int priv_iface_mac(char*, void*, size_t);
+void asroot_iface_mac(void);
#endif
int priv_iface_init(int, char *);
int asroot_iface_init_os(int, char *, int *);
PRIV_IFACE_MULTICAST,
PRIV_IFACE_DESCRIPTION,
PRIV_IFACE_PROMISC,
+ PRIV_IFACE_MAC,
PRIV_SNMP_SOCKET,
};
return receive_fd(PRIV_UNPRIVILEGED);
}
-/* Proxy for ethtool ioctl */
+/* Proxy for ethtool ioctl (GSET only) */
int
priv_ethtool(char *ifname, void *ethc, size_t length)
{
return rc;
}
+/* Proxy to get permanent MAC address */
+int
+priv_iface_mac(char *ifname, void *mac, size_t length)
+{
+ int rc, len;
+ enum priv_cmd cmd = PRIV_IFACE_MAC;
+ must_write(PRIV_UNPRIVILEGED, &cmd, sizeof(enum priv_cmd));
+ len = strlen(ifname);
+ must_write(PRIV_UNPRIVILEGED, &len, sizeof(int));
+ must_write(PRIV_UNPRIVILEGED, ifname, len);
+ priv_wait();
+ must_read(PRIV_UNPRIVILEGED, &rc, sizeof(int));
+ if (rc != 0)
+ return rc;
+ must_read(PRIV_UNPRIVILEGED, mac, length);
+ return rc;
+}
+
void
asroot_open()
{
const char* authorized[] = {
"/proc/sys/net/ipv4/ip_forward",
- "/proc/net/bonding/[^.][^/]*",
- "/proc/self/net/bonding/[^.][^/]*",
#ifdef ENABLE_OLDIES
SYSFS_CLASS_NET "[^.][^/]*/brforward",
SYSFS_CLASS_NET "[^.][^/]*/brport",
must_write(PRIV_PRIVILEGED, ðc, sizeof(struct ethtool_cmd));
}
+void
+asroot_iface_mac()
+{
+ struct ifreq ifr = {};
+ int len, rc, sock = -1;
+ char *ifname;
+ struct ethtool_perm_addr *epaddr;
+
+ must_read(PRIV_PRIVILEGED, &len, sizeof(int));
+ if ((ifname = (char*)malloc(len + 1)) == NULL)
+ fatal("privsep", NULL);
+ must_read(PRIV_PRIVILEGED, ifname, len);
+ ifname[len] = '\0';
+ strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ free(ifname);
+
+ if ((epaddr = malloc(sizeof(struct ethtool_perm_addr) + ETHER_ADDR_LEN)) == NULL)
+ fatal("privsep", NULL);
+ epaddr->cmd = ETHTOOL_GPERMADDR;
+ epaddr->size = ETHER_ADDR_LEN;
+ ifr.ifr_data = (caddr_t)epaddr;
+ if (((rc = sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) ||
+ (rc = ioctl(sock, SIOCETHTOOL, &ifr)) != 0) {
+ if (sock != -1) close(sock);
+ free(epaddr);
+ must_write(PRIV_PRIVILEGED, &rc, sizeof(int));
+ return;
+ }
+ close(sock);
+ must_write(PRIV_PRIVILEGED, &rc, sizeof(int));
+ must_write(PRIV_PRIVILEGED, epaddr->data, ETHER_ADDR_LEN);
+ free(epaddr);
+}
+
int
asroot_iface_init_os(int ifindex, char *name, int *fd)
{
#ifdef HOST_OS_LINUX
{PRIV_OPEN, asroot_open},
{PRIV_ETHTOOL, asroot_ethtool},
+ {PRIV_IFACE_MAC, asroot_iface_mac},
#endif
{PRIV_IFACE_INIT, asroot_iface_init},
{PRIV_IFACE_MULTICAST, asroot_iface_multicast},
# Gather network information
@{PROC}/sys/net/ipv4/ip_forward r,
- @{PROC}/net/bonding/* r,
- @{PROC}/self/net/bonding/* r,
/sys/devices/virtual/dmi/** r,
/sys/devices/pci**/net/*/ifalias r,
}