xref: /netbsd-src/external/bsd/tcpdump/dist/print-bfd.c (revision 26ba0b503b498a5194a71ac319838b7f5497f3fe)
10f74e101Schristos /*
20f74e101Schristos  * Redistribution and use in source and binary forms, with or without
30f74e101Schristos  * modification, are permitted provided that: (1) source code
40f74e101Schristos  * distributions retain the above copyright notice and this paragraph
50f74e101Schristos  * in its entirety, and (2) distributions including binary code include
60f74e101Schristos  * the above copyright notice and this paragraph in its entirety in
70f74e101Schristos  * the documentation or other materials provided with the distribution.
80f74e101Schristos  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
90f74e101Schristos  * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
100f74e101Schristos  * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
110f74e101Schristos  * FOR A PARTICULAR PURPOSE.
120f74e101Schristos  *
1372c96ff3Schristos  * Original code by Hannes Gredler (hannes@gredler.at)
140f74e101Schristos  */
150f74e101Schristos 
1611b3aaa1Schristos #include <sys/cdefs.h>
170f74e101Schristos #ifndef lint
18*26ba0b50Schristos __RCSID("$NetBSD: print-bfd.c,v 1.10 2024/09/02 16:15:30 christos Exp $");
190f74e101Schristos #endif
200f74e101Schristos 
21dc860a36Sspz /* \summary: Bidirectional Forwarding Detection (BFD) printer */
22dc860a36Sspz 
23817e9a7eSchristos /*
24817e9a7eSchristos  * specification: draft-ietf-bfd-base-01 for version 0,
25817e9a7eSchristos  * RFC 5880 for version 1, and RFC 5881
26817e9a7eSchristos  */
27dc860a36Sspz 
28c74ad251Schristos #include <config.h>
290f74e101Schristos 
30c74ad251Schristos #include "netdissect-stdinc.h"
310f74e101Schristos 
32c74ad251Schristos #define ND_LONGJMP_FROM_TCHECK
33fdccd7e4Schristos #include "netdissect.h"
340f74e101Schristos #include "extract.h"
350f74e101Schristos 
360f74e101Schristos #include "udp.h"
370f74e101Schristos 
380f74e101Schristos /*
39817e9a7eSchristos  * Control packet, BFDv0, draft-ietf-bfd-base-01
400f74e101Schristos  *
410f74e101Schristos  *     0                   1                   2                   3
420f74e101Schristos  *     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
430f74e101Schristos  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
44817e9a7eSchristos  *    |Vers |  Diag   |H|D|P|F|C|A|Rsv|  Detect Mult  |    Length     |
450f74e101Schristos  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
460f74e101Schristos  *    |                       My Discriminator                        |
470f74e101Schristos  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
480f74e101Schristos  *    |                      Your Discriminator                       |
490f74e101Schristos  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
500f74e101Schristos  *    |                    Desired Min TX Interval                    |
510f74e101Schristos  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
520f74e101Schristos  *    |                   Required Min RX Interval                    |
530f74e101Schristos  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
540f74e101Schristos  *    |                 Required Min Echo RX Interval                 |
550f74e101Schristos  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
560f74e101Schristos  */
570f74e101Schristos 
580f74e101Schristos /*
59dc860a36Sspz  *  Control packet, BFDv1, RFC 5880
600f74e101Schristos  *
610f74e101Schristos  *     0                   1                   2                   3
620f74e101Schristos  *     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
630f74e101Schristos  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
64dc860a36Sspz  *    |Vers |  Diag   |Sta|P|F|C|A|D|M|  Detect Mult  |    Length     |
650f74e101Schristos  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
660f74e101Schristos  *    |                       My Discriminator                        |
670f74e101Schristos  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
680f74e101Schristos  *    |                      Your Discriminator                       |
690f74e101Schristos  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
700f74e101Schristos  *    |                    Desired Min TX Interval                    |
710f74e101Schristos  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
720f74e101Schristos  *    |                   Required Min RX Interval                    |
730f74e101Schristos  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
740f74e101Schristos  *    |                 Required Min Echo RX Interval                 |
750f74e101Schristos  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
760f74e101Schristos  */
770f74e101Schristos 
780f74e101Schristos struct bfd_header_t {
79c74ad251Schristos     nd_uint8_t  version_diag;
80c74ad251Schristos     nd_uint8_t  flags;
81c74ad251Schristos     nd_uint8_t  detect_time_multiplier;
82c74ad251Schristos     nd_uint8_t  length;
83c74ad251Schristos     nd_uint32_t my_discriminator;
84c74ad251Schristos     nd_uint32_t your_discriminator;
85c74ad251Schristos     nd_uint32_t desired_min_tx_interval;
86c74ad251Schristos     nd_uint32_t required_min_rx_interval;
87c74ad251Schristos     nd_uint32_t required_min_echo_interval;
880f74e101Schristos };
890f74e101Schristos 
900f74e101Schristos /*
910f74e101Schristos  *    An optional Authentication Header may be present
920f74e101Schristos  *
930f74e101Schristos  *     0                   1                   2                   3
940f74e101Schristos  *     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
950f74e101Schristos  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
960f74e101Schristos  *    |   Auth Type   |   Auth Len    |    Authentication Data...     |
970f74e101Schristos  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
980f74e101Schristos  */
990f74e101Schristos 
1000f74e101Schristos struct bfd_auth_header_t {
101c74ad251Schristos     nd_uint8_t auth_type;
102c74ad251Schristos     nd_uint8_t auth_len;
103c74ad251Schristos     nd_uint8_t auth_data;
104c74ad251Schristos     nd_uint8_t dummy; /* minimum 4 bytes */
105dc860a36Sspz };
106dc860a36Sspz 
107dc860a36Sspz enum auth_type {
108dc860a36Sspz     AUTH_PASSWORD = 1,
109dc860a36Sspz     AUTH_MD5      = 2,
110dc860a36Sspz     AUTH_MET_MD5  = 3,
111dc860a36Sspz     AUTH_SHA1     = 4,
112dc860a36Sspz     AUTH_MET_SHA1 = 5
1130f74e101Schristos };
1140f74e101Schristos 
1150f74e101Schristos static const struct tok bfd_v1_authentication_values[] = {
116dc860a36Sspz     { AUTH_PASSWORD, "Simple Password" },
117dc860a36Sspz     { AUTH_MD5,      "Keyed MD5" },
118dc860a36Sspz     { AUTH_MET_MD5,  "Meticulous Keyed MD5" },
119dc860a36Sspz     { AUTH_SHA1,     "Keyed SHA1" },
120dc860a36Sspz     { AUTH_MET_SHA1, "Meticulous Keyed SHA1" },
1210f74e101Schristos     { 0, NULL }
1220f74e101Schristos };
1230f74e101Schristos 
124dc860a36Sspz enum auth_length {
125dc860a36Sspz     AUTH_PASSWORD_FIELD_MIN_LEN = 4,  /* header + password min: 3 + 1 */
126dc860a36Sspz     AUTH_PASSWORD_FIELD_MAX_LEN = 19, /* header + password max: 3 + 16 */
127dc860a36Sspz     AUTH_MD5_FIELD_LEN  = 24,
128dc860a36Sspz     AUTH_MD5_HASH_LEN   = 16,
129dc860a36Sspz     AUTH_SHA1_FIELD_LEN = 28,
130dc860a36Sspz     AUTH_SHA1_HASH_LEN  = 20
131dc860a36Sspz };
132dc860a36Sspz 
1330f74e101Schristos #define BFD_EXTRACT_VERSION(x) (((x)&0xe0)>>5)
1340f74e101Schristos #define BFD_EXTRACT_DIAG(x)     ((x)&0x1f)
1350f74e101Schristos 
1360f74e101Schristos static const struct tok bfd_diag_values[] = {
1370f74e101Schristos     { 0, "No Diagnostic" },
1380f74e101Schristos     { 1, "Control Detection Time Expired" },
1390f74e101Schristos     { 2, "Echo Function Failed" },
1400f74e101Schristos     { 3, "Neighbor Signaled Session Down" },
1410f74e101Schristos     { 4, "Forwarding Plane Reset" },
1420f74e101Schristos     { 5, "Path Down" },
1430f74e101Schristos     { 6, "Concatenated Path Down" },
1440f74e101Schristos     { 7, "Administratively Down" },
1450f74e101Schristos     { 8, "Reverse Concatenated Path Down" },
1460f74e101Schristos     { 0, NULL }
1470f74e101Schristos };
1480f74e101Schristos 
149c74ad251Schristos static const struct tok bfd_port_values[] = {
150c74ad251Schristos     { BFD_CONTROL_PORT,  "Control" },
151c74ad251Schristos     { BFD_MULTIHOP_PORT, "Multihop" },
152c74ad251Schristos     { BFD_LAG_PORT,      "Lag" },
153c74ad251Schristos     { 0, NULL }
154c74ad251Schristos };
155c74ad251Schristos 
156817e9a7eSchristos #define BFD_FLAG_AUTH 0x04
157817e9a7eSchristos 
1580f74e101Schristos static const struct tok bfd_v0_flag_values[] = {
1590f74e101Schristos     { 0x80, "I Hear You" },
1600f74e101Schristos     { 0x40, "Demand" },
1610f74e101Schristos     { 0x20, "Poll" },
1620f74e101Schristos     { 0x10, "Final" },
163817e9a7eSchristos     { 0x08, "Control Plane Independent" },
164817e9a7eSchristos     { BFD_FLAG_AUTH, "Authentication Present" },
1650f74e101Schristos     { 0x02, "Reserved" },
1660f74e101Schristos     { 0x01, "Reserved" },
1670f74e101Schristos     { 0, NULL }
1680f74e101Schristos };
1690f74e101Schristos 
1700f74e101Schristos static const struct tok bfd_v1_flag_values[] = {
1710f74e101Schristos     { 0x20, "Poll" },
1720f74e101Schristos     { 0x10, "Final" },
1730f74e101Schristos     { 0x08, "Control Plane Independent" },
1740f74e101Schristos     { BFD_FLAG_AUTH, "Authentication Present" },
1750f74e101Schristos     { 0x02, "Demand" },
176dc860a36Sspz     { 0x01, "Multipoint" },
1770f74e101Schristos     { 0, NULL }
1780f74e101Schristos };
1790f74e101Schristos 
1800f74e101Schristos static const struct tok bfd_v1_state_values[] = {
1810f74e101Schristos     { 0, "AdminDown" },
1820f74e101Schristos     { 1, "Down" },
1830f74e101Schristos     { 2, "Init" },
1840f74e101Schristos     { 3, "Up" },
1850f74e101Schristos     { 0, NULL }
1860f74e101Schristos };
1870f74e101Schristos 
188c74ad251Schristos static void
189c74ad251Schristos auth_print(netdissect_options *ndo, const u_char *pptr)
190dc860a36Sspz {
191dc860a36Sspz         const struct bfd_auth_header_t *bfd_auth_header;
192c74ad251Schristos         uint8_t auth_type, auth_len;
193dc860a36Sspz         int i;
194dc860a36Sspz 
195c74ad251Schristos         pptr += sizeof (struct bfd_header_t);
196dc860a36Sspz         bfd_auth_header = (const struct bfd_auth_header_t *)pptr;
197c74ad251Schristos         ND_TCHECK_SIZE(bfd_auth_header);
198c74ad251Schristos         auth_type = GET_U_1(bfd_auth_header->auth_type);
199c74ad251Schristos         auth_len = GET_U_1(bfd_auth_header->auth_len);
200c74ad251Schristos         ND_PRINT("\n\tAuthentication: %s (%u), length: %u",
201c74ad251Schristos                  tok2str(bfd_v1_authentication_values,"Unknown",auth_type),
202c74ad251Schristos                  auth_type, auth_len);
203dc860a36Sspz                 pptr += 2;
204c74ad251Schristos                 ND_PRINT("\n\t  Auth Key ID: %u", GET_U_1(pptr));
205dc860a36Sspz 
206c74ad251Schristos         switch(auth_type) {
207dc860a36Sspz             case AUTH_PASSWORD:
208dc860a36Sspz /*
209dc860a36Sspz  *    Simple Password Authentication Section Format
210dc860a36Sspz  *
211dc860a36Sspz  *     0                   1                   2                   3
212dc860a36Sspz  *     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
213dc860a36Sspz  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
214dc860a36Sspz  *    |   Auth Type   |   Auth Len    |  Auth Key ID  |  Password...  |
215dc860a36Sspz  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
216dc860a36Sspz  *    |                              ...                              |
217dc860a36Sspz  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
218dc860a36Sspz  */
219c74ad251Schristos                 if (auth_len < AUTH_PASSWORD_FIELD_MIN_LEN ||
220c74ad251Schristos                     auth_len > AUTH_PASSWORD_FIELD_MAX_LEN) {
221c74ad251Schristos                     ND_PRINT("[invalid length %u]",
222c74ad251Schristos                              auth_len);
223dc860a36Sspz                     break;
224dc860a36Sspz                 }
225dc860a36Sspz                 pptr++;
226c74ad251Schristos                 ND_PRINT(", Password: ");
227dc860a36Sspz                 /* the length is equal to the password length plus three */
228c74ad251Schristos                 (void)nd_printn(ndo, pptr, auth_len - 3, NULL);
229dc860a36Sspz                 break;
230dc860a36Sspz             case AUTH_MD5:
231dc860a36Sspz             case AUTH_MET_MD5:
232dc860a36Sspz /*
233dc860a36Sspz  *    Keyed MD5 and Meticulous Keyed MD5 Authentication Section Format
234dc860a36Sspz  *
235dc860a36Sspz  *     0                   1                   2                   3
236dc860a36Sspz  *     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
237dc860a36Sspz  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
238dc860a36Sspz  *    |   Auth Type   |   Auth Len    |  Auth Key ID  |   Reserved    |
239dc860a36Sspz  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
240dc860a36Sspz  *    |                        Sequence Number                        |
241dc860a36Sspz  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
242dc860a36Sspz  *    |                      Auth Key/Digest...                       |
243dc860a36Sspz  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
244dc860a36Sspz  *    |                              ...                              |
245dc860a36Sspz  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
246dc860a36Sspz  */
247c74ad251Schristos                 if (auth_len != AUTH_MD5_FIELD_LEN) {
248c74ad251Schristos                     ND_PRINT("[invalid length %u]",
249c74ad251Schristos                              auth_len);
250dc860a36Sspz                     break;
251dc860a36Sspz                 }
252dc860a36Sspz                 pptr += 2;
253c74ad251Schristos                 ND_PRINT(", Sequence Number: 0x%08x", GET_BE_U_4(pptr));
254dc860a36Sspz                 pptr += 4;
255c74ad251Schristos                 ND_TCHECK_LEN(pptr, AUTH_MD5_HASH_LEN);
256c74ad251Schristos                 ND_PRINT("\n\t  Digest: ");
257dc860a36Sspz                 for(i = 0; i < AUTH_MD5_HASH_LEN; i++)
258c74ad251Schristos                     ND_PRINT("%02x", GET_U_1(pptr + i));
259dc860a36Sspz                 break;
260dc860a36Sspz             case AUTH_SHA1:
261dc860a36Sspz             case AUTH_MET_SHA1:
262dc860a36Sspz /*
263dc860a36Sspz  *    Keyed SHA1 and Meticulous Keyed SHA1 Authentication Section Format
264dc860a36Sspz  *
265dc860a36Sspz  *     0                   1                   2                   3
266dc860a36Sspz  *     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
267dc860a36Sspz  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
268dc860a36Sspz  *    |   Auth Type   |   Auth Len    |  Auth Key ID  |   Reserved    |
269dc860a36Sspz  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
270dc860a36Sspz  *    |                        Sequence Number                        |
271dc860a36Sspz  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
272dc860a36Sspz  *    |                       Auth Key/Hash...                        |
273dc860a36Sspz  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
274dc860a36Sspz  *    |                              ...                              |
275dc860a36Sspz  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
276dc860a36Sspz  */
277c74ad251Schristos                 if (auth_len != AUTH_SHA1_FIELD_LEN) {
278c74ad251Schristos                     ND_PRINT("[invalid length %u]",
279c74ad251Schristos                              auth_len);
280dc860a36Sspz                     break;
281dc860a36Sspz                 }
282dc860a36Sspz                 pptr += 2;
283c74ad251Schristos                 ND_PRINT(", Sequence Number: 0x%08x", GET_BE_U_4(pptr));
284dc860a36Sspz                 pptr += 4;
285c74ad251Schristos                 ND_TCHECK_LEN(pptr, AUTH_SHA1_HASH_LEN);
286c74ad251Schristos                 ND_PRINT("\n\t  Hash: ");
287dc860a36Sspz                 for(i = 0; i < AUTH_SHA1_HASH_LEN; i++)
288c74ad251Schristos                     ND_PRINT("%02x", GET_U_1(pptr + i));
289dc860a36Sspz                 break;
290dc860a36Sspz         }
291dc860a36Sspz }
292dc860a36Sspz 
2930f74e101Schristos void
294c74ad251Schristos bfd_print(netdissect_options *ndo, const u_char *pptr,
295c74ad251Schristos           u_int len, u_int port)
2960f74e101Schristos {
297c74ad251Schristos 	ndo->ndo_protocol = "bfd";
298c74ad251Schristos         if (port == BFD_CONTROL_PORT ||
299c74ad251Schristos             port == BFD_MULTIHOP_PORT ||
300c74ad251Schristos             port == BFD_LAG_PORT) {
301817e9a7eSchristos             /*
302817e9a7eSchristos              * Control packet.
303817e9a7eSchristos              */
3040f74e101Schristos             const struct bfd_header_t *bfd_header;
305817e9a7eSchristos             uint8_t version_diag;
306b3a00663Schristos             uint8_t version = 0;
307817e9a7eSchristos             uint8_t flags;
3080f74e101Schristos 
3090f74e101Schristos             bfd_header = (const struct bfd_header_t *)pptr;
310c74ad251Schristos             ND_TCHECK_SIZE(bfd_header);
311c74ad251Schristos             version_diag = GET_U_1(bfd_header->version_diag);
312817e9a7eSchristos             version = BFD_EXTRACT_VERSION(version_diag);
313c74ad251Schristos             flags = GET_U_1(bfd_header->flags);
314817e9a7eSchristos 
315817e9a7eSchristos             switch (version) {
3160f74e101Schristos 
3170f74e101Schristos                 /* BFDv0 */
318817e9a7eSchristos             case 0:
319*26ba0b50Schristos                 if (ndo->ndo_vflag < 1) {
320c74ad251Schristos                     ND_PRINT("BFDv0, Control, Flags: [%s], length: %u",
321817e9a7eSchristos                            bittok2str(bfd_v0_flag_values, "none", flags),
322c74ad251Schristos                            len);
3230f74e101Schristos                     return;
3240f74e101Schristos                 }
3250f74e101Schristos 
326c74ad251Schristos                 ND_PRINT("BFDv0, length: %u\n\tControl, Flags: [%s], Diagnostic: %s (0x%02x)",
3270f74e101Schristos                        len,
328817e9a7eSchristos                        bittok2str(bfd_v0_flag_values, "none", flags),
329817e9a7eSchristos                        tok2str(bfd_diag_values,"unknown",BFD_EXTRACT_DIAG(version_diag)),
330c74ad251Schristos                        BFD_EXTRACT_DIAG(version_diag));
3310f74e101Schristos 
332c74ad251Schristos                 ND_PRINT("\n\tDetection Timer Multiplier: %u (%u ms Detection time), BFD Length: %u",
333c74ad251Schristos                        GET_U_1(bfd_header->detect_time_multiplier),
334c74ad251Schristos                        GET_U_1(bfd_header->detect_time_multiplier) * GET_BE_U_4(bfd_header->desired_min_tx_interval)/1000,
335c74ad251Schristos                        GET_U_1(bfd_header->length));
3360f74e101Schristos 
3370f74e101Schristos 
338c74ad251Schristos                 ND_PRINT("\n\tMy Discriminator: 0x%08x",
339c74ad251Schristos                          GET_BE_U_4(bfd_header->my_discriminator));
340c74ad251Schristos                 ND_PRINT(", Your Discriminator: 0x%08x",
341c74ad251Schristos                          GET_BE_U_4(bfd_header->your_discriminator));
342c74ad251Schristos                 ND_PRINT("\n\t  Desired min Tx Interval:    %4u ms",
343c74ad251Schristos                          GET_BE_U_4(bfd_header->desired_min_tx_interval)/1000);
344c74ad251Schristos                 ND_PRINT("\n\t  Required min Rx Interval:   %4u ms",
345c74ad251Schristos                          GET_BE_U_4(bfd_header->required_min_rx_interval)/1000);
346c74ad251Schristos                 ND_PRINT("\n\t  Required min Echo Interval: %4u ms",
347c74ad251Schristos                          GET_BE_U_4(bfd_header->required_min_echo_interval)/1000);
3480f74e101Schristos 
349817e9a7eSchristos                 if (flags & BFD_FLAG_AUTH) {
350c74ad251Schristos                     auth_print(ndo, pptr);
3510f74e101Schristos                 }
3520f74e101Schristos                 break;
3530f74e101Schristos 
3540f74e101Schristos                 /* BFDv1 */
355817e9a7eSchristos             case 1:
356*26ba0b50Schristos                 if (ndo->ndo_vflag < 1) {
357c74ad251Schristos                     ND_PRINT("BFDv1, %s, State %s, Flags: [%s], length: %u",
358c74ad251Schristos                            tok2str(bfd_port_values, "unknown (%u)", port),
359817e9a7eSchristos                            tok2str(bfd_v1_state_values, "unknown (%u)", (flags & 0xc0) >> 6),
360817e9a7eSchristos                            bittok2str(bfd_v1_flag_values, "none", flags & 0x3f),
361c74ad251Schristos                            len);
362817e9a7eSchristos                     return;
363817e9a7eSchristos                 }
364817e9a7eSchristos 
365c74ad251Schristos                 ND_PRINT("BFDv1, length: %u\n\t%s, State %s, Flags: [%s], Diagnostic: %s (0x%02x)",
366817e9a7eSchristos                        len,
367c74ad251Schristos                        tok2str(bfd_port_values, "unknown (%u)", port),
368817e9a7eSchristos                        tok2str(bfd_v1_state_values, "unknown (%u)", (flags & 0xc0) >> 6),
369817e9a7eSchristos                        bittok2str(bfd_v1_flag_values, "none", flags & 0x3f),
370817e9a7eSchristos                        tok2str(bfd_diag_values,"unknown",BFD_EXTRACT_DIAG(version_diag)),
371c74ad251Schristos                        BFD_EXTRACT_DIAG(version_diag));
372817e9a7eSchristos 
373c74ad251Schristos                 ND_PRINT("\n\tDetection Timer Multiplier: %u (%u ms Detection time), BFD Length: %u",
374c74ad251Schristos                        GET_U_1(bfd_header->detect_time_multiplier),
375c74ad251Schristos                        GET_U_1(bfd_header->detect_time_multiplier) * GET_BE_U_4(bfd_header->desired_min_tx_interval)/1000,
376c74ad251Schristos                        GET_U_1(bfd_header->length));
377817e9a7eSchristos 
378817e9a7eSchristos 
379c74ad251Schristos                 ND_PRINT("\n\tMy Discriminator: 0x%08x",
380c74ad251Schristos                          GET_BE_U_4(bfd_header->my_discriminator));
381c74ad251Schristos                 ND_PRINT(", Your Discriminator: 0x%08x",
382c74ad251Schristos                          GET_BE_U_4(bfd_header->your_discriminator));
383c74ad251Schristos                 ND_PRINT("\n\t  Desired min Tx Interval:    %4u ms",
384c74ad251Schristos                          GET_BE_U_4(bfd_header->desired_min_tx_interval)/1000);
385c74ad251Schristos                 ND_PRINT("\n\t  Required min Rx Interval:   %4u ms",
386c74ad251Schristos                          GET_BE_U_4(bfd_header->required_min_rx_interval)/1000);
387c74ad251Schristos                 ND_PRINT("\n\t  Required min Echo Interval: %4u ms",
388c74ad251Schristos                          GET_BE_U_4(bfd_header->required_min_echo_interval)/1000);
389817e9a7eSchristos 
390817e9a7eSchristos                 if (flags & BFD_FLAG_AUTH) {
391c74ad251Schristos                     auth_print(ndo, pptr);
392817e9a7eSchristos                 }
393817e9a7eSchristos                 break;
3940f74e101Schristos 
3950f74e101Schristos             default:
396c74ad251Schristos                 ND_PRINT("BFDv%u, Control, length: %u",
397817e9a7eSchristos                        version,
398c74ad251Schristos                        len);
399b3a00663Schristos                 if (ndo->ndo_vflag >= 1) {
400b3a00663Schristos                     if(!print_unknown_data(ndo, pptr,"\n\t",len))
4010f74e101Schristos                         return;
4020f74e101Schristos                 }
4030f74e101Schristos                 break;
4040f74e101Schristos             }
405817e9a7eSchristos         } else if (port == BFD_ECHO_PORT) {
406817e9a7eSchristos             /*
407817e9a7eSchristos              * Echo packet.
408817e9a7eSchristos              */
409c74ad251Schristos             ND_PRINT("BFD, Echo, length: %u",
410c74ad251Schristos                    len);
411817e9a7eSchristos             if (ndo->ndo_vflag >= 1) {
412817e9a7eSchristos                 if(!print_unknown_data(ndo, pptr,"\n\t",len))
413817e9a7eSchristos                     return;
414817e9a7eSchristos             }
415817e9a7eSchristos         } else {
416817e9a7eSchristos             /*
417817e9a7eSchristos              * Unknown packet type.
418817e9a7eSchristos              */
419c74ad251Schristos             ND_PRINT("BFD, unknown (%u), length: %u",
420817e9a7eSchristos                    port,
421c74ad251Schristos                    len);
422817e9a7eSchristos             if (ndo->ndo_vflag >= 1) {
423817e9a7eSchristos                     if(!print_unknown_data(ndo, pptr,"\n\t",len))
424817e9a7eSchristos                             return;
425817e9a7eSchristos             }
426817e9a7eSchristos         }
4270f74e101Schristos }
428