#endif
#ifdef ENABLE_DOT1
{ HMSG_GET_VLANS, client_handle_port_related },
+ { HMSG_GET_PPVIDS, client_handle_port_related },
+ { HMSG_GET_PIDS, client_handle_port_related },
#endif
{ HMSG_SHUTDOWN, client_handle_shutdown },
{ 0, NULL } };
s->hdr.len = sizeof(int);
break;
case HMSG_GET_VLANS:
+ case HMSG_GET_PPVIDS:
+ case HMSG_GET_PIDS:
case HMSG_GET_PORT:
case HMSG_GET_CHASSIS:
/* We read the index which is right after the interface name */
return;
}
break;
+ case HMSG_GET_PPVIDS:
+ if (ctl_msg_pack_list(
+ STRUCT_LLDPD_PPVID,
+ &port->p_ppvids,
+ sizeof(struct lldpd_ppvid), s, &p) == -1) {
+ LLOG_WARNX("unable to send ppvids information for "
+ "interface %s for %d", ifname, r->hdr.pid);
+ s->hdr.len = -1;
+ return;
+ }
+ break;
+ case HMSG_GET_PIDS:
+ if (ctl_msg_pack_list(
+ STRUCT_LLDPD_PI,
+ &port->p_pids,
+ sizeof(struct lldpd_pi), s, &p) == -1) {
+ LLOG_WARNX("unable to send PI's information for "
+ "interface %s for %d", ifname, r->hdr.pid);
+ s->hdr.len = -1;
+ return;
+ }
+ break;
#endif
case HMSG_GET_PORT:
if (ctl_msg_pack_structure(STRUCT_LLDPD_PORT,
TAILQ_HEAD(interfaces, lldpd_interface);
#ifdef ENABLE_DOT1
TAILQ_HEAD(vlans, lldpd_vlan);
+TAILQ_HEAD(ppvids, lldpd_ppvid);
+TAILQ_HEAD(pids, lldpd_pi);
#endif
#define ntohll(x) (((u_int64_t)(ntohl((int)((x << 32) >> 32))) << 32) | \
fatalx("get_vlans: unable to retrieve the list of vlans");
return 1;
}
+
+static int
+get_ppvids(int s, struct ppvids *pvs, char *interface, int nb)
+{
+ void *p;
+ struct hmsg *h;
+
+ if ((h = (struct hmsg *)malloc(MAX_HMSGSIZE)) == NULL)
+ fatal(NULL);
+ ctl_msg_init(h, HMSG_GET_PPVIDS);
+ strlcpy((char *)&h->data, interface, IFNAMSIZ);
+ memcpy((char*)&h->data + IFNAMSIZ, &nb, sizeof(int));
+ h->hdr.len += IFNAMSIZ + sizeof(int);
+ if (ctl_msg_send(s, h) == -1)
+ fatalx("get_ppvids: unable to send request");
+ if (ctl_msg_recv(s, h) == -1)
+ fatalx("get_ppvids: unable to receive answer");
+ if (h->hdr.type != HMSG_GET_PPVIDS)
+ fatalx("get_ppvids: unknown answer type received");
+ p = &h->data;
+ if (ctl_msg_unpack_list(STRUCT_LLDPD_PPVID,
+ pvs, sizeof(struct lldpd_ppvid), h, &p) == -1)
+ fatalx("get_ppvids: unable to retrieve the list of ppvids");
+ return 1;
+}
+
+static int
+get_pids(int s, struct pids *pids, char *interface, int nb)
+{
+ void *p;
+ struct hmsg *h;
+
+ if ((h = (struct hmsg *)malloc(MAX_HMSGSIZE)) == NULL)
+ fatal(NULL);
+ ctl_msg_init(h, HMSG_GET_PIDS);
+ strlcpy((char *)&h->data, interface, IFNAMSIZ);
+ memcpy((char*)&h->data + IFNAMSIZ, &nb, sizeof(int));
+ h->hdr.len += IFNAMSIZ + sizeof(int);
+ if (ctl_msg_send(s, h) == -1)
+ fatalx("get_pids: unable to send request");
+ if (ctl_msg_recv(s, h) == -1)
+ fatalx("get_pids: unable to receive answer");
+ if (h->hdr.type != HMSG_GET_PIDS)
+ fatalx("get_ppvids: unknown answer type received");
+ p = &h->data;
+ if (ctl_msg_unpack_list(STRUCT_LLDPD_PI,
+ pids, sizeof(struct lldpd_pi), h, &p) == -1)
+ fatalx("get_pids: unable to retrieve the list of pids");
+ return 1;
+}
#endif
static int
tag_end(w);
}
}
+
+static void
+display_ppvids(struct writer *w, struct lldpd_port *port)
+{
+ struct lldpd_ppvid *ppvid;
+ TAILQ_FOREACH(ppvid, &port->p_ppvids, p_entries) {
+ tag_start(w, "ppvid", "PPVID");
+ switch(ppvid->p_cap_status) {
+ case LLDPD_PPVID_CAP_SUPPORTED:
+ tag_attr(w, "ppvid-cap-status supported", "",
+ u2str(ppvid->p_cap_status));
+ break;
+ case LLDPD_PPVID_CAP_ENABLED:
+ tag_attr(w, "ppvid-cap-status enabled", "",
+ u2str(ppvid->p_cap_status));
+ break;
+ case LLDPD_PPVID_CAP_SUPPORTED_AND_ENABLED:
+ tag_attr(w,
+ "ppvid-cap-status supported, enabled",
+ "",
+ u2str(ppvid->p_cap_status));
+ break;
+ }
+ tag_attr(w, "ppvid", "", u2str(ppvid->p_ppvid));
+ tag_end(w);
+ }
+}
+
+static void
+display_pids(struct writer *w, struct lldpd_port *port)
+{
+ struct lldpd_pi *pi;
+ TAILQ_FOREACH(pi, &port->p_pids, p_entries) {
+ tag_start(w, "pi", "PI");
+ tag_data(w, pi->p_pi);
+ tag_end(w);
+ }
+}
#endif
static const char*
struct interfaces ifs;
#ifdef ENABLE_DOT1
struct vlans vls;
+ struct ppvids pvs;
+ struct pids pids;
#endif
struct lldpd_interface *iff;
struct lldpd_chassis chassis;
if (!TAILQ_EMPTY(&port.p_vlans) || port.p_pvid) {
display_vlans(w, &port);
}
+ if (get_ppvids(s, &pvs, iff->name, i) != -1)
+ memcpy(&port.p_ppvids, &pvs, sizeof(struct ppvids));
+ if (!TAILQ_EMPTY(&port.p_ppvids)) {
+ display_ppvids(w, &port);
+ }
+ if (get_pids(s, &pids, iff->name, i) != -1)
+ memcpy(&port.p_pids, &pids, sizeof(struct pids));
+ if (!TAILQ_EMPTY(&port.p_pids)) {
+ display_pids(w, &port);
+ }
#endif
#ifdef ENABLE_LLDPMED
if (port.p_med_cap_enabled) {
#ifdef ENABLE_DOT1
const u_int8_t dot1[] = LLDP_TLV_ORG_DOT1;
struct lldpd_vlan *vlan;
+ struct lldpd_ppvid *ppvid;
+ struct lldpd_pi *pi;
#endif
#ifdef ENABLE_DOT3
const u_int8_t dot3[] = LLDP_TLV_ORG_DOT3;
goto toobig;
#ifdef ENABLE_DOT1
+ /* Port VLAN ID */
+ if(port->p_pvid != 0) {
+ if (!(
+ POKE_START_LLDP_TLV(LLDP_TLV_ORG) &&
+ POKE_BYTES(dot1, sizeof(dot1)) &&
+ POKE_UINT8(LLDP_TLV_DOT1_PVID) &&
+ POKE_UINT16(port->p_pvid) &&
+ POKE_END_LLDP_TLV)) {
+ goto toobig;
+ }
+ }
+ /* Port and Protocol VLAN IDs */
+ TAILQ_FOREACH(ppvid, &port->p_ppvids, p_entries) {
+ if (!(
+ POKE_START_LLDP_TLV(LLDP_TLV_ORG) &&
+ POKE_BYTES(dot1, sizeof(dot1)) &&
+ POKE_UINT8(LLDP_TLV_DOT1_PPVID) &&
+ POKE_UINT8(ppvid->p_cap_status) &&
+ POKE_UINT16(ppvid->p_ppvid) &&
+ POKE_END_LLDP_TLV)) {
+ goto toobig;
+ }
+ }
/* VLANs */
TAILQ_FOREACH(vlan, &port->p_vlans, v_entries) {
if (!(
POKE_END_LLDP_TLV))
goto toobig;
}
+ /* Protocol Identities */
+ TAILQ_FOREACH(pi, &port->p_pids, p_entries) {
+ if (!(
+ POKE_START_LLDP_TLV(LLDP_TLV_ORG) &&
+ POKE_BYTES(dot1, sizeof(dot1)) &&
+ POKE_UINT8(LLDP_TLV_DOT1_PI) &&
+ POKE_UINT8(strlen(pi->p_pi)) &&
+ POKE_BYTES(pi->p_pi, strlen(pi->p_pi)) &&
+ POKE_END_LLDP_TLV))
+ goto toobig;
+ }
#endif
#ifdef ENABLE_DOT3
#ifdef ENABLE_DOT1
struct lldpd_vlan *vlan;
int vlan_len;
+ struct lldpd_ppvid *ppvid;
+ struct lldpd_pi *pi;
+ int pi_len;
#endif
if ((chassis = calloc(1, sizeof(struct lldpd_chassis))) == NULL) {
}
#ifdef ENABLE_DOT1
TAILQ_INIT(&port->p_vlans);
+ TAILQ_INIT(&port->p_ppvids);
+ TAILQ_INIT(&port->p_pids);
#endif
length = s;
CHECK_TLV_SIZE(6, "PVID");
port->p_pvid = PEEK_UINT16;
break;
+ case LLDP_TLV_DOT1_PPVID:
+ CHECK_TLV_SIZE(7, "PPVID");
+ /* validation needed */
+ /* PPVID has to be unique if more than
+ one PPVID TLVs are received -
+ discard if duplicate */
+ /* if support bit is not set and
+ enabled bit is set - PPVID TLV is
+ considered error and discarded */
+ /* if PPVID > 4096 - bad and discard */
+ if ((ppvid = (struct lldpd_ppvid *)calloc(1,
+ sizeof(struct lldpd_ppvid))) == NULL) {
+ LLOG_WARN("unable to alloc ppvid "
+ "structure for "
+ "tlv received on %s",
+ hardware->h_ifname);
+ goto malformed;
+ }
+ ppvid->p_cap_status = PEEK_UINT8;
+ ppvid->p_ppvid = PEEK_UINT16;
+ TAILQ_INSERT_TAIL(&port->p_ppvids,
+ ppvid, p_entries);
+ break;
+ case LLDP_TLV_DOT1_PI:
+ /* validation needed */
+ /* PI has to be unique if more than
+ one PI TLVs are received - discard
+ if duplicate ?? */
+ CHECK_TLV_SIZE(5, "PI");
+ if ((pi = (struct lldpd_pi *)calloc(1,
+ sizeof(struct lldpd_pi))) == NULL) {
+ LLOG_WARN("unable to alloc PI "
+ "structure for "
+ "tlv received on %s",
+ hardware->h_ifname);
+ goto malformed;
+ }
+ pi_len = PEEK_UINT8;
+ CHECK_TLV_SIZE(1 + pi_len, "PI");
+ if ((pi->p_pi =
+ (char *)calloc(1, pi_len + 1)) == NULL) {
+ LLOG_WARN("unable to alloc pid name for "
+ "tlv received on %s",
+ hardware->h_ifname);
+ goto malformed;
+ }
+ PEEK_BYTES(pi->p_pi, pi_len);
+ TAILQ_INSERT_TAIL(&port->p_pids,
+ pi, p_entries);
+ break;
default:
/* Unknown Dot1 TLV, ignore it */
hardware->h_rx_unrecognized_cnt++;
#endif
#ifdef ENABLE_DOT1
TAILQ_INIT(&hardware->h_lport.p_vlans);
+ TAILQ_INIT(&hardware->h_lport.p_ppvids);
+ TAILQ_INIT(&hardware->h_lport.p_pids);
#endif
return hardware;
}
free(vlan);
}
}
+
+void
+lldpd_ppvid_cleanup(struct lldpd_port *port)
+{
+ struct lldpd_ppvid *ppvid, *ppvid_next;
+ for (ppvid = TAILQ_FIRST(&port->p_ppvids);
+ ppvid != NULL;
+ ppvid = ppvid_next) {
+ ppvid_next = TAILQ_NEXT(ppvid, p_entries);
+ TAILQ_REMOVE(&port->p_ppvids, ppvid, p_entries);
+ free(ppvid);
+ }
+}
+
+void
+lldpd_pi_cleanup(struct lldpd_port *port)
+{
+ struct lldpd_pi *pi, *pi_next;
+ for (pi = TAILQ_FIRST(&port->p_pids);
+ pi != NULL;
+ pi = pi_next) {
+ free(pi->p_pi);
+ pi_next = TAILQ_NEXT(pi, p_entries);
+ TAILQ_REMOVE(&port->p_pids, pi, p_entries);
+ free(pi);
+ }
+}
#endif
/* If `all' is true, clear all information, including information that
#endif
#ifdef ENABLE_DOT1
lldpd_vlan_cleanup(port);
+ lldpd_ppvid_cleanup(port);
+ lldpd_pi_cleanup(port);
#endif
free(port->p_id);
free(port->p_descr);
static char *
lldpd_get_os_release() {
static char release[1024];
+ char line[1024];
+ char *key, *val;
+ char *ptr1 = release;
+ char *ptr2 = release;
FILE *fp = fopen("/etc/os-release", "r");
if (!fp) {
return NULL;
}
- char line[1024];
- char *key, *val;
-
while ((fgets(line, 1024, fp) != NULL)) {
key = strtok(line, "=");
val = strtok(NULL, "=");
fclose(fp);
/* Remove trailing newline and all " in the string. */
- char *ptr1 = release;
- char *ptr2 = release;
while (*ptr1 != 0) {
if ((*ptr1 == '"') || (*ptr1 == '\n')) {
++ptr1;
#define USING_AGENTX_SUBAGENT_MODULE 1
#ifdef ENABLE_DOT1
+#define LLDPD_PPVID_CAP_SUPPORTED 0x01
+#define LLDPD_PPVID_CAP_ENABLED 0x02
+#define LLDPD_PPVID_CAP_SUPPORTED_AND_ENABLED 0x03
+
+struct lldpd_ppvid {
+ TAILQ_ENTRY(lldpd_ppvid) p_entries;
+ u_int8_t p_cap_status;
+ u_int16_t p_ppvid;
+};
+#define STRUCT_LLDPD_PPVID "(Lbw)"
+
struct lldpd_vlan {
TAILQ_ENTRY(lldpd_vlan) v_entries;
char *v_name;
u_int16_t v_vid;
};
#define STRUCT_LLDPD_VLAN "(Lsw)"
+
+struct lldpd_pi {
+ TAILQ_ENTRY(lldpd_pi) p_entries;
+ char *p_pi;
+};
+#define STRUCT_LLDPD_PI "(Ls)"
#endif
#ifdef ENABLE_LLDPMED
#endif
#ifdef ENABLE_DOT1
-#define STRUCT_LLDPD_PORT_DOT1 "wPP"
+#define STRUCT_LLDPD_PORT_DOT1 "wPPP"
u_int16_t p_pvid;
TAILQ_HEAD(, lldpd_vlan) p_vlans;
+ TAILQ_HEAD(, lldpd_ppvid) p_ppvids;
+ TAILQ_HEAD(, lldpd_pi) p_pids;
#else
#define STRUCT_LLDPD_PORT_DOT1 ""
#endif
HMSG_GET_PORT,
HMSG_GET_CHASSIS,
HMSG_GET_VLANS,
+ HMSG_GET_PPVIDS,
+ HMSG_GET_PIDS,
HMSG_SET_LOCATION,
HMSG_SET_POLICY,
HMSG_SET_POWER,
struct lldpd_hardware *lldpd_alloc_hardware(struct lldpd *, char *);
void lldpd_hardware_cleanup(struct lldpd*, struct lldpd_hardware *);
#ifdef ENABLE_DOT1
+void lldpd_ppvid_cleanup(struct lldpd_port *);
void lldpd_vlan_cleanup(struct lldpd_port *);
+void lldpd_pi_cleanup(struct lldpd_port *);
#endif
void lldpd_remote_cleanup(struct lldpd *, struct lldpd_hardware *, int);
void lldpd_port_cleanup(struct lldpd*, struct lldpd_port *, int);