The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997 |
| 3 | * The Regents of the University of California. All rights reserved. |
| 4 | * |
| 5 | * Redistribution and use in source and binary forms, with or without |
| 6 | * modification, are permitted provided that: (1) source code distributions |
| 7 | * retain the above copyright notice and this paragraph in its entirety, (2) |
| 8 | * distributions including binary code include the above copyright notice and |
| 9 | * this paragraph in its entirety in the documentation or other materials |
| 10 | * provided with the distribution, and (3) all advertising materials mentioning |
| 11 | * features or use of this software display the following acknowledgement: |
| 12 | * ``This product includes software developed by the University of California, |
| 13 | * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of |
| 14 | * the University nor the names of its contributors may be used to endorse |
| 15 | * or promote products derived from this software without specific prior |
| 16 | * written permission. |
| 17 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED |
| 18 | * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF |
| 19 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
| 20 | * |
| 21 | * Code by Gert Doering, SpaceNet GmbH, gert@space.net |
| 22 | * |
| 23 | * Reference documentation: |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 24 | * https://web.archive.org/web/20000914194913/http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.pdf |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 25 | */ |
| 26 | |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 27 | /* \summary: Cisco Discovery Protocol (CDP) printer */ |
| 28 | |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 29 | #ifdef HAVE_CONFIG_H |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 30 | #include <config.h> |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 31 | #endif |
| 32 | |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 33 | #include "netdissect-stdinc.h" |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 34 | |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 35 | #include <string.h> |
| 36 | |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 37 | #define ND_LONGJMP_FROM_TCHECK |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 38 | #include "netdissect.h" |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 39 | #include "addrtoname.h" |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 40 | #include "extract.h" |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 41 | #include "nlpid.h" |
| 42 | |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 43 | |
| 44 | #define CDP_HEADER_LEN 4 |
| 45 | #define CDP_HEADER_VERSION_OFFSET 0 |
| 46 | #define CDP_HEADER_TTL_OFFSET 1 |
| 47 | #define CDP_HEADER_CHECKSUM_OFFSET 2 |
| 48 | |
| 49 | #define CDP_TLV_HEADER_LEN 4 |
| 50 | #define CDP_TLV_TYPE_OFFSET 0 |
| 51 | #define CDP_TLV_LEN_OFFSET 2 |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 52 | |
JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 53 | static const struct tok cdp_capability_values[] = { |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 54 | { 0x01, "Router" }, |
| 55 | { 0x02, "Transparent Bridge" }, |
| 56 | { 0x04, "Source Route Bridge" }, |
| 57 | { 0x08, "L2 Switch" }, |
| 58 | { 0x10, "L3 capable" }, |
| 59 | { 0x20, "IGMP snooping" }, |
| 60 | { 0x40, "L1 capable" }, |
| 61 | { 0, NULL } |
| 62 | }; |
| 63 | |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 64 | static void cdp_print_addr(netdissect_options *, const u_char *, u_int); |
| 65 | static void cdp_print_prefixes(netdissect_options *, const u_char *, u_int); |
| 66 | |
| 67 | static void |
| 68 | cdp_print_string(netdissect_options *ndo, |
| 69 | const u_char *cp, const u_int len) |
| 70 | { |
| 71 | ND_PRINT("'"); |
| 72 | (void)nd_printn(ndo, cp, len, NULL); |
| 73 | ND_PRINT("'"); |
| 74 | } |
| 75 | |
| 76 | static void |
| 77 | cdp_print_power(netdissect_options *ndo, |
| 78 | const u_char *cp, const u_int len) |
| 79 | { |
| 80 | u_int val = 0; |
| 81 | |
| 82 | switch (len) { |
| 83 | case 1: |
| 84 | val = GET_U_1(cp); |
| 85 | break; |
| 86 | case 2: |
| 87 | val = GET_BE_U_2(cp); |
| 88 | break; |
| 89 | case 3: |
| 90 | val = GET_BE_U_3(cp); |
| 91 | break; |
| 92 | } |
| 93 | ND_PRINT("%1.2fW", val / 1000.0); |
| 94 | } |
| 95 | |
| 96 | static void |
| 97 | cdp_print_capability(netdissect_options *ndo, |
| 98 | const u_char *cp, const u_int len _U_) |
| 99 | { |
| 100 | uint32_t val = GET_BE_U_4(cp); |
| 101 | |
| 102 | ND_PRINT("(0x%08x): %s", val, |
| 103 | bittok2str(cdp_capability_values, "none", val)); |
| 104 | } |
| 105 | |
| 106 | /* Rework the version string to get a nice indentation. */ |
| 107 | static void |
| 108 | cdp_print_version(netdissect_options *ndo, |
| 109 | const u_char *cp, const u_int len) |
| 110 | { |
| 111 | unsigned i; |
| 112 | |
| 113 | ND_PRINT("\n\t "); |
| 114 | for (i = 0; i < len; i++) { |
| 115 | u_char c = GET_U_1(cp + i); |
| 116 | |
| 117 | if (c == '\n') |
| 118 | ND_PRINT("\n\t "); |
| 119 | else |
| 120 | fn_print_char(ndo, c); |
| 121 | } |
| 122 | } |
| 123 | |
| 124 | static void |
| 125 | cdp_print_uint16(netdissect_options *ndo, |
| 126 | const u_char *cp, const u_int len _U_) |
| 127 | { |
| 128 | ND_PRINT("%u", GET_BE_U_2(cp)); |
| 129 | } |
| 130 | |
| 131 | static void |
| 132 | cdp_print_duplex(netdissect_options *ndo, |
| 133 | const u_char *cp, const u_int len _U_) |
| 134 | { |
| 135 | ND_PRINT("%s", GET_U_1(cp) ? "full": "half"); |
| 136 | } |
| 137 | |
| 138 | /* https://www.cisco.com/c/en/us/td/docs/voice_ip_comm/cata/186/2_12_m/english/release/notes/186rn21m.html |
| 139 | * plus more details from other sources |
| 140 | * |
| 141 | * There are apparently versions of the request with both |
| 142 | * 2 bytes and 3 bytes of value. The 3 bytes of value |
| 143 | * appear to be a 1-byte application type followed by a |
| 144 | * 2-byte VLAN ID; the 2 bytes of value are unknown |
| 145 | * (they're 0x20 0x00 in some captures I've seen; that |
| 146 | * is not a valid VLAN ID, as VLAN IDs are 12 bits). |
| 147 | * |
| 148 | * The replies all appear to be 3 bytes long. |
| 149 | */ |
| 150 | static void |
| 151 | cdp_print_ata186(netdissect_options *ndo, |
| 152 | const u_char *cp, const u_int len) |
| 153 | { |
| 154 | if (len == 2) |
| 155 | ND_PRINT("unknown 0x%04x", GET_BE_U_2(cp)); |
| 156 | else |
| 157 | ND_PRINT("app %u, vlan %u", GET_U_1(cp), GET_BE_U_2(cp + 1)); |
| 158 | } |
| 159 | |
| 160 | static void |
| 161 | cdp_print_mtu(netdissect_options *ndo, |
| 162 | const u_char *cp, const u_int len _U_) |
| 163 | { |
| 164 | ND_PRINT("%u bytes", GET_BE_U_4(cp)); |
| 165 | } |
| 166 | |
| 167 | static void |
| 168 | cdp_print_uint8x(netdissect_options *ndo, |
| 169 | const u_char *cp, const u_int len _U_) |
| 170 | { |
| 171 | ND_PRINT("0x%02x", GET_U_1(cp)); |
| 172 | } |
| 173 | |
| 174 | static void |
| 175 | cdp_print_phys_loc(netdissect_options *ndo, |
| 176 | const u_char *cp, const u_int len) |
| 177 | { |
| 178 | ND_PRINT("0x%02x", GET_U_1(cp)); |
| 179 | if (len > 1) { |
| 180 | ND_PRINT("/"); |
| 181 | (void)nd_printn(ndo, cp + 1, len - 1, NULL); |
| 182 | } |
| 183 | } |
| 184 | |
| 185 | struct cdp_tlvinfo { |
| 186 | const char *name; |
| 187 | void (*printer)(netdissect_options *ndo, const u_char *, u_int); |
| 188 | int min_len, max_len; |
| 189 | }; |
| 190 | |
| 191 | #define T_DEV_ID 0x01 |
| 192 | #define T_MAX 0x17 |
| 193 | static const struct cdp_tlvinfo cdptlvs[T_MAX + 1] = { |
| 194 | /* 0x00 */ |
| 195 | [ T_DEV_ID ] = { "Device-ID", cdp_print_string, -1, -1 }, |
| 196 | [ 0x02 ] = { "Address", cdp_print_addr, -1, -1 }, |
| 197 | [ 0x03 ] = { "Port-ID", cdp_print_string, -1, -1 }, |
| 198 | [ 0x04 ] = { "Capability", cdp_print_capability, 4, 4 }, |
| 199 | [ 0x05 ] = { "Version String", cdp_print_version, -1, -1 }, |
| 200 | [ 0x06 ] = { "Platform", cdp_print_string, -1, -1 }, |
| 201 | [ 0x07 ] = { "Prefixes", cdp_print_prefixes, -1, -1 }, |
| 202 | /* not documented */ |
| 203 | [ 0x08 ] = { "Protocol-Hello option", NULL, -1, -1 }, |
| 204 | /* CDPv2 */ |
| 205 | [ 0x09 ] = { "VTP Management Domain", cdp_print_string, -1, -1 }, |
| 206 | /* CDPv2 */ |
| 207 | [ 0x0a ] = { "Native VLAN ID", cdp_print_uint16, 2, 2 }, |
| 208 | /* CDPv2 */ |
| 209 | [ 0x0b ] = { "Duplex", cdp_print_duplex, 1, 1 }, |
| 210 | /* 0x0c */ |
| 211 | /* 0x0d */ |
| 212 | /* incomplete doc. */ |
| 213 | [ 0x0e ] = { "ATA-186 VoIP VLAN assignment", cdp_print_ata186, 3, 3 }, |
| 214 | /* incomplete doc. */ |
| 215 | [ 0x0f ] = { "ATA-186 VoIP VLAN request", cdp_print_ata186, 2, 3 }, |
| 216 | /* not documented */ |
| 217 | [ 0x10 ] = { "power consumption", cdp_print_power, 1, 3 }, |
| 218 | /* not documented */ |
| 219 | [ 0x11 ] = { "MTU", cdp_print_mtu, 4, 4 }, |
| 220 | /* not documented */ |
| 221 | [ 0x12 ] = { "AVVID trust bitmap", cdp_print_uint8x, 1, 1 }, |
| 222 | /* not documented */ |
| 223 | [ 0x13 ] = { "AVVID untrusted ports CoS", cdp_print_uint8x, 1, 1 }, |
| 224 | /* not documented */ |
| 225 | [ 0x14 ] = { "System Name", cdp_print_string, -1, -1 }, |
| 226 | /* not documented */ |
| 227 | [ 0x15 ] = { "System Object ID (not decoded)", NULL, -1, -1 }, |
| 228 | [ 0x16 ] = { "Management Addresses", cdp_print_addr, 4, -1 }, |
| 229 | /* not documented */ |
| 230 | [ 0x17 ] = { "Physical Location", cdp_print_phys_loc, 1, -1 }, |
| 231 | }; |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 232 | |
| 233 | void |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 234 | cdp_print(netdissect_options *ndo, |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 235 | const u_char *tptr, u_int length) |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 236 | { |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 237 | u_int orig_length = length; |
| 238 | uint16_t checksum; |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 239 | |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 240 | ndo->ndo_protocol = "cdp"; |
| 241 | |
| 242 | if (length < CDP_HEADER_LEN) { |
| 243 | ND_PRINT(" (packet length %u < %u)", length, CDP_HEADER_LEN); |
| 244 | goto invalid; |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 245 | } |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 246 | ND_PRINT("CDPv%u, ttl: %us", |
| 247 | GET_U_1(tptr + CDP_HEADER_VERSION_OFFSET), |
| 248 | GET_U_1(tptr + CDP_HEADER_TTL_OFFSET)); |
| 249 | checksum = GET_BE_U_2(tptr + CDP_HEADER_CHECKSUM_OFFSET); |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 250 | if (ndo->ndo_vflag) |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 251 | ND_PRINT(", checksum: 0x%04x (unverified), length %u", |
| 252 | checksum, orig_length); |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 253 | tptr += CDP_HEADER_LEN; |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 254 | length -= CDP_HEADER_LEN; |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 255 | |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 256 | while (length) { |
| 257 | u_int type, len; |
| 258 | const struct cdp_tlvinfo *info; |
| 259 | const char *name; |
| 260 | u_char covered = 0; |
| 261 | |
| 262 | if (length < CDP_TLV_HEADER_LEN) { |
| 263 | ND_PRINT(" (remaining packet length %u < %u)", |
| 264 | length, CDP_TLV_HEADER_LEN); |
| 265 | goto invalid; |
| 266 | } |
| 267 | type = GET_BE_U_2(tptr + CDP_TLV_TYPE_OFFSET); |
| 268 | len = GET_BE_U_2(tptr + CDP_TLV_LEN_OFFSET); /* object length includes the 4 bytes header length */ |
| 269 | info = type <= T_MAX ? &cdptlvs[type] : NULL; |
| 270 | name = (info && info->name) ? info->name : "unknown field type"; |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 271 | if (len < CDP_TLV_HEADER_LEN) { |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 272 | if (ndo->ndo_vflag) |
| 273 | ND_PRINT("\n\t%s (0x%02x), TLV length: %u byte%s (too short)", |
| 274 | name, type, len, PLURAL_SUFFIX(len)); |
| 275 | else |
| 276 | ND_PRINT(", %s TLV length %u too short", |
| 277 | name, len); |
| 278 | goto invalid; |
| 279 | } |
| 280 | if (len > length) { |
| 281 | ND_PRINT(" (TLV length %u > %u)", len, length); |
| 282 | goto invalid; |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 283 | } |
| 284 | tptr += CDP_TLV_HEADER_LEN; |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 285 | length -= CDP_TLV_HEADER_LEN; |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 286 | len -= CDP_TLV_HEADER_LEN; |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 287 | |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 288 | /* In non-verbose mode just print Device-ID. */ |
| 289 | if (!ndo->ndo_vflag && type == T_DEV_ID) |
| 290 | ND_PRINT(", Device-ID "); |
| 291 | else if (ndo->ndo_vflag) |
| 292 | ND_PRINT("\n\t%s (0x%02x), value length: %u byte%s: ", |
| 293 | name, type, len, PLURAL_SUFFIX(len)); |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 294 | |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 295 | if (info) { |
| 296 | if ((info->min_len > 0 && len < (unsigned)info->min_len) || |
| 297 | (info->max_len > 0 && len > (unsigned)info->max_len)) |
| 298 | ND_PRINT(" (malformed TLV)"); |
| 299 | else if (ndo->ndo_vflag || type == T_DEV_ID) { |
| 300 | if (info->printer) |
| 301 | info->printer(ndo, tptr, len); |
| 302 | else |
| 303 | ND_TCHECK_LEN(tptr, len); |
| 304 | /* |
| 305 | * When the type is defined without a printer, |
| 306 | * do not print the hex dump. |
| 307 | */ |
| 308 | covered = 1; |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 309 | } |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 310 | } |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 311 | |
| 312 | if (!covered) { |
| 313 | ND_TCHECK_LEN(tptr, len); |
| 314 | print_unknown_data(ndo, tptr, "\n\t ", len); |
| 315 | } |
| 316 | tptr += len; |
| 317 | length -= len; |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 318 | } |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 319 | if (ndo->ndo_vflag < 1) |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 320 | ND_PRINT(", length %u", orig_length); |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 321 | |
| 322 | return; |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 323 | invalid: |
| 324 | nd_print_invalid(ndo); |
| 325 | ND_TCHECK_LEN(tptr, length); |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 326 | } |
| 327 | |
| 328 | /* |
| 329 | * Protocol type values. |
| 330 | * |
| 331 | * PT_NLPID means that the protocol type field contains an OSI NLPID. |
| 332 | * |
| 333 | * PT_IEEE_802_2 means that the protocol type field contains an IEEE 802.2 |
| 334 | * LLC header that specifies that the payload is for that protocol. |
| 335 | */ |
| 336 | #define PT_NLPID 1 /* OSI NLPID */ |
| 337 | #define PT_IEEE_802_2 2 /* IEEE 802.2 LLC header */ |
| 338 | |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 339 | static void |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 340 | cdp_print_addr(netdissect_options *ndo, |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 341 | const u_char * p, u_int l) |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 342 | { |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 343 | u_int num; |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 344 | static const u_char prot_ipv6[] = { |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 345 | 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x86, 0xdd |
| 346 | }; |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 347 | |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 348 | if (l < 4) { |
| 349 | ND_PRINT(" (not enough space for num)"); |
| 350 | goto invalid; |
| 351 | } |
| 352 | num = GET_BE_U_4(p); |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 353 | p += 4; |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 354 | l -= 4; |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 355 | |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 356 | while (num) { |
| 357 | u_int pt, pl, al; |
| 358 | |
| 359 | if (l < 2) { |
| 360 | ND_PRINT(" (not enough space for PT+PL)"); |
| 361 | goto invalid; |
| 362 | } |
| 363 | pt = GET_U_1(p); /* type of "protocol" field */ |
| 364 | pl = GET_U_1(p + 1); /* length of "protocol" field */ |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 365 | p += 2; |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 366 | l -= 2; |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 367 | |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 368 | if (l < pl + 2) { |
| 369 | ND_PRINT(" (not enough space for P+AL)"); |
| 370 | goto invalid; |
| 371 | } |
| 372 | /* Skip the protocol for now. */ |
| 373 | al = GET_BE_U_2(p + pl); /* address length */ |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 374 | |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 375 | if (pt == PT_NLPID && pl == 1 && GET_U_1(p) == NLPID_IP && |
| 376 | al == 4) { |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 377 | /* |
| 378 | * IPv4: protocol type = NLPID, protocol length = 1 |
| 379 | * (1-byte NLPID), protocol = 0xcc (NLPID for IPv4), |
| 380 | * address length = 4 |
| 381 | */ |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 382 | p += pl + 2; |
| 383 | l -= pl + 2; |
| 384 | /* p is just beyond al now. */ |
| 385 | if (l < al) { |
| 386 | ND_PRINT(" (not enough space for A)"); |
| 387 | goto invalid; |
| 388 | } |
| 389 | ND_PRINT("IPv4 (%u) %s", num, GET_IPADDR_STRING(p)); |
| 390 | p += al; |
| 391 | l -= al; |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 392 | } |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 393 | else if (pt == PT_IEEE_802_2 && pl == 8 && |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 394 | memcmp(p, prot_ipv6, 8) == 0 && al == 16) { |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 395 | /* |
| 396 | * IPv6: protocol type = IEEE 802.2 header, |
| 397 | * protocol length = 8 (size of LLC+SNAP header), |
| 398 | * protocol = LLC+SNAP header with the IPv6 |
| 399 | * Ethertype, address length = 16 |
| 400 | */ |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 401 | p += pl + 2; |
| 402 | l -= pl + 2; |
| 403 | /* p is just beyond al now. */ |
| 404 | if (l < al) { |
| 405 | ND_PRINT(" (not enough space for A)"); |
| 406 | goto invalid; |
| 407 | } |
| 408 | ND_PRINT("IPv6 (%u) %s", num, GET_IP6ADDR_STRING(p)); |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 409 | p += al; |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 410 | l -= al; |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 411 | } |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 412 | else { |
| 413 | /* |
| 414 | * Generic case: just print raw data |
| 415 | */ |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 416 | ND_PRINT("pt=0x%02x, pl=%u, pb=", pt, pl); |
| 417 | while (pl != 0) { |
| 418 | ND_PRINT(" %02x", GET_U_1(p)); |
| 419 | p++; |
| 420 | l--; |
| 421 | pl--; |
| 422 | } |
| 423 | ND_PRINT(", al=%u, a=", al); |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 424 | p += 2; |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 425 | l -= 2; |
| 426 | /* p is just beyond al now. */ |
| 427 | if (l < al) { |
| 428 | ND_PRINT(" (not enough space for A)"); |
| 429 | goto invalid; |
| 430 | } |
| 431 | while (al != 0) { |
| 432 | ND_PRINT(" %02x", GET_U_1(p)); |
| 433 | p++; |
| 434 | l--; |
| 435 | al--; |
| 436 | } |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 437 | } |
| 438 | num--; |
| 439 | if (num) |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 440 | ND_PRINT(" "); |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 441 | } |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 442 | if (l) |
| 443 | ND_PRINT(" (%u bytes of stray data)", l); |
| 444 | return; |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 445 | |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 446 | invalid: |
| 447 | ND_TCHECK_LEN(p, l); |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 448 | } |
| 449 | |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 450 | static void |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 451 | cdp_print_prefixes(netdissect_options *ndo, |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 452 | const u_char * p, u_int l) |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 453 | { |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 454 | if (l % 5) { |
| 455 | ND_PRINT(" [length %u is not a multiple of 5]", l); |
| 456 | goto invalid; |
| 457 | } |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 458 | |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 459 | ND_PRINT(" IPv4 Prefixes (%u):", l / 5); |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 460 | |
| 461 | while (l > 0) { |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 462 | ND_PRINT(" %u.%u.%u.%u/%u", |
| 463 | GET_U_1(p), GET_U_1(p + 1), GET_U_1(p + 2), |
| 464 | GET_U_1(p + 3), GET_U_1(p + 4)); |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 465 | l -= 5; |
| 466 | p += 5; |
| 467 | } |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 468 | return; |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 469 | |
Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 470 | invalid: |
| 471 | ND_TCHECK_LEN(p, l); |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 472 | } |