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