1 /* -*- mode: c; c-file-style: "openbsd" -*- */
2 /*
3 * Copyright (c) 2015 Vincent Bernat <bernat@luffy.cx>
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 #include <stdlib.h>
19 #include <sys/socket.h>
20 #include <arpa/inet.h>
21 #include <netinet/in.h>
22 #include <check.h>
23 #include "common.h"
24
25 char filenameprefix[] = "lldp_send";
26
27 static struct lldpd test_lldpd = {
28 .g_config = {
29 .c_cap_advertise = 1, /* Chassis capabilities advertisement */
30 .c_mgmt_advertise = 1, /* Management addresses advertisement */
31 }
32 };
33
34 #define ck_assert_str_eq_n(X, Y, N) \
35 ck_assert_msg(!strncmp(X, Y, N), "Assertion '"#X"=="#Y"' failed: "#X"==\"%s\", "#Y"==\"%s\"", X, Y)
36
37 static void
check_received_port(struct lldpd_port * sport,struct lldpd_port * rport)38 check_received_port(
39 struct lldpd_port *sport,
40 struct lldpd_port *rport)
41 {
42 ck_assert_int_eq(rport->p_id_subtype, sport->p_id_subtype);
43 ck_assert_int_eq(rport->p_id_len, sport->p_id_len);
44 ck_assert_str_eq_n(rport->p_id, sport->p_id, sport->p_id_len);
45 ck_assert_str_eq(rport->p_descr, sport->p_descr);
46 #ifdef ENABLE_DOT3
47 ck_assert_int_eq(rport->p_mfs, sport->p_mfs);
48 #endif
49 }
50
51 static void
check_received_chassis(struct lldpd_chassis * schassis,struct lldpd_chassis * rchassis)52 check_received_chassis(
53 struct lldpd_chassis *schassis,
54 struct lldpd_chassis *rchassis)
55 {
56 ck_assert_int_eq(rchassis->c_id_subtype, schassis->c_id_subtype);
57 ck_assert_int_eq(rchassis->c_id_len, schassis->c_id_len);
58 ck_assert_str_eq_n(rchassis->c_id, schassis->c_id, schassis->c_id_len);
59 ck_assert_str_eq(rchassis->c_name, schassis->c_name);
60 ck_assert_str_eq(rchassis->c_descr, schassis->c_descr);
61 ck_assert_int_eq(rchassis->c_cap_available, schassis->c_cap_available);
62 ck_assert_int_eq(rchassis->c_cap_enabled, schassis->c_cap_enabled);
63 }
64
65 #ifdef ENABLE_LLDPMED
66 static void
check_received_port_med(struct lldpd_port * sport,struct lldpd_port * rport)67 check_received_port_med(
68 struct lldpd_port *sport,
69 struct lldpd_port *rport)
70 {
71 ck_assert_int_eq(rport->p_med_cap_enabled, sport->p_med_cap_enabled);
72 ck_assert_int_eq(rport->p_med_cap_enabled, sport->p_med_cap_enabled);
73 ck_assert_int_eq(
74 rport->p_med_location[LLDP_MED_LOCFORMAT_CIVIC-1].format,
75 sport->p_med_location[LLDP_MED_LOCFORMAT_CIVIC-1].format);
76 ck_assert_int_eq(
77 rport->p_med_location[LLDP_MED_LOCFORMAT_CIVIC-1].data_len,
78 sport->p_med_location[LLDP_MED_LOCFORMAT_CIVIC-1].data_len);
79 ck_assert_str_eq_n(
80 rport->p_med_location[LLDP_MED_LOCFORMAT_CIVIC-1].data,
81 sport->p_med_location[LLDP_MED_LOCFORMAT_CIVIC-1].data,
82 sport->p_med_location[LLDP_MED_LOCFORMAT_CIVIC-1].data_len);
83 ck_assert_int_eq(
84 rport->p_med_policy[LLDP_MED_APPTYPE_SOFTPHONEVOICE-1].type,
85 sport->p_med_policy[LLDP_MED_APPTYPE_SOFTPHONEVOICE-1].type);
86 ck_assert_int_eq(
87 rport->p_med_policy[LLDP_MED_APPTYPE_SOFTPHONEVOICE-1].tagged,
88 sport->p_med_policy[LLDP_MED_APPTYPE_SOFTPHONEVOICE-1].tagged);
89 ck_assert_int_eq(
90 rport->p_med_policy[LLDP_MED_APPTYPE_SOFTPHONEVOICE-1].vid,
91 sport->p_med_policy[LLDP_MED_APPTYPE_SOFTPHONEVOICE-1].vid);
92 ck_assert_int_eq(
93 rport->p_med_policy[LLDP_MED_APPTYPE_SOFTPHONEVOICE-1].priority,
94 sport->p_med_policy[LLDP_MED_APPTYPE_SOFTPHONEVOICE-1].priority);
95 ck_assert_int_eq(
96 rport->p_med_policy[LLDP_MED_APPTYPE_SOFTPHONEVOICE-1].dscp,
97 sport->p_med_policy[LLDP_MED_APPTYPE_SOFTPHONEVOICE-1].dscp);
98 ck_assert_int_eq(
99 rport->p_med_power.devicetype, sport->p_med_power.devicetype);
100 ck_assert_int_eq(rport->p_med_power.source, sport->p_med_power.source);
101 ck_assert_int_eq(rport->p_med_power.priority,
102 sport->p_med_power.priority);
103 ck_assert_int_eq(rport->p_med_power.val, sport->p_med_power.val);
104 }
105
106 static void
check_received_chassis_med(struct lldpd_chassis * schassis,struct lldpd_chassis * rchassis)107 check_received_chassis_med(
108 struct lldpd_chassis *schassis,
109 struct lldpd_chassis *rchassis)
110 {
111 ck_assert_int_eq(rchassis->c_med_cap_available,
112 schassis->c_med_cap_available);
113 ck_assert_int_eq(rchassis->c_med_type, schassis->c_med_type);
114 ck_assert_str_eq(rchassis->c_med_hw, schassis->c_med_hw);
115 ck_assert_str_eq(rchassis->c_med_fw, schassis->c_med_fw);
116 ck_assert_str_eq(rchassis->c_med_sw, schassis->c_med_sw);
117 ck_assert_str_eq(rchassis->c_med_sn, schassis->c_med_sn);
118 }
119 #endif
120
121 #ifdef ENABLE_DOT3
122 static void
check_received_port_dot3(struct lldpd_port * sport,struct lldpd_port * rport)123 check_received_port_dot3(
124 struct lldpd_port *sport,
125 struct lldpd_port *rport)
126 {
127 ck_assert_int_eq(rport->p_aggregid, sport->p_aggregid);
128 ck_assert_int_eq(rport->p_macphy.autoneg_support,
129 sport->p_macphy.autoneg_support);
130 ck_assert_int_eq(rport->p_macphy.autoneg_enabled,
131 sport->p_macphy.autoneg_enabled);
132 ck_assert_int_eq(rport->p_macphy.autoneg_advertised,
133 sport->p_macphy.autoneg_advertised);
134 ck_assert_int_eq(rport->p_macphy.mau_type, sport->p_macphy.mau_type);
135 }
136 #endif
137
START_TEST(test_send_rcv_basic)138 START_TEST (test_send_rcv_basic)
139 {
140 int n;
141 struct packet *pkt;
142 struct lldpd_chassis *nchassis = NULL;
143 struct lldpd_port *nport = NULL;
144
145 /* Populate port and chassis */
146 hardware.h_lport.p_id_subtype = LLDP_PORTID_SUBTYPE_IFNAME;
147 hardware.h_lport.p_id = "FastEthernet 1/5";
148 hardware.h_lport.p_id_len = strlen(hardware.h_lport.p_id);
149 hardware.h_lport.p_descr = "Fake port description";
150 hardware.h_lport.p_mfs = 1516;
151 chassis.c_id_subtype = LLDP_CHASSISID_SUBTYPE_LLADDR;
152 chassis.c_id = macaddress;
153 chassis.c_id_len = ETHER_ADDR_LEN;
154 chassis.c_name = "First chassis";
155 chassis.c_descr = "Chassis description";
156 chassis.c_cap_available = chassis.c_cap_enabled = LLDP_CAP_ROUTER;
157
158 /* Build packet */
159 n = lldp_send(&test_lldpd, &hardware);
160 if (n != 0) {
161 fail("unable to build packet");
162 return;
163 }
164 if (TAILQ_EMPTY(&pkts)) {
165 fail("no packets sent");
166 return;
167 }
168 pkt = TAILQ_FIRST(&pkts);
169 fail_unless(TAILQ_NEXT(pkt, next) == NULL, "more than one packet sent");
170
171 /* decode the retrieved packet calling lldp_decode() */
172 fail_unless(lldp_decode(NULL, pkt->data, pkt->size, &hardware,
173 &nchassis, &nport) != -1);
174 if (!nchassis || !nport) {
175 fail("unable to decode packet");
176 return;
177 }
178 /* verify port values */
179 check_received_port(&hardware.h_lport, nport);
180 /* verify chassis values */
181 check_received_chassis(&chassis, nchassis);
182 }
183 END_TEST
184
185 #define ETHERTYPE_OFFSET 2 * ETHER_ADDR_LEN
186 #define VLAN_TAG_SIZE 2
START_TEST(test_send_rcv_vlan_tx)187 START_TEST (test_send_rcv_vlan_tx)
188 {
189 int n;
190 struct packet *pkt;
191 struct lldpd_chassis *nchassis = NULL;
192 struct lldpd_port *nport = NULL;
193 int vlan_id = 100;
194 int vlan_prio = 5;
195 int vlan_dei = 1;
196 unsigned int vlan_tag = 0;
197 unsigned int tmp;
198
199 /* Populate port and chassis */
200 hardware.h_lport.p_id_subtype = LLDP_PORTID_SUBTYPE_IFNAME;
201 hardware.h_lport.p_id = "FastEthernet 1/5";
202 hardware.h_lport.p_id_len = strlen(hardware.h_lport.p_id);
203 hardware.h_lport.p_descr = "Fake port description";
204 hardware.h_lport.p_mfs = 1516;
205
206 /* Assembly VLAN tag: Priority(3bits) | DEI(1bit) | VID(12bits) */
207 vlan_tag = ((vlan_prio & 0x7) << 13) |
208 ((vlan_dei & 0x1) << 12) |
209 (vlan_id & 0xfff);
210 hardware.h_lport.p_vlan_tx_tag = vlan_tag;
211 hardware.h_lport.p_vlan_tx_enabled = 1;
212 chassis.c_id_subtype = LLDP_CHASSISID_SUBTYPE_LLADDR;
213 chassis.c_id = macaddress;
214 chassis.c_id_len = ETHER_ADDR_LEN;
215 chassis.c_name = "First chassis";
216 chassis.c_descr = "Chassis description";
217 chassis.c_cap_available = chassis.c_cap_enabled = LLDP_CAP_ROUTER;
218
219 /* Build packet */
220 n = lldp_send(&test_lldpd, &hardware);
221 if (n != 0) {
222 fail("unable to build packet");
223 return;
224 }
225 if (TAILQ_EMPTY(&pkts)) {
226 fail("no packets sent");
227 return;
228 }
229 pkt = TAILQ_FIRST(&pkts);
230 fail_unless(TAILQ_NEXT(pkt, next) == NULL, "more than one packet sent");
231
232 /* Check ETHER_TYPE, should be VLAN */
233 memcpy(&tmp, (unsigned char*) pkt->data + ETHERTYPE_OFFSET, ETHER_TYPE_LEN);
234 ck_assert_uint_eq(ntohl(tmp)>>16, ETHERTYPE_VLAN);
235
236 /* Check VLAN tag */
237 memcpy(&tmp, (unsigned char*) pkt->data + ETHERTYPE_OFFSET + ETHER_TYPE_LEN, VLAN_TAG_SIZE);
238 ck_assert_uint_eq(ntohl(tmp)>>16, vlan_tag);
239
240 /* Remove VLAN ethertype and VLAN tag */
241 memmove((unsigned char*) pkt->data + ETHERTYPE_OFFSET,
242 /* move all after VLAN tag */
243 (unsigned char*) pkt->data + ETHERTYPE_OFFSET + ETHER_TYPE_LEN + VLAN_TAG_SIZE,
244 /* size without src and dst MAC, VLAN tag */
245 pkt->size - (ETHERTYPE_OFFSET + ETHER_TYPE_LEN + VLAN_TAG_SIZE));
246
247 /* Decode the packet without VLAN tag, calling lldp_decode() */
248 fail_unless(lldp_decode(NULL, pkt->data, pkt->size, &hardware,
249 &nchassis, &nport) != -1);
250 if (!nchassis || !nport) {
251 fail("unable to decode packet");
252 return;
253 }
254
255 /* Verify port values (VLAN information is not checked here) */
256 check_received_port(&hardware.h_lport, nport);
257 /* Verify chassis values */
258 check_received_chassis(&chassis, nchassis);
259 }
260 END_TEST
261
262 #ifdef ENABLE_DOT1
263 /* This test case tests send and receive of all DOT1 TLVs(2005 and 2009):
264 Port Valn ID, VLAN, Port Protocol VLAN ID, Protocol Identity,
265 VID Usage Digest, Management VID, and 802.1ax Link Aggregation TLVs */
START_TEST(test_send_rcv_dot1_tlvs)266 START_TEST (test_send_rcv_dot1_tlvs)
267 {
268 int n;
269 struct lldpd_vlan *rvlan, vlan1, vlan2, vlan3;
270 struct lldpd_ppvid ppvid, *rppvid;
271 struct lldpd_pi pi1, pi2, *rpi;
272 struct lldpd_chassis *nchassis = NULL;
273 struct lldpd_port *nport = NULL;
274 struct packet *pkt;
275
276 /* Populate port and chassis */
277 hardware.h_lport.p_id_subtype = LLDP_PORTID_SUBTYPE_LLADDR;
278 hardware.h_lport.p_id = macaddress;
279 hardware.h_lport.p_id_len = ETHER_ADDR_LEN;
280 hardware.h_lport.p_descr = "Fake port description";
281 hardware.h_lport.p_mfs = 1516;
282 hardware.h_lport.p_pvid = 1500;
283 chassis.c_id_subtype = LLDP_CHASSISID_SUBTYPE_LOCAL;
284 chassis.c_id = "Chassis name";
285 chassis.c_id_len = strlen(chassis.c_id);
286 chassis.c_name = "Second chassis";
287 chassis.c_descr = "Chassis description";
288 chassis.c_cap_available = LLDP_CAP_ROUTER | LLDP_CAP_BRIDGE;
289 chassis.c_cap_enabled = LLDP_CAP_ROUTER;
290 vlan1.v_name = "Voice"; vlan1.v_vid = 157;
291 vlan2.v_name = "Data"; vlan2.v_vid = 1247;
292 vlan3.v_name = "Control"; vlan3.v_vid = 741;
293 TAILQ_INSERT_TAIL(&hardware.h_lport.p_vlans, &vlan1, v_entries);
294 TAILQ_INSERT_TAIL(&hardware.h_lport.p_vlans, &vlan2, v_entries);
295 TAILQ_INSERT_TAIL(&hardware.h_lport.p_vlans, &vlan3, v_entries);
296 ppvid.p_cap_status = 3;
297 ppvid.p_ppvid = 1500;
298 TAILQ_INSERT_TAIL(&hardware.h_lport.p_ppvids, &ppvid, p_entries);
299 pi1.p_pi = "IEEE Link Aggregration Control Protocol 802.3ad";
300 pi1.p_pi_len = strlen(pi1.p_pi);
301 pi2.p_pi = "IEEE Link Layer Discovery Protocol 802.1ab-2005";
302 pi2.p_pi_len = strlen(pi2.p_pi);
303 TAILQ_INSERT_TAIL(&hardware.h_lport.p_pids, &pi1, p_entries);
304 TAILQ_INSERT_TAIL(&hardware.h_lport.p_pids, &pi2, p_entries);
305
306 /* Build packet */
307 n = lldp_send(&test_lldpd, &hardware);
308 if (n != 0) {
309 fail("unable to build packet");
310 return;
311 }
312 if (TAILQ_EMPTY(&pkts)) {
313 fail("no packets sent");
314 return;
315 }
316 pkt = TAILQ_FIRST(&pkts);
317 fail_unless(TAILQ_NEXT(pkt, next) == NULL, "more than one packet sent");
318
319 /* decode the retrieved packet calling lldp_decode() */
320 fail_unless(lldp_decode(NULL, pkt->data, pkt->size, &hardware,
321 &nchassis, &nport) != -1);
322 if (!nchassis || !nport) {
323 fail("unable to decode packet");
324 return;
325 }
326
327 /* verify port values */
328 check_received_port(&hardware.h_lport, nport);
329 /* verify chassis values */
330 check_received_chassis(&chassis, nchassis);
331
332 if (TAILQ_EMPTY(&nport->p_vlans)) {
333 fail("no VLAN");
334 return;
335 }
336
337 rvlan = TAILQ_FIRST(&nport->p_vlans);
338 ck_assert_int_eq(rvlan->v_vid, vlan1.v_vid);
339 ck_assert_str_eq(rvlan->v_name, vlan1.v_name);
340
341 rvlan = TAILQ_NEXT(rvlan, v_entries);
342 if (!rvlan) {
343 fail("no more VLAN");
344 return;
345 }
346 ck_assert_int_eq(rvlan->v_vid, vlan2.v_vid);
347 ck_assert_str_eq(rvlan->v_name, vlan2.v_name);
348
349 rvlan = TAILQ_NEXT(rvlan, v_entries);
350 if (!rvlan) {
351 fail("no more VLAN");
352 return;
353 }
354 ck_assert_int_eq(rvlan->v_vid, vlan3.v_vid);
355 ck_assert_str_eq(rvlan->v_name, vlan3.v_name);
356
357 rvlan = TAILQ_NEXT(rvlan, v_entries);
358 fail_unless(rvlan == NULL);
359
360 ck_assert_int_eq(nport->p_pvid, hardware.h_lport.p_pvid);
361
362 if (TAILQ_EMPTY(&nport->p_ppvids)) {
363 fail("no Port Protocal VLAN ID");
364 return;
365 }
366 rppvid = TAILQ_FIRST(&nport->p_ppvids);
367 ck_assert_int_eq(rppvid->p_cap_status, ppvid.p_cap_status);
368 ck_assert_int_eq(rppvid->p_ppvid, ppvid.p_ppvid);
369
370 if (TAILQ_EMPTY(&nport->p_pids)) {
371 fail("no Protocal Identity TLV");
372 return;
373 }
374 rpi = TAILQ_FIRST(&nport->p_pids);
375 ck_assert_int_eq(rpi->p_pi_len, pi1.p_pi_len);
376 ck_assert_str_eq_n(rpi->p_pi, pi1.p_pi, pi1.p_pi_len);
377
378 rpi = TAILQ_NEXT(rpi, p_entries);
379 if (!rpi) {
380 fail("no more Protocol Identity TLVs");
381 return;
382 }
383 ck_assert_int_eq(rpi->p_pi_len, pi2.p_pi_len);
384 ck_assert_str_eq_n(rpi->p_pi, pi2.p_pi, pi2.p_pi_len);
385
386 rpi = TAILQ_NEXT(rpi, p_entries);
387 fail_unless(rpi == NULL);
388 }
389 END_TEST
390 #endif
391
392 #ifdef ENABLE_LLDPMED
START_TEST(test_send_rcv_med)393 START_TEST (test_send_rcv_med)
394 {
395 int n;
396 struct packet *pkt;
397 struct lldpd_chassis *nchassis = NULL;
398 struct lldpd_port *nport = NULL;
399
400 /* Populate port and chassis */
401 hardware.h_lport.p_id_subtype = LLDP_PORTID_SUBTYPE_LLADDR;
402 hardware.h_lport.p_id = macaddress;
403 hardware.h_lport.p_id_len = ETHER_ADDR_LEN;
404 hardware.h_lport.p_descr = "Fake port description";
405 hardware.h_lport.p_mfs = 1516;
406 chassis.c_id_subtype = LLDP_CHASSISID_SUBTYPE_LOCAL;
407 chassis.c_id = "Chassis name";
408 chassis.c_id_len = strlen(chassis.c_id);
409 chassis.c_name = "Third chassis";
410 chassis.c_descr = "Chassis description";
411 chassis.c_cap_available = LLDP_CAP_ROUTER | LLDP_CAP_BRIDGE;
412 chassis.c_cap_enabled = LLDP_CAP_ROUTER;
413 chassis.c_med_cap_available = LLDP_MED_CAP_CAP | LLDP_MED_CAP_POLICY |
414 LLDP_MED_CAP_LOCATION | LLDP_MED_CAP_MDI_PSE |
415 LLDP_MED_CAP_IV;
416 chassis.c_med_type = LLDP_MED_CLASS_III;
417 chassis.c_med_hw = "hardware rev 5";
418 chassis.c_med_fw = "47b5";
419 chassis.c_med_sw = "2.6.22b5";
420 chassis.c_med_sn = "SN 47842";
421 hardware.h_lport.p_med_cap_enabled = chassis.c_med_cap_available;
422 hardware.h_lport.p_med_location[LLDP_MED_LOCFORMAT_CIVIC-1].format =
423 LLDP_MED_LOCFORMAT_CIVIC;
424 hardware.h_lport.p_med_location[LLDP_MED_LOCFORMAT_CIVIC-1].data = "Your favorite city";
425 hardware.h_lport.p_med_location[LLDP_MED_LOCFORMAT_CIVIC-1].data_len =
426 sizeof("Your favorite city");
427 hardware.h_lport.p_med_policy[LLDP_MED_APPTYPE_SOFTPHONEVOICE-1].type =
428 LLDP_MED_APPTYPE_SOFTPHONEVOICE;
429 hardware.h_lport.p_med_policy[LLDP_MED_APPTYPE_SOFTPHONEVOICE-1].tagged =
430 1;
431 hardware.h_lport.p_med_policy[LLDP_MED_APPTYPE_SOFTPHONEVOICE-1].vid =
432 51;
433 hardware.h_lport.p_med_policy[LLDP_MED_APPTYPE_SOFTPHONEVOICE-1].priority =
434 6;
435 hardware.h_lport.p_med_policy[LLDP_MED_APPTYPE_SOFTPHONEVOICE-1].dscp =
436 46;
437 hardware.h_lport.p_med_power.devicetype = LLDP_MED_POW_TYPE_PSE;
438 hardware.h_lport.p_med_power.source = LLDP_MED_POW_SOURCE_PRIMARY;
439 hardware.h_lport.p_med_power.priority = LLDP_MED_POW_PRIO_HIGH;
440 hardware.h_lport.p_med_power.val = 65;
441
442 /* Build packet */
443 n = lldp_send(&test_lldpd, &hardware);
444 if (n != 0) {
445 fail("unable to build packet");
446 return;
447 }
448 if (TAILQ_EMPTY(&pkts)) {
449 fail("no packets sent");
450 return;
451 }
452 pkt = TAILQ_FIRST(&pkts);
453 fail_unless(TAILQ_NEXT(pkt, next) == NULL, "more than one packet sent");
454
455 /* decode the retrieved packet calling lldp_decode() */
456 fail_unless(lldp_decode(NULL, pkt->data, pkt->size, &hardware,
457 &nchassis, &nport) != -1);
458 if (!nchassis || !nport) {
459 fail("unable to decode packet");
460 return;
461 }
462 /* verify port values */
463 check_received_port(&hardware.h_lport, nport);
464 /* verify chassis values */
465 check_received_chassis(&chassis, nchassis);
466
467 /* veridfy med content */
468 check_received_port_med(&hardware.h_lport, nport);
469 check_received_chassis_med(&chassis, nchassis);
470 }
471 END_TEST
472 #endif
473
474 #ifdef ENABLE_DOT3
START_TEST(test_send_rcv_dot3)475 START_TEST (test_send_rcv_dot3)
476 {
477 int n;
478 struct lldpd_chassis *nchassis = NULL;
479 struct lldpd_port *nport = NULL;
480 struct packet *pkt;
481
482 /* Populate port and chassis */
483 hardware.h_lport.p_id_subtype = LLDP_PORTID_SUBTYPE_IFNAME;
484 hardware.h_lport.p_id = "FastEthernet 1/5";
485 hardware.h_lport.p_id_len = strlen(hardware.h_lport.p_id);
486 hardware.h_lport.p_descr = "Fake port description";
487 hardware.h_lport.p_mfs = 1516;
488 hardware.h_lport.p_aggregid = 5;
489 hardware.h_lport.p_macphy.autoneg_support = 1;
490 hardware.h_lport.p_macphy.autoneg_enabled = 1;
491 hardware.h_lport.p_macphy.autoneg_advertised = LLDP_DOT3_LINK_AUTONEG_10BASE_T |
492 LLDP_DOT3_LINK_AUTONEG_10BASET_FD | LLDP_DOT3_LINK_AUTONEG_100BASE_TX |
493 LLDP_DOT3_LINK_AUTONEG_100BASE_TXFD;
494 hardware.h_lport.p_macphy.mau_type = LLDP_DOT3_MAU_100BASETXFD;
495 chassis.c_id_subtype = LLDP_CHASSISID_SUBTYPE_LLADDR;
496 chassis.c_id = macaddress;
497 chassis.c_id_len = ETHER_ADDR_LEN;
498 chassis.c_name = "Fourth chassis";
499 chassis.c_descr = "Long chassis description";
500 chassis.c_cap_available = chassis.c_cap_enabled = LLDP_CAP_ROUTER | LLDP_CAP_WLAN;
501
502 /* Build packet */
503 n = lldp_send(&test_lldpd, &hardware);
504 if (n != 0) {
505 fail("unable to build packet");
506 return;
507 }
508 if (TAILQ_EMPTY(&pkts)) {
509 fail("no packets sent");
510 return;
511 }
512 pkt = TAILQ_FIRST(&pkts);
513 fail_unless(TAILQ_NEXT(pkt, next) == NULL, "more than one packet sent");
514
515 /* decode the retrieved packet calling lldp_decode() */
516 fail_unless(lldp_decode(NULL, pkt->data, pkt->size, &hardware,
517 &nchassis, &nport) != -1);
518 if (!nchassis || !nport) {
519 fail("unable to decode packet");
520 return;
521 }
522 /* verify port values */
523 check_received_port(&hardware.h_lport, nport);
524 /* verify chassis values */
525 check_received_chassis(&chassis, nchassis);
526 /* verify dot3 values */
527 check_received_port_dot3(&hardware.h_lport, nport);
528 }
529 END_TEST
530 #endif
531
START_TEST(test_recv_min)532 START_TEST (test_recv_min)
533 {
534 char pkt1[] = {
535 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e, 0x00, 0x17,
536 0xd1, 0xa8, 0x35, 0xbe, 0x88, 0xcc, 0x02, 0x07,
537 0x04, 0x00, 0x17, 0xd1, 0xa8, 0x35, 0xbf, 0x04,
538 0x07, 0x03, 0x00, 0x17, 0xd1, 0xa8, 0x36, 0x02,
539 0x06, 0x02, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00,
540 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
541 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
542 0x00, 0x00, 0x00, 0x00 };
543 /* This is:
544 Ethernet II, Src: Nortel_a8:35:be (00:17:d1:a8:35:be), Dst: LLDP_Multicast (01:80:c2:00:00:0e)
545 Destination: LLDP_Multicast (01:80:c2:00:00:0e)
546 Source: Nortel_a8:35:be (00:17:d1:a8:35:be)
547 Type: 802.1 Link Layer Discovery Protocol (LLDP) (0x88cc)
548 Link Layer Discovery Protocol
549 Chassis Subtype = MAC address
550 0000 001. .... .... = TLV Type: Chassis Id (1)
551 .... ...0 0000 0111 = TLV Length: 7
552 Chassis Id Subtype: MAC address (4)
553 Chassis Id: Nortel_a8:35:bf (00:17:d1:a8:35:bf)
554 Port Subtype = MAC address
555 0000 010. .... .... = TLV Type: Port Id (2)
556 .... ...0 0000 0111 = TLV Length: 7
557 Port Id Subtype: MAC address (3)
558 Port Id: Nortel_a8:36:02 (00:17:d1:a8:36:02)
559 Time To Live = 120 sec
560 0000 011. .... .... = TLV Type: Time to Live (3)
561 .... ...0 0000 0010 = TLV Length: 2
562 Seconds: 120
563 End of LLDPDU
564 0000 000. .... .... = TLV Type: End of LLDPDU (0)
565 .... ...0 0000 0000 = TLV Length: 0
566 */
567 struct lldpd_chassis *nchassis = NULL;
568 struct lldpd_port *nport = NULL;
569 char mac1[] = { 0x0, 0x17, 0xd1, 0xa8, 0x35, 0xbf };
570 char mac2[] = { 0x0, 0x17, 0xd1, 0xa8, 0x36, 0x02 };
571
572 fail_unless(lldp_decode(NULL, pkt1, sizeof(pkt1), &hardware,
573 &nchassis, &nport) != -1);
574 if (!nchassis || !nport) {
575 fail("unable to decode packet");
576 return;
577 }
578 ck_assert_int_eq(nchassis->c_id_subtype,
579 LLDP_CHASSISID_SUBTYPE_LLADDR);
580 ck_assert_int_eq(nchassis->c_id_len, ETHER_ADDR_LEN);
581 fail_unless(memcmp(mac1, nchassis->c_id, ETHER_ADDR_LEN) == 0);
582 ck_assert_int_eq(nport->p_id_subtype,
583 LLDP_PORTID_SUBTYPE_LLADDR);
584 ck_assert_int_eq(nport->p_id_len, ETHER_ADDR_LEN);
585 fail_unless(memcmp(mac2, nport->p_id, ETHER_ADDR_LEN) == 0);
586 ck_assert_ptr_eq(nchassis->c_name, NULL);
587 ck_assert_ptr_eq(nchassis->c_descr, NULL);
588 ck_assert_ptr_eq(nport->p_descr, NULL);
589 ck_assert_int_eq(nport->p_ttl, 120);
590 }
591 END_TEST
592
START_TEST(test_recv_lldpd)593 START_TEST (test_recv_lldpd)
594 {
595 /* This is a frame generated by lldpd */
596 char pkt1[] = {
597 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e, 0x00, 0x16,
598 0x17, 0x2f, 0xa1, 0xb6, 0x88, 0xcc, 0x02, 0x07,
599 0x04, 0x00, 0x16, 0x17, 0x2f, 0xa1, 0xb6, 0x04,
600 0x07, 0x03, 0x00, 0x16, 0x17, 0x2f, 0xa1, 0xb6,
601 0x06, 0x02, 0x00, 0x78, 0x0a, 0x1a, 0x6e, 0x61,
602 0x72, 0x75, 0x74, 0x6f, 0x2e, 0x58, 0x58, 0x58,
603 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58,
604 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58,
605 0x0c, 0x3f, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x20,
606 0x32, 0x2e, 0x36, 0x2e, 0x32, 0x39, 0x2d, 0x32,
607 0x2d, 0x61, 0x6d, 0x64, 0x36, 0x34, 0x20, 0x23,
608 0x31, 0x20, 0x53, 0x4d, 0x50, 0x20, 0x53, 0x75,
609 0x6e, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x31, 0x37,
610 0x20, 0x31, 0x37, 0x3a, 0x31, 0x35, 0x3a, 0x34,
611 0x37, 0x20, 0x55, 0x54, 0x43, 0x20, 0x32, 0x30,
612 0x30, 0x39, 0x20, 0x78, 0x38, 0x36, 0x5f, 0x36,
613 0x34, 0x0e, 0x04, 0x00, 0x1c, 0x00, 0x14, 0x10,
614 0x0c, 0x05, 0x01, 0x0a, 0xee, 0x50, 0x4b, 0x02,
615 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x04, 0x65,
616 0x74, 0x68, 0x30, 0xfe, 0x09, 0x00, 0x12, 0x0f,
617 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x09,
618 0x00, 0x12, 0x0f, 0x01, 0x03, 0x6c, 0x03, 0x00,
619 0x10, 0xfe, 0x06, 0x00, 0x12, 0x0f, 0x04, 0x05,
620 0xdc, 0xfe, 0x07, 0x00, 0x12, 0xbb, 0x01, 0x00,
621 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x12, 0xbb, 0x05,
622 0x4e, 0x44, 0x39, 0x39, 0x31, 0x37, 0x38, 0x39,
623 0x37, 0x30, 0x32, 0xfe, 0x0b, 0x00, 0x12, 0xbb,
624 0x06, 0x30, 0x38, 0x30, 0x30, 0x31, 0x32, 0x20,
625 0xfe, 0x12, 0x00, 0x12, 0xbb, 0x07, 0x32, 0x2e,
626 0x36, 0x2e, 0x32, 0x39, 0x2d, 0x32, 0x2d, 0x61,
627 0x6d, 0x64, 0x36, 0x34, 0xfe, 0x10, 0x00, 0x12,
628 0xbb, 0x08, 0x31, 0x30, 0x35, 0x38, 0x32, 0x30,
629 0x38, 0x35, 0x30, 0x30, 0x30, 0x39, 0xfe, 0x15,
630 0x00, 0x12, 0xbb, 0x09, 0x4e, 0x45, 0x43, 0x20,
631 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72,
632 0x73, 0x20, 0x53, 0x41, 0x53, 0xfe, 0x13, 0x00,
633 0x12, 0xbb, 0x0a, 0x50, 0x4f, 0x57, 0x45, 0x52,
634 0x4d, 0x41, 0x54, 0x45, 0x20, 0x56, 0x4c, 0x33,
635 0x35, 0x30, 0xfe, 0x0d, 0x00, 0x12, 0xbb, 0x0b,
636 0x31, 0x30, 0x30, 0x32, 0x30, 0x37, 0x31, 0x32,
637 0x30, 0x00, 0x00 };
638 /* This is:
639 Ethernet II, Src: Msi_2f:a1:b6 (00:16:17:2f:a1:b6), Dst: LLDP_Multicast (01:80:c2:00:00:0e)
640 Destination: LLDP_Multicast (01:80:c2:00:00:0e)
641 Source: Msi_2f:a1:b6 (00:16:17:2f:a1:b6)
642 Type: 802.1 Link Layer Discovery Protocol (LLDP) (0x88cc)
643 Link Layer Discovery Protocol
644 Chassis Subtype = MAC address
645 0000 001. .... .... = TLV Type: Chassis Id (1)
646 .... ...0 0000 0111 = TLV Length: 7
647 Chassis Id Subtype: MAC address (4)
648 Chassis Id: Msi_2f:a1:b6 (00:16:17:2f:a1:b6)
649 Port Subtype = MAC address
650 0000 010. .... .... = TLV Type: Port Id (2)
651 .... ...0 0000 0111 = TLV Length: 7
652 Port Id Subtype: MAC address (3)
653 Port Id: Msi_2f:a1:b6 (00:16:17:2f:a1:b6)
654 Time To Live = 120 sec
655 0000 011. .... .... = TLV Type: Time to Live (3)
656 .... ...0 0000 0010 = TLV Length: 2
657 Seconds: 120
658 System Name = naruto.XXXXXXXXXXXXXXXXXXX
659 0000 101. .... .... = TLV Type: System Name (5)
660 .... ...0 0001 1010 = TLV Length: 26
661 System Name = naruto.bureau.b1.p.fti.net
662 System Description = Linux 2.6.29-2-amd64 #1 SMP Sun May 17 17:15:47 UTC 2009 x86_64
663 0000 110. .... .... = TLV Type: System Description (6)
664 .... ...0 0011 1111 = TLV Length: 63
665 System Description = Linux 2.6.29-2-amd64 #1 SMP Sun May 17 17:15:47 UTC 2009 x86_64
666 Capabilities
667 0000 111. .... .... = TLV Type: System Capabilities (7)
668 .... ...0 0000 0100 = TLV Length: 4
669 Capabilities: 0x001c
670 .... .... .... .1.. = Bridge
671 .... .... .... 1... = WLAN access point
672 .... .... ...1 .... = Router
673 Enabled Capabilities: 0x0014
674 .... .... .... .1.. = Bridge
675 .... .... ...1 .... = Router
676 Management Address
677 0001 000. .... .... = TLV Type: Management Address (8)
678 .... ...0 0000 1100 = TLV Length: 12
679 Address String Length: 5
680 Address Subtype: IPv4 (1)
681 Management Address: 10.238.80.75
682 Interface Subtype: ifIndex (2)
683 Interface Number: 3
684 OID String Length: 0
685 Port Description = eth0
686 0000 100. .... .... = TLV Type: Port Description (4)
687 .... ...0 0000 0100 = TLV Length: 4
688 Port Description: eth0
689 IEEE 802.3 - Link Aggregation
690 1111 111. .... .... = TLV Type: Organization Specific (127)
691 .... ...0 0000 1001 = TLV Length: 9
692 Organization Unique Code: IEEE 802.3 (0x00120f)
693 IEEE 802.3 Subtype: Link Aggregation (0x03)
694 Aggregation Status: 0x01
695 .... ...1 = Aggregation Capability: Yes
696 .... ..0. = Aggregation Status: Not Enabled
697 Aggregated Port Id: 0
698 IEEE 802.3 - MAC/PHY Configuration/Status
699 1111 111. .... .... = TLV Type: Organization Specific (127)
700 .... ...0 0000 1001 = TLV Length: 9
701 Organization Unique Code: IEEE 802.3 (0x00120f)
702 IEEE 802.3 Subtype: MAC/PHY Configuration/Status (0x01)
703 Auto-Negotiation Support/Status: 0x03
704 .... ...1 = Auto-Negotiation: Supported
705 .... ..1. = Auto-Negotiation: Enabled
706 PMD Auto-Negotiation Advertised Capability: 0x6C03
707 .... .... .... ...1 = 1000BASE-T (full duplex mode)
708 .... .... .... ..1. = 1000BASE-T (half duplex mode)
709 .... .1.. .... .... = 100BASE-TX (full duplex mode)
710 .... 1... .... .... = 100BASE-TX (half duplex mode)
711 ..1. .... .... .... = 10BASE-T (full duplex mode)
712 .1.. .... .... .... = 10BASE-T (half duplex mode)
713 Operational MAU Type: 100BaseTXFD - 2 pair category 5 UTP, full duplex mode (0x0010)
714 IEEE 802.3 - Maximum Frame Size
715 1111 111. .... .... = TLV Type: Organization Specific (127)
716 .... ...0 0000 0110 = TLV Length: 6
717 Organization Unique Code: IEEE 802.3 (0x00120f)
718 IEEE 802.3 Subtype: Maximum Frame Size (0x04)
719 Maximum Frame Size: 1500
720 TIA - Media Capabilities
721 1111 111. .... .... = TLV Type: Organization Specific (127)
722 .... ...0 0000 0111 = TLV Length: 7
723 Organization Unique Code: TIA (0x0012bb)
724 Media Subtype: Media Capabilities (0x01)
725 Capabilities: 0x0000
726 Class Type: Type Not Defined
727 TIA - Inventory - Hardware Revision
728 1111 111. .... .... = TLV Type: Organization Specific (127)
729 .... ...0 0000 1111 = TLV Length: 15
730 Organization Unique Code: TIA (0x0012bb)
731 Media Subtype: Inventory - Hardware Revision (0x05)
732 Hardware Revision: ND991789702
733 TIA - Inventory - Firmware Revision
734 1111 111. .... .... = TLV Type: Organization Specific (127)
735 .... ...0 0000 1011 = TLV Length: 10
736 Organization Unique Code: TIA (0x0012bb)
737 Media Subtype: Inventory - Firmware Revision (0x06)
738 Firmware Revision: 080012
739 TIA - Inventory - Software Revision
740 1111 111. .... .... = TLV Type: Organization Specific (127)
741 .... ...0 0001 0010 = TLV Length: 18
742 Organization Unique Code: TIA (0x0012bb)
743 Media Subtype: Inventory - Software Revision (0x07)
744 Software Revision: 2.6.29-2-amd64
745 TIA - Inventory - Serial Number
746 1111 111. .... .... = TLV Type: Organization Specific (127)
747 .... ...0 0001 0000 = TLV Length: 16
748 Organization Unique Code: TIA (0x0012bb)
749 Media Subtype: Inventory - Serial Number (0x08)
750 Serial Number: 105820850009
751 TIA - Inventory - Manufacturer Name
752 1111 111. .... .... = TLV Type: Organization Specific (127)
753 .... ...0 0001 0101 = TLV Length: 21
754 Organization Unique Code: TIA (0x0012bb)
755 Media Subtype: Inventory - Manufacturer Name (0x09)
756 Manufacturer Name: NEC Computers SAS
757 TIA - Inventory - Model Name
758 1111 111. .... .... = TLV Type: Organization Specific (127)
759 .... ...0 0001 0011 = TLV Length: 19
760 Organization Unique Code: TIA (0x0012bb)
761 Media Subtype: Inventory - Model Name (0x0a)
762 Model Name: POWERMATE VL350
763 TIA - Inventory - Asset ID
764 1111 111. .... .... = TLV Type: Organization Specific (127)
765 .... ...0 0000 1101 = TLV Length: 13
766 Organization Unique Code: TIA (0x0012bb)
767 Media Subtype: Inventory - Asset ID (0x0b)
768 Asset ID: 100207120
769 End of LLDPDU
770 0000 000. .... .... = TLV Type: End of LLDPDU (0)
771 .... ...0 0000 0000 = TLV Length: 0
772 */
773 struct lldpd_chassis *nchassis = NULL;
774 struct lldpd_port *nport = NULL;
775 char mac1[] = { 0x00, 0x16, 0x17, 0x2f, 0xa1, 0xb6 };
776
777 fail_unless(lldp_decode(NULL, pkt1, sizeof(pkt1), &hardware,
778 &nchassis, &nport) != -1);
779 if (!nchassis || !nport) {
780 fail("unable to decode packet");
781 return;
782 }
783 ck_assert_int_eq(nchassis->c_id_subtype,
784 LLDP_CHASSISID_SUBTYPE_LLADDR);
785 ck_assert_int_eq(nchassis->c_id_len, ETHER_ADDR_LEN);
786 fail_unless(memcmp(mac1, nchassis->c_id, ETHER_ADDR_LEN) == 0);
787 ck_assert_int_eq(nport->p_id_subtype,
788 LLDP_PORTID_SUBTYPE_LLADDR);
789 ck_assert_int_eq(nport->p_id_len, ETHER_ADDR_LEN);
790 fail_unless(memcmp(mac1, nport->p_id, ETHER_ADDR_LEN) == 0);
791 ck_assert_int_eq(nport->p_ttl, 120);
792 ck_assert_str_eq(nchassis->c_name, "naruto.XXXXXXXXXXXXXXXXXXX");
793 ck_assert_str_eq(nchassis->c_descr,
794 "Linux 2.6.29-2-amd64 #1 SMP Sun May 17 17:15:47 UTC 2009 x86_64");
795 ck_assert_str_eq(nport->p_descr, "eth0");
796 ck_assert_int_eq(nchassis->c_cap_available,
797 LLDP_CAP_WLAN | LLDP_CAP_ROUTER | LLDP_CAP_BRIDGE);
798 ck_assert_int_eq(nchassis->c_cap_enabled,
799 LLDP_CAP_ROUTER | LLDP_CAP_BRIDGE);
800 ck_assert_int_eq(nchassis->c_mgmt.tqh_first->m_addr.inet.s_addr,
801 (u_int32_t)inet_addr("10.238.80.75"));
802 ck_assert_int_eq(nchassis->c_mgmt.tqh_first->m_iface, 3);
803 #ifdef ENABLE_DOT3
804 ck_assert_int_eq(nport->p_aggregid, 0);
805 ck_assert_int_eq(nport->p_macphy.autoneg_enabled, 1);
806 ck_assert_int_eq(nport->p_macphy.autoneg_support, 1);
807 ck_assert_int_eq(nport->p_macphy.autoneg_advertised,
808 LLDP_DOT3_LINK_AUTONEG_1000BASE_TFD |
809 LLDP_DOT3_LINK_AUTONEG_1000BASE_T |
810 LLDP_DOT3_LINK_AUTONEG_100BASE_TXFD |
811 LLDP_DOT3_LINK_AUTONEG_100BASE_TX |
812 LLDP_DOT3_LINK_AUTONEG_10BASET_FD |
813 LLDP_DOT3_LINK_AUTONEG_10BASE_T);
814 ck_assert_int_eq(nport->p_macphy.mau_type,
815 LLDP_DOT3_MAU_100BASETXFD);
816 ck_assert_int_eq(nport->p_mfs, 1500);
817 #endif
818 #ifdef ENABLE_LLDPMED
819 ck_assert_int_eq(nchassis->c_med_type, 0);
820 ck_assert_str_eq(nchassis->c_med_hw, "ND991789702");
821 ck_assert_str_eq(nchassis->c_med_fw, "080012 "); /* Extra space */
822 ck_assert_str_eq(nchassis->c_med_sw, "2.6.29-2-amd64");
823 ck_assert_str_eq(nchassis->c_med_sn, "105820850009");
824 ck_assert_str_eq(nchassis->c_med_manuf, "NEC Computers SAS");
825 ck_assert_str_eq(nchassis->c_med_model, "POWERMATE VL350");
826 ck_assert_str_eq(nchassis->c_med_asset, "100207120");
827 #endif
828 }
829 END_TEST
830
831 Suite *
lldp_suite(void)832 lldp_suite(void)
833 {
834 Suite *s = suite_create("LLDP");
835 TCase *tc_send = tcase_create("Send LLDP packets");
836 TCase *tc_receive = tcase_create("Receive LLDP packets");
837
838 /* Send tests are first run without knowing the result. The
839 result is then checked with:
840 tshark -V -T text -r tests/lldp_send_0000.pcap
841
842 If the result is correct, then, we get the packet as C
843 bytes using wireshark export to C arrays (tshark seems not
844 be able to do this).
845 */
846
847 tcase_add_checked_fixture(tc_send, pcap_setup, pcap_teardown);
848 tcase_add_test(tc_send, test_send_rcv_basic);
849 tcase_add_test(tc_send, test_send_rcv_vlan_tx);
850 #ifdef ENABLE_DOT1
851 tcase_add_test(tc_send, test_send_rcv_dot1_tlvs);
852 #endif
853 #ifdef ENABLE_LLDPMED
854 tcase_add_test(tc_send, test_send_rcv_med);
855 #endif
856 #ifdef ENABLE_DOT3
857 tcase_add_test(tc_send, test_send_rcv_dot3);
858 #endif
859 suite_add_tcase(s, tc_send);
860
861 tcase_add_test(tc_receive, test_recv_min);
862 tcase_add_test(tc_receive, test_recv_lldpd);
863 suite_add_tcase(s, tc_receive);
864
865 return s;
866 }
867
868 int
main()869 main()
870 {
871 int number_failed;
872 Suite *s = lldp_suite ();
873 SRunner *sr = srunner_create (s);
874 srunner_set_fork_status (sr, CK_NOFORK); /* Can't fork because
875 we need to write
876 files */
877 srunner_run_all (sr, CK_ENV);
878 number_failed = srunner_ntests_failed (sr);
879 srunner_free (sr);
880 return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
881 }
882