1 /* 2 * Copyright (c) 1992, 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 /* 23 * Original code by Matt Thomas, Digital Equipment Corporation 24 */ 25 26 #ifndef lint 27 static char rcsid[] = 28 "@(#) $Header: print-isoclns.c,v 1.12 96/07/14 19:39:00 leres Exp $ (LBL)"; 29 #endif 30 31 #include <sys/types.h> 32 #include <sys/time.h> 33 #include <sys/socket.h> 34 35 #if __STDC__ 36 struct mbuf; 37 struct rtentry; 38 #endif 39 #include <net/if.h> 40 41 #include <netinet/in.h> 42 #include <netinet/if_ether.h> 43 44 #include <stdio.h> 45 46 #include "interface.h" 47 #include "addrtoname.h" 48 #include "ethertype.h" 49 #include "extract.h" 50 51 #define NLPID_CLNS 129 /* 0x81 */ 52 #define NLPID_ESIS 130 /* 0x82 */ 53 #define NLPID_ISIS 131 /* 0x83 */ 54 #define NLPID_NULLNS 0 55 56 static int osi_cksum(const u_char *, int, u_char *); 57 static void esis_print(const u_char *, u_int); 58 static int isis_print(const u_char *, u_int); 59 60 void 61 isoclns_print(const u_char *p, u_int length, u_int caplen, 62 const u_char *esrc, const u_char *edst) 63 { 64 if (caplen < 1) { 65 printf("[|iso-clns] "); 66 if (!eflag) 67 printf("%s > %s", 68 etheraddr_string(esrc), 69 etheraddr_string(edst)); 70 return; 71 } 72 73 switch (*p) { 74 75 case NLPID_CLNS: 76 printf("iso clns"); 77 if (!eflag) 78 (void)printf(" %s > %s", 79 etheraddr_string(esrc), 80 etheraddr_string(edst)); 81 break; 82 83 case NLPID_ESIS: 84 printf("iso esis"); 85 if (!eflag) 86 (void)printf(" %s > %s", 87 etheraddr_string(esrc), 88 etheraddr_string(edst)); 89 esis_print(p, length); 90 return; 91 92 case NLPID_ISIS: 93 printf("iso isis"); 94 if (!eflag) 95 (void)printf(" %s > %s", 96 etheraddr_string(esrc), 97 etheraddr_string(edst)); 98 (void)printf(" len=%d ", length); 99 if (!isis_print(p, length)) 100 default_print_unaligned(p, caplen); 101 break; 102 103 case NLPID_NULLNS: 104 printf("iso nullns"); 105 if (!eflag) 106 (void)printf(" %s > %s", 107 etheraddr_string(esrc), 108 etheraddr_string(edst)); 109 break; 110 111 default: 112 printf("iso clns %02x", p[0]); 113 if (!eflag) 114 (void)printf(" %s > %s", 115 etheraddr_string(esrc), 116 etheraddr_string(edst)); 117 (void)printf(" len=%d ", length); 118 if (caplen > 1) 119 default_print_unaligned(p, caplen); 120 break; 121 } 122 } 123 124 #define ESIS_REDIRECT 6 125 #define ESIS_ESH 2 126 #define ESIS_ISH 4 127 128 struct esis_hdr { 129 u_char version; 130 u_char reserved; 131 u_char type; 132 u_char tmo[2]; 133 u_char cksum[2]; 134 }; 135 136 static void 137 esis_print(const u_char *p, u_int length) 138 { 139 const u_char *ep; 140 int li = p[1]; 141 const struct esis_hdr *eh = (const struct esis_hdr *) &p[2]; 142 u_char cksum[2]; 143 u_char off[2]; 144 145 if (length == 2) { 146 if (qflag) 147 printf(" bad pkt!"); 148 else 149 printf(" no header at all!"); 150 return; 151 } 152 ep = p + li; 153 if (li > length) { 154 if (qflag) 155 printf(" bad pkt!"); 156 else 157 printf(" LI(%d) > PDU size (%d)!", li, length); 158 return; 159 } 160 if (li < sizeof(struct esis_hdr) + 2) { 161 if (qflag) 162 printf(" bad pkt!"); 163 else { 164 printf(" too short for esis header %d:", li); 165 while (--length >= 0) 166 printf("%02X", *p++); 167 } 168 return; 169 } 170 switch (eh->type & 0x1f) { 171 172 case ESIS_REDIRECT: 173 printf(" redirect"); 174 break; 175 176 case ESIS_ESH: 177 printf(" esh"); 178 break; 179 180 case ESIS_ISH: 181 printf(" ish"); 182 break; 183 184 default: 185 printf(" type %d", eh->type & 0x1f); 186 break; 187 } 188 off[0] = eh->cksum[0]; 189 off[1] = eh->cksum[1]; 190 if (vflag && osi_cksum(p, li, off)) { 191 printf(" bad cksum (got %02x%02x)", 192 eh->cksum[1], eh->cksum[0]); 193 default_print(p, length); 194 return; 195 } 196 if (eh->version != 1) { 197 printf(" unsupported version %d", eh->version); 198 return; 199 } 200 p += sizeof(*eh) + 2; 201 li -= sizeof(*eh) + 2; /* protoid * li */ 202 203 switch (eh->type & 0x1f) { 204 case ESIS_REDIRECT: { 205 const u_char *dst, *snpa, *is; 206 207 dst = p; p += *p + 1; 208 if (p > snapend) 209 return; 210 printf("\n\t\t\t %s", isonsap_string(dst)); 211 snpa = p; p += *p + 1; 212 is = p; p += *p + 1; 213 if (p > snapend) 214 return; 215 if (p > ep) { 216 printf(" [bad li]"); 217 return; 218 } 219 if (is[0] == 0) 220 printf(" > %s", etheraddr_string(&snpa[1])); 221 else 222 printf(" > %s", isonsap_string(is)); 223 li = ep - p; 224 break; 225 } 226 #if 0 227 case ESIS_ESH: 228 printf(" esh"); 229 break; 230 #endif 231 case ESIS_ISH: { 232 const u_char *is; 233 234 is = p; p += *p + 1; 235 if (p > ep) { 236 printf(" [bad li]"); 237 return; 238 } 239 if (p > snapend) 240 return; 241 if (!qflag) 242 printf("\n\t\t\t %s", isonsap_string(is)); 243 li = ep - p; 244 break; 245 } 246 247 default: 248 (void)printf(" len=%d", length); 249 if (length && p < snapend) { 250 length = snapend - p; 251 default_print(p, length); 252 } 253 return; 254 } 255 if (vflag) 256 while (p < ep && li) { 257 int op, opli; 258 const u_char *q; 259 260 if (snapend - p < 2) 261 return; 262 if (li < 2) { 263 printf(" bad opts/li"); 264 return; 265 } 266 op = *p++; 267 opli = *p++; 268 li -= 2; 269 if (opli > li) { 270 printf(" opt (%d) too long", op); 271 return; 272 } 273 li -= opli; 274 q = p; 275 p += opli; 276 if (snapend < p) 277 return; 278 if (op == 198 && opli == 2) { 279 printf(" tmo=%d", q[0] * 256 + q[1]); 280 continue; 281 } 282 printf (" %d:<", op); 283 while (--opli >= 0) 284 printf("%02x", *q++); 285 printf (">"); 286 } 287 } 288 289 /* 290 * print_nsap 291 * Print out an NSAP. 292 */ 293 294 void 295 print_nsap (register const u_char *cp, register int length) 296 { 297 int i; 298 299 for (i = 0; i < length; i++) { 300 printf("%02x", *cp++); 301 if (((i & 1) == 0) && (i + 1 < length)) { 302 printf("."); 303 } 304 305 } 306 } 307 308 /* 309 * IS-IS is defined in ISO 10589. Look there for protocol definitions. 310 */ 311 312 #define SYSTEM_ID_LEN sizeof(struct ether_addr) 313 #define ISIS_VERSION 1 314 #define PDU_TYPE_MASK 0x1F 315 #define PRIORITY_MASK 0x7F 316 317 #define L1_LAN_IIH 15 318 #define L2_LAN_IIH 16 319 #define PTP_IIH 17 320 321 #define TLV_AREA_ADDR 1 322 #define TLV_ISNEIGH 6 323 #define TLV_PADDING 8 324 #define TLV_AUTHENT 10 325 326 struct isis_header { 327 u_char nlpid; 328 u_char fixed_len; 329 u_char version; /* Protocol version? */ 330 u_char id_length; 331 u_char enc_pdu_type; /* 3 MSbs are reserved */ 332 u_char pkt_version; /* Packet format version? */ 333 u_char reserved; 334 u_char enc_max_area; 335 u_char circuit; 336 u_char enc_source_id[SYSTEM_ID_LEN]; 337 u_char enc_holding_time[2]; 338 u_char enc_packet_len[2]; 339 u_char enc_priority; 340 u_char enc_lan_id[SYSTEM_ID_LEN+1]; 341 }; 342 343 #define ISIS_HEADER_SIZE (15+(SYSTEM_ID_LEN<<1)) 344 345 /* 346 * isis_print 347 * Decode IS-IS packets. Return 0 on error. 348 * 349 * So far, this is only smart enough to print IIH's. Someday... 350 */ 351 352 static int 353 isis_print (const u_char *p, u_int length) 354 { 355 struct isis_header *header; 356 u_char pdu_type, max_area, priority, *pptr, type, len, *tptr, tmp, alen; 357 u_short packet_len, holding_time; 358 359 header = (struct isis_header *)p; 360 printf("\n\t\t\t"); 361 362 /* 363 * Sanity checking of the header. 364 */ 365 if (header->nlpid != NLPID_ISIS) { 366 printf(" coding error!"); 367 return(0); 368 } 369 370 if (header->version != ISIS_VERSION) { 371 printf(" version %d packet not supported", header->version); 372 return(0); 373 } 374 375 if ((header->id_length != SYSTEM_ID_LEN) && (header->id_length != 0)) { 376 printf(" system ID length of %d is not supported", 377 header->id_length); 378 return(0); 379 } 380 381 if ((header->fixed_len != ISIS_HEADER_SIZE)) { 382 printf(" bogus fixed header length %d should be %d", 383 header->fixed_len, ISIS_HEADER_SIZE); 384 return(0); 385 } 386 387 pdu_type = header->enc_pdu_type & PDU_TYPE_MASK; 388 if ((pdu_type != L1_LAN_IIH) && (pdu_type != L2_LAN_IIH)) { 389 printf(" PDU type (%d) not supported", pdu_type); 390 return; 391 } 392 393 if (header->pkt_version != ISIS_VERSION) { 394 printf(" version %d packet not supported", header->pkt_version); 395 return; 396 } 397 398 max_area = header->enc_max_area; 399 switch(max_area) { 400 case 0: 401 max_area = 3; /* silly shit */ 402 break; 403 case 255: 404 printf(" bad packet -- 255 areas"); 405 return(0); 406 default: 407 break; 408 } 409 410 switch (header->circuit) { 411 case 0: 412 printf(" PDU with circuit type 0"); 413 return(0); 414 case 1: 415 if (pdu_type == L2_LAN_IIH) { 416 printf(" L2 IIH on an L1 only circuit"); 417 return(0); 418 } 419 break; 420 case 2: 421 if (pdu_type == L1_LAN_IIH) { 422 printf(" L1 IIH on an L2 only circuit"); 423 return(0); 424 } 425 break; 426 case 3: 427 break; 428 default: 429 printf(" unknown circuit type"); 430 return(0); 431 } 432 433 holding_time = EXTRACT_16BITS(header->enc_holding_time); 434 435 packet_len = EXTRACT_16BITS(header->enc_packet_len); 436 if ((packet_len < ISIS_HEADER_SIZE) || 437 (packet_len > length)) { 438 printf(" bogus packet length %d, real length %d", packet_len, 439 length); 440 return(0); 441 } 442 443 priority = header->enc_priority & PRIORITY_MASK; 444 445 /* 446 * Now print the fixed header. 447 */ 448 switch (pdu_type) { 449 case L1_LAN_IIH: 450 printf(" L1 lan iih, "); 451 break; 452 case L2_LAN_IIH: 453 printf(" L2 lan iih, "); 454 break; 455 } 456 457 printf("circuit "); 458 switch (header->circuit) { 459 case 1: 460 printf("l1 only, "); 461 break; 462 case 2: 463 printf("l2 only, "); 464 break; 465 case 3: 466 printf("l1-l2, "); 467 break; 468 } 469 470 printf ("holding time %d ", holding_time); 471 printf ("\n\t\t\t source %s, length %d", 472 etheraddr_string(header->enc_source_id), packet_len); 473 printf ("\n\t\t\t lan id %s(%d)", etheraddr_string(header->enc_lan_id), 474 header->enc_lan_id[SYSTEM_ID_LEN]); 475 476 /* 477 * Now print the TLV's. 478 */ 479 packet_len -= ISIS_HEADER_SIZE; 480 pptr = (char *)p + ISIS_HEADER_SIZE; 481 while (packet_len >= 2) { 482 if (pptr >= snapend) { 483 printf("\n\t\t\t packet exceeded snapshot"); 484 return(1); 485 } 486 type = *pptr++; 487 len = *pptr++; 488 packet_len -= 2; 489 if (len > packet_len) { 490 break; 491 } 492 493 switch (type) { 494 case TLV_AREA_ADDR: 495 printf("\n\t\t\t area addresses"); 496 tmp = len; 497 tptr = pptr; 498 alen = *tptr++; 499 while (tmp && alen < tmp) { 500 printf("\n\t\t\t "); 501 print_nsap(tptr, alen); 502 printf(" (%d)", alen); 503 tptr += alen; 504 tmp -= alen + 1; 505 alen = *tptr++; 506 } 507 break; 508 case TLV_ISNEIGH: 509 printf("\n\t\t\t neighbor addresses"); 510 tmp = len; 511 tptr = pptr; 512 while (tmp >= sizeof(struct ether_addr)) { 513 printf("\n\t\t\t %s", etheraddr_string(tptr)); 514 tmp -= sizeof(struct ether_addr); 515 tptr += sizeof(struct ether_addr); 516 } 517 break; 518 case TLV_PADDING: 519 printf("\n\t\t\t padding for %d bytes", len); 520 break; 521 case TLV_AUTHENT: 522 printf("\n\t\t\t authentication data"); 523 default_print(pptr, len); 524 break; 525 default: 526 printf("\n\t\t\t unknown TLV, type %d, length %d", type, len); 527 break; 528 } 529 530 pptr += len; 531 packet_len -= len; 532 } 533 534 if (packet_len != 0) { 535 printf("\n\t\t\t %d straggler bytes", packet_len); 536 } 537 return(1); 538 } 539 540 /* 541 * Verify the checksum. See 8473-1, Appendix C, section C.4. 542 */ 543 544 static int 545 osi_cksum(register const u_char *p, register int len, u_char *off) 546 { 547 int32_t c0 = 0, c1 = 0; 548 549 if ((off[0] == 0) && (off[1] == 0)) 550 return 0; 551 552 while (--len >= 0) { 553 c0 += *p++; 554 c0 %= 255; 555 c1 += c0; 556 c1 %= 255; 557 } 558 return (c0 | c1); 559 } 560