#include <arpa/inet.h>
#include <net/if_arp.h>
+#if LLDPD_FD_SETSIZE != FD_SETSIZE
+# warning "FD_SETSIZE is set to an inconsistent value."
+#endif
+
#ifdef USE_SNMP
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
static void
usage(void)
{
- fprintf(stderr, "usage: %s [options]\n", __progname);
+ fprintf(stderr, "Usage: %s [OPTIONS ...]\n", __progname);
+
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, "-d Do not daemonize.\n");
+ fprintf(stderr, "-i Disable LLDP-MED inventory TLV transmission.\n");
+ fprintf(stderr, "-k Disable advertising of kernel release, version, machine.\n");
+ fprintf(stderr, "-m IP Specify the management address of this system.\n");
+ fprintf(stderr, "-M class Enable emission of LLDP-MED frame. 'class' should be one of:\n");
+ fprintf(stderr, " 1 Generic Endpoint (Class I)\n");
+ fprintf(stderr, " 2 Media Endpoint (Class II)\n");
+ fprintf(stderr, " 3 Communication Device Endpoints (Class III)\n");
+ fprintf(stderr, " 4 Network Connectivity Device\n");
+ fprintf(stderr, "-x Enable SNMP subagent.\n");
+#ifdef ENABLE_LISTENVLAN
+ fprintf(stderr, "-v Listen on VLAN as well.\n");
+#endif
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, "Protocol support. (Disabled by default)\n");
+ fprintf(stderr, "-c Enable the support of CDP protocol. (Cisco)\n");
+ fprintf(stderr, "-e Enable the support of EDP protocol. (Extreme)\n");
+ fprintf(stderr, "-f Enable the support of FDP protocol. (Foundry)\n");
+ fprintf(stderr, "-s Enable the support of SONMP protocol. (Nortel)\n");
+
+ fprintf(stderr, "\n");
+
fprintf(stderr, "see manual page lldpd(8) for more information\n");
exit(1);
}
strlcpy(hardware->h_ifname, name, sizeof(hardware->h_ifname));
hardware->h_lport.p_chassis = LOCAL_CHASSIS(cfg);
+ hardware->h_lport.p_chassis->c_refcount++;
TAILQ_INIT(&hardware->h_rports);
#ifdef ENABLE_LLDPMED
/* If `all' is true, clear all information, including information that
are not refreshed periodically. Port should be freed manually. */
void
-lldpd_port_cleanup(struct lldpd_port *port, int all)
+lldpd_port_cleanup(struct lldpd *cfg, struct lldpd_port *port, int all)
{
#ifdef ENABLE_LLDPMED
int i;
free(port->p_descr);
if (all) {
free(port->p_lastframe);
- if (port->p_chassis) /* chassis may not have been attributed, yet */
+ if (port->p_chassis) { /* chassis may not have been attributed, yet */
port->p_chassis->c_refcount--;
+ port->p_chassis = NULL;
+ }
}
}
}
if (del) {
TAILQ_REMOVE(&hardware->h_rports, port, p_entries);
- lldpd_port_cleanup(port, 1);
+ lldpd_port_cleanup(cfg, port, 1);
free(port);
}
}
lldpd_hardware_cleanup(struct lldpd *cfg, struct lldpd_hardware *hardware)
{
int i;
- lldpd_port_cleanup(&hardware->h_lport, 1);
+ lldpd_port_cleanup(cfg, &hardware->h_lport, 1);
/* If we have a dedicated cleanup function, use it. Otherwise,
we just free the hardware-dependent data and close all FD
in h_recvfds and h_sendfd. */
hardware->h_ops->cleanup(cfg, hardware);
else {
free(hardware->h_data);
- for (i=0; i < FD_SETSIZE; i++)
+ for (i=0; i < LLDPD_FD_SETSIZE; i++)
if (FD_ISSET(i, &hardware->h_recvfds))
close(i);
if (hardware->h_sendfd) close(hardware->h_sendfd);
lldpd_cleanup(struct lldpd *cfg)
{
struct lldpd_hardware *hardware, *hardware_next;
+ struct lldpd_chassis *chassis, *chassis_next;
for (hardware = TAILQ_FIRST(&cfg->g_hardware); hardware != NULL;
hardware = hardware_next) {
} else
lldpd_remote_cleanup(cfg, hardware, 0);
}
+
+ for (chassis = TAILQ_FIRST(&cfg->g_chassis); chassis;
+ chassis = chassis_next) {
+ chassis_next = TAILQ_NEXT(chassis, c_entries);
+ if (chassis->c_refcount == 0) {
+ TAILQ_REMOVE(&cfg->g_chassis, chassis, c_entries);
+ lldpd_chassis_cleanup(chassis, 1);
+ }
+ }
}
static int
if (oport) {
/* The port is known, remove it before adding it back */
TAILQ_REMOVE(&hardware->h_rports, oport, p_entries);
- lldpd_port_cleanup(oport, 1);
+ lldpd_port_cleanup(cfg, oport, 1);
free(oport);
}
if (ochassis) {
} else {
/* Chassis not known, add it */
chassis->c_index = ++cfg->g_lastrid;
- port->p_chassis = chassis;
chassis->c_refcount = 0;
TAILQ_INSERT_TAIL(&cfg->g_chassis, chassis, c_entries);
i = 0; TAILQ_FOREACH(ochassis, &cfg->g_chassis, c_entries) i++;
TAILQ_INSERT_TAIL(&hardware->h_rports, port, p_entries);
port->p_chassis = chassis;
port->p_chassis->c_refcount++;
+ /* Several cases are possible :
+ 1. chassis is new, its refcount was 0. It is now attached
+ to this port, its refcount is 1.
+ 2. chassis already exists and was attached to another
+ port, we increase its refcount accordingly.
+ 3. chassis already exists and was attached to the same
+ port, its refcount was decreased with
+ lldpd_port_cleanup() and is now increased again.
+
+ In all cases, if the port already existed, it has been
+ freed with lldpd_port_cleanup() and therefore, the refcount
+ of the chassis that was attached to it is decreased.
+ */
i = 0; TAILQ_FOREACH(oport, &hardware->h_rports, p_entries) i++;
LLOG_DEBUG("Currently, %s known %d neighbors",
hardware->h_ifname, i);
continue;
/* This is quite expensive but we don't rely on internal
* structure of fd_set. */
- for (n = 0; n < FD_SETSIZE; n++)
+ for (n = 0; n < LLDPD_FD_SETSIZE; n++)
if (FD_ISSET(n, &hardware->h_recvfds)) {
FD_SET(n, &rfds);
if (nfds < n)
}
#endif /* USE_SNMP */
TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries) {
- for (n = 0; n < FD_SETSIZE; n++)
+ for (n = 0; n < LLDPD_FD_SETSIZE; n++)
if ((FD_ISSET(n, &hardware->h_recvfds)) &&
(FD_ISSET(n, &rfds))) break;
- if (n == FD_SETSIZE) continue;
+ if (n == LLDPD_FD_SETSIZE) continue;
if ((buffer = (char *)malloc(
hardware->h_mtu)) == NULL) {
LLOG_WARN("failed to alloc reception buffer");
int ch, debug = 0;
#ifdef USE_SNMP
int snmp = 0;
+ char *agentx = NULL; /* AgentX socket */
#endif
char *mgmtp = NULL;
char *popt, opts[] =
#ifdef ENABLE_LISTENVLAN
"v"
#endif
- "kdxm:p:M:i@ ";
+ "kdxX:m:p:M:i@ ";
int i, found, advertise_version = 1;
#ifdef ENABLE_LISTENVLAN
int vlan = 0;
usage();
break;
#endif
- case 'x':
#ifdef USE_SNMP
+ case 'x':
snmp = 1;
+ break;
+ case 'X':
+ snmp = 1;
+ agentx = optarg;
+ break;
#else
+ case 'x':
+ case 'X':
fprintf(stderr, "SNMP support is not built-in\n");
usage();
#endif
}
log_init(debug, __progname);
+ tzset(); /* Get timezone info before chroot */
if (!debug) {
int pid;
TAILQ_INIT(&cfg->g_hardware);
TAILQ_INIT(&cfg->g_chassis);
TAILQ_INSERT_TAIL(&cfg->g_chassis, lchassis, c_entries);
- lchassis->c_refcount++;
+ lchassis->c_refcount++; /* We should always keep a reference to local chassis */
TAILQ_INIT(&cfg->g_callbacks);
#ifdef USE_SNMP
if (snmp) {
cfg->g_snmp = 1;
- agent_init(cfg, debug);
+ agent_init(cfg, agentx, debug);
}
#endif /* USE_SNMP */