decode.c (61690B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * Routines to Decode ethernet/ip packets and print various amounts of 8 * information. 9 */ 10 11 #ifndef GHS 12 #ifndef NO_SAL_APPL 13 #ifndef __KERNEL__ 14 15 #ifdef linux 16 #undef _POSIX_SOURCE 17 #undef _POSIX_C_SOURCE 18 #undef _GNU_SOURCE 19 #undef _SVID_SOURCE 20 #define _BSD_SOURCE 21 #endif 22 23 #include <sal/types.h> 24 #include <sys/socket.h> 25 #include <sys/types.h> 26 #include <net/if.h> 27 #include <netinet/in.h> 28 #include <netinet/tcp.h> 29 30 #include <appl/diag/system.h> 31 #include <appl/diag/decode.h> 32 33 #if defined(BCM_ESW_SUPPORT) 34 #include <soc/dcbformats.h> 35 #include <bcm_int/esw/oam.h> 36 #endif 37 38 /* 39 * Macro: HDR_DECL 40 * Purpose: Used for declaration of a local header pointer. 41 * Parameters: t - type of header 42 * h - pointer variable to declare 43 * p - pointer to header in packet. 44 * 45 * 46 * This macro is used as follows: 47 * 48 * HDR_DECL(struct foo, local_variable, parameter_pointer) 49 * 50 * Where a variable "struct foo *local_variable" is declared locally, 51 * and if p is not 4-byte aligned, a local variable of type "struct foo" 52 * is also declared, and "local_variable" points to it, otherwise, 53 * local_variable will point directly into the packet. If a local 54 * variable is used to hold the header, the passed in header is 55 * copied into it. 56 */ 57 #define HDR_DECL(_t, _h, _p) \ 58 _t _h##_aligned_structure; \ 59 _t *_h = (PTR_TO_INT(_p) & 0x3) ? \ 60 (_t *)memcpy(&_h##_aligned_structure, _p, sizeof(_t)) \ 61 : (_t *)(_p) 62 63 #define DECODE_LIST(_l) (_l) , COUNTOF(_l) 64 65 #define DECODE_LIST_NULL NULL, 0 66 67 typedef struct decode_list_s { 68 uint32 dl_low; /* Low compare value*/ 69 uint32 dl_high; /* Hi compare value */ 70 struct decode_s *dl_decode; /* Next layer decode */ 71 char *dl_string; /* Desciption */ 72 } decode_list_t; 73 74 typedef struct decode_s { 75 char *d_name; /* Decode "name" ie, IP/Ethernet */ 76 char *(*d_df)(const char *, char *, void *, 77 int, decode_list_t *, void *); 78 int (*d_compare)(decode_list_t *, void *); 79 int (*d_length)(decode_list_t *, void *); 80 decode_list_t *d_dl; /* Decode list this type */ 81 int d_dl_cnt; /* # entires in decode list */ 82 } decode_t; 83 84 /************************************************************************ 85 ************************************************************************ 86 ************************************************************************ 87 * * 88 * Forward declare decode tables * 89 */ 90 91 static decode_t d_ether_table; /* Ethernet Decode */ 92 static decode_t d_arp_table; /* ARP Decode */ 93 static decode_t d_ip_table; /* IP Decode */ 94 static decode_t d_tcp_table; /* TCP Decode */ 95 static decode_t d_icmp_table; /* ICMP Decode */ 96 static decode_t d_oam_table; /* OAM Decode */ 97 98 #if defined(BCM_ESW_SUPPORT) 99 static decode_t d_oam_lmm_table; /* OAM LM Decode */ 100 static decode_t d_oam_lmr_table; /* OAM LM Decode */ 101 static decode_t d_oam_dmm_table; /* OAM DM Decode */ 102 static decode_t d_oam_dmr_table; /* OAM DM Decode */ 103 #endif 104 105 static char * 106 d_skip(char *d) 107 /* 108 * Function: d_skip 109 * Purpose: Skip passed all chars in current string. 110 * Parameters: d - pointer to string to skip 111 * Returns: Pointer to \0 in d. 112 */ 113 { 114 while (*d++) 115 ; 116 return(d - 1); 117 } 118 119 static char * 120 d_strcat(char *d, char *s) 121 /* 122 * Function: d_strcat 123 * Purpose: Our local strcat that returns a pointer to the end of 124 * the destination string. 125 * Parameters: d - destination 126 * s - source 127 * Returns: Pointer to the end of the destination string (ie. a 128 * pointer to the '\0' 129 */ 130 { 131 d = d_skip(d); 132 while ('\0' != (*d++ = *s++)) 133 ; 134 return(d - 1); 135 } 136 137 static char * 138 d_strnl(char *s, const char *pfx) 139 /* 140 * Function: d_strnl 141 * Purpose: Add a newline to the end of a buffer. 142 * Parameters: s - pointer to string formatting into. 143 * pfx - prefix for output. 144 * Returns: Pointer to end of string. 145 */ 146 { 147 s = d_skip(s); 148 s = d_strcat(s, "\n"); 149 s = d_strcat(s, (char *)pfx); 150 return(s); 151 } 152 153 static char * 154 d_vformat_bytes(char *s, unsigned char *d, int l, int brk, char sep) 155 /* 156 * Function: p_vformat_bytes 157 * Pupose: Format raw hex output. 158 * Parameters: s - pointer to string to format into. 159 * d - pointer to bytes to format 160 * l - length (# bytes to format) 161 * brk - # bytes to format before "sep" character inserted. 162 * sep - character used to break up stream of bytes. 163 * Returns: Pointer to end of string ('\0') 164 */ 165 { 166 int i; 167 168 s = d_skip(s); 169 for (i = 0; i < l; i++, d++) { 170 *s++ = (char)i2xdigit(*d >> 4); 171 *s++ = (char)i2xdigit(*d & 0xf); 172 if (((i % brk) == (brk - 1)) && (i != (l-1))) { 173 *s++ = sep; 174 } 175 } 176 *s = '\0'; 177 return(s); 178 } 179 180 static char * 181 d_strcat_dec_cvt(char *s, unsigned int n) 182 /* 183 * Function: d_strcat_dec_cvt 184 * Purpose: Concat a decimal number into a string, but does not 185 * null terminate. 186 * Parameters: s - pointer to string to concat into. 187 * n - number to format. 188 * Returns: Pointer to char after end of string. 189 */ 190 { 191 if (10 > n) { /* Bottom out condition */ 192 *s++ = (char)(n + '0'); 193 } else { 194 s = d_strcat_dec_cvt(s, n / 10); 195 *s++ = (char)((n % 10) + '0'); 196 } 197 return(s); 198 } 199 200 static char * 201 d_strcat_dec(char *s, char *b, unsigned int n, char *a) 202 /* 203 * Function: d_strcat_dec 204 * Purpose: Concat a decimal number ito a string. 205 * Parameters: s - pointer to string to concat into. 206 * b - string to prepend to number (Before) 207 * n - number to format. 208 * a - string to concat after number (After) 209 * Returns: Pointer to end of string ('\0') 210 */ 211 { 212 s = d_skip(s); 213 if (b) { 214 s = d_strcat(s, b); 215 } 216 if (0 == n) { 217 *s++ = '0'; 218 } else { 219 s = d_strcat_dec_cvt(s, n); 220 } 221 *s = '\0'; 222 if (a) { 223 s = d_strcat(s, a); 224 } 225 return(s); 226 } 227 228 static char * 229 d_vformat_dec(char *s, unsigned char *d, int l, int brk, char sep) 230 /* 231 * Function: p_vformat_dev 232 * Pupose: Format raw hex output. 233 * Parameters: s - pointer to string to format into. 234 * d - pointer to bytes to format 235 * l - length (# bytes to format) 236 * brk - # bytes to format before "sep" character inserted. 237 * sep - character used to break up stream of bytes. 238 * Returns: Pointer to end of string ('\0') 239 */ 240 { 241 int i; 242 243 for (i = 0; i < l; i++, d++) { 244 s = d_strcat_dec(s, NULL, (uint32)*d, NULL); 245 if (((i % brk) == (brk -1)) && (i != (l-1))) { 246 *s++ = sep; 247 *s = '\0'; /* Needed for strcat */ 248 } 249 } 250 *s = '\0'; 251 return(s); 252 } 253 254 static char * 255 d_vformat_hex(char *s, unsigned int x, int digits, int pfx) 256 /* 257 * Function: d_vformat_hex 258 * Purpose: Format a number of hex digits into a string. 259 * Parameters: s - pointer to string to format into. 260 * x - number to format 261 * digits - number of hex digits, low order nibbles 262 * used to form number. 263 * Returns: 264 */ 265 { 266 if (pfx) { 267 *s++ = '0'; 268 *s++ = 'x'; 269 } 270 while (digits--) { 271 *s++ = i2xdigit(x >> (digits * 4)); 272 } 273 *s = '\0'; 274 return(s); 275 } 276 277 static decode_list_t * 278 d_find_decode(decode_t *decode, void *hdr, int l) 279 /* 280 * Function: d_find_decode 281 * Purpose: Locate an entry in a decode list corresponding to the 282 * current header. 283 * Parameters: decode - pointer to decode list. 284 * hdr - pointer to current header. 285 * l - length of current header. 286 * Returns: Pointer to decode list entry or NULL if not found. 287 */ 288 { 289 int lo, hi, cur; /* Binary search values */ 290 decode_list_t *rv = NULL; 291 292 COMPILER_REFERENCE(l); 293 294 /* Perform simple binary search on packet */ 295 296 if (decode->d_dl) { /* If no list, give up now */ 297 lo = 0; 298 hi = decode->d_dl_cnt - 1; 299 300 do { 301 cur = lo + (hi - lo) / 2; 302 switch(decode->d_compare(&decode->d_dl[cur], hdr)) { 303 case -1: /* low */ 304 hi = cur - 1; 305 break; 306 case 0: /* found */ 307 rv = &decode->d_dl[cur]; 308 break; 309 case 1: /* high */ 310 lo = cur + 1; 311 break; 312 } 313 } while (!rv && ((hi - lo) > 0)); 314 315 /* Check if we have just landed on it */ 316 if (!rv && (0 == decode->d_compare(&decode->d_dl[lo], hdr))) { 317 rv = &decode->d_dl[lo]; 318 } 319 } 320 return(rv); 321 } 322 323 static char * 324 d_decode(const char *pfx, char *s, decode_t *decode, void *hdr, int l, void *pd) 325 /* 326 * Function: d_decode 327 * Purpose: Decode multiple levels of a packet. 328 * Parameters: pfx - prefix string attached to each line. 329 * s - pointer to string to format into. 330 * decode - pointer to decode entry to start from 331 * hdr - pointer to shere to start i packet. 332 * l - # bytes i packet valid starting at hdr. 333 * Returns: Pointer to end of string. 334 */ 335 { 336 decode_list_t *dl; 337 int hl; /* header length */ 338 339 if (decode->d_name) { 340 s = d_strnl(s, pfx); 341 s = d_strcat(s, " "); 342 s = d_strcat(s, decode->d_name); 343 s = d_strcat(s, ": "); 344 } 345 dl = d_find_decode(decode, hdr, l); /* Find this level decode */ 346 if (decode->d_df) { 347 /* 348 * May or may not be further decode function at a given 349 * level. 350 */ 351 s = decode->d_df(pfx, s, hdr, l, dl, pd); 352 } 353 if (dl) { 354 hl = decode->d_length(dl, hdr); 355 hdr = (void *)((char *)hdr + hl); 356 l -= hl; /* Remove our header */ 357 if (dl->dl_decode) { /* Next level if there */ 358 s = d_decode(pfx, s, dl->dl_decode, hdr, l, pd); 359 } 360 } else { /* end of the line */ 361 if (!decode->d_df) { 362 s = d_strcat(s, ": "); 363 s = d_vformat_bytes(s, hdr, 20, 1, ' '); 364 } 365 } 366 return(s); 367 } 368 369 /************************************************************************ 370 ************************************************************************ 371 ************************************************************************ 372 * * 373 * Ethernet * 374 */ 375 376 #include <soc/enet.h> 377 378 static int 379 d_ether_compare(decode_list_t *dl, void *hdr) 380 /* 381 * Function: d_ether_compare 382 * Purpose: Compare routine for ethernet packet type. 383 * Parameters: dl - pointer to entry to compare. 384 * hdr - pointer to ethernet header to compare. 385 * Returns: -1 - hdr LESS than hdr 386 * 0 - hdr EQUAL hdr 387 * 1 - hdr GREATER than hdr 388 * Notes: If LEN < 0x600, it is an 802.3 packet, otherwise 389 * type field indicates packet type. The 802.3 "entry" is 390 * the first entry so we make sure we zoom in on it. 391 */ 392 { 393 enet_hdr_t *eh = (enet_hdr_t *)hdr; 394 uint16 t; 395 396 if (ENET_TAGGED(eh)) { 397 t = bcm_ntohs(eh->en_tag_len); 398 } else { 399 t = bcm_ntohs(eh->en_untagged_len); 400 } 401 402 if (dl->dl_low > t) { 403 return(-1); 404 } else if (dl->dl_high < t) { 405 return(1); 406 } else { 407 return(0); 408 } 409 } 410 411 char * 412 d_ether_decode(const char *pfx, char *s, void *ehp, int el, decode_list_t *dl, void *pd) 413 /* 414 * Function: p_ether_decode 415 * Purpose: Format ethernet header into string. 416 * Parameters: pfx - prefix for output. 417 * s - pointer to string to format into 418 * ehp - ethernet header 419 * el - length of packet starting at eh 420 * dl - pointer to data list entry matching 421 * Returns: Pointer to where string ends ('\0') 422 */ 423 { 424 enet_hdr_t *eh = (enet_hdr_t *)ehp; 425 426 COMPILER_REFERENCE(pfx); 427 COMPILER_REFERENCE(pd); 428 429 /* 430 * Make a best guess at if the header is a valid length, if it 431 * is less that min length (UNTAGGED) or if it is less that 432 * a calculated length it is in error. This is not perfect, but it is 433 * close enough for now. 434 */ 435 if ((el < ENET_UNTAGGED_HDR_LEN) || 436 (el < ENET_HDR_LEN(eh))) { 437 s = d_strcat_dec(s, "ETHER (***INVALID LENGTH ", el, "***):"); 438 s = d_vformat_bytes(s, (unsigned char *)eh, el, 1, ' '); 439 return(s); 440 } 441 442 s = d_strcat(s, "dst<"); 443 s = d_vformat_bytes(s,(unsigned char *)&eh->en_dhost, 444 sizeof(eh->en_dhost), 1, ':'); 445 s = d_strcat(s, "> src<"); 446 s = d_vformat_bytes(s,(unsigned char *)&eh->en_shost, 447 sizeof(eh->en_shost), 1, ':'); 448 s = d_strcat(s, "> "); 449 450 if (ENET_SNAP(eh)) { 451 s = d_strcat(s, "SNAP Packet "); 452 } else if (ENET_TAGGED(eh)) { 453 s = d_strcat(s, "Tagged Packet "); 454 } else { 455 s = d_strcat(s, "Untagged Packet "); 456 } 457 458 if (ENET_SNAP(eh) || (ENET_TAGGED(eh))) { 459 s = d_strcat(s, "ProtID<"); 460 s = d_vformat_hex(s, bcm_ntohs(eh->en_tag_tpid), 4, 1); 461 s = d_strcat(s, "> Ctrl<"); 462 s = d_vformat_hex(s, bcm_ntohs(eh->en_tag_ctrl), 4, 1); 463 s = d_strcat(s, "> "); 464 } else if (bcm_ntohs(eh->en_untagged_len) < 0x600) { 465 s = d_strcat_dec(s, "Length<",bcm_ntohs(eh->en_untagged_len),"-bytes> "); 466 } 467 468 if (dl) { 469 s = d_strcat(s, dl->dl_string); 470 } else { 471 s = d_strcat(s, "* Unknown/Experimental format * "); 472 s = d_vformat_bytes(s, (unsigned char *)eh, 64 > el ? el : 64, 1, 473 ' '); 474 } 475 476 return(s); 477 } 478 479 /*ARGSUSED*/ 480 static int 481 d_ether_length(decode_list_t *dl, void *ehp) 482 /* 483 * Function: d_ether_length 484 * Purpose: Determine the length of the ethernet header. 485 * Parameters: dl - pointer to decode list entry. 486 * ehp - pointer to ethernet header. 487 * Returns: Integer length. 488 * Notes: For tagged packets, the ethernet header is larger. 489 */ 490 { 491 enet_hdr_t *eh = (enet_hdr_t *)ehp; 492 493 COMPILER_REFERENCE(dl); 494 return(ENET_HDR_LEN(eh)); 495 } 496 497 static decode_list_t d_ether_type[] = { 498 {0x0000, 0x0600, &d_ip_table,"802.3 Packet"}, 499 {0x0800, 0x0800, &d_ip_table,"Internet Protocol (IP)"}, 500 {0x0801, 0x0801, NULL, "X.75 Internet"}, 501 {0x0802, 0x0802, NULL, "NBS Internet"}, 502 {0x0803, 0x0803, NULL, "ECMA Internet"}, 503 {0x0804, 0x0804, NULL, "CHAOSnet"}, 504 {0x0805, 0x0805, NULL, "X.25 Level 3"}, 505 {0x0806, 0x0806, &d_arp_table, "ARP (IP and CHAOS)"}, 506 {0x0807, 0x0807, NULL, "XNS Compatibility"}, 507 {0x081C, 0x081C, NULL, "Symbolics Private"}, 508 {0x0888, 0x088a, NULL, "Xyplex"}, 509 {0x0900, 0x0900, NULL, "Ungermann-Bass network debugger"}, 510 {0x0A00, 0x0A00, NULL, "Xerox IEEE802.3 PUP"}, 511 {0x0A01, 0x0A01, NULL, "Xerox IEEE802.3 PUP Address Translation"}, 512 {0x0BAD, 0x0BAD, NULL, "Banyan Systems"}, 513 {0x0BAF, 0x0BAF, NULL, "Banyon VINES Echo"}, 514 {0x1000, 0x100f, NULL, "Berkeley Trailer negotiation"}, 515 {0x1234, 0x1234, NULL, "DCA - Multicast"}, 516 {0x1600, 0x1600, NULL, "VALID system protocol"}, 517 {0x1989, 0x1989, NULL, "Artificial Horizons (\"Aviator\" dogfight " 518 "simulator [on Sun])"}, 519 {0x1995, 0x1995, NULL, "Datapoint Corporation (RCL lan protocol)"}, 520 {0x3C00, 0x3C00, NULL, "3Com NBP virtual circuit datagram (like " 521 "XNS SPP) not registered"}, 522 {0x3C01, 0x3C01, NULL, "3Com NBP System control datagram not " 523 "registered"}, 524 {0x3C02, 0x3C02, NULL, "3Com NBP Connect request (virtual cct) " 525 "not registered"}, 526 {0x3C03, 0x3C03, NULL, "3Com NBP Connect response not registered"}, 527 {0x3C04, 0x3C04, NULL, "3Com NBP Connect complete not registered"}, 528 {0x3C05, 0x3C05, NULL, "3Com NBP Close request (virtual cct) " 529 "not registered"}, 530 {0x3C06, 0x3C06, NULL, "3Com NBP Close response not registered"}, 531 {0x3C07, 0x3C07, NULL, "3Com NBP Datagram (like XNS IDP) not " 532 "registered"}, 533 {0x3C08, 0x3C08, NULL, "3Com NBP Datagram broadcast not " 534 "registered"}, 535 {0x3C09, 0x3C09, NULL, "3Com NBP Claim NetBIOS name not " 536 "registered"}, 537 {0x3C0A, 0x3C0A, NULL, "3Com NBP Delete Netbios name not " 538 "registered"}, 539 {0x3C0B, 0x3C0B, NULL, "3Com NBP Remote adaptor status request " 540 "not registered"}, 541 {0x3C0C, 0x3C0C, NULL, "3Com NBP Remote adaptor response not " 542 "registered"}, 543 {0x3C0D, 0x3C0D, NULL, "3Com NBP Reset not registered"}, 544 {0x4242, 0x4242, NULL, "PCS Basic Block Protocol"}, 545 {0x424C, 0x424C, NULL, "Information Modes Little Big LAN " 546 "diagnostic"}, 547 {0x4321, 0x4321, NULL, "THD - Diddle"}, 548 {0x4C42, 0x4C42, NULL, "Information Modes Little Big LAN"}, 549 {0x5208, 0x5208, NULL, "BBN Simnet Private"}, 550 {0x6000, 0x6000, NULL, "DEC unassigned, experimental"}, 551 {0x6001, 0x6001, NULL, "DEC Maintenance Operation Protocol (MOP) " 552 "Dump/Load Assistance"}, 553 {0x6002, 0x6002, NULL, "DEC Maintenance Operation Protocol (MOP) " 554 "Remote Console"}, 555 {0x6003, 0x6003, NULL, "DECNET Phase IV, DNA Routing"}, 556 {0x6004, 0x6004, NULL, "DEC Local Area Transport (LAT)"}, 557 {0x6005, 0x6005, NULL, "DEC diagnostic protocol (at interface " 558 "initialization)"}, 559 {0x6006, 0x6006, NULL, "DEC customer protocol"}, 560 {0x6007, 0x6007, NULL, "DEC Local Area VAX Cluster,System " 561 "Communication Architecture"}, 562 {0x6008, 0x6008, NULL, "DEC AMBER"}, 563 {0x6009, 0x6009, NULL, "DEC MUMPS"}, 564 {0x6010, 0x6014, NULL, "3Com Corporation"}, 565 {0x7000, 0x7000, NULL, "Ungermann-Bass download"}, 566 {0x7001, 0x7001, NULL, "Ungermann-Bass NIUs"}, 567 {0x7002, 0x7002, NULL, "Ungermann-Bass diagnostic/loopback"}, 568 {0x7003, 0x7003, NULL, "Ungermann-Bass (NMC to/from UB Bridge)"}, 569 {0x7005, 0x7005, NULL, "Ungermann-Bass Bridge Spanning Tree"}, 570 {0x7007, 0x7007, NULL, "OS/9 Microware"}, 571 {0x7009, 0x7009, NULL, "OS/9 Net"}, 572 {0x7020, 0x7029, NULL, "LRT (England) (now Sintrom)"}, 573 {0x7030, 0x7030, NULL, "Racal-Interlan"}, 574 {0x7031, 0x7031, NULL, "Prime NTS (Network Terminal Service)"}, 575 {0x7034, 0x7034, NULL, "Cabletron"}, 576 {0x8003, 0x8003, NULL, "Cronus VLN"}, 577 {0x8004, 0x8004, NULL, "Cronus Direct"}, 578 {0x8005, 0x8005, NULL, "HP Probe protocol"}, 579 {0x8006, 0x8006, NULL, "Nestar"}, 580 {0x8008, 0x8008, NULL, "AT&T/Stanford University"}, 581 {0x8010, 0x8010, NULL, "Excelan"}, 582 {0x8013, 0x8013, NULL, "Silicon Graphics diagnostic"}, 583 {0x8014, 0x8014, NULL, "Silicon Graphics network games"}, 584 {0x8015, 0x8015, NULL, "Silicon Graphics reserved"}, 585 {0x8016, 0x8016, NULL, "Silicon Graphics XNS NameServer, bounce " 586 "server"}, 587 {0x8019, 0x8019, NULL, "Apollo DOMAIN"}, 588 {0x802E, 0x802E, NULL, "Tymshare"}, 589 {0x802F, 0x802F, NULL, "Tigan, Inc."}, 590 {0x8035, 0x8035, NULL, "Reverse Address Resolution Protocol " 591 "(RARP)"}, 592 {0x8036, 0x8036, NULL, "Aeonic Systems"}, 593 {0x8037, 0x8037, NULL, "IPX (Novell Netware)"}, 594 {0x8038, 0x8038, NULL, "DEC LanBridge Management"}, 595 {0x8039, 0x8039, NULL, "DEC DSM/DDP"}, 596 {0x803A, 0x803A, NULL, "DEC Argonaut Console"}, 597 {0x803B, 0x803B, NULL, "DEC VAXELN"}, 598 {0x803C, 0x803C, NULL, "DEC DNS Naming Service"}, 599 {0x803D, 0x803D, NULL, "DEC Ethernet CSMA/CD Encryption Protocol"}, 600 {0x803E, 0x803E, NULL, "DEC Distributed Time Service"}, 601 {0x803F, 0x803F, NULL, "DEC LAN Traffic Monitor Protocol"}, 602 {0x8040, 0x8040, NULL, "DEC PATHWORKS DECnet NETBIOS Emulation"}, 603 {0x8041, 0x8041, NULL, "DEC Local Area System Transport"}, 604 {0x8042, 0x8042, NULL, "DEC unassigned"}, 605 {0x8044, 0x8044, NULL, "Planning Research Corp."}, 606 {0x8046, 0x8046, NULL, "AT&T"}, 607 {0x8047, 0x8047, NULL, "AT&T"}, 608 {0x8048, 0x8048, NULL, "DEC Availability Manager for Distributed " 609 "Systems DECamds"}, 610 {0x8049, 0x8049, NULL, "ExperData"}, 611 {0x805B, 0x805B, NULL, "VMTP (Versatile Message Transaction " 612 "Protocol,RFC-1045) (Stanford)"}, 613 {0x805C, 0x805C, NULL, "Stanford V Kernel, version 6.0"}, 614 {0x805D, 0x805D, NULL, "Evans & Sutherland"}, 615 {0x8060, 0x8060, NULL, "Little Machines"}, 616 {0x8062, 0x8062, NULL, "Counterpoint Computers"}, 617 {0x8065, 0x8065, NULL, "University of Mass. at Amherst"}, 618 {0x8066, 0x8066, NULL, "University of Mass. at Amherst"}, 619 {0x8067, 0x8067, NULL, "Veeco Integrated Automation"}, 620 {0x8068, 0x8068, NULL, "General Dynamics"}, 621 {0x8069, 0x8069, NULL, "AT&T"}, 622 {0x806A, 0x806A, NULL, "Autophon"}, 623 {0x806C, 0x806C, NULL, "ComDesign"}, 624 {0x806D, 0x806D, NULL, "Compugraphic Corporation"}, 625 {0x806E, 0x8077, NULL, "Landmark Graphics Corporation"}, 626 {0x807A, 0x807A, NULL, "Matra"}, 627 {0x807B, 0x807B, NULL, "Dansk Data Elektronik"}, 628 {0x807C, 0x807C, NULL, "Merit Internodal (or Univ of Michigan)"}, 629 {0x807D, 0x807f, NULL, "Vitalink Communications"}, 630 {0x8080, 0x8080, NULL, "Vitalink TransLAN III Management"}, 631 {0x8081, 0x8083, NULL, "Counterpoint Computers"}, 632 {0x8088, 0x808a, NULL, "Xyplex"}, 633 {0x809B, 0x809B, NULL, "EtherTalk (AppleTalk over Ethernet)"}, 634 {0x809C, 0x809C, NULL, "Datability"}, 635 {0x809D, 0x809D, NULL, "Datability"}, 636 {0x809E, 0x809E, NULL, "Datability"}, 637 {0x809F, 0x809F, NULL, "Spider Systems Ltd."}, 638 {0x80A3, 0x80A3, NULL, "Nixdorf Computers"}, 639 {0x80A4, 0x80b3, NULL, "Siemens Gammasonics Inc."}, 640 {0x80C0, 0x80c3, NULL, "DCA (Digital Comm. Assoc.) Data Exchange " 641 "Cluster"}, 642 {0x80C6, 0x80C6, NULL, "Pacer Software"}, 643 {0x80C7, 0x80C7, NULL, "Applitek Corporation"}, 644 {0x80C8, 0x80cc, NULL, "Intergraph Corporation"}, 645 {0x80CD, 0x80CD, NULL, "Harris Corporation"}, 646 {0x80CE, 0x80CE, NULL, "Harris Corporation"}, 647 {0x80CF, 0x80d2, NULL, "Taylor Instrument"}, 648 {0x80D3, 0x80D4, NULL, "Rosemount Corporation"}, 649 {0x80D5, 0x80D5, NULL, "IBM SNA Services over Ethernet"}, 650 {0x80DD, 0x80DD, NULL, "Varian Associates"}, 651 {0x80DE, 0x80DE, NULL, "TRFS (Integrated Solutions Transparent " 652 "Remote File System)"}, 653 {0x80DF, 0x80DF, NULL, "TRFS (Integrated Solutions Transparent " 654 "Remote File System)"}, 655 {0x80E0, 0x80E3, NULL, "Allen-Bradley"}, 656 {0x80E4, 0x80ed, NULL, "Datability"}, 657 {0x80EF, 0x80f0, NULL, "Datability"}, 658 {0x80F2, 0x80F2, NULL, "Retix"}, 659 {0x80F3, 0x80F3, NULL, "AppleTalk Address Resolution Protocol " 660 "(AARP)"}, 661 {0x80F4, 0x80F4, NULL, "Kinetics"}, 662 {0x80F5, 0x80F5, NULL, "Kinetics"}, 663 {0x80F7, 0x80F7, NULL, "Apollo Computer"}, 664 {0x80FF, 0x8101, NULL, "Wellfleet Communications"}, 665 {0x8102, 0x8102, NULL, "Wellfleet; BOFL (Breath OF Life) pkts " 666 "[every 5-10 secs.]"}, 667 {0x8103, 0x8103, NULL, "Wellfleet Communications"}, 668 {0x8107, 0x8109, NULL, "Symbolics Private"}, 669 {0x812B, 0x812B, NULL, "Talaris"}, 670 {0x8130, 0x8130, NULL, "Waterloo Microsystems Inc."}, 671 {0x8131, 0x8131, NULL, "VG Laboratory Systems"}, 672 {0x8137, 0x8137, NULL, "Novell (old) NetWare IPX (ECONFIG E " 673 "option)"}, 674 {0x8138, 0x8138, NULL, "Novell, Inc."}, 675 {0x8139, 0x8139, NULL, "KTI"}, 676 {0x813a, 0x813a, NULL, "KTI"}, 677 {0x813b, 0x813b, NULL, "KTI"}, 678 {0x813c, 0x813c, NULL, "KTI"}, 679 {0x813d, 0x813d, NULL, "KTI"}, 680 {0x813F, 0x813F, NULL, "M/MUMPS data sharing"}, 681 {0x8145, 0x8147, NULL, "Vrije Universiteit (NL"}, 682 {0x814C, 0x814C, NULL, "SNMP over Ethernet (see RFC1089)"}, 683 {0x814F, 0x814F, NULL, "Technically Elite Concept"}, 684 {0x8191, 0x8191, NULL, "PowerLA"}, 685 {0x817D, 0x817D, NULL, "XTP"}, 686 {0x81D6, 0x81D6, NULL, "Artisoft Lantastic"}, 687 {0x81D7, 0x81D7, NULL, "Artisoft Lantastic"}, 688 {0x8203, 0x8205, NULL, "QNX Software Systems Ltd."}, 689 {0x8390, 0x8390, NULL, "Accton Technologies (unregistered)"}, 690 {0x852B, 0x852B, NULL, "Talaris multicast"}, 691 {0x8582, 0x8582, NULL, "Kalpana"}, 692 {0x86DD, 0x86DD, NULL, "IP version 6"}, 693 {0x8739, 0x8739, NULL, "Control Technology Inc"}, 694 {0x873A, 0x873A, NULL, "Control Technology Inc"}, 695 {0x873B, 0x873B, NULL, "Control Technology Inc"}, 696 {0x873C, 0x873C, NULL, "Control Technology Inc"}, 697 {0x8820, 0x8820, NULL, "Hitachi Cable (Optoelectronic Systems " 698 "Laboratory)"}, 699 {0x8856, 0x8856, NULL, "Axis Communications AB"}, 700 {0x8888, 0x8888, NULL, "HP LanProbe test"}, 701 {0x8902, 0x8902, &d_oam_table,"OAM"}, 702 {0x9000, 0x9000, NULL, "Loopback (Configuration Test Protocol)"}, 703 {0x9001, 0x9001, NULL, "3Com (Formerly Bridge Communications), " 704 "XNS Systems Management"}, 705 {0x9002, 0x9002, NULL, "3Com (Formerly Bridge Communications), " 706 "TCP/IP Systems Management"}, 707 {0x9003, 0x9003, NULL, "3Com (Formerly Bridge Communications), " 708 "loopback detection"}, 709 {0xAAAA, 0xAAAA, NULL, "DECNET"}, 710 {0xFAF5, 0xFAF5, NULL, "Sonix Arpeggio"}, 711 {0xFF00, 0xFF00, NULL, "BBN VITAL-LanBridge cache wakeups"}, 712 }; 713 /* 714 * Ethernet decode table. 715 */ 716 static decode_t d_ether_table = { 717 "Ethernet", 718 d_ether_decode, 719 d_ether_compare, 720 d_ether_length, 721 DECODE_LIST(d_ether_type) 722 }; 723 724 /************************************************************************ 725 ************************************************************************ 726 ************************************************************************ 727 * * 728 * ARP * 729 */ 730 /* From <net/if_arp.h> which does not exist on all systems */ 731 struct arphdr { 732 uint16 ar_hrd; 733 uint16 ar_pro; 734 uint8 ar_hln; 735 uint8 ar_pln; 736 uint8 ar_op; 737 }; 738 739 static int 740 d_arp_compare(decode_list_t *dl, void *ahp) 741 /* 742 * Function: d_arp_compare 743 * Purpose: Compare routine for arp packet type. 744 * Parameters: dl - pointer to entry to compare. 745 * hdr - pointer to arp header to compare. 746 * Returns: -1 - hdr LESS than dl 747 * 0 - hdr EQUAL dl 748 * 1 - hdr GREATER than dl 749 */ 750 { 751 HDR_DECL(struct arphdr, ah, ahp); 752 753 if (dl->dl_low > bcm_ntohs(ah->ar_op)) { 754 return(-1); 755 } else if (dl->dl_high < bcm_ntohs(ah->ar_op)) { 756 return(1); 757 } else { 758 return(0); 759 } 760 } 761 762 char * 763 d_arp_decode(const char *pfx, char *s, void *ahp, int el, decode_list_t *dl, void *pd) 764 /* 765 * Function: p_arp_decode 766 * Purpose: Format arp header into string. 767 * Parameters: pfx - output prefix 768 * s - pointer to string to format into 769 * ahp - arp header 770 * el - length of packet starting at ahp 771 * dl - pointer to data list entry matching 772 * Returns: Pointer to where string ends ('\0') 773 */ 774 { 775 HDR_DECL(struct arphdr, ah, ahp); 776 unsigned char *aptr = (unsigned char *)ahp + sizeof(struct arphdr); 777 778 COMPILER_REFERENCE(pfx); 779 COMPILER_REFERENCE(pd); 780 781 if (el < (int)sizeof(struct arphdr)) { 782 s = d_strcat(s, "ARP (***INVALID***):"); 783 s = d_vformat_bytes(s, (unsigned char *)ah, el, 1, ' '); 784 return(s); 785 } 786 787 s = d_strcat(s, dl->dl_string); 788 s = d_strcat_dec(s, " fmt<", bcm_ntohs(ah->ar_hrd), "> src-ha<"); 789 s = d_vformat_bytes(s, aptr, ah->ar_hln, 1, ':'); 790 aptr += ah->ar_hln; 791 s = d_strcat(s, "> src_pa<"); 792 s = d_vformat_dec(s, aptr, ah->ar_pln, 1, ':'); 793 aptr += ah->ar_pln; 794 s = d_strcat(s, "> tar_ha<"); 795 s = d_vformat_bytes(s, aptr, ah->ar_hln, 1, ':'); 796 aptr += ah->ar_hln; 797 s = d_strcat(s, "> tar_pa<"); 798 s = d_vformat_dec(s, aptr, ah->ar_pln, 1, ':'); 799 aptr += ah->ar_pln; 800 s = d_strcat(s, ">"); 801 802 return(s); 803 } 804 805 static int 806 d_arp_length(decode_list_t *dl, void *ahp) 807 /* 808 * Function: d_arp_length 809 * Purpose: Determine the length of the arp header. 810 * Parameters: dl - pointer to decode list entry. 811 * ehp - pointer to arp header. 812 * Returns: Integer length. 813 */ 814 { 815 HDR_DECL(struct arphdr, ah, ahp); 816 817 COMPILER_REFERENCE(dl); 818 819 return(sizeof(struct arphdr) + ah->ar_hln * 2 + ah->ar_pln * 2); 820 } 821 822 static decode_list_t d_arp_type[] = { 823 {0, 0, NULL, "Invalid (0)"}, 824 {1, 1, NULL, "Request [RFC826]"}, 825 {2, 2, NULL, "Reply [RFC826]"}, 826 {3, 3, NULL, "Request Reverse (RARP) [RFC903]"}, 827 {4, 4, NULL, "Reply Reverse (RARP) [RFC903]"}, 828 {5, 5, NULL, "DRARP-Request [David Brownell]"}, 829 {6, 6, NULL, "DRARP-Reply [David Brownell]"}, 830 {7, 7, NULL, "DRARP-Error [David Brownell]"}, 831 {8, 8, NULL, "InARP-Request [RFC1293]"}, 832 {9, 9, NULL, "InARP-Reply [RFC1293]"}, 833 {10, 10, NULL, "ARP-NAK [RFC1577]"}, 834 {11, 11, NULL, "MARS-Request [Armitage]"}, 835 {12, 12, NULL, "MARS-Multi [Armitage]"}, 836 {13, 13, NULL, "MARS-MServ [Armitage]"}, 837 {14, 14, NULL, "MARS-Join [Armitage]"}, 838 {15, 15, NULL, "MARS-Leave [Armitage]"}, 839 {16, 16, NULL, "MARS-NAK [Armitage]"}, 840 {17, 17, NULL, "MARS-Unserv [Armitage]"}, 841 {18, 18, NULL, "MARS-SJoin [Armitage]"}, 842 {19, 19, NULL, "MARS-SLeave [Armitage]"}, 843 {20, 20, NULL, "MARS-Grouplist-Request [Armitage]"}, 844 {21, 21, NULL, "MARS-Grouplist-Reply [Armitage]"}, 845 {22, 22, NULL, "MARS-Redirect-Map [Armitage]"}, 846 {23, 23, NULL, "MAPOS-UNARP [Maruyama]"}, 847 {24, 0xffff,NULL, "Undefined"} 848 }; 849 850 static decode_t d_arp_table = { 851 "ARP", 852 d_arp_decode, 853 d_arp_compare, 854 d_arp_length, 855 DECODE_LIST(d_arp_type) 856 }; 857 858 #if defined(BCM_ESW_SUPPORT) 859 static int 860 d_oam_compare(decode_list_t *dl, void *ahp) 861 /* 862 * Function: d_arp_compare 863 * Purpose: Compare routine for arp packet type. 864 * Parameters: dl - pointer to entry to compare. 865 * hdr - pointer to arp header to compare. 866 * Returns: -1 - hdr LESS than dl 867 * 0 - hdr EQUAL dl 868 * 1 - hdr GREATER than dl 869 */ 870 { 871 HDR_DECL(oam_hdr_t, ah, ahp); 872 873 if (dl->dl_low > ah->opcode) { 874 return(-1); 875 } else if (dl->dl_high < ah->opcode) { 876 return(1); 877 } else { 878 return(0); 879 } 880 } 881 882 char * 883 d_oam_decode(const char *pfx, char *s, void *ahp, int el, decode_list_t *dl, void *pd) 884 /* 885 * Function: p_arp_decode 886 * Purpose: Format arp header into string. 887 * Parameters: pfx - output prefix 888 * s - pointer to string to format into 889 * ahp - arp header 890 * el - length of packet starting at ahp 891 * dl - pointer to data list entry matching 892 * Returns: Pointer to where string ends ('\0') 893 */ 894 { 895 HDR_DECL(oam_hdr_t, ah, ahp); 896 897 COMPILER_REFERENCE(pfx); 898 COMPILER_REFERENCE(pd); 899 900 if (el < (int)sizeof(oam_hdr_t)) { 901 s = d_strcat(s, "OAM (***INVALID***):"); 902 s = d_vformat_bytes(s, (unsigned char *)ah, el, 1, ' '); 903 return(s); 904 } 905 906 s = d_strcat(s, dl->dl_string); 907 s = d_strcat_dec(s, " mdl<", (ah->mdl_ver >> 5), ">"); 908 s = d_strcat_dec(s, " opcode<", ah->opcode, ">"); 909 s = d_strcat_dec(s, " flag<", ah->flags, ">"); 910 s = d_strcat_dec(s, " first_tlvoffset<", ah->first_tlvoffset, ">"); 911 912 return(s); 913 } 914 915 static int 916 d_oam_length(decode_list_t *dl, void *ahp) 917 /* 918 * Function: d_arp_length 919 * Purpose: Determine the length of the arp header. 920 * Parameters: dl - pointer to decode list entry. 921 * ehp - pointer to arp header. 922 * Returns: Integer length. 923 */ 924 { 925 COMPILER_REFERENCE(ahp); 926 COMPILER_REFERENCE(dl); 927 928 return(sizeof(oam_hdr_t)); 929 } 930 931 char * 932 d_oam_lmr_decode(const char *pfx, char *s, void *ahp, int el, decode_list_t *dl, void *pd) 933 /* 934 * Function: p_arp_decode 935 * Purpose: Format arp header into string. 936 * Parameters: pfx - output prefix 937 * s - pointer to string to format into 938 * ahp - oam header 939 * el - length of packet starting at ahp 940 * dl - pointer to data list entry matching 941 * Returns: Pointer to where string ends ('\0') 942 */ 943 { 944 #ifdef BCM_ENDURO_SUPPORT 945 dcb20_t *pdcb; 946 #endif 947 HDR_DECL(oam_lm_pkt_t, ah, ahp); 948 949 COMPILER_REFERENCE(pfx); 950 951 if (el < (int)sizeof(oam_lm_pkt_t)) { 952 s = d_strcat(s, "LMR (***INVALID***):"); 953 s = d_vformat_bytes(s, (unsigned char *)ah, el, 1, ' '); 954 return(s); 955 } 956 957 s = d_strcat(s, "TxFCf:<"); 958 s = d_vformat_hex(s, bcm_ntohl(ah->txfcf), 8, 1); 959 s = d_strcat(s, "> RxFCf:<"); 960 s = d_vformat_hex(s, bcm_ntohl(ah->rxfcf), 8, 1); 961 s = d_strcat(s, "> TxFCb:<"); 962 s = d_vformat_hex(s, bcm_ntohl(ah->txfcb), 8, 1); 963 s = d_strcat(s, ">"); 964 #ifdef BCM_ENDURO_SUPPORT 965 if (pd) { 966 pdcb = (dcb20_t *)pd; 967 s = d_strcat(s, " RxFCb:<"); 968 s = d_vformat_hex(s, pdcb->timestamp, 8, 1); 969 s = d_strcat(s, ">"); 970 } 971 #endif 972 return(s); 973 } 974 975 char * 976 d_oam_lmm_decode(const char *pfx, char *s, void *ahp, int el, decode_list_t *dl, void *pd) 977 /* 978 * Function: p_arp_decode 979 * Purpose: Format arp header into string. 980 * Parameters: pfx - output prefix 981 * s - pointer to string to format into 982 * ahp - oam header 983 * el - length of packet starting at ahp 984 * dl - pointer to data list entry matching 985 * Returns: Pointer to where string ends ('\0') 986 */ 987 { 988 #ifdef BCM_ENDURO_SUPPORT 989 dcb20_t *pdcb; 990 #endif 991 HDR_DECL(oam_lm_pkt_t, ah, ahp); 992 993 COMPILER_REFERENCE(pfx); 994 995 if (el < (int)sizeof(oam_lm_pkt_t)) { 996 s = d_strcat(s, "LMM (***INVALID***):"); 997 s = d_vformat_bytes(s, (unsigned char *)ah, el, 1, ' '); 998 return(s); 999 } 1000 1001 s = d_strcat(s, "TxFCf:<"); 1002 s = d_vformat_hex(s, bcm_ntohl(ah->txfcf), 8, 1); 1003 s = d_strcat(s, "> RxFCf:<"); 1004 #ifdef BCM_ENDURO_SUPPORT 1005 if (pd) { 1006 pdcb = (dcb20_t *)pd; 1007 s = d_vformat_hex(s, pdcb->timestamp, 8, 1); 1008 } else 1009 #endif 1010 { 1011 s = d_vformat_hex(s, bcm_ntohl(ah->rxfcf), 8, 1); 1012 } 1013 s = d_strcat(s, "> TxFCb:<"); 1014 s = d_vformat_hex(s, bcm_ntohl(ah->txfcb), 8, 1); 1015 s = d_strcat(s, ">"); 1016 1017 return(s); 1018 } 1019 1020 char * 1021 d_oam_dmr_decode(const char *pfx, char *s, void *ahp, int el, decode_list_t *dl, void *pd) 1022 /* 1023 * Function: p_arp_decode 1024 * Purpose: Format arp header into string. 1025 * Parameters: pfx - output prefix 1026 * s - pointer to string to format into 1027 * ahp - oam header 1028 * el - length of packet starting at ahp 1029 * dl - pointer to data list entry matching 1030 * Returns: Pointer to where string ends ('\0') 1031 */ 1032 { 1033 #ifdef BCM_ENDURO_SUPPORT 1034 dcb20_t *pdcb; 1035 #endif 1036 HDR_DECL(oam_dm_pkt_t, ah, ahp); 1037 1038 COMPILER_REFERENCE(pfx); 1039 1040 if (el < (int)sizeof(oam_dm_pkt_t)) { 1041 s = d_strcat(s, "DMR (***INVALID***):"); 1042 s = d_vformat_bytes(s, (unsigned char *)ah, el, 1, ' '); 1043 return(s); 1044 } 1045 s = d_strcat(s, "TxTSf:<"); 1046 s = d_vformat_hex(s, bcm_ntohl(ah->txtsf_upper), 8, 1); 1047 s = d_vformat_hex(s, bcm_ntohl(ah->txtsf), 8, 0); 1048 s = d_strcat(s, "> RxTSf:<"); 1049 s = d_vformat_hex(s, bcm_ntohl(ah->rxtsf_upper), 8, 1); 1050 s = d_vformat_hex(s, bcm_ntohl(ah->rxtsf), 8, 0); 1051 s = d_strcat(s, "> TxTSb:<"); 1052 s = d_vformat_hex(s, bcm_ntohl(ah->txtsb_upper), 8, 1); 1053 s = d_vformat_hex(s, bcm_ntohl(ah->txtsb), 8, 0); 1054 s = d_strcat(s, "> RxTSb:<"); 1055 #ifdef BCM_ENDURO_SUPPORT 1056 if (pd) { 1057 pdcb = (dcb20_t *)pd; 1058 s = d_vformat_hex(s, pdcb->timestamp_upper, 8, 1); 1059 s = d_vformat_hex(s, pdcb->timestamp, 8, 0); 1060 } else 1061 #endif 1062 { 1063 s = d_vformat_hex(s, bcm_ntohl(ah->rxtsb_upper), 8, 1); 1064 s = d_vformat_hex(s, bcm_ntohl(ah->rxtsb), 8, 0); 1065 } 1066 s = d_strcat(s, ">"); 1067 1068 ahp = (void *)((char *)ahp + sizeof(oam_dm_pkt_t)); 1069 return(s); 1070 } 1071 1072 char * 1073 d_oam_dmm_decode(const char *pfx, char *s, void *ahp, int el, decode_list_t *dl, void *pd) 1074 /* 1075 * Function: p_arp_decode 1076 * Purpose: Format arp header into string. 1077 * Parameters: pfx - output prefix 1078 * s - pointer to string to format into 1079 * ahp - oam header 1080 * el - length of packet starting at ahp 1081 * dl - pointer to data list entry matching 1082 * Returns: Pointer to where string ends ('\0') 1083 */ 1084 { 1085 #ifdef BCM_ENDURO_SUPPORT 1086 dcb20_t *pdcb; 1087 #endif 1088 HDR_DECL(oam_dm_pkt_t, ah, ahp); 1089 1090 COMPILER_REFERENCE(pfx); 1091 1092 if (el < (int)sizeof(oam_dm_pkt_t)) { 1093 s = d_strcat(s, "DMM (***INVALID***):"); 1094 s = d_vformat_bytes(s, (unsigned char *)ah, el, 1, ' '); 1095 return(s); 1096 } 1097 s = d_strcat(s, "TxTSf:<"); 1098 s = d_vformat_hex(s, bcm_ntohl(ah->txtsf_upper), 8, 1); 1099 s = d_vformat_hex(s, bcm_ntohl(ah->txtsf), 8, 0); 1100 s = d_strcat(s, "> RxTSf:<"); 1101 #ifdef BCM_ENDURO_SUPPORT 1102 if (pd) { 1103 pdcb = (dcb20_t *)pd; 1104 s = d_vformat_hex(s, pdcb->timestamp_upper, 8, 1); 1105 s = d_vformat_hex(s, pdcb->timestamp, 8, 0); 1106 } else 1107 #endif 1108 { 1109 s = d_vformat_hex(s, bcm_ntohl(ah->rxtsf_upper), 8, 1); 1110 s = d_vformat_hex(s, bcm_ntohl(ah->rxtsf), 8, 0); 1111 } 1112 s = d_strcat(s, "> TxTSb:<"); 1113 s = d_vformat_hex(s, bcm_ntohl(ah->txtsb_upper), 8, 1); 1114 s = d_vformat_hex(s, bcm_ntohl(ah->txtsb), 8, 0); 1115 s = d_strcat(s, "> RxTSb:<"); 1116 s = d_vformat_hex(s, bcm_ntohl(ah->rxtsb_upper), 8, 1); 1117 s = d_vformat_hex(s, bcm_ntohl(ah->rxtsb), 8, 0); 1118 s = d_strcat(s, ">"); 1119 1120 ahp = (void *)((char *)ahp + sizeof(oam_dm_pkt_t)); 1121 return(s); 1122 } 1123 1124 static decode_list_t d_oam_type[] = { 1125 {0, 41, NULL, "Undefined"}, 1126 {42, 42, &d_oam_lmr_table, "LMR"}, 1127 {43, 43, &d_oam_lmm_table, "LMM"}, 1128 {46, 46, &d_oam_dmr_table, "DMR"}, 1129 {47, 47, &d_oam_dmm_table, "DMM"}, 1130 {48, 0xff, NULL, "Undefined"} 1131 }; 1132 1133 static decode_t d_oam_table = { 1134 "OAM", 1135 d_oam_decode, 1136 d_oam_compare, 1137 d_oam_length, 1138 DECODE_LIST(d_oam_type) 1139 }; 1140 1141 static decode_t d_oam_lmr_table = { /* OAM LMR*/ 1142 "LMR", 1143 d_oam_lmr_decode, 1144 NULL, 1145 NULL, 1146 DECODE_LIST_NULL 1147 }; 1148 1149 static decode_t d_oam_lmm_table = { /* OAM LMM */ 1150 "LMM", 1151 d_oam_lmm_decode, 1152 NULL, 1153 NULL, 1154 DECODE_LIST_NULL 1155 }; 1156 1157 static decode_t d_oam_dmr_table = { /* OAM DMR */ 1158 "DMR", 1159 d_oam_dmr_decode, 1160 NULL, 1161 NULL, 1162 DECODE_LIST_NULL 1163 }; 1164 1165 static decode_t d_oam_dmm_table = { /* OAM DMM */ 1166 "DMM", 1167 d_oam_dmm_decode, 1168 NULL, 1169 NULL, 1170 DECODE_LIST_NULL 1171 }; 1172 #endif 1173 1174 /************************************************************************ 1175 ************************************************************************ 1176 ************************************************************************ 1177 * * 1178 * IP * 1179 */ 1180 struct ip { 1181 #if defined(LE_HOST) 1182 unsigned int ip_hl:4; 1183 unsigned int ip_v:4; 1184 #else /* !LE_HOST */ 1185 unsigned int ip_v:4; 1186 unsigned int ip_hl:4; 1187 #endif 1188 uint8 ip_tos; 1189 uint16 ip_len; 1190 uint16 ip_id; 1191 uint16 ip_off; 1192 uint8 ip_ttl; 1193 uint8 ip_p; 1194 uint16 ip_sum; 1195 struct in_addr ip_src; 1196 struct in_addr ip_dst; 1197 }; 1198 1199 static int 1200 d_ip_compare(decode_list_t *dl, void *ipp) 1201 /* 1202 * Function: d_arp_compare 1203 * Purpose: Compare routine for arp packet type. 1204 * Parameters: dl - pointer to entry to compare. 1205 * ipp - pointer to ip header to compare. 1206 * Returns: -1 - hdr LESS than dl 1207 * 0 - hdr EQUAL dl 1208 * 1 - hdr GREATER than dl 1209 * Notes: Comparing byte field so no alignment required. 1210 */ 1211 { 1212 struct ip *iph = (struct ip *)ipp; 1213 1214 if (dl->dl_low > iph->ip_p) { 1215 return(-1); 1216 } else if (dl->dl_high < iph->ip_p) { 1217 return(1); 1218 } else { 1219 return(0); 1220 } 1221 } 1222 1223 char * 1224 d_ip_decode(const char *pfx, char *s, void *ihp, int il, decode_list_t *dl, void *pd) 1225 /* 1226 * Function: p_ip_decode 1227 * Purpose: Format ip header into string. 1228 * Parameters: pfx - output prefix 1229 * s - pointer to string to format into 1230 * ihp - ip header 1231 * il - length of packet starting at ihp 1232 * dl - pointer to data list entry matching 1233 * Returns: Pointer to where string ends ('\0') 1234 */ 1235 { 1236 HDR_DECL(struct ip, ih, ihp); 1237 1238 COMPILER_REFERENCE(pfx); 1239 COMPILER_REFERENCE(dl); 1240 COMPILER_REFERENCE(pd); 1241 1242 if (il < (int)sizeof(struct ip)) { 1243 s = d_strcat(s, "(***INVALID***):"); 1244 s = d_vformat_bytes(s, (unsigned char *)ih, il, 1, ' '); 1245 return(s); 1246 } 1247 1248 s = d_strcat_dec(s, "V(", ih->ip_v, ") src<"); 1249 s = d_vformat_dec(s, (unsigned char *)&ih->ip_src, sizeof(ih->ip_src), 1250 1, '.'); 1251 s = d_strcat(s, "> dst<"); 1252 s = d_vformat_dec(s, (unsigned char *)&ih->ip_dst, sizeof(ih->ip_dst), 1253 1, '.'); 1254 s = d_strcat_dec(s, "> hl<", ih->ip_hl, "> "); 1255 s = d_strcat_dec(s, "service-type<", ih->ip_tos, "> "); 1256 s = d_strcat_dec(s, "tl<", bcm_ntohs(ih->ip_len), "> "); 1257 s = d_strcat_dec(s, "id<", bcm_ntohs(ih->ip_id), "> "); 1258 s = d_strcat_dec(s, "frg-off<", bcm_ntohs(ih->ip_off), "> "); 1259 s = d_strcat_dec(s, "ttl<", ih->ip_ttl, "> "); 1260 s = d_strcat(s, "> chk-sum<"); 1261 s = d_vformat_hex(s, bcm_ntohs(ih->ip_sum), 4, 1); 1262 s = d_strcat(s, ">"); 1263 1264 return(s); 1265 } 1266 1267 /*ARGSUSED*/ 1268 static int 1269 d_ip_length(decode_list_t *dl, void *ihp) 1270 /* 1271 * Function: d_ip_length 1272 * Purpose: Determine the length of the ip header. 1273 * Parameters: dl - pointer to decode list entry. 1274 * ihp - pointer to ip header. 1275 * Returns: Integer length. 1276 */ 1277 { 1278 HDR_DECL(struct ip, ih, ihp); 1279 1280 COMPILER_REFERENCE(dl); 1281 1282 if (ih->ip_hl < sizeof(struct ip)) { 1283 return(sizeof(struct ip)); 1284 } 1285 return(ih->ip_hl); 1286 } 1287 1288 static decode_list_t d_ip_type[] = { 1289 {0, 0, NULL, "IPv6 Hop-by-Hop Option [RFC1883]"}, 1290 {1, 1, &d_icmp_table, "ICMP Internet Control Message [RFC792]"}, 1291 {2, 2, NULL, "Internet Group Management [RFC1112]"}, 1292 {3, 3, NULL, "Gateway-to-Gateway [RFC823]"}, 1293 {4, 4, NULL, "IP in IP (encapsulation) [RFC2003]"}, 1294 {5, 5, NULL, "Stream [RFC119,IEN119]"}, 1295 {6, 6, &d_tcp_table, "TCP (Transmission Control) [RFC793]"}, 1296 {7, 7, NULL, "CBT [Ballardie]"}, 1297 {8, 8, NULL, "Exterior Gateway Protocol [RFC88,DLM1]"}, 1298 {9, 9, NULL, "any private interior gateway [IANA]"}, 1299 {10, 10, NULL, "BBN-RCC-MON BBN RCC Monitoring [SGC]"}, 1300 {11, 11, NULL, "NVP-II Network Voice Protocol [RFC74,SC3]"}, 1301 {12, 12, NULL, "PUP [PU,XEROX]"}, 1302 {13, 13, NULL, "ARGUS [RWS4]"}, 1303 {14, 14, NULL, "EMCON [BN7]"}, 1304 {15, 15, NULL, "Cross Net Debugger [IEN158,JFH2]"}, 1305 {16, 16, NULL, "Chaos [NC3]"}, 1306 {17, 17, NULL, "User Datagram [RFC768,JBP]"}, 1307 {18, 18, NULL, "Multiplexing [IEN90,JBP]"}, 1308 {19, 19, NULL, "DCN Measurement Subsystems [DLM1]"}, 1309 {20, 20, NULL, "Host Monitoring [RFC869,RH6]"}, 1310 {21, 21, NULL, "Packet Radio Measurement [ZSU]"}, 1311 {22, 22, NULL, "XEROX NS IDP [ETHERNET,XEROX]"}, 1312 {23, 23, NULL, "Trunk-1 [BWB6]"}, 1313 {24, 24, NULL, "Trunk-2 [BWB6]"}, 1314 {25, 25, NULL, "Leaf-1 [BWB6]"}, 1315 {26, 26, NULL, "Leaf-2 [BWB6]"}, 1316 {27, 27, NULL, "Reliable Data Protocol [RFC908,RH6]"}, 1317 {28, 28, NULL, "Internet Reliable Transaction " 1318 "[RFC938,TXM]"}, 1319 {29, 29, NULL, "ISO Transport Protocol Class 4 " 1320 "[RFC969,DDC1]"}, 1321 {31, 31, NULL, "MFE Network Services Protocol"}, 1322 {32, 32, NULL, "MERIT Internodal Protocol [HWB]"}, 1323 {33, 33, NULL, "Sequential Exchange Protocol [JC120]"}, 1324 {34, 34, NULL, "Third Party Connect Protocol [SAF3]"}, 1325 {35, 35, NULL, "Inter-Domain Policy Routing Protocol " 1326 "[GXC]"}, 1327 {37, 37, NULL, "Datagram Delivery Protocol [WXC]"}, 1328 {38, 38, NULL, "IDPR Control Message Transport Proto " 1329 "[DXF]"}, 1330 {40, 40, NULL, "IL Transport Protocol [Presotto]"}, 1331 {41, 41, NULL, "Ipv6 [Deering] "}, 1332 {42, 42, NULL, "Source Demand Routing Protocol [DXE1]"}, 1333 {43, 43, NULL, "Route Routing Header for IPv6 [Deering]"}, 1334 {44, 44, NULL, "Frag Fragment Header for IPv6 [Deering]"}, 1335 {45, 45, NULL, "Inter-Domain Routing Protocol [Sue Hares]"}, 1336 {46, 46, NULL, "Reservation Protocol [Bob Braden]"}, 1337 {47, 47, NULL, "General Routing Encapsulation [Tony Li]"}, 1338 {48, 48, NULL, "Mobile Host Routing Protocol"}, 1339 {50, 50, NULL, "Encap Security Payload for IPv6 [RFC1827]"}, 1340 {51, 51, NULL, "Authentication Header for IPv6 [RFC1826]"}, 1341 {52, 52, NULL, "Integrated Net Layer Security TUBA [JI6]"}, 1342 {54, 54, &d_arp_table, "ARP Address Resolution Protocol [RFC1735]"}, 1343 {55, 55, NULL, "IP Mobility [Perkins]"}, 1344 {56, 56, NULL, "Transport Layer Security Protocol [Oberg]"}, 1345 {57, 57, NULL, "SKIP [Markson]"}, 1346 {58, 58, NULL, "ICMP for IPv6 [RFC1883]"}, 1347 {59, 59, NULL, "No Next Header for IPv6 [RFC1883]"}, 1348 {60, 60, NULL, "Destination Options for IPv6 [RFC1883]"}, 1349 {61, 61, NULL, "host internal protocol [IANA]"}, 1350 {62, 62, NULL, "CFTP [CFTP,HCF2]"}, 1351 {63, 63, NULL, "local network [IANA]"}, 1352 {64, 64, NULL, "SATNET and Backroom EXPAK [SHB]"}, 1353 {65, 65, NULL, "Kryptolan [PXL1]"}, 1354 {66, 66, NULL, "MIT Remote Virtual Disk Protocol [MBG]"}, 1355 {67, 67, NULL, "Internet Pluribus Packet Core [SHB]"}, 1356 {68, 68, NULL, "distributed file system [IANA]"}, 1357 {69, 69, NULL, "SATNET Monitoring [SHB]"}, 1358 {70, 70, NULL, "VISA Protocol [GXT1]"}, 1359 {71, 71, NULL, "Internet Packet Core Utility [SHB]"}, 1360 {72, 72, NULL, "Computer Protocol Network Executive " 1361 "[DXM2]"}, 1362 {73, 73, NULL, "Computer Protocol Heart Beat [DXM2]"}, 1363 {74, 74, NULL, "Wang Span Network [VXD]"}, 1364 {75, 75, NULL, "Packet Video Protocol [SC3]"}, 1365 {76, 76, NULL, "SAT-MON Backroom SATNET Monitoring [SHB]"}, 1366 {77, 77, NULL, "SUN ND PROTOCOL-Temporary [WM3]"}, 1367 {78, 78, NULL, "WIDEBAND Monitoring [SHB]"}, 1368 {79, 79, NULL, "WIDEBAND EXPAK [SHB]"}, 1369 {80, 80, NULL, "ISO Internet Protocol [MTR]"}, 1370 {81, 81, NULL, "VMTP [DRC3]"}, 1371 {82, 82, NULL, "VMTP SECURE-VMTP [DRC3]"}, 1372 {83, 83, NULL, "VINES [BXH]"}, 1373 {84, 84, NULL, "TTP [JXS]"}, 1374 {85, 85, NULL, "IGP NSFNET-IGP [HWB]"}, 1375 {86, 86, NULL, "Dissimilar Gateway Protocol [DGP,ML109]"}, 1376 {87, 87, NULL, "TCF [GAL5]"}, 1377 {89, 89, NULL, "OSPFIGP [RFC1583,JTM4]"}, 1378 {90, 90, NULL, "RPC Sprite RPC Protocol [SPRITE,BXW] "}, 1379 {91, 91, NULL, "Locus Address Resolution Protocol [BXH]"}, 1380 {92, 92, NULL, "Multicast Transport Protocol [SXA]"}, 1381 {93, 93, NULL, "AX.25 Frames [BK29]"}, 1382 {94, 94, NULL, "IP-within-IP Encapsulation Protocol [JI6]"}, 1383 {95, 95, NULL, "Mobile Internetworking Control Pro [JI6]"}, 1384 {96, 96, NULL, "Semaphore Communications Sec. Pro [HXH]"}, 1385 {97, 97, NULL, "Ethernet-within-IP Encapsulation [RXH1]"}, 1386 {98, 98, NULL, "Encapsulation Header [RFC1241,RXB3]"}, 1387 {99, 99, NULL, "private encryption scheme [IANA]"}, 1388 {100, 100, NULL, "GMTP [RXB5]"}, 1389 {101, 101, NULL, "Ipsilon Flow Management Protocol [Hinden]"}, 1390 {102, 102, NULL, "PNNI over IP [Callon]"}, 1391 {103, 103, NULL, "Protocol Independent Multicast " 1392 "[Farinacci]"}, 1393 {104, 104, NULL, "ARIS [Feldman]"}, 1394 {105, 105, NULL, "SCPS [Durst]"}, 1395 {106, 106, NULL, "QNX [Hunter]"}, 1396 {107, 107, NULL, "Active Networks [Braden]"}, 1397 {108, 108, NULL, "IP Payload Compression Protocol [RFC2393]"}, 1398 {109, 109, NULL, "Sitara Networks Protocol"}, 1399 {110, 110, NULL, "Peer Compaq Peer Protocol"}, 1400 {111, 111, NULL, "in-IP IPX in IP"}, 1401 {112, 112, NULL, "Virtual Router Redundancy Protocol"}, 1402 {114, 114, NULL, "0-hop protocol [IANA]"}, 1403 {115, 115, NULL, "Layer Two Tunneling Protocol [Aboba]"}, 1404 {116, 116, NULL, "D-II Data Exchange (DDX [Worley] "}, 1405 {117, 117, NULL, "Interactive Agent Transfer Protocol"}, 1406 {118, 118, NULL, "Schedule Transfer [JMP]"}, 1407 {119, 119, NULL, "SpectraLink Radio Protocol [Hamilton]"}, 1408 {120, 120, NULL, "UTI [Lothberg]"}, 1409 {121, 121, NULL, "Simple Message Protocol [Ekblad]"}, 1410 {122, 254, NULL, "Unassigned"}, 1411 {255, 255, NULL, "Reserved"} 1412 }; 1413 1414 static decode_t d_ip_table = { 1415 "IP", 1416 d_ip_decode, 1417 d_ip_compare, 1418 d_ip_length, 1419 DECODE_LIST(d_ip_type) 1420 }; 1421 1422 /************************************************************************ 1423 ************************************************************************ 1424 ************************************************************************ 1425 * * 1426 * ICMP * 1427 */ 1428 #define ICMP_MINLEN 8 1429 struct icmp_ra_addr { 1430 uint32 ira_addr; 1431 uint32 ira_preference; 1432 }; 1433 1434 struct icmp { 1435 uint8 icmp_type; 1436 uint8 icmp_code; 1437 uint16 icmp_cksum; 1438 union 1439 { 1440 uint8 ih_pptr; 1441 struct in_addr ih_gwaddr; 1442 struct ih_idseq 1443 { 1444 uint16 icd_id; 1445 uint16 icd_seq; 1446 } ih_idseq; 1447 uint32 ih_void; 1448 struct ih_pmtu 1449 { 1450 uint16 ipm_void; 1451 uint16 ipm_nextmtu; 1452 } ih_pmtu; 1453 struct ih_rtradv 1454 { 1455 uint8 irt_num_addrs; 1456 uint8 irt_wpa; 1457 uint16 irt_lifetime; 1458 } ih_rtradv; 1459 } icmp_hun; 1460 union 1461 { 1462 struct 1463 { 1464 uint32 its_otime; 1465 uint32 its_rtime; 1466 uint32 its_ttime; 1467 } id_ts; 1468 struct 1469 { 1470 struct ip idi_ip; 1471 /* options and then 64 bits of data */ 1472 } id_ip; 1473 struct icmp_ra_addr id_radv; 1474 uint32 id_mask; 1475 uint8 id_data[1]; 1476 } icmp_dun; 1477 }; 1478 1479 static int 1480 d_icmp_compare(decode_list_t *dl, void *icp) 1481 /* 1482 * Function: d_icmp_compare 1483 * Purpose: Compare routine for ICMP packets. 1484 * Parameters: dl - pointer to entry to compare 1485 * icp - pointer to header to compare. 1486 * Returns: -1 - hdr LESS than dl 1487 * 0 - hdr EQUAL dl 1488 * 1 - hdr GREATER than dl 1489 */ 1490 { 1491 struct icmp *ic = (struct icmp *)icp; 1492 1493 if (dl->dl_low > ic->icmp_type) { 1494 return(-1); 1495 } else if (dl->dl_high < ic->icmp_type) { 1496 return(1); 1497 } else { 1498 return(0); 1499 } 1500 } 1501 1502 char * 1503 d_icmp_decode(const char *pfx, char *s, void *icp, int il, decode_list_t *dl, void *pd) 1504 /* 1505 * Function: p_icmp_decode 1506 * Purpose: Format ICMP header into string. 1507 * Parameters: pfx - output prefix 1508 * s - pointer to string to format into 1509 * icp - icmp header pointer 1510 * il - length of packet starting at icp 1511 * dl - pointer to data list entry matching 1512 * Returns: Pointer to where string ends ('\0') 1513 */ 1514 { 1515 HDR_DECL(struct icmp, ic, icp); 1516 1517 COMPILER_REFERENCE(pfx); 1518 COMPILER_REFERENCE(il); 1519 COMPILER_REFERENCE(pd); 1520 1521 s = d_strcat_dec(s, "Type-", ic->icmp_type, " ("); 1522 if (dl) { 1523 s = d_strcat(s, dl->dl_string); 1524 s = d_strcat(s, ") "); 1525 s = d_strcat_dec(s, "Code-", ic->icmp_code, " "); 1526 } else { 1527 s = d_strcat(s, "INVALID"); 1528 s = d_strcat(s, ") "); 1529 return(s); 1530 } 1531 1532 return(s); 1533 } 1534 1535 static int 1536 d_icmp_compare_code(decode_list_t *dl, void *icp) 1537 /* 1538 * Function: d_icmp_compare_code 1539 * Purpose: Compare routine for ICMP packets on their "code". 1540 * Parameters: dl - pointer to entry to compare 1541 * icp - pointer to header to compare. 1542 * Returns: -1 - hdr LESS than dl 1543 * 0 - hdr EQUAL dl 1544 * 1 - hdr GREATER than dl 1545 */ 1546 { 1547 struct icmp *ic = (struct icmp *)icp; 1548 1549 if (dl->dl_low > ic->icmp_code) { 1550 return(-1); 1551 } else if (dl->dl_high < ic->icmp_code) { 1552 return(1); 1553 } else { 1554 return(0); 1555 } 1556 } 1557 1558 char * 1559 d_icmp_decode_code(const char *pfx, char *s, void *icp, int il, 1560 decode_list_t *dl) 1561 /* 1562 * Function: p_icmp_decode_code 1563 * Purpose: Format ICMP output for a type/code match. 1564 * Parameters: pfx - output prefix 1565 * s - pointer to string to format into 1566 * icp - icmp header pointer 1567 * il - length of packet starting at icp 1568 * dl - pointer to data list entry matching 1569 * Returns: Pointer to where string ends ('\0') 1570 */ 1571 { 1572 HDR_DECL(struct icmp, ic, icp); 1573 1574 COMPILER_REFERENCE(pfx); 1575 1576 s = d_strcat_dec(s, "Code-", ic->icmp_code, " ("); 1577 if (dl) { 1578 s = d_strcat(s, dl->dl_string); 1579 s = d_strcat(s, ") "); 1580 } else { 1581 s = d_strcat(s, "*Invalid*"); 1582 s = d_strcat(s, ") "); 1583 s = d_vformat_bytes(s, (unsigned char *)ic, il, 1, ' '); 1584 return(s); 1585 } 1586 1587 return(s); 1588 } 1589 1590 /*ARGSUSED*/ 1591 static int 1592 d_icmp_length(decode_list_t *dl, void *icp) 1593 /* 1594 * Function: d_icmp_length 1595 * Purpose: Determine the length of the icmp header. 1596 * Parameters: dl - pointer to decode list entry. 1597 * icp - pointer to ICMP header. 1598 * Returns: Integer length. 1599 */ 1600 { 1601 COMPILER_REFERENCE(dl); 1602 COMPILER_REFERENCE(icp); 1603 1604 return(ICMP_MINLEN); /* Next layer decode handles it */ 1605 } 1606 1607 static char * 1608 d_icmp_decode_default(const char *pfx, char *s, void *icp, int il, 1609 decode_list_t *dl, void *pd) 1610 /* 1611 * Function: p_icmp_decode_default 1612 * Purpose: Format ICMP output for an arbitrary ICMP packet, starting 1613 * with the "code". 1614 * Parameters: pfx - output prefix 1615 * s - pointer to string to format into 1616 * icp - icmp header pointer 1617 * il - length of packet starting at icp 1618 * dl - pointer to data list entry matching, if NULL, 1619 * assumes code is not used. 1620 * Returns: Pointer to where string ends ('\0') 1621 */ 1622 { 1623 HDR_DECL(struct icmp, ic, icp); 1624 1625 COMPILER_REFERENCE(pfx); 1626 COMPILER_REFERENCE(il); 1627 1628 if (dl) { 1629 s = d_strcat(s, " ("); 1630 s = d_strcat(s, dl->dl_string); 1631 s = d_strcat(s, ")"); 1632 } 1633 s = d_strcat_dec(s, "Code <", bcm_ntohs(ic->icmp_code), "> Checksum <"); 1634 s = d_vformat_hex(s, bcm_ntohs(ic->icmp_cksum), 4, 1); 1635 s = d_strcat(s, "> hun <"); 1636 /* For now, simply display remainder in bytes */ 1637 1638 s = d_vformat_bytes(s, (unsigned char *)&ic->icmp_hun, 4, 1, ' '); 1639 s = d_strcat(s, "> "); 1640 1641 return(s); 1642 } 1643 1644 /* Forward declare local tables */ 1645 1646 static decode_t d_icmp_type3_table; 1647 static decode_t d_icmp_type5_table; 1648 static decode_t d_icmp_type11_table; 1649 static decode_t d_icmp_type12_table; 1650 static decode_t d_icmp_default_table; 1651 1652 static decode_list_t d_icmp_type[] = { 1653 {0, 0, &d_icmp_default_table, "Echo Reply [RFC792]"}, 1654 {1, 1, &d_icmp_default_table, "Unassigned [JBP]"}, 1655 {2, 2, &d_icmp_default_table, "Unassigned [JBP]"}, 1656 {3, 3, &d_icmp_type3_table, "Destination Unreachable [RFC792]"}, 1657 {4, 4, &d_icmp_default_table, "Source Quench [RFC792]"}, 1658 {5, 5, &d_icmp_type5_table, "Redirect [RFC792]"}, 1659 {6, 6, &d_icmp_default_table, "Alternate Host Address [JBP]"}, 1660 {7, 7, &d_icmp_default_table, "Unassigned [JBP]"}, 1661 {8, 8, &d_icmp_default_table, "Echo [RFC792]"}, 1662 {9, 9, &d_icmp_default_table, "Router Advertisement [RFC1256]"}, 1663 {10, 10, &d_icmp_default_table, "Router Selection [RFC1256]"}, 1664 {11, 11, &d_icmp_type11_table, "Time Exceeded [RFC792]"}, 1665 {12, 12, &d_icmp_type12_table, "Parameter Problem [RFC792]"}, 1666 {13, 13, &d_icmp_default_table, "Timestamp [RFC792]"}, 1667 {14, 14, &d_icmp_default_table, "Timestamp Reply [RFC792]"}, 1668 {15, 15, &d_icmp_default_table, "Information Request [RFC792]"}, 1669 {16, 16, &d_icmp_default_table, "Information Reply [RFC792]"}, 1670 {17, 17, &d_icmp_default_table, "Address Mask Request [RFC950]"}, 1671 {18, 18, &d_icmp_default_table, "Address Mask Reply [RFC950]"}, 1672 {19, 19, &d_icmp_default_table, "Reserved (for Security [Solo]"}, 1673 {20, 20, &d_icmp_default_table, "Reserved (for Robustness " 1674 "Experiment [ZSu]"}, 1675 {21, 29, &d_icmp_default_table, "Unknown"}, 1676 {30, 30, &d_icmp_default_table, "Traceroute [RFC1393]"}, 1677 {31, 31, &d_icmp_default_table, "Datagram Conversion Error " 1678 "[RFC1475]"}, 1679 {32, 32, &d_icmp_default_table, "Mobile Host Redirect " 1680 "[David Johnson]"}, 1681 {33, 33, &d_icmp_default_table, "IPv6 Where-Are-You"}, 1682 {34, 34, &d_icmp_default_table, "IPv6 I-Am-Here"}, 1683 {35, 35, &d_icmp_default_table, "Mobile Registration Request"}, 1684 {36, 36, &d_icmp_default_table, "Mobile Registration Reply"}, 1685 {37, 37, &d_icmp_default_table, "Domain Name Request"}, 1686 {38, 38, &d_icmp_default_table, "Domain Name Reply"}, 1687 {39, 39, &d_icmp_default_table, "SKIP [Markson]"}, 1688 {40, 40, &d_icmp_default_table, "Photuris [Simpson]"}, 1689 {41, 255, &d_icmp_default_table, "Reserved"} 1690 }; 1691 1692 static decode_list_t d_icmp_type3[] = { 1693 {0, 0, NULL, "Net Unreachable"}, 1694 {1, 1, NULL, "Host Unreachable"}, 1695 {2, 2, NULL, "Protocol Unreachable"}, 1696 {3, 3, NULL, "Port Unreachable"}, 1697 {4, 4, NULL, "Fragmentation Needed and Don't " 1698 "Fragment was Set"}, 1699 {5, 5, NULL, "Source Route Failed"}, 1700 {6, 6, NULL, "Destination Network Unknown"}, 1701 {7, 7, NULL, "Destination Host Unknown"}, 1702 {8, 8, NULL, "Source Host Isolated"}, 1703 {9, 9, NULL, "Communication with Destination Network is " 1704 "Administratively Prohibited"}, 1705 {10, 10, NULL, "Communication with Destination Host is " 1706 "Administratively Prohibited"}, 1707 {11, 11, NULL, "Destination Network Unreachable for Type " 1708 "of Service"}, 1709 {12, 12, NULL, "Destination Host Unreachable for Type " 1710 "of Service"}, 1711 {13, 13, NULL, "Communication Administratively Prohibited " 1712 "[RFC1812]"}, 1713 {14, 14, NULL, "Host Precedence Violation [RFC1812]"}, 1714 {15, 15, NULL, "Precedence cutoff in effect [RFC1812]"}, 1715 {16, 255, NULL, "*Invalid*"} 1716 }; 1717 1718 static decode_list_t d_icmp_type5[] = { 1719 {0, 0, NULL, "Redirect Datagram for the Network " 1720 "(or subnet)"}, 1721 {1, 1, NULL, "Redirect Datagram for the Host"}, 1722 {2, 2, NULL, "Redirect Datagram for the Type of " 1723 "Service and Network"}, 1724 {3, 3, NULL, "Redirect Datagram for the Type of " 1725 "Service and Host"}, 1726 {4, 255, NULL, "*Invalid*"} 1727 }; 1728 1729 static decode_list_t d_icmp_type11[] = { 1730 {0, 0, NULL, "Time to Live exceeded in Transit"}, 1731 {1, 1, NULL, "Fragment Reassembly Time Exceeded"}, 1732 {2, 255, NULL, "*Invalid*"} 1733 }; 1734 1735 static decode_list_t d_icmp_type12[] = { 1736 {0, 0, NULL, "Pointer indicates the error"}, 1737 {1, 1, NULL, "Missing a Required Option [RFC1108]"}, 1738 {2, 2, NULL, "Bad Length"}, 1739 {3, 255, NULL, "*Invalid*"} 1740 1741 }; 1742 1743 static decode_t d_icmp_table = { 1744 "ICMP", 1745 d_icmp_decode, 1746 d_icmp_compare, 1747 d_icmp_length, 1748 DECODE_LIST(d_icmp_type) 1749 }; 1750 1751 static decode_t d_icmp_type3_table = { /* Type 3 CODE table */ 1752 "Type 3", 1753 d_icmp_decode_default, 1754 d_icmp_compare_code, 1755 d_icmp_length, 1756 DECODE_LIST(d_icmp_type3) 1757 }; 1758 1759 static decode_t d_icmp_type5_table = { /* Type 5 CODE table */ 1760 "Type 5", 1761 d_icmp_decode_default, 1762 d_icmp_compare_code, 1763 d_icmp_length, 1764 DECODE_LIST(d_icmp_type5) 1765 }; 1766 static decode_t d_icmp_type11_table = { /* Type 11 CODE table */ 1767 "Type 11", 1768 d_icmp_decode_default, 1769 d_icmp_compare_code, 1770 d_icmp_length, 1771 DECODE_LIST(d_icmp_type11) 1772 }; 1773 1774 static decode_t d_icmp_type12_table = { /* Type 12 CODE table */ 1775 "Type 12", 1776 d_icmp_decode_default, 1777 d_icmp_compare_code, 1778 d_icmp_length, 1779 DECODE_LIST(d_icmp_type12) 1780 }; 1781 1782 static decode_t d_icmp_default_table = { /* Generic code table */ 1783 "Generic", 1784 d_icmp_decode_default, 1785 d_icmp_compare_code, 1786 d_icmp_length, 1787 DECODE_LIST_NULL 1788 }; 1789 1790 /************************************************************************ 1791 ************************************************************************ 1792 ************************************************************************ 1793 * * 1794 * TCP * 1795 */ 1796 1797 #include <netinet/tcp.h> 1798 1799 static int 1800 d_tcp_length(decode_list_t *tl, void *tcpp) 1801 /* 1802 * Function: 1803 * Purpose: 1804 * Parameters: 1805 * Returns: 1806 */ 1807 { 1808 COMPILER_REFERENCE(tl); 1809 COMPILER_REFERENCE(tcpp); 1810 1811 return(sizeof(struct tcphdr)); 1812 } 1813 1814 static char * 1815 d_tcp_decode(const char *pfx, char *s, void *tcpp, int tl, decode_list_t *dl, void *pd) 1816 /* 1817 * Function: d_tcp_decode 1818 * Purpose: Format TCP header into string. 1819 * Parameters: pfx - prefix for output. 1820 * s - pointer to string to format into. 1821 * tcpp - pointer to tcp header. 1822 * tl - length remaining in packet. 1823 * tl - pointer to matching data list entry. 1824 * Returns: Pointer to where string ends ('\0') 1825 */ 1826 { 1827 static const char *tcp_flags[] = { 1828 "FIN", "SYN", "RST", "PUSH", "ACK", "URG" 1829 }; 1830 HDR_DECL(struct tcphdr, tcp, tcpp); 1831 int first, i; 1832 1833 COMPILER_REFERENCE(pfx); 1834 COMPILER_REFERENCE(pd); 1835 1836 if (tl < d_tcp_length(dl, tcpp)) { /* Invalid length */ 1837 s = d_strcat_dec(s, "*Invalid Length for TCP packet* ", tl, "-bytes"); 1838 } 1839 1840 s = d_strcat_dec(s, "sPort<", bcm_ntohs(tcp->th_sport), "> "); 1841 s = d_strcat_dec(s, "dPort<", bcm_ntohs(tcp->th_dport), "> "); 1842 s = d_strcat_dec(s, "Seq<", ntohl(tcp->th_seq), "> "); 1843 s = d_strcat_dec(s, "Ack<", ntohl(tcp->th_ack), "> "); 1844 s = d_strcat_dec(s, "Off<", tcp->th_off, "> Flags<"); 1845 s = d_vformat_hex(s, tcp->th_flags, 2, 1); 1846 s = d_strcat(s, "="); 1847 first = TRUE; 1848 for (i = 0; i < COUNTOF(tcp_flags); i++) { 1849 if (tcp->th_flags & (1 << i)) { 1850 if (first) { 1851 first = FALSE; 1852 } else { 1853 s = d_strcat(s, ","); 1854 } 1855 s = d_strcat(s, (char *)tcp_flags[i]); 1856 } 1857 } 1858 s = d_strcat(s, "> Csum<"); 1859 s = d_vformat_hex(s, bcm_ntohs(tcp->th_sum), 4, 1); 1860 s = d_strcat(s, "> Urp<"); 1861 s = d_vformat_hex(s, bcm_ntohs(tcp->th_urp), 4, 1); 1862 s = d_strcat(s, ">"); 1863 return(s); 1864 } 1865 1866 static decode_t d_tcp_table = { 1867 "TCP", 1868 d_tcp_decode, 1869 NULL, 1870 d_tcp_length, 1871 DECODE_LIST_NULL /* Nothing more to decode */ 1872 }; 1873 1874 /************************************************************************ 1875 ************************************************************************ 1876 ************************************************************************ 1877 * * 1878 * Main Decode * 1879 */ 1880 1881 int 1882 d_packet_vformat(char *pfx, char *s, int type, void *p, int pl, void *d) 1883 /* 1884 * Function: d_packet_vformat 1885 * Purpose: Decode a packet into a buffer. 1886 * Parameters: pfx - output prefix 1887 * type - type of packet (DECODE_ETHER etc) 1888 * p - pointer to packet 1889 * pl - length of packet 1890 * Returns: 0 - success, -1 failed. 1891 * Notes: Calls NO routines that require malloc/free etc, and can 1892 * thus be called from an interrupt handler. 1893 */ 1894 { 1895 switch(type) { 1896 case DECODE_ETHER: 1897 (void)d_decode(pfx, s, &d_ether_table, p, pl, d); 1898 break; 1899 case DECODE_IP: 1900 (void)d_decode(pfx, s, &d_ip_table, p, pl, d); 1901 break; 1902 case DECODE_TCP: 1903 (void)d_decode(pfx, s, &d_tcp_table, p, pl, d); 1904 break; 1905 case DECODE_ARP: 1906 (void)d_decode(pfx, s, &d_arp_table, p, pl, d); 1907 break; 1908 case DECODE_GB_ETHER: 1909 (void)d_decode(pfx, s, &d_ether_table, p, pl, d); 1910 break; 1911 default: 1912 (void)d_strcat(s, "****** Invalid type ******"); 1913 return(-1); 1914 } 1915 return(0); 1916 } 1917 1918 int 1919 d_packet_format(char *pfx, int type, void *p, int pl, void *d) 1920 /* 1921 * Function: d_packet_format 1922 * Purpose: Decode a packet and display results. 1923 * Parameters: pfx - pointer to prefix string inserted at start of 1924 * every line. 1925 * type - type of packet (DECODE_ETHER etc) 1926 * p - pointer to packet 1927 * pl - length of packet 1928 * Returns: 0 - success 1929 * -1 - failed 1930 * Notes: Calls malloc and can not be used in interrupt handler. 1931 */ 1932 { 1933 int rv; 1934 char *s, *ts; 1935 1936 if (NULL == (s = sal_alloc(4096,"decode"))) { 1937 rv = -1; 1938 } else { 1939 *s = '\0'; 1940 ts = d_strcat(s, pfx); 1941 rv = d_packet_vformat(pfx, ts, type, p, pl, d); 1942 if (0 == rv) { 1943 sal_printf("%s\n", s); 1944 } 1945 sal_free(s); 1946 } 1947 1948 return(rv); 1949 } 1950 1951 #endif /* __KERNEL__ */ 1952 1953 #endif /* NO_SAL_APPL */ 1954 #endif /* GHS */