#define _LLDPD_H
#if HAVE_CONFIG_H
- #include <config.h>
+# include <config.h>
#endif
#define _GNU_SOURCE 1
#include <stdlib.h>
#include <string.h>
#include <sys/queue.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
#ifndef INCLUDE_LINUX_IF_H
-#include <net/if.h>
+# include <net/if.h>
#else
-#include <arpa/inet.h>
-#include <linux/if.h>
+# include <arpa/inet.h>
+# include <linux/if.h>
+#endif
+#if HAVE_GETIFADDRS
+# include <ifaddrs.h>
#endif
#include <net/ethernet.h>
#include <netinet/in.h>
#include <linux/ethtool.h>
+#include <sys/un.h>
#include "compat.h"
-#include "llc.h"
#include "lldp.h"
#if defined (ENABLE_CDP) || defined (ENABLE_FDP)
-#include "cdp.h"
+# include "cdp.h"
#endif
#ifdef ENABLE_SONMP
-#include "sonmp.h"
+# include "sonmp.h"
#endif
#ifdef ENABLE_EDP
-#include "edp.h"
+# include "edp.h"
#endif
#define SYSFS_CLASS_NET "/sys/class/net/"
#endif
struct lldpd_chassis {
+ TAILQ_ENTRY(lldpd_chassis) c_entries;
+ u_int16_t c_refcount; /* Reference count by ports */
+ u_int16_t c_index; /* Monotonic index */
+ u_int8_t c_protocol; /* Protocol used to get this chassis */
u_int8_t c_id_subtype;
char *c_id;
int c_id_len;
u_int32_t c_mgmt_if;
#ifdef ENABLE_LLDPMED
-#define STRUCT_LLDPD_CHASSIS_MED "wwbsssssss"
+#define STRUCT_LLDPD_CHASSIS_MED "wbsssssss"
u_int16_t c_med_cap_available;
u_int8_t c_med_type;
char *c_med_hw;
#endif
};
-#define STRUCT_LLDPD_CHASSIS "(bCsswwwll" STRUCT_LLDPD_CHASSIS_MED ")"
+#define STRUCT_LLDPD_CHASSIS "(LwwbbCsswwwll" STRUCT_LLDPD_CHASSIS_MED ")"
struct lldpd_port {
+ TAILQ_ENTRY(lldpd_port) p_entries;
+ struct lldpd_chassis *p_chassis; /* Attached chassis */
+ time_t p_lastchange; /* Time of last change of values */
+ time_t p_lastupdate; /* Time of last update received */
+ struct lldpd_frame *p_lastframe; /* Frame received during last update */
+ u_int8_t p_protocol; /* Protocol used to get this port */
u_int8_t p_id_subtype;
char *p_id;
int p_id_len;
#define STRUCT_LLDPD_PORT_MED ""
#endif
-
#ifdef ENABLE_DOT1
#define STRUCT_LLDPD_PORT_DOT1 "wPP"
u_int16_t p_pvid;
#endif
};
-#define STRUCT_LLDPD_PORT "(bCsw" \
+#define STRUCT_LLDPD_PORT "(LPttPbbCsw" \
STRUCT_LLDPD_PORT_DOT3 \
STRUCT_LLDPD_PORT_MED \
STRUCT_LLDPD_PORT_DOT1 ")"
struct lldpd_frame {
int size;
- unsigned char frame[];
+ unsigned char frame[1];
+};
+
+struct lldpd_hardware;
+struct lldpd;
+struct lldpd_ops {
+ int(*send)(struct lldpd *,
+ struct lldpd_hardware*,
+ char *, size_t); /* Function to send a frame */
+ int(*recv)(struct lldpd *,
+ struct lldpd_hardware*,
+ int, char *, size_t); /* Function to receive a frame */
+ int(*cleanup)(struct lldpd *, struct lldpd_hardware *); /* Cleanup function. */
};
+/* An interface is uniquely identified by h_ifindex, h_ifname and h_ops. This
+ * means if an interface becomes enslaved, it will be considered as a new
+ * interface. The same applies for renaming and we include the index in case of
+ * renaming to an existing interface. */
struct lldpd_hardware {
TAILQ_ENTRY(lldpd_hardware) h_entries;
-#define INTERFACE_OPENED(x) ((x)->h_raw != -1)
-
- int h_raw;
- int h_raw_real; /* For bonding */
- int h_master; /* For bonding */
-
-#define LLDPD_MODE_ANY 0
-#define LLDPD_MODE_LLDP 1
-#define LLDPD_MODE_CDPV1 2
-#define LLDPD_MODE_CDPV2 3
-#define LLDPD_MODE_SONMP 4
-#define LLDPD_MODE_EDP 5
-#define LLDPD_MODE_FDP 6
- int h_mode;
+ fd_set h_recvfds; /* FD for reception */
+ int h_sendfd; /* FD for sending, only used by h_ops */
+ struct lldpd_ops *h_ops; /* Hardware-dependent functions */
+ void *h_data; /* Hardware-dependent data */
- int h_flags;
int h_mtu;
- char h_ifname[IFNAMSIZ];
+ int h_flags; /* Packets will be sent only
+ if IFF_RUNNING. Will be
+ removed if this is left
+ to 0. */
+ int h_ifindex; /* Interface index, used by SNMP */
+ char h_ifname[IFNAMSIZ]; /* Should be unique */
u_int8_t h_lladdr[ETHER_ADDR_LEN];
u_int64_t h_tx_cnt;
u_int64_t h_rx_ageout_cnt;
u_int64_t h_rx_unrecognized_cnt;
- u_int8_t *h_proto_macs;
- time_t h_start_probe;
-
- struct lldpd_port h_lport;
- time_t h_llastchange;
- struct lldpd_frame *h_llastframe;
-
- time_t h_rlastchange;
- time_t h_rlastupdate;
- int h_rid;
- struct lldpd_frame *h_rlastframe;
- struct lldpd_port *h_rport;
- struct lldpd_chassis *h_rchassis;
-};
-
-/* lldpd_vif can be casted to lldpd_hardware on some cases */
-struct lldpd_vif {
- TAILQ_ENTRY(lldpd_vif) vif_entries;
- int vif_raw;
- int vif_raw_real; /* Not used */
- int vif_master; /* Not used */
- int vif_mode; /* Not used */
- int vif_flags;
- int vif_mtu;
- char vif_ifname[IFNAMSIZ];
-
- /* No more compatibility with struct lldpd_hardware from here */
- struct lldpd_hardware *vif_real;
+ struct lldpd_port h_lport; /* Port attached to this hardware port */
+ TAILQ_HEAD(, lldpd_port) h_rports; /* Remote ports */
};
struct lldpd_interface {
};
#define STRUCT_LLDPD_INTERFACE "(Ls)"
-struct lldpd_client {
- TAILQ_ENTRY(lldpd_client) next;
- int fd;
-};
-
-#define PROTO_SEND_SIG struct lldpd *, struct lldpd_chassis *, struct lldpd_hardware *
+#define PROTO_SEND_SIG struct lldpd *, struct lldpd_hardware *
#define PROTO_DECODE_SIG struct lldpd *, char *, int, struct lldpd_hardware *, struct lldpd_chassis **, struct lldpd_port **
#define PROTO_GUESS_SIG char *, int
-struct lldpd;
struct protocol {
+#define LLDPD_MODE_LLDP 1
+#define LLDPD_MODE_CDPV1 2
+#define LLDPD_MODE_CDPV2 3
+#define LLDPD_MODE_SONMP 4
+#define LLDPD_MODE_EDP 5
+#define LLDPD_MODE_FDP 6
int mode; /* > 0 mode identifier (unique per protocol) */
int enabled; /* Is this protocol enabled? */
char *name; /* Name of protocol */
int(*decode)(PROTO_DECODE_SIG); /* How to decode a frame */
int(*guess)(PROTO_GUESS_SIG); /* Can be NULL, use MAC address in this case */
u_int8_t mac[ETH_ALEN]; /* Destination MAC address used by this protocol */
- struct sock_filter *filter; /* BPF filter */
- size_t filterlen; /* Size of BPF filter */
+};
+
+#define CALLBACK_SIG struct lldpd*, struct lldpd_callback*
+struct lldpd_callback {
+ TAILQ_ENTRY(lldpd_callback) next;
+ int fd; /* FD that will trigger this callback */
+ void(*function)(CALLBACK_SIG); /* Function called */
+ void *data; /* Optional data for this callback*/
};
struct lldpd {
int g_delay;
struct protocol *g_protocols;
- int g_multi; /* Set to 1 if multiple protocols */
- int g_probe_time;
+#ifdef ENABLE_LISTENVLAN
int g_listen_vlans;
+#endif
#ifdef ENABLE_LLDPMED
int g_noinventory;
#endif
+ int g_advertise_version;
time_t g_lastsent;
int g_lastrid;
/* Unix socket handling */
int g_ctl;
- TAILQ_HEAD(, lldpd_client) g_clients;
- char *g_mgmt_pattern;
+ TAILQ_HEAD(, lldpd_callback) g_callbacks;
- struct lldpd_chassis g_lchassis;
+ char *g_mgmt_pattern;
+#define LOCAL_CHASSIS(cfg) ((struct lldpd_chassis *)(TAILQ_FIRST(&cfg->g_chassis)))
+ TAILQ_HEAD(, lldpd_chassis) g_chassis;
TAILQ_HEAD(, lldpd_hardware) g_hardware;
- TAILQ_HEAD(, lldpd_vif) g_vif;
};
+typedef void(*lldpd_ifhandlers)(struct lldpd *, struct ifaddrs *);
+
enum hmsg_type {
HMSG_NONE,
HMSG_GET_INTERFACES,
- HMSG_GET_CHASSIS,
+ HMSG_GET_NB_PORTS,
HMSG_GET_PORT,
+ HMSG_GET_CHASSIS,
HMSG_GET_VLANS,
HMSG_SET_LOCATION,
HMSG_SHUTDOWN
#define MAX_HMSGSIZE 8192
/* lldpd.c */
-void lldpd_cleanup(struct lldpd *);
-void lldpd_hardware_cleanup(struct lldpd_hardware *);
+struct lldpd_hardware *lldpd_get_hardware(struct lldpd *,
+ char *, int, struct lldpd_ops *);
+struct lldpd_hardware *lldpd_alloc_hardware(struct lldpd *, char *);
+void lldpd_hardware_cleanup(struct lldpd*, struct lldpd_hardware *);
#ifdef ENABLE_DOT1
void lldpd_vlan_cleanup(struct lldpd_port *);
#endif
void lldpd_remote_cleanup(struct lldpd *, struct lldpd_hardware *, int);
-void lldpd_port_cleanup(struct lldpd_port *);
-void lldpd_chassis_cleanup(struct lldpd_chassis *);
+void lldpd_port_cleanup(struct lldpd_port *, int);
+void lldpd_chassis_cleanup(struct lldpd_chassis *, int);
+int lldpd_callback_add(struct lldpd *, int, void(*fn)(CALLBACK_SIG), void *);
+void lldpd_callback_del(struct lldpd *, int, void(*fn)(CALLBACK_SIG));
+int lldpd_main(int, char **);
/* lldp.c */
int lldp_send(PROTO_SEND_SIG);
int ctl_create(char *);
int ctl_connect(char *);
void ctl_cleanup(char *);
-int ctl_accept(struct lldpd *, int);
-int ctl_close(struct lldpd *, int);
+void ctl_accept(struct lldpd *, struct lldpd_callback *);
void ctl_msg_init(struct hmsg *, enum hmsg_type);
int ctl_msg_send(int, struct hmsg *);
int ctl_msg_recv(int, struct hmsg *);
int ctl_msg_pack_structure(char *, void *, unsigned int, struct hmsg *, void **);
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_wireless(struct lldpd *, const char *);
-int iface_is_vlan(struct lldpd *, const char *);
-int iface_is_bond(struct lldpd *, const char *);
-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 *);
+/* interfaces.c */
+void lldpd_ifh_bond(struct lldpd *, struct ifaddrs *);
+void lldpd_ifh_eth(struct lldpd *, struct ifaddrs *);
+#ifdef ENABLE_DOT1
+void lldpd_ifh_vlan(struct lldpd *, struct ifaddrs *);
+#endif
+void lldpd_ifh_mgmt(struct lldpd *, struct ifaddrs *);
+
+/* dmi.c */
#ifdef ENABLE_LLDPMED
-char *dmi_hw();
-char *dmi_fw();
-char *dmi_sn();
-char *dmi_manuf();
-char *dmi_model();
-char *dmi_asset();
+char *dmi_hw(void);
+char *dmi_fw(void);
+char *dmi_sn(void);
+char *dmi_manuf(void);
+char *dmi_model(void);
+char *dmi_asset(void);
#endif
/* log.c */
-void log_init(int);
-void log_warn(const char *, ...);
-#define LLOG_WARN(x,...) log_warn("%s: " x, __FUNCTION__, ##__VA_ARGS__)
-void log_warnx(const char *, ...);
-#define LLOG_WARNX(x,...) log_warnx("%s: " x, __FUNCTION__, ##__VA_ARGS__)
-void log_info(const char *, ...);
-#define LLOG_INFO(x,...) log_info("%s: " x, __FUNCTION__, ##__VA_ARGS__)
-void log_debug(const char *, ...);
-#define LLOG_DEBUG(x,...) log_debug("%s: " x, __FUNCTION__, ##__VA_ARGS__)
+void log_init(int, const char *);
+void log_warn(const char *, ...) __attribute__ ((format (printf, 1, 2)));
+#define LLOG_WARN(x,...) log_warn("%s: " x, __FUNCTION__ , ## __VA_ARGS__)
+void log_warnx(const char *, ...) __attribute__ ((format (printf, 1, 2)));
+#define LLOG_WARNX(x,...) log_warnx("%s: " x, __FUNCTION__ , ## __VA_ARGS__)
+void log_info(const char *, ...) __attribute__ ((format (printf, 1, 2)));
+#define LLOG_INFO(x,...) log_info("%s: " x, __FUNCTION__ , ## __VA_ARGS__)
+void log_debug(const char *, ...) __attribute__ ((format (printf, 1, 2)));
+#define LLOG_DEBUG(x,...) log_debug("%s: " x, __FUNCTION__ , ## __VA_ARGS__)
void fatal(const char *);
void fatalx(const char *);
/* agent.c */
-void agent_shutdown();
-void agent_init(struct lldpd *, int);
+void agent_shutdown(void);
+void agent_init(struct lldpd *, char *, int);
/* agent_priv.c */
-void agent_priv_register_domain();
-
-/* strlcpy.c */
-size_t strlcpy(char *, const char *, size_t);
-
-/* iov.c */
-void iov_dump(struct lldpd_frame **, struct iovec *, int);
-u_int16_t iov_checksum(struct iovec *, int, int);
+void agent_priv_register_domain(void);
/* client.c */
struct client_handle {
void (*handle)(struct lldpd*, struct hmsg*, struct hmsg*);
};
-void client_handle_client(struct lldpd *, struct lldpd_client *,
- char *, int);
+void client_handle_client(struct lldpd *, struct lldpd_callback *,
+ char *, int);
void client_handle_none(struct lldpd *, struct hmsg *,
struct hmsg *);
void client_handle_get_interfaces(struct lldpd *, struct hmsg *,
/* priv.c */
void priv_init(char*);
-int priv_ctl_create();
-void priv_ctl_cleanup();
-char *priv_gethostbyname();
+int priv_ctl_create(void);
+void priv_ctl_cleanup(void);
+char *priv_gethostbyname(void);
int priv_open(char*);
int priv_ethtool(char*, struct ethtool_cmd*);
-int priv_iface_init(struct lldpd_hardware *, int);
-int priv_iface_multicast(char *, u_int8_t *, int);
+int priv_iface_init(const char *);
+int priv_iface_multicast(const char *, u_int8_t *, int);
int priv_snmp_socket(struct sockaddr_un *);
/* privsep_fdpass.c */