struct lldp_tlv *create_power_via_mdi_tlv(struct lldp_port *lldp_port) { struct lldp_tlv* tlv = initialize_tlv(); char OUI[3] = {0x00, 0x01, 0x0F}; char subtype = 2; if(tlv == NULL) return NULL; tlv->type = POWER_VIA_MDI_TLV; // Constant defined in tlv_00120f.h tlv->length = 7; // The Power Via MDI TLV length is always 7. tlv->info_string = malloc(7); if(tlv->info_string == NULL) { destroy_tlv(&tlv); return NULL; } memcpy(tlv->info_string, OUI, 3); memcpy(tlv->info_string, &subtype, 1); // Are there any devices in *NIX that support PSE or PD as per RFC 3621? return tlv; }
// MAC/PHY Configuration/Status TLV struct lldp_tlv *create_mac_phy_configuration_status_tlv(struct lldp_port *lldp_port) { struct lldp_tlv *tlv = initialize_tlv(); char OUI[3] = {0x00, 0x01, 0x0F}; char subtype = 1; if(tlv == NULL) return NULL; tlv->type = MAC_PHY_CONFIGURATION_STATUS_TLV; // Constant defined in tlv_00120f.h tlv->length = 9; // The MAC/PHY Configuration/Status TLV length is always 9. tlv->info_string = malloc(9); if(tlv->info_string == NULL) { destroy_tlv(&tlv); return NULL; } memcpy(&tlv->info_string[0], OUI, 3); memcpy(&tlv->info_string[3], &subtype, 1); /* memcpy(&tlv->info_string[4], &lldp_port->autoNegCapabilitiesAndSupport, 1); memcpy(&tlv->info_string[5], &lldp_port->ifMauAutoNegCapAdvertisedBits, 2); memcpy(&tlv->info_string[7], &lldp_port->ifMauType, 2); */ return tlv; }
struct lldp_tlv *create_end_of_lldpdu_tlv(struct lldp_port *lldp_port) { struct lldp_tlv* tlv = initialize_tlv(); tlv->type = END_OF_LLDPDU_TLV; // Constant defined in lldp_tlv.h tlv->length = 0; // The End of LLDPDU TLV is length 0. tlv->info_string = NULL; return tlv; }
// NB: Initial deployment will do IPv4 only... // struct lldp_tlv *create_management_address_tlv(struct lldp_port *lldp_port) { struct lldp_tlv *tlv = initialize_tlv(); uint32_t if_index = htonl(lldp_port->if_index); tlv->type = MANAGEMENT_ADDRESS_TLV; // Constant defined in lldp_tlv.h #define MGMT_ADDR_STR_LEN 1 #define MGMT_ADDR_SUBTYPE 1 #define IPV4_LEN 4 #define IF_NUM_SUBTYPE 1 #define IF_NUM 4 #define OID 1 #define OBJ_IDENTIFIER 0 // management address string length (1 octet) // management address subtype (1 octet) // management address (4 bytes for IPv4) // interface numbering subtype (1 octet) // interface number (4 bytes) // OID string length (1 byte) // object identifier (0 to 128 octets) tlv->length = MGMT_ADDR_STR_LEN + MGMT_ADDR_SUBTYPE + IPV4_LEN + IF_NUM_SUBTYPE + IF_NUM + OID + OBJ_IDENTIFIER ; //uint64_t tlv_offset = 0; tlv->info_string = calloc(1, tlv->length); // Management address string length // subtype of 1 byte + management address length, so 5 for IPv4 tlv->info_string[0] = 5; // 1 for IPv4 as per http://www.iana.org/assignments/address-family-numbers tlv->info_string[1] = 1; // Copy in our IP memcpy(&tlv->info_string[2], lldp_port->source_ipaddr, 4); // Interface numbering subtype... system port number in our case. tlv->info_string[6] = 3; // Interface number... 4 bytes long, or uint32_t memcpy(&tlv->info_string[7], &lldp_port->if_index, sizeof(uint32_t)); debug_printf(DEBUG_NORMAL, "Would stuff interface #: %d\n", if_index); // OID - 0 for us tlv->info_string[11] = 0; // object identifier... doesn't exist for us because it's not required, and we don't have an OID. return tlv; }
struct lldp_tlv *create_system_name_tlv(struct lldp_port *lldp_port) { struct lldp_tlv* tlv = initialize_tlv(); tlv->type = SYSTEM_NAME_TLV; // Constant defined in lldp_tlv.h tlv->length = strlen(lldp_systemname); tlv->info_string = calloc(1, tlv->length); memcpy(tlv->info_string, lldp_systemname, tlv->length); return tlv; }
struct lldp_tlv *create_port_description_tlv(struct lldp_port *lldp_port) { struct lldp_tlv* tlv = initialize_tlv(); tlv->type = PORT_DESCRIPTION_TLV; // onstant defined in lldp_tlv.h tlv->length = strlen(lldp_port->if_name); tlv->info_string = calloc(1, tlv->length); memcpy(&tlv->info_string[0], lldp_port->if_name, strlen(lldp_port->if_name)); return tlv; }
struct lldp_tlv *create_ttl_tlv(struct lldp_port *lldp_port) { struct lldp_tlv* tlv = initialize_tlv(); uint16_t ttl = htons(lldp_port->tx.txTTL); tlv->type = TIME_TO_LIVE_TLV; // Constant defined in lldp_tlv.h tlv->length = 2; // Static length defined by IEEE 802.1AB section 9.5.4 tlv->info_string = calloc(1, tlv->length); memcpy(tlv->info_string, &ttl, tlv->length); return tlv; }
struct lldp_tlv *create_system_capabilities_tlv(struct lldp_port *lldp_port) { struct lldp_tlv* tlv = initialize_tlv(); // Tell it we're a station for now... bit 7 uint16_t capabilities = htons(128); tlv->type = SYSTEM_CAPABILITIES_TLV; // Constant defined in lldp_tlv.h tlv->length = 4; tlv->info_string = calloc(1, tlv->length); memcpy(&tlv->info_string[0], &capabilities, sizeof(uint16_t)); memcpy(&tlv->info_string[2], &capabilities, sizeof(uint16_t)); return tlv; }
struct lldp_tlv *create_system_description_tlv(struct lldp_port *lldp_port) { struct lldp_tlv* tlv = initialize_tlv(); tlv->type = SYSTEM_DESCRIPTION_TLV; // Constant defined in lldp_tlv.h tlv->length = strlen(lldp_systemdesc); tlv->info_string = calloc(1, tlv->length); memcpy(tlv->info_string, lldp_systemdesc, tlv->length); return tlv; }
struct lldp_tlv *create_chassis_id_tlv(struct lldp_port *lldp_port) { struct lldp_tlv* tlv = initialize_tlv(); tlv->type = CHASSIS_ID_TLV; // Constant defined in lldp_tlv.h tlv->length = 7; //The size of a MAC + the size of the subtype (1 byte) tlv->info_string = calloc(1, tlv->length); // CHASSIS_ID_MAC_ADDRESS is a 1-byte value - 4 in this case. Defined in lldp_tlv.h tlv->info_string[0] = CHASSIS_ID_MAC_ADDRESS; // We need to start copying at the 2nd byte, so we use [1] here... // This reads "memory copy to the destination at the address of tlv->info_string[1] with the source my_mac for 6 bytes" (the size of a MAC address) memcpy(&tlv->info_string[1], &lldp_port->source_mac[0], 6); return tlv; }
struct lldp_tlv *create_port_id_tlv(struct lldp_port *lldp_port) { struct lldp_tlv* tlv = initialize_tlv(); tlv->type = PORT_ID_TLV; // Constant defined in lldp_tlv.h tlv->length = 1 + strlen(lldp_port->if_name); //The length of the interface name + the size of the subtype (1 byte) tlv->info_string = calloc(1, tlv->length); // PORT_ID_INTERFACE_NAME is a 1-byte value - 5 in this case. Defined in lldp_tlv.h tlv->info_string[0] = PORT_ID_INTERFACE_NAME; // We need to start copying at the 2nd byte, so we use [1] here... // This reads "memory copy to the destination at the address of tlv->info_string[1] with the source lldp_port->if_name for strlen(lldp_port->if_name) bytes" memcpy(&tlv->info_string[1], lldp_port->if_name, strlen(lldp_port->if_name)); return tlv; }
struct lldp_tlv *create_lldpmed_location_identification_tlv (struct lldp_port *lldp_port) { int j; int len = 0; int pos = 0; struct lldp_tlv *tlv = initialize_tlv(); //just 1, 2 or 3 is allowed for location data format, 0 is invalid, 4-255 is reserved for future use if ((lci.location_data_format < 1) || (lci.location_data_format > 3)) { debug_printf (DEBUG_NORMAL, "[ERROR] in config file: invalid location_data_format '%d' \n", lci.location_data_format); free(tlv); return NULL; } //set CATypes with no content "" to NULL, otherwise CAType with length 0 is created for (j = 0; j < 33; j++) { if ((lci.civic_ca[j] != NULL) && (strcmp (lci.civic_ca[j], "") == 0)) lci.civic_ca[j] = NULL; } //calculate LCI Length for Civic Location if (lci.location_data_format == LCI_CIVIC) { for (j = 0; j < 33; j++) { //printf ("%i\n", j); //(strlen(civic_ca[j]) > 0) && if ((lci.civic_ca[j] != NULL)) len += strlen (lci.civic_ca[j]) + 1 + 1;//length of CAvalue + CAtype + CAlength } len += 1 + 2;//add len for What and Countrycode tlv->length = 1 + len + 4 + 1;//1 for the LCI length field, LCI length plus 4 for the MED Header and 1 for Location Data Format } //length for coordinate based if (lci.location_data_format == LCI_COORDINATE) { int tmp = strlen (lci.coordinate_based_lci) / 2; if (tmp == 23) debug_printf (DEBUG_NORMAL, "Coordinate based LCI contains colons\n"); if ((tmp != 16) && (tmp != 23)) debug_printf (DEBUG_NORMAL, "coordinate_based_lci has wrong length '%d' \n", tmp); tlv->length = 16 + 5;//MED Header (5) + geo location is always 16 //printf ("geo loc data length calculated = %i \n", tlv->length); } //length for ELIN if (lci.location_data_format == LCI_ELIN) tlv->length = strlen (lci.elin) + 5; tlv->type = ORG_SPECIFIC_TLV; tlv->info_string = calloc(1, tlv->length); //MED-Header tlv->info_string[0] = 0x00; tlv->info_string[1] = 0x12; tlv->info_string[2] = 0xBB; tlv->info_string[3] = 3; //set Location Data Format tlv->info_string[4] = lci.location_data_format; //-------------------- // create Location ID //-------------------- //handle civic location LCI if (lci.location_data_format == 2) { tlv->info_string[5] = len;//LCI Length tlv->info_string[6] = lci.civic_what; tlv->info_string[7] = lci.civic_countrycode[0]; tlv->info_string[8] = lci.civic_countrycode[1]; pos = 9; debug_printf (DEBUG_NORMAL, "create civic location identification TLV\n"); //for(j = 0; j < 33; j++) //printf("CA typ %i len(%i) = %s \n", j, strlen(civic_ca[j]), civic_ca[j]); //printf("nr 12 %s",civic_ca[12]); for (j = 0; j < 33; j++) { //(strlen(civic_ca[j]) > 1) && if ((lci.civic_ca[j] != NULL)) { int calength = strlen (lci.civic_ca[j]); debug_printf (DEBUG_NORMAL, "CA Type %i with len %i contains %s \n", j, calength, lci.civic_ca[j]); tlv->info_string[pos] = j; pos++; tlv->info_string[pos] = calength; pos++; memcpy(&tlv->info_string[pos], lci.civic_ca[j], calength); pos += calength; } } } //handle ECS ELIN data format if (lci.location_data_format == 3) memcpy(&tlv->info_string[5], lci.elin, strlen(lci.elin)); //handling coordinate-based LCI if (lci.location_data_format == 1) { char temp[3]; char out[17]; // binary location + string terminator char *in = calloc (1, strlen(lci.coordinate_based_lci) + 1); int k, i, u; int counter = 0; //remove colons from string for (u = 0; u < strlen (lci.coordinate_based_lci); u++) { if (lci.coordinate_based_lci[u] != ':') { in[counter] = lci.coordinate_based_lci[u]; counter++; } } in[32] = '\0'; // initialize string terminators out[16] = '\0'; temp[2] = '\0'; debug_printf (DEBUG_NORMAL, "coordinate_based_lci: %s\n", lci.coordinate_based_lci); debug_printf (DEBUG_NORMAL, "coordinate_based without colons: %s \n", in); //convert string to hex for (i = 0; i < 16; i++) { temp[0] = in[i * 2]; temp[1] = in[i * 2 + 1]; out[i] = (char) strtol (temp, NULL, 16); } free (in); debug_printf (DEBUG_NORMAL, "out: "); for (i = 0; i < 16; i++) { //proper output requires unsigned char cast debug_printf (DEBUG_NORMAL, "%02x", (unsigned char)out[i]); } debug_printf (DEBUG_NORMAL, "\n"); memcpy(&tlv->info_string[5], out, 16); } return tlv; }