]> The Tcpdump Group git mirrors - tcpdump/blob - print-lldp.c
add basic support for the IEEE Link Discovery Protocol as per 802.1ab
[tcpdump] / print-lldp.c
1 /*
2 * Copyright (c) 1998-2007 The TCPDUMP project
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that: (1) source code
6 * distributions retain the above copyright notice and this paragraph
7 * in its entirety, and (2) distributions including binary code include
8 * the above copyright notice and this paragraph in its entirety in
9 * the documentation or other materials provided with the distribution.
10 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
11 * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
12 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
13 * FOR A PARTICULAR PURPOSE.
14 *
15 * support for the IEEE Link Discovery Protocol as per 802.1ab
16 *
17 * Original code by Hannes Gredler (hannes@juniper.net)
18 */
19
20 #ifndef lint
21 static const char rcsid[] _U_ =
22 "@(#) $Header: /tcpdump/master/tcpdump/print-lldp.c,v 1.1 2007-08-03 11:03:19 hannes Exp $";
23 #endif
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include <tcpdump-stdinc.h>
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 #include "interface.h"
36 #include "extract.h"
37 #include "addrtoname.h"
38
39 #define LLDP_EXTRACT_TYPE(x) (((x)&0xfe00)>>9)
40 #define LLDP_EXTRACT_LEN(x) ((x)&0x01ff)
41
42 #define LLDP_END_TLV 0
43 #define LLDP_CHASSIS_ID_TLV 1
44 #define LLDP_PORT_ID_TLV 2
45 #define LLDP_TTL_TLV 3
46 #define LLDP_PORT_DESCR_TLV 4
47 #define LLDP_SYSTEM_NAME_TLV 5
48 #define LLDP_SYSTEM_DESCR_TLV 6
49 #define LLDP_SYSTEM_CAP_TLV 7
50 #define LLDP_MGMT_ADDR_TLV 8
51 #define LLDP_PRIVATE_TLV 127
52
53
54 static const struct tok lldp_tlv_values[] = {
55 { LLDP_END_TLV, "End" },
56 { LLDP_CHASSIS_ID_TLV, "Chassis ID" },
57 { LLDP_PORT_ID_TLV, "Port ID" },
58 { LLDP_TTL_TLV, "Time to Live" },
59 { LLDP_PORT_DESCR_TLV, "Port Description" },
60 { LLDP_SYSTEM_NAME_TLV, "System Name" },
61 { LLDP_SYSTEM_DESCR_TLV, "System Description" },
62 { LLDP_SYSTEM_CAP_TLV, "System Capabilities" },
63 { LLDP_MGMT_ADDR_TLV, "Management Address" },
64 { LLDP_PRIVATE_TLV, "Organization specific" },
65 { 0, NULL}
66 };
67
68 void lldp_print(register const u_char *pptr, register u_int len) {
69
70 u_int16_t tlv;
71 u_int tlen, hexdump, tlv_type, tlv_len;
72 const u_char *tptr;
73
74 tptr = pptr;
75 tlen = len;
76
77 printf("LLDP, length %u", len);
78
79 if (!vflag) {
80 return;
81 }
82
83 while (tlen >= sizeof(tlv)) {
84
85 TCHECK2(*tptr, sizeof(tlv));
86
87 tlv = EXTRACT_16BITS(tptr);
88
89 tlv_type = LLDP_EXTRACT_TYPE(tlv);
90 tlv_len = LLDP_EXTRACT_LEN(tlv);
91 hexdump = FALSE;
92
93 tlen -= sizeof(tlv);
94 tptr += sizeof(tlv);
95
96 printf("\n\t%s TLV (%u), length %u",
97 tok2str(lldp_tlv_values, "Unknown", tlv_type),
98 tlv_type, tlv_len);
99
100 /* infinite loop check */
101 if (!tlv_type || !tlv_len) {
102 break;
103 }
104
105 TCHECK2(*tptr, tlv_len);
106
107 switch (tlv_type) {
108 case LLDP_TTL_TLV:
109 printf(", TTL %us", EXTRACT_16BITS(tptr));
110 break;
111
112 case LLDP_SYSTEM_NAME_TLV:
113 case LLDP_PORT_DESCR_TLV:
114 printf(", ");
115 safeputs((const char *)tptr, tlv_len);
116 break;
117
118 case LLDP_SYSTEM_DESCR_TLV:
119 printf("\n\t ");
120 safeputs((const char *)tptr, tlv_len);
121 break;
122
123 default:
124 hexdump = TRUE;
125 }
126
127 /* do we also want to see a hex dump ? */
128 if (vflag > 1 || hexdump) {
129 print_unknown_data(tptr,"\n\t ", tlv_len);
130 }
131
132 tlen -= tlv_len;
133 tptr += tlv_len;
134 }
135 return;
136 trunc:
137 printf("\n\t[|LLDP]");
138 }