chiark / gitweb /
Remove src/kernel-install
[elogind.git] / src / libsystemd-network / test-lldp.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright (C) 2014 Tom Gundersen
7   Copyright (C) 2014 Susant Sahani
8
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.
13
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.
18
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/>.
21 ***/
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <net/ethernet.h>
26 #include <arpa/inet.h>
27
28 #include "macro.h"
29 #include "lldp.h"
30 #include "lldp-tlv.h"
31
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"
35
36 static struct ether_addr mac_addr = {
37         .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
38 };
39
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),
45         };
46
47         /* Append ethernet header */
48         memcpy(&ether.ether_dhost, lldp_dst, ETHER_ADDR_LEN);
49         memcpy(&ether.ether_shost, &mac_addr, ETHER_ADDR_LEN);
50
51         assert_se(tlv_packet_new(&m) >= 0);
52
53         assert_se(tlv_packet_append_bytes(m, &ether, sizeof(struct ether_header)) >= 0);
54
55         assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_CHASSIS_ID) >= 0);
56
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);
59
60         assert_se(lldp_tlv_packet_close_container(m) >= 0);
61
62         /* port name */
63         assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_PORT_ID) >= 0);
64
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);
67
68         assert_se(lldp_tlv_packet_close_container(m) >= 0);
69
70         /* ttl */
71         assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_TTL) >= 0);
72
73         assert_se(tlv_packet_append_u16(m, 170) >= 0);
74
75         assert_se(lldp_tlv_packet_close_container(m) >= 0);
76
77         /* system name */
78         assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_SYSTEM_NAME) >= 0);
79
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);
83
84         /* system descrition */
85         assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_SYSTEM_DESCRIPTION) >= 0);
86
87         assert_se(tlv_packet_append_bytes(m, TEST_LLDP_TYPE_SYSTEM_DESC,
88                                           strlen(TEST_LLDP_TYPE_SYSTEM_DESC)) >= 0);
89
90         assert_se(lldp_tlv_packet_close_container(m) >= 0);
91
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);
95
96         *ret = m;
97
98         m = NULL;
99
100         return 0;
101 }
102
103 static int lldp_parse_chassis_tlv(tlv_packet *m, uint8_t *type) {
104         uint8_t *p, subtype;
105         uint16_t length;
106
107         assert_se(lldp_tlv_packet_enter_container(m, LLDP_TYPE_CHASSIS_ID) >= 0);
108         assert_se(tlv_packet_read_u8(m, &subtype) >= 0);
109
110         switch (subtype) {
111         case LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS:
112
113                 *type = LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS;
114                 assert_se(tlv_packet_read_bytes(m, &p, &length) >= 0);
115
116                 assert_se(memcmp(p, &mac_addr.ether_addr_octet, ETHER_ADDR_LEN) == 0);
117
118                 break;
119         default:
120                 assert_not_reached("Unhandled option");
121         }
122
123         assert_se(lldp_tlv_packet_exit_container(m) >= 0);
124
125         return 0;
126 }
127
128 static int lldp_parse_port_id_tlv(tlv_packet *m) {
129         _cleanup_free_ char *p = NULL;
130         char *str = NULL;
131         uint16_t length;
132         uint8_t subtype;
133
134         assert_se(lldp_tlv_packet_enter_container(m, LLDP_TYPE_PORT_ID) >= 0);
135
136         assert_se(tlv_packet_read_u8(m, &subtype) >= 0);
137
138         switch (subtype) {
139         case LLDP_PORT_SUBTYPE_INTERFACE_NAME:
140                 assert_se(tlv_packet_read_string(m, &str, &length) >= 0);
141
142                 p = strndup(str, length-1);
143                 assert_se(p);
144
145                 assert_se(streq(p, TEST_LLDP_PORT) == 1);
146                 break;
147         default:
148                 assert_not_reached("Unhandled option");
149         }
150
151         assert_se(lldp_tlv_packet_exit_container(m) >= 0);
152
153         return 0;
154 }
155
156 static int lldp_parse_system_name_tlv(tlv_packet *m) {
157         _cleanup_free_ char *p = NULL;
158         char *str = NULL;
159         uint16_t length;
160
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);
163
164         p = strndup(str, length);
165         assert_se(p);
166
167         assert_se(streq(p, TEST_LLDP_TYPE_SYSTEM_NAME) == 1);
168
169         assert_se(lldp_tlv_packet_exit_container(m) >= 0);
170
171         return 1;
172 }
173
174 static int lldp_parse_system_desc_tlv(tlv_packet *m) {
175         _cleanup_free_ char *p = NULL;
176         char *str = NULL;
177         uint16_t length;
178
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);
181
182         p = strndup(str, length);
183         assert_se(p);
184
185         assert_se(streq(p, TEST_LLDP_TYPE_SYSTEM_DESC) == 1);
186
187         assert_se(lldp_tlv_packet_exit_container(m) >= 0);
188
189         return 0;
190 }
191
192 static int lldp_parse_ttl_tlv(tlv_packet *m) {
193         uint16_t ttl;
194
195         assert_se(lldp_tlv_packet_enter_container(m, LLDP_TYPE_TTL) >= 0);
196         assert_se(tlv_packet_read_u16(m, &ttl) >= 0);
197
198         assert_se(ttl == 170);
199
200         assert_se(lldp_tlv_packet_exit_container(m) >= 0);
201
202         return 0;
203 }
204
205 static int lldp_parse_tlv_packet(tlv_packet *m, int len) {
206         uint8_t subtype;
207
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);
214
215         return 0;
216 }
217
218 int main(int argc, char *argv[]) {
219         _cleanup_tlv_packet_free_ tlv_packet *tlv = NULL;
220
221         /* form a packet */
222         lldp_build_tlv_packet(&tlv);
223
224         /* parse the packet */
225         tlv_packet_parse_pdu(tlv, tlv->length);
226
227         /* verify */
228         lldp_parse_tlv_packet(tlv, tlv->length);
229
230         return 0;
231 }