print-fr.c revision 146778
1/* 2 * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996 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 * $FreeBSD: head/contrib/tcpdump/print-fr.c 146778 2005-05-29 19:09:28Z sam $ 22 */ 23 24#ifndef lint 25static const char rcsid[] _U_ = 26 "@(#)$Header: /tcpdump/master/tcpdump/print-fr.c,v 1.32 2005/04/06 21:32:39 mcr Exp $ (LBL)"; 27#endif 28 29#ifdef HAVE_CONFIG_H 30#include "config.h" 31#endif 32 33#include <tcpdump-stdinc.h> 34 35#include <stdio.h> 36#include <string.h> 37#include <pcap.h> 38 39#include "addrtoname.h" 40#include "interface.h" 41#include "ethertype.h" 42#include "nlpid.h" 43#include "extract.h" 44#include "oui.h" 45 46static void frf15_print(const u_char *, u_int); 47 48/* 49 * the frame relay header has a variable length 50 * 51 * the EA bit determines if there is another byte 52 * in the header 53 * 54 * minimum header length is 2 bytes 55 * maximum header length is 4 bytes 56 * 57 * 7 6 5 4 3 2 1 0 58 * +----+----+----+----+----+----+----+----+ 59 * | DLCI (6 bits) | CR | EA | 60 * +----+----+----+----+----+----+----+----+ 61 * | DLCI (4 bits) |FECN|BECN| DE | EA | 62 * +----+----+----+----+----+----+----+----+ 63 * | DLCI (7 bits) | EA | 64 * +----+----+----+----+----+----+----+----+ 65 * | DLCI (6 bits) |SDLC| EA | 66 * +----+----+----+----+----+----+----+----+ 67 */ 68 69#define FR_EA_BIT 0x01 70 71#define FR_CR_BIT 0x02000000 72#define FR_DE_BIT 0x00020000 73#define FR_BECN_BIT 0x00040000 74#define FR_FECN_BIT 0x00080000 75#define FR_SDLC_BIT 0x00000002 76 77 78struct tok fr_header_flag_values[] = { 79 { FR_CR_BIT, "C!" }, 80 { FR_DE_BIT, "DE" }, 81 { FR_BECN_BIT, "BECN" }, 82 { FR_FECN_BIT, "FECN" }, 83 { FR_SDLC_BIT, "sdlcore" }, 84 { 0, NULL } 85}; 86 87 88/* Finds out Q.922 address length, DLCI and flags. Returns 0 on success 89 * save the flags dep. on address length 90 */ 91static int parse_q922_addr(const u_char *p, u_int *dlci, u_int *sdlcore, 92 u_int *addr_len, u_int8_t *flags) 93{ 94 if ((p[0] & FR_EA_BIT)) 95 return -1; 96 97 *addr_len = 2; 98 *dlci = ((p[0] & 0xFC) << 2) | ((p[1] & 0xF0) >> 4); 99 100 flags[0] = p[0] & 0x02; /* populate the first flag fields */ 101 flags[1] = p[1] & 0x0c; 102 103 if (p[1] & FR_EA_BIT) 104 return 0; /* 2-byte Q.922 address */ 105 106 p += 2; 107 (*addr_len)++; /* 3- or 4-byte Q.922 address */ 108 if ((p[0] & FR_EA_BIT) == 0) { 109 *dlci = (*dlci << 7) | (p[0] >> 1); 110 (*addr_len)++; /* 4-byte Q.922 address */ 111 p++; 112 } 113 114 if ((p[0] & FR_EA_BIT) == 0) 115 return -1; /* more than 4 bytes of Q.922 address? */ 116 117 flags[3] = p[0] & 0x02; 118 119 if (p[0] & 0x02) 120 *sdlcore = p[0] >> 2; 121 else 122 *dlci = (*dlci << 6) | (p[0] >> 2); 123 124 return 0; 125} 126 127/* Frame Relay packet structure, with flags and CRC removed 128 129 +---------------------------+ 130 | Q.922 Address* | 131 +-- --+ 132 | | 133 +---------------------------+ 134 | Control (UI = 0x03) | 135 +---------------------------+ 136 | Optional Pad (0x00) | 137 +---------------------------+ 138 | NLPID | 139 +---------------------------+ 140 | . | 141 | . | 142 | . | 143 | Data | 144 | . | 145 | . | 146 +---------------------------+ 147 148 * Q.922 addresses, as presently defined, are two octets and 149 contain a 10-bit DLCI. In some networks Q.922 addresses 150 may optionally be increased to three or four octets. 151*/ 152 153static u_int 154fr_hdrlen(const u_char *p, u_int addr_len, u_int caplen) 155{ 156 if ((caplen > addr_len + 1 /* UI */ + 1 /* pad */) && 157 !p[addr_len + 1] /* pad exist */) 158 return addr_len + 1 /* UI */ + 1 /* pad */ + 1 /* NLPID */; 159 else 160 return addr_len + 1 /* UI */ + 1 /* NLPID */; 161} 162 163static void 164fr_hdr_print(int length, u_int addr_len, u_int dlci, u_int8_t *flags, u_int16_t nlpid) 165{ 166 if (qflag) { 167 (void)printf("Q.922, DLCI %u, length %u: ", 168 dlci, 169 length); 170 } else { 171 if (nlpid <= 0xff) /* if its smaller than 256 then its a NLPID */ 172 (void)printf("Q.922, hdr-len %u, DLCI %u, Flags [%s], NLPID %s (0x%02x), length %u: ", 173 addr_len, 174 dlci, 175 bittok2str(fr_header_flag_values, "none", EXTRACT_32BITS(flags)), 176 tok2str(nlpid_values,"unknown", nlpid), 177 nlpid, 178 length); 179 else /* must be an ethertype */ 180 (void)printf("Q.922, hdr-len %u, DLCI %u, Flags [%s], cisco-ethertype %s (0x%04x), length %u: ", 181 addr_len, 182 dlci, 183 bittok2str(fr_header_flag_values, "none", EXTRACT_32BITS(flags)), 184 tok2str(ethertype_values, "unknown", nlpid), 185 nlpid, 186 length); 187 } 188} 189 190u_int 191fr_if_print(const struct pcap_pkthdr *h, register const u_char *p) 192{ 193 register u_int length = h->len; 194 register u_int caplen = h->caplen; 195 u_int16_t extracted_ethertype; 196 u_int32_t orgcode; 197 register u_short et; 198 u_int dlci; 199 u_int sdlcore; 200 u_int addr_len; 201 u_int16_t nlpid; 202 u_int hdr_len; 203 u_int8_t flags[4]; 204 205 if (caplen < 4) { /* minimum frame header length */ 206 printf("[|fr]"); 207 return caplen; 208 } 209 210 if (parse_q922_addr(p, &dlci, &sdlcore, &addr_len, flags)) { 211 printf("Q.922, invalid address"); 212 return caplen; 213 } 214 215 hdr_len = fr_hdrlen(p, addr_len, caplen); 216 217 if (caplen < hdr_len) { 218 printf("[|fr]"); 219 return caplen; 220 } 221 222 if (p[addr_len] != 0x03 && dlci != 0) { 223 224 /* lets figure out if we have cisco style encapsulation: */ 225 extracted_ethertype = EXTRACT_16BITS(p+addr_len); 226 227 if (eflag) 228 fr_hdr_print(length, addr_len, dlci, flags, extracted_ethertype); 229 230 if (ether_encap_print(extracted_ethertype, 231 p+addr_len+ETHERTYPE_LEN, 232 length-addr_len-ETHERTYPE_LEN, 233 caplen-addr_len-ETHERTYPE_LEN, 234 &extracted_ethertype) == 0) 235 /* ether_type not known, probably it wasn't one */ 236 printf("UI %02x! ", p[addr_len]); 237 else 238 return hdr_len; 239 } 240 241 if (!p[addr_len + 1]) { /* pad byte should be used with 3-byte Q.922 */ 242 if (addr_len != 3) 243 printf("Pad! "); 244 } else if (addr_len == 3) 245 printf("No pad! "); 246 247 nlpid = p[hdr_len - 1]; 248 249 if (eflag) 250 fr_hdr_print(length, addr_len, dlci, flags, nlpid); 251 252 p += hdr_len; 253 length -= hdr_len; 254 caplen -= hdr_len; 255 256 switch (nlpid) { 257 case NLPID_IP: 258 ip_print(gndo, p, length); 259 break; 260 261#ifdef INET6 262 case NLPID_IP6: 263 ip6_print(p, length); 264 break; 265#endif 266 case NLPID_CLNP: 267 case NLPID_ESIS: 268 case NLPID_ISIS: 269 isoclns_print(p-1, length+1, caplen+1); /* OSI printers need the NLPID field */ 270 break; 271 272 case NLPID_SNAP: 273 orgcode = EXTRACT_24BITS(p); 274 et = EXTRACT_16BITS(p + 3); 275 276 if (eflag) 277 (void)printf("SNAP, oui %s (0x%06x), ethertype %s (0x%04x): ", 278 tok2str(oui_values,"Unknown",orgcode), 279 orgcode, 280 tok2str(ethertype_values,"Unknown", et), 281 et); 282 283 if (snap_print((const u_char *)(p + 5), length - 5, 284 caplen - 5, &extracted_ethertype, orgcode, et, 285 0) == 0) { 286 /* ether_type not known, print raw packet */ 287 if (!eflag) 288 fr_hdr_print(length + hdr_len, hdr_len, 289 dlci, flags, nlpid); 290 if (!xflag && !qflag) 291 default_print(p - hdr_len, caplen + hdr_len); 292 } 293 break; 294 295 case NLPID_Q933: 296 q933_print(p, length); 297 break; 298 299 case NLPID_MFR: 300 frf15_print(p, length); 301 break; 302 303 default: 304 if (!eflag) 305 fr_hdr_print(length + hdr_len, addr_len, 306 dlci, flags, nlpid); 307 if (!xflag) 308 default_print(p, caplen); 309 } 310 311 return hdr_len; 312} 313 314/* an NLPID of 0xb1 indicates a 2-byte 315 * FRF.15 header 316 * 317 * 7 6 5 4 3 2 1 0 318 * +----+----+----+----+----+----+----+----+ 319 * ~ Q.922 header ~ 320 * +----+----+----+----+----+----+----+----+ 321 * | NLPID (8 bits) | NLPID=0xb1 322 * +----+----+----+----+----+----+----+----+ 323 * | B | E | C |seq. (high 4 bits) | R | 324 * +----+----+----+----+----+----+----+----+ 325 * | sequence (low 8 bits) | 326 * +----+----+----+----+----+----+----+----+ 327 */ 328 329struct tok frf15_flag_values[] = { 330 { 0x80, "Begin" }, 331 { 0x40, "End" }, 332 { 0x20, "Control" }, 333 { 0, NULL } 334}; 335 336#define FR_FRF15_FRAGTYPE 0x01 337 338static void 339frf15_print (const u_char *p, u_int length) { 340 341 u_int16_t sequence_num, flags; 342 343 flags = p[0]&0xe0; 344 sequence_num = (p[0]&0x1e)<<7 | p[1]; 345 346 printf("FRF.15, seq 0x%03x, Flags [%s],%s Fragmentation, length %u", 347 sequence_num, 348 bittok2str(frf15_flag_values,"none",flags), 349 flags&FR_FRF15_FRAGTYPE ? "Interface" : "End-to-End", 350 length); 351 352/* TODO: 353 * depending on all permutations of the B, E and C bit 354 * dig as deep as we can - e.g. on the first (B) fragment 355 * there is enough payload to print the IP header 356 * on non (B) fragments it depends if the fragmentation 357 * model is end-to-end or interface based wether we want to print 358 * another Q.922 header 359 */ 360 361} 362 363/* 364 * Q.933 decoding portion for framerelay specific. 365 */ 366 367/* Q.933 packet format 368 Format of Other Protocols 369 using Q.933 NLPID 370 +-------------------------------+ 371 | Q.922 Address | 372 +---------------+---------------+ 373 |Control 0x03 | NLPID 0x08 | 374 +---------------+---------------+ 375 | L2 Protocol ID | 376 | octet 1 | octet 2 | 377 +-------------------------------+ 378 | L3 Protocol ID | 379 | octet 2 | octet 2 | 380 +-------------------------------+ 381 | Protocol Data | 382 +-------------------------------+ 383 | FCS | 384 +-------------------------------+ 385 */ 386 387/* L2 (Octet 1)- Call Reference Usually is 0x0 */ 388 389/* 390 * L2 (Octet 2)- Message Types definition 1 byte long. 391 */ 392/* Call Establish */ 393#define MSG_TYPE_ESC_TO_NATIONAL 0x00 394#define MSG_TYPE_ALERT 0x01 395#define MSG_TYPE_CALL_PROCEEDING 0x02 396#define MSG_TYPE_CONNECT 0x07 397#define MSG_TYPE_CONNECT_ACK 0x0F 398#define MSG_TYPE_PROGRESS 0x03 399#define MSG_TYPE_SETUP 0x05 400/* Call Clear */ 401#define MSG_TYPE_DISCONNECT 0x45 402#define MSG_TYPE_RELEASE 0x4D 403#define MSG_TYPE_RELEASE_COMPLETE 0x5A 404#define MSG_TYPE_RESTART 0x46 405#define MSG_TYPE_RESTART_ACK 0x4E 406/* Status */ 407#define MSG_TYPE_STATUS 0x7D 408#define MSG_TYPE_STATUS_ENQ 0x75 409 410struct tok fr_q933_msg_values[] = { 411 { MSG_TYPE_ESC_TO_NATIONAL, "ESC to National" }, 412 { MSG_TYPE_ALERT, "Alert" }, 413 { MSG_TYPE_CALL_PROCEEDING, "Call proceeding" }, 414 { MSG_TYPE_CONNECT, "Connect" }, 415 { MSG_TYPE_CONNECT_ACK, "Connect ACK" }, 416 { MSG_TYPE_PROGRESS, "Progress" }, 417 { MSG_TYPE_SETUP, "Setup" }, 418 { MSG_TYPE_DISCONNECT, "Disconnect" }, 419 { MSG_TYPE_RELEASE, "Release" }, 420 { MSG_TYPE_RELEASE_COMPLETE, "Release Complete" }, 421 { MSG_TYPE_RESTART, "Restart" }, 422 { MSG_TYPE_RESTART_ACK, "Restart ACK" }, 423 { MSG_TYPE_STATUS, "Status Reply" }, 424 { MSG_TYPE_STATUS_ENQ, "Status Enquiry" }, 425 { 0, NULL } 426}; 427 428#define MSG_ANSI_LOCKING_SHIFT 0x95 429 430#define FR_LMI_ANSI_REPORT_TYPE_IE 0x01 431#define FR_LMI_ANSI_LINK_VERIFY_IE_91 0x19 /* details? */ 432#define FR_LMI_ANSI_LINK_VERIFY_IE 0x03 433#define FR_LMI_ANSI_PVC_STATUS_IE 0x07 434 435#define FR_LMI_CCITT_REPORT_TYPE_IE 0x51 436#define FR_LMI_CCITT_LINK_VERIFY_IE 0x53 437#define FR_LMI_CCITT_PVC_STATUS_IE 0x57 438 439struct tok fr_q933_ie_values_codeset5[] = { 440 { FR_LMI_ANSI_REPORT_TYPE_IE, "ANSI Report Type" }, 441 { FR_LMI_ANSI_LINK_VERIFY_IE_91, "ANSI Link Verify" }, 442 { FR_LMI_ANSI_LINK_VERIFY_IE, "ANSI Link Verify" }, 443 { FR_LMI_ANSI_PVC_STATUS_IE, "ANSI PVC Status" }, 444 { FR_LMI_CCITT_REPORT_TYPE_IE, "CCITT Report Type" }, 445 { FR_LMI_CCITT_LINK_VERIFY_IE, "CCITT Link Verify" }, 446 { FR_LMI_CCITT_PVC_STATUS_IE, "CCITT PVC Status" }, 447 { 0, NULL } 448}; 449 450#define FR_LMI_REPORT_TYPE_IE_FULL_STATUS 0 451#define FR_LMI_REPORT_TYPE_IE_LINK_VERIFY 1 452#define FR_LMI_REPORT_TYPE_IE_ASYNC_PVC 2 453 454struct tok fr_lmi_report_type_ie_values[] = { 455 { FR_LMI_REPORT_TYPE_IE_FULL_STATUS, "Full Status" }, 456 { FR_LMI_REPORT_TYPE_IE_LINK_VERIFY, "Link verify" }, 457 { FR_LMI_REPORT_TYPE_IE_ASYNC_PVC, "Async PVC Status" }, 458 { 0, NULL } 459}; 460 461/* array of 16 codepages - currently we only support codepage 5 */ 462static struct tok *fr_q933_ie_codesets[] = { 463 NULL, 464 NULL, 465 NULL, 466 NULL, 467 NULL, 468 fr_q933_ie_values_codeset5, 469 NULL, 470 NULL, 471 NULL, 472 NULL, 473 NULL, 474 NULL, 475 NULL, 476 NULL, 477 NULL, 478 NULL 479}; 480 481 482struct common_ie_header { 483 u_int8_t ie_id; 484 u_int8_t ie_len; 485}; 486 487void 488q933_print(const u_char *p, u_int length) 489{ 490 const u_char *ptemp = p; 491 struct common_ie_header *ie_p; 492 int olen; 493 int is_ansi = 0; 494 u_int dlci,codeset; 495 496 if (length < 9) { /* shortest: Q.933a LINK VERIFY */ 497 printf("[|q.933]"); 498 return; 499 } 500 501 codeset = p[2]&0x0f; /* extract the codeset */ 502 503 if (p[2] == MSG_ANSI_LOCKING_SHIFT) 504 is_ansi = 1; 505 506 printf("%s", eflag ? "" : "Q.933, "); 507 508 /* printing out header part */ 509 printf(is_ansi ? "ANSI" : "CCITT "); 510 511 if (p[0]) 512 printf(", Call Ref: 0x%02x", p[0]); 513 514 if (vflag) 515 printf(", %s (0x%02x), length %u", 516 tok2str(fr_q933_msg_values,"unknown message",p[1]), 517 p[1], 518 length); 519 else 520 printf(", %s", 521 tok2str(fr_q933_msg_values,"unknown message 0x%02x",p[1])); 522 523 olen = length; /* preserve the original length for non verbose mode */ 524 525 if (length < (u_int)(2 - is_ansi)) { 526 printf("[|q.933]"); 527 return; 528 } 529 length -= 2 - is_ansi; 530 ptemp += 2 + is_ansi; 531 532 /* Loop through the rest of IE */ 533 while (length > sizeof(struct common_ie_header)) { 534 ie_p = (struct common_ie_header *)ptemp; 535 if (length < sizeof(struct common_ie_header) || 536 length < sizeof(struct common_ie_header) + ie_p->ie_len) { 537 if (vflag) /* not bark if there is just a trailer */ 538 printf("\n[|q.933]"); 539 else 540 printf(", length %u",olen); 541 return; 542 } 543 544 /* lets do the full IE parsing only in verbose mode 545 * however some IEs (DLCI Status, Link Verify) 546 * are also intereststing in non-verbose mode */ 547 if (vflag) 548 printf("\n\t%s IE (%u), length %u: ", 549 tok2str(fr_q933_ie_codesets[codeset],"unknown",ie_p->ie_id), 550 ie_p->ie_id, 551 ie_p->ie_len); 552 553 switch (ie_p->ie_id) { 554 555 case FR_LMI_ANSI_REPORT_TYPE_IE: /* fall through */ 556 case FR_LMI_CCITT_REPORT_TYPE_IE: 557 if (vflag) 558 printf("%s (%u)", 559 tok2str(fr_lmi_report_type_ie_values,"unknown",ptemp[2]), 560 ptemp[2]); 561 break; 562 563 case FR_LMI_ANSI_LINK_VERIFY_IE: /* fall through */ 564 case FR_LMI_CCITT_LINK_VERIFY_IE: 565 case FR_LMI_ANSI_LINK_VERIFY_IE_91: 566 if (!vflag) 567 printf(", "); 568 printf("TX Seq: %3d, RX Seq: %3d", ptemp[2], ptemp[3]); 569 break; 570 case FR_LMI_ANSI_PVC_STATUS_IE: /* fall through */ 571 case FR_LMI_CCITT_PVC_STATUS_IE: 572 if (!vflag) 573 printf(", "); 574 /* now parse the DLCI information element. */ 575 if ((ie_p->ie_len < 3) || 576 (ptemp[2] & 0x80) || 577 ((ie_p->ie_len == 3) && !(ptemp[3] & 0x80)) || 578 ((ie_p->ie_len == 4) && ((ptemp[3] & 0x80) || !(ptemp[4] & 0x80))) || 579 ((ie_p->ie_len == 5) && ((ptemp[3] & 0x80) || (ptemp[4] & 0x80) || 580 !(ptemp[5] & 0x80))) || 581 (ie_p->ie_len > 5) || 582 !(ptemp[ie_p->ie_len + 1] & 0x80)) 583 printf("Invalid DLCI IE"); 584 585 dlci = ((ptemp[2] & 0x3F) << 4) | ((ptemp[3] & 0x78) >> 3); 586 if (ie_p->ie_len == 4) 587 dlci = (dlci << 6) | ((ptemp[4] & 0x7E) >> 1); 588 else if (ie_p->ie_len == 5) 589 dlci = (dlci << 13) | (ptemp[4] & 0x7F) | ((ptemp[5] & 0x7E) >> 1); 590 591 printf("DLCI %u: status %s%s", dlci, 592 ptemp[ie_p->ie_len + 1] & 0x8 ? "New, " : "", 593 ptemp[ie_p->ie_len + 1] & 0x2 ? "Active" : "Inactive"); 594 break; 595 596 default: 597 if (vflag <= 1) 598 print_unknown_data(ptemp+2,"\n\t",ie_p->ie_len); 599 break; 600 } 601 602 /* do we want to see a hexdump of the IE ? */ 603 if (vflag> 1) 604 print_unknown_data(ptemp+2,"\n\t ",ie_p->ie_len); 605 606 length = length - ie_p->ie_len - 2; 607 ptemp = ptemp + ie_p->ie_len + 2; 608 } 609 if (!vflag) 610 printf(", length %u",olen); 611} 612