print-isoclns.c revision 17751
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 5617751Spststatic int osi_cksum(const u_char *, int, 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: 7617688Spst printf("iso clns"); 7717680Spst if (!eflag) 7817680Spst (void)printf(" %s > %s", 7917680Spst etheraddr_string(esrc), 8017680Spst etheraddr_string(edst)); 8117680Spst break; 8217680Spst 8317688Spst case NLPID_ESIS: 8417688Spst printf("iso esis"); 8517680Spst if (!eflag) 8617680Spst (void)printf(" %s > %s", 8717680Spst etheraddr_string(esrc), 8817680Spst etheraddr_string(edst)); 8917680Spst esis_print(p, length); 9017680Spst return; 9117680Spst 9217688Spst case NLPID_ISIS: 9317688Spst printf("iso isis"); 9417680Spst if (!eflag) 9517680Spst (void)printf(" %s > %s", 9617680Spst etheraddr_string(esrc), 9717680Spst etheraddr_string(edst)); 9817680Spst (void)printf(" len=%d ", length); 9917751Spst if (!isis_print(p, length)) 10017688Spst default_print_unaligned(p, caplen); 10117680Spst break; 10217680Spst 10317688Spst case NLPID_NULLNS: 10417688Spst printf("iso nullns"); 10517680Spst if (!eflag) 10617680Spst (void)printf(" %s > %s", 10717680Spst etheraddr_string(esrc), 10817680Spst etheraddr_string(edst)); 10917680Spst break; 11017680Spst 11117680Spst default: 11217688Spst printf("iso clns %02x", p[0]); 11317680Spst if (!eflag) 11417680Spst (void)printf(" %s > %s", 11517680Spst etheraddr_string(esrc), 11617680Spst etheraddr_string(edst)); 11717680Spst (void)printf(" len=%d ", length); 11817680Spst if (caplen > 1) 11917680Spst default_print_unaligned(p, caplen); 12017680Spst break; 12117680Spst } 12217680Spst} 12317680Spst 12417680Spst#define ESIS_REDIRECT 6 12517680Spst#define ESIS_ESH 2 12617680Spst#define ESIS_ISH 4 12717680Spst 12817680Spststruct esis_hdr { 12917680Spst u_char version; 13017680Spst u_char reserved; 13117680Spst u_char type; 13217680Spst u_char tmo[2]; 13317680Spst u_char cksum[2]; 13417680Spst}; 13517680Spst 13617680Spststatic void 13717680Spstesis_print(const u_char *p, u_int length) 13817680Spst{ 13917680Spst const u_char *ep; 14017680Spst int li = p[1]; 14117680Spst const struct esis_hdr *eh = (const struct esis_hdr *) &p[2]; 14217680Spst u_char cksum[2]; 14317680Spst u_char off[2]; 14417680Spst 14517680Spst if (length == 2) { 14617680Spst if (qflag) 14717680Spst printf(" bad pkt!"); 14817680Spst else 14917680Spst printf(" no header at all!"); 15017680Spst return; 15117680Spst } 15217680Spst ep = p + li; 15317680Spst if (li > length) { 15417680Spst if (qflag) 15517680Spst printf(" bad pkt!"); 15617680Spst else 15717680Spst printf(" LI(%d) > PDU size (%d)!", li, length); 15817680Spst return; 15917680Spst } 16017680Spst if (li < sizeof(struct esis_hdr) + 2) { 16117680Spst if (qflag) 16217680Spst printf(" bad pkt!"); 16317680Spst else { 16417680Spst printf(" too short for esis header %d:", li); 16517680Spst while (--length >= 0) 16617680Spst printf("%02X", *p++); 16717680Spst } 16817680Spst return; 16917680Spst } 17017680Spst switch (eh->type & 0x1f) { 17117680Spst 17217680Spst case ESIS_REDIRECT: 17317680Spst printf(" redirect"); 17417680Spst break; 17517680Spst 17617680Spst case ESIS_ESH: 17717680Spst printf(" esh"); 17817680Spst break; 17917680Spst 18017680Spst case ESIS_ISH: 18117680Spst printf(" ish"); 18217680Spst break; 18317680Spst 18417680Spst default: 18517680Spst printf(" type %d", eh->type & 0x1f); 18617680Spst break; 18717680Spst } 18817680Spst off[0] = eh->cksum[0]; 18917680Spst off[1] = eh->cksum[1]; 19017751Spst if (vflag && osi_cksum(p, li, off)) { 19117751Spst printf(" bad cksum (got %02x%02x)", 19217751Spst eh->cksum[1], eh->cksum[0]); 19317751Spst default_print(p, length); 19417680Spst return; 19517680Spst } 19617680Spst if (eh->version != 1) { 19717680Spst printf(" unsupported version %d", eh->version); 19817680Spst return; 19917680Spst } 20017680Spst p += sizeof(*eh) + 2; 20117680Spst li -= sizeof(*eh) + 2; /* protoid * li */ 20217680Spst 20317680Spst switch (eh->type & 0x1f) { 20417680Spst case ESIS_REDIRECT: { 20517680Spst const u_char *dst, *snpa, *is; 20617680Spst 20717680Spst dst = p; p += *p + 1; 20817680Spst if (p > snapend) 20917680Spst return; 21017688Spst printf("\n\t\t\t %s", isonsap_string(dst)); 21117680Spst snpa = p; p += *p + 1; 21217680Spst is = p; p += *p + 1; 21317680Spst if (p > snapend) 21417680Spst return; 21517680Spst if (p > ep) { 21617680Spst printf(" [bad li]"); 21717680Spst return; 21817680Spst } 21917680Spst if (is[0] == 0) 22017680Spst printf(" > %s", etheraddr_string(&snpa[1])); 22117680Spst else 22217680Spst printf(" > %s", isonsap_string(is)); 22317680Spst li = ep - p; 22417680Spst break; 22517680Spst } 22617680Spst#if 0 22717680Spst case ESIS_ESH: 22817680Spst printf(" esh"); 22917680Spst break; 23017680Spst#endif 23117680Spst case ESIS_ISH: { 23217680Spst const u_char *is; 23317680Spst 23417680Spst is = p; p += *p + 1; 23517680Spst if (p > ep) { 23617680Spst printf(" [bad li]"); 23717680Spst return; 23817680Spst } 23917680Spst if (p > snapend) 24017680Spst return; 24117751Spst if (!qflag) 24217751Spst 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 54017751Spst/* 54117751Spst * Verify the checksum. See 8473-1, Appendix C, section C.4. 54217751Spst */ 54317751Spst 54417688Spststatic int 54517751Spstosi_cksum(register const u_char *p, register int len, u_char *off) 54617680Spst{ 54717680Spst int32_t c0 = 0, c1 = 0; 54817680Spst 54917751Spst if ((off[0] == 0) && (off[1] == 0)) 55017680Spst return 0; 55117680Spst 55217680Spst while (--len >= 0) { 55317680Spst c0 += *p++; 55417751Spst c0 %= 255; 55517680Spst c1 += c0; 55617680Spst c1 %= 255; 55717680Spst } 55817751Spst return (c0 | c1); 55917680Spst} 560