/* * 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: /cvs/OpenBSD/src/usr.sbin/tcpdump/print-isoclns.c,v 1.6 1997/07/25 20:12:25 mickey Exp $ (LBL)"; #endif #include #include #include #ifdef __STDC__ struct mbuf; struct rtentry; #endif #include #include #include #include #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 (--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]); }