| /* |
| * Copyright (c) 1992, 1993, 1994, 1995, 1996 |
| * The Regents of the University of California. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that: (1) source code distributions |
| * retain the above copyright notice and this paragraph in its entirety, (2) |
| * distributions including binary code include the above copyright notice and |
| * this paragraph in its entirety in the documentation or other materials |
| * provided with the distribution, and (3) all advertising materials mentioning |
| * features or use of this software display the following acknowledgement: |
| * ``This product includes software developed by the University of California, |
| * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of |
| * the University nor the names of its contributors may be used to endorse |
| * or promote products derived from this software without specific prior |
| * written permission. |
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED |
| * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
| * |
| * Original code by Matt Thomas, Digital Equipment Corporation |
| */ |
| |
| #ifndef lint |
| static const char rcsid[] = |
| "@(#) $Header: /tcpdump/master/tcpdump/print-isoclns.c,v 1.16 1999-11-21 09:36:55 fenner Exp $ (LBL)"; |
| #endif |
| |
| #ifdef HAVE_CONFIG_H |
| #include "config.h" |
| #endif |
| |
| #include <sys/types.h> |
| #include <sys/time.h> |
| #include <sys/socket.h> |
| |
| #if __STDC__ |
| struct mbuf; |
| struct rtentry; |
| #endif |
| #include <net/if.h> |
| |
| #include <netinet/in.h> |
| #include <netinet/if_ether.h> |
| |
| #include <stdio.h> |
| |
| #include "interface.h" |
| #include "addrtoname.h" |
| #include "ethertype.h" |
| |
| #define CLNS 129 |
| #define ESIS 130 |
| #define ISIS 131 |
| #define NULLNS 0 |
| |
| static int osi_cksum(const u_char *, u_int, const u_char *, u_char *, u_char *); |
| static void esis_print(const u_char *, u_int); |
| |
| void |
| isoclns_print(const u_char *p, u_int length, u_int caplen, |
| const u_char *esrc, const u_char *edst) |
| { |
| if (caplen < 1) { |
| printf("[|iso-clns] "); |
| if (!eflag) |
| printf("%s > %s", |
| etheraddr_string(esrc), |
| etheraddr_string(edst)); |
| return; |
| } |
| |
| switch (*p) { |
| |
| case CLNS: |
| /* esis_print(&p, &length); */ |
| printf("iso-clns"); |
| if (!eflag) |
| (void)printf(" %s > %s", |
| etheraddr_string(esrc), |
| etheraddr_string(edst)); |
| break; |
| |
| case ESIS: |
| printf("iso-esis"); |
| if (!eflag) |
| (void)printf(" %s > %s", |
| etheraddr_string(esrc), |
| etheraddr_string(edst)); |
| esis_print(p, length); |
| return; |
| |
| case ISIS: |
| printf("iso-isis"); |
| if (!eflag) |
| (void)printf(" %s > %s", |
| etheraddr_string(esrc), |
| etheraddr_string(edst)); |
| /* isis_print(&p, &length); */ |
| (void)printf(" len=%d ", length); |
| if (caplen > 1) |
| default_print_unaligned(p, caplen); |
| break; |
| |
| case NULLNS: |
| printf("iso-nullns"); |
| if (!eflag) |
| (void)printf(" %s > %s", |
| etheraddr_string(esrc), |
| etheraddr_string(edst)); |
| break; |
| |
| default: |
| printf("iso-clns %02x", p[0]); |
| if (!eflag) |
| (void)printf(" %s > %s", |
| etheraddr_string(esrc), |
| etheraddr_string(edst)); |
| (void)printf(" len=%d ", length); |
| if (caplen > 1) |
| default_print_unaligned(p, caplen); |
| break; |
| } |
| } |
| |
| #define ESIS_REDIRECT 6 |
| #define ESIS_ESH 2 |
| #define ESIS_ISH 4 |
| |
| struct esis_hdr { |
| u_char version; |
| u_char reserved; |
| u_char type; |
| u_char tmo[2]; |
| u_char cksum[2]; |
| }; |
| |
| static void |
| esis_print(const u_char *p, u_int length) |
| { |
| const u_char *ep; |
| int li = p[1]; |
| const struct esis_hdr *eh = (const struct esis_hdr *) &p[2]; |
| u_char cksum[2]; |
| u_char off[2]; |
| |
| if (length == 2) { |
| if (qflag) |
| printf(" bad pkt!"); |
| else |
| printf(" no header at all!"); |
| return; |
| } |
| ep = p + li; |
| if (li > length) { |
| if (qflag) |
| printf(" bad pkt!"); |
| else |
| printf(" LI(%d) > PDU size (%d)!", li, length); |
| return; |
| } |
| if (li < sizeof(struct esis_hdr) + 2) { |
| if (qflag) |
| printf(" bad pkt!"); |
| else { |
| printf(" too short for esis header %d:", li); |
| while (--length != 0) |
| printf("%02X", *p++); |
| } |
| return; |
| } |
| switch (eh->type & 0x1f) { |
| |
| case ESIS_REDIRECT: |
| printf(" redirect"); |
| break; |
| |
| case ESIS_ESH: |
| printf(" esh"); |
| break; |
| |
| case ESIS_ISH: |
| printf(" ish"); |
| break; |
| |
| default: |
| printf(" type %d", eh->type & 0x1f); |
| break; |
| } |
| off[0] = eh->cksum[0]; |
| off[1] = eh->cksum[1]; |
| if (vflag && osi_cksum(p, li, eh->cksum, cksum, off)) { |
| printf(" bad cksum (got %02x%02x want %02x%02x)", |
| eh->cksum[1], eh->cksum[0], cksum[1], cksum[0]); |
| return; |
| } |
| if (eh->version != 1) { |
| printf(" unsupported version %d", eh->version); |
| return; |
| } |
| p += sizeof(*eh) + 2; |
| li -= sizeof(*eh) + 2; /* protoid * li */ |
| |
| switch (eh->type & 0x1f) { |
| case ESIS_REDIRECT: { |
| const u_char *dst, *snpa, *is; |
| |
| dst = p; p += *p + 1; |
| if (p > snapend) |
| return; |
| printf(" %s", isonsap_string(dst)); |
| snpa = p; p += *p + 1; |
| is = p; p += *p + 1; |
| if (p > snapend) |
| return; |
| if (p > ep) { |
| printf(" [bad li]"); |
| return; |
| } |
| if (is[0] == 0) |
| printf(" > %s", etheraddr_string(&snpa[1])); |
| else |
| printf(" > %s", isonsap_string(is)); |
| li = ep - p; |
| break; |
| } |
| #if 0 |
| case ESIS_ESH: |
| printf(" esh"); |
| break; |
| #endif |
| case ESIS_ISH: { |
| const u_char *is; |
| |
| is = p; p += *p + 1; |
| if (p > ep) { |
| printf(" [bad li]"); |
| return; |
| } |
| if (p > snapend) |
| return; |
| printf(" %s", isonsap_string(is)); |
| li = ep - p; |
| break; |
| } |
| |
| default: |
| (void)printf(" len=%d", length); |
| if (length && p < snapend) { |
| length = snapend - p; |
| default_print(p, length); |
| } |
| return; |
| } |
| if (vflag) |
| while (p < ep && li) { |
| int op, opli; |
| const u_char *q; |
| |
| if (snapend - p < 2) |
| return; |
| if (li < 2) { |
| printf(" bad opts/li"); |
| return; |
| } |
| op = *p++; |
| opli = *p++; |
| li -= 2; |
| if (opli > li) { |
| printf(" opt (%d) too long", op); |
| return; |
| } |
| li -= opli; |
| q = p; |
| p += opli; |
| if (snapend < p) |
| return; |
| if (op == 198 && opli == 2) { |
| printf(" tmo=%d", q[0] * 256 + q[1]); |
| continue; |
| } |
| printf (" %d:<", op); |
| while (--opli >= 0) |
| printf("%02x", *q++); |
| printf (">"); |
| } |
| } |
| |
| static int |
| osi_cksum(register const u_char *p, register u_int len, |
| const u_char *toff, u_char *cksum, u_char *off) |
| { |
| int x, y, f = (len - ((toff - p) + 1)); |
| int32_t c0 = 0, c1 = 0; |
| |
| if ((cksum[0] = off[0]) == 0 && (cksum[1] = off[1]) == 0) |
| return 0; |
| |
| off[0] = off[1] = 0; |
| while ((int)--len >= 0) { |
| c0 += *p++; |
| c1 += c0; |
| c0 %= 255; |
| c1 %= 255; |
| } |
| x = (c0 * f - c1); |
| if (x < 0) |
| x = 255 - (-x % 255); |
| else |
| x %= 255; |
| y = -1 * (x + c0); |
| if (y < 0) |
| y = 255 - (-y % 255); |
| else |
| y %= 255; |
| |
| off[0] = x; |
| off[1] = y; |
| |
| return (off[0] != cksum[0] || off[1] != cksum[1]); |
| } |