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/>.
25 #include <net/ethernet.h>
26 #include <arpa/inet.h>
32 #define TEST_LLDP_PORT "em1"
33 #define TEST_LLDP_TYPE_SYSTEM_NAME "systemd-lldp"
34 #define TEST_LLDP_TYPE_SYSTEM_DESC "systemd-lldp-desc"
36 static struct ether_addr mac_addr = {
37 .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
40 static int lldp_build_tlv_packet(tlv_packet **ret) {
41 _cleanup_tlv_packet_free_ tlv_packet *m = NULL;
42 const uint8_t lldp_dst[] = LLDP_MULTICAST_ADDR;
43 struct ether_header ether = {
44 .ether_type = htons(ETHERTYPE_LLDP),
47 /* Append ethernet header */
48 memcpy(ðer.ether_dhost, lldp_dst, ETHER_ADDR_LEN);
49 memcpy(ðer.ether_shost, &mac_addr, ETHER_ADDR_LEN);
51 assert_se(tlv_packet_new(&m) >= 0);
53 assert_se(tlv_packet_append_bytes(m, ðer, sizeof(struct ether_header)) >= 0);
55 assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_CHASSIS_ID) >= 0);
57 assert_se(tlv_packet_append_u8(m, LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS) >= 0);
58 assert_se(tlv_packet_append_bytes(m, &mac_addr, ETHER_ADDR_LEN) >= 0);
60 assert_se(lldp_tlv_packet_close_container(m) >= 0);
63 assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_PORT_ID) >= 0);
65 assert_se(tlv_packet_append_u8(m, LLDP_PORT_SUBTYPE_INTERFACE_NAME) >= 0);
66 assert_se(tlv_packet_append_bytes(m, TEST_LLDP_PORT, strlen(TEST_LLDP_PORT) + 1) >= 0);
68 assert_se(lldp_tlv_packet_close_container(m) >= 0);
71 assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_TTL) >= 0);
73 assert_se(tlv_packet_append_u16(m, 170) >= 0);
75 assert_se(lldp_tlv_packet_close_container(m) >= 0);
78 assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_SYSTEM_NAME) >= 0);
80 assert_se(tlv_packet_append_bytes(m, TEST_LLDP_TYPE_SYSTEM_NAME,
81 strlen(TEST_LLDP_TYPE_SYSTEM_NAME)) >= 0);
82 assert_se(lldp_tlv_packet_close_container(m) >= 0);
84 /* system descrition */
85 assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_SYSTEM_DESCRIPTION) >= 0);
87 assert_se(tlv_packet_append_bytes(m, TEST_LLDP_TYPE_SYSTEM_DESC,
88 strlen(TEST_LLDP_TYPE_SYSTEM_DESC)) >= 0);
90 assert_se(lldp_tlv_packet_close_container(m) >= 0);
92 /* Mark end of packet */
93 assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_END) >= 0);
94 assert_se(lldp_tlv_packet_close_container(m) >= 0);
103 static int lldp_parse_chassis_tlv(tlv_packet *m, uint8_t *type) {
107 assert_se(lldp_tlv_packet_enter_container(m, LLDP_TYPE_CHASSIS_ID) >= 0);
108 assert_se(tlv_packet_read_u8(m, &subtype) >= 0);
111 case LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS:
113 *type = LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS;
114 assert_se(tlv_packet_read_bytes(m, &p, &length) >= 0);
116 assert_se(memcmp(p, &mac_addr.ether_addr_octet, ETHER_ADDR_LEN) == 0);
120 assert_not_reached("Unhandled option");
123 assert_se(lldp_tlv_packet_exit_container(m) >= 0);
128 static int lldp_parse_port_id_tlv(tlv_packet *m) {
129 _cleanup_free_ char *p = NULL;
134 assert_se(lldp_tlv_packet_enter_container(m, LLDP_TYPE_PORT_ID) >= 0);
136 assert_se(tlv_packet_read_u8(m, &subtype) >= 0);
139 case LLDP_PORT_SUBTYPE_INTERFACE_NAME:
140 assert_se(tlv_packet_read_string(m, &str, &length) >= 0);
142 p = strndup(str, length-1);
145 assert_se(streq(p, TEST_LLDP_PORT) == 1);
148 assert_not_reached("Unhandled option");
151 assert_se(lldp_tlv_packet_exit_container(m) >= 0);
156 static int lldp_parse_system_name_tlv(tlv_packet *m) {
157 _cleanup_free_ char *p = NULL;
161 assert_se(lldp_tlv_packet_enter_container(m, LLDP_TYPE_SYSTEM_NAME) >= 0);
162 assert_se(tlv_packet_read_string(m, &str, &length) >= 0);
164 p = strndup(str, length);
167 assert_se(streq(p, TEST_LLDP_TYPE_SYSTEM_NAME) == 1);
169 assert_se(lldp_tlv_packet_exit_container(m) >= 0);
174 static int lldp_parse_system_desc_tlv(tlv_packet *m) {
175 _cleanup_free_ char *p = NULL;
179 assert_se(lldp_tlv_packet_enter_container(m, LLDP_TYPE_SYSTEM_DESCRIPTION) >= 0);
180 assert_se(tlv_packet_read_string(m, &str, &length) >= 0);
182 p = strndup(str, length);
185 assert_se(streq(p, TEST_LLDP_TYPE_SYSTEM_DESC) == 1);
187 assert_se(lldp_tlv_packet_exit_container(m) >= 0);
192 static int lldp_parse_ttl_tlv(tlv_packet *m) {
195 assert_se(lldp_tlv_packet_enter_container(m, LLDP_TYPE_TTL) >= 0);
196 assert_se(tlv_packet_read_u16(m, &ttl) >= 0);
198 assert_se(ttl == 170);
200 assert_se(lldp_tlv_packet_exit_container(m) >= 0);
205 static int lldp_parse_tlv_packet(tlv_packet *m, int len) {
208 assert_se(tlv_packet_parse_pdu(m, len) >= 0);
209 assert_se(lldp_parse_chassis_tlv(m, &subtype) >= 0);
210 assert_se(lldp_parse_port_id_tlv(m) >= 0);
211 assert_se(lldp_parse_system_name_tlv(m) >= 0);
212 assert_se(lldp_parse_ttl_tlv(m) >= 0);
213 assert_se(lldp_parse_system_desc_tlv(m) >= 0);
218 int main(int argc, char *argv[]) {
219 _cleanup_tlv_packet_free_ tlv_packet *tlv = NULL;
222 lldp_build_tlv_packet(&tlv);
224 /* parse the packet */
225 tlv_packet_parse_pdu(tlv, tlv->length);
228 lldp_parse_tlv_packet(tlv, tlv->length);