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