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 = {
49 .ether_type = htons(ETHERTYPE_LLDP),
52 /* Append ethernet header */
53 memcpy(ðer.ether_dhost, lldp_dst, ETHER_ADDR_LEN);
54 memcpy(ðer.ether_shost, &mac_addr, ETHER_ADDR_LEN);
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 _cleanup_free_ char *p = NULL;
139 assert_se(lldp_tlv_packet_enter_container(m, LLDP_TYPE_PORT_ID) >= 0);
141 assert_se(tlv_packet_read_u8(m, &subtype) >= 0);
144 case LLDP_PORT_SUBTYPE_INTERFACE_NAME:
145 assert_se(tlv_packet_read_string(m, &str, &length) >= 0);
147 p = strndup(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 _cleanup_free_ char *p = NULL;
166 assert_se(lldp_tlv_packet_enter_container(m, LLDP_TYPE_SYSTEM_NAME) >= 0);
167 assert_se(tlv_packet_read_string(m, &str, &length) >= 0);
169 p = strndup(str, length);
172 assert_se(streq(p, TEST_LLDP_TYPE_SYSTEM_NAME) == 1);
174 assert_se(lldp_tlv_packet_exit_container(m) >= 0);
179 static int lldp_parse_system_desc_tlv(tlv_packet *m) {
180 _cleanup_free_ char *p = NULL;
184 assert_se(lldp_tlv_packet_enter_container(m, LLDP_TYPE_SYSTEM_DESCRIPTION) >= 0);
185 assert_se(tlv_packet_read_string(m, &str, &length) >= 0);
187 p = strndup(str, length);
190 assert_se(streq(p, TEST_LLDP_TYPE_SYSTEM_DESC) == 1);
192 assert_se(lldp_tlv_packet_exit_container(m) >= 0);
197 static int lldp_parse_ttl_tlv(tlv_packet *m) {
200 assert_se(lldp_tlv_packet_enter_container(m, LLDP_TYPE_TTL) >= 0);
201 assert_se(tlv_packet_read_u16(m, &ttl) >= 0);
203 assert_se(ttl == 170);
205 assert_se(lldp_tlv_packet_exit_container(m) >= 0);
210 static int lldp_parse_tlv_packet(tlv_packet *m, int len) {
213 assert_se(tlv_packet_parse_pdu(m, len) >= 0);
214 assert_se(lldp_parse_chassis_tlv(m, &subtype) >= 0);
215 assert_se(lldp_parse_port_id_tlv(m) >= 0);
216 assert_se(lldp_parse_system_name_tlv(m) >= 0);
217 assert_se(lldp_parse_ttl_tlv(m) >= 0);
218 assert_se(lldp_parse_system_desc_tlv(m) >= 0);
223 int main(int argc, char *argv[]) {
224 _cleanup_tlv_packet_free_ tlv_packet *tlv = NULL;
227 lldp_build_tlv_packet(&tlv);
229 /* parse the packet */
230 tlv_packet_parse_pdu(tlv, tlv->length);
233 lldp_parse_tlv_packet(tlv, tlv->length);