static void display_med(struct writer *w, lldpctl_atom_t *port) { lldpctl_atom_t *medpolicies, *medpolicy; lldpctl_atom_t *medlocations, *medlocation; lldpctl_atom_t *caelements, *caelement; long int cap = lldpctl_atom_get_int(port, lldpctl_k_chassis_med_cap); const char *type; if (lldpctl_atom_get_int(port, lldpctl_k_chassis_med_type) <= 0) return; tag_start(w, "lldp-med", "LLDP-MED"); tag_datatag(w, "device-type", "Device Type", lldpctl_atom_get_str(port, lldpctl_k_chassis_med_type)); display_med_capability(w, cap, LLDP_MED_CAP_CAP, "Capabilities"); display_med_capability(w, cap, LLDP_MED_CAP_POLICY, "Policy"); display_med_capability(w, cap, LLDP_MED_CAP_LOCATION, "Location"); display_med_capability(w, cap, LLDP_MED_CAP_MDI_PSE, "MDI/PSE"); display_med_capability(w, cap, LLDP_MED_CAP_MDI_PD, "MDI/PD"); display_med_capability(w, cap, LLDP_MED_CAP_IV, "Inventory"); /* LLDP MED policies */ medpolicies = lldpctl_atom_get(port, lldpctl_k_port_med_policies); lldpctl_atom_foreach(medpolicies, medpolicy) { if (lldpctl_atom_get_int(medpolicy, lldpctl_k_med_policy_type) <= 0) continue; tag_start(w, "policy", "LLDP-MED Network Policy for"); tag_attr(w, "apptype", "", lldpctl_atom_get_str(medpolicy, lldpctl_k_med_policy_type)); tag_attr(w, "defined", "Defined", (lldpctl_atom_get_int(medpolicy, lldpctl_k_med_policy_unknown) > 0)?"no":"yes"); if (lldpctl_atom_get_int(medpolicy, lldpctl_k_med_policy_tagged) > 0) { int vid = lldpctl_atom_get_int(medpolicy, lldpctl_k_med_policy_vid); tag_start(w, "vlan", "VLAN"); if (vid == 0) { tag_attr(w, "vid", "", "priority"); } else if (vid == 4095) { tag_attr(w, "vid", "", "reserved"); } else { tag_attr(w, "vid", "", lldpctl_atom_get_str(medpolicy, lldpctl_k_med_policy_vid)); } tag_end(w); } tag_datatag(w, "priority", "Priority", lldpctl_atom_get_str(medpolicy, lldpctl_k_med_policy_priority)); tag_datatag(w, "dscp", "DSCP Value", lldpctl_atom_get_str(medpolicy, lldpctl_k_med_policy_dscp)); tag_end(w); } lldpctl_atom_dec_ref(medpolicies); /* LLDP MED locations */ medlocations = lldpctl_atom_get(port, lldpctl_k_port_med_locations); lldpctl_atom_foreach(medlocations, medlocation) { int format = lldpctl_atom_get_int(medlocation, lldpctl_k_med_location_format); if (format <= 0) continue; tag_start(w, "location", "LLDP-MED Location Identification"); tag_attr(w, "type", "Type", lldpctl_atom_get_str(medlocation, lldpctl_k_med_location_format)); switch (format) { case LLDP_MED_LOCFORMAT_COORD: tag_attr(w, "geoid", "Geoid", lldpctl_atom_get_str(medlocation, lldpctl_k_med_location_geoid)); tag_datatag(w, "lat", "Latitude", lldpctl_atom_get_str(medlocation, lldpctl_k_med_location_latitude)); tag_datatag(w, "lon", "Longitude", lldpctl_atom_get_str(medlocation, lldpctl_k_med_location_longitude)); tag_start(w, "altitude", "Altitude"); tag_attr(w, "unit", "", lldpctl_atom_get_str(medlocation, lldpctl_k_med_location_altitude_unit)); tag_data(w, lldpctl_atom_get_str(medlocation, lldpctl_k_med_location_altitude)); tag_end(w); break; case LLDP_MED_LOCFORMAT_CIVIC: tag_datatag(w, "country", "Country", lldpctl_atom_get_str(medlocation, lldpctl_k_med_location_country)); caelements = lldpctl_atom_get(medlocation, lldpctl_k_med_location_ca_elements); lldpctl_atom_foreach(caelements, caelement) { type = lldpctl_atom_get_str(caelement, lldpctl_k_med_civicaddress_type); tag_datatag(w, totag(type), type, lldpctl_atom_get_str(caelement, lldpctl_k_med_civicaddress_value)); } lldpctl_atom_dec_ref(caelements); break; case LLDP_MED_LOCFORMAT_ELIN: tag_datatag(w, "ecs", "ECS ELIN", lldpctl_atom_get_str(medlocation, lldpctl_k_med_location_elin)); break; }
static void display_med(struct writer *w, struct lldpd_chassis *chassis, struct lldpd_port *port) { int i; char *value; tag_start(w, "lldp-med", "LLDP-MED"); tag_datatag(w, "device-type", "Device Type", map_lookup(chassis_med_type_map, chassis->c_med_type)); display_med_capability(w, chassis, LLDPMED_CAP_CAP); display_med_capability(w, chassis, LLDPMED_CAP_POLICY); display_med_capability(w, chassis, LLDPMED_CAP_LOCATION); display_med_capability(w, chassis, LLDPMED_CAP_MDI_PSE); display_med_capability(w, chassis, LLDPMED_CAP_MDI_PD); display_med_capability(w, chassis, LLDPMED_CAP_IV); for (i = 0; i < LLDPMED_APPTYPE_LAST; i++) { if (i+1 == port->p_med_policy[i].type) { tag_start(w, "policy", "LLDP-MED Network Policy for"); tag_attr(w, "apptype", "AppType", u2str(port->p_med_policy[i].type)); tag_attr(w, "defined", "Defined", (port->p_med_policy[i].unknown)?"no":"yes"); tag_datatag(w, "descr", "", map_lookup(port_med_policy_map, port->p_med_policy[i].type)); if (port->p_med_policy[i].tagged) { tag_start(w, "vlan", "VLAN"); if (port->p_med_policy[i].vid == 0) { tag_attr(w, "vid", "", "priority"); } else if (port->p_med_policy[i].vid == 4095) { tag_attr(w, "vid", "", "reserved"); } else { tag_attr(w, "vid", "", u2str(port->p_med_policy[i].vid)); } tag_end(w); } tag_datatag(w, "priority", "Layer 2 Priority", u2str(port->p_med_policy[i].priority)); tag_datatag(w, "dscp", "DSCP Value", u2str(port->p_med_policy[i].dscp)); tag_end(w); } } for (i = 0; i < LLDPMED_LOCFORMAT_LAST; i++) { if (i+1 == port->p_med_location[i].format) { tag_start(w, "location", "LLDP-MED Location Identification"); switch(port->p_med_location[i].format) { case LLDPMED_LOCFORMAT_COORD: tag_attr(w, "type", "Type", "coordinates"); if (port->p_med_location[i].data_len != 16) { tag_datatag(w, "error", "Error", "bad data length"); } else { u_int64_t l; u_int8_t v; char * s; v = *(u_int8_t*)(port->p_med_location[i].data + 15); tag_attr(w, "geoid", "Geoid", map_lookup(port_med_geoid_map,v)); /* Latitude and longitude */ memcpy(&l, port->p_med_location[i].data, sizeof(u_int64_t)); l = (ntohll(l) & 0x03FFFFFFFF000000ULL) >> 24; display_latitude_or_longitude(w,0, l); memcpy(&l, port->p_med_location[i].data + 5, sizeof(u_int64_t)); l = (ntohll(l) & 0x03FFFFFFFF000000ULL) >> 24; display_latitude_or_longitude(w,1, l); /* Altitude */ memcpy(&l, port->p_med_location[i].data + 10, sizeof(u_int64_t)); l = (ntohll(l) & 0x3FFFFFFF000000ULL) >> 24; display_fixed_precision(l, 22, 8, 1, &s); tag_start(w, "altitude", "Altitude"); switch ((*(u_int8_t*)(port->p_med_location[i].data + 10)) & 0xf0) { case (1 << 4): tag_attr(w, "unit", "", "m"); break; case (2 << 4): tag_attr(w, "unit", "", "floor"); break; default: tag_attr(w, "unit", "", "unknown"); } tag_data(w,s); tag_end(w); } break; case LLDPMED_LOCFORMAT_CIVIC: tag_attr(w, "type", "Type", "address"); if ((port->p_med_location[i].data_len < 3) || (port->p_med_location[i].data_len - 1 != *(u_int8_t*)port->p_med_location[i].data)) { tag_datatag(w, "error", "Error", "bad data length"); } else { int l = 4, n, catype, calength; char country[3]; country[0] = ((char *)port->p_med_location[i].data)[2]; country[1] = ((char *)port->p_med_location[i].data)[3]; country[2] = 0; tag_datatag(w, "country", "Country", country); while ((n = (port-> p_med_location[i].data_len - l)) >= 2) { catype = *(u_int8_t*)(port-> p_med_location[i].data + l); calength = *(u_int8_t*)(port-> p_med_location[i].data + l + 1); if (n < 2 + calength) { tag_datatag(w, "error", "Error", "bad data length"); break; } if ((value = strndup((char *)(port-> p_med_location[i].data + l + 2), calength)) == NULL) { fatalx("not enough memory"); break; } tag_datatag(w, map_lookup(civic_address_type_tags,catype), map_lookup(civic_address_type_values,catype), value); free(value); l += 2 + calength; } } break; case LLDPMED_LOCFORMAT_ELIN: if ((value = strndup((char *)(port-> p_med_location[i].data), port->p_med_location[i].data_len)) == NULL) { fatalx( "not enough memory"); break; } tag_attr(w, "type", "Type", "elin"); tag_datatag(w, "ecs", "ECS ELIN", value); free(value); break; default: tag_attr(w, "type", "", "unknown"); tag_datatag(w, "unknown", "Data", dump(port->p_med_location[i].data, port->p_med_location[i].data_len, 20, ' ')); } tag_end(w); } }