+lldpd (0.7.10)
+ * Features:
+ + Ability to set promiscuous mode to work around bugs of some
+ switches encapsulating LLDP frames inside 802.1Q frames.
+
lldpd (0.7.9)
* Changes:
+ Default location for chroot, socket and PID are now configurable
1. Disable VLAN acceleration on the receive side (`ethtool -K eth0
rxvlan off`) but this may or may not work. Check if there are
similar properties that could apply with `ethtool -k eth0`.
- 2. Put the interface in promiscuous mode with `ip link eth0 set
- promisc on`.
+ 2. Put the interface in promiscuous mode with `ip link set
+ promisc on dev eth0`.
On modern networks, the performance impact should be nonexistent.
return 1;
}
+static int
+cmd_iface_promisc(struct lldpctl_conn_t *conn, struct writer *w,
+ struct cmd_env *env, void *arg)
+{
+ lldpctl_atom_t *config = lldpctl_get_configuration(conn);
+ if (config == NULL) {
+ log_warnx("lldpctl", "unable to get configuration from lldpd. %s",
+ lldpctl_last_strerror(conn));
+ return 0;
+ }
+ if (lldpctl_atom_set_int(config,
+ lldpctl_k_config_iface_promisc,
+ arg?1:0) == NULL) {
+ log_warnx("lldpctl", "unable to %s promiscuous mode: %s",
+ arg?"enable":"disable",
+ lldpctl_last_strerror(conn));
+ lldpctl_atom_dec_ref(config);
+ return 0;
+ }
+ log_info("lldpctl", "interface promiscuous mode %s",
+ arg?"enabled":"disabled");
+ lldpctl_atom_dec_ref(config);
+ return 1;
+}
+
static int
cmd_system_description(struct lldpctl_conn_t *conn, struct writer *w,
struct cmd_env *env, void *arg)
NEWLINE, "Don't update interface descriptions with neighbor name",
NULL, cmd_update_descriptions, NULL);
+ commands_new(
+ commands_new(configure_interface,
+ "promiscuous", "Enable promiscuous mode on managed interfaces",
+ NULL, NULL, NULL),
+ NEWLINE, "Enable promiscuous mode on managed interfaces",
+ NULL, cmd_iface_promisc, "enable");
+ commands_new(
+ commands_new(unconfigure_interface,
+ "promiscuous", "Don't enable promiscuous mode on managed interfaces",
+ NULL, NULL, NULL),
+ NEWLINE, "Don't enable promiscuous mode on managed interfaces",
+ NULL, cmd_iface_promisc, NULL);
+
register_commands_srcmac_type(configure_system);
}
tag_datatag(w, "ifdescr-update", "Update interface descriptions",
lldpctl_atom_get_int(configuration, lldpctl_k_config_ifdescr_update)?
"yes":"no");
+ tag_datatag(w, "iface-promisc", "Promiscuous mode on managed interfaces",
+ lldpctl_atom_get_int(configuration, lldpctl_k_config_iface_promisc)?
+ "yes":"no");
tag_datatag(w, "lldpmed-no-inventory", "Disable LLDP-MED inventory",
(lldpctl_atom_get_int(configuration, lldpctl_k_config_lldpmed_noinventory) == 0)?
"no":"yes");
is found or with the number of neighbors found.
.Ed
+.Cd configure
+.Cd system interface promiscuous
+.Bd -ragged -offset XXXXXX
+Enable promiscuous mode on managed interfaces. This option is only
+needed if you don't receive LLDP frames from the remote switch. The
+most plausible explanation for this is the frame is tagged with some
+VLAN (usually VLAN 1) and your network card is filtering VLAN. This is
+not the only available solution to work-around this problem. If you
+are concerned about performance issues, you can also tag the VLAN 1 on
+each interface.
+.Pp
+When the interface is not managed any more (or when quitting
+.Nm ) ,
+the interface is left in promiscuous mode as it is difficult to know
+if someone else also put the interface in promiscuous mode.
+.Pp
+This option is known to be useful when the remote switch is a Cisco
+2960.
+.Ed
+
+.Cd unconfigure
+.Cd system interface promiscuous
+.Bd -ragged -offset XXXXXX
+Do not set promiscuous mode on managed interfaces. This option does
+not disable promiscuous mode on interfaces already using this mode.
+.Ed
+
.Cd configure
.Cd system ip management pattern Ar pattern
.Bd -ragged -offset XXXXXX
cfg->g_config.c_set_ifdescr = config->c_set_ifdescr;
levent_update_now(cfg);
}
+ if (config->c_promisc != cfg->g_config.c_promisc) {
+ log_debug("rpc", "%s promiscuous mode on managed interfaces",
+ config->c_promisc?"enable":"disable");
+ cfg->g_config.c_promisc = config->c_promisc;
+ levent_update_now(cfg);
+ }
if (config->c_bond_slave_src_mac_type != 0) {
if (config->c_bond_slave_src_mac_type >
LLDP_BOND_SLAVE_SRC_MAC_TYPE_UNKNOWN &&
TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries) {
if (!hardware->h_flags) continue;
ifbsd_macphy(cfg, hardware);
+ interfaces_helper_promisc(cfg, hardware);
}
if (cfg->g_iface_event == NULL) {
TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries) {
if (!hardware->h_flags) continue;
iflinux_macphy(hardware);
+ interfaces_helper_promisc(cfg, hardware);
}
if (cfg->g_iface_event == NULL) {
extern struct lldpd_ops bpf_ops;
void
interfaces_update(struct lldpd *cfg) {
+ struct lldpd_hardware *hardware;
caddr_t buffer = NULL;
struct interfaces_device_list *interfaces;
struct interfaces_address_list *addresses;
interfaces_helper_mgmt(cfg, addresses);
interfaces_helper_chassis(cfg, interfaces);
+ /* Mac/PHY */
+ TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries) {
+ if (!hardware->h_flags) continue;
+ /* TODO: mac/phy for Solaris */
+ interfaces_helper_promisc(cfg, hardware);
+ }
+
end:
free(buffer);
interfaces_free_devices(interfaces);
}
}
+void
+interfaces_helper_promisc(struct lldpd *cfg,
+ struct lldpd_hardware *hardware)
+{
+ if (!cfg->g_config.c_promisc) return;
+ if (priv_iface_promisc(hardware->h_ifname) != 0) {
+ log_warnx("interfaces",
+ "unable to enable promiscuous mode for %s",
+ hardware->h_ifname);
+ }
+}
+
/**
* Send the packet using the hardware function. Optionnaly mangle the MAC address.
*
int priv_iface_multicast(const char *, u_int8_t *, int);
int priv_iface_description(const char *, const char *);
int asroot_iface_description_os(const char *, const char *);
+int priv_iface_promisc(const char*);
+int asroot_iface_promisc_os(const char *);
int priv_snmp_socket(struct sockaddr_un *);
enum priv_cmd {
PRIV_IFACE_INIT,
PRIV_IFACE_MULTICAST,
PRIV_IFACE_DESCRIPTION,
+ PRIV_IFACE_PROMISC,
PRIV_SNMP_SOCKET,
};
struct interfaces_device_list *,
const char *);
+void interfaces_helper_promisc(struct lldpd *,
+ struct lldpd_hardware *);
void interfaces_helper_whitelist(struct lldpd *,
struct interfaces_device_list *);
void interfaces_helper_chassis(struct lldpd *,
return 0;
}
+int
+asroot_iface_promisc_os(const char *name)
+{
+ /* The promiscuous mode can be set when setting BPF
+ (BIOCPROMISC). Unfortunately, the interface is locked down and we
+ cannot change that without reopening a new socket. Let's do nothing
+ for now. */
+ return 0;
+}
fclose(fp);
return 0;
}
+
+int
+asroot_iface_promisc_os(const char *name)
+{
+ int s, rc;
+ if ((s = socket(PF_PACKET, SOCK_RAW,
+ htons(ETH_P_ALL))) < 0) {
+ rc = errno;
+ log_warn("privsep", "unable to open raw socket");
+ return rc;
+ }
+
+ struct ifreq ifr = {};
+ strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+
+ if (ioctl(s, SIOCGIFFLAGS, &ifr) == -1) {
+ rc = errno;
+ log_warn("privsep", "unable to get interface flags for %s",
+ name);
+ close(s);
+ return rc;
+ }
+
+ if (ifr.ifr_flags & IFF_PROMISC)
+ return 0;
+ ifr.ifr_flags |= IFF_PROMISC;
+ if (ioctl(s, SIOCSIFFLAGS, &ifr) == -1) {
+ rc = errno;
+ log_warn("privsep", "unable to set promisc mode for %s",
+ name);
+ close(s);
+ return rc;
+ }
+ log_info("privsep", "promiscuous mode enabled for %s", name);
+ close(s);
+ return 0;
+}
return rc;
}
+/* Proxy to set interface in promiscuous mode */
+int
+priv_iface_promisc(const char *ifname)
+{
+ int rc;
+ enum priv_cmd cmd = PRIV_IFACE_PROMISC;
+ must_write(PRIV_UNPRIVILEGED, &cmd, sizeof(enum priv_cmd));
+ must_write(PRIV_UNPRIVILEGED, ifname, IFNAMSIZ);
+ priv_wait();
+ must_read(PRIV_UNPRIVILEGED, &rc, sizeof(int));
+ return rc;
+}
+
int
priv_snmp_socket(struct sockaddr_un *addr)
{
free(description);
}
+static void
+asroot_iface_promisc()
+{
+ char name[IFNAMSIZ];
+ int rc;
+ must_read(PRIV_PRIVILEGED, &name, sizeof(name));
+ name[sizeof(name) - 1] = '\0';
+ rc = asroot_iface_promisc_os(name);
+ must_write(PRIV_PRIVILEGED, &rc, sizeof(rc));
+}
+
static void
asroot_snmp_socket()
{
{PRIV_IFACE_INIT, asroot_iface_init},
{PRIV_IFACE_MULTICAST, asroot_iface_multicast},
{PRIV_IFACE_DESCRIPTION, asroot_iface_description},
+ {PRIV_IFACE_PROMISC, asroot_iface_promisc},
{PRIV_SNMP_SOCKET, asroot_snmp_socket},
{-1, NULL}
};
return c->config->c_advertise_version;
case lldpctl_k_config_ifdescr_update:
return c->config->c_set_ifdescr;
+ case lldpctl_k_config_iface_promisc:
+ return c->config->c_promisc;
#ifdef ENABLE_LLDPMED
case lldpctl_k_config_lldpmed_noinventory:
return c->config->c_noinventory;
case lldpctl_k_config_ifdescr_update:
config.c_set_ifdescr = c->config->c_set_ifdescr = value;
break;
+ case lldpctl_k_config_iface_promisc:
+ config.c_promisc = c->config->c_promisc = value;
+ break;
#ifdef ENABLE_LLDPMED
case lldpctl_k_config_fast_start_enabled:
config.c_enable_fast_start = value?1:2;
lldpctl_k_config_fast_start_enabled, /**< `(I,WO)` Is fast start enabled */
lldpctl_k_config_fast_start_interval, /**< `(I,WO)` Start fast transmit interval */
lldpctl_k_config_ifdescr_update, /**< `(I,WO)` Enable or disable setting interface description */
+ lldpctl_k_config_iface_promisc, /**< `(I,WO)` Enable or disable promiscuous mode on interfaces */
lldpctl_k_interface_name = 1000, /**< `(S)` The interface name. */
char *c_hostname; /* Override system name */
int c_advertise_version; /* Should the precise version be advertised? */
int c_set_ifdescr; /* Set interface description */
+ int c_promisc; /* Interfaces should be in promiscuous mode */
#ifdef ENABLE_LLDPMED
int c_noinventory; /* Don't send inventory with LLDP-MED */