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 * UNIDIRECTIONAL LINK DETECTION (UDLD) as per 16a5779b6eSRui Paulo * http://www.ietf.org/internet-drafts/draft-foschiano-udld-02.txt 17a5779b6eSRui Paulo * 18a5779b6eSRui Paulo * Original code by Carles Kishimoto <carles.kishimoto@gmail.com> 19a5779b6eSRui Paulo */ 20a5779b6eSRui Paulo 21a5779b6eSRui Paulo #ifdef HAVE_CONFIG_H 22a5779b6eSRui Paulo #include "config.h" 23a5779b6eSRui Paulo #endif 24a5779b6eSRui Paulo 25a5779b6eSRui Paulo #include <tcpdump-stdinc.h> 26a5779b6eSRui Paulo 27a5779b6eSRui Paulo #include <stdio.h> 28a5779b6eSRui Paulo #include <string.h> 29a5779b6eSRui Paulo 30a5779b6eSRui Paulo #include "interface.h" 31a5779b6eSRui Paulo #include "addrtoname.h" 32a5779b6eSRui Paulo #include "extract.h" 33a5779b6eSRui Paulo #include "nlpid.h" 34a5779b6eSRui Paulo 35a5779b6eSRui Paulo #define UDLD_HEADER_LEN 4 36a5779b6eSRui Paulo #define UDLD_DEVICE_ID_TLV 0x0001 37a5779b6eSRui Paulo #define UDLD_PORT_ID_TLV 0x0002 38a5779b6eSRui Paulo #define UDLD_ECHO_TLV 0x0003 39a5779b6eSRui Paulo #define UDLD_MESSAGE_INTERVAL_TLV 0x0004 40a5779b6eSRui Paulo #define UDLD_TIMEOUT_INTERVAL_TLV 0x0005 41a5779b6eSRui Paulo #define UDLD_DEVICE_NAME_TLV 0x0006 42a5779b6eSRui Paulo #define UDLD_SEQ_NUMBER_TLV 0x0007 43a5779b6eSRui Paulo 44a5779b6eSRui Paulo static struct tok udld_tlv_values[] = { 45a5779b6eSRui Paulo { UDLD_DEVICE_ID_TLV, "Device-ID TLV"}, 46a5779b6eSRui Paulo { UDLD_PORT_ID_TLV, "Port-ID TLV"}, 47a5779b6eSRui Paulo { UDLD_ECHO_TLV, "Echo TLV"}, 48a5779b6eSRui Paulo { UDLD_MESSAGE_INTERVAL_TLV, "Message Interval TLV"}, 49a5779b6eSRui Paulo { UDLD_TIMEOUT_INTERVAL_TLV, "Timeout Interval TLV"}, 50a5779b6eSRui Paulo { UDLD_DEVICE_NAME_TLV, "Device Name TLV"}, 51a5779b6eSRui Paulo { UDLD_SEQ_NUMBER_TLV,"Sequence Number TLV"}, 52a5779b6eSRui Paulo { 0, NULL} 53a5779b6eSRui Paulo }; 54a5779b6eSRui Paulo 55a5779b6eSRui Paulo static struct tok udld_code_values[] = { 56a5779b6eSRui Paulo { 0x00, "Reserved"}, 57a5779b6eSRui Paulo { 0x01, "Probe message"}, 58a5779b6eSRui Paulo { 0x02, "Echo message"}, 59a5779b6eSRui Paulo { 0x03, "Flush message"}, 60a5779b6eSRui Paulo { 0, NULL} 61a5779b6eSRui Paulo }; 62a5779b6eSRui Paulo 63a5779b6eSRui Paulo static struct tok udld_flags_values[] = { 64a5779b6eSRui Paulo { 0x00, "RT"}, 65a5779b6eSRui Paulo { 0x01, "RSY"}, 66a5779b6eSRui Paulo { 0, NULL} 67a5779b6eSRui Paulo }; 68a5779b6eSRui Paulo 69a5779b6eSRui Paulo /* 70a5779b6eSRui Paulo * 71a5779b6eSRui Paulo * 0 1 2 3 72a5779b6eSRui 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 73a5779b6eSRui Paulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 74a5779b6eSRui Paulo * | Ver | Opcode | Flags | Checksum | 75a5779b6eSRui Paulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 76a5779b6eSRui Paulo * | List of TLVs (variable length list) | 77a5779b6eSRui Paulo * | ... | 78a5779b6eSRui Paulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 79a5779b6eSRui Paulo * 80a5779b6eSRui Paulo */ 81a5779b6eSRui Paulo 82a5779b6eSRui Paulo #define UDLD_EXTRACT_VERSION(x) (((x)&0xe0)>>5) 83a5779b6eSRui Paulo #define UDLD_EXTRACT_OPCODE(x) ((x)&0x1f) 84a5779b6eSRui Paulo 85a5779b6eSRui Paulo void 86a5779b6eSRui Paulo udld_print (const u_char *pptr, u_int length) 87a5779b6eSRui Paulo { 88a5779b6eSRui Paulo int code, type, len; 89a5779b6eSRui Paulo const u_char *tptr; 90a5779b6eSRui Paulo 91a5779b6eSRui Paulo if (length < UDLD_HEADER_LEN) 92a5779b6eSRui Paulo goto trunc; 93a5779b6eSRui Paulo 94a5779b6eSRui Paulo tptr = pptr; 95a5779b6eSRui Paulo 96a5779b6eSRui Paulo if (!TTEST2(*tptr, UDLD_HEADER_LEN)) 97a5779b6eSRui Paulo goto trunc; 98a5779b6eSRui Paulo 99a5779b6eSRui Paulo code = UDLD_EXTRACT_OPCODE(*tptr); 100a5779b6eSRui Paulo 101a5779b6eSRui Paulo printf("UDLDv%u, Code %s (%x), Flags [%s] (0x%02x), length %u", 102a5779b6eSRui Paulo UDLD_EXTRACT_VERSION(*tptr), 103a5779b6eSRui Paulo tok2str(udld_code_values, "Reserved", code), 104a5779b6eSRui Paulo code, 105a5779b6eSRui Paulo bittok2str(udld_flags_values, "none", *(tptr+1)), 106a5779b6eSRui Paulo *(tptr+1), 107a5779b6eSRui Paulo length); 108a5779b6eSRui Paulo 109a5779b6eSRui Paulo /* 110a5779b6eSRui Paulo * In non-verbose mode, just print version and opcode type 111a5779b6eSRui Paulo */ 112a5779b6eSRui Paulo if (vflag < 1) { 113a5779b6eSRui Paulo return; 114a5779b6eSRui Paulo } 115a5779b6eSRui Paulo 116a5779b6eSRui Paulo printf("\n\tChecksum 0x%04x (unverified)", EXTRACT_16BITS(tptr+2)); 117a5779b6eSRui Paulo 118a5779b6eSRui Paulo tptr += UDLD_HEADER_LEN; 119a5779b6eSRui Paulo 120a5779b6eSRui Paulo while (tptr < (pptr+length)) { 121a5779b6eSRui Paulo 122a5779b6eSRui Paulo if (!TTEST2(*tptr, 4)) 123a5779b6eSRui Paulo goto trunc; 124a5779b6eSRui Paulo 125a5779b6eSRui Paulo type = EXTRACT_16BITS(tptr); 126a5779b6eSRui Paulo len = EXTRACT_16BITS(tptr+2); 127a5779b6eSRui Paulo len -= 4; 128a5779b6eSRui Paulo tptr += 4; 129a5779b6eSRui Paulo 130a5779b6eSRui Paulo /* infinite loop check */ 131a5779b6eSRui Paulo if (type == 0 || len == 0) { 132a5779b6eSRui Paulo return; 133a5779b6eSRui Paulo } 134a5779b6eSRui Paulo 135a5779b6eSRui Paulo printf("\n\t%s (0x%04x) TLV, length %u", 136a5779b6eSRui Paulo tok2str(udld_tlv_values, "Unknown", type), 137a5779b6eSRui Paulo type, len); 138a5779b6eSRui Paulo 139a5779b6eSRui Paulo switch (type) { 140a5779b6eSRui Paulo case UDLD_DEVICE_ID_TLV: 141a5779b6eSRui Paulo case UDLD_PORT_ID_TLV: 142a5779b6eSRui Paulo case UDLD_ECHO_TLV: 143a5779b6eSRui Paulo case UDLD_DEVICE_NAME_TLV: 144a5779b6eSRui Paulo printf(", %s", tptr); 145a5779b6eSRui Paulo break; 146a5779b6eSRui Paulo 147a5779b6eSRui Paulo case UDLD_MESSAGE_INTERVAL_TLV: 148a5779b6eSRui Paulo case UDLD_TIMEOUT_INTERVAL_TLV: 149a5779b6eSRui Paulo printf(", %us", (*tptr)); 150a5779b6eSRui Paulo break; 151a5779b6eSRui Paulo 152a5779b6eSRui Paulo case UDLD_SEQ_NUMBER_TLV: 153a5779b6eSRui Paulo printf(", %u", EXTRACT_32BITS(tptr)); 154a5779b6eSRui Paulo break; 155a5779b6eSRui Paulo 156a5779b6eSRui Paulo default: 157a5779b6eSRui Paulo break; 158a5779b6eSRui Paulo } 159a5779b6eSRui Paulo tptr += len; 160a5779b6eSRui Paulo } 161a5779b6eSRui Paulo 162a5779b6eSRui Paulo return; 163a5779b6eSRui Paulo 164a5779b6eSRui Paulo trunc: 165a5779b6eSRui Paulo printf("[|udld]"); 166a5779b6eSRui Paulo } 167a5779b6eSRui Paulo 168a5779b6eSRui Paulo /* 169a5779b6eSRui Paulo * Local Variables: 170a5779b6eSRui Paulo * c-style: whitesmith 171a5779b6eSRui Paulo * c-basic-offset: 4 172a5779b6eSRui Paulo * End: 173a5779b6eSRui Paulo */ 174