print-isoclns.c revision 17688
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.
2017680Spst */
2117680Spst
2217680Spst/*
2317680Spst * Original code by Matt Thomas, Digital Equipment Corporation
2417680Spst */
2517680Spst
2617680Spst#ifndef lint
2717680Spststatic char rcsid[] =
2817680Spst    "@(#) $Header: print-isoclns.c,v 1.12 96/07/14 19:39:00 leres Exp $ (LBL)";
2917680Spst#endif
3017680Spst
3117680Spst#include <sys/types.h>
3217680Spst#include <sys/time.h>
3317680Spst#include <sys/socket.h>
3417680Spst
3517680Spst#if __STDC__
3617680Spststruct mbuf;
3717680Spststruct rtentry;
3817680Spst#endif
3917680Spst#include <net/if.h>
4017680Spst
4117680Spst#include <netinet/in.h>
4217680Spst#include <netinet/if_ether.h>
4317680Spst
4417680Spst#include <stdio.h>
4517680Spst
4617680Spst#include "interface.h"
4717680Spst#include "addrtoname.h"
4817680Spst#include "ethertype.h"
4917688Spst#include "extract.h"
5017680Spst
5117688Spst#define	NLPID_CLNS	129	/* 0x81 */
5217688Spst#define	NLPID_ESIS	130	/* 0x82 */
5317688Spst#define	NLPID_ISIS	131	/* 0x83 */
5417688Spst#define	NLPID_NULLNS	0
5517680Spst
5617680Spststatic int osi_cksum(const u_char *, u_int, const u_char *, u_char *, u_char *);
5717680Spststatic void esis_print(const u_char *, u_int);
5817688Spststatic int isis_print(const u_char *, u_int);
5917680Spst
6017680Spstvoid
6117680Spstisoclns_print(const u_char *p, u_int length, u_int caplen,
6217680Spst	      const u_char *esrc, const u_char *edst)
6317680Spst{
6417680Spst	if (caplen < 1) {
6517680Spst		printf("[|iso-clns] ");
6617680Spst		if (!eflag)
6717680Spst			printf("%s > %s",
6817680Spst			       etheraddr_string(esrc),
6917680Spst			       etheraddr_string(edst));
7017680Spst		return;
7117680Spst	}
7217680Spst
7317680Spst	switch (*p) {
7417680Spst
7517688Spst	case NLPID_CLNS:
7617680Spst		/* esis_print(&p, &length); */
7717688Spst		printf("iso clns");
7817680Spst		if (!eflag)
7917680Spst			(void)printf(" %s > %s",
8017680Spst				     etheraddr_string(esrc),
8117680Spst				     etheraddr_string(edst));
8217680Spst		break;
8317680Spst
8417688Spst	case NLPID_ESIS:
8517688Spst		printf("iso esis");
8617680Spst		if (!eflag)
8717680Spst			(void)printf(" %s > %s",
8817680Spst				     etheraddr_string(esrc),
8917680Spst				     etheraddr_string(edst));
9017680Spst		esis_print(p, length);
9117680Spst		return;
9217680Spst
9317688Spst	case NLPID_ISIS:
9417688Spst		printf("iso isis");
9517680Spst		if (!eflag)
9617680Spst			(void)printf(" %s > %s",
9717680Spst				     etheraddr_string(esrc),
9817680Spst				     etheraddr_string(edst));
9917680Spst		(void)printf(" len=%d ", length);
10017688Spst		if (!isis_print(p, length)) {
10117688Spst		    default_print_unaligned(p, caplen);
10217688Spst		}
10317680Spst		break;
10417680Spst
10517688Spst	case NLPID_NULLNS:
10617688Spst		printf("iso nullns");
10717680Spst		if (!eflag)
10817680Spst			(void)printf(" %s > %s",
10917680Spst				     etheraddr_string(esrc),
11017680Spst				     etheraddr_string(edst));
11117680Spst		break;
11217680Spst
11317680Spst	default:
11417688Spst		printf("iso clns %02x", p[0]);
11517680Spst		if (!eflag)
11617680Spst			(void)printf(" %s > %s",
11717680Spst				     etheraddr_string(esrc),
11817680Spst				     etheraddr_string(edst));
11917680Spst		(void)printf(" len=%d ", length);
12017680Spst		if (caplen > 1)
12117680Spst			default_print_unaligned(p, caplen);
12217680Spst		break;
12317680Spst	}
12417680Spst}
12517680Spst
12617680Spst#define	ESIS_REDIRECT	6
12717680Spst#define	ESIS_ESH	2
12817680Spst#define	ESIS_ISH	4
12917680Spst
13017680Spststruct esis_hdr {
13117680Spst	u_char version;
13217680Spst	u_char reserved;
13317680Spst	u_char type;
13417680Spst	u_char tmo[2];
13517680Spst	u_char cksum[2];
13617680Spst};
13717680Spst
13817680Spststatic void
13917680Spstesis_print(const u_char *p, u_int length)
14017680Spst{
14117680Spst	const u_char *ep;
14217680Spst	int li = p[1];
14317680Spst	const struct esis_hdr *eh = (const struct esis_hdr *) &p[2];
14417680Spst	u_char cksum[2];
14517680Spst	u_char off[2];
14617680Spst
14717680Spst	if (length == 2) {
14817680Spst		if (qflag)
14917680Spst			printf(" bad pkt!");
15017680Spst		else
15117680Spst			printf(" no header at all!");
15217680Spst		return;
15317680Spst	}
15417680Spst	ep = p + li;
15517680Spst	if (li > length) {
15617680Spst		if (qflag)
15717680Spst			printf(" bad pkt!");
15817680Spst		else
15917680Spst			printf(" LI(%d) > PDU size (%d)!", li, length);
16017680Spst		return;
16117680Spst	}
16217680Spst	if (li < sizeof(struct esis_hdr) + 2) {
16317680Spst		if (qflag)
16417680Spst			printf(" bad pkt!");
16517680Spst		else {
16617680Spst			printf(" too short for esis header %d:", li);
16717680Spst			while (--length >= 0)
16817680Spst				printf("%02X", *p++);
16917680Spst		}
17017680Spst		return;
17117680Spst	}
17217680Spst	switch (eh->type & 0x1f) {
17317680Spst
17417680Spst	case ESIS_REDIRECT:
17517680Spst		printf(" redirect");
17617680Spst		break;
17717680Spst
17817680Spst	case ESIS_ESH:
17917680Spst		printf(" esh");
18017680Spst		break;
18117680Spst
18217680Spst	case ESIS_ISH:
18317680Spst		printf(" ish");
18417680Spst		break;
18517680Spst
18617680Spst	default:
18717680Spst		printf(" type %d", eh->type & 0x1f);
18817680Spst		break;
18917680Spst	}
19017680Spst	off[0] = eh->cksum[0];
19117680Spst	off[1] = eh->cksum[1];
19217680Spst	if (vflag && osi_cksum(p, li, eh->cksum, cksum, off)) {
19317680Spst		printf(" bad cksum (got %02x%02x want %02x%02x)",
19417680Spst		       eh->cksum[1], eh->cksum[0], cksum[1], cksum[0]);
19517680Spst		return;
19617680Spst	}
19717680Spst	if (eh->version != 1) {
19817680Spst		printf(" unsupported version %d", eh->version);
19917680Spst		return;
20017680Spst	}
20117680Spst	p += sizeof(*eh) + 2;
20217680Spst	li -= sizeof(*eh) + 2;	/* protoid * li */
20317680Spst
20417680Spst	switch (eh->type & 0x1f) {
20517680Spst	case ESIS_REDIRECT: {
20617680Spst		const u_char *dst, *snpa, *is;
20717680Spst
20817680Spst		dst = p; p += *p + 1;
20917680Spst		if (p > snapend)
21017680Spst			return;
21117688Spst		printf("\n\t\t\t %s", isonsap_string(dst));
21217680Spst		snpa = p; p += *p + 1;
21317680Spst		is = p;   p += *p + 1;
21417680Spst		if (p > snapend)
21517680Spst			return;
21617680Spst		if (p > ep) {
21717680Spst			printf(" [bad li]");
21817680Spst			return;
21917680Spst		}
22017680Spst		if (is[0] == 0)
22117680Spst			printf(" > %s", etheraddr_string(&snpa[1]));
22217680Spst		else
22317680Spst			printf(" > %s", isonsap_string(is));
22417680Spst		li = ep - p;
22517680Spst		break;
22617680Spst	}
22717680Spst#if 0
22817680Spst	case ESIS_ESH:
22917680Spst		printf(" esh");
23017680Spst		break;
23117680Spst#endif
23217680Spst	case ESIS_ISH: {
23317680Spst		const u_char *is;
23417680Spst
23517680Spst		is = p; p += *p + 1;
23617680Spst		if (p > ep) {
23717680Spst			printf(" [bad li]");
23817680Spst			return;
23917680Spst		}
24017680Spst		if (p > snapend)
24117680Spst			return;
24217688Spst		printf("\n\t\t\t %s", isonsap_string(is));
24317680Spst		li = ep - p;
24417680Spst		break;
24517680Spst	}
24617680Spst
24717680Spst	default:
24817680Spst		(void)printf(" len=%d", length);
24917680Spst		if (length && p < snapend) {
25017680Spst			length = snapend - p;
25117680Spst			default_print(p, length);
25217680Spst		}
25317680Spst		return;
25417680Spst	}
25517680Spst	if (vflag)
25617680Spst		while (p < ep && li) {
25717680Spst			int op, opli;
25817680Spst			const u_char *q;
25917680Spst
26017680Spst			if (snapend - p < 2)
26117680Spst				return;
26217680Spst			if (li < 2) {
26317680Spst				printf(" bad opts/li");
26417680Spst				return;
26517680Spst			}
26617680Spst			op = *p++;
26717680Spst			opli = *p++;
26817680Spst			li -= 2;
26917680Spst			if (opli > li) {
27017680Spst				printf(" opt (%d) too long", op);
27117680Spst				return;
27217680Spst			}
27317680Spst			li -= opli;
27417680Spst			q = p;
27517680Spst			p += opli;
27617680Spst			if (snapend < p)
27717680Spst				return;
27817680Spst			if (op == 198 && opli == 2) {
27917680Spst				printf(" tmo=%d", q[0] * 256 + q[1]);
28017680Spst				continue;
28117680Spst			}
28217680Spst			printf (" %d:<", op);
28317680Spst			while (--opli >= 0)
28417680Spst				printf("%02x", *q++);
28517680Spst			printf (">");
28617680Spst		}
28717680Spst}
28817680Spst
28917688Spst/*
29017688Spst * print_nsap
29117688Spst * Print out an NSAP.
29217688Spst */
29317688Spst
29417688Spstvoid
29517688Spstprint_nsap (register const u_char *cp, register int length)
29617688Spst{
29717688Spst    int i;
29817688Spst
29917688Spst    for (i = 0; i < length; i++) {
30017688Spst	printf("%02x", *cp++);
30117688Spst	if (((i & 1) == 0) && (i + 1 < length)) {
30217688Spst	    printf(".");
30317688Spst	}
30417688Spst
30517688Spst    }
30617688Spst}
30717688Spst
30817688Spst/*
30917688Spst * IS-IS is defined in ISO 10589.  Look there for protocol definitions.
31017688Spst */
31117688Spst
31217688Spst#define SYSTEM_ID_LEN	sizeof(struct ether_addr)
31317688Spst#define ISIS_VERSION	1
31417688Spst#define PDU_TYPE_MASK	0x1F
31517688Spst#define PRIORITY_MASK	0x7F
31617688Spst
31717688Spst#define L1_LAN_IIH	15
31817688Spst#define L2_LAN_IIH	16
31917688Spst#define PTP_IIH		17
32017688Spst
32117688Spst#define TLV_AREA_ADDR	1
32217688Spst#define TLV_ISNEIGH	6
32317688Spst#define TLV_PADDING	8
32417688Spst#define TLV_AUTHENT	10
32517688Spst
32617688Spststruct isis_header {
32717688Spst    u_char nlpid;
32817688Spst    u_char fixed_len;
32917688Spst    u_char version;			/* Protocol version? */
33017688Spst    u_char id_length;
33117688Spst    u_char enc_pdu_type;		/* 3 MSbs are reserved */
33217688Spst    u_char pkt_version;			/* Packet format version? */
33317688Spst    u_char reserved;
33417688Spst    u_char enc_max_area;
33517688Spst    u_char circuit;
33617688Spst    u_char enc_source_id[SYSTEM_ID_LEN];
33717688Spst    u_char enc_holding_time[2];
33817688Spst    u_char enc_packet_len[2];
33917688Spst    u_char enc_priority;
34017688Spst    u_char enc_lan_id[SYSTEM_ID_LEN+1];
34117688Spst};
34217688Spst
34317688Spst#define ISIS_HEADER_SIZE (15+(SYSTEM_ID_LEN<<1))
34417688Spst
34517688Spst/*
34617688Spst * isis_print
34717688Spst * Decode IS-IS packets.  Return 0 on error.
34817688Spst *
34917688Spst * So far, this is only smart enough to print IIH's.  Someday...
35017688Spst */
35117688Spst
35217680Spststatic int
35317688Spstisis_print (const u_char *p, u_int length)
35417688Spst{
35517688Spst    struct isis_header *header;
35617688Spst    u_char pdu_type, max_area, priority, *pptr, type, len, *tptr, tmp, alen;
35717688Spst    u_short packet_len, holding_time;
35817688Spst
35917688Spst    header = (struct isis_header *)p;
36017688Spst    printf("\n\t\t\t");
36117688Spst
36217688Spst    /*
36317688Spst     * Sanity checking of the header.
36417688Spst     */
36517688Spst    if (header->nlpid != NLPID_ISIS) {
36617688Spst	printf(" coding error!");
36717688Spst	return(0);
36817688Spst    }
36917688Spst
37017688Spst    if (header->version != ISIS_VERSION) {
37117688Spst	printf(" version %d packet not supported", header->version);
37217688Spst	return(0);
37317688Spst    }
37417688Spst
37517688Spst    if ((header->id_length != SYSTEM_ID_LEN) && (header->id_length != 0)) {
37617688Spst	printf(" system ID length of %d is not supported",
37717688Spst	       header->id_length);
37817688Spst	return(0);
37917688Spst    }
38017688Spst
38117688Spst    if ((header->fixed_len != ISIS_HEADER_SIZE)) {
38217688Spst	printf(" bogus fixed header length %d should be %d",
38317688Spst	       header->fixed_len, ISIS_HEADER_SIZE);
38417688Spst	return(0);
38517688Spst    }
38617688Spst
38717688Spst    pdu_type = header->enc_pdu_type & PDU_TYPE_MASK;
38817688Spst    if ((pdu_type != L1_LAN_IIH) && (pdu_type != L2_LAN_IIH)) {
38917688Spst	printf(" PDU type (%d) not supported", pdu_type);
39017688Spst	return;
39117688Spst    }
39217688Spst
39317688Spst    if (header->pkt_version != ISIS_VERSION) {
39417688Spst	printf(" version %d packet not supported", header->pkt_version);
39517688Spst	return;
39617688Spst    }
39717688Spst
39817688Spst    max_area = header->enc_max_area;
39917688Spst    switch(max_area) {
40017688Spst    case 0:
40117688Spst	max_area = 3;			/* silly shit */
40217688Spst	break;
40317688Spst    case 255:
40417688Spst	printf(" bad packet -- 255 areas");
40517688Spst	return(0);
40617688Spst    default:
40717688Spst	break;
40817688Spst    }
40917688Spst
41017688Spst    switch (header->circuit) {
41117688Spst    case 0:
41217688Spst	printf(" PDU with circuit type 0");
41317688Spst	return(0);
41417688Spst    case 1:
41517688Spst	if (pdu_type == L2_LAN_IIH) {
41617688Spst	    printf(" L2 IIH on an L1 only circuit");
41717688Spst	    return(0);
41817688Spst	}
41917688Spst	break;
42017688Spst    case 2:
42117688Spst	if (pdu_type == L1_LAN_IIH) {
42217688Spst	    printf(" L1 IIH on an L2 only circuit");
42317688Spst	    return(0);
42417688Spst	}
42517688Spst	break;
42617688Spst    case 3:
42717688Spst	break;
42817688Spst    default:
42917688Spst	printf(" unknown circuit type");
43017688Spst	return(0);
43117688Spst    }
43217688Spst
43317688Spst    holding_time = EXTRACT_16BITS(header->enc_holding_time);
43417688Spst
43517688Spst    packet_len = EXTRACT_16BITS(header->enc_packet_len);
43617688Spst    if ((packet_len < ISIS_HEADER_SIZE) ||
43717688Spst	(packet_len > length)) {
43817688Spst	printf(" bogus packet length %d, real length %d", packet_len,
43917688Spst	       length);
44017688Spst	return(0);
44117688Spst    }
44217688Spst
44317688Spst    priority = header->enc_priority & PRIORITY_MASK;
44417688Spst
44517688Spst    /*
44617688Spst     * Now print the fixed header.
44717688Spst     */
44817688Spst    switch (pdu_type) {
44917688Spst    case L1_LAN_IIH:
45017688Spst	printf(" L1 lan iih, ");
45117688Spst	break;
45217688Spst    case L2_LAN_IIH:
45317688Spst	printf(" L2 lan iih, ");
45417688Spst	break;
45517688Spst    }
45617688Spst
45717688Spst    printf("circuit ");
45817688Spst    switch (header->circuit) {
45917688Spst    case 1:
46017688Spst	printf("l1 only, ");
46117688Spst	break;
46217688Spst    case 2:
46317688Spst	printf("l2 only, ");
46417688Spst	break;
46517688Spst    case 3:
46617688Spst	printf("l1-l2, ");
46717688Spst	break;
46817688Spst    }
46917688Spst
47017688Spst    printf ("holding time %d ", holding_time);
47117688Spst    printf ("\n\t\t\t source %s, length %d",
47217688Spst	    etheraddr_string(header->enc_source_id), packet_len);
47317688Spst    printf ("\n\t\t\t lan id %s(%d)", etheraddr_string(header->enc_lan_id),
47417688Spst	    header->enc_lan_id[SYSTEM_ID_LEN]);
47517688Spst
47617688Spst    /*
47717688Spst     * Now print the TLV's.
47817688Spst     */
47917688Spst    packet_len -= ISIS_HEADER_SIZE;
48017688Spst    pptr = (char *)p + ISIS_HEADER_SIZE;
48117688Spst    while (packet_len >= 2) {
48217688Spst	if (pptr >= snapend) {
48317688Spst	    printf("\n\t\t\t packet exceeded snapshot");
48417688Spst	    return(1);
48517688Spst	}
48617688Spst	type = *pptr++;
48717688Spst	len = *pptr++;
48817688Spst	packet_len -= 2;
48917688Spst	if (len > packet_len) {
49017688Spst	    break;
49117688Spst	}
49217688Spst
49317688Spst	switch (type) {
49417688Spst	case TLV_AREA_ADDR:
49517688Spst	    printf("\n\t\t\t area addresses");
49617688Spst	    tmp = len;
49717688Spst	    tptr = pptr;
49817688Spst	    alen = *tptr++;
49917688Spst	    while (tmp && alen < tmp) {
50017688Spst		printf("\n\t\t\t ");
50117688Spst		print_nsap(tptr, alen);
50217688Spst		printf(" (%d)", alen);
50317688Spst		tptr += alen;
50417688Spst		tmp -= alen + 1;
50517688Spst		alen = *tptr++;
50617688Spst	    }
50717688Spst	    break;
50817688Spst	case TLV_ISNEIGH:
50917688Spst	    printf("\n\t\t\t neighbor addresses");
51017688Spst	    tmp = len;
51117688Spst	    tptr = pptr;
51217688Spst	    while (tmp >= sizeof(struct ether_addr)) {
51317688Spst		printf("\n\t\t\t %s", etheraddr_string(tptr));
51417688Spst		tmp -= sizeof(struct ether_addr);
51517688Spst		tptr += sizeof(struct ether_addr);
51617688Spst	    }
51717688Spst	    break;
51817688Spst	case TLV_PADDING:
51917688Spst	    printf("\n\t\t\t padding for %d bytes", len);
52017688Spst	    break;
52117688Spst	case TLV_AUTHENT:
52217688Spst	    printf("\n\t\t\t authentication data");
52317688Spst	    default_print(pptr, len);
52417688Spst	    break;
52517688Spst	default:
52617688Spst	    printf("\n\t\t\t unknown TLV, type %d, length %d", type, len);
52717688Spst	    break;
52817688Spst	}
52917688Spst
53017688Spst	pptr += len;
53117688Spst	packet_len -= len;
53217688Spst    }
53317688Spst
53417688Spst    if (packet_len != 0) {
53517688Spst	printf("\n\t\t\t %d straggler bytes", packet_len);
53617688Spst    }
53717688Spst    return(1);
53817688Spst}
53917688Spst
54017688Spststatic int
54117680Spstosi_cksum(register const u_char *p, register u_int len,
54217680Spst	  const u_char *toff, u_char *cksum, u_char *off)
54317680Spst{
54417680Spst	int x, y, f = (len - ((toff - p) + 1));
54517680Spst	int32_t c0 = 0, c1 = 0;
54617680Spst
54717680Spst	if ((cksum[0] = off[0]) == 0 && (cksum[1] = off[1]) == 0)
54817680Spst		return 0;
54917680Spst
55017680Spst	off[0] = off[1] = 0;
55117680Spst	while (--len >= 0) {
55217680Spst		c0 += *p++;
55317680Spst		c1 += c0;
55417680Spst		c0 %= 255;
55517680Spst		c1 %= 255;
55617680Spst	}
55717680Spst	x = (c0 * f - c1);
55817680Spst	if (x < 0)
55917680Spst		x = 255 - (-x % 255);
56017680Spst	else
56117680Spst		x %= 255;
56217680Spst	y = -1 * (x + c0);
56317680Spst	if (y < 0)
56417680Spst		y = 255 - (-y % 255);
56517680Spst	else
56617680Spst		y %= 255;
56717680Spst
56817680Spst	off[0] = x;
56917680Spst	off[1] = y;
57017680Spst
57117680Spst	return (off[0] != cksum[0] || off[1] != cksum[1]);
57217680Spst}
573