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