print-isoclns.c revision 56896
117680Spst/*
217680Spst * Copyright (c) 1992, 1993, 1994, 1995, 1996
317680Spst *	The Regents of the University of California.  All rights reserved.
417680Spst *
517680Spst * Redistribution and use in source and binary forms, with or without
617680Spst * modification, are permitted provided that: (1) source code distributions
717680Spst * retain the above copyright notice and this paragraph in its entirety, (2)
817680Spst * distributions including binary code include the above copyright notice and
917680Spst * this paragraph in its entirety in the documentation or other materials
1017680Spst * provided with the distribution, and (3) all advertising materials mentioning
1117680Spst * features or use of this software display the following acknowledgement:
1217680Spst * ``This product includes software developed by the University of California,
1317680Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1417680Spst * the University nor the names of its contributors may be used to endorse
1517680Spst * or promote products derived from this software without specific prior
1617680Spst * written permission.
1717680Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1817680Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1917680Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2026183Sfenner *
2117680Spst * Original code by Matt Thomas, Digital Equipment Corporation
2256896Sfenner *
2356896Sfenner * $FreeBSD: head/contrib/tcpdump/print-isoclns.c 56896 2000-01-30 01:05:24Z fenner $
2417680Spst */
2517680Spst
2617680Spst#ifndef lint
2726183Sfennerstatic const char rcsid[] =
2856896Sfenner    "@(#) $Header: /tcpdump/master/tcpdump/print-isoclns.c,v 1.16 1999/11/21 09:36:55 fenner Exp $ (LBL)";
2917680Spst#endif
3017680Spst
3156896Sfenner#ifdef HAVE_CONFIG_H
3256896Sfenner#include "config.h"
3356896Sfenner#endif
3456896Sfenner
3517680Spst#include <sys/types.h>
3617680Spst#include <sys/time.h>
3717680Spst#include <sys/socket.h>
3817680Spst
3917680Spst#if __STDC__
4017680Spststruct mbuf;
4117680Spststruct rtentry;
4217680Spst#endif
4317680Spst#include <net/if.h>
4417680Spst
4517680Spst#include <netinet/in.h>
4621262Swollman#include <net/ethernet.h>
4717680Spst
4817680Spst#include <stdio.h>
4917680Spst
5017680Spst#include "interface.h"
5117680Spst#include "addrtoname.h"
5217680Spst#include "ethertype.h"
5317688Spst#include "extract.h"
5417680Spst
5517688Spst#define	NLPID_CLNS	129	/* 0x81 */
5617688Spst#define	NLPID_ESIS	130	/* 0x82 */
5717688Spst#define	NLPID_ISIS	131	/* 0x83 */
5817688Spst#define	NLPID_NULLNS	0
5917680Spst
6032149Spst
6132149Spst/*
6232149Spst * IS-IS is defined in ISO 10589.  Look there for protocol definitions.
6332149Spst */
6432149Spst
6532149Spst#define SYSTEM_ID_LEN	sizeof(struct ether_addr)
6632149Spst#define ISIS_VERSION	1
6732149Spst#define PDU_TYPE_MASK	0x1F
6832149Spst#define PRIORITY_MASK	0x7F
6932149Spst
7032149Spst#define L1_LAN_IIH	15
7132149Spst#define L2_LAN_IIH	16
7232149Spst#define PTP_IIH		17
7332149Spst#define L1_LS_PDU       18
7432149Spst#define L2_LS_PDU       19
7532149Spst#define L1_COMPLETE_SEQ_PDU  24
7632149Spst#define L2_COMPLETE_SEQ_PDU  25
7732149Spst
7832149Spst/*
7932149Spst * A TLV is a tuple of a type, length and a value and is normally used for
8032149Spst * encoding information in all sorts of places.  This is an enumeration of
8132149Spst * the well known types.
8232149Spst */
8332149Spst
8432149Spst#define TLV_AREA_ADDR   1
8532149Spst#define TLV_IS_REACH	2
8632149Spst#define TLV_ES_REACH	3
8732149Spst#define TLV_SUMMARY	5
8832149Spst#define TLV_ISNEIGH     6
8932149Spst#define TLV_PADDING     8
9032149Spst#define TLV_LSP		9
9132149Spst#define TLV_AUTHENT     10
9232149Spst#define TLV_IP_REACH	128
9332149Spst#define TLV_PROTOCOLS	129
9432149Spst#define TLV_IP_EXTERN	130
9532149Spst#define TLV_IDRP_INFO	131
9632149Spst#define TLV_IPADDR	132
9732149Spst#define TLV_IPAUTH	133
9832149Spst#define TLV_PTP_ADJ	240
9932149Spst
10032149Spst/*
10132149Spst * Katz's point to point adjacency TLV uses codes to tell us the state of
10232149Spst * the remote adjacency.  Enumerate them.
10332149Spst */
10432149Spst
10532149Spst#define ISIS_PTP_ADJ_UP   0
10632149Spst#define ISIS_PTP_ADJ_INIT 1
10732149Spst#define ISIS_PTP_ADJ_DOWN 2
10832149Spst
10917751Spststatic int osi_cksum(const u_char *, int, u_char *);
11017680Spststatic void esis_print(const u_char *, u_int);
11117688Spststatic int isis_print(const u_char *, u_int);
11217680Spst
11332149Spst
11432149Spststruct isis_ptp_adjancey_values {
11532149Spst	u_char id;
11632149Spst	char   *name;
11732149Spst};
11832149Spst
11932149Spststatic struct isis_ptp_adjancey_values isis_ptp_adjancey_values[] = {
12032149Spst	ISIS_PTP_ADJ_UP,    "UP",
12132149Spst	ISIS_PTP_ADJ_INIT,  "INIT",
12232149Spst        ISIS_PTP_ADJ_DOWN,  "DOWN"
12332149Spst};
12432149Spst
12532149Spststruct isis_common_header {
12632149Spst    u_char nlpid;
12732149Spst    u_char fixed_len;
12832149Spst    u_char version;			/* Protocol version? */
12932149Spst    u_char id_length;
13032149Spst    u_char enc_pdu_type;		/* 3 MSbs are reserved */
13132149Spst    u_char pkt_version;			/* Packet format version? */
13232149Spst    u_char reserved;
13332149Spst    u_char enc_max_area;
13432149Spst};
13532149Spst
13632149Spststruct isis_header {
13732149Spst    u_char nlpid;
13832149Spst    u_char fixed_len;
13932149Spst    u_char version;			/* Protocol version? */
14032149Spst    u_char id_length;
14132149Spst    u_char enc_pdu_type;		/* 3 MSbs are reserved */
14232149Spst    u_char pkt_version;			/* Packet format version? */
14332149Spst    u_char reserved;
14432149Spst    u_char enc_max_area;
14532149Spst    u_char circuit;
14632149Spst    u_char enc_source_id[SYSTEM_ID_LEN];
14732149Spst    u_char enc_holding_time[2];
14832149Spst    u_char enc_packet_len[2];
14932149Spst    u_char enc_priority;
15032149Spst    u_char enc_lan_id[SYSTEM_ID_LEN+1];
15132149Spst};
15232149Spststruct isis_lan_header {
15332149Spst    u_char circuit;
15432149Spst    u_char enc_source_id[SYSTEM_ID_LEN];
15532149Spst    u_char enc_holding_time[2];
15632149Spst    u_char enc_packet_len[2];
15732149Spst    u_char enc_priority;
15832149Spst    u_char enc_lan_id[SYSTEM_ID_LEN+1];
15932149Spst};
16032149Spst
16132149Spststruct isis_ptp_header {
16232149Spst    u_char circuit;
16332149Spst    u_char enc_source_id[SYSTEM_ID_LEN];
16432149Spst    u_char enc_holding_time[2];
16532149Spst    u_char enc_packet_len[2];
16632149Spst    u_char loc_circuit_id;
16732149Spst};
16832149Spst
16932149Spst#define ISIS_COMMON_HEADER_SIZE (sizeof(struct isis_common_header))
17032149Spst#define ISIS_HEADER_SIZE (15+(SYSTEM_ID_LEN<<1))
17132149Spst#define ISIS_PTP_HEADER_SIZE (14+SYSTEM_ID_LEN)
17232149Spst#define L1_LS_PDU_HEADER_SIZE (21+SYSTEM_ID_LEN)
17332149Spst#define L2_LS_PDU_HEADER_SIZE L1_LS_PDU_HEADER_SIZE
17432149Spst#define L1_COMPLETE_SEQ_PDU_HEADER_SIZE 33
17532149Spst#define L2_COMPLETE_SEQ_PDU_HEADER_SIZE L1_COMPLETE_SEQ_PDU_HEADER_SIZE
17632149Spst
17732149Spst
17832149Spst
17917680Spstvoid
18017680Spstisoclns_print(const u_char *p, u_int length, u_int caplen,
18117680Spst	      const u_char *esrc, const u_char *edst)
18217680Spst{
18332149Spst	u_char pdu_type;
18432149Spst	struct isis_header *header;
18532149Spst
18632149Spst	header = (struct isis_header *)p;
18732149Spst	pdu_type = header->enc_pdu_type & PDU_TYPE_MASK;
18832149Spst
18917680Spst	if (caplen < 1) {
19017680Spst		printf("[|iso-clns] ");
19117680Spst		if (!eflag)
19217680Spst			printf("%s > %s",
19317680Spst			       etheraddr_string(esrc),
19417680Spst			       etheraddr_string(edst));
19517680Spst		return;
19617680Spst	}
19717680Spst
19817680Spst	switch (*p) {
19917680Spst
20017688Spst	case NLPID_CLNS:
20117688Spst		printf("iso clns");
20217680Spst		if (!eflag)
20317680Spst			(void)printf(" %s > %s",
20417680Spst				     etheraddr_string(esrc),
20517680Spst				     etheraddr_string(edst));
20617680Spst		break;
20717680Spst
20817688Spst	case NLPID_ESIS:
20917688Spst		printf("iso esis");
21017680Spst		if (!eflag)
21117680Spst			(void)printf(" %s > %s",
21217680Spst				     etheraddr_string(esrc),
21317680Spst				     etheraddr_string(edst));
21417680Spst		esis_print(p, length);
21517680Spst		return;
21617680Spst
21717688Spst	case NLPID_ISIS:
21817688Spst		printf("iso isis");
21932149Spst		if (!eflag) {
22032149Spst			if(pdu_type != PTP_IIH)
22132149Spst				(void)printf(" %s > %s",
22217680Spst				     etheraddr_string(esrc),
22317680Spst				     etheraddr_string(edst));
22432149Spst		}
22517680Spst		(void)printf(" len=%d ", length);
22617751Spst		if (!isis_print(p, length))
22717688Spst		    default_print_unaligned(p, caplen);
22817680Spst		break;
22917680Spst
23017688Spst	case NLPID_NULLNS:
23117688Spst		printf("iso nullns");
23217680Spst		if (!eflag)
23317680Spst			(void)printf(" %s > %s",
23417680Spst				     etheraddr_string(esrc),
23517680Spst				     etheraddr_string(edst));
23617680Spst		break;
23717680Spst
23817680Spst	default:
23917688Spst		printf("iso clns %02x", p[0]);
24017680Spst		if (!eflag)
24117680Spst			(void)printf(" %s > %s",
24217680Spst				     etheraddr_string(esrc),
24317680Spst				     etheraddr_string(edst));
24417680Spst		(void)printf(" len=%d ", length);
24517680Spst		if (caplen > 1)
24617680Spst			default_print_unaligned(p, caplen);
24717680Spst		break;
24817680Spst	}
24917680Spst}
25017680Spst
25117680Spst#define	ESIS_REDIRECT	6
25217680Spst#define	ESIS_ESH	2
25317680Spst#define	ESIS_ISH	4
25417680Spst
25517680Spststruct esis_hdr {
25617680Spst	u_char version;
25717680Spst	u_char reserved;
25817680Spst	u_char type;
25917680Spst	u_char tmo[2];
26017680Spst	u_char cksum[2];
26117680Spst};
26217680Spst
26317680Spststatic void
26417680Spstesis_print(const u_char *p, u_int length)
26517680Spst{
26617680Spst	const u_char *ep;
26717680Spst	int li = p[1];
26817680Spst	const struct esis_hdr *eh = (const struct esis_hdr *) &p[2];
26917680Spst	u_char cksum[2];
27017680Spst	u_char off[2];
27117680Spst
27217680Spst	if (length == 2) {
27317680Spst		if (qflag)
27417680Spst			printf(" bad pkt!");
27517680Spst		else
27617680Spst			printf(" no header at all!");
27717680Spst		return;
27817680Spst	}
27917680Spst	ep = p + li;
28017680Spst	if (li > length) {
28117680Spst		if (qflag)
28217680Spst			printf(" bad pkt!");
28317680Spst		else
28417680Spst			printf(" LI(%d) > PDU size (%d)!", li, length);
28517680Spst		return;
28617680Spst	}
28717680Spst	if (li < sizeof(struct esis_hdr) + 2) {
28817680Spst		if (qflag)
28917680Spst			printf(" bad pkt!");
29017680Spst		else {
29117680Spst			printf(" too short for esis header %d:", li);
29239300Sfenner			while (--length != 0)
29317680Spst				printf("%02X", *p++);
29417680Spst		}
29517680Spst		return;
29617680Spst	}
29717680Spst	switch (eh->type & 0x1f) {
29817680Spst
29917680Spst	case ESIS_REDIRECT:
30017680Spst		printf(" redirect");
30117680Spst		break;
30217680Spst
30317680Spst	case ESIS_ESH:
30417680Spst		printf(" esh");
30517680Spst		break;
30617680Spst
30717680Spst	case ESIS_ISH:
30817680Spst		printf(" ish");
30917680Spst		break;
31017680Spst
31117680Spst	default:
31217680Spst		printf(" type %d", eh->type & 0x1f);
31317680Spst		break;
31417680Spst	}
31517680Spst	off[0] = eh->cksum[0];
31617680Spst	off[1] = eh->cksum[1];
31717751Spst	if (vflag && osi_cksum(p, li, off)) {
31817751Spst		printf(" bad cksum (got %02x%02x)",
31917751Spst		       eh->cksum[1], eh->cksum[0]);
32017751Spst		default_print(p, length);
32117680Spst		return;
32217680Spst	}
32317680Spst	if (eh->version != 1) {
32417680Spst		printf(" unsupported version %d", eh->version);
32517680Spst		return;
32617680Spst	}
32717680Spst	p += sizeof(*eh) + 2;
32817680Spst	li -= sizeof(*eh) + 2;	/* protoid * li */
32917680Spst
33017680Spst	switch (eh->type & 0x1f) {
33117680Spst	case ESIS_REDIRECT: {
33217680Spst		const u_char *dst, *snpa, *is;
33317680Spst
33417680Spst		dst = p; p += *p + 1;
33517680Spst		if (p > snapend)
33617680Spst			return;
33717688Spst		printf("\n\t\t\t %s", isonsap_string(dst));
33817680Spst		snpa = p; p += *p + 1;
33917680Spst		is = p;   p += *p + 1;
34017680Spst		if (p > snapend)
34117680Spst			return;
34217680Spst		if (p > ep) {
34317680Spst			printf(" [bad li]");
34417680Spst			return;
34517680Spst		}
34617680Spst		if (is[0] == 0)
34717680Spst			printf(" > %s", etheraddr_string(&snpa[1]));
34817680Spst		else
34917680Spst			printf(" > %s", isonsap_string(is));
35017680Spst		li = ep - p;
35117680Spst		break;
35217680Spst	}
35317680Spst#if 0
35417680Spst	case ESIS_ESH:
35517680Spst		printf(" esh");
35617680Spst		break;
35717680Spst#endif
35817680Spst	case ESIS_ISH: {
35917680Spst		const u_char *is;
36017680Spst
36117680Spst		is = p; p += *p + 1;
36217680Spst		if (p > ep) {
36317680Spst			printf(" [bad li]");
36417680Spst			return;
36517680Spst		}
36617680Spst		if (p > snapend)
36717680Spst			return;
36817751Spst		if (!qflag)
36917751Spst			printf("\n\t\t\t %s", isonsap_string(is));
37017680Spst		li = ep - p;
37117680Spst		break;
37217680Spst	}
37317680Spst
37417680Spst	default:
37517680Spst		(void)printf(" len=%d", length);
37617680Spst		if (length && p < snapend) {
37717680Spst			length = snapend - p;
37817680Spst			default_print(p, length);
37917680Spst		}
38017680Spst		return;
38117680Spst	}
38217680Spst	if (vflag)
38317680Spst		while (p < ep && li) {
38417680Spst			int op, opli;
38517680Spst			const u_char *q;
38617680Spst
38717680Spst			if (snapend - p < 2)
38817680Spst				return;
38917680Spst			if (li < 2) {
39017680Spst				printf(" bad opts/li");
39117680Spst				return;
39217680Spst			}
39317680Spst			op = *p++;
39417680Spst			opli = *p++;
39517680Spst			li -= 2;
39617680Spst			if (opli > li) {
39717680Spst				printf(" opt (%d) too long", op);
39817680Spst				return;
39917680Spst			}
40017680Spst			li -= opli;
40117680Spst			q = p;
40217680Spst			p += opli;
40317680Spst			if (snapend < p)
40417680Spst				return;
40517680Spst			if (op == 198 && opli == 2) {
40617680Spst				printf(" tmo=%d", q[0] * 256 + q[1]);
40717680Spst				continue;
40817680Spst			}
40917680Spst			printf (" %d:<", op);
41017680Spst			while (--opli >= 0)
41117680Spst				printf("%02x", *q++);
41217680Spst			printf (">");
41317680Spst		}
41417680Spst}
41517680Spst
41617688Spst/*
41717688Spst * print_nsap
41817688Spst * Print out an NSAP.
41917688Spst */
42017688Spst
42117688Spstvoid
42217688Spstprint_nsap (register const u_char *cp, register int length)
42317688Spst{
42417688Spst    int i;
42517688Spst
42617688Spst    for (i = 0; i < length; i++) {
42717688Spst	printf("%02x", *cp++);
42817688Spst	if (((i & 1) == 0) && (i + 1 < length)) {
42917688Spst	    printf(".");
43017688Spst	}
43117688Spst
43217688Spst    }
43317688Spst}
43417688Spst
43517688Spst/*
43617688Spst * isis_print
43717688Spst * Decode IS-IS packets.  Return 0 on error.
43817688Spst *
43917688Spst * So far, this is only smart enough to print IIH's.  Someday...
44017688Spst */
44117688Spst
44217680Spststatic int
44317688Spstisis_print (const u_char *p, u_int length)
44417688Spst{
44517688Spst    struct isis_header *header;
44632149Spst    struct isis_ptp_header *header_ptp;
44717688Spst    u_char pdu_type, max_area, priority, *pptr, type, len, *tptr, tmp, alen;
44817688Spst    u_short packet_len, holding_time;
44932149Spst    int i;
45017688Spst
45132149Spst    header_ptp = (struct isis_ptp_header *)header = (struct isis_header *)p;
45217688Spst    printf("\n\t\t\t");
45317688Spst
45417688Spst    /*
45517688Spst     * Sanity checking of the header.
45617688Spst     */
45717688Spst    if (header->nlpid != NLPID_ISIS) {
45817688Spst	printf(" coding error!");
45917688Spst	return(0);
46017688Spst    }
46117688Spst
46217688Spst    if (header->version != ISIS_VERSION) {
46317688Spst	printf(" version %d packet not supported", header->version);
46417688Spst	return(0);
46517688Spst    }
46617688Spst
46717688Spst    if ((header->id_length != SYSTEM_ID_LEN) && (header->id_length != 0)) {
46817688Spst	printf(" system ID length of %d is not supported",
46917688Spst	       header->id_length);
47017688Spst	return(0);
47117688Spst    }
47217688Spst
47332149Spst    if ((header->fixed_len != ISIS_HEADER_SIZE) &&
47432149Spst	(header->fixed_len != ISIS_PTP_HEADER_SIZE) &&
47532149Spst	(header->fixed_len != L1_LS_PDU_HEADER_SIZE) &&
47632149Spst	(header-> fixed_len != L1_COMPLETE_SEQ_PDU_HEADER_SIZE) ) {
47732149Spst	    printf(" bogus fixed header length",
47832149Spst		   header->fixed_len);
47932149Spst	    return(0);
48017688Spst    }
48117688Spst
48217688Spst    pdu_type = header->enc_pdu_type & PDU_TYPE_MASK;
48332149Spst    if ((pdu_type != L1_LAN_IIH) && (pdu_type != L2_LAN_IIH) &&
48432149Spst	(pdu_type != PTP_IIH) &&
48532149Spst	(pdu_type != L1_COMPLETE_SEQ_PDU) &&
48632149Spst	(pdu_type != L2_COMPLETE_SEQ_PDU) ) {
48717688Spst	printf(" PDU type (%d) not supported", pdu_type);
48817688Spst	return;
48917688Spst    }
49017688Spst
49117688Spst    if (header->pkt_version != ISIS_VERSION) {
49217688Spst	printf(" version %d packet not supported", header->pkt_version);
49317688Spst	return;
49417688Spst    }
49517688Spst
49617688Spst    max_area = header->enc_max_area;
49717688Spst    switch(max_area) {
49817688Spst    case 0:
49917688Spst	max_area = 3;			/* silly shit */
50017688Spst	break;
50117688Spst    case 255:
50217688Spst	printf(" bad packet -- 255 areas");
50317688Spst	return(0);
50417688Spst    default:
50517688Spst	break;
50617688Spst    }
50717688Spst
50817688Spst    switch (header->circuit) {
50917688Spst    case 0:
51017688Spst	printf(" PDU with circuit type 0");
51117688Spst	return(0);
51217688Spst    case 1:
51317688Spst	if (pdu_type == L2_LAN_IIH) {
51417688Spst	    printf(" L2 IIH on an L1 only circuit");
51517688Spst	    return(0);
51617688Spst	}
51717688Spst	break;
51817688Spst    case 2:
51917688Spst	if (pdu_type == L1_LAN_IIH) {
52017688Spst	    printf(" L1 IIH on an L2 only circuit");
52117688Spst	    return(0);
52217688Spst	}
52317688Spst	break;
52417688Spst    case 3:
52517688Spst	break;
52617688Spst    default:
52717688Spst	printf(" unknown circuit type");
52817688Spst	return(0);
52917688Spst    }
53017688Spst
53117688Spst    holding_time = EXTRACT_16BITS(header->enc_holding_time);
53217688Spst
53317688Spst    packet_len = EXTRACT_16BITS(header->enc_packet_len);
53417688Spst    if ((packet_len < ISIS_HEADER_SIZE) ||
53517688Spst	(packet_len > length)) {
53617688Spst	printf(" bogus packet length %d, real length %d", packet_len,
53717688Spst	       length);
53817688Spst	return(0);
53917688Spst    }
54017688Spst
54132149Spst    if(pdu_type != PTP_IIH)
54232149Spst	    priority = header->enc_priority & PRIORITY_MASK;
54317688Spst
54417688Spst    /*
54517688Spst     * Now print the fixed header.
54617688Spst     */
54717688Spst    switch (pdu_type) {
54817688Spst    case L1_LAN_IIH:
54917688Spst	printf(" L1 lan iih, ");
55017688Spst	break;
55117688Spst    case L2_LAN_IIH:
55217688Spst	printf(" L2 lan iih, ");
55317688Spst	break;
55432149Spst    case PTP_IIH:
55532149Spst	printf(" PTP iih, ");
55632149Spst	break;
55717688Spst    }
55817688Spst
55917688Spst    printf("circuit ");
56017688Spst    switch (header->circuit) {
56117688Spst    case 1:
56217688Spst	printf("l1 only, ");
56317688Spst	break;
56417688Spst    case 2:
56517688Spst	printf("l2 only, ");
56617688Spst	break;
56717688Spst    case 3:
56817688Spst	printf("l1-l2, ");
56917688Spst	break;
57017688Spst    }
57117688Spst
57217688Spst    printf ("holding time %d ", holding_time);
57317688Spst    printf ("\n\t\t\t source %s, length %d",
57417688Spst	    etheraddr_string(header->enc_source_id), packet_len);
57532149Spst    if((pdu_type==L1_LAN_IIH)||(pdu_type==L2_LAN_IIH))
57632149Spst	    printf ("\n\t\t\t lan id %s(%d)", etheraddr_string(header->enc_lan_id),
57732149Spst		    header->enc_lan_id[SYSTEM_ID_LEN]);
57817688Spst
57917688Spst    /*
58017688Spst     * Now print the TLV's.
58117688Spst     */
58232149Spst    if(pdu_type==PTP_IIH) {
58332149Spst	    packet_len -= ISIS_PTP_HEADER_SIZE;
58432149Spst	    pptr = (char *)p + ISIS_PTP_HEADER_SIZE;
58532149Spst    } else {
58632149Spst	    packet_len -= ISIS_HEADER_SIZE;
58732149Spst	    pptr = (char *)p + ISIS_HEADER_SIZE;
58832149Spst    }
58917688Spst    while (packet_len >= 2) {
59017688Spst	if (pptr >= snapend) {
59117688Spst	    printf("\n\t\t\t packet exceeded snapshot");
59217688Spst	    return(1);
59317688Spst	}
59417688Spst	type = *pptr++;
59517688Spst	len = *pptr++;
59617688Spst	packet_len -= 2;
59717688Spst	if (len > packet_len) {
59817688Spst	    break;
59917688Spst	}
60017688Spst
60117688Spst	switch (type) {
60217688Spst	case TLV_AREA_ADDR:
60317688Spst	    printf("\n\t\t\t area addresses");
60417688Spst	    tmp = len;
60517688Spst	    tptr = pptr;
60617688Spst	    alen = *tptr++;
60717688Spst	    while (tmp && alen < tmp) {
60817688Spst		printf("\n\t\t\t ");
60917688Spst		print_nsap(tptr, alen);
61017688Spst		printf(" (%d)", alen);
61117688Spst		tptr += alen;
61217688Spst		tmp -= alen + 1;
61317688Spst		alen = *tptr++;
61417688Spst	    }
61517688Spst	    break;
61617688Spst	case TLV_ISNEIGH:
61717688Spst	    printf("\n\t\t\t neighbor addresses");
61817688Spst	    tmp = len;
61917688Spst	    tptr = pptr;
62017688Spst	    while (tmp >= sizeof(struct ether_addr)) {
62117688Spst		printf("\n\t\t\t %s", etheraddr_string(tptr));
62217688Spst		tmp -= sizeof(struct ether_addr);
62317688Spst		tptr += sizeof(struct ether_addr);
62417688Spst	    }
62517688Spst	    break;
62617688Spst	case TLV_PADDING:
62717688Spst	    printf("\n\t\t\t padding for %d bytes", len);
62817688Spst	    break;
62917688Spst	case TLV_AUTHENT:
63017688Spst	    printf("\n\t\t\t authentication data");
63117688Spst	    default_print(pptr, len);
63217688Spst	    break;
63332149Spst	case TLV_PTP_ADJ:
63432149Spst	    printf("\n\t\t\t PTP adjacency status %s",
63532149Spst		   isis_ptp_adjancey_values[*pptr].name);
63632149Spst	    break;
63732149Spst	case TLV_PROTOCOLS:
63832149Spst	    printf("\n\t\t\t Supports protocols %s", (len>1)? "are":"is");
63932149Spst	    for(i=0;i<len;i++)
64032149Spst		printf(" %02X", (u_char)*(pptr+i));
64132149Spst	    break;
64232149Spst	case TLV_IPADDR:
64332149Spst	    printf("\n\t\t\t IP address: %s", ipaddr_string(pptr));
64432149Spst	    break;
64517688Spst	default:
64617688Spst	    printf("\n\t\t\t unknown TLV, type %d, length %d", type, len);
64717688Spst	    break;
64817688Spst	}
64917688Spst
65017688Spst	pptr += len;
65117688Spst	packet_len -= len;
65217688Spst    }
65317688Spst
65417688Spst    if (packet_len != 0) {
65517688Spst	printf("\n\t\t\t %d straggler bytes", packet_len);
65617688Spst    }
65717688Spst    return(1);
65817688Spst}
65917688Spst
66017751Spst/*
66117751Spst * Verify the checksum.  See 8473-1, Appendix C, section C.4.
66217751Spst */
66317751Spst
66417688Spststatic int
66517751Spstosi_cksum(register const u_char *p, register int len, u_char *off)
66617680Spst{
66717680Spst	int32_t c0 = 0, c1 = 0;
66817680Spst
66917751Spst	if ((off[0] == 0) && (off[1] == 0))
67017680Spst		return 0;
67117680Spst
67239300Sfenner	off[0] = off[1] = 0;
67339300Sfenner	while ((int)--len >= 0) {
67417680Spst		c0 += *p++;
67517751Spst		c0 %= 255;
67617680Spst		c1 += c0;
67717680Spst		c1 %= 255;
67817680Spst	}
67917751Spst	return (c0 | c1);
68017680Spst}
681