]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-network/test-lldp.c
Merge pull request #2981 from keszybz/test-nss
[thirdparty/systemd.git] / src / libsystemd-network / test-lldp.c
1 /***
2 This file is part of systemd.
3
4 Copyright (C) 2014 Tom Gundersen
5 Copyright (C) 2014 Susant Sahani
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <arpa/inet.h>
22 #include <net/ethernet.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <unistd.h>
26
27 #include "sd-event.h"
28 #include "sd-lldp.h"
29
30 #include "alloc-util.h"
31 #include "fd-util.h"
32 #include "lldp-network.h"
33 #include "macro.h"
34 #include "string-util.h"
35
36 #define TEST_LLDP_PORT "em1"
37 #define TEST_LLDP_TYPE_SYSTEM_NAME "systemd-lldp"
38 #define TEST_LLDP_TYPE_SYSTEM_DESC "systemd-lldp-desc"
39
40 static int test_fd[2] = { -1, -1 };
41 static int lldp_handler_calls;
42
43 int lldp_network_bind_raw_socket(int ifindex) {
44 if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0, test_fd) < 0)
45 return -errno;
46
47 return test_fd[0];
48 }
49
50 static void lldp_handler(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n, void *userdata) {
51 lldp_handler_calls++;
52 }
53
54 static int start_lldp(sd_lldp **lldp, sd_event *e, sd_lldp_callback_t cb, void *cb_data) {
55 int r;
56
57 r = sd_lldp_new(lldp, 42);
58 if (r < 0)
59 return r;
60
61 r = sd_lldp_attach_event(*lldp, e, 0);
62 if (r < 0)
63 return r;
64
65 r = sd_lldp_set_callback(*lldp, cb, cb_data);
66 if (r < 0)
67 return r;
68
69 r = sd_lldp_start(*lldp);
70 if (r < 0)
71 return r;
72
73 return 0;
74 }
75
76 static int stop_lldp(sd_lldp *lldp) {
77 int r;
78
79 r = sd_lldp_stop(lldp);
80 if (r < 0)
81 return r;
82
83 r = sd_lldp_detach_event(lldp);
84 if (r < 0)
85 return r;
86
87 sd_lldp_unref(lldp);
88 safe_close(test_fd[1]);
89
90 return 0;
91 }
92
93 static void test_receive_basic_packet(sd_event *e) {
94
95 static const uint8_t frame[] = {
96 /* Ethernet header */
97 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC*/
98 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */
99 0x88, 0xcc, /* Ethertype */
100 /* LLDP mandatory TLVs */
101 0x02, 0x07, 0x04, 0x00, 0x01, 0x02, /* Chassis: MAC, 00:01:02:03:04:05 */
102 0x03, 0x04, 0x05,
103 0x04, 0x04, 0x05, 0x31, 0x2f, 0x33, /* Port: interface name, "1/3" */
104 0x06, 0x02, 0x00, 0x78, /* TTL: 120 seconds*/
105 /* LLDP optional TLVs */
106 0x08, 0x04, 0x50, 0x6f, 0x72, 0x74, /* Port Description: "Port" */
107 0x0a, 0x03, 0x53, 0x59, 0x53, /* System Name: "SYS" */
108 0x0c, 0x04, 0x66, 0x6f, 0x6f, 0x00, /* System Description: "foo" (NULL-terminated) */
109 0x00, 0x00 /* End Of LLDPDU */
110 };
111
112 sd_lldp *lldp;
113 sd_lldp_neighbor **neighbors;
114 uint8_t type;
115 const void *data;
116 uint16_t ttl;
117 size_t length;
118 const char *str;
119
120 lldp_handler_calls = 0;
121 assert_se(start_lldp(&lldp, e, lldp_handler, NULL) == 0);
122
123 assert_se(write(test_fd[1], frame, sizeof(frame)) == sizeof(frame));
124 sd_event_run(e, 0);
125 assert_se(lldp_handler_calls == 1);
126 assert_se(sd_lldp_get_neighbors(lldp, &neighbors) == 1);
127
128 assert_se(sd_lldp_neighbor_get_chassis_id(neighbors[0], &type, &data, &length) == 0);
129 assert_se(type == SD_LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS);
130 assert_se(length == ETH_ALEN);
131 assert_se(!memcmp(data, "\x00\x01\x02\x03\x04\x05", ETH_ALEN));
132
133 assert_se(sd_lldp_neighbor_get_port_id(neighbors[0], &type, &data, &length) == 0);
134 assert_se(type == SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME);
135 assert_se(length == 3);
136 assert_se(strneq((char *) data, "1/3", 3));
137
138 assert_se(sd_lldp_neighbor_get_port_description(neighbors[0], &str) == 0);
139 assert_se(streq(str, "Port"));
140
141 assert_se(sd_lldp_neighbor_get_system_name(neighbors[0], &str) == 0);
142 assert_se(streq(str, "SYS"));
143
144 assert_se(sd_lldp_neighbor_get_system_description(neighbors[0], &str) == 0);
145 assert_se(streq(str, "foo"));
146
147 assert_se(sd_lldp_neighbor_get_ttl(neighbors[0], &ttl) == 0);
148 assert_se(ttl == 120);
149
150 sd_lldp_neighbor_unref(neighbors[0]);
151 free(neighbors);
152
153 assert_se(stop_lldp(lldp) == 0);
154 }
155
156 static void test_receive_incomplete_packet(sd_event *e) {
157 sd_lldp *lldp;
158 sd_lldp_neighbor **neighbors;
159 uint8_t frame[] = {
160 /* Ethernet header */
161 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC*/
162 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */
163 0x88, 0xcc, /* Ethertype */
164 /* LLDP mandatory TLVs */
165 0x02, 0x07, 0x04, 0x00, 0x01, 0x02, /* Chassis: MAC, 00:01:02:03:04:05 */
166 0x03, 0x04, 0x05,
167 0x04, 0x04, 0x05, 0x31, 0x2f, 0x33, /* Port: interface name, "1/3" */
168 /* Missing TTL */
169 0x00, 0x00 /* End Of LLDPDU */
170 };
171
172 lldp_handler_calls = 0;
173 assert_se(start_lldp(&lldp, e, lldp_handler, NULL) == 0);
174
175 assert_se(write(test_fd[1], frame, sizeof(frame)) == sizeof(frame));
176 sd_event_run(e, 0);
177 assert_se(lldp_handler_calls == 0);
178 assert_se(sd_lldp_get_neighbors(lldp, &neighbors) == 0);
179
180 assert_se(stop_lldp(lldp) == 0);
181 }
182
183 static void test_receive_oui_packet(sd_event *e) {
184 sd_lldp *lldp;
185 sd_lldp_neighbor **neighbors;
186 uint8_t frame[] = {
187 /* Ethernet header */
188 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC*/
189 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */
190 0x88, 0xcc, /* Ethertype */
191 /* LLDP mandatory TLVs */
192 0x02, 0x07, 0x04, 0x00, 0x01, 0x02, /* Chassis: MAC, 00:01:02:03:04:05 */
193 0x03, 0x04, 0x05,
194 0x04, 0x04, 0x05, 0x31, 0x2f, 0x33, /* Port TLV: interface name, "1/3" */
195 0x06, 0x02, 0x00, 0x78, /* TTL: 120 seconds*/
196 /* LLDP optional TLVs */
197 0xfe, 0x06, 0x00, 0x80, 0xc2, 0x01, /* Port VLAN ID: 0x1234 */
198 0x12, 0x34,
199 0xfe, 0x07, 0x00, 0x80, 0xc2, 0x02, /* Port and protocol: flag 1, PPVID 0x7788 */
200 0x01, 0x77, 0x88,
201 0xfe, 0x0d, 0x00, 0x80, 0xc2, 0x03, /* VLAN Name: ID 0x1234, name "Vlan51" */
202 0x12, 0x34, 0x06, 0x56, 0x6c, 0x61,
203 0x6e, 0x35, 0x31,
204 0xfe, 0x06, 0x00, 0x80, 0xc2, 0x06, /* Management VID: 0x0102 */
205 0x01, 0x02,
206 0xfe, 0x09, 0x00, 0x80, 0xc2, 0x07, /* Link aggregation: status 1, ID 0x00140012 */
207 0x01, 0x00, 0x14, 0x00, 0x12,
208 0x00, 0x00 /* End of LLDPDU */
209 };
210
211 lldp_handler_calls = 0;
212 assert_se(start_lldp(&lldp, e, lldp_handler, NULL) == 0);
213
214 assert_se(write(test_fd[1], frame, sizeof(frame)) == sizeof(frame));
215 sd_event_run(e, 0);
216 assert_se(lldp_handler_calls == 1);
217 assert_se(sd_lldp_get_neighbors(lldp, &neighbors) == 1);
218
219 assert_se(sd_lldp_neighbor_tlv_rewind(neighbors[0]) >= 0);
220 assert_se(sd_lldp_neighbor_tlv_is_type(neighbors[0], SD_LLDP_TYPE_CHASSIS_ID) > 0);
221 assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
222 assert_se(sd_lldp_neighbor_tlv_is_type(neighbors[0], SD_LLDP_TYPE_PORT_ID) > 0);
223 assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
224 assert_se(sd_lldp_neighbor_tlv_is_type(neighbors[0], SD_LLDP_TYPE_TTL) > 0);
225 assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
226 assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_1, SD_LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID) > 0);
227 assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
228 assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_1, SD_LLDP_OUI_802_1_SUBTYPE_PORT_PROTOCOL_VLAN_ID) > 0);
229 assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
230 assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_1, SD_LLDP_OUI_802_1_SUBTYPE_VLAN_NAME) > 0);
231 assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
232 assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_1, SD_LLDP_OUI_802_1_SUBTYPE_MANAGEMENT_VID) > 0);
233 assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
234 assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_1, SD_LLDP_OUI_802_1_SUBTYPE_LINK_AGGREGATION) > 0);
235 assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
236 assert_se(sd_lldp_neighbor_tlv_is_type(neighbors[0], SD_LLDP_TYPE_END) > 0);
237 assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) == 0);
238
239 sd_lldp_neighbor_unref(neighbors[0]);
240 free(neighbors);
241
242 assert_se(stop_lldp(lldp) == 0);
243 }
244
245 int main(int argc, char *argv[]) {
246 _cleanup_(sd_event_unrefp) sd_event *e = NULL;
247
248 log_set_max_level(LOG_DEBUG);
249
250 /* LLDP reception tests */
251 assert_se(sd_event_new(&e) == 0);
252 test_receive_basic_packet(e);
253 test_receive_incomplete_packet(e);
254 test_receive_oui_packet(e);
255
256 return 0;
257 }