lldp-tlv.c revision 11e8357164694d8307dea5bcae017c98c5f125ab
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering This file is part of systemd.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Copyright (C) 2014 Tom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Copyright (C) 2014 Susant Sahani
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is free software; you can redistribute it and/or modify it
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering under the terms of the GNU Lesser General Public License as published by
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering (at your option) any later version.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is distributed in the hope that it will be useful, but
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Lesser General Public License for more details.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering You should have received a copy of the GNU Lesser General Public License
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poetteringtlv_packet *sd_lldp_packet_ref(tlv_packet *m) {
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poetteringtlv_packet *sd_lldp_packet_unref(tlv_packet *m) {
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering LIST_FOREACH_SAFE(section, s, n, m->sections)
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poetteringint tlv_packet_append_bytes(tlv_packet *m, const void *data, size_t data_length) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (m->length + data_length > ETHER_MAX_LEN)
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poetteringint tlv_packet_append_u8(tlv_packet *m, uint8_t data) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return tlv_packet_append_bytes(m, &data, sizeof(uint8_t));
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersenint tlv_packet_append_u16(tlv_packet *m, uint16_t data) {
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen return tlv_packet_append_bytes(m, &type, sizeof(uint16_t));
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poetteringint tlv_packet_append_u32(tlv_packet *m, uint32_t data) {
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering return tlv_packet_append_bytes(m, &type, sizeof(uint32_t));
6cb08a8930bdaca950b152b1e8b82466ed59511cLennart Poetteringint tlv_packet_append_string(tlv_packet *m, char *data, uint16_t size) {
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering return tlv_packet_append_bytes(m, data, size);
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poetteringint lldp_tlv_packet_open_container(tlv_packet *m, uint16_t type) {
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering return tlv_packet_append_u16(m, type << 9);
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poetteringint lldp_tlv_packet_close_container(tlv_packet *m) {
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering assert_return(m->container_pos, -EINVAL);
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering memcpy(&type, m->container_pos, sizeof(uint16_t));
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering type |= htons(((m->pdu + m->length) - (m->container_pos + 2)) & 0x01ff);
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering memcpy(m->container_pos, &type, sizeof(uint16_t));
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poetteringstatic inline int tlv_packet_read_internal(tlv_section *m, void **data) {
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poetteringint tlv_packet_read_u8(tlv_packet *m, uint8_t *data) {
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering r = tlv_packet_read_internal(m->container, &val);
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poetteringint tlv_packet_read_u16(tlv_packet *m, uint16_t *data) {
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering r = tlv_packet_read_internal(m->container, &val);
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poetteringint tlv_packet_read_u32(tlv_packet *m, uint32_t *data) {
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering r = tlv_packet_read_internal(m->container, &val);
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poetteringint tlv_packet_read_string(tlv_packet *m, char **data, uint16_t *data_length) {
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen r = tlv_packet_read_internal(m->container, &val);
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering m->container->read_pos += m->container->length;
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poetteringint tlv_packet_read_bytes(tlv_packet *m, uint8_t **data, uint16_t *data_length) {
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering r = tlv_packet_read_internal(m->container, &val);
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering m->container->read_pos += m->container->length;
d74fb368b18f0fbd9a4fe6f15691bbea7f3c4a01Tom Gundersen/* parse raw TLV packet */
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poetteringint tlv_packet_parse_pdu(tlv_packet *m, uint16_t size) {
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen /* extract ethernet herader */
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering p += sizeof(struct ether_header);
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering for (l = 0; l <= size; ) {
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersen if (section->type == LLDP_TYPE_END || section->type >=_LLDP_TYPE_MAX) {
4e0b8b17a7465653f4e7b819dad5f8e30d64c0c4Tom Gundersen LIST_INSERT_AFTER(section, m->sections, tail, section);
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poetteringint lldp_tlv_packet_enter_container(tlv_packet *m, uint16_t type) {
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersenint lldp_tlv_packet_exit_container(tlv_packet *m) {
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersenstatic int lldp_tlv_packet_read_u16_tlv(tlv_packet *tlv, uint16_t type, uint16_t *value) {
011842775f750711833526d5bba1b818713947f5Lennart Poettering r = lldp_tlv_packet_enter_container(tlv, type);
011842775f750711833526d5bba1b818713947f5Lennart Poettering (void) lldp_tlv_packet_exit_container(tlv);
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersenstatic int lldp_tlv_packet_read_string_tlv(tlv_packet *tlv, uint16_t type, char **data, uint16_t *length) {
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen r = lldp_tlv_packet_enter_container(tlv, type);
6cb08a8930bdaca950b152b1e8b82466ed59511cLennart Poettering r = tlv_packet_read_string(tlv, &s, length);
f4461e5641d53f27d6e76e0607bdaa9c0c58c1f6Lennart Poettering *data = (char *) s;
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poetteringint sd_lldp_packet_read_chassis_id(tlv_packet *tlv,
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering r = lldp_tlv_packet_enter_container(tlv, LLDP_TYPE_CHASSIS_ID);
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering r = tlv_packet_read_bytes(tlv, data, length);
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering (void) lldp_tlv_packet_exit_container(tlv);
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poetteringint sd_lldp_packet_read_port_id(tlv_packet *tlv,
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering r = lldp_tlv_packet_enter_container(tlv, LLDP_TYPE_PORT_ID);
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering r = tlv_packet_read_string(tlv, &s, length);
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering r = tlv_packet_read_bytes(tlv, data, length);
92ec902aad1ade7acbe50efd7b8ef87fbdc63af3Lennart Poettering (void) lldp_tlv_packet_exit_container(tlv);
92ec902aad1ade7acbe50efd7b8ef87fbdc63af3Lennart Poetteringint sd_lldp_packet_read_ttl(tlv_packet *tlv, uint16_t *ttl) {
92ec902aad1ade7acbe50efd7b8ef87fbdc63af3Lennart Poettering return lldp_tlv_packet_read_u16_tlv(tlv, LLDP_TYPE_TTL, ttl);
92ec902aad1ade7acbe50efd7b8ef87fbdc63af3Lennart Poetteringint sd_lldp_packet_read_system_name(tlv_packet *tlv,
92ec902aad1ade7acbe50efd7b8ef87fbdc63af3Lennart Poettering return lldp_tlv_packet_read_string_tlv(tlv, LLDP_TYPE_SYSTEM_NAME, data, length);
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poetteringint sd_lldp_packet_read_system_description(tlv_packet *tlv,
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering return lldp_tlv_packet_read_string_tlv(tlv, LLDP_TYPE_SYSTEM_DESCRIPTION, data, length);
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poetteringint sd_lldp_packet_read_port_description(tlv_packet *tlv,
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering return lldp_tlv_packet_read_string_tlv(tlv, LLDP_TYPE_PORT_DESCRIPTION, data, length);
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poetteringint sd_lldp_packet_read_system_capability(tlv_packet *tlv, uint16_t *data) {
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering return lldp_tlv_packet_read_u16_tlv(tlv, LLDP_TYPE_SYSTEM_CAPABILITIES, data);
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poetteringint sd_lldp_packet_get_destination_type(tlv_packet *tlv, int *dest) {
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt /* 802.1AB-2009, Table 7-1 */
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt if (!memcmp(&tlv->mac, LLDP_MAC_NEAREST_BRIDGE, ETH_ALEN))
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt *dest = SD_LLDP_DESTINATION_TYPE_NEAREST_BRIDGE;
636e813dc98ea40c58c6c85bc5e7e3c9f0904ea2Lennart Poettering else if (!memcmp(&tlv->mac, LLDP_MAC_NEAREST_NON_TPMR_BRIDGE, ETH_ALEN))
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering *dest = SD_LLDP_DESTINATION_TYPE_NEAREST_NON_TPMR_BRIDGE;
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering else if (!memcmp(&tlv->mac, LLDP_MAC_NEAREST_CUSTOMER_BRIDGE, ETH_ALEN))