10f74e101Schristos /* 20f74e101Schristos * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997 30f74e101Schristos * The Regents of the University of California. All rights reserved. 40f74e101Schristos * 50f74e101Schristos * Redistribution and use in source and binary forms, with or without 60f74e101Schristos * modification, are permitted provided that: (1) source code distributions 70f74e101Schristos * retain the above copyright notice and this paragraph in its entirety, (2) 80f74e101Schristos * distributions including binary code include the above copyright notice and 90f74e101Schristos * this paragraph in its entirety in the documentation or other materials 100f74e101Schristos * provided with the distribution, and (3) all advertising materials mentioning 110f74e101Schristos * features or use of this software display the following acknowledgement: 120f74e101Schristos * ``This product includes software developed by the University of California, 130f74e101Schristos * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 140f74e101Schristos * the University nor the names of its contributors may be used to endorse 150f74e101Schristos * or promote products derived from this software without specific prior 160f74e101Schristos * written permission. 170f74e101Schristos * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 180f74e101Schristos * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 190f74e101Schristos * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 200f74e101Schristos */ 210f74e101Schristos 2211b3aaa1Schristos #include <sys/cdefs.h> 230f74e101Schristos #ifndef lint 24*26ba0b50Schristos __RCSID("$NetBSD: print-decnet.c,v 1.12 2024/09/02 16:15:31 christos Exp $"); 250f74e101Schristos #endif 260f74e101Schristos 27dc860a36Sspz /* \summary: DECnet printer */ 28dc860a36Sspz 29c74ad251Schristos #include <config.h> 300f74e101Schristos 31c74ad251Schristos #include "netdissect-stdinc.h" 320f74e101Schristos 330f74e101Schristos #include <stdio.h> 340f74e101Schristos #include <stdlib.h> 350f74e101Schristos 36c74ad251Schristos #define ND_LONGJMP_FROM_TCHECK 37fdccd7e4Schristos #include "netdissect.h" 38c74ad251Schristos #include "extract.h" 390f74e101Schristos #include "addrtoname.h" 400f74e101Schristos 41b3a00663Schristos 42fdccd7e4Schristos #ifndef _WIN32 43c74ad251Schristos typedef nd_uint8_t byte; /* single byte field */ 44b3a00663Schristos #else 45b3a00663Schristos /* 46b3a00663Schristos * the keyword 'byte' generates conflicts in Windows 47b3a00663Schristos */ 48c74ad251Schristos typedef nd_uint8_t Byte; /* single byte field */ 49b3a00663Schristos #define byte Byte 50fdccd7e4Schristos #endif /* _WIN32 */ 51c74ad251Schristos typedef nd_uint16_t word; /* 2 byte field */ 52c74ad251Schristos typedef nd_uint32_t longword; /* 4 bytes field */ 53b3a00663Schristos 54b3a00663Schristos /* 55b3a00663Schristos * Definitions for DECNET Phase IV protocol headers 56b3a00663Schristos */ 57c74ad251Schristos typedef union { 58c74ad251Schristos nd_mac_addr dne_addr; /* full Ethernet address */ 59b3a00663Schristos struct { 60c74ad251Schristos nd_byte dne_hiord[4]; /* DECnet HIORD prefix */ 61c74ad251Schristos nd_byte dne_nodeaddr[2]; /* DECnet node address */ 62b3a00663Schristos } dne_remote; 63c74ad251Schristos } etheraddr; /* Ethernet address */ 64b3a00663Schristos 65b3a00663Schristos #define HIORD 0x000400aa /* high 32-bits of address (swapped) */ 66b3a00663Schristos 67b3a00663Schristos #define AREAMASK 0176000 /* mask for area field */ 68b3a00663Schristos #define AREASHIFT 10 /* bit-offset for area field */ 69b3a00663Schristos #define NODEMASK 01777 /* mask for node address field */ 70b3a00663Schristos 71b3a00663Schristos /* 72b3a00663Schristos * Define long and short header formats. 73b3a00663Schristos */ 74b3a00663Schristos struct shorthdr 75b3a00663Schristos { 76b3a00663Schristos byte sh_flags; /* route flags */ 77b3a00663Schristos word sh_dst; /* destination node address */ 78b3a00663Schristos word sh_src; /* source node address */ 79b3a00663Schristos byte sh_visits; /* visit count */ 80b3a00663Schristos }; 81b3a00663Schristos 82b3a00663Schristos struct longhdr 83b3a00663Schristos { 84b3a00663Schristos byte lg_flags; /* route flags */ 85b3a00663Schristos byte lg_darea; /* destination area (reserved) */ 86b3a00663Schristos byte lg_dsarea; /* destination subarea (reserved) */ 87b3a00663Schristos etheraddr lg_dst; /* destination id */ 88b3a00663Schristos byte lg_sarea; /* source area (reserved) */ 89b3a00663Schristos byte lg_ssarea; /* source subarea (reserved) */ 90b3a00663Schristos etheraddr lg_src; /* source id */ 91b3a00663Schristos byte lg_nextl2; /* next level 2 router (reserved) */ 92b3a00663Schristos byte lg_visits; /* visit count */ 93b3a00663Schristos byte lg_service; /* service class (reserved) */ 94b3a00663Schristos byte lg_pt; /* protocol type (reserved) */ 95b3a00663Schristos }; 96b3a00663Schristos 97b3a00663Schristos union routehdr 98b3a00663Schristos { 99b3a00663Schristos struct shorthdr rh_short; /* short route header */ 100b3a00663Schristos struct longhdr rh_long; /* long route header */ 101b3a00663Schristos }; 102b3a00663Schristos 103b3a00663Schristos /* 104b3a00663Schristos * Define the values of various fields in the protocol messages. 105b3a00663Schristos * 106b3a00663Schristos * 1. Data packet formats. 107b3a00663Schristos */ 108b3a00663Schristos #define RMF_MASK 7 /* mask for message type */ 109b3a00663Schristos #define RMF_SHORT 2 /* short message format */ 110b3a00663Schristos #define RMF_LONG 6 /* long message format */ 111b3a00663Schristos #ifndef RMF_RQR 112b3a00663Schristos #define RMF_RQR 010 /* request return to sender */ 113b3a00663Schristos #define RMF_RTS 020 /* returning to sender */ 114b3a00663Schristos #define RMF_IE 040 /* intra-ethernet packet */ 115b3a00663Schristos #endif /* RMR_RQR */ 116b3a00663Schristos #define RMF_FVER 0100 /* future version flag */ 117b3a00663Schristos #define RMF_PAD 0200 /* pad field */ 118b3a00663Schristos #define RMF_PADMASK 0177 /* pad field mask */ 119b3a00663Schristos 120b3a00663Schristos #define VIS_MASK 077 /* visit field mask */ 121b3a00663Schristos 122b3a00663Schristos /* 123b3a00663Schristos * 2. Control packet formats. 124b3a00663Schristos */ 125b3a00663Schristos #define RMF_CTLMASK 017 /* mask for message type */ 126b3a00663Schristos #define RMF_CTLMSG 01 /* control message indicator */ 127b3a00663Schristos #define RMF_INIT 01 /* initialization message */ 128b3a00663Schristos #define RMF_VER 03 /* verification message */ 129b3a00663Schristos #define RMF_TEST 05 /* hello and test message */ 130b3a00663Schristos #define RMF_L1ROUT 07 /* level 1 routing message */ 131b3a00663Schristos #define RMF_L2ROUT 011 /* level 2 routing message */ 132b3a00663Schristos #define RMF_RHELLO 013 /* router hello message */ 133b3a00663Schristos #define RMF_EHELLO 015 /* endnode hello message */ 134b3a00663Schristos 135b3a00663Schristos #define TI_L2ROUT 01 /* level 2 router */ 136b3a00663Schristos #define TI_L1ROUT 02 /* level 1 router */ 137b3a00663Schristos #define TI_ENDNODE 03 /* endnode */ 138b3a00663Schristos #define TI_VERIF 04 /* verification required */ 139b3a00663Schristos #define TI_BLOCK 010 /* blocking requested */ 140b3a00663Schristos 141b3a00663Schristos #define VE_VERS 2 /* version number (2) */ 142b3a00663Schristos #define VE_ECO 0 /* ECO number */ 143b3a00663Schristos #define VE_UECO 0 /* user ECO number (0) */ 144b3a00663Schristos 145b3a00663Schristos #define P3_VERS 1 /* phase III version number (1) */ 146b3a00663Schristos #define P3_ECO 3 /* ECO number (3) */ 147b3a00663Schristos #define P3_UECO 0 /* user ECO number (0) */ 148b3a00663Schristos 149b3a00663Schristos #define II_L2ROUT 01 /* level 2 router */ 150b3a00663Schristos #define II_L1ROUT 02 /* level 1 router */ 151b3a00663Schristos #define II_ENDNODE 03 /* endnode */ 152b3a00663Schristos #define II_VERIF 04 /* verification required */ 153b3a00663Schristos #define II_NOMCAST 040 /* no multicast traffic accepted */ 154b3a00663Schristos #define II_BLOCK 0100 /* blocking requested */ 155b3a00663Schristos #define II_TYPEMASK 03 /* mask for node type */ 156b3a00663Schristos 157b3a00663Schristos #define TESTDATA 0252 /* test data bytes */ 158b3a00663Schristos #define TESTLEN 1 /* length of transmitted test data */ 159b3a00663Schristos 160b3a00663Schristos /* 161b3a00663Schristos * Define control message formats. 162b3a00663Schristos */ 163b3a00663Schristos struct initmsg /* initialization message */ 164b3a00663Schristos { 165b3a00663Schristos byte in_flags; /* route flags */ 166b3a00663Schristos word in_src; /* source node address */ 167b3a00663Schristos byte in_info; /* routing layer information */ 168b3a00663Schristos word in_blksize; /* maximum data link block size */ 169b3a00663Schristos byte in_vers; /* version number */ 170b3a00663Schristos byte in_eco; /* ECO number */ 171b3a00663Schristos byte in_ueco; /* user ECO number */ 172b3a00663Schristos word in_hello; /* hello timer */ 173b3a00663Schristos byte in_rsvd; /* reserved image field */ 174b3a00663Schristos }; 175b3a00663Schristos 176b3a00663Schristos struct verifmsg /* verification message */ 177b3a00663Schristos { 178b3a00663Schristos byte ve_flags; /* route flags */ 179b3a00663Schristos word ve_src; /* source node address */ 180b3a00663Schristos byte ve_fcnval; /* function value image field */ 181b3a00663Schristos }; 182b3a00663Schristos 183b3a00663Schristos struct testmsg /* hello and test message */ 184b3a00663Schristos { 185b3a00663Schristos byte te_flags; /* route flags */ 186b3a00663Schristos word te_src; /* source node address */ 187b3a00663Schristos byte te_data; /* test data image field */ 188b3a00663Schristos }; 189b3a00663Schristos 190b3a00663Schristos struct l1rout /* level 1 routing message */ 191b3a00663Schristos { 192b3a00663Schristos byte r1_flags; /* route flags */ 193b3a00663Schristos word r1_src; /* source node address */ 194b3a00663Schristos byte r1_rsvd; /* reserved field */ 195b3a00663Schristos }; 196b3a00663Schristos 197b3a00663Schristos struct l2rout /* level 2 routing message */ 198b3a00663Schristos { 199b3a00663Schristos byte r2_flags; /* route flags */ 200b3a00663Schristos word r2_src; /* source node address */ 201b3a00663Schristos byte r2_rsvd; /* reserved field */ 202b3a00663Schristos }; 203b3a00663Schristos 204b3a00663Schristos struct rhellomsg /* router hello message */ 205b3a00663Schristos { 206b3a00663Schristos byte rh_flags; /* route flags */ 207b3a00663Schristos byte rh_vers; /* version number */ 208b3a00663Schristos byte rh_eco; /* ECO number */ 209b3a00663Schristos byte rh_ueco; /* user ECO number */ 210b3a00663Schristos etheraddr rh_src; /* source id */ 211b3a00663Schristos byte rh_info; /* routing layer information */ 212b3a00663Schristos word rh_blksize; /* maximum data link block size */ 213b3a00663Schristos byte rh_priority; /* router's priority */ 214b3a00663Schristos byte rh_area; /* reserved */ 215b3a00663Schristos word rh_hello; /* hello timer */ 216b3a00663Schristos byte rh_mpd; /* reserved */ 217b3a00663Schristos }; 218b3a00663Schristos 219b3a00663Schristos struct ehellomsg /* endnode hello message */ 220b3a00663Schristos { 221b3a00663Schristos byte eh_flags; /* route flags */ 222b3a00663Schristos byte eh_vers; /* version number */ 223b3a00663Schristos byte eh_eco; /* ECO number */ 224b3a00663Schristos byte eh_ueco; /* user ECO number */ 225b3a00663Schristos etheraddr eh_src; /* source id */ 226b3a00663Schristos byte eh_info; /* routing layer information */ 227b3a00663Schristos word eh_blksize; /* maximum data link block size */ 228b3a00663Schristos byte eh_area; /* area (reserved) */ 229b3a00663Schristos byte eh_seed[8]; /* verification seed */ 230b3a00663Schristos etheraddr eh_router; /* designated router */ 231b3a00663Schristos word eh_hello; /* hello timer */ 232b3a00663Schristos byte eh_mpd; /* (reserved) */ 233b3a00663Schristos byte eh_data; /* test data image field */ 234b3a00663Schristos }; 235b3a00663Schristos 236b3a00663Schristos union controlmsg 237b3a00663Schristos { 238b3a00663Schristos struct initmsg cm_init; /* initialization message */ 239b3a00663Schristos struct verifmsg cm_ver; /* verification message */ 240b3a00663Schristos struct testmsg cm_test; /* hello and test message */ 241b3a00663Schristos struct l1rout cm_l1rou; /* level 1 routing message */ 242b3a00663Schristos struct l2rout cm_l2rout; /* level 2 routing message */ 243b3a00663Schristos struct rhellomsg cm_rhello; /* router hello message */ 244b3a00663Schristos struct ehellomsg cm_ehello; /* endnode hello message */ 245b3a00663Schristos }; 246b3a00663Schristos 247b3a00663Schristos /* Macros for decoding routing-info fields */ 248b3a00663Schristos #define RI_COST(x) ((x)&0777) 249b3a00663Schristos #define RI_HOPS(x) (((x)>>10)&037) 250ba2ff121Schristos 251b3a00663Schristos /* 252b3a00663Schristos * NSP protocol fields and values. 253b3a00663Schristos */ 254b3a00663Schristos 255b3a00663Schristos #define NSP_TYPEMASK 014 /* mask to isolate type code */ 256b3a00663Schristos #define NSP_SUBMASK 0160 /* mask to isolate subtype code */ 257b3a00663Schristos #define NSP_SUBSHFT 4 /* shift to move subtype code */ 258b3a00663Schristos 259b3a00663Schristos #define MFT_DATA 0 /* data message */ 260b3a00663Schristos #define MFT_ACK 04 /* acknowledgement message */ 261b3a00663Schristos #define MFT_CTL 010 /* control message */ 262b3a00663Schristos 263b3a00663Schristos #define MFS_ILS 020 /* data or I/LS indicator */ 264b3a00663Schristos #define MFS_BOM 040 /* beginning of message (data) */ 265b3a00663Schristos #define MFS_MOM 0 /* middle of message (data) */ 266b3a00663Schristos #define MFS_EOM 0100 /* end of message (data) */ 267b3a00663Schristos #define MFS_INT 040 /* interrupt message */ 268b3a00663Schristos 269b3a00663Schristos #define MFS_DACK 0 /* data acknowledgement */ 270b3a00663Schristos #define MFS_IACK 020 /* I/LS acknowledgement */ 271b3a00663Schristos #define MFS_CACK 040 /* connect acknowledgement */ 272b3a00663Schristos 273b3a00663Schristos #define MFS_NOP 0 /* no operation */ 274b3a00663Schristos #define MFS_CI 020 /* connect initiate */ 275b3a00663Schristos #define MFS_CC 040 /* connect confirm */ 276b3a00663Schristos #define MFS_DI 060 /* disconnect initiate */ 277b3a00663Schristos #define MFS_DC 0100 /* disconnect confirm */ 278b3a00663Schristos #define MFS_RCI 0140 /* retransmitted connect initiate */ 279b3a00663Schristos 280b3a00663Schristos #define SGQ_ACK 0100000 /* ack */ 281b3a00663Schristos #define SGQ_NAK 0110000 /* negative ack */ 282b3a00663Schristos #define SGQ_OACK 0120000 /* other channel ack */ 283b3a00663Schristos #define SGQ_ONAK 0130000 /* other channel negative ack */ 284b3a00663Schristos #define SGQ_MASK 07777 /* mask to isolate seq # */ 285b3a00663Schristos #define SGQ_OTHER 020000 /* other channel qualifier */ 286b3a00663Schristos #define SGQ_DELAY 010000 /* ack delay flag */ 287b3a00663Schristos 288b3a00663Schristos #define SGQ_EOM 0100000 /* pseudo flag for end-of-message */ 289b3a00663Schristos 290b3a00663Schristos #define LSM_MASK 03 /* mask for modifier field */ 291b3a00663Schristos #define LSM_NOCHANGE 0 /* no change */ 292b3a00663Schristos #define LSM_DONOTSEND 1 /* do not send data */ 293b3a00663Schristos #define LSM_SEND 2 /* send data */ 294b3a00663Schristos 295b3a00663Schristos #define LSI_MASK 014 /* mask for interpretation field */ 296b3a00663Schristos #define LSI_DATA 0 /* data segment or message count */ 297b3a00663Schristos #define LSI_INTR 4 /* interrupt request count */ 298b3a00663Schristos #define LSI_INTM 0377 /* funny marker for int. message */ 299b3a00663Schristos 300b3a00663Schristos #define COS_MASK 014 /* mask for flow control field */ 301b3a00663Schristos #define COS_NONE 0 /* no flow control */ 302b3a00663Schristos #define COS_SEGMENT 04 /* segment flow control */ 303b3a00663Schristos #define COS_MESSAGE 010 /* message flow control */ 304b3a00663Schristos #define COS_DEFAULT 1 /* default value for field */ 305b3a00663Schristos 306b3a00663Schristos #define COI_MASK 3 /* mask for version field */ 307b3a00663Schristos #define COI_32 0 /* version 3.2 */ 308b3a00663Schristos #define COI_31 1 /* version 3.1 */ 309b3a00663Schristos #define COI_40 2 /* version 4.0 */ 310b3a00663Schristos #define COI_41 3 /* version 4.1 */ 311b3a00663Schristos 312b3a00663Schristos #define MNU_MASK 140 /* mask for session control version */ 313b3a00663Schristos #define MNU_10 000 /* session V1.0 */ 314b3a00663Schristos #define MNU_20 040 /* session V2.0 */ 315b3a00663Schristos #define MNU_ACCESS 1 /* access control present */ 316b3a00663Schristos #define MNU_USRDATA 2 /* user data field present */ 317b3a00663Schristos #define MNU_INVKPROXY 4 /* invoke proxy field present */ 318b3a00663Schristos #define MNU_UICPROXY 8 /* use uic-based proxy */ 319b3a00663Schristos 320b3a00663Schristos #define DC_NORESOURCES 1 /* no resource reason code */ 321b3a00663Schristos #define DC_NOLINK 41 /* no link terminate reason code */ 322b3a00663Schristos #define DC_COMPLETE 42 /* disconnect complete reason code */ 323b3a00663Schristos 324b3a00663Schristos #define DI_NOERROR 0 /* user disconnect */ 325b3a00663Schristos #define DI_SHUT 3 /* node is shutting down */ 326b3a00663Schristos #define DI_NOUSER 4 /* destination end user does not exist */ 327b3a00663Schristos #define DI_INVDEST 5 /* invalid end user destination */ 328b3a00663Schristos #define DI_REMRESRC 6 /* insufficient remote resources */ 329b3a00663Schristos #define DI_TPA 8 /* third party abort */ 330b3a00663Schristos #define DI_PROTOCOL 7 /* protocol error discovered */ 331b3a00663Schristos #define DI_ABORT 9 /* user abort */ 332b3a00663Schristos #define DI_LOCALRESRC 32 /* insufficient local resources */ 333b3a00663Schristos #define DI_REMUSERRESRC 33 /* insufficient remote user resources */ 334b3a00663Schristos #define DI_BADACCESS 34 /* bad access control information */ 335b3a00663Schristos #define DI_BADACCNT 36 /* bad ACCOUNT information */ 336b3a00663Schristos #define DI_CONNECTABORT 38 /* connect request cancelled */ 337b3a00663Schristos #define DI_TIMEDOUT 38 /* remote node or user crashed */ 338b3a00663Schristos #define DI_UNREACHABLE 39 /* local timers expired due to ... */ 339b3a00663Schristos #define DI_BADIMAGE 43 /* bad image data in connect */ 340b3a00663Schristos #define DI_SERVMISMATCH 54 /* cryptographic service mismatch */ 341b3a00663Schristos 342b3a00663Schristos #define UC_OBJREJECT 0 /* object rejected connect */ 343b3a00663Schristos #define UC_USERDISCONNECT 0 /* user disconnect */ 344b3a00663Schristos #define UC_RESOURCES 1 /* insufficient resources (local or remote) */ 345b3a00663Schristos #define UC_NOSUCHNODE 2 /* unrecognized node name */ 346b3a00663Schristos #define UC_REMOTESHUT 3 /* remote node shutting down */ 347b3a00663Schristos #define UC_NOSUCHOBJ 4 /* unrecognized object */ 348b3a00663Schristos #define UC_INVOBJFORMAT 5 /* invalid object name format */ 349b3a00663Schristos #define UC_OBJTOOBUSY 6 /* object too busy */ 350b3a00663Schristos #define UC_NETWORKABORT 8 /* network abort */ 351b3a00663Schristos #define UC_USERABORT 9 /* user abort */ 352b3a00663Schristos #define UC_INVNODEFORMAT 10 /* invalid node name format */ 353b3a00663Schristos #define UC_LOCALSHUT 11 /* local node shutting down */ 354b3a00663Schristos #define UC_ACCESSREJECT 34 /* invalid access control information */ 355b3a00663Schristos #define UC_NORESPONSE 38 /* no response from object */ 356b3a00663Schristos #define UC_UNREACHABLE 39 /* node unreachable */ 357b3a00663Schristos 358b3a00663Schristos /* 359b3a00663Schristos * NSP message formats. 360b3a00663Schristos */ 361b3a00663Schristos struct nsphdr /* general nsp header */ 362b3a00663Schristos { 363b3a00663Schristos byte nh_flags; /* message flags */ 364b3a00663Schristos word nh_dst; /* destination link address */ 365b3a00663Schristos word nh_src; /* source link address */ 366b3a00663Schristos }; 367b3a00663Schristos 368b3a00663Schristos struct seghdr /* data segment header */ 369b3a00663Schristos { 370b3a00663Schristos byte sh_flags; /* message flags */ 371b3a00663Schristos word sh_dst; /* destination link address */ 372b3a00663Schristos word sh_src; /* source link address */ 373b3a00663Schristos word sh_seq[3]; /* sequence numbers */ 374b3a00663Schristos }; 375b3a00663Schristos 376b3a00663Schristos struct minseghdr /* minimum data segment header */ 377b3a00663Schristos { 378b3a00663Schristos byte ms_flags; /* message flags */ 379b3a00663Schristos word ms_dst; /* destination link address */ 380b3a00663Schristos word ms_src; /* source link address */ 381b3a00663Schristos word ms_seq; /* sequence number */ 382b3a00663Schristos }; 383b3a00663Schristos 384b3a00663Schristos struct lsmsg /* link service message (after hdr) */ 385b3a00663Schristos { 386b3a00663Schristos byte ls_lsflags; /* link service flags */ 387b3a00663Schristos byte ls_fcval; /* flow control value */ 388b3a00663Schristos }; 389b3a00663Schristos 390b3a00663Schristos struct ackmsg /* acknowledgement message */ 391b3a00663Schristos { 392b3a00663Schristos byte ak_flags; /* message flags */ 393b3a00663Schristos word ak_dst; /* destination link address */ 394b3a00663Schristos word ak_src; /* source link address */ 395b3a00663Schristos word ak_acknum[2]; /* acknowledgement numbers */ 396b3a00663Schristos }; 397b3a00663Schristos 398b3a00663Schristos struct minackmsg /* minimum acknowledgement message */ 399b3a00663Schristos { 400b3a00663Schristos byte mk_flags; /* message flags */ 401b3a00663Schristos word mk_dst; /* destination link address */ 402b3a00663Schristos word mk_src; /* source link address */ 403b3a00663Schristos word mk_acknum; /* acknowledgement number */ 404b3a00663Schristos }; 405b3a00663Schristos 406b3a00663Schristos struct ciackmsg /* connect acknowledgement message */ 407b3a00663Schristos { 408b3a00663Schristos byte ck_flags; /* message flags */ 409b3a00663Schristos word ck_dst; /* destination link address */ 410b3a00663Schristos }; 411b3a00663Schristos 412b3a00663Schristos struct cimsg /* connect initiate message */ 413b3a00663Schristos { 414b3a00663Schristos byte ci_flags; /* message flags */ 415b3a00663Schristos word ci_dst; /* destination link address (0) */ 416b3a00663Schristos word ci_src; /* source link address */ 417b3a00663Schristos byte ci_services; /* requested services */ 418b3a00663Schristos byte ci_info; /* information */ 419b3a00663Schristos word ci_segsize; /* maximum segment size */ 420b3a00663Schristos }; 421b3a00663Schristos 422b3a00663Schristos struct ccmsg /* connect confirm message */ 423b3a00663Schristos { 424b3a00663Schristos byte cc_flags; /* message flags */ 425b3a00663Schristos word cc_dst; /* destination link address */ 426b3a00663Schristos word cc_src; /* source link address */ 427b3a00663Schristos byte cc_services; /* requested services */ 428b3a00663Schristos byte cc_info; /* information */ 429b3a00663Schristos word cc_segsize; /* maximum segment size */ 430b3a00663Schristos byte cc_optlen; /* optional data length */ 431b3a00663Schristos }; 432b3a00663Schristos 433b3a00663Schristos struct cnmsg /* generic connect message */ 434b3a00663Schristos { 435b3a00663Schristos byte cn_flags; /* message flags */ 436b3a00663Schristos word cn_dst; /* destination link address */ 437b3a00663Schristos word cn_src; /* source link address */ 438b3a00663Schristos byte cn_services; /* requested services */ 439b3a00663Schristos byte cn_info; /* information */ 440b3a00663Schristos word cn_segsize; /* maximum segment size */ 441b3a00663Schristos }; 442b3a00663Schristos 443b3a00663Schristos struct dimsg /* disconnect initiate message */ 444b3a00663Schristos { 445b3a00663Schristos byte di_flags; /* message flags */ 446b3a00663Schristos word di_dst; /* destination link address */ 447b3a00663Schristos word di_src; /* source link address */ 448b3a00663Schristos word di_reason; /* reason code */ 449b3a00663Schristos byte di_optlen; /* optional data length */ 450b3a00663Schristos }; 451b3a00663Schristos 452b3a00663Schristos struct dcmsg /* disconnect confirm message */ 453b3a00663Schristos { 454b3a00663Schristos byte dc_flags; /* message flags */ 455b3a00663Schristos word dc_dst; /* destination link address */ 456b3a00663Schristos word dc_src; /* source link address */ 457b3a00663Schristos word dc_reason; /* reason code */ 458b3a00663Schristos }; 459b3a00663Schristos 4600f74e101Schristos /* Forwards */ 461b3a00663Schristos static int print_decnet_ctlmsg(netdissect_options *, const union routehdr *, u_int, u_int); 462c74ad251Schristos static void print_t_info(netdissect_options *, u_int); 463c74ad251Schristos static void print_l1_routes(netdissect_options *, const u_char *, u_int); 464c74ad251Schristos static void print_l2_routes(netdissect_options *, const u_char *, u_int); 465c74ad251Schristos static void print_i_info(netdissect_options *, u_int); 466c74ad251Schristos static void print_elist(const u_char *, u_int); 467b3a00663Schristos static int print_nsp(netdissect_options *, const u_char *, u_int); 468c74ad251Schristos static void print_reason(netdissect_options *, u_int); 4690f74e101Schristos 4700f74e101Schristos void 471b3a00663Schristos decnet_print(netdissect_options *ndo, 472c74ad251Schristos const u_char *ap, u_int length, 473c74ad251Schristos u_int caplen) 4740f74e101Schristos { 475c74ad251Schristos const union routehdr *rhp; 476c74ad251Schristos u_int mflags; 477c74ad251Schristos uint16_t dst, src; 478c74ad251Schristos u_int hops; 4790f74e101Schristos u_int nsplen, pktlen; 4800f74e101Schristos const u_char *nspp; 4810f74e101Schristos 482c74ad251Schristos ndo->ndo_protocol = "decnet"; 4830f74e101Schristos if (length < sizeof(struct shorthdr)) { 484c74ad251Schristos ND_PRINT(" (length %u < %zu)", length, sizeof(struct shorthdr)); 485c74ad251Schristos goto invalid; 4860f74e101Schristos } 4870f74e101Schristos 488c74ad251Schristos pktlen = GET_LE_U_2(ap); 4890f74e101Schristos if (pktlen < sizeof(struct shorthdr)) { 490c74ad251Schristos ND_PRINT(" (pktlen %u < %zu)", pktlen, sizeof(struct shorthdr)); 491c74ad251Schristos goto invalid; 4920f74e101Schristos } 4930f74e101Schristos if (pktlen > length) { 494c74ad251Schristos ND_PRINT(" (pktlen %u > %u)", pktlen, length); 495c74ad251Schristos goto invalid; 4960f74e101Schristos } 4970f74e101Schristos length = pktlen; 4980f74e101Schristos 499c74ad251Schristos rhp = (const union routehdr *)(ap + sizeof(short)); 500c74ad251Schristos mflags = GET_U_1(rhp->rh_short.sh_flags); 5010f74e101Schristos 5020f74e101Schristos if (mflags & RMF_PAD) { 5030f74e101Schristos /* pad bytes of some sort in front of message */ 5040f74e101Schristos u_int padlen = mflags & RMF_PADMASK; 505b3a00663Schristos if (ndo->ndo_vflag) 506c74ad251Schristos ND_PRINT("[pad:%u] ", padlen); 5070f74e101Schristos if (length < padlen + 2) { 508c74ad251Schristos ND_PRINT(" (length %u < %u)", length, padlen + 2); 509c74ad251Schristos goto invalid; 5100f74e101Schristos } 511c74ad251Schristos ND_TCHECK_LEN(ap + sizeof(short), padlen); 5120f74e101Schristos ap += padlen; 5130f74e101Schristos length -= padlen; 5140f74e101Schristos caplen -= padlen; 515c74ad251Schristos rhp = (const union routehdr *)(ap + sizeof(short)); 516c74ad251Schristos mflags = GET_U_1(rhp->rh_short.sh_flags); 5170f74e101Schristos } 5180f74e101Schristos 5190f74e101Schristos if (mflags & RMF_FVER) { 520c74ad251Schristos ND_PRINT("future-version-decnet"); 521c74ad251Schristos ND_DEFAULTPRINT(ap, ND_MIN(length, caplen)); 5220f74e101Schristos return; 5230f74e101Schristos } 5240f74e101Schristos 5250f74e101Schristos /* is it a control message? */ 5260f74e101Schristos if (mflags & RMF_CTLMSG) { 527b3a00663Schristos if (!print_decnet_ctlmsg(ndo, rhp, length, caplen)) 528c74ad251Schristos goto invalid; 5290f74e101Schristos return; 5300f74e101Schristos } 5310f74e101Schristos 5320f74e101Schristos switch (mflags & RMF_MASK) { 5330f74e101Schristos case RMF_LONG: 5340f74e101Schristos if (length < sizeof(struct longhdr)) { 535c74ad251Schristos ND_PRINT(" (length %u < %zu)", length, sizeof(struct longhdr)); 536c74ad251Schristos goto invalid; 5370f74e101Schristos } 538c74ad251Schristos ND_TCHECK_SIZE(&rhp->rh_long); 5390f74e101Schristos dst = 540c74ad251Schristos GET_LE_U_2(rhp->rh_long.lg_dst.dne_remote.dne_nodeaddr); 5410f74e101Schristos src = 542c74ad251Schristos GET_LE_U_2(rhp->rh_long.lg_src.dne_remote.dne_nodeaddr); 543c74ad251Schristos hops = GET_U_1(rhp->rh_long.lg_visits); 544c74ad251Schristos nspp = ap + sizeof(short) + sizeof(struct longhdr); 5450f74e101Schristos nsplen = length - sizeof(struct longhdr); 5460f74e101Schristos break; 5470f74e101Schristos case RMF_SHORT: 548c74ad251Schristos dst = GET_LE_U_2(rhp->rh_short.sh_dst); 549c74ad251Schristos src = GET_LE_U_2(rhp->rh_short.sh_src); 550c74ad251Schristos hops = (GET_U_1(rhp->rh_short.sh_visits) & VIS_MASK)+1; 551c74ad251Schristos nspp = ap + sizeof(short) + sizeof(struct shorthdr); 5520f74e101Schristos nsplen = length - sizeof(struct shorthdr); 5530f74e101Schristos break; 5540f74e101Schristos default: 555c74ad251Schristos ND_PRINT("unknown message flags under mask"); 556c74ad251Schristos ND_DEFAULTPRINT((const u_char *)ap, ND_MIN(length, caplen)); 5570f74e101Schristos return; 5580f74e101Schristos } 5590f74e101Schristos 560c74ad251Schristos ND_PRINT("%s > %s %u ", 561c74ad251Schristos dnaddr_string(ndo, src), dnaddr_string(ndo, dst), pktlen); 562b3a00663Schristos if (ndo->ndo_vflag) { 5630f74e101Schristos if (mflags & RMF_RQR) 564c74ad251Schristos ND_PRINT("RQR "); 5650f74e101Schristos if (mflags & RMF_RTS) 566c74ad251Schristos ND_PRINT("RTS "); 5670f74e101Schristos if (mflags & RMF_IE) 568c74ad251Schristos ND_PRINT("IE "); 569c74ad251Schristos ND_PRINT("%u hops ", hops); 5700f74e101Schristos } 5710f74e101Schristos 572b3a00663Schristos if (!print_nsp(ndo, nspp, nsplen)) 573c74ad251Schristos goto invalid; 5740f74e101Schristos return; 5750f74e101Schristos 576c74ad251Schristos invalid: 577c74ad251Schristos nd_print_invalid(ndo); 5780f74e101Schristos } 5790f74e101Schristos 5800f74e101Schristos static int 581b3a00663Schristos print_decnet_ctlmsg(netdissect_options *ndo, 582c74ad251Schristos const union routehdr *rhp, u_int length, 5830f74e101Schristos u_int caplen) 5840f74e101Schristos { 58572c96ff3Schristos /* Our caller has already checked for mflags */ 586c74ad251Schristos u_int mflags = GET_U_1(rhp->rh_short.sh_flags); 587c74ad251Schristos const union controlmsg *cmp = (const union controlmsg *)rhp; 588c74ad251Schristos uint16_t src, dst; 589c74ad251Schristos u_int info, blksize, eco, ueco, hello, other, vers; 590c74ad251Schristos u_int priority; 591c74ad251Schristos const u_char *rhpx = (const u_char *)rhp; 5920f74e101Schristos 5930f74e101Schristos switch (mflags & RMF_CTLMASK) { 5940f74e101Schristos case RMF_INIT: 595c74ad251Schristos ND_PRINT("init "); 5960f74e101Schristos if (length < sizeof(struct initmsg)) 597c74ad251Schristos goto invalid; 598c74ad251Schristos ND_TCHECK_SIZE(&cmp->cm_init); 599c74ad251Schristos src = GET_LE_U_2(cmp->cm_init.in_src); 600c74ad251Schristos info = GET_U_1(cmp->cm_init.in_info); 601c74ad251Schristos blksize = GET_LE_U_2(cmp->cm_init.in_blksize); 602c74ad251Schristos vers = GET_U_1(cmp->cm_init.in_vers); 603c74ad251Schristos eco = GET_U_1(cmp->cm_init.in_eco); 604c74ad251Schristos ueco = GET_U_1(cmp->cm_init.in_ueco); 605c74ad251Schristos hello = GET_LE_U_2(cmp->cm_init.in_hello); 606b3a00663Schristos print_t_info(ndo, info); 607c74ad251Schristos ND_PRINT("src %sblksize %u vers %u eco %u ueco %u hello %u", 608b3a00663Schristos dnaddr_string(ndo, src), blksize, vers, eco, ueco, 609c74ad251Schristos hello); 6100f74e101Schristos break; 6110f74e101Schristos case RMF_VER: 612c74ad251Schristos ND_PRINT("verification "); 6130f74e101Schristos if (length < sizeof(struct verifmsg)) 614c74ad251Schristos goto invalid; 615c74ad251Schristos src = GET_LE_U_2(cmp->cm_ver.ve_src); 616c74ad251Schristos other = GET_U_1(cmp->cm_ver.ve_fcnval); 617c74ad251Schristos ND_PRINT("src %s fcnval %o", dnaddr_string(ndo, src), other); 6180f74e101Schristos break; 6190f74e101Schristos case RMF_TEST: 620c74ad251Schristos ND_PRINT("test "); 6210f74e101Schristos if (length < sizeof(struct testmsg)) 622c74ad251Schristos goto invalid; 623c74ad251Schristos src = GET_LE_U_2(cmp->cm_test.te_src); 624c74ad251Schristos other = GET_U_1(cmp->cm_test.te_data); 625c74ad251Schristos ND_PRINT("src %s data %o", dnaddr_string(ndo, src), other); 6260f74e101Schristos break; 6270f74e101Schristos case RMF_L1ROUT: 628c74ad251Schristos ND_PRINT("lev-1-routing "); 6290f74e101Schristos if (length < sizeof(struct l1rout)) 630c74ad251Schristos goto invalid; 631c74ad251Schristos ND_TCHECK_SIZE(&cmp->cm_l1rou); 632c74ad251Schristos src = GET_LE_U_2(cmp->cm_l1rou.r1_src); 633c74ad251Schristos ND_PRINT("src %s ", dnaddr_string(ndo, src)); 634c74ad251Schristos print_l1_routes(ndo, &(rhpx[sizeof(struct l1rout)]), 6350f74e101Schristos length - sizeof(struct l1rout)); 6360f74e101Schristos break; 6370f74e101Schristos case RMF_L2ROUT: 638c74ad251Schristos ND_PRINT("lev-2-routing "); 6390f74e101Schristos if (length < sizeof(struct l2rout)) 640c74ad251Schristos goto invalid; 641c74ad251Schristos ND_TCHECK_SIZE(&cmp->cm_l2rout); 642c74ad251Schristos src = GET_LE_U_2(cmp->cm_l2rout.r2_src); 643c74ad251Schristos ND_PRINT("src %s ", dnaddr_string(ndo, src)); 644c74ad251Schristos print_l2_routes(ndo, &(rhpx[sizeof(struct l2rout)]), 6450f74e101Schristos length - sizeof(struct l2rout)); 6460f74e101Schristos break; 6470f74e101Schristos case RMF_RHELLO: 648c74ad251Schristos ND_PRINT("router-hello "); 6490f74e101Schristos if (length < sizeof(struct rhellomsg)) 650c74ad251Schristos goto invalid; 651c74ad251Schristos ND_TCHECK_SIZE(&cmp->cm_rhello); 652c74ad251Schristos vers = GET_U_1(cmp->cm_rhello.rh_vers); 653c74ad251Schristos eco = GET_U_1(cmp->cm_rhello.rh_eco); 654c74ad251Schristos ueco = GET_U_1(cmp->cm_rhello.rh_ueco); 655c74ad251Schristos src = 656c74ad251Schristos GET_LE_U_2(cmp->cm_rhello.rh_src.dne_remote.dne_nodeaddr); 657c74ad251Schristos info = GET_U_1(cmp->cm_rhello.rh_info); 658c74ad251Schristos blksize = GET_LE_U_2(cmp->cm_rhello.rh_blksize); 659c74ad251Schristos priority = GET_U_1(cmp->cm_rhello.rh_priority); 660c74ad251Schristos hello = GET_LE_U_2(cmp->cm_rhello.rh_hello); 661b3a00663Schristos print_i_info(ndo, info); 662c74ad251Schristos ND_PRINT("vers %u eco %u ueco %u src %s blksize %u pri %u hello %u", 663b3a00663Schristos vers, eco, ueco, dnaddr_string(ndo, src), 664c74ad251Schristos blksize, priority, hello); 665c74ad251Schristos print_elist(&(rhpx[sizeof(struct rhellomsg)]), 6660f74e101Schristos length - sizeof(struct rhellomsg)); 6670f74e101Schristos break; 6680f74e101Schristos case RMF_EHELLO: 669c74ad251Schristos ND_PRINT("endnode-hello "); 6700f74e101Schristos if (length < sizeof(struct ehellomsg)) 671c74ad251Schristos goto invalid; 672c74ad251Schristos vers = GET_U_1(cmp->cm_ehello.eh_vers); 673c74ad251Schristos eco = GET_U_1(cmp->cm_ehello.eh_eco); 674c74ad251Schristos ueco = GET_U_1(cmp->cm_ehello.eh_ueco); 675c74ad251Schristos src = 676c74ad251Schristos GET_LE_U_2(cmp->cm_ehello.eh_src.dne_remote.dne_nodeaddr); 677c74ad251Schristos info = GET_U_1(cmp->cm_ehello.eh_info); 678c74ad251Schristos blksize = GET_LE_U_2(cmp->cm_ehello.eh_blksize); 6790f74e101Schristos /*seed*/ 680c74ad251Schristos dst = 681c74ad251Schristos GET_LE_U_2(cmp->cm_ehello.eh_router.dne_remote.dne_nodeaddr); 682c74ad251Schristos hello = GET_LE_U_2(cmp->cm_ehello.eh_hello); 683c74ad251Schristos other = GET_U_1(cmp->cm_ehello.eh_data); 684b3a00663Schristos print_i_info(ndo, info); 685c74ad251Schristos ND_PRINT("vers %u eco %u ueco %u src %s blksize %u rtr %s hello %u data %o", 686b3a00663Schristos vers, eco, ueco, dnaddr_string(ndo, src), 687c74ad251Schristos blksize, dnaddr_string(ndo, dst), hello, other); 6880f74e101Schristos break; 6890f74e101Schristos 6900f74e101Schristos default: 691c74ad251Schristos ND_PRINT("unknown control message"); 692c74ad251Schristos ND_DEFAULTPRINT((const u_char *)rhp, ND_MIN(length, caplen)); 6930f74e101Schristos break; 6940f74e101Schristos } 695c74ad251Schristos return (1); 6960f74e101Schristos 697c74ad251Schristos invalid: 6980f74e101Schristos return (0); 6990f74e101Schristos } 7000f74e101Schristos 7010f74e101Schristos static void 702b3a00663Schristos print_t_info(netdissect_options *ndo, 703c74ad251Schristos u_int info) 7040f74e101Schristos { 705c74ad251Schristos u_int ntype = info & 3; 7060f74e101Schristos switch (ntype) { 707c74ad251Schristos case 0: ND_PRINT("reserved-ntype? "); break; 708c74ad251Schristos case TI_L2ROUT: ND_PRINT("l2rout "); break; 709c74ad251Schristos case TI_L1ROUT: ND_PRINT("l1rout "); break; 710c74ad251Schristos case TI_ENDNODE: ND_PRINT("endnode "); break; 7110f74e101Schristos } 7120f74e101Schristos if (info & TI_VERIF) 713c74ad251Schristos ND_PRINT("verif "); 7140f74e101Schristos if (info & TI_BLOCK) 715c74ad251Schristos ND_PRINT("blo "); 7160f74e101Schristos } 7170f74e101Schristos 718c74ad251Schristos static void 719b3a00663Schristos print_l1_routes(netdissect_options *ndo, 720c74ad251Schristos const u_char *rp, u_int len) 7210f74e101Schristos { 722c74ad251Schristos u_int count; 723c74ad251Schristos u_int id; 724c74ad251Schristos u_int info; 7250f74e101Schristos 7260f74e101Schristos /* The last short is a checksum */ 7270f74e101Schristos while (len > (3 * sizeof(short))) { 728c74ad251Schristos ND_TCHECK_LEN(rp, 3 * sizeof(short)); 729c74ad251Schristos count = GET_LE_U_2(rp); 7300f74e101Schristos if (count > 1024) 731c74ad251Schristos return; /* seems to be bogus from here on */ 7320f74e101Schristos rp += sizeof(short); 7330f74e101Schristos len -= sizeof(short); 734c74ad251Schristos id = GET_LE_U_2(rp); 7350f74e101Schristos rp += sizeof(short); 7360f74e101Schristos len -= sizeof(short); 737c74ad251Schristos info = GET_LE_U_2(rp); 7380f74e101Schristos rp += sizeof(short); 7390f74e101Schristos len -= sizeof(short); 740c74ad251Schristos ND_PRINT("{ids %u-%u cost %u hops %u} ", id, id + count, 741c74ad251Schristos RI_COST(info), RI_HOPS(info)); 7420f74e101Schristos } 7430f74e101Schristos } 7440f74e101Schristos 745c74ad251Schristos static void 746b3a00663Schristos print_l2_routes(netdissect_options *ndo, 747c74ad251Schristos const u_char *rp, u_int len) 7480f74e101Schristos { 749c74ad251Schristos u_int count; 750c74ad251Schristos u_int area; 751c74ad251Schristos u_int info; 7520f74e101Schristos 7530f74e101Schristos /* The last short is a checksum */ 7540f74e101Schristos while (len > (3 * sizeof(short))) { 755c74ad251Schristos ND_TCHECK_LEN(rp, 3 * sizeof(short)); 756c74ad251Schristos count = GET_LE_U_2(rp); 7570f74e101Schristos if (count > 1024) 758c74ad251Schristos return; /* seems to be bogus from here on */ 7590f74e101Schristos rp += sizeof(short); 7600f74e101Schristos len -= sizeof(short); 761c74ad251Schristos area = GET_LE_U_2(rp); 7620f74e101Schristos rp += sizeof(short); 7630f74e101Schristos len -= sizeof(short); 764c74ad251Schristos info = GET_LE_U_2(rp); 7650f74e101Schristos rp += sizeof(short); 7660f74e101Schristos len -= sizeof(short); 767c74ad251Schristos ND_PRINT("{areas %u-%u cost %u hops %u} ", area, area + count, 768c74ad251Schristos RI_COST(info), RI_HOPS(info)); 7690f74e101Schristos } 7700f74e101Schristos } 7710f74e101Schristos 7720f74e101Schristos static void 773b3a00663Schristos print_i_info(netdissect_options *ndo, 774c74ad251Schristos u_int info) 7750f74e101Schristos { 776c74ad251Schristos u_int ntype = info & II_TYPEMASK; 7770f74e101Schristos switch (ntype) { 778c74ad251Schristos case 0: ND_PRINT("reserved-ntype? "); break; 779c74ad251Schristos case II_L2ROUT: ND_PRINT("l2rout "); break; 780c74ad251Schristos case II_L1ROUT: ND_PRINT("l1rout "); break; 781c74ad251Schristos case II_ENDNODE: ND_PRINT("endnode "); break; 7820f74e101Schristos } 7830f74e101Schristos if (info & II_VERIF) 784c74ad251Schristos ND_PRINT("verif "); 7850f74e101Schristos if (info & II_NOMCAST) 786c74ad251Schristos ND_PRINT("nomcast "); 7870f74e101Schristos if (info & II_BLOCK) 788c74ad251Schristos ND_PRINT("blo "); 7890f74e101Schristos } 7900f74e101Schristos 791c74ad251Schristos static void 792c74ad251Schristos print_elist(const u_char *elp _U_, u_int len _U_) 7930f74e101Schristos { 7940f74e101Schristos /* Not enough examples available for me to debug this */ 7950f74e101Schristos } 7960f74e101Schristos 7970f74e101Schristos static int 798b3a00663Schristos print_nsp(netdissect_options *ndo, 799b3a00663Schristos const u_char *nspp, u_int nsplen) 8000f74e101Schristos { 801fdccd7e4Schristos const struct nsphdr *nsphp = (const struct nsphdr *)nspp; 802c74ad251Schristos u_int dst, src, flags; 8030f74e101Schristos 804c74ad251Schristos if (nsplen < sizeof(struct nsphdr)) { 805c74ad251Schristos ND_PRINT(" (nsplen %u < %zu)", nsplen, sizeof(struct nsphdr)); 806c74ad251Schristos goto invalid; 807c74ad251Schristos } 808c74ad251Schristos flags = GET_U_1(nsphp->nh_flags); 809c74ad251Schristos dst = GET_LE_U_2(nsphp->nh_dst); 810c74ad251Schristos src = GET_LE_U_2(nsphp->nh_src); 8110f74e101Schristos 8120f74e101Schristos switch (flags & NSP_TYPEMASK) { 8130f74e101Schristos case MFT_DATA: 8140f74e101Schristos switch (flags & NSP_SUBMASK) { 8150f74e101Schristos case MFS_BOM: 8160f74e101Schristos case MFS_MOM: 8170f74e101Schristos case MFS_EOM: 8180f74e101Schristos case MFS_BOM+MFS_EOM: 819c74ad251Schristos ND_PRINT("data %u>%u ", src, dst); 8200f74e101Schristos { 821fdccd7e4Schristos const struct seghdr *shp = (const struct seghdr *)nspp; 822c74ad251Schristos u_int ack; 8230f74e101Schristos u_int data_off = sizeof(struct minseghdr); 8240f74e101Schristos 8250f74e101Schristos if (nsplen < data_off) 826c74ad251Schristos goto invalid; 827c74ad251Schristos ack = GET_LE_U_2(shp->sh_seq[0]); 8280f74e101Schristos if (ack & SGQ_ACK) { /* acknum field */ 8290f74e101Schristos if ((ack & SGQ_NAK) == SGQ_NAK) 830c74ad251Schristos ND_PRINT("nak %u ", ack & SGQ_MASK); 8310f74e101Schristos else 832c74ad251Schristos ND_PRINT("ack %u ", ack & SGQ_MASK); 8330f74e101Schristos data_off += sizeof(short); 8340f74e101Schristos if (nsplen < data_off) 835c74ad251Schristos goto invalid; 836c74ad251Schristos ack = GET_LE_U_2(shp->sh_seq[1]); 8370f74e101Schristos if (ack & SGQ_OACK) { /* ackoth field */ 8380f74e101Schristos if ((ack & SGQ_ONAK) == SGQ_ONAK) 839c74ad251Schristos ND_PRINT("onak %u ", ack & SGQ_MASK); 8400f74e101Schristos else 841c74ad251Schristos ND_PRINT("oack %u ", ack & SGQ_MASK); 8420f74e101Schristos data_off += sizeof(short); 8430f74e101Schristos if (nsplen < data_off) 844c74ad251Schristos goto invalid; 845c74ad251Schristos ack = GET_LE_U_2(shp->sh_seq[2]); 8460f74e101Schristos } 8470f74e101Schristos } 848c74ad251Schristos ND_PRINT("seg %u ", ack & SGQ_MASK); 8490f74e101Schristos } 8500f74e101Schristos break; 8510f74e101Schristos case MFS_ILS+MFS_INT: 852c74ad251Schristos ND_PRINT("intr "); 8530f74e101Schristos { 854fdccd7e4Schristos const struct seghdr *shp = (const struct seghdr *)nspp; 855c74ad251Schristos u_int ack; 8560f74e101Schristos u_int data_off = sizeof(struct minseghdr); 8570f74e101Schristos 8580f74e101Schristos if (nsplen < data_off) 859c74ad251Schristos goto invalid; 860c74ad251Schristos ack = GET_LE_U_2(shp->sh_seq[0]); 8610f74e101Schristos if (ack & SGQ_ACK) { /* acknum field */ 8620f74e101Schristos if ((ack & SGQ_NAK) == SGQ_NAK) 863c74ad251Schristos ND_PRINT("nak %u ", ack & SGQ_MASK); 8640f74e101Schristos else 865c74ad251Schristos ND_PRINT("ack %u ", ack & SGQ_MASK); 8660f74e101Schristos data_off += sizeof(short); 8670f74e101Schristos if (nsplen < data_off) 868c74ad251Schristos goto invalid; 869c74ad251Schristos ack = GET_LE_U_2(shp->sh_seq[1]); 8700f74e101Schristos if (ack & SGQ_OACK) { /* ackdat field */ 8710f74e101Schristos if ((ack & SGQ_ONAK) == SGQ_ONAK) 872c74ad251Schristos ND_PRINT("nakdat %u ", ack & SGQ_MASK); 8730f74e101Schristos else 874c74ad251Schristos ND_PRINT("ackdat %u ", ack & SGQ_MASK); 8750f74e101Schristos data_off += sizeof(short); 8760f74e101Schristos if (nsplen < data_off) 877c74ad251Schristos goto invalid; 878c74ad251Schristos ack = GET_LE_U_2(shp->sh_seq[2]); 8790f74e101Schristos } 8800f74e101Schristos } 881c74ad251Schristos ND_PRINT("seg %u ", ack & SGQ_MASK); 8820f74e101Schristos } 8830f74e101Schristos break; 8840f74e101Schristos case MFS_ILS: 885c74ad251Schristos ND_PRINT("link-service %u>%u ", src, dst); 8860f74e101Schristos { 887fdccd7e4Schristos const struct seghdr *shp = (const struct seghdr *)nspp; 888fdccd7e4Schristos const struct lsmsg *lsmp = 889c74ad251Schristos (const struct lsmsg *)(nspp + sizeof(struct seghdr)); 890c74ad251Schristos u_int ack; 891c74ad251Schristos u_int lsflags, fcval; 8920f74e101Schristos 8930f74e101Schristos if (nsplen < sizeof(struct seghdr) + sizeof(struct lsmsg)) 894c74ad251Schristos goto invalid; 895c74ad251Schristos ack = GET_LE_U_2(shp->sh_seq[0]); 8960f74e101Schristos if (ack & SGQ_ACK) { /* acknum field */ 8970f74e101Schristos if ((ack & SGQ_NAK) == SGQ_NAK) 898c74ad251Schristos ND_PRINT("nak %u ", ack & SGQ_MASK); 8990f74e101Schristos else 900c74ad251Schristos ND_PRINT("ack %u ", ack & SGQ_MASK); 901c74ad251Schristos ack = GET_LE_U_2(shp->sh_seq[1]); 9020f74e101Schristos if (ack & SGQ_OACK) { /* ackdat field */ 9030f74e101Schristos if ((ack & SGQ_ONAK) == SGQ_ONAK) 904c74ad251Schristos ND_PRINT("nakdat %u ", ack & SGQ_MASK); 9050f74e101Schristos else 906c74ad251Schristos ND_PRINT("ackdat %u ", ack & SGQ_MASK); 907c74ad251Schristos ack = GET_LE_U_2(shp->sh_seq[2]); 9080f74e101Schristos } 9090f74e101Schristos } 910c74ad251Schristos ND_PRINT("seg %u ", ack & SGQ_MASK); 911c74ad251Schristos lsflags = GET_U_1(lsmp->ls_lsflags); 912c74ad251Schristos fcval = GET_U_1(lsmp->ls_fcval); 9130f74e101Schristos switch (lsflags & LSI_MASK) { 9140f74e101Schristos case LSI_DATA: 915c74ad251Schristos ND_PRINT("dat seg count %u ", fcval); 9160f74e101Schristos switch (lsflags & LSM_MASK) { 9170f74e101Schristos case LSM_NOCHANGE: 9180f74e101Schristos break; 9190f74e101Schristos case LSM_DONOTSEND: 920c74ad251Schristos ND_PRINT("donotsend-data "); 9210f74e101Schristos break; 9220f74e101Schristos case LSM_SEND: 923c74ad251Schristos ND_PRINT("send-data "); 9240f74e101Schristos break; 9250f74e101Schristos default: 926c74ad251Schristos ND_PRINT("reserved-fcmod? %x", lsflags); 9270f74e101Schristos break; 9280f74e101Schristos } 9290f74e101Schristos break; 9300f74e101Schristos case LSI_INTR: 931c74ad251Schristos ND_PRINT("intr req count %u ", fcval); 9320f74e101Schristos break; 9330f74e101Schristos default: 934c74ad251Schristos ND_PRINT("reserved-fcval-int? %x", lsflags); 9350f74e101Schristos break; 9360f74e101Schristos } 9370f74e101Schristos } 9380f74e101Schristos break; 9390f74e101Schristos default: 940c74ad251Schristos ND_PRINT("reserved-subtype? %x %u > %u", flags, src, dst); 9410f74e101Schristos break; 9420f74e101Schristos } 9430f74e101Schristos break; 9440f74e101Schristos case MFT_ACK: 9450f74e101Schristos switch (flags & NSP_SUBMASK) { 9460f74e101Schristos case MFS_DACK: 947c74ad251Schristos ND_PRINT("data-ack %u>%u ", src, dst); 9480f74e101Schristos { 949fdccd7e4Schristos const struct ackmsg *amp = (const struct ackmsg *)nspp; 950c74ad251Schristos u_int ack; 9510f74e101Schristos 9520f74e101Schristos if (nsplen < sizeof(struct ackmsg)) 953c74ad251Schristos goto invalid; 954c74ad251Schristos ND_TCHECK_SIZE(amp); 955c74ad251Schristos ack = GET_LE_U_2(amp->ak_acknum[0]); 9560f74e101Schristos if (ack & SGQ_ACK) { /* acknum field */ 9570f74e101Schristos if ((ack & SGQ_NAK) == SGQ_NAK) 958c74ad251Schristos ND_PRINT("nak %u ", ack & SGQ_MASK); 9590f74e101Schristos else 960c74ad251Schristos ND_PRINT("ack %u ", ack & SGQ_MASK); 961c74ad251Schristos ack = GET_LE_U_2(amp->ak_acknum[1]); 9620f74e101Schristos if (ack & SGQ_OACK) { /* ackoth field */ 9630f74e101Schristos if ((ack & SGQ_ONAK) == SGQ_ONAK) 964c74ad251Schristos ND_PRINT("onak %u ", ack & SGQ_MASK); 9650f74e101Schristos else 966c74ad251Schristos ND_PRINT("oack %u ", ack & SGQ_MASK); 9670f74e101Schristos } 9680f74e101Schristos } 9690f74e101Schristos } 9700f74e101Schristos break; 9710f74e101Schristos case MFS_IACK: 972c74ad251Schristos ND_PRINT("ils-ack %u>%u ", src, dst); 9730f74e101Schristos { 974fdccd7e4Schristos const struct ackmsg *amp = (const struct ackmsg *)nspp; 975c74ad251Schristos u_int ack; 9760f74e101Schristos 9770f74e101Schristos if (nsplen < sizeof(struct ackmsg)) 978c74ad251Schristos goto invalid; 979c74ad251Schristos ND_TCHECK_SIZE(amp); 980c74ad251Schristos ack = GET_LE_U_2(amp->ak_acknum[0]); 9810f74e101Schristos if (ack & SGQ_ACK) { /* acknum field */ 9820f74e101Schristos if ((ack & SGQ_NAK) == SGQ_NAK) 983c74ad251Schristos ND_PRINT("nak %u ", ack & SGQ_MASK); 9840f74e101Schristos else 985c74ad251Schristos ND_PRINT("ack %u ", ack & SGQ_MASK); 986c74ad251Schristos ack = GET_LE_U_2(amp->ak_acknum[1]); 9870f74e101Schristos if (ack & SGQ_OACK) { /* ackdat field */ 9880f74e101Schristos if ((ack & SGQ_ONAK) == SGQ_ONAK) 989c74ad251Schristos ND_PRINT("nakdat %u ", ack & SGQ_MASK); 9900f74e101Schristos else 991c74ad251Schristos ND_PRINT("ackdat %u ", ack & SGQ_MASK); 9920f74e101Schristos } 9930f74e101Schristos } 9940f74e101Schristos } 9950f74e101Schristos break; 9960f74e101Schristos case MFS_CACK: 997c74ad251Schristos ND_PRINT("conn-ack %u", dst); 9980f74e101Schristos break; 9990f74e101Schristos default: 1000c74ad251Schristos ND_PRINT("reserved-acktype? %x %u > %u", flags, src, dst); 10010f74e101Schristos break; 10020f74e101Schristos } 10030f74e101Schristos break; 10040f74e101Schristos case MFT_CTL: 10050f74e101Schristos switch (flags & NSP_SUBMASK) { 10060f74e101Schristos case MFS_CI: 10070f74e101Schristos case MFS_RCI: 10080f74e101Schristos if ((flags & NSP_SUBMASK) == MFS_CI) 1009c74ad251Schristos ND_PRINT("conn-initiate "); 10100f74e101Schristos else 1011c74ad251Schristos ND_PRINT("retrans-conn-initiate "); 1012c74ad251Schristos ND_PRINT("%u>%u ", src, dst); 10130f74e101Schristos { 1014fdccd7e4Schristos const struct cimsg *cimp = (const struct cimsg *)nspp; 1015c74ad251Schristos u_int services, info, segsize; 10160f74e101Schristos 10170f74e101Schristos if (nsplen < sizeof(struct cimsg)) 1018c74ad251Schristos goto invalid; 1019c74ad251Schristos services = GET_U_1(cimp->ci_services); 1020c74ad251Schristos info = GET_U_1(cimp->ci_info); 1021c74ad251Schristos segsize = GET_LE_U_2(cimp->ci_segsize); 10220f74e101Schristos 10230f74e101Schristos switch (services & COS_MASK) { 10240f74e101Schristos case COS_NONE: 10250f74e101Schristos break; 10260f74e101Schristos case COS_SEGMENT: 1027c74ad251Schristos ND_PRINT("seg "); 10280f74e101Schristos break; 10290f74e101Schristos case COS_MESSAGE: 1030c74ad251Schristos ND_PRINT("msg "); 10310f74e101Schristos break; 10320f74e101Schristos } 10330f74e101Schristos switch (info & COI_MASK) { 10340f74e101Schristos case COI_32: 1035c74ad251Schristos ND_PRINT("ver 3.2 "); 10360f74e101Schristos break; 10370f74e101Schristos case COI_31: 1038c74ad251Schristos ND_PRINT("ver 3.1 "); 10390f74e101Schristos break; 10400f74e101Schristos case COI_40: 1041c74ad251Schristos ND_PRINT("ver 4.0 "); 10420f74e101Schristos break; 10430f74e101Schristos case COI_41: 1044c74ad251Schristos ND_PRINT("ver 4.1 "); 10450f74e101Schristos break; 10460f74e101Schristos } 1047c74ad251Schristos ND_PRINT("segsize %u ", segsize); 10480f74e101Schristos } 10490f74e101Schristos break; 10500f74e101Schristos case MFS_CC: 1051c74ad251Schristos ND_PRINT("conn-confirm %u>%u ", src, dst); 10520f74e101Schristos { 1053fdccd7e4Schristos const struct ccmsg *ccmp = (const struct ccmsg *)nspp; 1054c74ad251Schristos u_int services, info; 10550f74e101Schristos u_int segsize, optlen; 10560f74e101Schristos 10570f74e101Schristos if (nsplen < sizeof(struct ccmsg)) 1058c74ad251Schristos goto invalid; 1059c74ad251Schristos services = GET_U_1(ccmp->cc_services); 1060c74ad251Schristos info = GET_U_1(ccmp->cc_info); 1061c74ad251Schristos segsize = GET_LE_U_2(ccmp->cc_segsize); 1062c74ad251Schristos optlen = GET_U_1(ccmp->cc_optlen); 10630f74e101Schristos 10640f74e101Schristos switch (services & COS_MASK) { 10650f74e101Schristos case COS_NONE: 10660f74e101Schristos break; 10670f74e101Schristos case COS_SEGMENT: 1068c74ad251Schristos ND_PRINT("seg "); 10690f74e101Schristos break; 10700f74e101Schristos case COS_MESSAGE: 1071c74ad251Schristos ND_PRINT("msg "); 10720f74e101Schristos break; 10730f74e101Schristos } 10740f74e101Schristos switch (info & COI_MASK) { 10750f74e101Schristos case COI_32: 1076c74ad251Schristos ND_PRINT("ver 3.2 "); 10770f74e101Schristos break; 10780f74e101Schristos case COI_31: 1079c74ad251Schristos ND_PRINT("ver 3.1 "); 10800f74e101Schristos break; 10810f74e101Schristos case COI_40: 1082c74ad251Schristos ND_PRINT("ver 4.0 "); 10830f74e101Schristos break; 10840f74e101Schristos case COI_41: 1085c74ad251Schristos ND_PRINT("ver 4.1 "); 10860f74e101Schristos break; 10870f74e101Schristos } 1088c74ad251Schristos ND_PRINT("segsize %u ", segsize); 10890f74e101Schristos if (optlen) { 1090c74ad251Schristos ND_PRINT("optlen %u ", optlen); 10910f74e101Schristos } 10920f74e101Schristos } 10930f74e101Schristos break; 10940f74e101Schristos case MFS_DI: 1095c74ad251Schristos ND_PRINT("disconn-initiate %u>%u ", src, dst); 10960f74e101Schristos { 1097fdccd7e4Schristos const struct dimsg *dimp = (const struct dimsg *)nspp; 1098c74ad251Schristos u_int reason; 10990f74e101Schristos u_int optlen; 11000f74e101Schristos 11010f74e101Schristos if (nsplen < sizeof(struct dimsg)) 1102c74ad251Schristos goto invalid; 1103c74ad251Schristos reason = GET_LE_U_2(dimp->di_reason); 1104c74ad251Schristos optlen = GET_U_1(dimp->di_optlen); 11050f74e101Schristos 1106b3a00663Schristos print_reason(ndo, reason); 11070f74e101Schristos if (optlen) { 1108c74ad251Schristos ND_PRINT("optlen %u ", optlen); 11090f74e101Schristos } 11100f74e101Schristos } 11110f74e101Schristos break; 11120f74e101Schristos case MFS_DC: 1113c74ad251Schristos ND_PRINT("disconn-confirm %u>%u ", src, dst); 11140f74e101Schristos { 1115fdccd7e4Schristos const struct dcmsg *dcmp = (const struct dcmsg *)nspp; 1116c74ad251Schristos u_int reason; 11170f74e101Schristos 1118c74ad251Schristos reason = GET_LE_U_2(dcmp->dc_reason); 11190f74e101Schristos 1120b3a00663Schristos print_reason(ndo, reason); 11210f74e101Schristos } 11220f74e101Schristos break; 11230f74e101Schristos default: 1124c74ad251Schristos ND_PRINT("reserved-ctltype? %x %u > %u", flags, src, dst); 11250f74e101Schristos break; 11260f74e101Schristos } 11270f74e101Schristos break; 11280f74e101Schristos default: 1129c74ad251Schristos ND_PRINT("reserved-type? %x %u > %u", flags, src, dst); 11300f74e101Schristos break; 11310f74e101Schristos } 11320f74e101Schristos return (1); 11330f74e101Schristos 1134c74ad251Schristos invalid: 11350f74e101Schristos return (0); 11360f74e101Schristos } 11370f74e101Schristos 1138870189d2Schristos static const struct tok reason2str[] = { 11390f74e101Schristos { UC_OBJREJECT, "object rejected connect" }, 11400f74e101Schristos { UC_RESOURCES, "insufficient resources" }, 11410f74e101Schristos { UC_NOSUCHNODE, "unrecognized node name" }, 11420f74e101Schristos { DI_SHUT, "node is shutting down" }, 11430f74e101Schristos { UC_NOSUCHOBJ, "unrecognized object" }, 11440f74e101Schristos { UC_INVOBJFORMAT, "invalid object name format" }, 11450f74e101Schristos { UC_OBJTOOBUSY, "object too busy" }, 11460f74e101Schristos { DI_PROTOCOL, "protocol error discovered" }, 11470f74e101Schristos { DI_TPA, "third party abort" }, 11480f74e101Schristos { UC_USERABORT, "user abort" }, 11490f74e101Schristos { UC_INVNODEFORMAT, "invalid node name format" }, 11500f74e101Schristos { UC_LOCALSHUT, "local node shutting down" }, 11510f74e101Schristos { DI_LOCALRESRC, "insufficient local resources" }, 11520f74e101Schristos { DI_REMUSERRESRC, "insufficient remote user resources" }, 11530f74e101Schristos { UC_ACCESSREJECT, "invalid access control information" }, 11540f74e101Schristos { DI_BADACCNT, "bad ACCOUNT information" }, 11550f74e101Schristos { UC_NORESPONSE, "no response from object" }, 11560f74e101Schristos { UC_UNREACHABLE, "node unreachable" }, 11570f74e101Schristos { DC_NOLINK, "no link terminate" }, 11580f74e101Schristos { DC_COMPLETE, "disconnect complete" }, 11590f74e101Schristos { DI_BADIMAGE, "bad image data in connect" }, 11600f74e101Schristos { DI_SERVMISMATCH, "cryptographic service mismatch" }, 11610f74e101Schristos { 0, NULL } 11620f74e101Schristos }; 11630f74e101Schristos 11640f74e101Schristos static void 1165b3a00663Schristos print_reason(netdissect_options *ndo, 1166c74ad251Schristos u_int reason) 11670f74e101Schristos { 1168c74ad251Schristos ND_PRINT("%s ", tok2str(reason2str, "reason-%u", reason)); 11690f74e101Schristos } 11700f74e101Schristos 11710f74e101Schristos const char * 1172fdccd7e4Schristos dnnum_string(netdissect_options *ndo, u_short dnaddr) 11730f74e101Schristos { 11740f74e101Schristos char *str; 11750f74e101Schristos size_t siz; 1176c74ad251Schristos u_int area = (u_short)(dnaddr & AREAMASK) >> AREASHIFT; 1177c74ad251Schristos u_int node = dnaddr & NODEMASK; 11780f74e101Schristos 1179c74ad251Schristos /* malloc() return used by the 'dnaddrtable' hash table: do not free() */ 11800f74e101Schristos str = (char *)malloc(siz = sizeof("00.0000")); 11810f74e101Schristos if (str == NULL) 1182c74ad251Schristos (*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC, "%s: malloc", __func__); 1183c74ad251Schristos snprintf(str, siz, "%u.%u", area, node); 11840f74e101Schristos return(str); 11850f74e101Schristos } 1186