1 /* 2 * Copyright (c) 1994, 1995, 1996, 1997 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-atm.c,v 1.9 2017/09/08 14:01:12 christos Exp $"); 25 #endif 26 27 /* \summary: Asynchronous Transfer Mode (ATM) printer */ 28 29 #ifdef HAVE_CONFIG_H 30 #include "config.h" 31 #endif 32 33 #include <netdissect-stdinc.h> 34 35 #include "netdissect.h" 36 #include "extract.h" 37 #include "addrtoname.h" 38 #include "atm.h" 39 #include "llc.h" 40 41 /* start of the original atmuni31.h */ 42 43 /* 44 * Copyright (c) 1997 Yen Yen Lim and North Dakota State University 45 * All rights reserved. 46 * 47 * Redistribution and use in source and binary forms, with or without 48 * modification, are permitted provided that the following conditions 49 * are met: 50 * 1. Redistributions of source code must retain the above copyright 51 * notice, this list of conditions and the following disclaimer. 52 * 2. Redistributions in binary form must reproduce the above copyright 53 * notice, this list of conditions and the following disclaimer in the 54 * documentation and/or other materials provided with the distribution. 55 * 3. All advertising materials mentioning features or use of this software 56 * must display the following acknowledgement: 57 * This product includes software developed by Yen Yen Lim and 58 North Dakota State University 59 * 4. The name of the author may not be used to endorse or promote products 60 * derived from this software without specific prior written permission. 61 * 62 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 63 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 64 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 65 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 66 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 67 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 68 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 69 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 70 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 71 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 72 * POSSIBILITY OF SUCH DAMAGE. 73 */ 74 75 /* Based on UNI3.1 standard by ATM Forum */ 76 77 /* ATM traffic types based on VPI=0 and (the following VCI */ 78 #define VCI_PPC 0x05 /* Point-to-point signal msg */ 79 #define VCI_BCC 0x02 /* Broadcast signal msg */ 80 #define VCI_OAMF4SC 0x03 /* Segment OAM F4 flow cell */ 81 #define VCI_OAMF4EC 0x04 /* End-to-end OAM F4 flow cell */ 82 #define VCI_METAC 0x01 /* Meta signal msg */ 83 #define VCI_ILMIC 0x10 /* ILMI msg */ 84 85 /* Q.2931 signalling messages */ 86 #define CALL_PROCEED 0x02 /* call proceeding */ 87 #define CONNECT 0x07 /* connect */ 88 #define CONNECT_ACK 0x0f /* connect_ack */ 89 #define SETUP 0x05 /* setup */ 90 #define RELEASE 0x4d /* release */ 91 #define RELEASE_DONE 0x5a /* release_done */ 92 #define RESTART 0x46 /* restart */ 93 #define RESTART_ACK 0x4e /* restart ack */ 94 #define STATUS 0x7d /* status */ 95 #define STATUS_ENQ 0x75 /* status ack */ 96 #define ADD_PARTY 0x80 /* add party */ 97 #define ADD_PARTY_ACK 0x81 /* add party ack */ 98 #define ADD_PARTY_REJ 0x82 /* add party rej */ 99 #define DROP_PARTY 0x83 /* drop party */ 100 #define DROP_PARTY_ACK 0x84 /* drop party ack */ 101 102 /* Information Element Parameters in the signalling messages */ 103 #define CAUSE 0x08 /* cause */ 104 #define ENDPT_REF 0x54 /* endpoint reference */ 105 #define AAL_PARA 0x58 /* ATM adaptation layer parameters */ 106 #define TRAFF_DESCRIP 0x59 /* atm traffic descriptors */ 107 #define CONNECT_ID 0x5a /* connection identifier */ 108 #define QOS_PARA 0x5c /* quality of service parameters */ 109 #define B_HIGHER 0x5d /* broadband higher layer information */ 110 #define B_BEARER 0x5e /* broadband bearer capability */ 111 #define B_LOWER 0x5f /* broadband lower information */ 112 #define CALLING_PARTY 0x6c /* calling party number */ 113 #define CALLED_PARTY 0x70 /* called party nmber */ 114 115 #define Q2931 0x09 116 117 /* Q.2931 signalling general messages format */ 118 #define PROTO_POS 0 /* offset of protocol discriminator */ 119 #define CALL_REF_POS 2 /* offset of call reference value */ 120 #define MSG_TYPE_POS 5 /* offset of message type */ 121 #define MSG_LEN_POS 7 /* offset of mesage length */ 122 #define IE_BEGIN_POS 9 /* offset of first information element */ 123 124 /* format of signalling messages */ 125 #define TYPE_POS 0 126 #define LEN_POS 2 127 #define FIELD_BEGIN_POS 4 128 129 /* end of the original atmuni31.h */ 130 131 static const char tstr[] = "[|atm]"; 132 133 #define OAM_CRC10_MASK 0x3ff 134 #define OAM_PAYLOAD_LEN 48 135 #define OAM_FUNCTION_SPECIFIC_LEN 45 /* this excludes crc10 and cell-type/function-type */ 136 #define OAM_CELLTYPE_FUNCTYPE_LEN 1 137 138 static const struct tok oam_f_values[] = { 139 { VCI_OAMF4SC, "OAM F4 (segment)" }, 140 { VCI_OAMF4EC, "OAM F4 (end)" }, 141 { 0, NULL } 142 }; 143 144 static const struct tok atm_pty_values[] = { 145 { 0x0, "user data, uncongested, SDU 0" }, 146 { 0x1, "user data, uncongested, SDU 1" }, 147 { 0x2, "user data, congested, SDU 0" }, 148 { 0x3, "user data, congested, SDU 1" }, 149 { 0x4, "VCC OAM F5 flow segment" }, 150 { 0x5, "VCC OAM F5 flow end-to-end" }, 151 { 0x6, "Traffic Control and resource Mgmt" }, 152 { 0, NULL } 153 }; 154 155 #define OAM_CELLTYPE_FM 0x1 156 #define OAM_CELLTYPE_PM 0x2 157 #define OAM_CELLTYPE_AD 0x8 158 #define OAM_CELLTYPE_SM 0xf 159 160 static const struct tok oam_celltype_values[] = { 161 { OAM_CELLTYPE_FM, "Fault Management" }, 162 { OAM_CELLTYPE_PM, "Performance Management" }, 163 { OAM_CELLTYPE_AD, "activate/deactivate" }, 164 { OAM_CELLTYPE_SM, "System Management" }, 165 { 0, NULL } 166 }; 167 168 #define OAM_FM_FUNCTYPE_AIS 0x0 169 #define OAM_FM_FUNCTYPE_RDI 0x1 170 #define OAM_FM_FUNCTYPE_CONTCHECK 0x4 171 #define OAM_FM_FUNCTYPE_LOOPBACK 0x8 172 173 static const struct tok oam_fm_functype_values[] = { 174 { OAM_FM_FUNCTYPE_AIS, "AIS" }, 175 { OAM_FM_FUNCTYPE_RDI, "RDI" }, 176 { OAM_FM_FUNCTYPE_CONTCHECK, "Continuity Check" }, 177 { OAM_FM_FUNCTYPE_LOOPBACK, "Loopback" }, 178 { 0, NULL } 179 }; 180 181 static const struct tok oam_pm_functype_values[] = { 182 { 0x0, "Forward Monitoring" }, 183 { 0x1, "Backward Reporting" }, 184 { 0x2, "Monitoring and Reporting" }, 185 { 0, NULL } 186 }; 187 188 static const struct tok oam_ad_functype_values[] = { 189 { 0x0, "Performance Monitoring" }, 190 { 0x1, "Continuity Check" }, 191 { 0, NULL } 192 }; 193 194 #define OAM_FM_LOOPBACK_INDICATOR_MASK 0x1 195 196 static const struct tok oam_fm_loopback_indicator_values[] = { 197 { 0x0, "Reply" }, 198 { 0x1, "Request" }, 199 { 0, NULL } 200 }; 201 202 static const struct tok *oam_functype_values[16] = { 203 NULL, 204 oam_fm_functype_values, /* 1 */ 205 oam_pm_functype_values, /* 2 */ 206 NULL, 207 NULL, 208 NULL, 209 NULL, 210 NULL, 211 oam_ad_functype_values, /* 8 */ 212 NULL, 213 NULL, 214 NULL, 215 NULL, 216 NULL, 217 NULL, 218 NULL 219 }; 220 221 /* 222 * Print an RFC 1483 LLC-encapsulated ATM frame. 223 */ 224 static u_int 225 atm_llc_print(netdissect_options *ndo, 226 const u_char *p, int length, int caplen) 227 { 228 int llc_hdrlen; 229 230 llc_hdrlen = llc_print(ndo, p, length, caplen, NULL, NULL); 231 if (llc_hdrlen < 0) { 232 /* packet not known, print raw packet */ 233 if (!ndo->ndo_suppress_default_print) 234 ND_DEFAULTPRINT(p, caplen); 235 llc_hdrlen = -llc_hdrlen; 236 } 237 return (llc_hdrlen); 238 } 239 240 /* 241 * Given a SAP value, generate the LLC header value for a UI packet 242 * with that SAP as the source and destination SAP. 243 */ 244 #define LLC_UI_HDR(sap) ((sap)<<16 | (sap<<8) | 0x03) 245 246 /* 247 * This is the top level routine of the printer. 'p' points 248 * to the LLC/SNAP header of the packet, 'h->ts' is the timestamp, 249 * 'h->len' is the length of the packet off the wire, and 'h->caplen' 250 * is the number of bytes actually captured. 251 */ 252 u_int 253 atm_if_print(netdissect_options *ndo, 254 const struct pcap_pkthdr *h, const u_char *p) 255 { 256 u_int caplen = h->caplen; 257 u_int length = h->len; 258 uint32_t llchdr; 259 u_int hdrlen = 0; 260 261 if (caplen < 1 || length < 1) { 262 ND_PRINT((ndo, "%s", tstr)); 263 return (caplen); 264 } 265 266 /* Cisco Style NLPID ? */ 267 if (*p == LLC_UI) { 268 if (ndo->ndo_eflag) 269 ND_PRINT((ndo, "CNLPID ")); 270 isoclns_print(ndo, p + 1, length - 1); 271 return hdrlen; 272 } 273 274 /* 275 * Must have at least a DSAP, an SSAP, and the first byte of the 276 * control field. 277 */ 278 if (caplen < 3 || length < 3) { 279 ND_PRINT((ndo, "%s", tstr)); 280 return (caplen); 281 } 282 283 /* 284 * Extract the presumed LLC header into a variable, for quick 285 * testing. 286 * Then check for a header that's neither a header for a SNAP 287 * packet nor an RFC 2684 routed NLPID-formatted PDU nor 288 * an 802.2-but-no-SNAP IP packet. 289 */ 290 llchdr = EXTRACT_24BITS(p); 291 if (llchdr != LLC_UI_HDR(LLCSAP_SNAP) && 292 llchdr != LLC_UI_HDR(LLCSAP_ISONS) && 293 llchdr != LLC_UI_HDR(LLCSAP_IP)) { 294 /* 295 * XXX - assume 802.6 MAC header from Fore driver. 296 * 297 * Unfortunately, the above list doesn't check for 298 * all known SAPs, doesn't check for headers where 299 * the source and destination SAP aren't the same, 300 * and doesn't check for non-UI frames. It also 301 * runs the risk of an 802.6 MAC header that happens 302 * to begin with one of those values being 303 * incorrectly treated as an 802.2 header. 304 * 305 * So is that Fore driver still around? And, if so, 306 * is it still putting 802.6 MAC headers on ATM 307 * packets? If so, could it be changed to use a 308 * new DLT_IEEE802_6 value if we added it? 309 */ 310 if (caplen < 20 || length < 20) { 311 ND_PRINT((ndo, "%s", tstr)); 312 return (caplen); 313 } 314 if (ndo->ndo_eflag) 315 ND_PRINT((ndo, "%08x%08x %08x%08x ", 316 EXTRACT_32BITS(p), 317 EXTRACT_32BITS(p+4), 318 EXTRACT_32BITS(p+8), 319 EXTRACT_32BITS(p+12))); 320 p += 20; 321 length -= 20; 322 caplen -= 20; 323 hdrlen += 20; 324 } 325 hdrlen += atm_llc_print(ndo, p, length, caplen); 326 return (hdrlen); 327 } 328 329 /* 330 * ATM signalling. 331 */ 332 static const struct tok msgtype2str[] = { 333 { CALL_PROCEED, "Call_proceeding" }, 334 { CONNECT, "Connect" }, 335 { CONNECT_ACK, "Connect_ack" }, 336 { SETUP, "Setup" }, 337 { RELEASE, "Release" }, 338 { RELEASE_DONE, "Release_complete" }, 339 { RESTART, "Restart" }, 340 { RESTART_ACK, "Restart_ack" }, 341 { STATUS, "Status" }, 342 { STATUS_ENQ, "Status_enquiry" }, 343 { ADD_PARTY, "Add_party" }, 344 { ADD_PARTY_ACK, "Add_party_ack" }, 345 { ADD_PARTY_REJ, "Add_party_reject" }, 346 { DROP_PARTY, "Drop_party" }, 347 { DROP_PARTY_ACK, "Drop_party_ack" }, 348 { 0, NULL } 349 }; 350 351 static void 352 sig_print(netdissect_options *ndo, 353 const u_char *p) 354 { 355 uint32_t call_ref; 356 357 ND_TCHECK(p[PROTO_POS]); 358 if (p[PROTO_POS] == Q2931) { 359 /* 360 * protocol:Q.2931 for User to Network Interface 361 * (UNI 3.1) signalling 362 */ 363 ND_PRINT((ndo, "Q.2931")); 364 ND_TCHECK(p[MSG_TYPE_POS]); 365 ND_PRINT((ndo, ":%s ", 366 tok2str(msgtype2str, "msgtype#%d", p[MSG_TYPE_POS]))); 367 368 /* 369 * The call reference comes before the message type, 370 * so if we know we have the message type, which we 371 * do from the caplen test above, we also know we have 372 * the call reference. 373 */ 374 call_ref = EXTRACT_24BITS(&p[CALL_REF_POS]); 375 ND_PRINT((ndo, "CALL_REF:0x%06x", call_ref)); 376 } else { 377 /* SCCOP with some unknown protocol atop it */ 378 ND_PRINT((ndo, "SSCOP, proto %d ", p[PROTO_POS])); 379 } 380 return; 381 382 trunc: 383 ND_PRINT((ndo, " %s", tstr)); 384 } 385 386 /* 387 * Print an ATM PDU (such as an AAL5 PDU). 388 */ 389 void 390 atm_print(netdissect_options *ndo, 391 u_int vpi, u_int vci, u_int traftype, const u_char *p, u_int length, 392 u_int caplen) 393 { 394 if (ndo->ndo_eflag) 395 ND_PRINT((ndo, "VPI:%u VCI:%u ", vpi, vci)); 396 397 if (vpi == 0) { 398 switch (vci) { 399 400 case VCI_PPC: 401 sig_print(ndo, p); 402 return; 403 404 case VCI_BCC: 405 ND_PRINT((ndo, "broadcast sig: ")); 406 return; 407 408 case VCI_OAMF4SC: /* fall through */ 409 case VCI_OAMF4EC: 410 oam_print(ndo, p, length, ATM_OAM_HEC); 411 return; 412 413 case VCI_METAC: 414 ND_PRINT((ndo, "meta: ")); 415 return; 416 417 case VCI_ILMIC: 418 ND_PRINT((ndo, "ilmi: ")); 419 snmp_print(ndo, p, length); 420 return; 421 } 422 } 423 424 switch (traftype) { 425 426 case ATM_LLC: 427 default: 428 /* 429 * Assumes traffic is LLC if unknown. 430 */ 431 atm_llc_print(ndo, p, length, caplen); 432 break; 433 434 case ATM_LANE: 435 lane_print(ndo, p, length, caplen); 436 break; 437 } 438 } 439 440 struct oam_fm_loopback_t { 441 uint8_t loopback_indicator; 442 uint8_t correlation_tag[4]; 443 uint8_t loopback_id[12]; 444 uint8_t source_id[12]; 445 uint8_t unused[16]; 446 }; 447 448 struct oam_fm_ais_rdi_t { 449 uint8_t failure_type; 450 uint8_t failure_location[16]; 451 uint8_t unused[28]; 452 }; 453 454 void 455 oam_print (netdissect_options *ndo, 456 const u_char *p, u_int length, u_int hec) 457 { 458 uint32_t cell_header; 459 uint16_t vpi, vci, cksum, cksum_shouldbe, idx; 460 uint8_t cell_type, func_type, payload, clp; 461 462 union { 463 const struct oam_fm_loopback_t *oam_fm_loopback; 464 const struct oam_fm_ais_rdi_t *oam_fm_ais_rdi; 465 } oam_ptr; 466 467 468 ND_TCHECK(*(p+ATM_HDR_LEN_NOHEC+hec)); 469 cell_header = EXTRACT_32BITS(p+hec); 470 cell_type = ((*(p+ATM_HDR_LEN_NOHEC+hec))>>4) & 0x0f; 471 func_type = (*(p+ATM_HDR_LEN_NOHEC+hec)) & 0x0f; 472 473 vpi = (cell_header>>20)&0xff; 474 vci = (cell_header>>4)&0xffff; 475 payload = (cell_header>>1)&0x7; 476 clp = cell_header&0x1; 477 478 ND_PRINT((ndo, "%s, vpi %u, vci %u, payload [ %s ], clp %u, length %u", 479 tok2str(oam_f_values, "OAM F5", vci), 480 vpi, vci, 481 tok2str(atm_pty_values, "Unknown", payload), 482 clp, length)); 483 484 if (!ndo->ndo_vflag) { 485 return; 486 } 487 488 ND_PRINT((ndo, "\n\tcell-type %s (%u)", 489 tok2str(oam_celltype_values, "unknown", cell_type), 490 cell_type)); 491 492 if (oam_functype_values[cell_type] == NULL) 493 ND_PRINT((ndo, ", func-type unknown (%u)", func_type)); 494 else 495 ND_PRINT((ndo, ", func-type %s (%u)", 496 tok2str(oam_functype_values[cell_type],"none",func_type), 497 func_type)); 498 499 p += ATM_HDR_LEN_NOHEC + hec; 500 501 switch (cell_type << 4 | func_type) { 502 case (OAM_CELLTYPE_FM << 4 | OAM_FM_FUNCTYPE_LOOPBACK): 503 oam_ptr.oam_fm_loopback = (const struct oam_fm_loopback_t *)(p + OAM_CELLTYPE_FUNCTYPE_LEN); 504 ND_TCHECK(*oam_ptr.oam_fm_loopback); 505 ND_PRINT((ndo, "\n\tLoopback-Indicator %s, Correlation-Tag 0x%08x", 506 tok2str(oam_fm_loopback_indicator_values, 507 "Unknown", 508 oam_ptr.oam_fm_loopback->loopback_indicator & OAM_FM_LOOPBACK_INDICATOR_MASK), 509 EXTRACT_32BITS(&oam_ptr.oam_fm_loopback->correlation_tag))); 510 ND_PRINT((ndo, "\n\tLocation-ID ")); 511 for (idx = 0; idx < sizeof(oam_ptr.oam_fm_loopback->loopback_id); idx++) { 512 if (idx % 2) { 513 ND_PRINT((ndo, "%04x ", EXTRACT_16BITS(&oam_ptr.oam_fm_loopback->loopback_id[idx]))); 514 } 515 } 516 ND_PRINT((ndo, "\n\tSource-ID ")); 517 for (idx = 0; idx < sizeof(oam_ptr.oam_fm_loopback->source_id); idx++) { 518 if (idx % 2) { 519 ND_PRINT((ndo, "%04x ", EXTRACT_16BITS(&oam_ptr.oam_fm_loopback->source_id[idx]))); 520 } 521 } 522 break; 523 524 case (OAM_CELLTYPE_FM << 4 | OAM_FM_FUNCTYPE_AIS): 525 case (OAM_CELLTYPE_FM << 4 | OAM_FM_FUNCTYPE_RDI): 526 oam_ptr.oam_fm_ais_rdi = (const struct oam_fm_ais_rdi_t *)(p + OAM_CELLTYPE_FUNCTYPE_LEN); 527 ND_TCHECK(*oam_ptr.oam_fm_ais_rdi); 528 ND_PRINT((ndo, "\n\tFailure-type 0x%02x", oam_ptr.oam_fm_ais_rdi->failure_type)); 529 ND_PRINT((ndo, "\n\tLocation-ID ")); 530 for (idx = 0; idx < sizeof(oam_ptr.oam_fm_ais_rdi->failure_location); idx++) { 531 if (idx % 2) { 532 ND_PRINT((ndo, "%04x ", EXTRACT_16BITS(&oam_ptr.oam_fm_ais_rdi->failure_location[idx]))); 533 } 534 } 535 break; 536 537 case (OAM_CELLTYPE_FM << 4 | OAM_FM_FUNCTYPE_CONTCHECK): 538 /* FIXME */ 539 break; 540 541 default: 542 break; 543 } 544 545 /* crc10 checksum verification */ 546 ND_TCHECK2(*(p + OAM_CELLTYPE_FUNCTYPE_LEN + OAM_FUNCTION_SPECIFIC_LEN), 2); 547 cksum = EXTRACT_16BITS(p + OAM_CELLTYPE_FUNCTYPE_LEN + OAM_FUNCTION_SPECIFIC_LEN) 548 & OAM_CRC10_MASK; 549 cksum_shouldbe = verify_crc10_cksum(0, p, OAM_PAYLOAD_LEN); 550 551 ND_PRINT((ndo, "\n\tcksum 0x%03x (%scorrect)", 552 cksum, 553 cksum_shouldbe == 0 ? "" : "in")); 554 555 return; 556 557 trunc: 558 ND_PRINT((ndo, "[|oam]")); 559 return; 560 } 561