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.10 2019/10/01 16:06:16 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 if (length < 4) { 466 ND_PRINT((ndo, "Message too short (%u bytes)", length)); 467 return length; 468 } 469 470 if ((p[0] & MFR_BEC_MASK) == MFR_CTRL_FRAME && p[1] == 0) { 471 ND_PRINT((ndo, "FRF.16 Control, Flags [%s], %s, length %u", 472 bittok2str(frf_flag_values,"none",(p[0] & MFR_BEC_MASK)), 473 tok2str(mfr_ctrl_msg_values,"Unknown Message (0x%02x)",p[2]), 474 length)); 475 tptr = p + 3; 476 tlen = length -3; 477 hdr_len = 3; 478 479 if (!ndo->ndo_vflag) 480 return hdr_len; 481 482 while (tlen>sizeof(struct ie_tlv_header_t)) { 483 ND_TCHECK2(*tptr, sizeof(struct ie_tlv_header_t)); 484 ie_type=tptr[0]; 485 ie_len=tptr[1]; 486 487 ND_PRINT((ndo, "\n\tIE %s (%u), length %u: ", 488 tok2str(mfr_ctrl_ie_values,"Unknown",ie_type), 489 ie_type, 490 ie_len)); 491 492 /* infinite loop check */ 493 if (ie_type == 0 || ie_len <= sizeof(struct ie_tlv_header_t)) 494 return hdr_len; 495 496 ND_TCHECK2(*tptr, ie_len); 497 tptr+=sizeof(struct ie_tlv_header_t); 498 /* tlv len includes header */ 499 ie_len-=sizeof(struct ie_tlv_header_t); 500 tlen-=sizeof(struct ie_tlv_header_t); 501 502 switch (ie_type) { 503 504 case MFR_CTRL_IE_MAGIC_NUM: 505 /* FRF.16.1 Section 3.4.3 Magic Number Information Element */ 506 if (ie_len != 4) { 507 ND_PRINT((ndo, "(invalid length)")); 508 break; 509 } 510 ND_PRINT((ndo, "0x%08x", EXTRACT_32BITS(tptr))); 511 break; 512 513 case MFR_CTRL_IE_BUNDLE_ID: /* same message format */ 514 case MFR_CTRL_IE_LINK_ID: 515 for (idx = 0; idx < ie_len && idx < MFR_ID_STRING_MAXLEN; idx++) { 516 if (*(tptr+idx) != 0) /* don't print null termination */ 517 safeputchar(ndo, *(tptr + idx)); 518 else 519 break; 520 } 521 break; 522 523 case MFR_CTRL_IE_TIMESTAMP: 524 if (ie_len == sizeof(struct timeval)) { 525 ts_print(ndo, (const struct timeval *)tptr); 526 break; 527 } 528 /* fall through and hexdump if no unix timestamp */ 529 530 /* 531 * FIXME those are the defined IEs that lack a decoder 532 * you are welcome to contribute code ;-) 533 */ 534 535 case MFR_CTRL_IE_VENDOR_EXT: 536 case MFR_CTRL_IE_CAUSE: 537 538 default: 539 if (ndo->ndo_vflag <= 1) 540 print_unknown_data(ndo, tptr, "\n\t ", ie_len); 541 break; 542 } 543 544 /* do we want to see a hexdump of the IE ? */ 545 if (ndo->ndo_vflag > 1 ) 546 print_unknown_data(ndo, tptr, "\n\t ", ie_len); 547 548 tlen-=ie_len; 549 tptr+=ie_len; 550 } 551 return hdr_len; 552 } 553 /* 554 * FRF.16 Fragmentation Frame 555 * 556 * 7 6 5 4 3 2 1 0 557 * +----+----+----+----+----+----+----+----+ 558 * | B | E | C=0|seq. (high 4 bits) | EA | 559 * +----+----+----+----+----+----+----+----+ 560 * | sequence (low 8 bits) | 561 * +----+----+----+----+----+----+----+----+ 562 * | DLCI (6 bits) | CR | EA | 563 * +----+----+----+----+----+----+----+----+ 564 * | DLCI (4 bits) |FECN|BECN| DE | EA | 565 * +----+----+----+----+----+----+----+----+ 566 */ 567 568 sequence_num = (p[0]&0x1e)<<7 | p[1]; 569 /* whole packet or first fragment ? */ 570 if ((p[0] & MFR_BEC_MASK) == MFR_FRAG_FRAME || 571 (p[0] & MFR_BEC_MASK) == MFR_B_BIT) { 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 hdr_len = 2; 576 fr_print(ndo, p+hdr_len,length-hdr_len); 577 return hdr_len; 578 } 579 580 /* must be a middle or the last fragment */ 581 ND_PRINT((ndo, "FRF.16 Frag, seq %u, Flags [%s]", 582 sequence_num, 583 bittok2str(frf_flag_values,"none",(p[0] & MFR_BEC_MASK)))); 584 print_unknown_data(ndo, p, "\n\t", length); 585 586 return hdr_len; 587 588 trunc: 589 ND_PRINT((ndo, "[|mfr]")); 590 return length; 591 } 592 593 /* an NLPID of 0xb1 indicates a 2-byte 594 * FRF.15 header 595 * 596 * 7 6 5 4 3 2 1 0 597 * +----+----+----+----+----+----+----+----+ 598 * ~ Q.922 header ~ 599 * +----+----+----+----+----+----+----+----+ 600 * | NLPID (8 bits) | NLPID=0xb1 601 * +----+----+----+----+----+----+----+----+ 602 * | B | E | C |seq. (high 4 bits) | R | 603 * +----+----+----+----+----+----+----+----+ 604 * | sequence (low 8 bits) | 605 * +----+----+----+----+----+----+----+----+ 606 */ 607 608 #define FR_FRF15_FRAGTYPE 0x01 609 610 static void 611 frf15_print(netdissect_options *ndo, 612 const u_char *p, u_int length) 613 { 614 uint16_t sequence_num, flags; 615 616 if (length < 2) 617 goto trunc; 618 ND_TCHECK2(*p, 2); 619 620 flags = p[0]&MFR_BEC_MASK; 621 sequence_num = (p[0]&0x1e)<<7 | p[1]; 622 623 ND_PRINT((ndo, "FRF.15, seq 0x%03x, Flags [%s],%s Fragmentation, length %u", 624 sequence_num, 625 bittok2str(frf_flag_values,"none",flags), 626 p[0]&FR_FRF15_FRAGTYPE ? "Interface" : "End-to-End", 627 length)); 628 629 /* TODO: 630 * depending on all permutations of the B, E and C bit 631 * dig as deep as we can - e.g. on the first (B) fragment 632 * there is enough payload to print the IP header 633 * on non (B) fragments it depends if the fragmentation 634 * model is end-to-end or interface based wether we want to print 635 * another Q.922 header 636 */ 637 return; 638 639 trunc: 640 ND_PRINT((ndo, "[|frf.15]")); 641 } 642 643 /* 644 * Q.933 decoding portion for framerelay specific. 645 */ 646 647 /* Q.933 packet format 648 Format of Other Protocols 649 using Q.933 NLPID 650 +-------------------------------+ 651 | Q.922 Address | 652 +---------------+---------------+ 653 |Control 0x03 | NLPID 0x08 | 654 +---------------+---------------+ 655 | L2 Protocol ID | 656 | octet 1 | octet 2 | 657 +-------------------------------+ 658 | L3 Protocol ID | 659 | octet 2 | octet 2 | 660 +-------------------------------+ 661 | Protocol Data | 662 +-------------------------------+ 663 | FCS | 664 +-------------------------------+ 665 */ 666 667 /* L2 (Octet 1)- Call Reference Usually is 0x0 */ 668 669 /* 670 * L2 (Octet 2)- Message Types definition 1 byte long. 671 */ 672 /* Call Establish */ 673 #define MSG_TYPE_ESC_TO_NATIONAL 0x00 674 #define MSG_TYPE_ALERT 0x01 675 #define MSG_TYPE_CALL_PROCEEDING 0x02 676 #define MSG_TYPE_CONNECT 0x07 677 #define MSG_TYPE_CONNECT_ACK 0x0F 678 #define MSG_TYPE_PROGRESS 0x03 679 #define MSG_TYPE_SETUP 0x05 680 /* Call Clear */ 681 #define MSG_TYPE_DISCONNECT 0x45 682 #define MSG_TYPE_RELEASE 0x4D 683 #define MSG_TYPE_RELEASE_COMPLETE 0x5A 684 #define MSG_TYPE_RESTART 0x46 685 #define MSG_TYPE_RESTART_ACK 0x4E 686 /* Status */ 687 #define MSG_TYPE_STATUS 0x7D 688 #define MSG_TYPE_STATUS_ENQ 0x75 689 690 static const struct tok fr_q933_msg_values[] = { 691 { MSG_TYPE_ESC_TO_NATIONAL, "ESC to National" }, 692 { MSG_TYPE_ALERT, "Alert" }, 693 { MSG_TYPE_CALL_PROCEEDING, "Call proceeding" }, 694 { MSG_TYPE_CONNECT, "Connect" }, 695 { MSG_TYPE_CONNECT_ACK, "Connect ACK" }, 696 { MSG_TYPE_PROGRESS, "Progress" }, 697 { MSG_TYPE_SETUP, "Setup" }, 698 { MSG_TYPE_DISCONNECT, "Disconnect" }, 699 { MSG_TYPE_RELEASE, "Release" }, 700 { MSG_TYPE_RELEASE_COMPLETE, "Release Complete" }, 701 { MSG_TYPE_RESTART, "Restart" }, 702 { MSG_TYPE_RESTART_ACK, "Restart ACK" }, 703 { MSG_TYPE_STATUS, "Status Reply" }, 704 { MSG_TYPE_STATUS_ENQ, "Status Enquiry" }, 705 { 0, NULL } 706 }; 707 708 #define IE_IS_SINGLE_OCTET(iecode) ((iecode) & 0x80) 709 #define IE_IS_SHIFT(iecode) (((iecode) & 0xF0) == 0x90) 710 #define IE_SHIFT_IS_NON_LOCKING(iecode) ((iecode) & 0x08) 711 #define IE_SHIFT_IS_LOCKING(iecode) (!(IE_SHIFT_IS_NON_LOCKING(iecode))) 712 #define IE_SHIFT_CODESET(iecode) ((iecode) & 0x07) 713 714 #define FR_LMI_ANSI_REPORT_TYPE_IE 0x01 715 #define FR_LMI_ANSI_LINK_VERIFY_IE_91 0x19 /* details? */ 716 #define FR_LMI_ANSI_LINK_VERIFY_IE 0x03 717 #define FR_LMI_ANSI_PVC_STATUS_IE 0x07 718 719 #define FR_LMI_CCITT_REPORT_TYPE_IE 0x51 720 #define FR_LMI_CCITT_LINK_VERIFY_IE 0x53 721 #define FR_LMI_CCITT_PVC_STATUS_IE 0x57 722 723 static const struct tok fr_q933_ie_values_codeset_0_5[] = { 724 { FR_LMI_ANSI_REPORT_TYPE_IE, "ANSI Report Type" }, 725 { FR_LMI_ANSI_LINK_VERIFY_IE_91, "ANSI Link Verify" }, 726 { FR_LMI_ANSI_LINK_VERIFY_IE, "ANSI Link Verify" }, 727 { FR_LMI_ANSI_PVC_STATUS_IE, "ANSI PVC Status" }, 728 { FR_LMI_CCITT_REPORT_TYPE_IE, "CCITT Report Type" }, 729 { FR_LMI_CCITT_LINK_VERIFY_IE, "CCITT Link Verify" }, 730 { FR_LMI_CCITT_PVC_STATUS_IE, "CCITT PVC Status" }, 731 { 0, NULL } 732 }; 733 734 #define FR_LMI_REPORT_TYPE_IE_FULL_STATUS 0 735 #define FR_LMI_REPORT_TYPE_IE_LINK_VERIFY 1 736 #define FR_LMI_REPORT_TYPE_IE_ASYNC_PVC 2 737 738 static const struct tok fr_lmi_report_type_ie_values[] = { 739 { FR_LMI_REPORT_TYPE_IE_FULL_STATUS, "Full Status" }, 740 { FR_LMI_REPORT_TYPE_IE_LINK_VERIFY, "Link verify" }, 741 { FR_LMI_REPORT_TYPE_IE_ASYNC_PVC, "Async PVC Status" }, 742 { 0, NULL } 743 }; 744 745 /* array of 16 codesets - currently we only support codepage 0 and 5 */ 746 static const struct tok *fr_q933_ie_codesets[] = { 747 fr_q933_ie_values_codeset_0_5, 748 NULL, 749 NULL, 750 NULL, 751 NULL, 752 fr_q933_ie_values_codeset_0_5, 753 NULL, 754 NULL, 755 NULL, 756 NULL, 757 NULL, 758 NULL, 759 NULL, 760 NULL, 761 NULL, 762 NULL 763 }; 764 765 static int fr_q933_print_ie_codeset_0_5(netdissect_options *ndo, u_int iecode, 766 u_int ielength, const u_char *p); 767 768 typedef int (*codeset_pr_func_t)(netdissect_options *, u_int iecode, 769 u_int ielength, const u_char *p); 770 771 /* array of 16 codesets - currently we only support codepage 0 and 5 */ 772 static const codeset_pr_func_t fr_q933_print_ie_codeset[] = { 773 fr_q933_print_ie_codeset_0_5, 774 NULL, 775 NULL, 776 NULL, 777 NULL, 778 fr_q933_print_ie_codeset_0_5, 779 NULL, 780 NULL, 781 NULL, 782 NULL, 783 NULL, 784 NULL, 785 NULL, 786 NULL, 787 NULL, 788 NULL 789 }; 790 791 /* 792 * ITU-T Q.933. 793 * 794 * p points to octet 2, the octet containing the length of the 795 * call reference value, so p[n] is octet n+2 ("octet X" is as 796 * used in Q.931/Q.933). 797 * 798 * XXX - actually used both for Q.931 and Q.933. 799 */ 800 void 801 q933_print(netdissect_options *ndo, 802 const u_char *p, u_int length) 803 { 804 u_int olen; 805 u_int call_ref_length, i; 806 uint8_t call_ref[15]; /* maximum length - length field is 4 bits */ 807 u_int msgtype; 808 u_int iecode; 809 u_int ielength; 810 u_int codeset = 0; 811 u_int is_ansi = 0; 812 u_int ie_is_known; 813 u_int non_locking_shift; 814 u_int unshift_codeset; 815 816 ND_PRINT((ndo, "%s", ndo->ndo_eflag ? "" : "Q.933")); 817 818 if (length == 0 || !ND_TTEST(*p)) { 819 if (!ndo->ndo_eflag) 820 ND_PRINT((ndo, ", ")); 821 ND_PRINT((ndo, "length %u", length)); 822 goto trunc; 823 } 824 825 /* 826 * Get the length of the call reference value. 827 */ 828 olen = length; /* preserve the original length for display */ 829 call_ref_length = (*p) & 0x0f; 830 p++; 831 length--; 832 833 /* 834 * Get the call reference value. 835 */ 836 for (i = 0; i < call_ref_length; i++) { 837 if (length == 0 || !ND_TTEST(*p)) { 838 if (!ndo->ndo_eflag) 839 ND_PRINT((ndo, ", ")); 840 ND_PRINT((ndo, "length %u", olen)); 841 goto trunc; 842 } 843 call_ref[i] = *p; 844 p++; 845 length--; 846 } 847 848 /* 849 * Get the message type. 850 */ 851 if (length == 0 || !ND_TTEST(*p)) { 852 if (!ndo->ndo_eflag) 853 ND_PRINT((ndo, ", ")); 854 ND_PRINT((ndo, "length %u", olen)); 855 goto trunc; 856 } 857 msgtype = *p; 858 p++; 859 length--; 860 861 /* 862 * Peek ahead to see if we start with a shift. 863 */ 864 non_locking_shift = 0; 865 unshift_codeset = codeset; 866 if (length != 0) { 867 if (!ND_TTEST(*p)) { 868 if (!ndo->ndo_eflag) 869 ND_PRINT((ndo, ", ")); 870 ND_PRINT((ndo, "length %u", olen)); 871 goto trunc; 872 } 873 iecode = *p; 874 if (IE_IS_SHIFT(iecode)) { 875 /* 876 * It's a shift. Skip over it. 877 */ 878 p++; 879 length--; 880 881 /* 882 * Get the codeset. 883 */ 884 codeset = IE_SHIFT_CODESET(iecode); 885 886 /* 887 * If it's a locking shift to codeset 5, 888 * mark this as ANSI. (XXX - 5 is actually 889 * for national variants in general, not 890 * the US variant in particular, but maybe 891 * this is more American exceptionalism. :-)) 892 */ 893 if (IE_SHIFT_IS_LOCKING(iecode)) { 894 /* 895 * It's a locking shift. 896 */ 897 if (codeset == 5) { 898 /* 899 * It's a locking shift to 900 * codeset 5, so this is 901 * T1.617 Annex D. 902 */ 903 is_ansi = 1; 904 } 905 } else { 906 /* 907 * It's a non-locking shift. 908 * Remember the current codeset, so we 909 * can revert to it after the next IE. 910 */ 911 non_locking_shift = 1; 912 unshift_codeset = 0; 913 } 914 } 915 } 916 917 /* printing out header part */ 918 if (!ndo->ndo_eflag) 919 ND_PRINT((ndo, ", ")); 920 ND_PRINT((ndo, "%s, codeset %u", is_ansi ? "ANSI" : "CCITT", codeset)); 921 922 if (call_ref_length != 0) { 923 ND_TCHECK(p[0]); 924 if (call_ref_length > 1 || p[0] != 0) { 925 /* 926 * Not a dummy call reference. 927 */ 928 ND_PRINT((ndo, ", Call Ref: 0x")); 929 for (i = 0; i < call_ref_length; i++) 930 ND_PRINT((ndo, "%02x", call_ref[i])); 931 } 932 } 933 if (ndo->ndo_vflag) { 934 ND_PRINT((ndo, ", %s (0x%02x), length %u", 935 tok2str(fr_q933_msg_values, 936 "unknown message", msgtype), 937 msgtype, 938 olen)); 939 } else { 940 ND_PRINT((ndo, ", %s", 941 tok2str(fr_q933_msg_values, 942 "unknown message 0x%02x", msgtype))); 943 } 944 945 /* Loop through the rest of the IEs */ 946 while (length != 0) { 947 /* 948 * What's the state of any non-locking shifts? 949 */ 950 if (non_locking_shift == 1) { 951 /* 952 * There's a non-locking shift in effect for 953 * this IE. Count it, so we reset the codeset 954 * before the next IE. 955 */ 956 non_locking_shift = 2; 957 } else if (non_locking_shift == 2) { 958 /* 959 * Unshift. 960 */ 961 codeset = unshift_codeset; 962 non_locking_shift = 0; 963 } 964 965 /* 966 * Get the first octet of the IE. 967 */ 968 if (!ND_TTEST(*p)) { 969 if (!ndo->ndo_vflag) { 970 ND_PRINT((ndo, ", length %u", olen)); 971 } 972 goto trunc; 973 } 974 iecode = *p; 975 p++; 976 length--; 977 978 /* Single-octet IE? */ 979 if (IE_IS_SINGLE_OCTET(iecode)) { 980 /* 981 * Yes. Is it a shift? 982 */ 983 if (IE_IS_SHIFT(iecode)) { 984 /* 985 * Yes. Is it locking? 986 */ 987 if (IE_SHIFT_IS_LOCKING(iecode)) { 988 /* 989 * Yes. 990 */ 991 non_locking_shift = 0; 992 } else { 993 /* 994 * No. Remember the current 995 * codeset, so we can revert 996 * to it after the next IE. 997 */ 998 non_locking_shift = 1; 999 unshift_codeset = codeset; 1000 } 1001 1002 /* 1003 * Get the codeset. 1004 */ 1005 codeset = IE_SHIFT_CODESET(iecode); 1006 } 1007 } else { 1008 /* 1009 * No. Get the IE length. 1010 */ 1011 if (length == 0 || !ND_TTEST(*p)) { 1012 if (!ndo->ndo_vflag) { 1013 ND_PRINT((ndo, ", length %u", olen)); 1014 } 1015 goto trunc; 1016 } 1017 ielength = *p; 1018 p++; 1019 length--; 1020 1021 /* lets do the full IE parsing only in verbose mode 1022 * however some IEs (DLCI Status, Link Verify) 1023 * are also interesting in non-verbose mode */ 1024 if (ndo->ndo_vflag) { 1025 ND_PRINT((ndo, "\n\t%s IE (0x%02x), length %u: ", 1026 tok2str(fr_q933_ie_codesets[codeset], 1027 "unknown", iecode), 1028 iecode, 1029 ielength)); 1030 } 1031 1032 /* sanity checks */ 1033 if (iecode == 0 || ielength == 0) { 1034 return; 1035 } 1036 if (length < ielength || !ND_TTEST2(*p, ielength)) { 1037 if (!ndo->ndo_vflag) { 1038 ND_PRINT((ndo, ", length %u", olen)); 1039 } 1040 goto trunc; 1041 } 1042 1043 ie_is_known = 0; 1044 if (fr_q933_print_ie_codeset[codeset] != NULL) { 1045 ie_is_known = fr_q933_print_ie_codeset[codeset](ndo, iecode, ielength, p); 1046 } 1047 1048 if (ie_is_known) { 1049 /* 1050 * Known IE; do we want to see a hexdump 1051 * of it? 1052 */ 1053 if (ndo->ndo_vflag > 1) { 1054 /* Yes. */ 1055 print_unknown_data(ndo, p, "\n\t ", ielength); 1056 } 1057 } else { 1058 /* 1059 * Unknown IE; if we're printing verbosely, 1060 * print its content in hex. 1061 */ 1062 if (ndo->ndo_vflag >= 1) { 1063 print_unknown_data(ndo, p, "\n\t", ielength); 1064 } 1065 } 1066 1067 length -= ielength; 1068 p += ielength; 1069 } 1070 } 1071 if (!ndo->ndo_vflag) { 1072 ND_PRINT((ndo, ", length %u", olen)); 1073 } 1074 return; 1075 1076 trunc: 1077 ND_PRINT((ndo, "[|q.933]")); 1078 } 1079 1080 static int 1081 fr_q933_print_ie_codeset_0_5(netdissect_options *ndo, u_int iecode, 1082 u_int ielength, const u_char *p) 1083 { 1084 u_int dlci; 1085 1086 switch (iecode) { 1087 1088 case FR_LMI_ANSI_REPORT_TYPE_IE: /* fall through */ 1089 case FR_LMI_CCITT_REPORT_TYPE_IE: 1090 if (ielength < 1) { 1091 if (!ndo->ndo_vflag) { 1092 ND_PRINT((ndo, ", ")); 1093 } 1094 ND_PRINT((ndo, "Invalid REPORT TYPE IE")); 1095 return 1; 1096 } 1097 if (ndo->ndo_vflag) { 1098 ND_PRINT((ndo, "%s (%u)", 1099 tok2str(fr_lmi_report_type_ie_values,"unknown",p[0]), 1100 p[0])); 1101 } 1102 return 1; 1103 1104 case FR_LMI_ANSI_LINK_VERIFY_IE: /* fall through */ 1105 case FR_LMI_CCITT_LINK_VERIFY_IE: 1106 case FR_LMI_ANSI_LINK_VERIFY_IE_91: 1107 if (!ndo->ndo_vflag) { 1108 ND_PRINT((ndo, ", ")); 1109 } 1110 if (ielength < 2) { 1111 ND_PRINT((ndo, "Invalid LINK VERIFY IE")); 1112 return 1; 1113 } 1114 ND_PRINT((ndo, "TX Seq: %3d, RX Seq: %3d", p[0], p[1])); 1115 return 1; 1116 1117 case FR_LMI_ANSI_PVC_STATUS_IE: /* fall through */ 1118 case FR_LMI_CCITT_PVC_STATUS_IE: 1119 if (!ndo->ndo_vflag) { 1120 ND_PRINT((ndo, ", ")); 1121 } 1122 /* now parse the DLCI information element. */ 1123 if ((ielength < 3) || 1124 (p[0] & 0x80) || 1125 ((ielength == 3) && !(p[1] & 0x80)) || 1126 ((ielength == 4) && ((p[1] & 0x80) || !(p[2] & 0x80))) || 1127 ((ielength == 5) && ((p[1] & 0x80) || (p[2] & 0x80) || 1128 !(p[3] & 0x80))) || 1129 (ielength > 5) || 1130 !(p[ielength - 1] & 0x80)) { 1131 ND_PRINT((ndo, "Invalid DLCI in PVC STATUS IE")); 1132 return 1; 1133 } 1134 1135 dlci = ((p[0] & 0x3F) << 4) | ((p[1] & 0x78) >> 3); 1136 if (ielength == 4) { 1137 dlci = (dlci << 6) | ((p[2] & 0x7E) >> 1); 1138 } 1139 else if (ielength == 5) { 1140 dlci = (dlci << 13) | (p[2] & 0x7F) | ((p[3] & 0x7E) >> 1); 1141 } 1142 1143 ND_PRINT((ndo, "DLCI %u: status %s%s", dlci, 1144 p[ielength - 1] & 0x8 ? "New, " : "", 1145 p[ielength - 1] & 0x2 ? "Active" : "Inactive")); 1146 return 1; 1147 } 1148 1149 return 0; 1150 } 1151 /* 1152 * Local Variables: 1153 * c-style: whitesmith 1154 * c-basic-offset: 8 1155 * End: 1156 */ 1157