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 22 #include <sys/cdefs.h> 23 #ifndef lint 24 #if 0 25 static const char rcsid[] _U_ = 26 "@(#)Header: /tcpdump/master/tcpdump/print-fr.c,v 1.51 2006-06-23 22:20:32 hannes Exp (LBL)"; 27 #else 28 __RCSID("$NetBSD: print-fr.c,v 1.2 2010/12/05 05:11:30 christos Exp $"); 29 #endif 30 #endif 31 32 #ifdef HAVE_CONFIG_H 33 #include "config.h" 34 #endif 35 36 #include <tcpdump-stdinc.h> 37 38 #include <stdio.h> 39 #include <string.h> 40 #include <pcap.h> 41 42 #include "addrtoname.h" 43 #include "interface.h" 44 #include "ethertype.h" 45 #include "nlpid.h" 46 #include "extract.h" 47 #include "oui.h" 48 49 static void frf15_print(const u_char *, u_int); 50 51 /* 52 * the frame relay header has a variable length 53 * 54 * the EA bit determines if there is another byte 55 * in the header 56 * 57 * minimum header length is 2 bytes 58 * maximum header length is 4 bytes 59 * 60 * 7 6 5 4 3 2 1 0 61 * +----+----+----+----+----+----+----+----+ 62 * | DLCI (6 bits) | CR | EA | 63 * +----+----+----+----+----+----+----+----+ 64 * | DLCI (4 bits) |FECN|BECN| DE | EA | 65 * +----+----+----+----+----+----+----+----+ 66 * | DLCI (7 bits) | EA | 67 * +----+----+----+----+----+----+----+----+ 68 * | DLCI (6 bits) |SDLC| EA | 69 * +----+----+----+----+----+----+----+----+ 70 */ 71 72 #define FR_EA_BIT 0x01 73 74 #define FR_CR_BIT 0x02000000 75 #define FR_DE_BIT 0x00020000 76 #define FR_BECN_BIT 0x00040000 77 #define FR_FECN_BIT 0x00080000 78 #define FR_SDLC_BIT 0x00000002 79 80 81 struct tok fr_header_flag_values[] = { 82 { FR_CR_BIT, "C!" }, 83 { FR_DE_BIT, "DE" }, 84 { FR_BECN_BIT, "BECN" }, 85 { FR_FECN_BIT, "FECN" }, 86 { FR_SDLC_BIT, "sdlcore" }, 87 { 0, NULL } 88 }; 89 90 /* FRF.15 / FRF.16 */ 91 #define MFR_B_BIT 0x80 92 #define MFR_E_BIT 0x40 93 #define MFR_C_BIT 0x20 94 #define MFR_BEC_MASK (MFR_B_BIT | MFR_E_BIT | MFR_C_BIT) 95 #define MFR_CTRL_FRAME (MFR_B_BIT | MFR_E_BIT | MFR_C_BIT) 96 #define MFR_FRAG_FRAME (MFR_B_BIT | MFR_E_BIT ) 97 98 struct tok frf_flag_values[] = { 99 { MFR_B_BIT, "Begin" }, 100 { MFR_E_BIT, "End" }, 101 { MFR_C_BIT, "Control" }, 102 { 0, NULL } 103 }; 104 105 /* Finds out Q.922 address length, DLCI and flags. Returns 0 on success 106 * save the flags dep. on address length 107 */ 108 static int parse_q922_addr(const u_char *p, u_int *dlci, 109 u_int *addr_len, u_int8_t *flags) 110 { 111 if ((p[0] & FR_EA_BIT)) 112 return -1; 113 114 *addr_len = 2; 115 *dlci = ((p[0] & 0xFC) << 2) | ((p[1] & 0xF0) >> 4); 116 117 flags[0] = p[0] & 0x02; /* populate the first flag fields */ 118 flags[1] = p[1] & 0x0c; 119 flags[2] = 0; /* clear the rest of the flags */ 120 flags[3] = 0; 121 122 if (p[1] & FR_EA_BIT) 123 return 0; /* 2-byte Q.922 address */ 124 125 p += 2; 126 (*addr_len)++; /* 3- or 4-byte Q.922 address */ 127 if ((p[0] & FR_EA_BIT) == 0) { 128 *dlci = (*dlci << 7) | (p[0] >> 1); 129 (*addr_len)++; /* 4-byte Q.922 address */ 130 p++; 131 } 132 133 if ((p[0] & FR_EA_BIT) == 0) 134 return -1; /* more than 4 bytes of Q.922 address? */ 135 136 flags[3] = p[0] & 0x02; 137 138 *dlci = (*dlci << 6) | (p[0] >> 2); 139 140 return 0; 141 } 142 143 char *q922_string(const u_char *p) { 144 145 static u_int dlci, addr_len; 146 static u_int8_t flags[4]; 147 static char buffer[sizeof("DLCI xxxxxxxxxx")]; 148 memset(buffer, 0, sizeof(buffer)); 149 150 if (parse_q922_addr(p, &dlci, &addr_len, flags) == 0){ 151 snprintf(buffer, sizeof(buffer), "DLCI %u", dlci); 152 } 153 154 return buffer; 155 } 156 157 158 /* Frame Relay packet structure, with flags and CRC removed 159 160 +---------------------------+ 161 | Q.922 Address* | 162 +-- --+ 163 | | 164 +---------------------------+ 165 | Control (UI = 0x03) | 166 +---------------------------+ 167 | Optional Pad (0x00) | 168 +---------------------------+ 169 | NLPID | 170 +---------------------------+ 171 | . | 172 | . | 173 | . | 174 | Data | 175 | . | 176 | . | 177 +---------------------------+ 178 179 * Q.922 addresses, as presently defined, are two octets and 180 contain a 10-bit DLCI. In some networks Q.922 addresses 181 may optionally be increased to three or four octets. 182 */ 183 184 static u_int 185 fr_hdrlen(const u_char *p, u_int addr_len) 186 { 187 if (!p[addr_len + 1] /* pad exist */) 188 return addr_len + 1 /* UI */ + 1 /* pad */ + 1 /* NLPID */; 189 else 190 return addr_len + 1 /* UI */ + 1 /* NLPID */; 191 } 192 193 static void 194 fr_hdr_print(int length, u_int addr_len, u_int dlci, u_int8_t *flags, u_int16_t nlpid) 195 { 196 if (qflag) { 197 (void)printf("Q.922, DLCI %u, length %u: ", 198 dlci, 199 length); 200 } else { 201 if (nlpid <= 0xff) /* if its smaller than 256 then its a NLPID */ 202 (void)printf("Q.922, hdr-len %u, DLCI %u, Flags [%s], NLPID %s (0x%02x), length %u: ", 203 addr_len, 204 dlci, 205 bittok2str(fr_header_flag_values, "none", EXTRACT_32BITS(flags)), 206 tok2str(nlpid_values,"unknown", nlpid), 207 nlpid, 208 length); 209 else /* must be an ethertype */ 210 (void)printf("Q.922, hdr-len %u, DLCI %u, Flags [%s], cisco-ethertype %s (0x%04x), length %u: ", 211 addr_len, 212 dlci, 213 bittok2str(fr_header_flag_values, "none", EXTRACT_32BITS(flags)), 214 tok2str(ethertype_values, "unknown", nlpid), 215 nlpid, 216 length); 217 } 218 } 219 220 u_int 221 fr_if_print(const struct pcap_pkthdr *h, register const u_char *p) 222 { 223 register u_int length = h->len; 224 register u_int caplen = h->caplen; 225 226 TCHECK2(*p, 4); /* minimum frame header length */ 227 228 if ((length = fr_print(p, length)) == 0) 229 return (0); 230 else 231 return length; 232 trunc: 233 printf("[|fr]"); 234 return caplen; 235 } 236 237 u_int 238 fr_print(register const u_char *p, u_int length) 239 { 240 u_int16_t extracted_ethertype; 241 u_int dlci; 242 u_int addr_len; 243 u_int16_t nlpid; 244 u_int hdr_len; 245 u_int8_t flags[4]; 246 247 if (parse_q922_addr(p, &dlci, &addr_len, flags)) { 248 printf("Q.922, invalid address"); 249 return 0; 250 } 251 252 TCHECK2(*p,addr_len+1+1); 253 hdr_len = fr_hdrlen(p, addr_len); 254 TCHECK2(*p,hdr_len); 255 256 if (p[addr_len] != 0x03 && dlci != 0) { 257 258 /* lets figure out if we have cisco style encapsulation: */ 259 extracted_ethertype = EXTRACT_16BITS(p+addr_len); 260 261 if (eflag) 262 fr_hdr_print(length, addr_len, dlci, flags, extracted_ethertype); 263 264 if (ethertype_print(extracted_ethertype, 265 p+addr_len+ETHERTYPE_LEN, 266 length-addr_len-ETHERTYPE_LEN, 267 length-addr_len-ETHERTYPE_LEN) == 0) 268 /* ether_type not known, probably it wasn't one */ 269 printf("UI %02x! ", p[addr_len]); 270 else 271 return hdr_len; 272 } 273 274 if (!p[addr_len + 1]) { /* pad byte should be used with 3-byte Q.922 */ 275 if (addr_len != 3) 276 printf("Pad! "); 277 } else if (addr_len == 3) 278 printf("No pad! "); 279 280 nlpid = p[hdr_len - 1]; 281 282 if (eflag) 283 fr_hdr_print(length, addr_len, dlci, flags, nlpid); 284 p += hdr_len; 285 length -= hdr_len; 286 287 switch (nlpid) { 288 case NLPID_IP: 289 ip_print(gndo, p, length); 290 break; 291 292 #ifdef INET6 293 case NLPID_IP6: 294 ip6_print(p, length); 295 break; 296 #endif 297 case NLPID_CLNP: 298 case NLPID_ESIS: 299 case NLPID_ISIS: 300 isoclns_print(p-1, length+1, length+1); /* OSI printers need the NLPID field */ 301 break; 302 303 case NLPID_SNAP: 304 if (snap_print(p, length, length, 0) == 0) { 305 /* ether_type not known, print raw packet */ 306 if (!eflag) 307 fr_hdr_print(length + hdr_len, hdr_len, 308 dlci, flags, nlpid); 309 if (!suppress_default_print) 310 default_print(p - hdr_len, length + hdr_len); 311 } 312 break; 313 314 case NLPID_Q933: 315 q933_print(p, length); 316 break; 317 318 case NLPID_MFR: 319 frf15_print(p, length); 320 break; 321 322 case NLPID_PPP: 323 ppp_print(p, length); 324 break; 325 326 default: 327 if (!eflag) 328 fr_hdr_print(length + hdr_len, addr_len, 329 dlci, flags, nlpid); 330 if (!xflag) 331 default_print(p, length); 332 } 333 334 return hdr_len; 335 336 trunc: 337 printf("[|fr]"); 338 return 0; 339 340 } 341 342 u_int 343 mfr_if_print(const struct pcap_pkthdr *h, register const u_char *p) 344 { 345 register u_int length = h->len; 346 register u_int caplen = h->caplen; 347 348 TCHECK2(*p, 2); /* minimum frame header length */ 349 350 if ((length = mfr_print(p, length)) == 0) 351 return (0); 352 else 353 return length; 354 trunc: 355 printf("[|mfr]"); 356 return caplen; 357 } 358 359 360 #define MFR_CTRL_MSG_ADD_LINK 1 361 #define MFR_CTRL_MSG_ADD_LINK_ACK 2 362 #define MFR_CTRL_MSG_ADD_LINK_REJ 3 363 #define MFR_CTRL_MSG_HELLO 4 364 #define MFR_CTRL_MSG_HELLO_ACK 5 365 #define MFR_CTRL_MSG_REMOVE_LINK 6 366 #define MFR_CTRL_MSG_REMOVE_LINK_ACK 7 367 368 struct tok mfr_ctrl_msg_values[] = { 369 { MFR_CTRL_MSG_ADD_LINK, "Add Link" }, 370 { MFR_CTRL_MSG_ADD_LINK_ACK, "Add Link ACK" }, 371 { MFR_CTRL_MSG_ADD_LINK_REJ, "Add Link Reject" }, 372 { MFR_CTRL_MSG_HELLO, "Hello" }, 373 { MFR_CTRL_MSG_HELLO_ACK, "Hello ACK" }, 374 { MFR_CTRL_MSG_REMOVE_LINK, "Remove Link" }, 375 { MFR_CTRL_MSG_REMOVE_LINK_ACK, "Remove Link ACK" }, 376 { 0, NULL } 377 }; 378 379 #define MFR_CTRL_IE_BUNDLE_ID 1 380 #define MFR_CTRL_IE_LINK_ID 2 381 #define MFR_CTRL_IE_MAGIC_NUM 3 382 #define MFR_CTRL_IE_TIMESTAMP 5 383 #define MFR_CTRL_IE_VENDOR_EXT 6 384 #define MFR_CTRL_IE_CAUSE 7 385 386 struct tok mfr_ctrl_ie_values[] = { 387 { MFR_CTRL_IE_BUNDLE_ID, "Bundle ID"}, 388 { MFR_CTRL_IE_LINK_ID, "Link ID"}, 389 { MFR_CTRL_IE_MAGIC_NUM, "Magic Number"}, 390 { MFR_CTRL_IE_TIMESTAMP, "Timestamp"}, 391 { MFR_CTRL_IE_VENDOR_EXT, "Vendor Extension"}, 392 { MFR_CTRL_IE_CAUSE, "Cause"}, 393 { 0, NULL } 394 }; 395 396 #define MFR_ID_STRING_MAXLEN 50 397 398 struct ie_tlv_header_t { 399 u_int8_t ie_type; 400 u_int8_t ie_len; 401 }; 402 403 u_int 404 mfr_print(register const u_char *p, u_int length) 405 { 406 u_int tlen,idx,hdr_len = 0; 407 u_int16_t sequence_num; 408 u_int8_t ie_type,ie_len; 409 const u_int8_t *tptr; 410 411 412 /* 413 * FRF.16 Link Integrity Control Frame 414 * 415 * 7 6 5 4 3 2 1 0 416 * +----+----+----+----+----+----+----+----+ 417 * | B | E | C=1| 0 0 0 0 | EA | 418 * +----+----+----+----+----+----+----+----+ 419 * | 0 0 0 0 0 0 0 0 | 420 * +----+----+----+----+----+----+----+----+ 421 * | message type | 422 * +----+----+----+----+----+----+----+----+ 423 */ 424 425 TCHECK2(*p, 4); /* minimum frame header length */ 426 427 if ((p[0] & MFR_BEC_MASK) == MFR_CTRL_FRAME && p[1] == 0) { 428 printf("FRF.16 Control, Flags [%s], %s, length %u", 429 bittok2str(frf_flag_values,"none",(p[0] & MFR_BEC_MASK)), 430 tok2str(mfr_ctrl_msg_values,"Unknown Message (0x%02x)",p[2]), 431 length); 432 tptr = p + 3; 433 tlen = length -3; 434 hdr_len = 3; 435 436 if (!vflag) 437 return hdr_len; 438 439 while (tlen>sizeof(struct ie_tlv_header_t)) { 440 TCHECK2(*tptr, sizeof(struct ie_tlv_header_t)); 441 ie_type=tptr[0]; 442 ie_len=tptr[1]; 443 444 printf("\n\tIE %s (%u), length %u: ", 445 tok2str(mfr_ctrl_ie_values,"Unknown",ie_type), 446 ie_type, 447 ie_len); 448 449 /* infinite loop check */ 450 if (ie_type == 0 || ie_len <= sizeof(struct ie_tlv_header_t)) 451 return hdr_len; 452 453 TCHECK2(*tptr,ie_len); 454 tptr+=sizeof(struct ie_tlv_header_t); 455 /* tlv len includes header */ 456 ie_len-=sizeof(struct ie_tlv_header_t); 457 tlen-=sizeof(struct ie_tlv_header_t); 458 459 switch (ie_type) { 460 461 case MFR_CTRL_IE_MAGIC_NUM: 462 printf("0x%08x",EXTRACT_32BITS(tptr)); 463 break; 464 465 case MFR_CTRL_IE_BUNDLE_ID: /* same message format */ 466 case MFR_CTRL_IE_LINK_ID: 467 for (idx = 0; idx < ie_len && idx < MFR_ID_STRING_MAXLEN; idx++) { 468 if (*(tptr+idx) != 0) /* don't print null termination */ 469 safeputchar(*(tptr+idx)); 470 else 471 break; 472 } 473 break; 474 475 case MFR_CTRL_IE_TIMESTAMP: 476 if (ie_len == sizeof(struct timeval)) { 477 ts_print((const struct timeval *)tptr); 478 break; 479 } 480 /* fall through and hexdump if no unix timestamp */ 481 482 /* 483 * FIXME those are the defined IEs that lack a decoder 484 * you are welcome to contribute code ;-) 485 */ 486 487 case MFR_CTRL_IE_VENDOR_EXT: 488 case MFR_CTRL_IE_CAUSE: 489 490 default: 491 if (vflag <= 1) 492 print_unknown_data(tptr,"\n\t ",ie_len); 493 break; 494 } 495 496 /* do we want to see a hexdump of the IE ? */ 497 if (vflag > 1 ) 498 print_unknown_data(tptr,"\n\t ",ie_len); 499 500 tlen-=ie_len; 501 tptr+=ie_len; 502 } 503 return hdr_len; 504 } 505 /* 506 * FRF.16 Fragmentation Frame 507 * 508 * 7 6 5 4 3 2 1 0 509 * +----+----+----+----+----+----+----+----+ 510 * | B | E | C=0|seq. (high 4 bits) | EA | 511 * +----+----+----+----+----+----+----+----+ 512 * | sequence (low 8 bits) | 513 * +----+----+----+----+----+----+----+----+ 514 * | DLCI (6 bits) | CR | EA | 515 * +----+----+----+----+----+----+----+----+ 516 * | DLCI (4 bits) |FECN|BECN| DE | EA | 517 * +----+----+----+----+----+----+----+----+ 518 */ 519 520 sequence_num = (p[0]&0x1e)<<7 | p[1]; 521 /* whole packet or first fragment ? */ 522 if ((p[0] & MFR_BEC_MASK) == MFR_FRAG_FRAME || 523 (p[0] & MFR_BEC_MASK) == MFR_B_BIT) { 524 printf("FRF.16 Frag, seq %u, Flags [%s], ", 525 sequence_num, 526 bittok2str(frf_flag_values,"none",(p[0] & MFR_BEC_MASK))); 527 hdr_len = 2; 528 fr_print(p+hdr_len,length-hdr_len); 529 return hdr_len; 530 } 531 532 /* must be a middle or the last fragment */ 533 printf("FRF.16 Frag, seq %u, Flags [%s]", 534 sequence_num, 535 bittok2str(frf_flag_values,"none",(p[0] & MFR_BEC_MASK))); 536 print_unknown_data(p,"\n\t",length); 537 538 return hdr_len; 539 540 trunc: 541 printf("[|mfr]"); 542 return length; 543 } 544 545 /* an NLPID of 0xb1 indicates a 2-byte 546 * FRF.15 header 547 * 548 * 7 6 5 4 3 2 1 0 549 * +----+----+----+----+----+----+----+----+ 550 * ~ Q.922 header ~ 551 * +----+----+----+----+----+----+----+----+ 552 * | NLPID (8 bits) | NLPID=0xb1 553 * +----+----+----+----+----+----+----+----+ 554 * | B | E | C |seq. (high 4 bits) | R | 555 * +----+----+----+----+----+----+----+----+ 556 * | sequence (low 8 bits) | 557 * +----+----+----+----+----+----+----+----+ 558 */ 559 560 #define FR_FRF15_FRAGTYPE 0x01 561 562 static void 563 frf15_print (const u_char *p, u_int length) { 564 565 u_int16_t sequence_num, flags; 566 567 flags = p[0]&MFR_BEC_MASK; 568 sequence_num = (p[0]&0x1e)<<7 | p[1]; 569 570 printf("FRF.15, seq 0x%03x, Flags [%s],%s Fragmentation, length %u", 571 sequence_num, 572 bittok2str(frf_flag_values,"none",flags), 573 p[0]&FR_FRF15_FRAGTYPE ? "Interface" : "End-to-End", 574 length); 575 576 /* TODO: 577 * depending on all permutations of the B, E and C bit 578 * dig as deep as we can - e.g. on the first (B) fragment 579 * there is enough payload to print the IP header 580 * on non (B) fragments it depends if the fragmentation 581 * model is end-to-end or interface based wether we want to print 582 * another Q.922 header 583 */ 584 585 } 586 587 /* 588 * Q.933 decoding portion for framerelay specific. 589 */ 590 591 /* Q.933 packet format 592 Format of Other Protocols 593 using Q.933 NLPID 594 +-------------------------------+ 595 | Q.922 Address | 596 +---------------+---------------+ 597 |Control 0x03 | NLPID 0x08 | 598 +---------------+---------------+ 599 | L2 Protocol ID | 600 | octet 1 | octet 2 | 601 +-------------------------------+ 602 | L3 Protocol ID | 603 | octet 2 | octet 2 | 604 +-------------------------------+ 605 | Protocol Data | 606 +-------------------------------+ 607 | FCS | 608 +-------------------------------+ 609 */ 610 611 /* L2 (Octet 1)- Call Reference Usually is 0x0 */ 612 613 /* 614 * L2 (Octet 2)- Message Types definition 1 byte long. 615 */ 616 /* Call Establish */ 617 #define MSG_TYPE_ESC_TO_NATIONAL 0x00 618 #define MSG_TYPE_ALERT 0x01 619 #define MSG_TYPE_CALL_PROCEEDING 0x02 620 #define MSG_TYPE_CONNECT 0x07 621 #define MSG_TYPE_CONNECT_ACK 0x0F 622 #define MSG_TYPE_PROGRESS 0x03 623 #define MSG_TYPE_SETUP 0x05 624 /* Call Clear */ 625 #define MSG_TYPE_DISCONNECT 0x45 626 #define MSG_TYPE_RELEASE 0x4D 627 #define MSG_TYPE_RELEASE_COMPLETE 0x5A 628 #define MSG_TYPE_RESTART 0x46 629 #define MSG_TYPE_RESTART_ACK 0x4E 630 /* Status */ 631 #define MSG_TYPE_STATUS 0x7D 632 #define MSG_TYPE_STATUS_ENQ 0x75 633 634 struct tok fr_q933_msg_values[] = { 635 { MSG_TYPE_ESC_TO_NATIONAL, "ESC to National" }, 636 { MSG_TYPE_ALERT, "Alert" }, 637 { MSG_TYPE_CALL_PROCEEDING, "Call proceeding" }, 638 { MSG_TYPE_CONNECT, "Connect" }, 639 { MSG_TYPE_CONNECT_ACK, "Connect ACK" }, 640 { MSG_TYPE_PROGRESS, "Progress" }, 641 { MSG_TYPE_SETUP, "Setup" }, 642 { MSG_TYPE_DISCONNECT, "Disconnect" }, 643 { MSG_TYPE_RELEASE, "Release" }, 644 { MSG_TYPE_RELEASE_COMPLETE, "Release Complete" }, 645 { MSG_TYPE_RESTART, "Restart" }, 646 { MSG_TYPE_RESTART_ACK, "Restart ACK" }, 647 { MSG_TYPE_STATUS, "Status Reply" }, 648 { MSG_TYPE_STATUS_ENQ, "Status Enquiry" }, 649 { 0, NULL } 650 }; 651 652 #define MSG_ANSI_LOCKING_SHIFT 0x95 653 654 #define FR_LMI_ANSI_REPORT_TYPE_IE 0x01 655 #define FR_LMI_ANSI_LINK_VERIFY_IE_91 0x19 /* details? */ 656 #define FR_LMI_ANSI_LINK_VERIFY_IE 0x03 657 #define FR_LMI_ANSI_PVC_STATUS_IE 0x07 658 659 #define FR_LMI_CCITT_REPORT_TYPE_IE 0x51 660 #define FR_LMI_CCITT_LINK_VERIFY_IE 0x53 661 #define FR_LMI_CCITT_PVC_STATUS_IE 0x57 662 663 struct tok fr_q933_ie_values_codeset5[] = { 664 { FR_LMI_ANSI_REPORT_TYPE_IE, "ANSI Report Type" }, 665 { FR_LMI_ANSI_LINK_VERIFY_IE_91, "ANSI Link Verify" }, 666 { FR_LMI_ANSI_LINK_VERIFY_IE, "ANSI Link Verify" }, 667 { FR_LMI_ANSI_PVC_STATUS_IE, "ANSI PVC Status" }, 668 { FR_LMI_CCITT_REPORT_TYPE_IE, "CCITT Report Type" }, 669 { FR_LMI_CCITT_LINK_VERIFY_IE, "CCITT Link Verify" }, 670 { FR_LMI_CCITT_PVC_STATUS_IE, "CCITT PVC Status" }, 671 { 0, NULL } 672 }; 673 674 #define FR_LMI_REPORT_TYPE_IE_FULL_STATUS 0 675 #define FR_LMI_REPORT_TYPE_IE_LINK_VERIFY 1 676 #define FR_LMI_REPORT_TYPE_IE_ASYNC_PVC 2 677 678 struct tok fr_lmi_report_type_ie_values[] = { 679 { FR_LMI_REPORT_TYPE_IE_FULL_STATUS, "Full Status" }, 680 { FR_LMI_REPORT_TYPE_IE_LINK_VERIFY, "Link verify" }, 681 { FR_LMI_REPORT_TYPE_IE_ASYNC_PVC, "Async PVC Status" }, 682 { 0, NULL } 683 }; 684 685 /* array of 16 codepages - currently we only support codepage 1,5 */ 686 static struct tok *fr_q933_ie_codesets[] = { 687 NULL, 688 fr_q933_ie_values_codeset5, 689 NULL, 690 NULL, 691 NULL, 692 fr_q933_ie_values_codeset5, 693 NULL, 694 NULL, 695 NULL, 696 NULL, 697 NULL, 698 NULL, 699 NULL, 700 NULL, 701 NULL, 702 NULL 703 }; 704 705 static int fr_q933_print_ie_codeset5(const struct ie_tlv_header_t *ie_p, 706 const u_char *p); 707 708 typedef int (*codeset_pr_func_t)(const struct ie_tlv_header_t *ie_p, 709 const u_char *p); 710 711 /* array of 16 codepages - currently we only support codepage 1,5 */ 712 static codeset_pr_func_t fr_q933_print_ie_codeset[] = { 713 NULL, 714 fr_q933_print_ie_codeset5, 715 NULL, 716 NULL, 717 NULL, 718 fr_q933_print_ie_codeset5, 719 NULL, 720 NULL, 721 NULL, 722 NULL, 723 NULL, 724 NULL, 725 NULL, 726 NULL, 727 NULL, 728 NULL 729 }; 730 731 void 732 q933_print(const u_char *p, u_int length) 733 { 734 const u_char *ptemp = p; 735 struct ie_tlv_header_t *ie_p; 736 int olen; 737 int is_ansi = 0; 738 u_int codeset; 739 u_int ie_is_known = 0; 740 741 if (length < 9) { /* shortest: Q.933a LINK VERIFY */ 742 printf("[|q.933]"); 743 return; 744 } 745 746 codeset = p[2]&0x0f; /* extract the codeset */ 747 748 if (p[2] == MSG_ANSI_LOCKING_SHIFT) { 749 is_ansi = 1; 750 } 751 752 printf("%s", eflag ? "" : "Q.933, "); 753 754 /* printing out header part */ 755 printf("%s, codeset %u", is_ansi ? "ANSI" : "CCITT", codeset); 756 757 if (p[0]) { 758 printf(", Call Ref: 0x%02x", p[0]); 759 } 760 if (vflag) { 761 printf(", %s (0x%02x), length %u", 762 tok2str(fr_q933_msg_values, 763 "unknown message", p[1]), 764 p[1], 765 length); 766 } else { 767 printf(", %s", 768 tok2str(fr_q933_msg_values, 769 "unknown message 0x%02x", p[1])); 770 } 771 772 olen = length; /* preserve the original length for non verbose mode */ 773 774 if (length < (u_int)(2 - is_ansi)) { 775 printf("[|q.933]"); 776 return; 777 } 778 length -= 2 + is_ansi; 779 ptemp += 2 + is_ansi; 780 781 /* Loop through the rest of IE */ 782 while (length > sizeof(struct ie_tlv_header_t)) { 783 ie_p = (struct ie_tlv_header_t *)ptemp; 784 if (length < sizeof(struct ie_tlv_header_t) || 785 length < sizeof(struct ie_tlv_header_t) + ie_p->ie_len) { 786 if (vflag) { /* not bark if there is just a trailer */ 787 printf("\n[|q.933]"); 788 } else { 789 printf(", length %u",olen); 790 } 791 return; 792 } 793 794 /* lets do the full IE parsing only in verbose mode 795 * however some IEs (DLCI Status, Link Verify) 796 * are also interestting in non-verbose mode */ 797 if (vflag) { 798 printf("\n\t%s IE (0x%02x), length %u: ", 799 tok2str(fr_q933_ie_codesets[codeset], 800 "unknown", ie_p->ie_type), 801 ie_p->ie_type, 802 ie_p->ie_len); 803 } 804 805 /* sanity check */ 806 if (ie_p->ie_type == 0 || ie_p->ie_len == 0) { 807 return; 808 } 809 810 if (fr_q933_print_ie_codeset[codeset] != NULL) { 811 ie_is_known = fr_q933_print_ie_codeset[codeset](ie_p, ptemp); 812 } 813 814 if (vflag >= 1 && !ie_is_known) { 815 print_unknown_data(ptemp+2,"\n\t",ie_p->ie_len); 816 } 817 818 /* do we want to see a hexdump of the IE ? */ 819 if (vflag> 1 && ie_is_known) { 820 print_unknown_data(ptemp+2,"\n\t ",ie_p->ie_len); 821 } 822 823 length = length - ie_p->ie_len - 2; 824 ptemp = ptemp + ie_p->ie_len + 2; 825 } 826 if (!vflag) { 827 printf(", length %u",olen); 828 } 829 } 830 831 static int 832 fr_q933_print_ie_codeset5(const struct ie_tlv_header_t *ie_p, const u_char *p) 833 { 834 u_int dlci; 835 836 switch (ie_p->ie_type) { 837 838 case FR_LMI_ANSI_REPORT_TYPE_IE: /* fall through */ 839 case FR_LMI_CCITT_REPORT_TYPE_IE: 840 if (vflag) { 841 printf("%s (%u)", 842 tok2str(fr_lmi_report_type_ie_values,"unknown",p[2]), 843 p[2]); 844 } 845 return 1; 846 847 case FR_LMI_ANSI_LINK_VERIFY_IE: /* fall through */ 848 case FR_LMI_CCITT_LINK_VERIFY_IE: 849 case FR_LMI_ANSI_LINK_VERIFY_IE_91: 850 if (!vflag) { 851 printf(", "); 852 } 853 printf("TX Seq: %3d, RX Seq: %3d", p[2], p[3]); 854 return 1; 855 856 case FR_LMI_ANSI_PVC_STATUS_IE: /* fall through */ 857 case FR_LMI_CCITT_PVC_STATUS_IE: 858 if (!vflag) { 859 printf(", "); 860 } 861 /* now parse the DLCI information element. */ 862 if ((ie_p->ie_len < 3) || 863 (p[2] & 0x80) || 864 ((ie_p->ie_len == 3) && !(p[3] & 0x80)) || 865 ((ie_p->ie_len == 4) && ((p[3] & 0x80) || !(p[4] & 0x80))) || 866 ((ie_p->ie_len == 5) && ((p[3] & 0x80) || (p[4] & 0x80) || 867 !(p[5] & 0x80))) || 868 (ie_p->ie_len > 5) || 869 !(p[ie_p->ie_len + 1] & 0x80)) { 870 printf("Invalid DLCI IE"); 871 } 872 873 dlci = ((p[2] & 0x3F) << 4) | ((p[3] & 0x78) >> 3); 874 if (ie_p->ie_len == 4) { 875 dlci = (dlci << 6) | ((p[4] & 0x7E) >> 1); 876 } 877 else if (ie_p->ie_len == 5) { 878 dlci = (dlci << 13) | (p[4] & 0x7F) | ((p[5] & 0x7E) >> 1); 879 } 880 881 printf("DLCI %u: status %s%s", dlci, 882 p[ie_p->ie_len + 1] & 0x8 ? "New, " : "", 883 p[ie_p->ie_len + 1] & 0x2 ? "Active" : "Inactive"); 884 return 1; 885 } 886 887 return 0; 888 } 889