1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright (C) 2014 Tom Gundersen
7 Copyright (C) 2014 Susant Sahani
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
26 #include <sys/socket.h>
28 #include <linux/if_ether.h>
29 #include <net/ethernet.h>
30 #include <sys/types.h>
31 #include <arpa/inet.h>
37 #define TEST_LLDP_PORT "em1"
38 #define TEST_LLDP_TYPE_SYSTEM_NAME "systemd-lldp"
39 #define TEST_LLDP_TYPE_SYSTEM_DESC "systemd-lldp-desc"
41 static struct ether_addr mac_addr = {
42 .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
45 static int lldp_build_tlv_packet(tlv_packet **ret) {
46 _cleanup_tlv_packet_free_ tlv_packet *m = NULL;
47 const uint8_t lldp_dst[] = LLDP_MULTICAST_ADDR;
48 struct ether_header ether;
50 /* Append ethernet header */
51 memset(ðer, 0, sizeof(ether));
52 memcpy(ðer.ether_dhost, lldp_dst, ETHER_ADDR_LEN);
53 memcpy(ðer.ether_shost, &mac_addr, ETHER_ADDR_LEN);
54 ether.ether_type = htons(ETHERTYPE_LLDP);
56 assert_se(tlv_packet_new(&m) >= 0);
58 assert_se(tlv_packet_append_bytes(m, ðer, sizeof(struct ether_header)) >= 0);
60 assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_CHASSIS_ID) >= 0);
62 assert_se(tlv_packet_append_u8(m, LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS) >= 0);
63 assert_se(tlv_packet_append_bytes(m, &mac_addr, ETHER_ADDR_LEN) >= 0);
65 assert_se(lldp_tlv_packet_close_container(m) >= 0);
68 assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_PORT_ID) >= 0);
70 assert_se(tlv_packet_append_u8(m, LLDP_PORT_SUBTYPE_INTERFACE_NAME) >= 0);
71 assert_se(tlv_packet_append_bytes(m, TEST_LLDP_PORT, strlen(TEST_LLDP_PORT) + 1) >= 0);
73 assert_se(lldp_tlv_packet_close_container(m) >= 0);
76 assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_TTL) >= 0);
78 assert_se(tlv_packet_append_u16(m, 170) >= 0);
80 assert_se(lldp_tlv_packet_close_container(m) >= 0);
83 assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_SYSTEM_NAME) >= 0);
85 assert_se(tlv_packet_append_bytes(m, TEST_LLDP_TYPE_SYSTEM_NAME,
86 strlen(TEST_LLDP_TYPE_SYSTEM_NAME)) >= 0);
87 assert_se(lldp_tlv_packet_close_container(m) >= 0);
89 /* system descrition */
90 assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_SYSTEM_DESCRIPTION) >= 0);
92 assert_se(tlv_packet_append_bytes(m, TEST_LLDP_TYPE_SYSTEM_DESC,
93 strlen(TEST_LLDP_TYPE_SYSTEM_DESC)) >= 0);
95 assert_se(lldp_tlv_packet_close_container(m) >= 0);
97 /* Mark end of packet */
98 assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_END) >= 0);
99 assert_se(lldp_tlv_packet_close_container(m) >= 0);
108 static int lldp_parse_chassis_tlv(tlv_packet *m, uint8_t *type) {
112 assert_se(lldp_tlv_packet_enter_container(m, LLDP_TYPE_CHASSIS_ID) >= 0);
113 assert_se(tlv_packet_read_u8(m, &subtype) >= 0);
116 case LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS:
118 *type = LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS;
119 assert_se(tlv_packet_read_bytes(m, &p, &length) >= 0);
121 assert_se(memcmp(p, &mac_addr.ether_addr_octet, ETHER_ADDR_LEN) == 0);
125 assert_not_reached("Unhandled option");
128 assert_se(lldp_tlv_packet_exit_container(m) >= 0);
133 static int lldp_parse_port_id_tlv(tlv_packet *m) {
134 char *str = NULL, *p;
138 assert_se(lldp_tlv_packet_enter_container(m, LLDP_TYPE_PORT_ID) >= 0);
140 assert_se(tlv_packet_read_u8(m, &subtype) >= 0);
143 case LLDP_PORT_SUBTYPE_INTERFACE_NAME:
144 assert_se(tlv_packet_read_string(m, &str, &length) >= 0);
146 p = malloc0(length + 1);
148 strncpy(p, str, length-1);
150 assert_se(streq(p, TEST_LLDP_PORT) == 1);
153 assert_not_reached("Unhandled option");
156 assert_se(lldp_tlv_packet_exit_container(m) >= 0);
161 static int lldp_parse_system_name_tlv(tlv_packet *m) {
162 char *str = NULL, *p;
165 assert_se(lldp_tlv_packet_enter_container(m, LLDP_TYPE_SYSTEM_NAME) >= 0);
166 assert_se(tlv_packet_read_string(m, &str, &length) >= 0);
168 p = malloc0(length + 1);
169 strncpy(p, str, length);
171 assert_se(streq(p, TEST_LLDP_TYPE_SYSTEM_NAME) == 1);
173 assert_se(lldp_tlv_packet_exit_container(m) >= 0);
178 static int lldp_parse_system_desc_tlv(tlv_packet *m) {
179 char *str = NULL, *p;
182 assert_se(lldp_tlv_packet_enter_container(m, LLDP_TYPE_SYSTEM_DESCRIPTION) >= 0);
183 assert_se(tlv_packet_read_string(m, &str, &length) >= 0);
185 p = malloc0(length + 1);
187 strncpy(p, str, length);
189 assert_se(streq(p, TEST_LLDP_TYPE_SYSTEM_DESC) == 1);
191 assert_se(lldp_tlv_packet_exit_container(m) >= 0);
196 static int lldp_parse_ttl_tlv(tlv_packet *m) {
199 assert_se(lldp_tlv_packet_enter_container(m, LLDP_TYPE_TTL) >= 0);
200 assert_se(tlv_packet_read_u16(m, &ttl) >= 0);
202 assert_se(ttl == 170);
204 assert_se(lldp_tlv_packet_exit_container(m) >= 0);
209 static int lldp_parse_tlv_packet(tlv_packet *m, int len) {
212 assert_se(tlv_packet_parse_pdu(m, len) >= 0);
213 assert_se(lldp_parse_chassis_tlv(m, &subtype) >= 0);
214 assert_se(lldp_parse_port_id_tlv(m) >= 0);
215 assert_se(lldp_parse_system_name_tlv(m) >= 0);
216 assert_se(lldp_parse_ttl_tlv(m) >= 0);
217 assert_se(lldp_parse_system_desc_tlv(m) >= 0);
222 int main(int argc, char *argv[]) {
223 _cleanup_tlv_packet_free_ tlv_packet *tlv = NULL;
226 lldp_build_tlv_packet(&tlv);
228 /* parse the packet */
229 tlv_packet_parse_pdu(tlv, tlv->length);
232 lldp_parse_tlv_packet(tlv, tlv->length);