mirror of
https://github.com/the-tcpdump-group/tcpdump.git
synced 2024-11-24 02:23:27 +08:00
322 lines
6.6 KiB
C
322 lines
6.6 KiB
C
/*
|
|
* 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]);
|
|
}
|