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 __RCSID("$NetBSD: print-fr.c,v 1.9 2017/09/08 14:01:13 christos Exp $"); 25 #endif 26 27 /* \summary: Frame Relay printer */ 28 29 #ifdef HAVE_CONFIG_H 30 #include "config.h" 31 #endif 32 33 #include <netdissect-stdinc.h> 34 35 #include <stdio.h> 36 #include <string.h> 37 38 #include "netdissect.h" 39 #include "addrtoname.h" 40 #include "ethertype.h" 41 #include "llc.h" 42 #include "nlpid.h" 43 #include "extract.h" 44 #include "oui.h" 45 46 static void frf15_print(netdissect_options *ndo, 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 78 static const struct 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 /* FRF.15 / FRF.16 */ 88 #define MFR_B_BIT 0x80 89 #define MFR_E_BIT 0x40 90 #define MFR_C_BIT 0x20 91 #define MFR_BEC_MASK (MFR_B_BIT | MFR_E_BIT | MFR_C_BIT) 92 #define MFR_CTRL_FRAME (MFR_B_BIT | MFR_E_BIT | MFR_C_BIT) 93 #define MFR_FRAG_FRAME (MFR_B_BIT | MFR_E_BIT ) 94 95 static const struct tok frf_flag_values[] = { 96 { MFR_B_BIT, "Begin" }, 97 { MFR_E_BIT, "End" }, 98 { MFR_C_BIT, "Control" }, 99 { 0, NULL } 100 }; 101 102 /* Finds out Q.922 address length, DLCI and flags. Returns 1 on success, 103 * 0 on invalid address, -1 on truncated packet 104 * save the flags dep. on address length 105 */ 106 static int parse_q922_addr(netdissect_options *ndo, 107 const u_char *p, u_int *dlci, 108 u_int *addr_len, uint8_t *flags, u_int length) 109 { 110 if (!ND_TTEST(p[0]) || length < 1) 111 return -1; 112 if ((p[0] & FR_EA_BIT)) 113 return 0; 114 115 if (!ND_TTEST(p[1]) || length < 2) 116 return -1; 117 *addr_len = 2; 118 *dlci = ((p[0] & 0xFC) << 2) | ((p[1] & 0xF0) >> 4); 119 120 flags[0] = p[0] & 0x02; /* populate the first flag fields */ 121 flags[1] = p[1] & 0x0c; 122 flags[2] = 0; /* clear the rest of the flags */ 123 flags[3] = 0; 124 125 if (p[1] & FR_EA_BIT) 126 return 1; /* 2-byte Q.922 address */ 127 128 p += 2; 129 length -= 2; 130 if (!ND_TTEST(p[0]) || length < 1) 131 return -1; 132 (*addr_len)++; /* 3- or 4-byte Q.922 address */ 133 if ((p[0] & FR_EA_BIT) == 0) { 134 *dlci = (*dlci << 7) | (p[0] >> 1); 135 (*addr_len)++; /* 4-byte Q.922 address */ 136 p++; 137 length--; 138 } 139 140 if (!ND_TTEST(p[0]) || length < 1) 141 return -1; 142 if ((p[0] & FR_EA_BIT) == 0) 143 return 0; /* more than 4 bytes of Q.922 address? */ 144 145 flags[3] = p[0] & 0x02; 146 147 *dlci = (*dlci << 6) | (p[0] >> 2); 148 149 return 1; 150 } 151 152 char * 153 q922_string(netdissect_options *ndo, const u_char *p, u_int length) 154 { 155 156 static u_int dlci, addr_len; 157 static uint8_t flags[4]; 158 static char buffer[sizeof("DLCI xxxxxxxxxx")]; 159 memset(buffer, 0, sizeof(buffer)); 160 161 if (parse_q922_addr(ndo, p, &dlci, &addr_len, flags, length) == 1){ 162 snprintf(buffer, sizeof(buffer), "DLCI %u", dlci); 163 } 164 165 return buffer; 166 } 167 168 169 /* Frame Relay packet structure, with flags and CRC removed 170 171 +---------------------------+ 172 | Q.922 Address* | 173 +-- --+ 174 | | 175 +---------------------------+ 176 | Control (UI = 0x03) | 177 +---------------------------+ 178 | Optional Pad (0x00) | 179 +---------------------------+ 180 | NLPID | 181 +---------------------------+ 182 | . | 183 | . | 184 | . | 185 | Data | 186 | . | 187 | . | 188 +---------------------------+ 189 190 * Q.922 addresses, as presently defined, are two octets and 191 contain a 10-bit DLCI. In some networks Q.922 addresses 192 may optionally be increased to three or four octets. 193 */ 194 195 static void 196 fr_hdr_print(netdissect_options *ndo, 197 int length, u_int addr_len, u_int dlci, uint8_t *flags, uint16_t nlpid) 198 { 199 if (ndo->ndo_qflag) { 200 ND_PRINT((ndo, "Q.922, DLCI %u, length %u: ", 201 dlci, 202 length)); 203 } else { 204 if (nlpid <= 0xff) /* if its smaller than 256 then its a NLPID */ 205 ND_PRINT((ndo, "Q.922, hdr-len %u, DLCI %u, Flags [%s], NLPID %s (0x%02x), length %u: ", 206 addr_len, 207 dlci, 208 bittok2str(fr_header_flag_values, "none", EXTRACT_32BITS(flags)), 209 tok2str(nlpid_values,"unknown", nlpid), 210 nlpid, 211 length)); 212 else /* must be an ethertype */ 213 ND_PRINT((ndo, "Q.922, hdr-len %u, DLCI %u, Flags [%s], cisco-ethertype %s (0x%04x), length %u: ", 214 addr_len, 215 dlci, 216 bittok2str(fr_header_flag_values, "none", EXTRACT_32BITS(flags)), 217 tok2str(ethertype_values, "unknown", nlpid), 218 nlpid, 219 length)); 220 } 221 } 222 223 u_int 224 fr_if_print(netdissect_options *ndo, 225 const struct pcap_pkthdr *h, register const u_char *p) 226 { 227 register u_int length = h->len; 228 register u_int caplen = h->caplen; 229 230 ND_TCHECK2(*p, 4); /* minimum frame header length */ 231 232 if ((length = fr_print(ndo, p, length)) == 0) 233 return (0); 234 else 235 return length; 236 trunc: 237 ND_PRINT((ndo, "[|fr]")); 238 return caplen; 239 } 240 241 u_int 242 fr_print(netdissect_options *ndo, 243 register const u_char *p, u_int length) 244 { 245 int ret; 246 uint16_t extracted_ethertype; 247 u_int dlci; 248 u_int addr_len; 249 uint16_t nlpid; 250 u_int hdr_len; 251 uint8_t flags[4]; 252 253 ret = parse_q922_addr(ndo, p, &dlci, &addr_len, flags, length); 254 if (ret == -1) 255 goto trunc; 256 if (ret == 0) { 257 ND_PRINT((ndo, "Q.922, invalid address")); 258 return 0; 259 } 260 261 ND_TCHECK(p[addr_len]); 262 if (length < addr_len + 1) 263 goto trunc; 264 265 if (p[addr_len] != LLC_UI && dlci != 0) { 266 /* 267 * Let's figure out if we have Cisco-style encapsulation, 268 * with an Ethernet type (Cisco HDLC type?) following the 269 * address. 270 */ 271 if (!ND_TTEST2(p[addr_len], 2) || length < addr_len + 2) { 272 /* no Ethertype */ 273 ND_PRINT((ndo, "UI %02x! ", p[addr_len])); 274 } else { 275 extracted_ethertype = EXTRACT_16BITS(p+addr_len); 276 277 if (ndo->ndo_eflag) 278 fr_hdr_print(ndo, length, addr_len, dlci, 279 flags, extracted_ethertype); 280 281 if (ethertype_print(ndo, extracted_ethertype, 282 p+addr_len+ETHERTYPE_LEN, 283 length-addr_len-ETHERTYPE_LEN, 284 ndo->ndo_snapend-p-addr_len-ETHERTYPE_LEN, 285 NULL, NULL) == 0) 286 /* ether_type not known, probably it wasn't one */ 287 ND_PRINT((ndo, "UI %02x! ", p[addr_len])); 288 else 289 return addr_len + 2; 290 } 291 } 292 293 ND_TCHECK(p[addr_len+1]); 294 if (length < addr_len + 2) 295 goto trunc; 296 297 if (p[addr_len + 1] == 0) { 298 /* 299 * Assume a pad byte after the control (UI) byte. 300 * A pad byte should only be used with 3-byte Q.922. 301 */ 302 if (addr_len != 3) 303 ND_PRINT((ndo, "Pad! ")); 304 hdr_len = addr_len + 1 /* UI */ + 1 /* pad */ + 1 /* NLPID */; 305 } else { 306 /* 307 * Not a pad byte. 308 * A pad byte should be used with 3-byte Q.922. 309 */ 310 if (addr_len == 3) 311 ND_PRINT((ndo, "No pad! ")); 312 hdr_len = addr_len + 1 /* UI */ + 1 /* NLPID */; 313 } 314 315 ND_TCHECK(p[hdr_len - 1]); 316 if (length < hdr_len) 317 goto trunc; 318 nlpid = p[hdr_len - 1]; 319 320 if (ndo->ndo_eflag) 321 fr_hdr_print(ndo, length, addr_len, dlci, flags, nlpid); 322 p += hdr_len; 323 length -= hdr_len; 324 325 switch (nlpid) { 326 case NLPID_IP: 327 ip_print(ndo, p, length); 328 break; 329 330 case NLPID_IP6: 331 ip6_print(ndo, p, length); 332 break; 333 334 case NLPID_CLNP: 335 case NLPID_ESIS: 336 case NLPID_ISIS: 337 isoclns_print(ndo, p - 1, length + 1); /* OSI printers need the NLPID field */ 338 break; 339 340 case NLPID_SNAP: 341 if (snap_print(ndo, p, length, ndo->ndo_snapend - p, NULL, NULL, 0) == 0) { 342 /* ether_type not known, print raw packet */ 343 if (!ndo->ndo_eflag) 344 fr_hdr_print(ndo, length + hdr_len, hdr_len, 345 dlci, flags, nlpid); 346 if (!ndo->ndo_suppress_default_print) 347 ND_DEFAULTPRINT(p - hdr_len, length + hdr_len); 348 } 349 break; 350 351 case NLPID_Q933: 352 q933_print(ndo, p, length); 353 break; 354 355 case NLPID_MFR: 356 frf15_print(ndo, p, length); 357 break; 358 359 case NLPID_PPP: 360 ppp_print(ndo, p, length); 361 break; 362 363 default: 364 if (!ndo->ndo_eflag) 365 fr_hdr_print(ndo, length + hdr_len, addr_len, 366 dlci, flags, nlpid); 367 if (!ndo->ndo_xflag) 368 ND_DEFAULTPRINT(p, length); 369 } 370 371 return hdr_len; 372 373 trunc: 374 ND_PRINT((ndo, "[|fr]")); 375 return 0; 376 377 } 378 379 u_int 380 mfr_if_print(netdissect_options *ndo, 381 const struct pcap_pkthdr *h, register const u_char *p) 382 { 383 register u_int length = h->len; 384 register u_int caplen = h->caplen; 385 386 ND_TCHECK2(*p, 2); /* minimum frame header length */ 387 388 if ((length = mfr_print(ndo, p, length)) == 0) 389 return (0); 390 else 391 return length; 392 trunc: 393 ND_PRINT((ndo, "[|mfr]")); 394 return caplen; 395 } 396 397 398 #define MFR_CTRL_MSG_ADD_LINK 1 399 #define MFR_CTRL_MSG_ADD_LINK_ACK 2 400 #define MFR_CTRL_MSG_ADD_LINK_REJ 3 401 #define MFR_CTRL_MSG_HELLO 4 402 #define MFR_CTRL_MSG_HELLO_ACK 5 403 #define MFR_CTRL_MSG_REMOVE_LINK 6 404 #define MFR_CTRL_MSG_REMOVE_LINK_ACK 7 405 406 static const struct tok mfr_ctrl_msg_values[] = { 407 { MFR_CTRL_MSG_ADD_LINK, "Add Link" }, 408 { MFR_CTRL_MSG_ADD_LINK_ACK, "Add Link ACK" }, 409 { MFR_CTRL_MSG_ADD_LINK_REJ, "Add Link Reject" }, 410 { MFR_CTRL_MSG_HELLO, "Hello" }, 411 { MFR_CTRL_MSG_HELLO_ACK, "Hello ACK" }, 412 { MFR_CTRL_MSG_REMOVE_LINK, "Remove Link" }, 413 { MFR_CTRL_MSG_REMOVE_LINK_ACK, "Remove Link ACK" }, 414 { 0, NULL } 415 }; 416 417 #define MFR_CTRL_IE_BUNDLE_ID 1 418 #define MFR_CTRL_IE_LINK_ID 2 419 #define MFR_CTRL_IE_MAGIC_NUM 3 420 #define MFR_CTRL_IE_TIMESTAMP 5 421 #define MFR_CTRL_IE_VENDOR_EXT 6 422 #define MFR_CTRL_IE_CAUSE 7 423 424 static const struct tok mfr_ctrl_ie_values[] = { 425 { MFR_CTRL_IE_BUNDLE_ID, "Bundle ID"}, 426 { MFR_CTRL_IE_LINK_ID, "Link ID"}, 427 { MFR_CTRL_IE_MAGIC_NUM, "Magic Number"}, 428 { MFR_CTRL_IE_TIMESTAMP, "Timestamp"}, 429 { MFR_CTRL_IE_VENDOR_EXT, "Vendor Extension"}, 430 { MFR_CTRL_IE_CAUSE, "Cause"}, 431 { 0, NULL } 432 }; 433 434 #define MFR_ID_STRING_MAXLEN 50 435 436 struct ie_tlv_header_t { 437 uint8_t ie_type; 438 uint8_t ie_len; 439 }; 440 441 u_int 442 mfr_print(netdissect_options *ndo, 443 register const u_char *p, u_int length) 444 { 445 u_int tlen,idx,hdr_len = 0; 446 uint16_t sequence_num; 447 uint8_t ie_type,ie_len; 448 const uint8_t *tptr; 449 450 451 /* 452 * FRF.16 Link Integrity Control Frame 453 * 454 * 7 6 5 4 3 2 1 0 455 * +----+----+----+----+----+----+----+----+ 456 * | B | E | C=1| 0 0 0 0 | EA | 457 * +----+----+----+----+----+----+----+----+ 458 * | 0 0 0 0 0 0 0 0 | 459 * +----+----+----+----+----+----+----+----+ 460 * | message type | 461 * +----+----+----+----+----+----+----+----+ 462 */ 463 464 ND_TCHECK2(*p, 4); /* minimum frame header length */ 465 466 if ((p[0] & MFR_BEC_MASK) == MFR_CTRL_FRAME && p[1] == 0) { 467 ND_PRINT((ndo, "FRF.16 Control, Flags [%s], %s, length %u", 468 bittok2str(frf_flag_values,"none",(p[0] & MFR_BEC_MASK)), 469 tok2str(mfr_ctrl_msg_values,"Unknown Message (0x%02x)",p[2]), 470 length)); 471 tptr = p + 3; 472 tlen = length -3; 473 hdr_len = 3; 474 475 if (!ndo->ndo_vflag) 476 return hdr_len; 477 478 while (tlen>sizeof(struct ie_tlv_header_t)) { 479 ND_TCHECK2(*tptr, sizeof(struct ie_tlv_header_t)); 480 ie_type=tptr[0]; 481 ie_len=tptr[1]; 482 483 ND_PRINT((ndo, "\n\tIE %s (%u), length %u: ", 484 tok2str(mfr_ctrl_ie_values,"Unknown",ie_type), 485 ie_type, 486 ie_len)); 487 488 /* infinite loop check */ 489 if (ie_type == 0 || ie_len <= sizeof(struct ie_tlv_header_t)) 490 return hdr_len; 491 492 ND_TCHECK2(*tptr, ie_len); 493 tptr+=sizeof(struct ie_tlv_header_t); 494 /* tlv len includes header */ 495 ie_len-=sizeof(struct ie_tlv_header_t); 496 tlen-=sizeof(struct ie_tlv_header_t); 497 498 switch (ie_type) { 499 500 case MFR_CTRL_IE_MAGIC_NUM: 501 ND_PRINT((ndo, "0x%08x", EXTRACT_32BITS(tptr))); 502 break; 503 504 case MFR_CTRL_IE_BUNDLE_ID: /* same message format */ 505 case MFR_CTRL_IE_LINK_ID: 506 for (idx = 0; idx < ie_len && idx < MFR_ID_STRING_MAXLEN; idx++) { 507 if (*(tptr+idx) != 0) /* don't print null termination */ 508 safeputchar(ndo, *(tptr + idx)); 509 else 510 break; 511 } 512 break; 513 514 case MFR_CTRL_IE_TIMESTAMP: 515 if (ie_len == sizeof(struct timeval)) { 516 ts_print(ndo, (const struct timeval *)tptr); 517 break; 518 } 519 /* fall through and hexdump if no unix timestamp */ 520 521 /* 522 * FIXME those are the defined IEs that lack a decoder 523 * you are welcome to contribute code ;-) 524 */ 525 526 case MFR_CTRL_IE_VENDOR_EXT: 527 case MFR_CTRL_IE_CAUSE: 528 529 default: 530 if (ndo->ndo_vflag <= 1) 531 print_unknown_data(ndo, tptr, "\n\t ", ie_len); 532 break; 533 } 534 535 /* do we want to see a hexdump of the IE ? */ 536 if (ndo->ndo_vflag > 1 ) 537 print_unknown_data(ndo, tptr, "\n\t ", ie_len); 538 539 tlen-=ie_len; 540 tptr+=ie_len; 541 } 542 return hdr_len; 543 } 544 /* 545 * FRF.16 Fragmentation Frame 546 * 547 * 7 6 5 4 3 2 1 0 548 * +----+----+----+----+----+----+----+----+ 549 * | B | E | C=0|seq. (high 4 bits) | EA | 550 * +----+----+----+----+----+----+----+----+ 551 * | sequence (low 8 bits) | 552 * +----+----+----+----+----+----+----+----+ 553 * | DLCI (6 bits) | CR | EA | 554 * +----+----+----+----+----+----+----+----+ 555 * | DLCI (4 bits) |FECN|BECN| DE | EA | 556 * +----+----+----+----+----+----+----+----+ 557 */ 558 559 sequence_num = (p[0]&0x1e)<<7 | p[1]; 560 /* whole packet or first fragment ? */ 561 if ((p[0] & MFR_BEC_MASK) == MFR_FRAG_FRAME || 562 (p[0] & MFR_BEC_MASK) == MFR_B_BIT) { 563 ND_PRINT((ndo, "FRF.16 Frag, seq %u, Flags [%s], ", 564 sequence_num, 565 bittok2str(frf_flag_values,"none",(p[0] & MFR_BEC_MASK)))); 566 hdr_len = 2; 567 fr_print(ndo, p+hdr_len,length-hdr_len); 568 return hdr_len; 569 } 570 571 /* must be a middle or the last fragment */ 572 ND_PRINT((ndo, "FRF.16 Frag, seq %u, Flags [%s]", 573 sequence_num, 574 bittok2str(frf_flag_values,"none",(p[0] & MFR_BEC_MASK)))); 575 print_unknown_data(ndo, p, "\n\t", length); 576 577 return hdr_len; 578 579 trunc: 580 ND_PRINT((ndo, "[|mfr]")); 581 return length; 582 } 583 584 /* an NLPID of 0xb1 indicates a 2-byte 585 * FRF.15 header 586 * 587 * 7 6 5 4 3 2 1 0 588 * +----+----+----+----+----+----+----+----+ 589 * ~ Q.922 header ~ 590 * +----+----+----+----+----+----+----+----+ 591 * | NLPID (8 bits) | NLPID=0xb1 592 * +----+----+----+----+----+----+----+----+ 593 * | B | E | C |seq. (high 4 bits) | R | 594 * +----+----+----+----+----+----+----+----+ 595 * | sequence (low 8 bits) | 596 * +----+----+----+----+----+----+----+----+ 597 */ 598 599 #define FR_FRF15_FRAGTYPE 0x01 600 601 static void 602 frf15_print(netdissect_options *ndo, 603 const u_char *p, u_int length) 604 { 605 uint16_t sequence_num, flags; 606 607 if (length < 2) 608 goto trunc; 609 ND_TCHECK2(*p, 2); 610 611 flags = p[0]&MFR_BEC_MASK; 612 sequence_num = (p[0]&0x1e)<<7 | p[1]; 613 614 ND_PRINT((ndo, "FRF.15, seq 0x%03x, Flags [%s],%s Fragmentation, length %u", 615 sequence_num, 616 bittok2str(frf_flag_values,"none",flags), 617 p[0]&FR_FRF15_FRAGTYPE ? "Interface" : "End-to-End", 618 length)); 619 620 /* TODO: 621 * depending on all permutations of the B, E and C bit 622 * dig as deep as we can - e.g. on the first (B) fragment 623 * there is enough payload to print the IP header 624 * on non (B) fragments it depends if the fragmentation 625 * model is end-to-end or interface based wether we want to print 626 * another Q.922 header 627 */ 628 return; 629 630 trunc: 631 ND_PRINT((ndo, "[|frf.15]")); 632 } 633 634 /* 635 * Q.933 decoding portion for framerelay specific. 636 */ 637 638 /* Q.933 packet format 639 Format of Other Protocols 640 using Q.933 NLPID 641 +-------------------------------+ 642 | Q.922 Address | 643 +---------------+---------------+ 644 |Control 0x03 | NLPID 0x08 | 645 +---------------+---------------+ 646 | L2 Protocol ID | 647 | octet 1 | octet 2 | 648 +-------------------------------+ 649 | L3 Protocol ID | 650 | octet 2 | octet 2 | 651 +-------------------------------+ 652 | Protocol Data | 653 +-------------------------------+ 654 | FCS | 655 +-------------------------------+ 656 */ 657 658 /* L2 (Octet 1)- Call Reference Usually is 0x0 */ 659 660 /* 661 * L2 (Octet 2)- Message Types definition 1 byte long. 662 */ 663 /* Call Establish */ 664 #define MSG_TYPE_ESC_TO_NATIONAL 0x00 665 #define MSG_TYPE_ALERT 0x01 666 #define MSG_TYPE_CALL_PROCEEDING 0x02 667 #define MSG_TYPE_CONNECT 0x07 668 #define MSG_TYPE_CONNECT_ACK 0x0F 669 #define MSG_TYPE_PROGRESS 0x03 670 #define MSG_TYPE_SETUP 0x05 671 /* Call Clear */ 672 #define MSG_TYPE_DISCONNECT 0x45 673 #define MSG_TYPE_RELEASE 0x4D 674 #define MSG_TYPE_RELEASE_COMPLETE 0x5A 675 #define MSG_TYPE_RESTART 0x46 676 #define MSG_TYPE_RESTART_ACK 0x4E 677 /* Status */ 678 #define MSG_TYPE_STATUS 0x7D 679 #define MSG_TYPE_STATUS_ENQ 0x75 680 681 static const struct tok fr_q933_msg_values[] = { 682 { MSG_TYPE_ESC_TO_NATIONAL, "ESC to National" }, 683 { MSG_TYPE_ALERT, "Alert" }, 684 { MSG_TYPE_CALL_PROCEEDING, "Call proceeding" }, 685 { MSG_TYPE_CONNECT, "Connect" }, 686 { MSG_TYPE_CONNECT_ACK, "Connect ACK" }, 687 { MSG_TYPE_PROGRESS, "Progress" }, 688 { MSG_TYPE_SETUP, "Setup" }, 689 { MSG_TYPE_DISCONNECT, "Disconnect" }, 690 { MSG_TYPE_RELEASE, "Release" }, 691 { MSG_TYPE_RELEASE_COMPLETE, "Release Complete" }, 692 { MSG_TYPE_RESTART, "Restart" }, 693 { MSG_TYPE_RESTART_ACK, "Restart ACK" }, 694 { MSG_TYPE_STATUS, "Status Reply" }, 695 { MSG_TYPE_STATUS_ENQ, "Status Enquiry" }, 696 { 0, NULL } 697 }; 698 699 #define IE_IS_SINGLE_OCTET(iecode) ((iecode) & 0x80) 700 #define IE_IS_SHIFT(iecode) (((iecode) & 0xF0) == 0x90) 701 #define IE_SHIFT_IS_NON_LOCKING(iecode) ((iecode) & 0x08) 702 #define IE_SHIFT_IS_LOCKING(iecode) (!(IE_SHIFT_IS_NON_LOCKING(iecode))) 703 #define IE_SHIFT_CODESET(iecode) ((iecode) & 0x07) 704 705 #define FR_LMI_ANSI_REPORT_TYPE_IE 0x01 706 #define FR_LMI_ANSI_LINK_VERIFY_IE_91 0x19 /* details? */ 707 #define FR_LMI_ANSI_LINK_VERIFY_IE 0x03 708 #define FR_LMI_ANSI_PVC_STATUS_IE 0x07 709 710 #define FR_LMI_CCITT_REPORT_TYPE_IE 0x51 711 #define FR_LMI_CCITT_LINK_VERIFY_IE 0x53 712 #define FR_LMI_CCITT_PVC_STATUS_IE 0x57 713 714 static const struct tok fr_q933_ie_values_codeset_0_5[] = { 715 { FR_LMI_ANSI_REPORT_TYPE_IE, "ANSI Report Type" }, 716 { FR_LMI_ANSI_LINK_VERIFY_IE_91, "ANSI Link Verify" }, 717 { FR_LMI_ANSI_LINK_VERIFY_IE, "ANSI Link Verify" }, 718 { FR_LMI_ANSI_PVC_STATUS_IE, "ANSI PVC Status" }, 719 { FR_LMI_CCITT_REPORT_TYPE_IE, "CCITT Report Type" }, 720 { FR_LMI_CCITT_LINK_VERIFY_IE, "CCITT Link Verify" }, 721 { FR_LMI_CCITT_PVC_STATUS_IE, "CCITT PVC Status" }, 722 { 0, NULL } 723 }; 724 725 #define FR_LMI_REPORT_TYPE_IE_FULL_STATUS 0 726 #define FR_LMI_REPORT_TYPE_IE_LINK_VERIFY 1 727 #define FR_LMI_REPORT_TYPE_IE_ASYNC_PVC 2 728 729 static const struct tok fr_lmi_report_type_ie_values[] = { 730 { FR_LMI_REPORT_TYPE_IE_FULL_STATUS, "Full Status" }, 731 { FR_LMI_REPORT_TYPE_IE_LINK_VERIFY, "Link verify" }, 732 { FR_LMI_REPORT_TYPE_IE_ASYNC_PVC, "Async PVC Status" }, 733 { 0, NULL } 734 }; 735 736 /* array of 16 codesets - currently we only support codepage 0 and 5 */ 737 static const struct tok *fr_q933_ie_codesets[] = { 738 fr_q933_ie_values_codeset_0_5, 739 NULL, 740 NULL, 741 NULL, 742 NULL, 743 fr_q933_ie_values_codeset_0_5, 744 NULL, 745 NULL, 746 NULL, 747 NULL, 748 NULL, 749 NULL, 750 NULL, 751 NULL, 752 NULL, 753 NULL 754 }; 755 756 static int fr_q933_print_ie_codeset_0_5(netdissect_options *ndo, u_int iecode, 757 u_int ielength, const u_char *p); 758 759 typedef int (*codeset_pr_func_t)(netdissect_options *, u_int iecode, 760 u_int ielength, const u_char *p); 761 762 /* array of 16 codesets - currently we only support codepage 0 and 5 */ 763 static const codeset_pr_func_t fr_q933_print_ie_codeset[] = { 764 fr_q933_print_ie_codeset_0_5, 765 NULL, 766 NULL, 767 NULL, 768 NULL, 769 fr_q933_print_ie_codeset_0_5, 770 NULL, 771 NULL, 772 NULL, 773 NULL, 774 NULL, 775 NULL, 776 NULL, 777 NULL, 778 NULL, 779 NULL 780 }; 781 782 /* 783 * ITU-T Q.933. 784 * 785 * p points to octet 2, the octet containing the length of the 786 * call reference value, so p[n] is octet n+2 ("octet X" is as 787 * used in Q.931/Q.933). 788 * 789 * XXX - actually used both for Q.931 and Q.933. 790 */ 791 void 792 q933_print(netdissect_options *ndo, 793 const u_char *p, u_int length) 794 { 795 u_int olen; 796 u_int call_ref_length, i; 797 uint8_t call_ref[15]; /* maximum length - length field is 4 bits */ 798 u_int msgtype; 799 u_int iecode; 800 u_int ielength; 801 u_int codeset = 0; 802 u_int is_ansi = 0; 803 u_int ie_is_known; 804 u_int non_locking_shift; 805 u_int unshift_codeset; 806 807 ND_PRINT((ndo, "%s", ndo->ndo_eflag ? "" : "Q.933")); 808 809 if (length == 0 || !ND_TTEST(*p)) { 810 if (!ndo->ndo_eflag) 811 ND_PRINT((ndo, ", ")); 812 ND_PRINT((ndo, "length %u", length)); 813 goto trunc; 814 } 815 816 /* 817 * Get the length of the call reference value. 818 */ 819 olen = length; /* preserve the original length for display */ 820 call_ref_length = (*p) & 0x0f; 821 p++; 822 length--; 823 824 /* 825 * Get the call reference value. 826 */ 827 for (i = 0; i < call_ref_length; i++) { 828 if (length == 0 || !ND_TTEST(*p)) { 829 if (!ndo->ndo_eflag) 830 ND_PRINT((ndo, ", ")); 831 ND_PRINT((ndo, "length %u", olen)); 832 goto trunc; 833 } 834 call_ref[i] = *p; 835 p++; 836 length--; 837 } 838 839 /* 840 * Get the message type. 841 */ 842 if (length == 0 || !ND_TTEST(*p)) { 843 if (!ndo->ndo_eflag) 844 ND_PRINT((ndo, ", ")); 845 ND_PRINT((ndo, "length %u", olen)); 846 goto trunc; 847 } 848 msgtype = *p; 849 p++; 850 length--; 851 852 /* 853 * Peek ahead to see if we start with a shift. 854 */ 855 non_locking_shift = 0; 856 unshift_codeset = codeset; 857 if (length != 0) { 858 if (!ND_TTEST(*p)) { 859 if (!ndo->ndo_eflag) 860 ND_PRINT((ndo, ", ")); 861 ND_PRINT((ndo, "length %u", olen)); 862 goto trunc; 863 } 864 iecode = *p; 865 if (IE_IS_SHIFT(iecode)) { 866 /* 867 * It's a shift. Skip over it. 868 */ 869 p++; 870 length--; 871 872 /* 873 * Get the codeset. 874 */ 875 codeset = IE_SHIFT_CODESET(iecode); 876 877 /* 878 * If it's a locking shift to codeset 5, 879 * mark this as ANSI. (XXX - 5 is actually 880 * for national variants in general, not 881 * the US variant in particular, but maybe 882 * this is more American exceptionalism. :-)) 883 */ 884 if (IE_SHIFT_IS_LOCKING(iecode)) { 885 /* 886 * It's a locking shift. 887 */ 888 if (codeset == 5) { 889 /* 890 * It's a locking shift to 891 * codeset 5, so this is 892 * T1.617 Annex D. 893 */ 894 is_ansi = 1; 895 } 896 } else { 897 /* 898 * It's a non-locking shift. 899 * Remember the current codeset, so we 900 * can revert to it after the next IE. 901 */ 902 non_locking_shift = 1; 903 unshift_codeset = 0; 904 } 905 } 906 } 907 908 /* printing out header part */ 909 if (!ndo->ndo_eflag) 910 ND_PRINT((ndo, ", ")); 911 ND_PRINT((ndo, "%s, codeset %u", is_ansi ? "ANSI" : "CCITT", codeset)); 912 913 if (call_ref_length != 0) { 914 ND_TCHECK(p[0]); 915 if (call_ref_length > 1 || p[0] != 0) { 916 /* 917 * Not a dummy call reference. 918 */ 919 ND_PRINT((ndo, ", Call Ref: 0x")); 920 for (i = 0; i < call_ref_length; i++) 921 ND_PRINT((ndo, "%02x", call_ref[i])); 922 } 923 } 924 if (ndo->ndo_vflag) { 925 ND_PRINT((ndo, ", %s (0x%02x), length %u", 926 tok2str(fr_q933_msg_values, 927 "unknown message", msgtype), 928 msgtype, 929 olen)); 930 } else { 931 ND_PRINT((ndo, ", %s", 932 tok2str(fr_q933_msg_values, 933 "unknown message 0x%02x", msgtype))); 934 } 935 936 /* Loop through the rest of the IEs */ 937 while (length != 0) { 938 /* 939 * What's the state of any non-locking shifts? 940 */ 941 if (non_locking_shift == 1) { 942 /* 943 * There's a non-locking shift in effect for 944 * this IE. Count it, so we reset the codeset 945 * before the next IE. 946 */ 947 non_locking_shift = 2; 948 } else if (non_locking_shift == 2) { 949 /* 950 * Unshift. 951 */ 952 codeset = unshift_codeset; 953 non_locking_shift = 0; 954 } 955 956 /* 957 * Get the first octet of the IE. 958 */ 959 if (!ND_TTEST(*p)) { 960 if (!ndo->ndo_vflag) { 961 ND_PRINT((ndo, ", length %u", olen)); 962 } 963 goto trunc; 964 } 965 iecode = *p; 966 p++; 967 length--; 968 969 /* Single-octet IE? */ 970 if (IE_IS_SINGLE_OCTET(iecode)) { 971 /* 972 * Yes. Is it a shift? 973 */ 974 if (IE_IS_SHIFT(iecode)) { 975 /* 976 * Yes. Is it locking? 977 */ 978 if (IE_SHIFT_IS_LOCKING(iecode)) { 979 /* 980 * Yes. 981 */ 982 non_locking_shift = 0; 983 } else { 984 /* 985 * No. Remember the current 986 * codeset, so we can revert 987 * to it after the next IE. 988 */ 989 non_locking_shift = 1; 990 unshift_codeset = codeset; 991 } 992 993 /* 994 * Get the codeset. 995 */ 996 codeset = IE_SHIFT_CODESET(iecode); 997 } 998 } else { 999 /* 1000 * No. Get the IE length. 1001 */ 1002 if (length == 0 || !ND_TTEST(*p)) { 1003 if (!ndo->ndo_vflag) { 1004 ND_PRINT((ndo, ", length %u", olen)); 1005 } 1006 goto trunc; 1007 } 1008 ielength = *p; 1009 p++; 1010 length--; 1011 1012 /* lets do the full IE parsing only in verbose mode 1013 * however some IEs (DLCI Status, Link Verify) 1014 * are also interesting in non-verbose mode */ 1015 if (ndo->ndo_vflag) { 1016 ND_PRINT((ndo, "\n\t%s IE (0x%02x), length %u: ", 1017 tok2str(fr_q933_ie_codesets[codeset], 1018 "unknown", iecode), 1019 iecode, 1020 ielength)); 1021 } 1022 1023 /* sanity checks */ 1024 if (iecode == 0 || ielength == 0) { 1025 return; 1026 } 1027 if (length < ielength || !ND_TTEST2(*p, ielength)) { 1028 if (!ndo->ndo_vflag) { 1029 ND_PRINT((ndo, ", length %u", olen)); 1030 } 1031 goto trunc; 1032 } 1033 1034 ie_is_known = 0; 1035 if (fr_q933_print_ie_codeset[codeset] != NULL) { 1036 ie_is_known = fr_q933_print_ie_codeset[codeset](ndo, iecode, ielength, p); 1037 } 1038 1039 if (ie_is_known) { 1040 /* 1041 * Known IE; do we want to see a hexdump 1042 * of it? 1043 */ 1044 if (ndo->ndo_vflag > 1) { 1045 /* Yes. */ 1046 print_unknown_data(ndo, p, "\n\t ", ielength); 1047 } 1048 } else { 1049 /* 1050 * Unknown IE; if we're printing verbosely, 1051 * print its content in hex. 1052 */ 1053 if (ndo->ndo_vflag >= 1) { 1054 print_unknown_data(ndo, p, "\n\t", ielength); 1055 } 1056 } 1057 1058 length -= ielength; 1059 p += ielength; 1060 } 1061 } 1062 if (!ndo->ndo_vflag) { 1063 ND_PRINT((ndo, ", length %u", olen)); 1064 } 1065 return; 1066 1067 trunc: 1068 ND_PRINT((ndo, "[|q.933]")); 1069 } 1070 1071 static int 1072 fr_q933_print_ie_codeset_0_5(netdissect_options *ndo, u_int iecode, 1073 u_int ielength, const u_char *p) 1074 { 1075 u_int dlci; 1076 1077 switch (iecode) { 1078 1079 case FR_LMI_ANSI_REPORT_TYPE_IE: /* fall through */ 1080 case FR_LMI_CCITT_REPORT_TYPE_IE: 1081 if (ielength < 1) { 1082 if (!ndo->ndo_vflag) { 1083 ND_PRINT((ndo, ", ")); 1084 } 1085 ND_PRINT((ndo, "Invalid REPORT TYPE IE")); 1086 return 1; 1087 } 1088 if (ndo->ndo_vflag) { 1089 ND_PRINT((ndo, "%s (%u)", 1090 tok2str(fr_lmi_report_type_ie_values,"unknown",p[0]), 1091 p[0])); 1092 } 1093 return 1; 1094 1095 case FR_LMI_ANSI_LINK_VERIFY_IE: /* fall through */ 1096 case FR_LMI_CCITT_LINK_VERIFY_IE: 1097 case FR_LMI_ANSI_LINK_VERIFY_IE_91: 1098 if (!ndo->ndo_vflag) { 1099 ND_PRINT((ndo, ", ")); 1100 } 1101 if (ielength < 2) { 1102 ND_PRINT((ndo, "Invalid LINK VERIFY IE")); 1103 return 1; 1104 } 1105 ND_PRINT((ndo, "TX Seq: %3d, RX Seq: %3d", p[0], p[1])); 1106 return 1; 1107 1108 case FR_LMI_ANSI_PVC_STATUS_IE: /* fall through */ 1109 case FR_LMI_CCITT_PVC_STATUS_IE: 1110 if (!ndo->ndo_vflag) { 1111 ND_PRINT((ndo, ", ")); 1112 } 1113 /* now parse the DLCI information element. */ 1114 if ((ielength < 3) || 1115 (p[0] & 0x80) || 1116 ((ielength == 3) && !(p[1] & 0x80)) || 1117 ((ielength == 4) && ((p[1] & 0x80) || !(p[2] & 0x80))) || 1118 ((ielength == 5) && ((p[1] & 0x80) || (p[2] & 0x80) || 1119 !(p[3] & 0x80))) || 1120 (ielength > 5) || 1121 !(p[ielength - 1] & 0x80)) { 1122 ND_PRINT((ndo, "Invalid DLCI in PVC STATUS IE")); 1123 return 1; 1124 } 1125 1126 dlci = ((p[0] & 0x3F) << 4) | ((p[1] & 0x78) >> 3); 1127 if (ielength == 4) { 1128 dlci = (dlci << 6) | ((p[2] & 0x7E) >> 1); 1129 } 1130 else if (ielength == 5) { 1131 dlci = (dlci << 13) | (p[2] & 0x7F) | ((p[3] & 0x7E) >> 1); 1132 } 1133 1134 ND_PRINT((ndo, "DLCI %u: status %s%s", dlci, 1135 p[ielength - 1] & 0x8 ? "New, " : "", 1136 p[ielength - 1] & 0x2 ? "Active" : "Inactive")); 1137 return 1; 1138 } 1139 1140 return 0; 1141 } 1142 /* 1143 * Local Variables: 1144 * c-style: whitesmith 1145 * c-basic-offset: 8 1146 * End: 1147 */ 1148