From: Vincent Bernat Date: Thu, 14 May 2009 15:56:59 +0000 (+0200) Subject: Also check for VLAN on bridges. X-Git-Tag: 0.4.0~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bac91719401f7e6b05c32b6e8f30f6b952507e56;p=thirdparty%2Flldpd.git Also check for VLAN on bridges. --- diff --git a/src/features.c b/src/features.c index 74379df9..fe988b55 100644 --- a/src/features.c +++ b/src/features.c @@ -80,6 +80,53 @@ iface_is_bridge(struct lldpd *cfg, const char *name) return 1; } +static int +old_iface_is_bridged_to(struct lldpd *cfg, const char *slave, const char *master) +{ + int j, index = if_nametoindex(slave); + int ifptindices[MAX_PORTS]; + unsigned long args2[4] = { BRCTL_GET_PORT_LIST, + (unsigned long)ifptindices, MAX_PORTS, 0 }; + struct ifreq ifr; + + strncpy(ifr.ifr_name, master, IFNAMSIZ); + memset(ifptindices, 0, sizeof(ifptindices)); + ifr.ifr_data = (char *)&args2; + + if (ioctl(cfg->g_sock, SIOCDEVPRIVATE, &ifr) < 0) { + LLOG_WARN("unable to get bridge members for %s", + ifr.ifr_name); + return 0; + } + + for (j = 0; j < MAX_PORTS; j++) { + if (ifptindices[j] == index) + return 1; + } + + return 0; +} + +int +iface_is_bridged_to(struct lldpd *cfg, const char *slave, const char *master) +{ + char path[SYSFS_PATH_MAX]; + int f; + + /* Master should be a bridge, first */ + if (!iface_is_bridge(cfg, master)) return 0; + + if (snprintf(path, SYSFS_PATH_MAX, + SYSFS_CLASS_NET "%s/" SYSFS_BRIDGE_PORT_SUBDIR "/%s/port_no", + master, slave) >= SYSFS_PATH_MAX) + LLOG_WARNX("path truncated"); + if ((f = priv_open(path)) < 0) { + return old_iface_is_bridged_to(cfg, slave, master); + } + close(f); + return 1; +} + int iface_is_vlan(struct lldpd *cfg, const char *name) { diff --git a/src/lldpd.c b/src/lldpd.c index 5d4222ec..2c9e1c53 100644 --- a/src/lldpd.c +++ b/src/lldpd.c @@ -597,8 +597,10 @@ lldpd_port_add(struct lldpd *cfg, struct ifaddrs *ifa) /* Check if we already have checked this one */ int skip = 0; TAILQ_FOREACH(vlan, &port->p_vlans, v_entries) { - if (strcmp(vlan->v_name, oifa->ifa_name) == 0) + if (strcmp(vlan->v_name, oifa->ifa_name) == 0) { skip = 1; + break; + } } if (skip) continue; #endif @@ -616,6 +618,7 @@ lldpd_port_add(struct lldpd *cfg, struct ifaddrs *ifa) strlcpy(ifv.device1, oifa->ifa_name, sizeof(ifv.device1)); if ((ioctl(cfg->g_sock, SIOCGIFVLAN, &ifv) >= 0) && ((iface_is_bond_slave(cfg, hardware->h_ifname, ifv.u.device2, NULL)) || + (iface_is_bridged_to(cfg, hardware->h_ifname, ifv.u.device2)) || (strncmp(hardware->h_ifname, ifv.u.device2, sizeof(ifv.u.device2)) == 0))) { if ((vlan = (struct lldpd_vlan *) calloc(1, sizeof(struct lldpd_vlan))) == NULL) diff --git a/src/lldpd.h b/src/lldpd.h index 302b9273..19683ed5 100644 --- a/src/lldpd.h +++ b/src/lldpd.h @@ -382,6 +382,8 @@ int ctl_msg_unpack_structure(char *, void *, unsigned int, struct hmsg *, void /* features.c */ int iface_is_bridge(struct lldpd *, const char *); +int iface_is_bridged_to(struct lldpd *, + const char *, const char *); int iface_is_wireless(struct lldpd *, const char *); int iface_is_vlan(struct lldpd *, const char *); int iface_is_bond(struct lldpd *, const char *); diff --git a/src/priv.c b/src/priv.c index e087cca4..a2ac841d 100644 --- a/src/priv.c +++ b/src/priv.c @@ -259,6 +259,7 @@ asroot_open() "/proc/self/net/bonding/[^.][^/]*", SYSFS_CLASS_NET "[^.][^/]*/brforward", SYSFS_CLASS_NET "[^.][^/]*/brport", + SYSFS_CLASS_NET "[^.][^/]*/brif/[^.][^/]*/port_no", SYSFS_CLASS_DMI "product_version", SYSFS_CLASS_DMI "product_serial", SYSFS_CLASS_DMI "product_name",