print-isoclns.c revision 147904
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 * 2398527Sfenner * Extensively modified by Hannes Gredler (hannes@juniper.net) for more 24146778Ssam * complete IS-IS & CLNP support. 2598527Sfenner * 2656896Sfenner * $FreeBSD: head/contrib/tcpdump/print-isoclns.c 147904 2005-07-11 04:14:02Z sam $ 2717680Spst */ 2817680Spst 2917680Spst#ifndef lint 30127675Sbmsstatic const char rcsid[] _U_ = 31147904Ssam "@(#) $Header: /tcpdump/master/tcpdump/print-isoclns.c,v 1.133.2.12 2005/06/16 01:14:52 guy Exp $ (LBL)"; 3217680Spst#endif 3317680Spst 3456896Sfenner#ifdef HAVE_CONFIG_H 3556896Sfenner#include "config.h" 3656896Sfenner#endif 3756896Sfenner 38127675Sbms#include <tcpdump-stdinc.h> 3917680Spst 4017680Spst#include <stdio.h> 4198527Sfenner#include <string.h> 4217680Spst 4317680Spst#include "interface.h" 4417680Spst#include "addrtoname.h" 4517680Spst#include "ethertype.h" 4675118Sfenner#include "ether.h" 47146778Ssam#include "nlpid.h" 4817688Spst#include "extract.h" 49127675Sbms#include "gmpls.h" 50146778Ssam#include "oui.h" 5117680Spst 52127675Sbms#define IPV4 1 /* AFI value */ 53127675Sbms#define IPV6 2 /* AFI value */ 54127675Sbms 5532149Spst/* 5632149Spst * IS-IS is defined in ISO 10589. Look there for protocol definitions. 5732149Spst */ 5832149Spst 5975118Sfenner#define SYSTEM_ID_LEN ETHER_ADDR_LEN 60127675Sbms#define NODE_ID_LEN SYSTEM_ID_LEN+1 61127675Sbms#define LSP_ID_LEN SYSTEM_ID_LEN+2 62127675Sbms 6332149Spst#define ISIS_VERSION 1 64146778Ssam#define ESIS_VERSION 1 65146778Ssam#define CLNP_VERSION 1 6632149Spst 67146778Ssam#define ISIS_PDU_TYPE_MASK 0x1F 68146778Ssam#define ESIS_PDU_TYPE_MASK 0x1F 69146778Ssam#define CLNP_PDU_TYPE_MASK 0x1F 70146778Ssam#define CLNP_FLAG_MASK 0xE0 71146778Ssam#define ISIS_LAN_PRIORITY_MASK 0x7F 7232149Spst 73146778Ssam#define ISIS_PDU_L1_LAN_IIH 15 74146778Ssam#define ISIS_PDU_L2_LAN_IIH 16 75146778Ssam#define ISIS_PDU_PTP_IIH 17 76146778Ssam#define ISIS_PDU_L1_LSP 18 77146778Ssam#define ISIS_PDU_L2_LSP 20 78146778Ssam#define ISIS_PDU_L1_CSNP 24 79146778Ssam#define ISIS_PDU_L2_CSNP 25 80146778Ssam#define ISIS_PDU_L1_PSNP 26 81146778Ssam#define ISIS_PDU_L2_PSNP 27 82146778Ssam 83127675Sbmsstatic struct tok isis_pdu_values[] = { 84146778Ssam { ISIS_PDU_L1_LAN_IIH, "L1 Lan IIH"}, 85146778Ssam { ISIS_PDU_L2_LAN_IIH, "L2 Lan IIH"}, 86146778Ssam { ISIS_PDU_PTP_IIH, "p2p IIH"}, 87146778Ssam { ISIS_PDU_L1_LSP, "L1 LSP"}, 88146778Ssam { ISIS_PDU_L2_LSP, "L2 LSP"}, 89146778Ssam { ISIS_PDU_L1_CSNP, "L1 CSNP"}, 90146778Ssam { ISIS_PDU_L2_CSNP, "L2 CSNP"}, 91146778Ssam { ISIS_PDU_L1_PSNP, "L1 PSNP"}, 92146778Ssam { ISIS_PDU_L2_PSNP, "L2 PSNP"}, 93127675Sbms { 0, NULL} 94127675Sbms}; 9598527Sfenner 9632149Spst/* 9732149Spst * A TLV is a tuple of a type, length and a value and is normally used for 9832149Spst * encoding information in all sorts of places. This is an enumeration of 9932149Spst * the well known types. 100127675Sbms * 101127675Sbms * list taken from rfc3359 plus some memory from veterans ;-) 10232149Spst */ 10332149Spst 104146778Ssam#define ISIS_TLV_AREA_ADDR 1 /* iso10589 */ 105146778Ssam#define ISIS_TLV_IS_REACH 2 /* iso10589 */ 106146778Ssam#define ISIS_TLV_ESNEIGH 3 /* iso10589 */ 107146778Ssam#define ISIS_TLV_PART_DIS 4 /* iso10589 */ 108146778Ssam#define ISIS_TLV_PREFIX_NEIGH 5 /* iso10589 */ 109146778Ssam#define ISIS_TLV_ISNEIGH 6 /* iso10589 */ 110146778Ssam#define ISIS_TLV_ISNEIGH_VARLEN 7 /* iso10589 */ 111146778Ssam#define ISIS_TLV_PADDING 8 /* iso10589 */ 112146778Ssam#define ISIS_TLV_LSP 9 /* iso10589 */ 113146778Ssam#define ISIS_TLV_AUTH 10 /* iso10589, rfc3567 */ 114146778Ssam#define ISIS_TLV_CHECKSUM 12 /* rfc3358 */ 115146778Ssam#define ISIS_TLV_LSP_BUFFERSIZE 14 /* iso10589 rev2 */ 116146778Ssam#define ISIS_TLV_EXT_IS_REACH 22 /* draft-ietf-isis-traffic-05 */ 117146778Ssam#define ISIS_TLV_IS_ALIAS_ID 24 /* draft-ietf-isis-ext-lsp-frags-02 */ 118146778Ssam#define ISIS_TLV_DECNET_PHASE4 42 119146778Ssam#define ISIS_TLV_LUCENT_PRIVATE 66 120146778Ssam#define ISIS_TLV_INT_IP_REACH 128 /* rfc1195, rfc2966 */ 121146778Ssam#define ISIS_TLV_PROTOCOLS 129 /* rfc1195 */ 122146778Ssam#define ISIS_TLV_EXT_IP_REACH 130 /* rfc1195, rfc2966 */ 123146778Ssam#define ISIS_TLV_IDRP_INFO 131 /* rfc1195 */ 124146778Ssam#define ISIS_TLV_IPADDR 132 /* rfc1195 */ 125146778Ssam#define ISIS_TLV_IPAUTH 133 /* rfc1195 */ 126146778Ssam#define ISIS_TLV_TE_ROUTER_ID 134 /* draft-ietf-isis-traffic-05 */ 127146778Ssam#define ISIS_TLV_EXTD_IP_REACH 135 /* draft-ietf-isis-traffic-05 */ 128146778Ssam#define ISIS_TLV_HOSTNAME 137 /* rfc2763 */ 129146778Ssam#define ISIS_TLV_SHARED_RISK_GROUP 138 /* draft-ietf-isis-gmpls-extensions */ 130146778Ssam#define ISIS_TLV_NORTEL_PRIVATE1 176 131146778Ssam#define ISIS_TLV_NORTEL_PRIVATE2 177 132147904Ssam#define ISIS_TLV_RESTART_SIGNALING 211 /* rfc3847 */ 133146778Ssam#define ISIS_TLV_MT_IS_REACH 222 /* draft-ietf-isis-wg-multi-topology-05 */ 134146778Ssam#define ISIS_TLV_MT_SUPPORTED 229 /* draft-ietf-isis-wg-multi-topology-05 */ 135146778Ssam#define ISIS_TLV_IP6ADDR 232 /* draft-ietf-isis-ipv6-02 */ 136146778Ssam#define ISIS_TLV_MT_IP_REACH 235 /* draft-ietf-isis-wg-multi-topology-05 */ 137146778Ssam#define ISIS_TLV_IP6_REACH 236 /* draft-ietf-isis-ipv6-02 */ 138146778Ssam#define ISIS_TLV_MT_IP6_REACH 237 /* draft-ietf-isis-wg-multi-topology-05 */ 139146778Ssam#define ISIS_TLV_PTP_ADJ 240 /* rfc3373 */ 140146778Ssam#define ISIS_TLV_IIH_SEQNR 241 /* draft-shen-isis-iih-sequence-00 */ 141146778Ssam#define ISIS_TLV_VENDOR_PRIVATE 250 /* draft-ietf-isis-experimental-tlv-01 */ 14232149Spst 143127675Sbmsstatic struct tok isis_tlv_values[] = { 144146778Ssam { ISIS_TLV_AREA_ADDR, "Area address(es)"}, 145146778Ssam { ISIS_TLV_IS_REACH, "IS Reachability"}, 146146778Ssam { ISIS_TLV_ESNEIGH, "ES Neighbor(s)"}, 147146778Ssam { ISIS_TLV_PART_DIS, "Partition DIS"}, 148146778Ssam { ISIS_TLV_PREFIX_NEIGH, "Prefix Neighbors"}, 149146778Ssam { ISIS_TLV_ISNEIGH, "IS Neighbor(s)"}, 150146778Ssam { ISIS_TLV_ISNEIGH_VARLEN, "IS Neighbor(s) (variable length)"}, 151146778Ssam { ISIS_TLV_PADDING, "Padding"}, 152146778Ssam { ISIS_TLV_LSP, "LSP entries"}, 153146778Ssam { ISIS_TLV_AUTH, "Authentication"}, 154146778Ssam { ISIS_TLV_CHECKSUM, "Checksum"}, 155146778Ssam { ISIS_TLV_LSP_BUFFERSIZE, "LSP Buffersize"}, 156146778Ssam { ISIS_TLV_EXT_IS_REACH, "Extended IS Reachability"}, 157146778Ssam { ISIS_TLV_IS_ALIAS_ID, "IS Alias ID"}, 158146778Ssam { ISIS_TLV_DECNET_PHASE4, "DECnet Phase IV"}, 159146778Ssam { ISIS_TLV_LUCENT_PRIVATE, "Lucent Proprietary"}, 160146778Ssam { ISIS_TLV_INT_IP_REACH, "IPv4 Internal Reachability"}, 161146778Ssam { ISIS_TLV_PROTOCOLS, "Protocols supported"}, 162146778Ssam { ISIS_TLV_EXT_IP_REACH, "IPv4 External Reachability"}, 163146778Ssam { ISIS_TLV_IDRP_INFO, "Inter-Domain Information Type"}, 164146778Ssam { ISIS_TLV_IPADDR, "IPv4 Interface address(es)"}, 165146778Ssam { ISIS_TLV_IPAUTH, "IPv4 authentication (deprecated)"}, 166146778Ssam { ISIS_TLV_TE_ROUTER_ID, "Traffic Engineering Router ID"}, 167146778Ssam { ISIS_TLV_EXTD_IP_REACH, "Extended IPv4 Reachability"}, 168146778Ssam { ISIS_TLV_SHARED_RISK_GROUP, "Shared Risk Link Group"}, 169146778Ssam { ISIS_TLV_NORTEL_PRIVATE1, "Nortel Proprietary"}, 170146778Ssam { ISIS_TLV_NORTEL_PRIVATE2, "Nortel Proprietary"}, 171146778Ssam { ISIS_TLV_HOSTNAME, "Hostname"}, 172146778Ssam { ISIS_TLV_RESTART_SIGNALING, "Restart Signaling"}, 173146778Ssam { ISIS_TLV_MT_IS_REACH, "Multi Topology IS Reachability"}, 174146778Ssam { ISIS_TLV_MT_SUPPORTED, "Multi Topology"}, 175146778Ssam { ISIS_TLV_IP6ADDR, "IPv6 Interface address(es)"}, 176146778Ssam { ISIS_TLV_MT_IP_REACH, "Multi-Topology IPv4 Reachability"}, 177146778Ssam { ISIS_TLV_IP6_REACH, "IPv6 reachability"}, 178146778Ssam { ISIS_TLV_MT_IP6_REACH, "Multi-Topology IP6 Reachability"}, 179146778Ssam { ISIS_TLV_PTP_ADJ, "Point-to-point Adjacency State"}, 180146778Ssam { ISIS_TLV_IIH_SEQNR, "Hello PDU Sequence Number"}, 181146778Ssam { ISIS_TLV_VENDOR_PRIVATE, "Vendor Private"}, 182127675Sbms { 0, NULL } 183127675Sbms}; 18498527Sfenner 185146778Ssam#define ESIS_OPTION_PROTOCOLS 129 186146778Ssam#define ESIS_OPTION_QOS_MAINTENANCE 195 /* iso9542 */ 187146778Ssam#define ESIS_OPTION_SECURITY 197 /* iso9542 */ 188146778Ssam#define ESIS_OPTION_ES_CONF_TIME 198 /* iso9542 */ 189146778Ssam#define ESIS_OPTION_PRIORITY 205 /* iso9542 */ 190146778Ssam#define ESIS_OPTION_ADDRESS_MASK 225 /* iso9542 */ 191146778Ssam#define ESIS_OPTION_SNPA_MASK 226 /* iso9542 */ 19298527Sfenner 193146778Ssamstatic struct tok esis_option_values[] = { 194146778Ssam { ESIS_OPTION_PROTOCOLS, "Protocols supported"}, 195146778Ssam { ESIS_OPTION_QOS_MAINTENANCE, "QoS Maintenance" }, 196146778Ssam { ESIS_OPTION_SECURITY, "Security" }, 197146778Ssam { ESIS_OPTION_ES_CONF_TIME, "ES Configuration Time" }, 198146778Ssam { ESIS_OPTION_PRIORITY, "Priority" }, 199146778Ssam { ESIS_OPTION_ADDRESS_MASK, "Addressk Mask" }, 200146778Ssam { ESIS_OPTION_SNPA_MASK, "SNPA Mask" }, 201146778Ssam { 0, NULL } 202146778Ssam}; 203146778Ssam 204146778Ssam#define CLNP_OPTION_DISCARD_REASON 193 205146778Ssam#define CLNP_OPTION_QOS_MAINTENANCE 195 /* iso8473 */ 206147904Ssam#define CLNP_OPTION_SECURITY 197 /* iso8473 */ 207147904Ssam#define CLNP_OPTION_SOURCE_ROUTING 200 /* iso8473 */ 208147904Ssam#define CLNP_OPTION_ROUTE_RECORDING 203 /* iso8473 */ 209147904Ssam#define CLNP_OPTION_PADDING 204 /* iso8473 */ 210146778Ssam#define CLNP_OPTION_PRIORITY 205 /* iso8473 */ 211146778Ssam 212146778Ssamstatic struct tok clnp_option_values[] = { 213146778Ssam { CLNP_OPTION_DISCARD_REASON, "Discard Reason"}, 214146778Ssam { CLNP_OPTION_PRIORITY, "Priority"}, 215146778Ssam { CLNP_OPTION_QOS_MAINTENANCE, "QoS Maintenance"}, 216147904Ssam { CLNP_OPTION_SECURITY, "Security"}, 217147904Ssam { CLNP_OPTION_SOURCE_ROUTING, "Source Routing"}, 218147904Ssam { CLNP_OPTION_ROUTE_RECORDING, "Route Recording"}, 219147904Ssam { CLNP_OPTION_PADDING, "Padding"}, 220146778Ssam { 0, NULL } 221146778Ssam}; 222146778Ssam 223146778Ssamstatic struct tok clnp_option_rfd_class_values[] = { 224146778Ssam { 0x0, "General"}, 225146778Ssam { 0x8, "Address"}, 226146778Ssam { 0x9, "Source Routeing"}, 227146778Ssam { 0xa, "Lifetime"}, 228146778Ssam { 0xb, "PDU Discarded"}, 229146778Ssam { 0xc, "Reassembly"}, 230146778Ssam { 0, NULL } 231146778Ssam}; 232146778Ssam 233146778Ssamstatic struct tok clnp_option_rfd_general_values[] = { 234146778Ssam { 0x0, "Reason not specified"}, 235146778Ssam { 0x1, "Protocol procedure error"}, 236146778Ssam { 0x2, "Incorrect checksum"}, 237146778Ssam { 0x3, "PDU discarded due to congestion"}, 238146778Ssam { 0x4, "Header syntax error (cannot be parsed)"}, 239146778Ssam { 0x5, "Segmentation needed but not permitted"}, 240146778Ssam { 0x6, "Incomplete PDU received"}, 241146778Ssam { 0x7, "Duplicate option"}, 242146778Ssam { 0, NULL } 243146778Ssam}; 244146778Ssam 245146778Ssamstatic struct tok clnp_option_rfd_address_values[] = { 246146778Ssam { 0x0, "Destination address unreachable"}, 247146778Ssam { 0x1, "Destination address unknown"}, 248146778Ssam { 0, NULL } 249146778Ssam}; 250146778Ssam 251146778Ssamstatic struct tok clnp_option_rfd_source_routeing_values[] = { 252146778Ssam { 0x0, "Unspecified source routeing error"}, 253146778Ssam { 0x1, "Syntax error in source routeing field"}, 254146778Ssam { 0x2, "Unknown address in source routeing field"}, 255146778Ssam { 0x3, "Path not acceptable"}, 256146778Ssam { 0, NULL } 257146778Ssam}; 258146778Ssam 259146778Ssamstatic struct tok clnp_option_rfd_lifetime_values[] = { 260146778Ssam { 0x0, "Lifetime expired while data unit in transit"}, 261146778Ssam { 0x1, "Lifetime expired during reassembly"}, 262146778Ssam { 0, NULL } 263146778Ssam}; 264146778Ssam 265146778Ssamstatic struct tok clnp_option_rfd_pdu_discard_values[] = { 266146778Ssam { 0x0, "Unsupported option not specified"}, 267146778Ssam { 0x1, "Unsupported protocol version"}, 268146778Ssam { 0x2, "Unsupported security option"}, 269146778Ssam { 0x3, "Unsupported source routeing option"}, 270146778Ssam { 0x4, "Unsupported recording of route option"}, 271146778Ssam { 0, NULL } 272146778Ssam}; 273146778Ssam 274146778Ssamstatic struct tok clnp_option_rfd_reassembly_values[] = { 275146778Ssam { 0x0, "Reassembly interference"}, 276146778Ssam { 0, NULL } 277146778Ssam}; 278146778Ssam 279146778Ssam/* array of 16 error-classes */ 280146778Ssamstatic struct tok *clnp_option_rfd_error_class[] = { 281146778Ssam clnp_option_rfd_general_values, 282146778Ssam NULL, 283146778Ssam NULL, 284146778Ssam NULL, 285146778Ssam NULL, 286146778Ssam NULL, 287146778Ssam NULL, 288146778Ssam NULL, 289146778Ssam clnp_option_rfd_address_values, 290146778Ssam clnp_option_rfd_source_routeing_values, 291146778Ssam clnp_option_rfd_lifetime_values, 292146778Ssam clnp_option_rfd_pdu_discard_values, 293146778Ssam clnp_option_rfd_reassembly_values, 294146778Ssam NULL, 295146778Ssam NULL, 296146778Ssam NULL 297146778Ssam}; 298146778Ssam 299147904Ssam#define CLNP_OPTION_OPTION_QOS_MASK 0x3f 300147904Ssam#define CLNP_OPTION_SCOPE_MASK 0xc0 301147904Ssam#define CLNP_OPTION_SCOPE_SA_SPEC 0x40 302147904Ssam#define CLNP_OPTION_SCOPE_DA_SPEC 0x80 303147904Ssam#define CLNP_OPTION_SCOPE_GLOBAL 0xc0 304146778Ssam 305147904Ssamstatic struct tok clnp_option_scope_values[] = { 306147904Ssam { CLNP_OPTION_SCOPE_SA_SPEC, "Source Address Specific"}, 307147904Ssam { CLNP_OPTION_SCOPE_DA_SPEC, "Destination Address Specific"}, 308147904Ssam { CLNP_OPTION_SCOPE_GLOBAL, "Globally unique"}, 309147904Ssam { 0, NULL } 310147904Ssam}; 311147904Ssam 312147904Ssamstatic struct tok clnp_option_sr_rr_values[] = { 313147904Ssam { 0x0, "partial"}, 314147904Ssam { 0x1, "complete"}, 315147904Ssam { 0, NULL } 316147904Ssam}; 317147904Ssam 318147904Ssamstatic struct tok clnp_option_sr_rr_string_values[] = { 319147904Ssam { CLNP_OPTION_SOURCE_ROUTING, "source routing"}, 320147904Ssam { CLNP_OPTION_ROUTE_RECORDING, "recording of route in progress"}, 321147904Ssam { 0, NULL } 322147904Ssam}; 323147904Ssam 324147904Ssamstatic struct tok clnp_option_qos_global_values[] = { 325147904Ssam { 0x20, "reserved"}, 326147904Ssam { 0x10, "sequencing vs. delay"}, 327147904Ssam { 0x08, "congested"}, 328147904Ssam { 0x04, "delay vs. cost"}, 329147904Ssam { 0x02, "error vs. delay"}, 330147904Ssam { 0x01, "error vs. cost"}, 331147904Ssam { 0, NULL } 332147904Ssam}; 333147904Ssam 334146778Ssam#define ISIS_SUBTLV_EXT_IS_REACH_ADMIN_GROUP 3 /* draft-ietf-isis-traffic-05 */ 335146778Ssam#define ISIS_SUBTLV_EXT_IS_REACH_LINK_LOCAL_REMOTE_ID 4 /* draft-ietf-isis-gmpls-extensions */ 336146778Ssam#define ISIS_SUBTLV_EXT_IS_REACH_LINK_REMOTE_ID 5 /* draft-ietf-isis-traffic-05 */ 337146778Ssam#define ISIS_SUBTLV_EXT_IS_REACH_IPV4_INTF_ADDR 6 /* draft-ietf-isis-traffic-05 */ 338146778Ssam#define ISIS_SUBTLV_EXT_IS_REACH_IPV4_NEIGHBOR_ADDR 8 /* draft-ietf-isis-traffic-05 */ 339146778Ssam#define ISIS_SUBTLV_EXT_IS_REACH_MAX_LINK_BW 9 /* draft-ietf-isis-traffic-05 */ 340146778Ssam#define ISIS_SUBTLV_EXT_IS_REACH_RESERVABLE_BW 10 /* draft-ietf-isis-traffic-05 */ 341146778Ssam#define ISIS_SUBTLV_EXT_IS_REACH_UNRESERVED_BW 11 /* draft-ietf-isis-traffic-05 */ 342146778Ssam#define ISIS_SUBTLV_EXT_IS_REACH_DIFFSERV_TE 12 /* draft-ietf-tewg-diff-te-proto-06 */ 343146778Ssam#define ISIS_SUBTLV_EXT_IS_REACH_TE_METRIC 18 /* draft-ietf-isis-traffic-05 */ 344146778Ssam#define ISIS_SUBTLV_EXT_IS_REACH_LINK_PROTECTION_TYPE 20 /* draft-ietf-isis-gmpls-extensions */ 345146778Ssam#define ISIS_SUBTLV_EXT_IS_REACH_INTF_SW_CAP_DESCR 21 /* draft-ietf-isis-gmpls-extensions */ 346146778Ssam 347127675Sbmsstatic struct tok isis_ext_is_reach_subtlv_values[] = { 348146778Ssam { ISIS_SUBTLV_EXT_IS_REACH_ADMIN_GROUP, "Administrative groups" }, 349146778Ssam { ISIS_SUBTLV_EXT_IS_REACH_LINK_LOCAL_REMOTE_ID, "Link Local/Remote Identifier" }, 350146778Ssam { ISIS_SUBTLV_EXT_IS_REACH_LINK_REMOTE_ID, "Link Remote Identifier" }, 351146778Ssam { ISIS_SUBTLV_EXT_IS_REACH_IPV4_INTF_ADDR, "IPv4 interface address" }, 352146778Ssam { ISIS_SUBTLV_EXT_IS_REACH_IPV4_NEIGHBOR_ADDR, "IPv4 neighbor address" }, 353146778Ssam { ISIS_SUBTLV_EXT_IS_REACH_MAX_LINK_BW, "Maximum link bandwidth" }, 354146778Ssam { ISIS_SUBTLV_EXT_IS_REACH_RESERVABLE_BW, "Reservable link bandwidth" }, 355146778Ssam { ISIS_SUBTLV_EXT_IS_REACH_UNRESERVED_BW, "Unreserved bandwidth" }, 356146778Ssam { ISIS_SUBTLV_EXT_IS_REACH_DIFFSERV_TE, "Diffserv TE" }, 357146778Ssam { ISIS_SUBTLV_EXT_IS_REACH_TE_METRIC, "Traffic Engineering Metric" }, 358146778Ssam { ISIS_SUBTLV_EXT_IS_REACH_LINK_PROTECTION_TYPE, "Link Protection Type" }, 359146778Ssam { ISIS_SUBTLV_EXT_IS_REACH_INTF_SW_CAP_DESCR, "Interface Switching Capability" }, 360146778Ssam { 250, "Reserved for cisco specific extensions" }, 361146778Ssam { 251, "Reserved for cisco specific extensions" }, 362146778Ssam { 252, "Reserved for cisco specific extensions" }, 363146778Ssam { 253, "Reserved for cisco specific extensions" }, 364146778Ssam { 254, "Reserved for cisco specific extensions" }, 365146778Ssam { 255, "Reserved for future expansion" }, 366127675Sbms { 0, NULL } 367127675Sbms}; 36898527Sfenner 369146778Ssam#define ISIS_SUBTLV_EXTD_IP_REACH_ADMIN_TAG32 1 /* draft-ietf-isis-admin-tags-01 */ 370146778Ssam#define ISIS_SUBTLV_EXTD_IP_REACH_ADMIN_TAG64 2 /* draft-ietf-isis-admin-tags-01 */ 371146778Ssam#define ISIS_SUBTLV_EXTD_IP_REACH_MGMT_PREFIX_COLOR 117 /* draft-ietf-isis-wg-multi-topology-05 */ 372127675Sbms 373127675Sbmsstatic struct tok isis_ext_ip_reach_subtlv_values[] = { 374146778Ssam { ISIS_SUBTLV_EXTD_IP_REACH_ADMIN_TAG32, "32-Bit Administrative tag" }, 375146778Ssam { ISIS_SUBTLV_EXTD_IP_REACH_ADMIN_TAG64, "64-Bit Administrative tag" }, 376146778Ssam { ISIS_SUBTLV_EXTD_IP_REACH_MGMT_PREFIX_COLOR, "Management Prefix Color" }, 377127675Sbms { 0, NULL } 378127675Sbms}; 379127675Sbms 380146778Ssam#define ISIS_SUBTLV_AUTH_SIMPLE 1 381146778Ssam#define ISIS_SUBTLV_AUTH_MD5 54 382146778Ssam#define ISIS_SUBTLV_AUTH_MD5_LEN 16 383146778Ssam#define ISIS_SUBTLV_AUTH_PRIVATE 255 384127675Sbms 385127675Sbmsstatic struct tok isis_subtlv_auth_values[] = { 386146778Ssam { ISIS_SUBTLV_AUTH_SIMPLE, "simple text password"}, 387146778Ssam { ISIS_SUBTLV_AUTH_MD5, "HMAC-MD5 password"}, 388146778Ssam { ISIS_SUBTLV_AUTH_PRIVATE, "Routing Domain private password"}, 389127675Sbms { 0, NULL } 390127675Sbms}; 391127675Sbms 392146778Ssam#define ISIS_SUBTLV_IDRP_RES 0 393146778Ssam#define ISIS_SUBTLV_IDRP_LOCAL 1 394146778Ssam#define ISIS_SUBTLV_IDRP_ASN 2 395127675Sbms 396127675Sbmsstatic struct tok isis_subtlv_idrp_values[] = { 397146778Ssam { ISIS_SUBTLV_IDRP_RES, "Reserved"}, 398146778Ssam { ISIS_SUBTLV_IDRP_LOCAL, "Routing-Domain Specific"}, 399146778Ssam { ISIS_SUBTLV_IDRP_ASN, "AS Number Tag"}, 400127675Sbms { 0, NULL} 401127675Sbms}; 402127675Sbms 403146778Ssam#define CLNP_SEGMENT_PART 0x80 404146778Ssam#define CLNP_MORE_SEGMENTS 0x40 405146778Ssam#define CLNP_REQUEST_ER 0x20 406127675Sbms 407146778Ssamstatic struct tok clnp_flag_values[] = { 408146778Ssam { CLNP_SEGMENT_PART, "Segmentation permitted"}, 409146778Ssam { CLNP_MORE_SEGMENTS, "more Segments"}, 410146778Ssam { CLNP_REQUEST_ER, "request Error Report"}, 411146778Ssam { 0, NULL} 412146778Ssam}; 413146778Ssam 41498527Sfenner#define ISIS_MASK_LSP_OL_BIT(x) ((x)&0x4) 41598527Sfenner#define ISIS_MASK_LSP_ISTYPE_BITS(x) ((x)&0x3) 41698527Sfenner#define ISIS_MASK_LSP_PARTITION_BIT(x) ((x)&0x80) 41798527Sfenner#define ISIS_MASK_LSP_ATT_BITS(x) ((x)&0x78) 41898527Sfenner#define ISIS_MASK_LSP_ATT_ERROR_BIT(x) ((x)&0x40) 41998527Sfenner#define ISIS_MASK_LSP_ATT_EXPENSE_BIT(x) ((x)&0x20) 42098527Sfenner#define ISIS_MASK_LSP_ATT_DELAY_BIT(x) ((x)&0x10) 42198527Sfenner#define ISIS_MASK_LSP_ATT_DEFAULT_BIT(x) ((x)&0x8) 42298527Sfenner 423127675Sbms#define ISIS_MASK_MTID(x) ((x)&0x0fff) 424127675Sbms#define ISIS_MASK_MTFLAGS(x) ((x)&0xf000) 42598527Sfenner 426127675Sbmsstatic struct tok isis_mt_flag_values[] = { 427127675Sbms { 0x4000, "sub-TLVs present"}, 428127675Sbms { 0x8000, "ATT bit set"}, 429127675Sbms { 0, NULL} 430127675Sbms}; 43198527Sfenner 432127675Sbms#define ISIS_MASK_TLV_EXTD_IP_UPDOWN(x) ((x)&0x80) 433127675Sbms#define ISIS_MASK_TLV_EXTD_IP_SUBTLV(x) ((x)&0x40) 43498527Sfenner 435127675Sbms#define ISIS_MASK_TLV_EXTD_IP6_IE(x) ((x)&0x40) 436127675Sbms#define ISIS_MASK_TLV_EXTD_IP6_SUBTLV(x) ((x)&0x20) 437127675Sbms 43898527Sfenner#define ISIS_LSP_TLV_METRIC_SUPPORTED(x) ((x)&0x80) 43998527Sfenner#define ISIS_LSP_TLV_METRIC_IE(x) ((x)&0x40) 44098527Sfenner#define ISIS_LSP_TLV_METRIC_UPDOWN(x) ((x)&0x80) 44198527Sfenner#define ISIS_LSP_TLV_METRIC_VALUE(x) ((x)&0x3f) 44298527Sfenner 443127675Sbms#define ISIS_MASK_TLV_SHARED_RISK_GROUP(x) ((x)&0x1) 444127675Sbms 445127675Sbmsstatic struct tok isis_mt_values[] = { 446127675Sbms { 0, "IPv4 unicast"}, 447127675Sbms { 1, "In-Band Management"}, 448127675Sbms { 2, "IPv6 unicast"}, 449127675Sbms { 3, "Multicast"}, 450127675Sbms { 4095, "Development, Experimental or Proprietary"}, 451127675Sbms { 0, NULL } 452127675Sbms}; 453127675Sbms 454127675Sbmsstatic struct tok isis_iih_circuit_type_values[] = { 455127675Sbms { 1, "Level 1 only"}, 456127675Sbms { 2, "Level 2 only"}, 457127675Sbms { 3, "Level 1, Level 2"}, 458127675Sbms { 0, NULL} 459127675Sbms}; 460127675Sbms 46198527Sfenner#define ISIS_LSP_TYPE_UNUSED0 0 46298527Sfenner#define ISIS_LSP_TYPE_LEVEL_1 1 46398527Sfenner#define ISIS_LSP_TYPE_UNUSED2 2 46498527Sfenner#define ISIS_LSP_TYPE_LEVEL_2 3 46598527Sfenner 46698527Sfennerstatic struct tok isis_lsp_istype_values[] = { 467127675Sbms { ISIS_LSP_TYPE_UNUSED0, "Unused 0x0 (invalid)"}, 468127675Sbms { ISIS_LSP_TYPE_LEVEL_1, "L1 IS"}, 469127675Sbms { ISIS_LSP_TYPE_UNUSED2, "Unused 0x2 (invalid)"}, 470127675Sbms { ISIS_LSP_TYPE_LEVEL_2, "L1L2 IS"}, 471127675Sbms { 0, NULL } 47298527Sfenner}; 47398527Sfenner 47432149Spst/* 47532149Spst * Katz's point to point adjacency TLV uses codes to tell us the state of 47632149Spst * the remote adjacency. Enumerate them. 47732149Spst */ 47832149Spst 47932149Spst#define ISIS_PTP_ADJ_UP 0 48032149Spst#define ISIS_PTP_ADJ_INIT 1 48132149Spst#define ISIS_PTP_ADJ_DOWN 2 48232149Spst 48398527Sfennerstatic struct tok isis_ptp_adjancey_values[] = { 484127675Sbms { ISIS_PTP_ADJ_UP, "Up" }, 485127675Sbms { ISIS_PTP_ADJ_INIT, "Initializing" }, 486127675Sbms { ISIS_PTP_ADJ_DOWN, "Down" }, 487127675Sbms { 0, NULL} 48832149Spst}; 48932149Spst 49098527Sfennerstruct isis_tlv_ptp_adj { 491127675Sbms u_int8_t adjacency_state; 492127675Sbms u_int8_t extd_local_circuit_id[4]; 493127675Sbms u_int8_t neighbor_sysid[SYSTEM_ID_LEN]; 494127675Sbms u_int8_t neighbor_extd_local_circuit_id[4]; 49532149Spst}; 49632149Spst 497127675Sbmsstatic int osi_cksum(const u_int8_t *, u_int); 498146778Ssamstatic int clnp_print(const u_int8_t *, u_int); 499127675Sbmsstatic void esis_print(const u_int8_t *, u_int); 500127675Sbmsstatic int isis_print(const u_int8_t *, u_int); 501127675Sbms 502127675Sbmsstruct isis_metric_block { 503127675Sbms u_int8_t metric_default; 504127675Sbms u_int8_t metric_delay; 505127675Sbms u_int8_t metric_expense; 506127675Sbms u_int8_t metric_error; 50798527Sfenner}; 50898527Sfenner 50998527Sfennerstruct isis_tlv_is_reach { 510127675Sbms struct isis_metric_block isis_metric_block; 511127675Sbms u_int8_t neighbor_nodeid[NODE_ID_LEN]; 51298527Sfenner}; 51398527Sfenner 514127675Sbmsstruct isis_tlv_es_reach { 515127675Sbms struct isis_metric_block isis_metric_block; 516127675Sbms u_int8_t neighbor_sysid[SYSTEM_ID_LEN]; 517127675Sbms}; 51898527Sfenner 519127675Sbmsstruct isis_tlv_ip_reach { 520127675Sbms struct isis_metric_block isis_metric_block; 521127675Sbms u_int8_t prefix[4]; 522127675Sbms u_int8_t mask[4]; 523127675Sbms}; 524127675Sbms 525127675Sbmsstatic struct tok isis_is_reach_virtual_values[] = { 526127675Sbms { 0, "IsNotVirtual"}, 527127675Sbms { 1, "IsVirtual"}, 528127675Sbms { 0, NULL } 529127675Sbms}; 530127675Sbms 531127675Sbmsstatic struct tok isis_restart_flag_values[] = { 532127675Sbms { 0x1, "Restart Request"}, 533127675Sbms { 0x2, "Restart Acknowledgement"}, 534147904Ssam { 0x4, "Suppress adjacency advertisement"}, 535127675Sbms { 0, NULL } 536127675Sbms}; 537127675Sbms 53832149Spststruct isis_common_header { 539127675Sbms u_int8_t nlpid; 540127675Sbms u_int8_t fixed_len; 541127675Sbms u_int8_t version; /* Protocol version */ 542127675Sbms u_int8_t id_length; 543127675Sbms u_int8_t pdu_type; /* 3 MSbits are reserved */ 544127675Sbms u_int8_t pdu_version; /* Packet format version */ 545127675Sbms u_int8_t reserved; 546127675Sbms u_int8_t max_area; 54732149Spst}; 54832149Spst 54998527Sfennerstruct isis_iih_lan_header { 550127675Sbms u_int8_t circuit_type; 551127675Sbms u_int8_t source_id[SYSTEM_ID_LEN]; 552127675Sbms u_int8_t holding_time[2]; 553127675Sbms u_int8_t pdu_len[2]; 554127675Sbms u_int8_t priority; 555127675Sbms u_int8_t lan_id[NODE_ID_LEN]; 55632149Spst}; 55798527Sfenner 55898527Sfennerstruct isis_iih_ptp_header { 559127675Sbms u_int8_t circuit_type; 560127675Sbms u_int8_t source_id[SYSTEM_ID_LEN]; 561127675Sbms u_int8_t holding_time[2]; 562127675Sbms u_int8_t pdu_len[2]; 563127675Sbms u_int8_t circuit_id; 56432149Spst}; 56532149Spst 56698527Sfennerstruct isis_lsp_header { 567127675Sbms u_int8_t pdu_len[2]; 568127675Sbms u_int8_t remaining_lifetime[2]; 569127675Sbms u_int8_t lsp_id[LSP_ID_LEN]; 570127675Sbms u_int8_t sequence_number[4]; 571127675Sbms u_int8_t checksum[2]; 572127675Sbms u_int8_t typeblock; 57332149Spst}; 57432149Spst 57598527Sfennerstruct isis_csnp_header { 576127675Sbms u_int8_t pdu_len[2]; 577127675Sbms u_int8_t source_id[NODE_ID_LEN]; 578127675Sbms u_int8_t start_lsp_id[LSP_ID_LEN]; 579127675Sbms u_int8_t end_lsp_id[LSP_ID_LEN]; 58098527Sfenner}; 58132149Spst 58298527Sfennerstruct isis_psnp_header { 583127675Sbms u_int8_t pdu_len[2]; 584127675Sbms u_int8_t source_id[NODE_ID_LEN]; 58598527Sfenner}; 58632149Spst 58798527Sfennerstruct isis_tlv_lsp { 588127675Sbms u_int8_t remaining_lifetime[2]; 589127675Sbms u_int8_t lsp_id[LSP_ID_LEN]; 590127675Sbms u_int8_t sequence_number[4]; 591127675Sbms u_int8_t checksum[2]; 59298527Sfenner}; 593127675Sbms 59498527Sfenner#define ISIS_COMMON_HEADER_SIZE (sizeof(struct isis_common_header)) 59598527Sfenner#define ISIS_IIH_LAN_HEADER_SIZE (sizeof(struct isis_iih_lan_header)) 59698527Sfenner#define ISIS_IIH_PTP_HEADER_SIZE (sizeof(struct isis_iih_ptp_header)) 59798527Sfenner#define ISIS_LSP_HEADER_SIZE (sizeof(struct isis_lsp_header)) 59898527Sfenner#define ISIS_CSNP_HEADER_SIZE (sizeof(struct isis_csnp_header)) 59998527Sfenner#define ISIS_PSNP_HEADER_SIZE (sizeof(struct isis_psnp_header)) 60032149Spst 601127675Sbmsvoid isoclns_print(const u_int8_t *p, u_int length, u_int caplen) 60217680Spst{ 60398527Sfenner const struct isis_common_header *header; 604127675Sbms 60598527Sfenner header = (const struct isis_common_header *)p; 60632149Spst 607146778Ssam if (caplen <= 1) { /* enough bytes on the wire ? */ 608146778Ssam printf("|OSI"); 609146778Ssam return; 610146778Ssam } 61117680Spst 612146778Ssam if (eflag) 613146778Ssam printf("OSI NLPID %s (0x%02x): ", 614146778Ssam tok2str(nlpid_values,"Unknown",*p), 615146778Ssam *p); 616146778Ssam 61717680Spst switch (*p) { 61817680Spst 619146778Ssam case NLPID_CLNP: 620146778Ssam if (!clnp_print(p, length)) 621146778Ssam print_unknown_data(p,"\n\t",caplen); 62217680Spst break; 62317680Spst 62417688Spst case NLPID_ESIS: 62517680Spst esis_print(p, length); 62617680Spst return; 62717680Spst 62817688Spst case NLPID_ISIS: 62917751Spst if (!isis_print(p, length)) 630127675Sbms print_unknown_data(p,"\n\t",caplen); 63117680Spst break; 63217680Spst 63317688Spst case NLPID_NULLNS: 634147904Ssam (void)printf("%slength: %u", 635147904Ssam eflag ? "" : ", ", 636147904Ssam length); 63717680Spst break; 63817680Spst 639146778Ssam case NLPID_Q933: 640146778Ssam q933_print(p+1, length-1); 641146778Ssam break; 642146778Ssam 643146778Ssam case NLPID_IP: 644146778Ssam ip_print(gndo, p+1, length-1); 645146778Ssam break; 646146778Ssam 647146778Ssam#ifdef INET6 648146778Ssam case NLPID_IP6: 649146778Ssam ip6_print(p+1, length-1); 650146778Ssam break; 651146778Ssam#endif 652146778Ssam 653146778Ssam case NLPID_PPP: 654146778Ssam ppp_print(p+1, length-1); 655146778Ssam break; 656146778Ssam 65717680Spst default: 658146778Ssam if (!eflag) 659146778Ssam printf("OSI NLPID 0x%02x unknown",*p); 660147904Ssam (void)printf("%slength: %u", 661147904Ssam eflag ? "" : ", ", 662147904Ssam length); 66317680Spst if (caplen > 1) 664127675Sbms print_unknown_data(p,"\n\t",caplen); 66517680Spst break; 66617680Spst } 66717680Spst} 66817680Spst 669146778Ssam#define CLNP_PDU_ER 1 670146778Ssam#define CLNP_PDU_DT 28 671146778Ssam#define CLNP_PDU_MD 29 672146778Ssam#define CLNP_PDU_ERQ 30 673146778Ssam#define CLNP_PDU_ERP 31 67417680Spst 675146778Ssamstatic struct tok clnp_pdu_values[] = { 676146778Ssam { CLNP_PDU_ER, "Error Report"}, 677146778Ssam { CLNP_PDU_MD, "MD"}, 678146778Ssam { CLNP_PDU_DT, "Data"}, 679146778Ssam { CLNP_PDU_ERQ, "Echo Request"}, 680146778Ssam { CLNP_PDU_ERP, "Echo Response"}, 681127675Sbms { 0, NULL } 682127675Sbms}; 683127675Sbms 684146778Ssamstruct clnp_header_t { 685146778Ssam u_int8_t nlpid; 686146778Ssam u_int8_t length_indicator; 687146778Ssam u_int8_t version; 688146778Ssam u_int8_t lifetime; /* units of 500ms */ 689146778Ssam u_int8_t type; 690146778Ssam u_int8_t segment_length[2]; 691146778Ssam u_int8_t cksum[2]; 692146778Ssam}; 693146778Ssam 694146778Ssamstruct clnp_segment_header_t { 695146778Ssam u_int8_t data_unit_id[2]; 696146778Ssam u_int8_t segment_offset[2]; 697146778Ssam u_int8_t total_length[2]; 698146778Ssam}; 699146778Ssam 700146778Ssam/* 701146778Ssam * clnp_print 702146778Ssam * Decode CLNP packets. Return 0 on error. 703146778Ssam */ 704146778Ssam 705146778Ssamstatic int clnp_print (const u_int8_t *pptr, u_int length) 706146778Ssam{ 707146778Ssam const u_int8_t *optr,*source_address,*dest_address; 708147904Ssam u_int li,tlen,nsap_offset,source_address_length,dest_address_length, clnp_pdu_type, clnp_flags; 709146778Ssam const struct clnp_header_t *clnp_header; 710146778Ssam const struct clnp_segment_header_t *clnp_segment_header; 711146778Ssam u_int8_t rfd_error_major,rfd_error_minor; 712146778Ssam 713146778Ssam clnp_header = (const struct clnp_header_t *) pptr; 714146778Ssam TCHECK(*clnp_header); 715146778Ssam 716146778Ssam li = clnp_header->length_indicator; 717146778Ssam optr = pptr; 718146778Ssam 719146778Ssam if (!eflag) 720146778Ssam printf("CLNP"); 721146778Ssam 722146778Ssam /* 723146778Ssam * Sanity checking of the header. 724146778Ssam */ 725146778Ssam 726146778Ssam if (clnp_header->version != CLNP_VERSION) { 727146778Ssam printf("version %d packet not supported", clnp_header->version); 728146778Ssam return (0); 729146778Ssam } 730146778Ssam 731146778Ssam /* FIXME further header sanity checking */ 732146778Ssam 733146778Ssam clnp_pdu_type = clnp_header->type & CLNP_PDU_TYPE_MASK; 734146778Ssam clnp_flags = clnp_header->type & CLNP_FLAG_MASK; 735146778Ssam 736146778Ssam pptr += sizeof(struct clnp_header_t); 737146778Ssam li -= sizeof(struct clnp_header_t); 738146778Ssam dest_address_length = *pptr; 739146778Ssam dest_address = pptr + 1; 740146778Ssam 741146778Ssam pptr += (1 + dest_address_length); 742146778Ssam li -= (1 + dest_address_length); 743146778Ssam source_address_length = *pptr; 744146778Ssam source_address = pptr +1; 745146778Ssam 746146778Ssam pptr += (1 + source_address_length); 747146778Ssam li -= (1 + source_address_length); 748146778Ssam 749146778Ssam if (vflag < 1) { 750146778Ssam printf("%s%s > %s, %s, length %u", 751146778Ssam eflag ? "" : ", ", 752146778Ssam isonsap_string(source_address, source_address_length), 753146778Ssam isonsap_string(dest_address, dest_address_length), 754146778Ssam tok2str(clnp_pdu_values,"unknown (%u)",clnp_pdu_type), 755146778Ssam length); 756146778Ssam return (1); 757146778Ssam } 758146778Ssam printf("%slength %u",eflag ? "" : ", ",length); 759146778Ssam 760146778Ssam printf("\n\t%s PDU, hlen: %u, v: %u, lifetime: %u.%us, Segment PDU length: %u, checksum: 0x%04x ", 761146778Ssam tok2str(clnp_pdu_values, "unknown (%u)",clnp_pdu_type), 762146778Ssam clnp_header->length_indicator, 763146778Ssam clnp_header->version, 764146778Ssam clnp_header->lifetime/2, 765146778Ssam (clnp_header->lifetime%2)*5, 766146778Ssam EXTRACT_16BITS(clnp_header->segment_length), 767146778Ssam EXTRACT_16BITS(clnp_header->cksum)); 768146778Ssam 769146778Ssam /* do not attempt to verify the checksum if it is zero */ 770146778Ssam if (EXTRACT_16BITS(clnp_header->cksum) == 0) 771146778Ssam printf("(unverified)"); 772146778Ssam else printf("(%s)", osi_cksum(optr, clnp_header->length_indicator) ? "incorrect" : "correct"); 773146778Ssam 774146778Ssam printf("\n\tFlags [%s]", 775146778Ssam bittok2str(clnp_flag_values,"none",clnp_flags)); 776146778Ssam 777146778Ssam printf("\n\tsource address (length %u): %s\n\tdest address (length %u): %s", 778146778Ssam source_address_length, 779146778Ssam isonsap_string(source_address, source_address_length), 780146778Ssam dest_address_length, 781146778Ssam isonsap_string(dest_address,dest_address_length)); 782146778Ssam 783146778Ssam if (clnp_flags & CLNP_SEGMENT_PART) { 784146778Ssam clnp_segment_header = (const struct clnp_segment_header_t *) pptr; 785146778Ssam printf("\n\tData Unit ID: 0x%04x, Segment Offset: %u, Total PDU Length: %u", 786146778Ssam EXTRACT_16BITS(clnp_segment_header->data_unit_id), 787146778Ssam EXTRACT_16BITS(clnp_segment_header->segment_offset), 788146778Ssam EXTRACT_16BITS(clnp_segment_header->total_length)); 789146778Ssam pptr+=sizeof(const struct clnp_segment_header_t); 790146778Ssam li-=sizeof(const struct clnp_segment_header_t); 791146778Ssam } 792146778Ssam 793146778Ssam /* now walk the options */ 794146778Ssam while (li >= 2) { 795146778Ssam u_int op, opli; 796146778Ssam const u_int8_t *tptr; 797146778Ssam 798147904Ssam TCHECK2(*pptr, 2); 799146778Ssam if (li < 2) { 800146778Ssam printf(", bad opts/li"); 801146778Ssam return (0); 802146778Ssam } 803146778Ssam op = *pptr++; 804146778Ssam opli = *pptr++; 805146778Ssam li -= 2; 806147904Ssam TCHECK2(*pptr, opli); 807146778Ssam if (opli > li) { 808146778Ssam printf(", opt (%d) too long", op); 809146778Ssam return (0); 810146778Ssam } 811146778Ssam li -= opli; 812146778Ssam tptr = pptr; 813147904Ssam tlen = opli; 814146778Ssam 815146778Ssam printf("\n\t %s Option #%u, length %u, value: ", 816146778Ssam tok2str(clnp_option_values,"Unknown",op), 817146778Ssam op, 818146778Ssam opli); 819146778Ssam 820146778Ssam switch (op) { 821146778Ssam 822147904Ssam 823147904Ssam case CLNP_OPTION_ROUTE_RECORDING: /* those two options share the format */ 824147904Ssam case CLNP_OPTION_SOURCE_ROUTING: 825147904Ssam printf("%s %s", 826147904Ssam tok2str(clnp_option_sr_rr_values,"Unknown",*tptr), 827147904Ssam tok2str(clnp_option_sr_rr_string_values,"Unknown Option %u",op)); 828147904Ssam nsap_offset=*(tptr+1); 829147904Ssam if (nsap_offset == 0) { 830147904Ssam printf(" Bad NSAP offset (0)"); 831147904Ssam break; 832147904Ssam } 833147904Ssam nsap_offset-=1; /* offset to nsap list */ 834147904Ssam if (nsap_offset > tlen) { 835147904Ssam printf(" Bad NSAP offset (past end of option)"); 836147904Ssam break; 837147904Ssam } 838147904Ssam tptr+=nsap_offset; 839147904Ssam tlen-=nsap_offset; 840147904Ssam while (tlen > 0) { 841147904Ssam source_address_length=*tptr; 842147904Ssam if (tlen < source_address_length+1) { 843147904Ssam printf("\n\t NSAP address goes past end of option"); 844147904Ssam break; 845147904Ssam } 846147904Ssam if (source_address_length > 0) { 847147904Ssam source_address=(tptr+1); 848147904Ssam TCHECK2(*source_address, source_address_length); 849147904Ssam printf("\n\t NSAP address (length %u): %s", 850147904Ssam source_address_length, 851147904Ssam isonsap_string(source_address, source_address_length)); 852147904Ssam } 853147904Ssam tlen-=source_address_length+1; 854147904Ssam } 855147904Ssam break; 856147904Ssam 857146778Ssam case CLNP_OPTION_PRIORITY: 858147904Ssam printf("0x%1x", *tptr&0x0f); 859147904Ssam break; 860146778Ssam 861147904Ssam case CLNP_OPTION_QOS_MAINTENANCE: 862147904Ssam printf("\n\t Format Code: %s", 863147904Ssam tok2str(clnp_option_scope_values,"Reserved",*tptr&CLNP_OPTION_SCOPE_MASK)); 864147904Ssam 865147904Ssam if ((*tptr&CLNP_OPTION_SCOPE_MASK) == CLNP_OPTION_SCOPE_GLOBAL) 866147904Ssam printf("\n\t QoS Flags [%s]", 867147904Ssam bittok2str(clnp_option_qos_global_values, 868147904Ssam "none", 869147904Ssam *tptr&CLNP_OPTION_OPTION_QOS_MASK)); 870147904Ssam break; 871147904Ssam 872147904Ssam case CLNP_OPTION_SECURITY: 873147904Ssam printf("\n\t Format Code: %s, Security-Level %u", 874147904Ssam tok2str(clnp_option_scope_values,"Reserved",*tptr&CLNP_OPTION_SCOPE_MASK), 875147904Ssam *(tptr+1)); 876147904Ssam break; 877147904Ssam 878146778Ssam case CLNP_OPTION_DISCARD_REASON: 879146778Ssam rfd_error_major = (*tptr&0xf0) >> 4; 880146778Ssam rfd_error_minor = *tptr&0x0f; 881146778Ssam printf("\n\t Class: %s Error (0x%01x), %s (0x%01x)", 882146778Ssam tok2str(clnp_option_rfd_class_values,"Unknown",rfd_error_major), 883146778Ssam rfd_error_major, 884146778Ssam tok2str(clnp_option_rfd_error_class[rfd_error_major],"Unknown",rfd_error_minor), 885146778Ssam rfd_error_minor); 886146778Ssam break; 887146778Ssam 888147904Ssam case CLNP_OPTION_PADDING: 889147904Ssam printf("padding data"); 890147904Ssam break; 891147904Ssam 892146778Ssam /* 893146778Ssam * FIXME those are the defined Options that lack a decoder 894146778Ssam * you are welcome to contribute code ;-) 895146778Ssam */ 896146778Ssam 897146778Ssam default: 898146778Ssam print_unknown_data(tptr,"\n\t ",opli); 899146778Ssam break; 900146778Ssam } 901146778Ssam if (vflag > 1) 902146778Ssam print_unknown_data(pptr,"\n\t ",opli); 903146778Ssam pptr += opli; 904146778Ssam } 905146778Ssam 906146778Ssam switch (clnp_pdu_type) { 907146778Ssam 908146778Ssam case CLNP_PDU_ER: /* fall through */ 909146778Ssam case CLNP_PDU_ERP: 910147904Ssam TCHECK(*pptr); 911146778Ssam if (*(pptr) == NLPID_CLNP) { 912146778Ssam printf("\n\t-----original packet-----\n\t"); 913146778Ssam /* FIXME recursion protection */ 914146778Ssam clnp_print(pptr, length-clnp_header->length_indicator); 915146778Ssam break; 916146778Ssam } 917146778Ssam 918146778Ssam case CLNP_PDU_DT: 919146778Ssam case CLNP_PDU_MD: 920146778Ssam case CLNP_PDU_ERQ: 921146778Ssam 922146778Ssam default: 923146778Ssam /* dump the PDU specific data */ 924146778Ssam if (length-(pptr-optr) > 0) { 925146778Ssam printf("\n\t undecoded non-header data, length %u",length-clnp_header->length_indicator); 926146778Ssam print_unknown_data(pptr,"\n\t ",length-(pptr-optr)); 927146778Ssam } 928146778Ssam } 929146778Ssam 930146778Ssam return (1); 931146778Ssam 932146778Ssam trunc: 933146778Ssam fputs("[|clnp]", stdout); 934146778Ssam return (1); 935146778Ssam 936146778Ssam} 937146778Ssam 938146778Ssam 939146778Ssam#define ESIS_PDU_REDIRECT 6 940146778Ssam#define ESIS_PDU_ESH 2 941146778Ssam#define ESIS_PDU_ISH 4 942146778Ssam 943146778Ssamstatic struct tok esis_pdu_values[] = { 944146778Ssam { ESIS_PDU_REDIRECT, "redirect"}, 945146778Ssam { ESIS_PDU_ESH, "ESH"}, 946146778Ssam { ESIS_PDU_ISH, "ISH"}, 947146778Ssam { 0, NULL } 948146778Ssam}; 949146778Ssam 950146778Ssamstruct esis_header_t { 951146778Ssam u_int8_t nlpid; 952146778Ssam u_int8_t length_indicator; 953127675Sbms u_int8_t version; 954127675Sbms u_int8_t reserved; 955127675Sbms u_int8_t type; 956146778Ssam u_int8_t holdtime[2]; 957127675Sbms u_int8_t cksum[2]; 95817680Spst}; 95917680Spst 96017680Spststatic void 961146778Ssamesis_print(const u_int8_t *pptr, u_int length) 96217680Spst{ 963146778Ssam const u_int8_t *optr; 964146778Ssam u_int li,esis_pdu_type,source_address_length, source_address_number; 965146778Ssam const struct esis_header_t *esis_header; 96617680Spst 967146778Ssam if (!eflag) 968146778Ssam printf("ES-IS"); 969146778Ssam 97098527Sfenner if (length <= 2) { 97117680Spst if (qflag) 972146778Ssam printf("bad pkt!"); 97317680Spst else 974146778Ssam printf("no header at all!"); 97517680Spst return; 97617680Spst } 977146778Ssam 978146778Ssam esis_header = (const struct esis_header_t *) pptr; 979147904Ssam TCHECK(*esis_header); 980146778Ssam li = esis_header->length_indicator; 981146778Ssam optr = pptr; 982146778Ssam 983146778Ssam /* 984146778Ssam * Sanity checking of the header. 985146778Ssam */ 986146778Ssam 987146778Ssam if (esis_header->nlpid != NLPID_ESIS) { 988146778Ssam printf(" nlpid 0x%02x packet not supported", esis_header->nlpid); 989146778Ssam return; 990146778Ssam } 991146778Ssam 992146778Ssam if (esis_header->version != ESIS_VERSION) { 993146778Ssam printf(" version %d packet not supported", esis_header->version); 994146778Ssam return; 995146778Ssam } 996146778Ssam 99717680Spst if (li > length) { 998146778Ssam printf(" length indicator(%d) > PDU size (%d)!", li, length); 999146778Ssam return; 100017680Spst } 1001146778Ssam 1002146778Ssam if (li < sizeof(struct esis_header_t) + 2) { 1003146778Ssam printf(" length indicator < min PDU size %d:", li); 1004146778Ssam while (--length != 0) 1005146778Ssam printf("%02X", *pptr++); 1006146778Ssam return; 100717680Spst } 100817680Spst 1009146778Ssam esis_pdu_type = esis_header->type & ESIS_PDU_TYPE_MASK; 101017680Spst 1011146778Ssam if (vflag < 1) { 1012146778Ssam printf("%s%s, length %u", 1013146778Ssam eflag ? "" : ", ", 1014146778Ssam tok2str(esis_pdu_values,"unknown type (%u)",esis_pdu_type), 1015146778Ssam length); 1016146778Ssam return; 1017146778Ssam } else 1018146778Ssam printf("%slength %u\n\t%s (%u)", 1019146778Ssam eflag ? "" : ", ", 1020146778Ssam length, 1021146778Ssam tok2str(esis_pdu_values,"unknown type: %u", esis_pdu_type), 1022146778Ssam esis_pdu_type); 102317680Spst 1024146778Ssam printf(", v: %u%s", esis_header->version, esis_header->version == ESIS_VERSION ? "" : "unsupported" ); 1025146778Ssam printf(", checksum: 0x%04x ", EXTRACT_16BITS(esis_header->cksum)); 1026146778Ssam /* do not attempt to verify the checksum if it is zero */ 1027146778Ssam if (EXTRACT_16BITS(esis_header->cksum) == 0) 1028146778Ssam printf("(unverified)"); 1029147904Ssam else 1030147904Ssam printf("(%s)", osi_cksum(pptr, li) ? "incorrect" : "correct"); 103117680Spst 1032146778Ssam printf(", holding time: %us, length indicator: %u",EXTRACT_16BITS(esis_header->holdtime),li); 103317680Spst 1034146778Ssam if (vflag > 1) 1035146778Ssam print_unknown_data(optr,"\n\t",sizeof(struct esis_header_t)); 1036146778Ssam 1037146778Ssam pptr += sizeof(struct esis_header_t); 1038146778Ssam li -= sizeof(struct esis_header_t); 1039146778Ssam 1040146778Ssam switch (esis_pdu_type) { 1041146778Ssam case ESIS_PDU_REDIRECT: { 1042147904Ssam const u_int8_t *dst, *snpa, *neta; 1043147904Ssam u_int dstl, snpal, netal; 1044146778Ssam 1045147904Ssam TCHECK(*pptr); 1046147904Ssam if (li < 1) { 1047147904Ssam printf(", bad redirect/li"); 104817680Spst return; 1049147904Ssam } 1050147904Ssam dstl = *pptr; 1051147904Ssam pptr++; 1052147904Ssam li--; 1053147904Ssam TCHECK2(*pptr, dstl); 1054147904Ssam if (li < dstl) { 1055147904Ssam printf(", bad redirect/li"); 105617680Spst return; 1057147904Ssam } 1058147904Ssam dst = pptr; 1059147904Ssam pptr += dstl; 1060147904Ssam li -= dstl; 1061147904Ssam printf("\n\t %s", isonsap_string(dst,dstl)); 1062146778Ssam 1063147904Ssam TCHECK(*pptr); 1064147904Ssam if (li < 1) { 1065147904Ssam printf(", bad redirect/li"); 1066147904Ssam return; 1067147904Ssam } 1068147904Ssam snpal = *pptr; 1069147904Ssam pptr++; 1070147904Ssam li--; 1071147904Ssam TCHECK2(*pptr, snpal); 1072147904Ssam if (li < snpal) { 1073147904Ssam printf(", bad redirect/li"); 1074147904Ssam return; 1075147904Ssam } 1076147904Ssam snpa = pptr; 1077147904Ssam pptr += snpal; 1078147904Ssam li -= snpal; 1079147904Ssam TCHECK(*pptr); 1080147904Ssam if (li < 1) { 1081147904Ssam printf(", bad redirect/li"); 1082147904Ssam return; 1083147904Ssam } 1084147904Ssam netal = *pptr; 1085147904Ssam pptr++; 1086147904Ssam TCHECK2(*pptr, netal); 1087147904Ssam if (li < netal) { 1088147904Ssam printf(", bad redirect/li"); 1089147904Ssam return; 1090147904Ssam } 1091147904Ssam neta = pptr; 1092147904Ssam pptr += netal; 1093147904Ssam li -= netal; 1094147904Ssam 1095147904Ssam if (netal == 0) 1096147904Ssam printf("\n\t %s", etheraddr_string(snpa)); 109717680Spst else 1098147904Ssam printf("\n\t %s", isonsap_string(neta,netal)); 109917680Spst break; 110017680Spst } 1101127675Sbms 1102146778Ssam case ESIS_PDU_ESH: 1103147904Ssam TCHECK(*pptr); 1104147904Ssam if (li < 1) { 1105147904Ssam printf(", bad esh/li"); 1106147904Ssam return; 1107147904Ssam } 1108146778Ssam source_address_number = *pptr; 1109146778Ssam pptr++; 1110146778Ssam li--; 1111127675Sbms 1112146778Ssam printf("\n\t Number of Source Addresses: %u", source_address_number); 1113146778Ssam 1114146778Ssam while (source_address_number > 0) { 1115147904Ssam TCHECK(*pptr); 1116147904Ssam if (li < 1) { 1117147904Ssam printf(", bad esh/li"); 1118147904Ssam return; 1119147904Ssam } 1120146778Ssam source_address_length = *pptr; 1121147904Ssam pptr++; 1122147904Ssam li--; 1123147904Ssam 1124147904Ssam TCHECK2(*pptr, source_address_length); 1125147904Ssam if (li < source_address_length) { 1126147904Ssam printf(", bad esh/li"); 1127147904Ssam return; 1128147904Ssam } 1129146778Ssam printf("\n\t NET (length: %u): %s", 1130146778Ssam source_address_length, 1131147904Ssam isonsap_string(pptr,source_address_length)); 1132147904Ssam pptr += source_address_length; 1133147904Ssam li -= source_address_length; 1134146778Ssam source_address_number--; 1135146778Ssam } 1136146778Ssam 1137146778Ssam break; 1138146778Ssam 1139146778Ssam case ESIS_PDU_ISH: { 1140147904Ssam TCHECK(*pptr); 1141147904Ssam if (li < 1) { 1142147904Ssam printf(", bad ish/li"); 1143147904Ssam return; 1144147904Ssam } 1145146778Ssam source_address_length = *pptr; 1146147904Ssam pptr++; 1147147904Ssam li--; 1148147904Ssam TCHECK2(*pptr, source_address_length); 1149147904Ssam if (li < source_address_length) { 1150147904Ssam printf(", bad ish/li"); 1151147904Ssam return; 1152147904Ssam } 1153147904Ssam printf("\n\t NET (length: %u): %s", source_address_length, isonsap_string(pptr, source_address_length)); 1154147904Ssam pptr += source_address_length; 1155147904Ssam li -= source_address_length; 1156146778Ssam break; 115717680Spst } 115817680Spst 115917680Spst default: 1160127675Sbms if (vflag <= 1) { 1161146778Ssam if (pptr < snapend) 1162146778Ssam print_unknown_data(pptr,"\n\t ",snapend-pptr); 1163127675Sbms } 1164127675Sbms return; 116517680Spst } 1166127675Sbms 1167146778Ssam /* now walk the options */ 1168146778Ssam while (li >= 2) { 1169146778Ssam u_int op, opli; 1170146778Ssam const u_int8_t *tptr; 1171146778Ssam 1172147904Ssam TCHECK2(*pptr, 2); 1173146778Ssam if (li < 2) { 1174146778Ssam printf(", bad opts/li"); 1175146778Ssam return; 1176146778Ssam } 1177146778Ssam op = *pptr++; 1178146778Ssam opli = *pptr++; 1179146778Ssam li -= 2; 1180146778Ssam if (opli > li) { 1181146778Ssam printf(", opt (%d) too long", op); 1182146778Ssam return; 1183146778Ssam } 1184146778Ssam li -= opli; 1185146778Ssam tptr = pptr; 1186146778Ssam 1187146778Ssam printf("\n\t %s Option #%u, length %u, value: ", 1188146778Ssam tok2str(esis_option_values,"Unknown",op), 1189146778Ssam op, 1190146778Ssam opli); 119117680Spst 1192146778Ssam switch (op) { 1193127675Sbms 1194146778Ssam case ESIS_OPTION_ES_CONF_TIME: 1195147904Ssam TCHECK2(*pptr, 2); 1196146778Ssam printf("%us", EXTRACT_16BITS(tptr)); 1197146778Ssam break; 1198127675Sbms 1199146778Ssam case ESIS_OPTION_PROTOCOLS: 1200146778Ssam while (opli>0) { 1201147904Ssam TCHECK(*pptr); 1202146778Ssam printf("%s (0x%02x)", 1203146778Ssam tok2str(nlpid_values, 1204146778Ssam "unknown", 1205146778Ssam *tptr), 1206146778Ssam *tptr); 1207146778Ssam if (opli>1) /* further NPLIDs ? - put comma */ 1208146778Ssam printf(", "); 1209146778Ssam tptr++; 1210146778Ssam opli--; 1211146778Ssam } 1212146778Ssam break; 1213127675Sbms 1214146778Ssam /* 1215146778Ssam * FIXME those are the defined Options that lack a decoder 1216146778Ssam * you are welcome to contribute code ;-) 1217146778Ssam */ 1218127675Sbms 1219146778Ssam case ESIS_OPTION_QOS_MAINTENANCE: 1220146778Ssam case ESIS_OPTION_SECURITY: 1221146778Ssam case ESIS_OPTION_PRIORITY: 1222146778Ssam case ESIS_OPTION_ADDRESS_MASK: 1223146778Ssam case ESIS_OPTION_SNPA_MASK: 122417680Spst 1225146778Ssam default: 1226146778Ssam print_unknown_data(tptr,"\n\t ",opli); 1227146778Ssam break; 1228146778Ssam } 1229146778Ssam if (vflag > 1) 1230146778Ssam print_unknown_data(pptr,"\n\t ",opli); 1231146778Ssam pptr += opli; 1232146778Ssam } 1233147904Ssamtrunc: 1234147904Ssam return; 1235146778Ssam} 1236146778Ssam 1237127675Sbms/* shared routine for printing system, node and lsp-ids */ 1238127675Sbmsstatic char * 1239127675Sbmsisis_print_id(const u_int8_t *cp, int id_len) 124098527Sfenner{ 1241127675Sbms int i; 1242127675Sbms static char id[sizeof("xxxx.xxxx.xxxx.yy-zz")]; 1243127675Sbms char *pos = id; 124417688Spst 1245127675Sbms for (i = 1; i <= SYSTEM_ID_LEN; i++) { 1246127675Sbms snprintf(pos, sizeof(id) - (pos - id), "%02x", *cp++); 1247127675Sbms pos += strlen(pos); 1248127675Sbms if (i == 2 || i == 4) 1249127675Sbms *pos++ = '.'; 125098527Sfenner } 1251127675Sbms if (id_len >= NODE_ID_LEN) { 1252127675Sbms snprintf(pos, sizeof(id) - (pos - id), ".%02x", *cp++); 1253127675Sbms pos += strlen(pos); 1254127675Sbms } 1255127675Sbms if (id_len == LSP_ID_LEN) 1256127675Sbms snprintf(pos, sizeof(id) - (pos - id), "-%02x", *cp); 1257127675Sbms return (id); 125898527Sfenner} 125998527Sfenner 1260127675Sbms/* print the 4-byte metric block which is common found in the old-style TLVs */ 126198527Sfennerstatic int 1262127675Sbmsisis_print_metric_block (const struct isis_metric_block *isis_metric_block) 126398527Sfenner{ 1264127675Sbms printf(", Default Metric: %d, %s", 1265127675Sbms ISIS_LSP_TLV_METRIC_VALUE(isis_metric_block->metric_default), 1266127675Sbms ISIS_LSP_TLV_METRIC_IE(isis_metric_block->metric_default) ? "External" : "Internal"); 1267127675Sbms if (!ISIS_LSP_TLV_METRIC_SUPPORTED(isis_metric_block->metric_delay)) 1268127675Sbms printf("\n\t\t Delay Metric: %d, %s", 1269127675Sbms ISIS_LSP_TLV_METRIC_VALUE(isis_metric_block->metric_delay), 1270127675Sbms ISIS_LSP_TLV_METRIC_IE(isis_metric_block->metric_delay) ? "External" : "Internal"); 1271127675Sbms if (!ISIS_LSP_TLV_METRIC_SUPPORTED(isis_metric_block->metric_expense)) 1272127675Sbms printf("\n\t\t Expense Metric: %d, %s", 1273127675Sbms ISIS_LSP_TLV_METRIC_VALUE(isis_metric_block->metric_expense), 1274127675Sbms ISIS_LSP_TLV_METRIC_IE(isis_metric_block->metric_expense) ? "External" : "Internal"); 1275127675Sbms if (!ISIS_LSP_TLV_METRIC_SUPPORTED(isis_metric_block->metric_error)) 1276127675Sbms printf("\n\t\t Error Metric: %d, %s", 1277127675Sbms ISIS_LSP_TLV_METRIC_VALUE(isis_metric_block->metric_error), 1278127675Sbms ISIS_LSP_TLV_METRIC_IE(isis_metric_block->metric_error) ? "External" : "Internal"); 127998527Sfenner 1280127675Sbms return(1); /* everything is ok */ 128198527Sfenner} 128298527Sfenner 128398527Sfennerstatic int 1284127675Sbmsisis_print_tlv_ip_reach (const u_int8_t *cp, const char *ident, int length) 128598527Sfenner{ 1286127675Sbms int prefix_len; 1287127675Sbms const struct isis_tlv_ip_reach *tlv_ip_reach; 128898527Sfenner 1289127675Sbms tlv_ip_reach = (const struct isis_tlv_ip_reach *)cp; 1290127675Sbms 1291127675Sbms while (length > 0) { 1292127675Sbms if ((size_t)length < sizeof(*tlv_ip_reach)) { 1293127675Sbms printf("short IPv4 Reachability (%d vs %lu)", 1294127675Sbms length, 1295127675Sbms (unsigned long)sizeof(*tlv_ip_reach)); 129698527Sfenner return (0); 129798527Sfenner } 1298127675Sbms 1299127675Sbms if (!TTEST(*tlv_ip_reach)) 1300127675Sbms return (0); 1301127675Sbms 1302127675Sbms prefix_len = mask2plen(EXTRACT_32BITS(tlv_ip_reach->mask)); 1303127675Sbms 1304127675Sbms if (prefix_len == -1) 1305127675Sbms printf("%sIPv4 prefix: %s mask %s", 1306127675Sbms ident, 1307127675Sbms ipaddr_string((tlv_ip_reach->prefix)), 1308127675Sbms ipaddr_string((tlv_ip_reach->mask))); 1309127675Sbms else 1310127675Sbms printf("%sIPv4 prefix: %15s/%u", 1311127675Sbms ident, 1312127675Sbms ipaddr_string((tlv_ip_reach->prefix)), 1313127675Sbms prefix_len); 1314127675Sbms 1315127675Sbms printf(", Distribution: %s, Metric: %u, %s", 1316127675Sbms ISIS_LSP_TLV_METRIC_UPDOWN(tlv_ip_reach->isis_metric_block.metric_default) ? "down" : "up", 1317127675Sbms ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->isis_metric_block.metric_default), 1318127675Sbms ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->isis_metric_block.metric_default) ? "External" : "Internal"); 1319127675Sbms 1320127675Sbms if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_ip_reach->isis_metric_block.metric_delay)) 1321127675Sbms printf("%s Delay Metric: %u, %s", 1322127675Sbms ident, 1323127675Sbms ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->isis_metric_block.metric_delay), 1324127675Sbms ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->isis_metric_block.metric_delay) ? "External" : "Internal"); 1325127675Sbms 1326127675Sbms if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_ip_reach->isis_metric_block.metric_expense)) 1327127675Sbms printf("%s Expense Metric: %u, %s", 1328127675Sbms ident, 1329127675Sbms ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->isis_metric_block.metric_expense), 1330127675Sbms ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->isis_metric_block.metric_expense) ? "External" : "Internal"); 1331127675Sbms 1332127675Sbms if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_ip_reach->isis_metric_block.metric_error)) 1333127675Sbms printf("%s Error Metric: %u, %s", 1334127675Sbms ident, 1335127675Sbms ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->isis_metric_block.metric_error), 1336127675Sbms ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->isis_metric_block.metric_error) ? "External" : "Internal"); 1337127675Sbms 1338127675Sbms length -= sizeof(struct isis_tlv_ip_reach); 1339127675Sbms tlv_ip_reach++; 134098527Sfenner } 134198527Sfenner return (1); 134298527Sfenner} 134398527Sfenner 1344127675Sbms/* 1345127675Sbms * this is the common IP-REACH subTLV decoder it is called 1346127675Sbms * from various EXTD-IP REACH TLVs (135,235,236,237) 1347127675Sbms */ 134898527Sfenner 1349127675Sbmsstatic int 1350127675Sbmsisis_print_ip_reach_subtlv (const u_int8_t *tptr,int subt,int subl,const char *ident) { 1351127675Sbms 1352127675Sbms /* first lets see if we know the subTLVs name*/ 1353127675Sbms printf("%s%s subTLV #%u, length: %u", 1354127675Sbms ident, 1355127675Sbms tok2str(isis_ext_ip_reach_subtlv_values, 1356127675Sbms "unknown", 1357127675Sbms subt), 1358127675Sbms subt, 1359127675Sbms subl); 1360127675Sbms 1361127675Sbms if (!TTEST2(*tptr,subl)) 1362127675Sbms goto trunctlv; 1363127675Sbms 1364127675Sbms switch(subt) { 1365146778Ssam case ISIS_SUBTLV_EXTD_IP_REACH_MGMT_PREFIX_COLOR: /* fall through */ 1366146778Ssam case ISIS_SUBTLV_EXTD_IP_REACH_ADMIN_TAG32: 1367127675Sbms while (subl >= 4) { 1368127675Sbms printf(", 0x%08x (=%u)", 1369127675Sbms EXTRACT_32BITS(tptr), 1370127675Sbms EXTRACT_32BITS(tptr)); 1371127675Sbms tptr+=4; 1372127675Sbms subl-=4; 137317688Spst } 1374127675Sbms break; 1375146778Ssam case ISIS_SUBTLV_EXTD_IP_REACH_ADMIN_TAG64: 1376127675Sbms while (subl >= 8) { 1377127675Sbms printf(", 0x%08x%08x", 1378127675Sbms EXTRACT_32BITS(tptr), 1379127675Sbms EXTRACT_32BITS(tptr+4)); 1380127675Sbms tptr+=8; 1381127675Sbms subl-=8; 1382127675Sbms } 1383127675Sbms break; 1384127675Sbms default: 1385127675Sbms if(!print_unknown_data(tptr,"\n\t\t ", 1386127675Sbms subl)) 1387127675Sbms return(0); 1388127675Sbms break; 1389127675Sbms } 1390127675Sbms return(1); 1391127675Sbms 1392127675Sbmstrunctlv: 1393127675Sbms printf("%spacket exceeded snapshot",ident); 1394127675Sbms return(0); 139598527Sfenner} 139617688Spst 1397127675Sbms/* 1398127675Sbms * this is the common IS-REACH subTLV decoder it is called 1399127675Sbms * from isis_print_ext_is_reach() 1400127675Sbms */ 1401127675Sbms 140298527Sfennerstatic int 1403127675Sbmsisis_print_is_reach_subtlv (const u_int8_t *tptr,int subt,int subl,const char *ident) { 140498527Sfenner 1405146778Ssam int priority_level,bandwidth_constraint; 1406127675Sbms union { /* int to float conversion buffer for several subTLVs */ 1407127675Sbms float f; 1408127675Sbms u_int32_t i; 1409127675Sbms } bw; 141098527Sfenner 1411127675Sbms /* first lets see if we know the subTLVs name*/ 1412127675Sbms printf("%s%s subTLV #%u, length: %u", 1413127675Sbms ident, 1414127675Sbms tok2str(isis_ext_is_reach_subtlv_values, 1415127675Sbms "unknown", 1416127675Sbms subt), 1417127675Sbms subt, 1418127675Sbms subl); 141998527Sfenner 1420127675Sbms if (!TTEST2(*tptr,subl)) 1421127675Sbms goto trunctlv; 142298527Sfenner 1423127675Sbms switch(subt) { 1424146778Ssam case ISIS_SUBTLV_EXT_IS_REACH_ADMIN_GROUP: 1425146778Ssam case ISIS_SUBTLV_EXT_IS_REACH_LINK_LOCAL_REMOTE_ID: 1426146778Ssam case ISIS_SUBTLV_EXT_IS_REACH_LINK_REMOTE_ID: 1427127675Sbms if (subl >= 4) { 1428127675Sbms printf(", 0x%08x", EXTRACT_32BITS(tptr)); 1429127675Sbms if (subl == 8) /* draft-ietf-isis-gmpls-extensions */ 1430127675Sbms printf(", 0x%08x", EXTRACT_32BITS(tptr+4)); 1431127675Sbms } 1432127675Sbms break; 1433146778Ssam case ISIS_SUBTLV_EXT_IS_REACH_IPV4_INTF_ADDR: 1434146778Ssam case ISIS_SUBTLV_EXT_IS_REACH_IPV4_NEIGHBOR_ADDR: 1435127675Sbms if (subl >= 4) 1436127675Sbms printf(", %s", ipaddr_string(tptr)); 1437127675Sbms break; 1438146778Ssam case ISIS_SUBTLV_EXT_IS_REACH_MAX_LINK_BW : 1439146778Ssam case ISIS_SUBTLV_EXT_IS_REACH_RESERVABLE_BW: 1440127675Sbms if (subl >= 4) { 1441127675Sbms bw.i = EXTRACT_32BITS(tptr); 1442127675Sbms printf(", %.3f Mbps", bw.f*8/1000000 ); 1443127675Sbms } 1444127675Sbms break; 1445146778Ssam case ISIS_SUBTLV_EXT_IS_REACH_UNRESERVED_BW : 1446127675Sbms if (subl >= 32) { 1447127675Sbms for (priority_level = 0; priority_level < 8; priority_level++) { 1448127675Sbms bw.i = EXTRACT_32BITS(tptr); 1449127675Sbms printf("%s priority level %d: %.3f Mbps", 1450127675Sbms ident, 1451127675Sbms priority_level, 1452127675Sbms bw.f*8/1000000 ); 1453127675Sbms tptr+=4; 1454127675Sbms } 1455127675Sbms } 1456127675Sbms break; 1457146778Ssam case ISIS_SUBTLV_EXT_IS_REACH_DIFFSERV_TE: 1458146778Ssam printf("%sBandwidth Constraints Model ID: %s (%u)", 1459146778Ssam ident, 1460146778Ssam tok2str(diffserv_te_bc_values, "unknown", *tptr), 1461146778Ssam *tptr); 1462146778Ssam tptr++; 1463146778Ssam /* decode BCs until the subTLV ends */ 1464146778Ssam for (bandwidth_constraint = 0; bandwidth_constraint < (subl-1)/4; bandwidth_constraint++) { 1465146778Ssam bw.i = EXTRACT_32BITS(tptr); 1466146778Ssam printf("%s Bandwidth constraint %d: %.3f Mbps", 1467146778Ssam ident, 1468146778Ssam bandwidth_constraint, 1469146778Ssam bw.f*8/1000000 ); 1470146778Ssam tptr+=4; 1471146778Ssam } 1472146778Ssam break; 1473146778Ssam case ISIS_SUBTLV_EXT_IS_REACH_TE_METRIC: 1474127675Sbms if (subl >= 3) 1475127675Sbms printf(", %u", EXTRACT_24BITS(tptr)); 1476127675Sbms break; 1477146778Ssam case ISIS_SUBTLV_EXT_IS_REACH_LINK_PROTECTION_TYPE: 1478127675Sbms if (subl >= 2) { 1479127675Sbms printf(", %s, Priority %u", 1480127675Sbms bittok2str(gmpls_link_prot_values, "none", *tptr), 1481127675Sbms *(tptr+1)); 1482127675Sbms } 1483127675Sbms break; 1484146778Ssam case ISIS_SUBTLV_EXT_IS_REACH_INTF_SW_CAP_DESCR: 1485127675Sbms if (subl >= 36) { 1486127675Sbms printf("%s Interface Switching Capability:%s", 1487127675Sbms ident, 1488127675Sbms tok2str(gmpls_switch_cap_values, "Unknown", *(tptr))); 1489127675Sbms printf(", LSP Encoding: %s", 1490127675Sbms tok2str(gmpls_encoding_values, "Unknown", *(tptr+1))); 1491127675Sbms tptr+=4; 1492127675Sbms printf("%s Max LSP Bandwidth:",ident); 1493127675Sbms for (priority_level = 0; priority_level < 8; priority_level++) { 1494127675Sbms bw.i = EXTRACT_32BITS(tptr); 1495127675Sbms printf("%s priority level %d: %.3f Mbps", 1496127675Sbms ident, 1497127675Sbms priority_level, 1498127675Sbms bw.f*8/1000000 ); 1499127675Sbms tptr+=4; 1500127675Sbms } 1501127675Sbms subl-=36; 1502127675Sbms /* there is some optional stuff left to decode but this is as of yet 1503127675Sbms not specified so just lets hexdump what is left */ 1504127675Sbms if(subl>0){ 1505127675Sbms if(!print_unknown_data(tptr,"\n\t\t ", 1506147904Ssam subl)) 1507127675Sbms return(0); 1508127675Sbms } 1509127675Sbms } 1510127675Sbms break; 1511127675Sbms default: 1512127675Sbms if(!print_unknown_data(tptr,"\n\t\t ", 1513127675Sbms subl)) 1514127675Sbms return(0); 1515127675Sbms break; 1516127675Sbms } 1517127675Sbms return(1); 151898527Sfenner 1519127675Sbmstrunctlv: 1520127675Sbms printf("%spacket exceeded snapshot",ident); 1521127675Sbms return(0); 1522127675Sbms} 152398527Sfenner 152498527Sfenner 1525127675Sbms/* 1526127675Sbms * this is the common IS-REACH decoder it is called 1527127675Sbms * from various EXTD-IS REACH style TLVs (22,24,222) 1528127675Sbms */ 152998527Sfenner 1530127675Sbmsstatic int 1531127675Sbmsisis_print_ext_is_reach (const u_int8_t *tptr,const char *ident, int tlv_type) { 153298527Sfenner 1533127675Sbms char ident_buffer[20]; 1534127675Sbms int subtlv_type,subtlv_len,subtlv_sum_len; 1535127675Sbms int proc_bytes = 0; /* how many bytes did we process ? */ 1536127675Sbms 1537127675Sbms if (!TTEST2(*tptr, NODE_ID_LEN)) 1538127675Sbms return(0); 153998527Sfenner 1540127675Sbms printf("%sIS Neighbor: %s", ident, isis_print_id(tptr, NODE_ID_LEN)); 1541127675Sbms tptr+=(NODE_ID_LEN); 154298527Sfenner 1543146778Ssam if (tlv_type != ISIS_TLV_IS_ALIAS_ID) { /* the Alias TLV Metric field is implicit 0 */ 1544127675Sbms if (!TTEST2(*tptr, 3)) /* and is therefore skipped */ 1545127675Sbms return(0); 1546127675Sbms printf(", Metric: %d",EXTRACT_24BITS(tptr)); 1547127675Sbms tptr+=3; 1548127675Sbms } 1549127675Sbms 1550127675Sbms if (!TTEST2(*tptr, 1)) 1551127675Sbms return(0); 1552127675Sbms subtlv_sum_len=*(tptr++); /* read out subTLV length */ 1553127675Sbms proc_bytes=NODE_ID_LEN+3+1; 1554127675Sbms printf(", %ssub-TLVs present",subtlv_sum_len ? "" : "no "); 1555127675Sbms if (subtlv_sum_len) { 1556127675Sbms printf(" (%u)",subtlv_sum_len); 1557127675Sbms while (subtlv_sum_len>0) { 1558127675Sbms if (!TTEST2(*tptr,2)) 1559127675Sbms return(0); 1560127675Sbms subtlv_type=*(tptr++); 1561127675Sbms subtlv_len=*(tptr++); 1562127675Sbms /* prepend the ident string */ 1563127675Sbms snprintf(ident_buffer, sizeof(ident_buffer), "%s ",ident); 1564127675Sbms if(!isis_print_is_reach_subtlv(tptr,subtlv_type,subtlv_len,ident_buffer)) 1565127675Sbms return(0); 1566127675Sbms tptr+=subtlv_len; 1567127675Sbms subtlv_sum_len-=(subtlv_len+2); 1568127675Sbms proc_bytes+=(subtlv_len+2); 1569127675Sbms } 1570127675Sbms } 1571127675Sbms return(proc_bytes); 157217688Spst} 157317688Spst 157417688Spst/* 1575127675Sbms * this is the common Multi Topology ID decoder 1576127675Sbms * it is called from various MT-TLVs (222,229,235,237) 1577127675Sbms */ 1578127675Sbms 1579127675Sbmsstatic int 1580127675Sbmsisis_print_mtid (const u_int8_t *tptr,const char *ident) { 1581127675Sbms 1582127675Sbms if (!TTEST2(*tptr, 2)) 1583127675Sbms return(0); 1584127675Sbms 1585127675Sbms printf("%s%s", 1586127675Sbms ident, 1587127675Sbms tok2str(isis_mt_values, 1588127675Sbms "Reserved for IETF Consensus", 1589127675Sbms ISIS_MASK_MTID(EXTRACT_16BITS(tptr)))); 1590127675Sbms 1591127675Sbms printf(" Topology (0x%03x), Flags: [%s]", 1592127675Sbms ISIS_MASK_MTID(EXTRACT_16BITS(tptr)), 1593127675Sbms bittok2str(isis_mt_flag_values, "none",ISIS_MASK_MTFLAGS(EXTRACT_16BITS(tptr)))); 1594127675Sbms 1595127675Sbms return(2); 1596127675Sbms} 1597127675Sbms 1598127675Sbms/* 1599127675Sbms * this is the common extended IP reach decoder 1600127675Sbms * it is called from TLVs (135,235,236,237) 1601127675Sbms * we process the TLV and optional subTLVs and return 1602127675Sbms * the amount of processed bytes 1603127675Sbms */ 1604127675Sbms 1605127675Sbmsstatic int 1606127675Sbmsisis_print_extd_ip_reach (const u_int8_t *tptr, const char *ident, u_int16_t afi) { 1607127675Sbms 1608127675Sbms char ident_buffer[20]; 1609127675Sbms u_int8_t prefix[16]; /* shared copy buffer for IPv4 and IPv6 prefixes */ 1610127675Sbms u_int metric, status_byte, bit_length, byte_length, sublen, processed, subtlvtype, subtlvlen; 1611127675Sbms 1612127675Sbms if (!TTEST2(*tptr, 4)) 1613127675Sbms return (0); 1614127675Sbms metric = EXTRACT_32BITS(tptr); 1615127675Sbms processed=4; 1616127675Sbms tptr+=4; 1617127675Sbms 1618127675Sbms if (afi == IPV4) { 1619127675Sbms if (!TTEST2(*tptr, 1)) /* fetch status byte */ 1620127675Sbms return (0); 1621127675Sbms status_byte=*(tptr++); 1622127675Sbms bit_length = status_byte&0x3f; 1623127675Sbms processed++; 1624127675Sbms#ifdef INET6 1625127675Sbms } else if (afi == IPV6) { 1626127675Sbms if (!TTEST2(*tptr, 1)) /* fetch status & prefix_len byte */ 1627127675Sbms return (0); 1628127675Sbms status_byte=*(tptr++); 1629127675Sbms bit_length=*(tptr++); 1630127675Sbms processed+=2; 1631127675Sbms#endif 1632127675Sbms } else 1633127675Sbms return (0); /* somebody is fooling us */ 1634127675Sbms 1635127675Sbms byte_length = (bit_length + 7) / 8; /* prefix has variable length encoding */ 1636127675Sbms 1637127675Sbms if (!TTEST2(*tptr, byte_length)) 1638127675Sbms return (0); 1639127675Sbms memset(prefix, 0, 16); /* clear the copy buffer */ 1640127675Sbms memcpy(prefix,tptr,byte_length); /* copy as much as is stored in the TLV */ 1641127675Sbms tptr+=byte_length; 1642127675Sbms processed+=byte_length; 1643127675Sbms 1644127675Sbms if (afi == IPV4) 1645127675Sbms printf("%sIPv4 prefix: %15s/%u", 1646127675Sbms ident, 1647127675Sbms ipaddr_string(prefix), 1648127675Sbms bit_length); 1649127675Sbms#ifdef INET6 1650127675Sbms if (afi == IPV6) 1651127675Sbms printf("%sIPv6 prefix: %s/%u", 1652127675Sbms ident, 1653127675Sbms ip6addr_string(prefix), 1654127675Sbms bit_length); 1655127675Sbms#endif 1656127675Sbms 1657127675Sbms printf(", Distribution: %s, Metric: %u", 1658127675Sbms ISIS_MASK_TLV_EXTD_IP_UPDOWN(status_byte) ? "down" : "up", 1659127675Sbms metric); 1660127675Sbms 1661127675Sbms if (afi == IPV4 && ISIS_MASK_TLV_EXTD_IP_SUBTLV(status_byte)) 1662127675Sbms printf(", sub-TLVs present"); 1663127675Sbms#ifdef INET6 1664127675Sbms if (afi == IPV6) 1665127675Sbms printf(", %s%s", 1666127675Sbms ISIS_MASK_TLV_EXTD_IP6_IE(status_byte) ? "External" : "Internal", 1667127675Sbms ISIS_MASK_TLV_EXTD_IP6_SUBTLV(status_byte) ? ", sub-TLVs present" : ""); 1668127675Sbms#endif 1669127675Sbms 1670127675Sbms if ((ISIS_MASK_TLV_EXTD_IP_SUBTLV(status_byte) && afi == IPV4) || 1671127675Sbms (ISIS_MASK_TLV_EXTD_IP6_SUBTLV(status_byte) && afi == IPV6)) { 1672127675Sbms /* assume that one prefix can hold more 1673127675Sbms than one subTLV - therefore the first byte must reflect 1674127675Sbms the aggregate bytecount of the subTLVs for this prefix 1675127675Sbms */ 1676127675Sbms if (!TTEST2(*tptr, 1)) 1677127675Sbms return (0); 1678127675Sbms sublen=*(tptr++); 1679127675Sbms processed+=sublen+1; 1680127675Sbms printf(" (%u)",sublen); /* print out subTLV length */ 1681127675Sbms 1682127675Sbms while (sublen>0) { 1683127675Sbms if (!TTEST2(*tptr,2)) 1684127675Sbms return (0); 1685127675Sbms subtlvtype=*(tptr++); 1686127675Sbms subtlvlen=*(tptr++); 1687127675Sbms /* prepend the ident string */ 1688127675Sbms snprintf(ident_buffer, sizeof(ident_buffer), "%s ",ident); 1689127675Sbms if(!isis_print_ip_reach_subtlv(tptr,subtlvtype,subtlvlen,ident_buffer)) 1690127675Sbms return(0); 1691127675Sbms tptr+=subtlvlen; 1692127675Sbms sublen-=(subtlvlen+2); 1693127675Sbms } 1694127675Sbms } 1695127675Sbms return (processed); 1696127675Sbms} 1697127675Sbms 1698127675Sbms/* 169917688Spst * isis_print 170017688Spst * Decode IS-IS packets. Return 0 on error. 170117688Spst */ 170217688Spst 1703127675Sbmsstatic int isis_print (const u_int8_t *p, u_int length) 170417688Spst{ 1705146778Ssam const struct isis_common_header *isis_header; 170617688Spst 170798527Sfenner const struct isis_iih_lan_header *header_iih_lan; 170898527Sfenner const struct isis_iih_ptp_header *header_iih_ptp; 170998527Sfenner const struct isis_lsp_header *header_lsp; 171098527Sfenner const struct isis_csnp_header *header_csnp; 171198527Sfenner const struct isis_psnp_header *header_psnp; 171217688Spst 171398527Sfenner const struct isis_tlv_lsp *tlv_lsp; 171498527Sfenner const struct isis_tlv_ptp_adj *tlv_ptp_adj; 171598527Sfenner const struct isis_tlv_is_reach *tlv_is_reach; 1716127675Sbms const struct isis_tlv_es_reach *tlv_es_reach; 171798527Sfenner 1718127675Sbms u_int8_t pdu_type, max_area, id_length, tlv_type, tlv_len, tmp, alen, lan_alen, prefix_len; 1719127675Sbms u_int8_t ext_is_len, ext_ip_len, mt_len; 1720127675Sbms const u_int8_t *optr, *pptr, *tptr; 172198527Sfenner u_short packet_len,pdu_len; 1722146778Ssam u_int i,vendor_id; 172398527Sfenner 172498527Sfenner packet_len=length; 1725127675Sbms optr = p; /* initialize the _o_riginal pointer to the packet start - 1726127675Sbms need it for parsing the checksum TLV */ 1727146778Ssam isis_header = (const struct isis_common_header *)p; 1728146778Ssam TCHECK(*isis_header); 1729127675Sbms pptr = p+(ISIS_COMMON_HEADER_SIZE); 173098527Sfenner header_iih_lan = (const struct isis_iih_lan_header *)pptr; 173198527Sfenner header_iih_ptp = (const struct isis_iih_ptp_header *)pptr; 173298527Sfenner header_lsp = (const struct isis_lsp_header *)pptr; 173398527Sfenner header_csnp = (const struct isis_csnp_header *)pptr; 173498527Sfenner header_psnp = (const struct isis_psnp_header *)pptr; 1735127675Sbms 1736146778Ssam if (!eflag) 1737146778Ssam printf("IS-IS"); 1738146778Ssam 173917688Spst /* 174017688Spst * Sanity checking of the header. 174117688Spst */ 174217688Spst 1743146778Ssam if (isis_header->version != ISIS_VERSION) { 1744146778Ssam printf("version %d packet not supported", isis_header->version); 174598527Sfenner return (0); 174617688Spst } 174717688Spst 1748146778Ssam if ((isis_header->id_length != SYSTEM_ID_LEN) && (isis_header->id_length != 0)) { 1749146778Ssam printf("system ID length of %d is not supported", 1750146778Ssam isis_header->id_length); 175198527Sfenner return (0); 175217688Spst } 1753127675Sbms 1754146778Ssam if (isis_header->pdu_version != ISIS_VERSION) { 1755146778Ssam printf("version %d packet not supported", isis_header->pdu_version); 175698527Sfenner return (0); 175717688Spst } 175817688Spst 1759146778Ssam max_area = isis_header->max_area; 176017688Spst switch(max_area) { 176117688Spst case 0: 1762127675Sbms max_area = 3; /* silly shit */ 176317688Spst break; 176417688Spst case 255: 1765146778Ssam printf("bad packet -- 255 areas"); 176698527Sfenner return (0); 176717688Spst default: 176817688Spst break; 176917688Spst } 177017688Spst 1771146778Ssam id_length = isis_header->id_length; 1772127675Sbms switch(id_length) { 1773127675Sbms case 0: 1774127675Sbms id_length = 6; /* silly shit again */ 1775127675Sbms break; 1776127675Sbms case 1: /* 1-8 are valid sys-ID lenghts */ 1777127675Sbms case 2: 1778127675Sbms case 3: 1779127675Sbms case 4: 1780127675Sbms case 5: 1781127675Sbms case 6: 1782127675Sbms case 7: 1783127675Sbms case 8: 1784127675Sbms break; 1785127675Sbms case 255: 1786127675Sbms id_length = 0; /* entirely useless */ 1787127675Sbms break; 1788127675Sbms default: 1789127675Sbms break; 1790127675Sbms } 1791127675Sbms 1792127675Sbms /* toss any non 6-byte sys-ID len PDUs */ 1793127675Sbms if (id_length != 6 ) { 1794146778Ssam printf("bad packet -- illegal sys-ID length (%u)", id_length); 1795127675Sbms return (0); 1796127675Sbms } 1797127675Sbms 1798146778Ssam pdu_type=isis_header->pdu_type; 1799127675Sbms 1800127675Sbms /* in non-verbose mode print the basic PDU Type plus PDU specific brief information*/ 1801127675Sbms if (vflag < 1) { 1802146778Ssam printf("%s%s", 1803146778Ssam eflag ? "" : ", ", 1804127675Sbms tok2str(isis_pdu_values,"unknown PDU-Type %u",pdu_type)); 1805127675Sbms 1806127675Sbms switch (pdu_type) { 1807127675Sbms 1808146778Ssam case ISIS_PDU_L1_LAN_IIH: 1809146778Ssam case ISIS_PDU_L2_LAN_IIH: 1810127675Sbms printf(", src-id %s", 1811127675Sbms isis_print_id(header_iih_lan->source_id,SYSTEM_ID_LEN)); 1812127675Sbms printf(", lan-id %s, prio %u", 1813127675Sbms isis_print_id(header_iih_lan->lan_id,NODE_ID_LEN), 1814127675Sbms header_iih_lan->priority); 1815127675Sbms break; 1816146778Ssam case ISIS_PDU_PTP_IIH: 1817127675Sbms printf(", src-id %s", isis_print_id(header_iih_ptp->source_id,SYSTEM_ID_LEN)); 1818127675Sbms break; 1819146778Ssam case ISIS_PDU_L1_LSP: 1820146778Ssam case ISIS_PDU_L2_LSP: 1821127675Sbms printf(", lsp-id %s, seq 0x%08x, lifetime %5us", 1822127675Sbms isis_print_id(header_lsp->lsp_id, LSP_ID_LEN), 1823127675Sbms EXTRACT_32BITS(header_lsp->sequence_number), 1824127675Sbms EXTRACT_16BITS(header_lsp->remaining_lifetime)); 1825127675Sbms break; 1826146778Ssam case ISIS_PDU_L1_CSNP: 1827146778Ssam case ISIS_PDU_L2_CSNP: 1828146778Ssam printf(", src-id %s", isis_print_id(header_csnp->source_id,NODE_ID_LEN)); 1829127675Sbms break; 1830146778Ssam case ISIS_PDU_L1_PSNP: 1831146778Ssam case ISIS_PDU_L2_PSNP: 1832146778Ssam printf(", src-id %s", isis_print_id(header_psnp->source_id,NODE_ID_LEN)); 1833127675Sbms break; 1834127675Sbms 1835127675Sbms } 1836127675Sbms printf(", length %u", length); 1837127675Sbms 1838127675Sbms return(1); 1839127675Sbms } 1840127675Sbms 1841127675Sbms /* ok they seem to want to know everything - lets fully decode it */ 1842146778Ssam printf("%slength %u", eflag ? "" : ", ",length); 1843127675Sbms 1844127675Sbms printf("\n\t%s, hlen: %u, v: %u, pdu-v: %u, sys-id-len: %u (%u), max-area: %u (%u)", 1845127675Sbms tok2str(isis_pdu_values, 1846127675Sbms "unknown, type %u", 1847127675Sbms pdu_type), 1848146778Ssam isis_header->fixed_len, 1849146778Ssam isis_header->version, 1850146778Ssam isis_header->pdu_version, 1851127675Sbms id_length, 1852146778Ssam isis_header->id_length, 185398527Sfenner max_area, 1854146778Ssam isis_header->max_area); 1855127675Sbms 1856127675Sbms if (vflag > 1) { 1857127675Sbms if(!print_unknown_data(optr,"\n\t",8)) /* provide the _o_riginal pointer */ 1858127675Sbms return(0); /* for optionally debugging the common header */ 1859127675Sbms } 1860127675Sbms 186198527Sfenner switch (pdu_type) { 186298527Sfenner 1863146778Ssam case ISIS_PDU_L1_LAN_IIH: 1864146778Ssam case ISIS_PDU_L2_LAN_IIH: 1865146778Ssam if (isis_header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE)) { 186698527Sfenner printf(", bogus fixed header length %u should be %lu", 1867146778Ssam isis_header->fixed_len, (unsigned long)ISIS_IIH_LAN_HEADER_SIZE); 186898527Sfenner return (0); 186917688Spst } 187098527Sfenner 187198527Sfenner pdu_len=EXTRACT_16BITS(header_iih_lan->pdu_len); 187298527Sfenner if (packet_len>pdu_len) { 1873127675Sbms packet_len=pdu_len; /* do TLV decoding as long as it makes sense */ 1874127675Sbms length=pdu_len; 187598527Sfenner } 187698527Sfenner 187798527Sfenner TCHECK(*header_iih_lan); 1878127675Sbms printf("\n\t source-id: %s, holding time: %us, Flags: [%s]", 1879127675Sbms isis_print_id(header_iih_lan->source_id,SYSTEM_ID_LEN), 1880127675Sbms EXTRACT_16BITS(header_iih_lan->holding_time), 1881127675Sbms tok2str(isis_iih_circuit_type_values, 1882127675Sbms "unknown circuit type 0x%02x", 1883127675Sbms header_iih_lan->circuit_type)); 188498527Sfenner 1885127675Sbms printf("\n\t lan-id: %s, Priority: %u, PDU length: %u", 1886127675Sbms isis_print_id(header_iih_lan->lan_id, NODE_ID_LEN), 1887146778Ssam (header_iih_lan->priority) & ISIS_LAN_PRIORITY_MASK, 1888127675Sbms pdu_len); 188998527Sfenner 1890127675Sbms if (vflag > 1) { 1891127675Sbms if(!print_unknown_data(pptr,"\n\t ",ISIS_IIH_LAN_HEADER_SIZE)) 1892127675Sbms return(0); 1893127675Sbms } 189498527Sfenner 189598527Sfenner packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE); 189698527Sfenner pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE); 189717688Spst break; 189898527Sfenner 1899146778Ssam case ISIS_PDU_PTP_IIH: 1900146778Ssam if (isis_header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE)) { 190198527Sfenner printf(", bogus fixed header length %u should be %lu", 1902146778Ssam isis_header->fixed_len, (unsigned long)ISIS_IIH_PTP_HEADER_SIZE); 190398527Sfenner return (0); 190417688Spst } 1905127675Sbms 190698527Sfenner pdu_len=EXTRACT_16BITS(header_iih_ptp->pdu_len); 190798527Sfenner if (packet_len>pdu_len) { 1908127675Sbms packet_len=pdu_len; /* do TLV decoding as long as it makes sense */ 1909127675Sbms length=pdu_len; 191098527Sfenner } 1911127675Sbms 191298527Sfenner TCHECK(*header_iih_ptp); 1913127675Sbms printf("\n\t source-id: %s, holding time: %us, Flags: [%s]", 1914127675Sbms isis_print_id(header_iih_ptp->source_id,SYSTEM_ID_LEN), 1915127675Sbms EXTRACT_16BITS(header_iih_ptp->holding_time), 1916127675Sbms tok2str(isis_iih_circuit_type_values, 1917127675Sbms "unknown circuit type 0x%02x", 1918127675Sbms header_iih_ptp->circuit_type)); 191998527Sfenner 1920127675Sbms printf("\n\t circuit-id: 0x%02x, PDU length: %u", 1921127675Sbms header_iih_ptp->circuit_id, 1922127675Sbms pdu_len); 192398527Sfenner 1924127675Sbms if (vflag > 1) { 1925127675Sbms if(!print_unknown_data(pptr,"\n\t ",ISIS_IIH_PTP_HEADER_SIZE)) 1926127675Sbms return(0); 1927127675Sbms } 192898527Sfenner 192998527Sfenner packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE); 193098527Sfenner pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE); 193117688Spst break; 193298527Sfenner 1933146778Ssam case ISIS_PDU_L1_LSP: 1934146778Ssam case ISIS_PDU_L2_LSP: 1935146778Ssam if (isis_header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE)) { 193698527Sfenner printf(", bogus fixed header length %u should be %lu", 1937146778Ssam isis_header->fixed_len, (unsigned long)ISIS_LSP_HEADER_SIZE); 193898527Sfenner return (0); 193998527Sfenner } 1940127675Sbms 194198527Sfenner pdu_len=EXTRACT_16BITS(header_lsp->pdu_len); 194298527Sfenner if (packet_len>pdu_len) { 1943127675Sbms packet_len=pdu_len; /* do TLV decoding as long as it makes sense */ 1944127675Sbms length=pdu_len; 194598527Sfenner } 194698527Sfenner 194798527Sfenner TCHECK(*header_lsp); 1948127675Sbms printf("\n\t lsp-id: %s, seq: 0x%08x, lifetime: %5us\n\t chksum: 0x%04x", 1949127675Sbms isis_print_id(header_lsp->lsp_id, LSP_ID_LEN), 1950127675Sbms EXTRACT_32BITS(header_lsp->sequence_number), 1951127675Sbms EXTRACT_16BITS(header_lsp->remaining_lifetime), 1952127675Sbms EXTRACT_16BITS(header_lsp->checksum)); 195398527Sfenner 1954127675Sbms /* if this is a purge do not attempt to verify the checksum */ 1955127675Sbms if ( EXTRACT_16BITS(header_lsp->remaining_lifetime) == 0 && 1956127675Sbms EXTRACT_16BITS(header_lsp->checksum) == 0) 1957127675Sbms printf(" (purged)"); 1958127675Sbms else 1959127675Sbms /* verify the checksum - 1960127675Sbms * checking starts at the lsp-id field at byte position [12] 1961127675Sbms * hence the length needs to be reduced by 12 bytes */ 1962127675Sbms printf(" (%s)", (osi_cksum((u_int8_t *)header_lsp->lsp_id, length-12)) ? "incorrect" : "correct"); 1963127675Sbms 1964127675Sbms printf(", PDU length: %u, Flags: [ %s", 1965127675Sbms pdu_len, 1966127675Sbms ISIS_MASK_LSP_OL_BIT(header_lsp->typeblock) ? "Overload bit set, " : ""); 1967127675Sbms 196898527Sfenner if (ISIS_MASK_LSP_ATT_BITS(header_lsp->typeblock)) { 196998527Sfenner printf("%s", ISIS_MASK_LSP_ATT_DEFAULT_BIT(header_lsp->typeblock) ? "default " : ""); 197098527Sfenner printf("%s", ISIS_MASK_LSP_ATT_DELAY_BIT(header_lsp->typeblock) ? "delay " : ""); 197198527Sfenner printf("%s", ISIS_MASK_LSP_ATT_EXPENSE_BIT(header_lsp->typeblock) ? "expense " : ""); 197298527Sfenner printf("%s", ISIS_MASK_LSP_ATT_ERROR_BIT(header_lsp->typeblock) ? "error " : ""); 197398527Sfenner printf("ATT bit set, "); 197498527Sfenner } 197598527Sfenner printf("%s", ISIS_MASK_LSP_PARTITION_BIT(header_lsp->typeblock) ? "P bit set, " : ""); 1976127675Sbms printf("%s ]", tok2str(isis_lsp_istype_values,"Unknown(0x%x)",ISIS_MASK_LSP_ISTYPE_BITS(header_lsp->typeblock))); 197798527Sfenner 1978127675Sbms if (vflag > 1) { 1979127675Sbms if(!print_unknown_data(pptr,"\n\t ",ISIS_LSP_HEADER_SIZE)) 1980127675Sbms return(0); 1981127675Sbms } 1982127675Sbms 198398527Sfenner packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE); 198498527Sfenner pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE); 198517688Spst break; 198698527Sfenner 1987146778Ssam case ISIS_PDU_L1_CSNP: 1988146778Ssam case ISIS_PDU_L2_CSNP: 1989146778Ssam if (isis_header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE)) { 199098527Sfenner printf(", bogus fixed header length %u should be %lu", 1991146778Ssam isis_header->fixed_len, (unsigned long)ISIS_CSNP_HEADER_SIZE); 199298527Sfenner return (0); 199398527Sfenner } 1994127675Sbms 199598527Sfenner pdu_len=EXTRACT_16BITS(header_csnp->pdu_len); 199698527Sfenner if (packet_len>pdu_len) { 1997127675Sbms packet_len=pdu_len; /* do TLV decoding as long as it makes sense */ 1998127675Sbms length=pdu_len; 199998527Sfenner } 200017688Spst 200198527Sfenner TCHECK(*header_csnp); 2002127675Sbms printf("\n\t source-id: %s, PDU length: %u", 2003127675Sbms isis_print_id(header_csnp->source_id, NODE_ID_LEN), 2004127675Sbms pdu_len); 2005127675Sbms printf("\n\t start lsp-id: %s", 2006127675Sbms isis_print_id(header_csnp->start_lsp_id, LSP_ID_LEN)); 2007127675Sbms printf("\n\t end lsp-id: %s", 2008127675Sbms isis_print_id(header_csnp->end_lsp_id, LSP_ID_LEN)); 200917688Spst 2010127675Sbms if (vflag > 1) { 2011127675Sbms if(!print_unknown_data(pptr,"\n\t ",ISIS_CSNP_HEADER_SIZE)) 2012127675Sbms return(0); 2013127675Sbms } 2014127675Sbms 201598527Sfenner packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE); 201698527Sfenner pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE); 201798527Sfenner break; 201817688Spst 2019146778Ssam case ISIS_PDU_L1_PSNP: 2020146778Ssam case ISIS_PDU_L2_PSNP: 2021146778Ssam if (isis_header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE)) { 202298527Sfenner printf("- bogus fixed header length %u should be %lu", 2023146778Ssam isis_header->fixed_len, (unsigned long)ISIS_PSNP_HEADER_SIZE); 202498527Sfenner return (0); 202598527Sfenner } 202698527Sfenner 202798527Sfenner pdu_len=EXTRACT_16BITS(header_psnp->pdu_len); 202898527Sfenner if (packet_len>pdu_len) { 2029127675Sbms packet_len=pdu_len; /* do TLV decoding as long as it makes sense */ 2030127675Sbms length=pdu_len; 203198527Sfenner } 203298527Sfenner 203398527Sfenner TCHECK(*header_psnp); 2034127675Sbms printf("\n\t source-id: %s, PDU length: %u", 2035127675Sbms isis_print_id(header_psnp->source_id, NODE_ID_LEN), 2036127675Sbms pdu_len); 2037127675Sbms 2038127675Sbms if (vflag > 1) { 2039127675Sbms if(!print_unknown_data(pptr,"\n\t ",ISIS_PSNP_HEADER_SIZE)) 2040127675Sbms return(0); 2041127675Sbms } 2042127675Sbms 204398527Sfenner packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE); 204498527Sfenner pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE); 204517688Spst break; 204617688Spst 204798527Sfenner default: 2048127675Sbms if(!print_unknown_data(pptr,"\n\t ",length)) 2049127675Sbms return(0); 2050127675Sbms return (0); 205117688Spst } 205217688Spst 205317688Spst /* 205417688Spst * Now print the TLV's. 205517688Spst */ 2056127675Sbms 205717688Spst while (packet_len >= 2) { 205898527Sfenner if (pptr == snapend) { 205998527Sfenner return (1); 206098527Sfenner } 206198527Sfenner 206298527Sfenner if (!TTEST2(*pptr, 2)) { 2063127675Sbms printf("\n\t\t packet exceeded snapshot (%ld) bytes", 2064127675Sbms (long)(pptr-snapend)); 206598527Sfenner return (1); 206617688Spst } 2067127675Sbms tlv_type = *pptr++; 2068127675Sbms tlv_len = *pptr++; 2069127675Sbms tmp =tlv_len; /* copy temporary len & pointer to packet data */ 2070127675Sbms tptr = pptr; 207117688Spst packet_len -= 2; 2072127675Sbms if (tlv_len > packet_len) { 207317688Spst break; 207417688Spst } 207517688Spst 2076127675Sbms /* first lets see if we know the TLVs name*/ 2077127675Sbms printf("\n\t %s TLV #%u, length: %u", 2078127675Sbms tok2str(isis_tlv_values, 2079127675Sbms "unknown", 2080127675Sbms tlv_type), 2081127675Sbms tlv_type, 2082127675Sbms tlv_len); 2083127675Sbms 2084147175Ssam if (tlv_len == 0) /* something is malformed */ 2085147175Ssam break; 2086147175Ssam 2087127675Sbms /* now check if we have a decoder otherwise do a hexdump at the end*/ 2088127675Sbms switch (tlv_type) { 2089146778Ssam case ISIS_TLV_AREA_ADDR: 209098527Sfenner if (!TTEST2(*tptr, 1)) 209198527Sfenner goto trunctlv; 209217688Spst alen = *tptr++; 209317688Spst while (tmp && alen < tmp) { 2094127675Sbms printf("\n\t Area address (length: %u): %s", 2095127675Sbms alen, 2096146778Ssam isonsap_string(tptr,alen)); 209717688Spst tptr += alen; 209817688Spst tmp -= alen + 1; 209998527Sfenner if (tmp==0) /* if this is the last area address do not attemt a boundary check */ 2100127675Sbms break; 210198527Sfenner if (!TTEST2(*tptr, 1)) 210298527Sfenner goto trunctlv; 210317688Spst alen = *tptr++; 210417688Spst } 210517688Spst break; 2106146778Ssam case ISIS_TLV_ISNEIGH: 210775118Sfenner while (tmp >= ETHER_ADDR_LEN) { 2108127675Sbms if (!TTEST2(*tptr, ETHER_ADDR_LEN)) 2109127675Sbms goto trunctlv; 2110127675Sbms printf("\n\t SNPA: %s",isis_print_id(tptr,ETHER_ADDR_LEN)); 2111127675Sbms tmp -= ETHER_ADDR_LEN; 2112127675Sbms tptr += ETHER_ADDR_LEN; 211317688Spst } 211417688Spst break; 211598527Sfenner 2116146778Ssam case ISIS_TLV_ISNEIGH_VARLEN: 2117147175Ssam if (!TTEST2(*tptr, 1) || tmp < 3) /* min. TLV length */ 2118127675Sbms goto trunctlv; 2119147904Ssam lan_alen = *tptr++; /* LAN address length */ 2120147904Ssam if (lan_alen == 0) { 2121147904Ssam printf("\n\t LAN address length 0 bytes (invalid)"); 2122147904Ssam break; 2123147904Ssam } 2124127675Sbms tmp --; 2125127675Sbms printf("\n\t LAN address length %u bytes ",lan_alen); 2126127675Sbms while (tmp >= lan_alen) { 2127127675Sbms if (!TTEST2(*tptr, lan_alen)) 2128127675Sbms goto trunctlv; 2129127675Sbms printf("\n\t\tIS Neighbor: %s",isis_print_id(tptr,lan_alen)); 2130127675Sbms tmp -= lan_alen; 2131127675Sbms tptr +=lan_alen; 2132127675Sbms } 2133127675Sbms break; 2134127675Sbms 2135146778Ssam case ISIS_TLV_PADDING: 213617688Spst break; 213798527Sfenner 2138146778Ssam case ISIS_TLV_MT_IS_REACH: 2139127675Sbms while (tmp >= 2+NODE_ID_LEN+3+1) { 2140127675Sbms mt_len = isis_print_mtid(tptr, "\n\t "); 2141127675Sbms if (mt_len == 0) /* did something go wrong ? */ 2142127675Sbms goto trunctlv; 2143127675Sbms tptr+=mt_len; 2144127675Sbms tmp-=mt_len; 214598527Sfenner 2146127675Sbms ext_is_len = isis_print_ext_is_reach(tptr,"\n\t ",tlv_type); 2147127675Sbms if (ext_is_len == 0) /* did something go wrong ? */ 214898527Sfenner goto trunctlv; 2149127675Sbms 2150127675Sbms tmp-=ext_is_len; 2151127675Sbms tptr+=ext_is_len; 215298527Sfenner } 215398527Sfenner break; 215498527Sfenner 2155146778Ssam case ISIS_TLV_IS_ALIAS_ID: 2156127675Sbms while (tmp >= NODE_ID_LEN+1) { /* is it worth attempting a decode ? */ 2157127675Sbms ext_is_len = isis_print_ext_is_reach(tptr,"\n\t ",tlv_type); 2158127675Sbms if (ext_is_len == 0) /* did something go wrong ? */ 2159127675Sbms goto trunctlv; 2160127675Sbms tmp-=ext_is_len; 2161127675Sbms tptr+=ext_is_len; 2162127675Sbms } 2163127675Sbms break; 2164127675Sbms 2165146778Ssam case ISIS_TLV_EXT_IS_REACH: 2166127675Sbms while (tmp >= NODE_ID_LEN+3+1) { /* is it worth attempting a decode ? */ 2167127675Sbms ext_is_len = isis_print_ext_is_reach(tptr,"\n\t ",tlv_type); 2168127675Sbms if (ext_is_len == 0) /* did something go wrong ? */ 2169127675Sbms goto trunctlv; 2170127675Sbms tmp-=ext_is_len; 2171127675Sbms tptr+=ext_is_len; 217298527Sfenner } 217398527Sfenner break; 2174146778Ssam case ISIS_TLV_IS_REACH: 217598527Sfenner if (!TTEST2(*tptr,1)) /* check if there is one byte left to read out the virtual flag */ 2176127675Sbms goto trunctlv; 2177127675Sbms printf("\n\t %s", 2178127675Sbms tok2str(isis_is_reach_virtual_values, 2179127675Sbms "bogus virtual flag 0x%02x", 2180127675Sbms *tptr++)); 218198527Sfenner tlv_is_reach = (const struct isis_tlv_is_reach *)tptr; 218298527Sfenner while (tmp >= sizeof(struct isis_tlv_is_reach)) { 218398527Sfenner if (!TTEST(*tlv_is_reach)) 218498527Sfenner goto trunctlv; 2185127675Sbms printf("\n\t IS Neighbor: %s", 2186127675Sbms isis_print_id(tlv_is_reach->neighbor_nodeid, NODE_ID_LEN)); 2187127675Sbms isis_print_metric_block(&tlv_is_reach->isis_metric_block); 218898527Sfenner tmp -= sizeof(struct isis_tlv_is_reach); 218998527Sfenner tlv_is_reach++; 219098527Sfenner } 219198527Sfenner break; 219298527Sfenner 2193146778Ssam case ISIS_TLV_ESNEIGH: 2194127675Sbms tlv_es_reach = (const struct isis_tlv_es_reach *)tptr; 2195127675Sbms while (tmp >= sizeof(struct isis_tlv_es_reach)) { 2196127675Sbms if (!TTEST(*tlv_es_reach)) 2197127675Sbms goto trunctlv; 2198127675Sbms printf("\n\t ES Neighbor: %s", 2199127675Sbms isis_print_id(tlv_es_reach->neighbor_sysid,SYSTEM_ID_LEN)); 2200127675Sbms isis_print_metric_block(&tlv_es_reach->isis_metric_block); 2201127675Sbms tmp -= sizeof(struct isis_tlv_es_reach); 2202127675Sbms tlv_es_reach++; 2203127675Sbms } 2204127675Sbms break; 2205127675Sbms 2206127675Sbms /* those two TLVs share the same format */ 2207146778Ssam case ISIS_TLV_INT_IP_REACH: 2208146778Ssam case ISIS_TLV_EXT_IP_REACH: 2209127675Sbms if (!isis_print_tlv_ip_reach(pptr, "\n\t ", tlv_len)) 221098527Sfenner return (1); 221117688Spst break; 221298527Sfenner 2213146778Ssam case ISIS_TLV_EXTD_IP_REACH: 2214127675Sbms while (tmp>0) { 2215127675Sbms ext_ip_len = isis_print_extd_ip_reach(tptr, "\n\t ", IPV4); 2216127675Sbms if (ext_ip_len == 0) /* did something go wrong ? */ 2217127675Sbms goto trunctlv; 2218127675Sbms tptr+=ext_ip_len; 2219127675Sbms tmp-=ext_ip_len; 2220127675Sbms } 222198527Sfenner break; 222298527Sfenner 2223146778Ssam case ISIS_TLV_MT_IP_REACH: 2224127675Sbms while (tmp>0) { 2225127675Sbms mt_len = isis_print_mtid(tptr, "\n\t "); 2226127675Sbms if (mt_len == 0) /* did something go wrong ? */ 2227127675Sbms goto trunctlv; 2228127675Sbms tptr+=mt_len; 2229127675Sbms tmp-=mt_len; 223098527Sfenner 2231127675Sbms ext_ip_len = isis_print_extd_ip_reach(tptr, "\n\t ", IPV4); 2232127675Sbms if (ext_ip_len == 0) /* did something go wrong ? */ 2233127675Sbms goto trunctlv; 2234127675Sbms tptr+=ext_ip_len; 2235127675Sbms tmp-=ext_ip_len; 223698527Sfenner } 223798527Sfenner break; 223898527Sfenner 223998527Sfenner#ifdef INET6 2240146778Ssam case ISIS_TLV_IP6_REACH: 2241127675Sbms while (tmp>0) { 2242127675Sbms ext_ip_len = isis_print_extd_ip_reach(tptr, "\n\t ", IPV6); 2243127675Sbms if (ext_ip_len == 0) /* did something go wrong ? */ 2244127675Sbms goto trunctlv; 2245127675Sbms tptr+=ext_ip_len; 2246127675Sbms tmp-=ext_ip_len; 2247127675Sbms } 2248127675Sbms break; 224998527Sfenner 2250146778Ssam case ISIS_TLV_MT_IP6_REACH: 2251127675Sbms while (tmp>0) { 2252127675Sbms mt_len = isis_print_mtid(tptr, "\n\t "); 2253127675Sbms if (mt_len == 0) /* did something go wrong ? */ 2254127675Sbms goto trunctlv; 2255127675Sbms tptr+=mt_len; 2256127675Sbms tmp-=mt_len; 225798527Sfenner 2258127675Sbms ext_ip_len = isis_print_extd_ip_reach(tptr, "\n\t ", IPV6); 2259127675Sbms if (ext_ip_len == 0) /* did something go wrong ? */ 2260127675Sbms goto trunctlv; 2261127675Sbms tptr+=ext_ip_len; 2262127675Sbms tmp-=ext_ip_len; 226398527Sfenner } 226498527Sfenner break; 226598527Sfenner 2266146778Ssam case ISIS_TLV_IP6ADDR: 2267147904Ssam while (tmp>=16) { 226898527Sfenner if (!TTEST2(*tptr, 16)) 226998527Sfenner goto trunctlv; 227098527Sfenner 2271127675Sbms printf("\n\t IPv6 interface address: %s", 227298527Sfenner ip6addr_string(tptr)); 227398527Sfenner 227498527Sfenner tptr += 16; 2275127675Sbms tmp -= 16; 227698527Sfenner } 227798527Sfenner break; 227898527Sfenner#endif 2279146778Ssam case ISIS_TLV_AUTH: 2280127675Sbms if (!TTEST2(*tptr, 1)) 228198527Sfenner goto trunctlv; 2282127675Sbms 2283127675Sbms printf("\n\t %s: ", 2284127675Sbms tok2str(isis_subtlv_auth_values, 2285127675Sbms "unknown Authentication type 0x%02x", 2286127675Sbms *tptr)); 2287127675Sbms 2288127675Sbms switch (*tptr) { 2289146778Ssam case ISIS_SUBTLV_AUTH_SIMPLE: 2290127675Sbms for(i=1;i<tlv_len;i++) { 2291127675Sbms if (!TTEST2(*(tptr+i), 1)) 229298527Sfenner goto trunctlv; 2293127675Sbms printf("%c",*(tptr+i)); 229498527Sfenner } 2295127675Sbms break; 2296146778Ssam case ISIS_SUBTLV_AUTH_MD5: 2297127675Sbms for(i=1;i<tlv_len;i++) { 2298127675Sbms if (!TTEST2(*(tptr+i), 1)) 229998527Sfenner goto trunctlv; 2300127675Sbms printf("%02x",*(tptr+i)); 230198527Sfenner } 2302146778Ssam if (tlv_len != ISIS_SUBTLV_AUTH_MD5_LEN+1) 2303127675Sbms printf(", (malformed subTLV) "); 2304127675Sbms break; 2305146778Ssam case ISIS_SUBTLV_AUTH_PRIVATE: 2306127675Sbms default: 2307127675Sbms if(!print_unknown_data(tptr+1,"\n\t\t ",tlv_len-1)) 2308127675Sbms return(0); 2309127675Sbms break; 231098527Sfenner } 231198527Sfenner break; 231298527Sfenner 2313146778Ssam case ISIS_TLV_PTP_ADJ: 2314127675Sbms tlv_ptp_adj = (const struct isis_tlv_ptp_adj *)tptr; 2315127675Sbms if(tmp>=1) { 2316127675Sbms if (!TTEST2(*tptr, 1)) 231798527Sfenner goto trunctlv; 2318127675Sbms printf("\n\t Adjacency State: %s (%u)", 2319127675Sbms tok2str(isis_ptp_adjancey_values, "unknown", *tptr), 2320127675Sbms *tptr); 2321127675Sbms tmp--; 232298527Sfenner } 2323127675Sbms if(tmp>sizeof(tlv_ptp_adj->extd_local_circuit_id)) { 2324127675Sbms if (!TTEST2(tlv_ptp_adj->extd_local_circuit_id, 2325127675Sbms sizeof(tlv_ptp_adj->extd_local_circuit_id))) 232698527Sfenner goto trunctlv; 2327127675Sbms printf("\n\t Extended Local circuit-ID: 0x%08x", 2328127675Sbms EXTRACT_32BITS(tlv_ptp_adj->extd_local_circuit_id)); 2329127675Sbms tmp-=sizeof(tlv_ptp_adj->extd_local_circuit_id); 233098527Sfenner } 2331127675Sbms if(tmp>=SYSTEM_ID_LEN) { 2332127675Sbms if (!TTEST2(tlv_ptp_adj->neighbor_sysid, SYSTEM_ID_LEN)) 233398527Sfenner goto trunctlv; 2334127675Sbms printf("\n\t Neighbor System-ID: %s", 2335127675Sbms isis_print_id(tlv_ptp_adj->neighbor_sysid,SYSTEM_ID_LEN)); 2336127675Sbms tmp-=SYSTEM_ID_LEN; 233798527Sfenner } 2338127675Sbms if(tmp>=sizeof(tlv_ptp_adj->neighbor_extd_local_circuit_id)) { 2339127675Sbms if (!TTEST2(tlv_ptp_adj->neighbor_extd_local_circuit_id, 2340127675Sbms sizeof(tlv_ptp_adj->neighbor_extd_local_circuit_id))) 234198527Sfenner goto trunctlv; 2342127675Sbms printf("\n\t Neighbor Extended Local circuit-ID: 0x%08x", 2343127675Sbms EXTRACT_32BITS(tlv_ptp_adj->neighbor_extd_local_circuit_id)); 234498527Sfenner } 234532149Spst break; 234698527Sfenner 2347146778Ssam case ISIS_TLV_PROTOCOLS: 2348127675Sbms printf("\n\t NLPID(s): "); 2349127675Sbms while (tmp>0) { 2350127675Sbms if (!TTEST2(*(tptr), 1)) 235198527Sfenner goto trunctlv; 2352127675Sbms printf("%s (0x%02x)", 2353146778Ssam tok2str(nlpid_values, 2354127675Sbms "unknown", 2355127675Sbms *tptr), 2356127675Sbms *tptr); 2357127675Sbms if (tmp>1) /* further NPLIDs ? - put comma */ 235898527Sfenner printf(", "); 2359127675Sbms tptr++; 2360127675Sbms tmp--; 236198527Sfenner } 236232149Spst break; 236398527Sfenner 2364146778Ssam case ISIS_TLV_TE_ROUTER_ID: 236598527Sfenner if (!TTEST2(*pptr, 4)) 236698527Sfenner goto trunctlv; 2367127675Sbms printf("\n\t Traffic Engineering Router ID: %s", ipaddr_string(pptr)); 236898527Sfenner break; 236998527Sfenner 2370146778Ssam case ISIS_TLV_IPADDR: 2371147904Ssam while (tmp>=4) { 237298527Sfenner if (!TTEST2(*tptr, 4)) 237398527Sfenner goto trunctlv; 2374127675Sbms printf("\n\t IPv4 interface address: %s", ipaddr_string(tptr)); 237598527Sfenner tptr += 4; 2376127675Sbms tmp -= 4; 237798527Sfenner } 237832149Spst break; 237998527Sfenner 2380146778Ssam case ISIS_TLV_HOSTNAME: 2381127675Sbms printf("\n\t Hostname: "); 2382127675Sbms while (tmp>0) { 2383127675Sbms if (!TTEST2(*tptr, 1)) 238498527Sfenner goto trunctlv; 2385127675Sbms printf("%c",*tptr++); 2386127675Sbms tmp--; 238798527Sfenner } 238898527Sfenner break; 238998527Sfenner 2390146778Ssam case ISIS_TLV_SHARED_RISK_GROUP: 2391147904Ssam if (tmp < NODE_ID_LEN) 2392147904Ssam break; 2393127675Sbms if (!TTEST2(*tptr, NODE_ID_LEN)) 2394127675Sbms goto trunctlv; 2395127675Sbms printf("\n\t IS Neighbor: %s", isis_print_id(tptr, NODE_ID_LEN)); 2396127675Sbms tptr+=(NODE_ID_LEN); 2397127675Sbms tmp-=(NODE_ID_LEN); 2398127675Sbms 2399147904Ssam if (tmp < 1) 2400147904Ssam break; 2401127675Sbms if (!TTEST2(*tptr, 1)) 2402127675Sbms goto trunctlv; 2403127675Sbms printf(", Flags: [%s]", ISIS_MASK_TLV_SHARED_RISK_GROUP(*tptr++) ? "numbered" : "unnumbered"); 2404127675Sbms tmp--; 2405127675Sbms 2406147904Ssam if (tmp < 4) 2407147904Ssam break; 2408127675Sbms if (!TTEST2(*tptr,4)) 2409127675Sbms goto trunctlv; 2410127675Sbms printf("\n\t IPv4 interface address: %s", ipaddr_string(tptr)); 2411127675Sbms tptr+=4; 2412127675Sbms tmp-=4; 2413127675Sbms 2414147904Ssam if (tmp < 4) 2415147904Ssam break; 2416127675Sbms if (!TTEST2(*tptr,4)) 2417127675Sbms goto trunctlv; 2418127675Sbms printf("\n\t IPv4 neighbor address: %s", ipaddr_string(tptr)); 2419127675Sbms tptr+=4; 2420127675Sbms tmp-=4; 2421127675Sbms 2422147904Ssam while (tmp>=4) { 2423127675Sbms if (!TTEST2(*tptr, 4)) 2424127675Sbms goto trunctlv; 2425127675Sbms printf("\n\t Link-ID: 0x%08x", EXTRACT_32BITS(tptr)); 2426127675Sbms tptr+=4; 2427127675Sbms tmp-=4; 2428127675Sbms } 2429127675Sbms break; 2430127675Sbms 2431146778Ssam case ISIS_TLV_LSP: 2432127675Sbms tlv_lsp = (const struct isis_tlv_lsp *)tptr; 2433147904Ssam while(tmp>=sizeof(struct isis_tlv_lsp)) { 2434127675Sbms if (!TTEST((tlv_lsp->lsp_id)[LSP_ID_LEN-1])) 243598527Sfenner goto trunctlv; 2436127675Sbms printf("\n\t lsp-id: %s", 2437127675Sbms isis_print_id(tlv_lsp->lsp_id, LSP_ID_LEN)); 243898527Sfenner if (!TTEST2(tlv_lsp->sequence_number, 4)) 243998527Sfenner goto trunctlv; 2440127675Sbms printf(", seq: 0x%08x",EXTRACT_32BITS(tlv_lsp->sequence_number)); 244198527Sfenner if (!TTEST2(tlv_lsp->remaining_lifetime, 2)) 244298527Sfenner goto trunctlv; 2443127675Sbms printf(", lifetime: %5ds",EXTRACT_16BITS(tlv_lsp->remaining_lifetime)); 244498527Sfenner if (!TTEST2(tlv_lsp->checksum, 2)) 244598527Sfenner goto trunctlv; 2446127675Sbms printf(", chksum: 0x%04x",EXTRACT_16BITS(tlv_lsp->checksum)); 2447127675Sbms tmp-=sizeof(struct isis_tlv_lsp); 244898527Sfenner tlv_lsp++; 244998527Sfenner } 245098527Sfenner break; 245198527Sfenner 2452146778Ssam case ISIS_TLV_CHECKSUM: 2453147904Ssam if (tmp < 2) 2454147904Ssam break; 2455127675Sbms if (!TTEST2(*tptr, 2)) 245698527Sfenner goto trunctlv; 2457127675Sbms printf("\n\t checksum: 0x%04x ", EXTRACT_16BITS(tptr)); 2458127675Sbms /* do not attempt to verify the checksum if it is zero 2459127675Sbms * most likely a HMAC-MD5 TLV is also present and 2460127675Sbms * to avoid conflicts the checksum TLV is zeroed. 2461127675Sbms * see rfc3358 for details 2462127675Sbms */ 2463127675Sbms if (EXTRACT_16BITS(tptr) == 0) 2464127675Sbms printf("(unverified)"); 2465127675Sbms else printf("(%s)", osi_cksum(optr, length) ? "incorrect" : "correct"); 246698527Sfenner break; 246798527Sfenner 2468146778Ssam case ISIS_TLV_MT_SUPPORTED: 2469127675Sbms while (tmp>1) { 2470127675Sbms /* length can only be a multiple of 2, otherwise there is 247198527Sfenner something broken -> so decode down until length is 1 */ 2472127675Sbms if (tmp!=1) { 2473127675Sbms mt_len = isis_print_mtid(tptr, "\n\t "); 2474127675Sbms if (mt_len == 0) /* did something go wrong ? */ 2475127675Sbms goto trunctlv; 2476127675Sbms tptr+=mt_len; 2477127675Sbms tmp-=mt_len; 247898527Sfenner } else { 2479127675Sbms printf("\n\t malformed MT-ID"); 248098527Sfenner break; 248198527Sfenner } 248298527Sfenner } 248398527Sfenner break; 248498527Sfenner 2485146778Ssam case ISIS_TLV_RESTART_SIGNALING: 2486147904Ssam if (tmp < 3) 2487147904Ssam break; 2488127675Sbms if (!TTEST2(*tptr, 3)) 2489127675Sbms goto trunctlv; 2490127675Sbms printf("\n\t Flags [%s], Remaining holding time %us", 2491127675Sbms bittok2str(isis_restart_flag_values, "none", *tptr), 2492127675Sbms EXTRACT_16BITS(tptr+1)); 2493127675Sbms tptr+=3; 2494147904Ssam tmp-=3; 2495147904Ssam if (tmp == SYSTEM_ID_LEN) { 2496147904Ssam if (!TTEST2(*tptr, SYSTEM_ID_LEN)) 2497147904Ssam goto trunctlv; 2498147904Ssam printf(", for %s",isis_print_id(tptr,SYSTEM_ID_LEN)); 2499147904Ssam } else if (tmp == NODE_ID_LEN) { 2500147904Ssam if (!TTEST2(*tptr, NODE_ID_LEN)) 2501147904Ssam goto trunctlv; 2502147904Ssam printf(", for %s",isis_print_id(tptr,NODE_ID_LEN)); 2503147904Ssam } 250498527Sfenner break; 250598527Sfenner 2506146778Ssam case ISIS_TLV_IDRP_INFO: 2507147904Ssam if (tmp < 1) 2508147904Ssam break; 2509127675Sbms if (!TTEST2(*tptr, 1)) 2510127675Sbms goto trunctlv; 2511127675Sbms printf("\n\t Inter-Domain Information Type: %s", 2512127675Sbms tok2str(isis_subtlv_idrp_values, 2513127675Sbms "Unknown (0x%02x)", 2514127675Sbms *tptr)); 2515127675Sbms switch (*tptr++) { 2516146778Ssam case ISIS_SUBTLV_IDRP_ASN: 2517127675Sbms if (!TTEST2(*tptr, 2)) /* fetch AS number */ 2518127675Sbms goto trunctlv; 2519127675Sbms printf("AS Number: %u",EXTRACT_16BITS(tptr)); 2520127675Sbms break; 2521146778Ssam case ISIS_SUBTLV_IDRP_LOCAL: 2522146778Ssam case ISIS_SUBTLV_IDRP_RES: 2523127675Sbms default: 2524127675Sbms if(!print_unknown_data(tptr,"\n\t ",tlv_len-1)) 2525127675Sbms return(0); 2526127675Sbms break; 2527127675Sbms } 2528127675Sbms break; 2529127675Sbms 2530146778Ssam case ISIS_TLV_LSP_BUFFERSIZE: 2531147904Ssam if (tmp < 2) 2532147904Ssam break; 2533127675Sbms if (!TTEST2(*tptr, 2)) 2534127675Sbms goto trunctlv; 2535127675Sbms printf("\n\t LSP Buffersize: %u",EXTRACT_16BITS(tptr)); 2536127675Sbms break; 2537127675Sbms 2538146778Ssam case ISIS_TLV_PART_DIS: 2539127675Sbms while (tmp >= SYSTEM_ID_LEN) { 2540127675Sbms if (!TTEST2(*tptr, SYSTEM_ID_LEN)) 2541127675Sbms goto trunctlv; 2542127675Sbms printf("\n\t %s",isis_print_id(tptr,SYSTEM_ID_LEN)); 2543127675Sbms tptr+=SYSTEM_ID_LEN; 2544127675Sbms tmp-=SYSTEM_ID_LEN; 2545127675Sbms } 2546127675Sbms break; 2547127675Sbms 2548146778Ssam case ISIS_TLV_PREFIX_NEIGH: 2549147904Ssam if (tmp < sizeof(struct isis_metric_block)) 2550147904Ssam break; 2551127675Sbms if (!TTEST2(*tptr, sizeof(struct isis_metric_block))) 2552127675Sbms goto trunctlv; 2553127675Sbms printf("\n\t Metric Block"); 2554127675Sbms isis_print_metric_block((const struct isis_metric_block *)tptr); 2555127675Sbms tptr+=sizeof(struct isis_metric_block); 2556127675Sbms tmp-=sizeof(struct isis_metric_block); 2557127675Sbms 2558127675Sbms while(tmp>0) { 2559127675Sbms if (!TTEST2(*tptr, 1)) 2560127675Sbms goto trunctlv; 2561127675Sbms prefix_len=*tptr++; /* read out prefix length in semioctets*/ 2562147904Ssam if (prefix_len < 2) { 2563147904Ssam printf("\n\t\tAddress: prefix length %u < 2", prefix_len); 2564147904Ssam break; 2565147904Ssam } 2566127675Sbms tmp--; 2567147904Ssam if (tmp < prefix_len/2) 2568147904Ssam break; 2569127675Sbms if (!TTEST2(*tptr, prefix_len/2)) 2570127675Sbms goto trunctlv; 2571127675Sbms printf("\n\t\tAddress: %s/%u", 2572146778Ssam isonsap_string(tptr,prefix_len/2), 2573127675Sbms prefix_len*4); 2574127675Sbms tptr+=prefix_len/2; 2575127675Sbms tmp-=prefix_len/2; 2576127675Sbms } 2577127675Sbms break; 2578127675Sbms 2579146778Ssam case ISIS_TLV_IIH_SEQNR: 2580147904Ssam if (tmp < 4) 2581147904Ssam break; 2582127675Sbms if (!TTEST2(*tptr, 4)) /* check if four bytes are on the wire */ 2583127675Sbms goto trunctlv; 2584127675Sbms printf("\n\t Sequence number: %u", EXTRACT_32BITS(tptr) ); 2585127675Sbms break; 2586127675Sbms 2587146778Ssam case ISIS_TLV_VENDOR_PRIVATE: 2588147904Ssam if (tmp < 3) 2589147904Ssam break; 2590127675Sbms if (!TTEST2(*tptr, 3)) /* check if enough byte for a full oui */ 2591127675Sbms goto trunctlv; 2592146778Ssam vendor_id = EXTRACT_24BITS(tptr); 2593146778Ssam printf("\n\t Vendor: %s (%u)", 2594146778Ssam tok2str(oui_values,"Unknown",vendor_id), 2595146778Ssam vendor_id); 2596127675Sbms tptr+=3; 2597127675Sbms tmp-=3; 2598127675Sbms if (tmp > 0) /* hexdump the rest */ 2599127675Sbms if(!print_unknown_data(tptr,"\n\t\t",tmp)) 2600127675Sbms return(0); 2601127675Sbms break; 2602127675Sbms /* 2603127675Sbms * FIXME those are the defined TLVs that lack a decoder 2604127675Sbms * you are welcome to contribute code ;-) 2605127675Sbms */ 2606127675Sbms 2607146778Ssam case ISIS_TLV_DECNET_PHASE4: 2608146778Ssam case ISIS_TLV_LUCENT_PRIVATE: 2609146778Ssam case ISIS_TLV_IPAUTH: 2610146778Ssam case ISIS_TLV_NORTEL_PRIVATE1: 2611146778Ssam case ISIS_TLV_NORTEL_PRIVATE2: 2612127675Sbms 261317688Spst default: 2614127675Sbms if (vflag <= 1) { 2615127675Sbms if(!print_unknown_data(pptr,"\n\t\t",tlv_len)) 2616127675Sbms return(0); 2617127675Sbms } 261817688Spst break; 261917688Spst } 2620127675Sbms /* do we want to see an additionally hexdump ? */ 2621127675Sbms if (vflag> 1) { 2622127675Sbms if(!print_unknown_data(pptr,"\n\t ",tlv_len)) 2623127675Sbms return(0); 2624127675Sbms } 262517688Spst 2626127675Sbms pptr += tlv_len; 2627127675Sbms packet_len -= tlv_len; 262817688Spst } 262917688Spst 263017688Spst if (packet_len != 0) { 2631127675Sbms printf("\n\t %u straggler bytes", packet_len); 263217688Spst } 263398527Sfenner return (1); 263498527Sfenner 2635127675Sbms trunc: 263698527Sfenner fputs("[|isis]", stdout); 263798527Sfenner return (1); 263898527Sfenner 2639127675Sbms trunctlv: 2640127675Sbms printf("\n\t\t packet exceeded snapshot"); 264117688Spst return(1); 264217688Spst} 264317688Spst 264417751Spst/* 264517751Spst * Verify the checksum. See 8473-1, Appendix C, section C.4. 264617751Spst */ 264717751Spst 264817688Spststatic int 2649127675Sbmsosi_cksum(const u_int8_t *tptr, u_int len) 265017680Spst{ 265117680Spst int32_t c0 = 0, c1 = 0; 265217680Spst 265339300Sfenner while ((int)--len >= 0) { 2654127675Sbms c0 += *tptr++; 265517751Spst c0 %= 255; 265617680Spst c1 += c0; 265717680Spst c1 %= 255; 265817680Spst } 265917751Spst return (c0 | c1); 266017680Spst} 2661146778Ssam 2662146778Ssam 2663146778Ssam/* 2664146778Ssam * Local Variables: 2665146778Ssam * c-style: whitesmith 2666146778Ssam * c-basic-offset: 8 2667146778Ssam * End: 2668146778Ssam */ 2669