xref: /freebsd/contrib/tcpdump/print-udld.c (revision 0a7e5f1f02aad2ff5fff1c60f44c6975fd07e1d9)
1a5779b6eSRui Paulo /*
2a5779b6eSRui Paulo  * Copyright (c) 1998-2007 The TCPDUMP project
3a5779b6eSRui Paulo  *
4a5779b6eSRui Paulo  * Redistribution and use in source and binary forms, with or without
5a5779b6eSRui Paulo  * modification, are permitted provided that: (1) source code
6a5779b6eSRui Paulo  * distributions retain the above copyright notice and this paragraph
7a5779b6eSRui Paulo  * in its entirety, and (2) distributions including binary code include
8a5779b6eSRui Paulo  * the above copyright notice and this paragraph in its entirety in
9a5779b6eSRui Paulo  * the documentation or other materials provided with the distribution.
10a5779b6eSRui Paulo  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
11a5779b6eSRui Paulo  * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
12a5779b6eSRui Paulo  * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
13a5779b6eSRui Paulo  * FOR A PARTICULAR PURPOSE.
14a5779b6eSRui Paulo  *
15a5779b6eSRui Paulo  * Original code by Carles Kishimoto <carles.kishimoto@gmail.com>
16a5779b6eSRui Paulo  */
17a5779b6eSRui Paulo 
183340d773SGleb Smirnoff /* \summary: Cisco UniDirectional Link Detection (UDLD) protocol printer */
193340d773SGleb Smirnoff 
203340d773SGleb Smirnoff /* specification: RFC 5171 */
213340d773SGleb Smirnoff 
22*ee67461eSJoseph Mingrone #include <config.h>
23a5779b6eSRui Paulo 
24*ee67461eSJoseph Mingrone #include "netdissect-stdinc.h"
25a5779b6eSRui Paulo 
26*ee67461eSJoseph Mingrone #define ND_LONGJMP_FROM_TCHECK
273340d773SGleb Smirnoff #include "netdissect.h"
28a5779b6eSRui Paulo #include "extract.h"
29a5779b6eSRui Paulo 
303340d773SGleb Smirnoff 
31a5779b6eSRui Paulo #define UDLD_HEADER_LEN			4
32*ee67461eSJoseph Mingrone #define UDLD_TLV_HEADER_LEN		4
33a5779b6eSRui Paulo #define UDLD_DEVICE_ID_TLV		0x0001
34a5779b6eSRui Paulo #define UDLD_PORT_ID_TLV		0x0002
35a5779b6eSRui Paulo #define UDLD_ECHO_TLV			0x0003
36a5779b6eSRui Paulo #define UDLD_MESSAGE_INTERVAL_TLV	0x0004
37a5779b6eSRui Paulo #define UDLD_TIMEOUT_INTERVAL_TLV	0x0005
38a5779b6eSRui Paulo #define UDLD_DEVICE_NAME_TLV		0x0006
39a5779b6eSRui Paulo #define UDLD_SEQ_NUMBER_TLV		0x0007
40a5779b6eSRui Paulo 
413c602fabSXin LI static const struct tok udld_tlv_values[] = {
42a5779b6eSRui Paulo     { UDLD_DEVICE_ID_TLV, "Device-ID TLV"},
43a5779b6eSRui Paulo     { UDLD_PORT_ID_TLV, "Port-ID TLV"},
44a5779b6eSRui Paulo     { UDLD_ECHO_TLV, "Echo TLV"},
45a5779b6eSRui Paulo     { UDLD_MESSAGE_INTERVAL_TLV, "Message Interval TLV"},
46a5779b6eSRui Paulo     { UDLD_TIMEOUT_INTERVAL_TLV, "Timeout Interval TLV"},
47a5779b6eSRui Paulo     { UDLD_DEVICE_NAME_TLV, "Device Name TLV"},
48a5779b6eSRui Paulo     { UDLD_SEQ_NUMBER_TLV,"Sequence Number TLV"},
49a5779b6eSRui Paulo     { 0, NULL}
50a5779b6eSRui Paulo };
51a5779b6eSRui Paulo 
523c602fabSXin LI static const struct tok udld_code_values[] = {
53a5779b6eSRui Paulo     { 0x00, "Reserved"},
54a5779b6eSRui Paulo     { 0x01, "Probe message"},
55a5779b6eSRui Paulo     { 0x02, "Echo message"},
56a5779b6eSRui Paulo     { 0x03, "Flush message"},
57a5779b6eSRui Paulo     { 0, NULL}
58a5779b6eSRui Paulo };
59a5779b6eSRui Paulo 
60*ee67461eSJoseph Mingrone static const struct tok udld_flags_bitmap_str[] = {
61*ee67461eSJoseph Mingrone     { 1U << 0, "RT"    },
62*ee67461eSJoseph Mingrone     { 1U << 1, "RSY"   },
63*ee67461eSJoseph Mingrone     { 1U << 2, "MBZ-2" },
64*ee67461eSJoseph Mingrone     { 1U << 3, "MBZ-3" },
65*ee67461eSJoseph Mingrone     { 1U << 4, "MBZ-4" },
66*ee67461eSJoseph Mingrone     { 1U << 5, "MBZ-5" },
67*ee67461eSJoseph Mingrone     { 1U << 6, "MBZ-6" },
68*ee67461eSJoseph Mingrone     { 1U << 7, "MBZ-7" },
69a5779b6eSRui Paulo     { 0, NULL}
70a5779b6eSRui Paulo };
71a5779b6eSRui Paulo 
72a5779b6eSRui Paulo /*
733340d773SGleb Smirnoff  * UDLD's Protocol Data Unit format:
74a5779b6eSRui Paulo  *
75a5779b6eSRui Paulo  *  0                   1                   2                   3
76a5779b6eSRui Paulo  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
77a5779b6eSRui Paulo  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
78a5779b6eSRui Paulo  * | Ver | Opcode  |     Flags     |           Checksum            |
79a5779b6eSRui Paulo  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
80a5779b6eSRui Paulo  * |               List of TLVs (variable length list)             |
81a5779b6eSRui Paulo  * |                              ...                              |
82a5779b6eSRui Paulo  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
83a5779b6eSRui Paulo  *
843340d773SGleb Smirnoff  * TLV format:
853340d773SGleb Smirnoff  *
863340d773SGleb Smirnoff  *  0                   1                   2                   3
873340d773SGleb Smirnoff  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
883340d773SGleb Smirnoff  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
893340d773SGleb Smirnoff  * |             TYPE              |            LENGTH             |
903340d773SGleb Smirnoff  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
913340d773SGleb Smirnoff  * |                             VALUE                             |
923340d773SGleb Smirnoff  * |                              ...                              |
933340d773SGleb Smirnoff  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
943340d773SGleb Smirnoff  *
953340d773SGleb Smirnoff  * LENGTH: Length in bytes of the Type, Length, and Value fields.
96a5779b6eSRui Paulo  */
97a5779b6eSRui Paulo 
98a5779b6eSRui Paulo #define	UDLD_EXTRACT_VERSION(x) (((x)&0xe0)>>5)
99a5779b6eSRui Paulo #define	UDLD_EXTRACT_OPCODE(x) ((x)&0x1f)
100a5779b6eSRui Paulo 
101a5779b6eSRui Paulo void
udld_print(netdissect_options * ndo,const u_char * tptr,u_int length)102*ee67461eSJoseph Mingrone udld_print(netdissect_options *ndo,
103*ee67461eSJoseph Mingrone            const u_char *tptr, u_int length)
104a5779b6eSRui Paulo {
105*ee67461eSJoseph Mingrone     uint8_t ver, code, flags;
106a5779b6eSRui Paulo 
107*ee67461eSJoseph Mingrone     ndo->ndo_protocol = "udld";
108a5779b6eSRui Paulo     if (length < UDLD_HEADER_LEN)
109*ee67461eSJoseph Mingrone         goto invalid;
110a5779b6eSRui Paulo 
111*ee67461eSJoseph Mingrone     ver = UDLD_EXTRACT_VERSION(GET_U_1(tptr));
112*ee67461eSJoseph Mingrone     code = UDLD_EXTRACT_OPCODE(GET_U_1(tptr));
113*ee67461eSJoseph Mingrone     tptr += 1;
114*ee67461eSJoseph Mingrone     length -= 1;
115a5779b6eSRui Paulo 
116*ee67461eSJoseph Mingrone     flags = GET_U_1(tptr);
117*ee67461eSJoseph Mingrone     tptr += 1;
118*ee67461eSJoseph Mingrone     length -= 1;
119a5779b6eSRui Paulo 
120*ee67461eSJoseph Mingrone     ND_PRINT("UDLDv%u, Code %s (%x), Flags [%s] (0x%02x), length %u",
121*ee67461eSJoseph Mingrone            ver,
122a5779b6eSRui Paulo            tok2str(udld_code_values, "Reserved", code),
123a5779b6eSRui Paulo            code,
124*ee67461eSJoseph Mingrone            bittok2str(udld_flags_bitmap_str, "none", flags),
125*ee67461eSJoseph Mingrone            flags,
126*ee67461eSJoseph Mingrone            length + 2);
127a5779b6eSRui Paulo 
128a5779b6eSRui Paulo     /*
129a5779b6eSRui Paulo      * In non-verbose mode, just print version and opcode type
130a5779b6eSRui Paulo      */
1313c602fabSXin LI     if (ndo->ndo_vflag < 1) {
132*ee67461eSJoseph Mingrone         goto tcheck_remainder;
133a5779b6eSRui Paulo     }
134a5779b6eSRui Paulo 
135*ee67461eSJoseph Mingrone     ND_PRINT("\n\tChecksum 0x%04x (unverified)", GET_BE_U_2(tptr));
136*ee67461eSJoseph Mingrone     tptr += 2;
137*ee67461eSJoseph Mingrone     length -= 2;
138a5779b6eSRui Paulo 
139*ee67461eSJoseph Mingrone     while (length) {
140*ee67461eSJoseph Mingrone         uint16_t type, len;
141a5779b6eSRui Paulo 
142*ee67461eSJoseph Mingrone         if (length < UDLD_TLV_HEADER_LEN)
1433340d773SGleb Smirnoff             goto invalid;
1443340d773SGleb Smirnoff 
145*ee67461eSJoseph Mingrone 	type = GET_BE_U_2(tptr);
146*ee67461eSJoseph Mingrone         tptr += 2;
147*ee67461eSJoseph Mingrone         length -= 2;
148*ee67461eSJoseph Mingrone 
149*ee67461eSJoseph Mingrone         len  = GET_BE_U_2(tptr);
150*ee67461eSJoseph Mingrone         tptr += 2;
151*ee67461eSJoseph Mingrone         length -= 2;
152*ee67461eSJoseph Mingrone 
153*ee67461eSJoseph Mingrone         ND_PRINT("\n\t%s (0x%04x) TLV, length %u",
154*ee67461eSJoseph Mingrone                tok2str(udld_tlv_values, "Unknown", type),
155*ee67461eSJoseph Mingrone                type, len);
156*ee67461eSJoseph Mingrone 
1573340d773SGleb Smirnoff         /* infinite loop check */
158*ee67461eSJoseph Mingrone         if (len <= UDLD_TLV_HEADER_LEN)
1593340d773SGleb Smirnoff             goto invalid;
1603340d773SGleb Smirnoff 
161*ee67461eSJoseph Mingrone         len -= UDLD_TLV_HEADER_LEN;
162*ee67461eSJoseph Mingrone         if (length < len)
163*ee67461eSJoseph Mingrone             goto invalid;
1643340d773SGleb Smirnoff 
165a5779b6eSRui Paulo         switch (type) {
166a5779b6eSRui Paulo         case UDLD_DEVICE_ID_TLV:
167a5779b6eSRui Paulo         case UDLD_PORT_ID_TLV:
168a5779b6eSRui Paulo         case UDLD_DEVICE_NAME_TLV:
169*ee67461eSJoseph Mingrone             ND_PRINT(", ");
170*ee67461eSJoseph Mingrone             nd_printjnp(ndo, tptr, len);
1713340d773SGleb Smirnoff             break;
1723340d773SGleb Smirnoff 
1733340d773SGleb Smirnoff         case UDLD_ECHO_TLV:
174*ee67461eSJoseph Mingrone             ND_PRINT(", ");
175*ee67461eSJoseph Mingrone             (void)nd_printn(ndo, tptr, len, NULL);
176a5779b6eSRui Paulo             break;
177a5779b6eSRui Paulo 
178a5779b6eSRui Paulo         case UDLD_MESSAGE_INTERVAL_TLV:
179a5779b6eSRui Paulo         case UDLD_TIMEOUT_INTERVAL_TLV:
1803340d773SGleb Smirnoff             if (len != 1)
1813340d773SGleb Smirnoff                 goto invalid;
182*ee67461eSJoseph Mingrone             ND_PRINT(", %us", (GET_U_1(tptr)));
183a5779b6eSRui Paulo             break;
184a5779b6eSRui Paulo 
185a5779b6eSRui Paulo         case UDLD_SEQ_NUMBER_TLV:
1863340d773SGleb Smirnoff             if (len != 4)
1873340d773SGleb Smirnoff                 goto invalid;
188*ee67461eSJoseph Mingrone             ND_PRINT(", %u", GET_BE_U_4(tptr));
189a5779b6eSRui Paulo             break;
190a5779b6eSRui Paulo 
191a5779b6eSRui Paulo         default:
192*ee67461eSJoseph Mingrone             ND_TCHECK_LEN(tptr, len);
193a5779b6eSRui Paulo             break;
194a5779b6eSRui Paulo         }
195a5779b6eSRui Paulo         tptr += len;
196*ee67461eSJoseph Mingrone         length -= len;
197a5779b6eSRui Paulo     }
198a5779b6eSRui Paulo 
199a5779b6eSRui Paulo     return;
200a5779b6eSRui Paulo 
2013340d773SGleb Smirnoff invalid:
202*ee67461eSJoseph Mingrone     nd_print_invalid(ndo);
203*ee67461eSJoseph Mingrone tcheck_remainder:
204*ee67461eSJoseph Mingrone     ND_TCHECK_LEN(tptr, length);
205a5779b6eSRui Paulo }
206